mirror of
https://github.com/lkddi/nexusphp.git
synced 2026-04-14 20:40:49 +08:00
medal management
This commit is contained in:
@@ -38,6 +38,9 @@
|
||||
<el-menu-item-group>
|
||||
<el-menu-item index="/exam-user"><i class="el-icon-menu" />Exam user</el-menu-item>
|
||||
</el-menu-item-group>
|
||||
<el-menu-item-group>
|
||||
<el-menu-item index="/medal"><i class="el-icon-menu" />Medal</el-menu-item>
|
||||
</el-menu-item-group>
|
||||
<el-menu-item-group>
|
||||
<el-menu-item index="/setting"><i class="el-icon-menu" />Setting</el-menu-item>
|
||||
</el-menu-item-group>
|
||||
|
||||
10
admin/src/router/index.js
vendored
10
admin/src/router/index.js
vendored
@@ -54,6 +54,16 @@ const router = createRouter({
|
||||
name: 'agent-allow-form',
|
||||
component: () => import('../views/agent-allow/form.vue')
|
||||
},
|
||||
{
|
||||
path: '/medal',
|
||||
name: 'medal',
|
||||
component: () => import('../views/medal/index.vue')
|
||||
},
|
||||
{
|
||||
path: '/medal-form',
|
||||
name: 'medal-form',
|
||||
component: () => import('../views/medal/form.vue')
|
||||
},
|
||||
{
|
||||
path: '/setting',
|
||||
name: 'setting',
|
||||
|
||||
23
admin/src/utils/api.js
vendored
23
admin/src/utils/api.js
vendored
@@ -72,6 +72,24 @@ const api = {
|
||||
deleteExam: (id) => {
|
||||
return axios.delete('exams/' + id);
|
||||
},
|
||||
|
||||
listMedal: (params = {}) => {
|
||||
return axios.get('medals', {params: params});
|
||||
},
|
||||
storeMedal: (params = {}) => {
|
||||
return axios.post('medals', params);
|
||||
},
|
||||
updateMedal: (id, params = {}) => {
|
||||
return axios.put('medals/' + id, params);
|
||||
},
|
||||
getMedal: (id) => {
|
||||
return axios.get('medals/' + id);
|
||||
},
|
||||
deleteMedal: (id) => {
|
||||
return axios.delete('medals/' + id);
|
||||
},
|
||||
|
||||
|
||||
listClass: (params = {}) => {
|
||||
return axios.get('user-classes', {params: params});
|
||||
},
|
||||
@@ -107,7 +125,10 @@ const api = {
|
||||
},
|
||||
listSystemInfo: () => {
|
||||
return axios.get('dashboard/system-info')
|
||||
}
|
||||
},
|
||||
removeUserMedal: (id) => {
|
||||
return axios.delete('user-medals/' + id);
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
|
||||
2
admin/src/utils/index.js
vendored
2
admin/src/utils/index.js
vendored
@@ -47,4 +47,6 @@ export const pathMap = {
|
||||
'exam-form': 'Exam form',
|
||||
'exam-user': 'Exam user',
|
||||
'setting': "Setting",
|
||||
'medal': 'Medal',
|
||||
'medal-form': 'Medal form',
|
||||
}
|
||||
|
||||
162
admin/src/views/medal/form.vue
Normal file
162
admin/src/views/medal/form.vue
Normal file
@@ -0,0 +1,162 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form :model="formData" :rules="rules" ref="formRef" label-width="200px" class="formData">
|
||||
<el-form-item label="Name" prop="name">
|
||||
<el-input v-model="formData.name" placeholder=""></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="Price" prop="price">
|
||||
<el-input v-model="formData.price" placeholder="Seed bonus"></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="Get type" prop="get_type">
|
||||
<el-radio-group v-model="formData.get_type">
|
||||
<el-radio :label="1">Exchange</el-radio>
|
||||
<el-radio :label="2">Grant</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="Image large" prop="image_large">
|
||||
<el-input v-model="formData.image_large" placeholder=""></el-input>
|
||||
</el-form-item>
|
||||
<el-form-item label="Image small" prop="image_small">
|
||||
<el-input v-model="formData.image_small" placeholder=""></el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Duration" prop="duration">
|
||||
<el-input v-model="formData.duration" placeholder="Unit: day, if empty, it's valid forever"></el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item label="Description" prop="description">
|
||||
<el-input type="textarea" v-model="formData.description" placeholder=""></el-input>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="submitAdd()">Submit</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { reactive, ref, toRefs, onMounted, onBeforeUnmount, getCurrentInstance } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { localGet } from '../../utils'
|
||||
import api from "../../utils/api";
|
||||
|
||||
export default {
|
||||
name: 'MedalForm',
|
||||
setup() {
|
||||
const { proxy } = getCurrentInstance()
|
||||
console.log('proxy', proxy)
|
||||
const formRef = ref(null)
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const { id } = route.query
|
||||
const state = reactive({
|
||||
token: localGet('token') || '',
|
||||
id: id,
|
||||
allClasses: [],
|
||||
formData: {
|
||||
name: '',
|
||||
description: '',
|
||||
image_large: '',
|
||||
image_small: '',
|
||||
duration: '',
|
||||
price: '',
|
||||
get_type: ''
|
||||
},
|
||||
rules: {
|
||||
name: [
|
||||
{ required: 'true', }
|
||||
],
|
||||
price: [
|
||||
{ required: 'true', }
|
||||
],
|
||||
image_large: [
|
||||
{ required: 'true', }
|
||||
],
|
||||
image_small: [
|
||||
{ required: 'true', }
|
||||
],
|
||||
description: [
|
||||
{ required: 'true', }
|
||||
],
|
||||
get_type: [
|
||||
{required: 'true'}
|
||||
]
|
||||
},
|
||||
})
|
||||
onMounted( async () => {
|
||||
if (id) {
|
||||
api.getMedal(id).then(res => {
|
||||
state.formData.name = res.data.name
|
||||
state.formData.image_large = res.data.image_large
|
||||
state.formData.image_small = res.data.image_small
|
||||
state.formData.description = res.data.description
|
||||
state.formData.price = res.data.price
|
||||
state.formData.duration = res.data.duration
|
||||
state.formData.get_type = res.data.get_type
|
||||
})
|
||||
}
|
||||
})
|
||||
onBeforeUnmount(() => {
|
||||
|
||||
})
|
||||
const submitAdd = () => {
|
||||
formRef.value.validate(async (vaild) => {
|
||||
if (vaild) {
|
||||
let params = state.formData;
|
||||
console.log(params)
|
||||
if (id) {
|
||||
await api.updateMedal(id, params)
|
||||
} else {
|
||||
await api.storeMedal(params)
|
||||
}
|
||||
await router.push({name: 'medal'})
|
||||
}
|
||||
})
|
||||
}
|
||||
const handleBeforeUpload = (file) => {
|
||||
const sufix = file.name.split('.')[1] || ''
|
||||
if (!['jpg', 'jpeg', 'png'].includes(sufix)) {
|
||||
ElMessage.error('请上传 jpg、jpeg、png 格式的图片')
|
||||
return false
|
||||
}
|
||||
}
|
||||
const handleUrlSuccess = (val) => {
|
||||
state.formData.goodsCoverImg = val.data || ''
|
||||
}
|
||||
const handleChangeCate = (val) => {
|
||||
state.categoryId = val[2] || 0
|
||||
}
|
||||
|
||||
const listAllClass = async () => {
|
||||
let res = await api.listClass()
|
||||
state.allClasses = res.data
|
||||
}
|
||||
const listAllIndex = async () => {
|
||||
let res = await api.listMedalIndex()
|
||||
state.formData.indexes = res.data
|
||||
}
|
||||
const getMedal = async (id) => {
|
||||
let res = await api.getMedal(id)
|
||||
console.log(res)
|
||||
}
|
||||
return {
|
||||
...toRefs(state),
|
||||
formRef,
|
||||
submitAdd,
|
||||
handleBeforeUpload,
|
||||
handleUrlSuccess,
|
||||
handleChangeCate,
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
151
admin/src/views/medal/index.vue
Normal file
151
admin/src/views/medal/index.vue
Normal file
@@ -0,0 +1,151 @@
|
||||
<template>
|
||||
<el-card class="">
|
||||
<template #header>
|
||||
<div class="nexus-table-header">
|
||||
<div class="left">
|
||||
|
||||
</div>
|
||||
<div class="right">
|
||||
<el-button type="primary" size="small" icon="el-icon-plus" @click="handleAdd">Add</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
ref="multipleTable"
|
||||
:data="tableData"
|
||||
tooltip-effect="dark"
|
||||
@selection-change="handleSelectionChange">
|
||||
<el-table-column
|
||||
type="selection"
|
||||
width="55">
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="id"
|
||||
label="Id"
|
||||
width="50"
|
||||
>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="name"
|
||||
label="Name"
|
||||
></el-table-column>
|
||||
<el-table-column
|
||||
prop="image_large"
|
||||
label="Large image"
|
||||
></el-table-column>
|
||||
<el-table-column
|
||||
prop="image_small"
|
||||
label="Small image"
|
||||
></el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="get_type_text"
|
||||
label="Get type"
|
||||
></el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="price"
|
||||
label="Price(bonus)"
|
||||
></el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="duration"
|
||||
label="Duration(day)"
|
||||
></el-table-column>
|
||||
|
||||
<el-table-column
|
||||
label="Action"
|
||||
width="100"
|
||||
>
|
||||
<template #default="scope">
|
||||
<a style="cursor: pointer; margin-right: 10px" @click="handleEdit(scope.row.id)">Edit</a>
|
||||
<el-popconfirm
|
||||
title="Confirm Delete ?"
|
||||
@confirm="handleDelete(scope.row.id)"
|
||||
>
|
||||
<template #reference>
|
||||
<a style="cursor: pointer">Delete</a>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!--总数超过一页,再展示分页器-->
|
||||
<el-pagination
|
||||
background
|
||||
layout="prev, pager, next"
|
||||
:total="total"
|
||||
:page-size="perPage"
|
||||
:current-page="currentPage"
|
||||
@current-change="changePage"
|
||||
/>
|
||||
</el-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { onMounted, reactive, ref, toRefs } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
import { useRouter } from 'vue-router'
|
||||
import api from '../../utils/api'
|
||||
import { useTable, renderTableData } from '../../utils/table'
|
||||
|
||||
export default {
|
||||
name: 'MedalTable',
|
||||
setup() {
|
||||
const multipleTable = ref(null)
|
||||
const router = useRouter()
|
||||
|
||||
const state = useTable()
|
||||
|
||||
onMounted(() => {
|
||||
console.log('MedalTable onMounted')
|
||||
fetchTableData()
|
||||
})
|
||||
const fetchTableData = async () => {
|
||||
state.loading = true
|
||||
let res = await api.listMedal(state.query)
|
||||
renderTableData(res, state)
|
||||
state.loading = false
|
||||
}
|
||||
const handleAdd = () => {
|
||||
router.push({ name: 'medal-form' })
|
||||
}
|
||||
const handleEdit = (id) => {
|
||||
router.push({ path: '/medal-form', query: { id } })
|
||||
}
|
||||
const handleDelete = async (id) => {
|
||||
let res = await api.deleteMedal(id)
|
||||
ElMessage.success(res.msg)
|
||||
state.query.page = 1;
|
||||
await fetchTableData()
|
||||
}
|
||||
const handleSelectionChange = (val) => {
|
||||
state.multipleSelection = val
|
||||
}
|
||||
const changePage = (val) => {
|
||||
state.query.page = val
|
||||
fetchTableData()
|
||||
}
|
||||
return {
|
||||
...toRefs(state),
|
||||
multipleTable,
|
||||
handleSelectionChange,
|
||||
handleAdd,
|
||||
handleEdit,
|
||||
handleDelete,
|
||||
fetchTableData,
|
||||
changePage,
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.swiper-container {
|
||||
min-height: 100%;
|
||||
}
|
||||
.el-card.is-always-shadow {
|
||||
min-height: 100%!important;
|
||||
}
|
||||
</style>
|
||||
@@ -153,12 +153,62 @@
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-card>
|
||||
|
||||
<el-row v-if="baseInfo.valid_medals && baseInfo.valid_medals.length">
|
||||
<el-col :span="12">
|
||||
<el-card >
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>Medal</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
ref="multipleTable"
|
||||
:data="baseInfo.valid_medals"
|
||||
tooltip-effect="dark"
|
||||
>
|
||||
<el-table-column
|
||||
prop="name"
|
||||
label="Name"
|
||||
></el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="image_large"
|
||||
label="Image"
|
||||
>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
prop="expire_at"
|
||||
label="Expire at"
|
||||
></el-table-column>
|
||||
|
||||
<el-table-column
|
||||
label="Action"
|
||||
width="100"
|
||||
>
|
||||
<template #default="scope">
|
||||
<el-popconfirm
|
||||
title="Confirm Remove ?"
|
||||
@confirm="handleRemoveUserMedal(scope.row.user_medal_id)"
|
||||
>
|
||||
<template #reference>
|
||||
<a style="cursor: pointer">Remove</a>
|
||||
</template>
|
||||
</el-popconfirm>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
<DialogAssignExam ref="assignExam" :reload="fetchPageData"/>
|
||||
<DialogViewInviteInfo ref="viewInviteInfo" />
|
||||
<DialogDisableUser ref="disableUser" :reload="fetchPageData" />
|
||||
<DialogModComment ref="modComment" />
|
||||
<DialogModComment ref="modComment" />
|
||||
<DialogResetPassword ref="resetPassword" />
|
||||
</template>
|
||||
|
||||
@@ -240,6 +290,12 @@ export default {
|
||||
const handleResetPassword = async () => {
|
||||
resetPassword.value.open(id)
|
||||
}
|
||||
|
||||
const handleRemoveUserMedal = async (id) => {
|
||||
let res = await api.removeUserMedal(id)
|
||||
ElMessage.success(res.msg)
|
||||
await fetchPageData()
|
||||
}
|
||||
return {
|
||||
...toRefs(state),
|
||||
handleRemoveExam,
|
||||
@@ -252,6 +308,7 @@ export default {
|
||||
handleGetModComment,
|
||||
handleResetPassword,
|
||||
fetchPageData,
|
||||
handleRemoveUserMedal,
|
||||
assignExam,
|
||||
viewInviteInfo,
|
||||
disableUser,
|
||||
@@ -271,10 +328,10 @@ export default {
|
||||
text-align: left;
|
||||
tr {
|
||||
th {
|
||||
padding-bottom: 10px;
|
||||
padding-bottom: 4px;
|
||||
}
|
||||
td {
|
||||
padding: 10px 0;
|
||||
padding: 4px 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user