| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347 |
- <template>
- <div class="badge-manage-page">
- <el-card>
- <div slot="header" class="clearfix">
- <span>勋章管理</span>
- <div style="float:right; display:flex; gap:10px;">
- <el-button type="primary" size="small" @click="showAddDialog">新增勋章</el-button>
- </div>
- </div>
- <!-- 搜索 -->
- <el-form :model="filters" inline size="small" style="margin-bottom:16px;">
- <el-form-item label="名称">
- <el-input v-model="filters.name" placeholder="搜索勋章名称" clearable @input="onSearchInput" />
- </el-form-item>
- <el-form-item label="分类">
- <el-select v-model="filters.category" placeholder="全部分类" clearable @change="fetchList" style="width:140px;">
- <el-option v-for="c in categoryOptions" :key="c.value" :label="c.label" :value="c.value" />
- </el-select>
- </el-form-item>
- <el-form-item label="等级">
- <el-select v-model="filters.level" placeholder="全部等级" clearable @change="fetchList" style="width:140px;">
- <el-option v-for="c in levelOptions" :key="c.value" :label="c.label" :value="c.value" />
- </el-select>
- </el-form-item>
- </el-form>
- <el-table :data="list" border stripe v-loading="loading" empty-text="暂无数据" style="width:100%" :max-height="tableHeight">
- <el-table-column prop="id" label="ID" width="60" />
- <el-table-column prop="name" label="名称" min-width="120" />
- <el-table-column prop="category" label="分类" width="90" />
- <el-table-column label="等级" width="80">
- <template slot-scope="{ row }">
- {{ levelMap[row.level] || row.level || '-' }}
- </template>
- </el-table-column>
- <el-table-column label="稀有度" width="80">
- <template slot-scope="{ row }">
- {{ rarityMap[row.rarity] || row.rarity || '-' }}
- </template>
- </el-table-column>
- <el-table-column label="启用" width="80" align="center">
- <template slot-scope="{ row }">
- <el-switch
- :value="row.isActive === 1"
- active-color="#67C23A"
- @change="onToggleActive(row)"
- />
- </template>
- </el-table-column>
- <el-table-column prop="sortOrder" label="排序" width="60" align="center" />
- <el-table-column prop="createdAt" label="创建时间" width="160" />
- <el-table-column label="操作" width="160" fixed="right">
- <template slot-scope="{ row }">
- <el-button type="text" @click="editRow(row)">编辑</el-button>
- <el-popconfirm title="确定删除此勋章吗?" @confirm="deleteRow(row)">
- <el-button type="text" style="color:#f56c6c" slot="reference">删除</el-button>
- </el-popconfirm>
- </template>
- </el-table-column>
- </el-table>
- </el-card>
- <!-- 新增/编辑弹窗 -->
- <el-dialog :visible.sync="dialog.visible" :title="dialog.isEdit ? '编辑勋章' : '新增勋章'" width="600px" :close-on-click-modal="false">
- <el-form :model="dialog.form" label-width="110px" size="small">
- <el-row :gutter="16">
- <el-col :span="12">
- <el-form-item label="名称" required>
- <el-input v-model="dialog.form.name" placeholder="勋章名称" />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="分类" required>
- <el-select v-model="dialog.form.category" placeholder="请选择" style="width:100%">
- <el-option v-for="c in categoryOptions" :key="c.value" :label="c.label" :value="c.value" />
- </el-select>
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="16">
- <el-col :span="12">
- <el-form-item label="等级">
- <el-select v-model="dialog.form.level" placeholder="请选择" style="width:100%">
- <el-option v-for="c in levelOptions" :key="c.value" :label="c.label" :value="c.value" />
- </el-select>
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="稀有度">
- <el-select v-model="dialog.form.rarity" placeholder="请选择" style="width:100%">
- <el-option v-for="c in rarityOptions" :key="c.value" :label="c.label" :value="c.value" />
- </el-select>
- </el-form-item>
- </el-col>
- </el-row>
- <el-form-item label="图标URL">
- <el-input v-model="dialog.form.icon" placeholder="勋章图标地址" />
- </el-form-item>
- <el-form-item label="描述">
- <el-input type="textarea" :rows="3" v-model="dialog.form.description" placeholder="勋章描述..." />
- </el-form-item>
- <el-row :gutter="16">
- <el-col :span="12">
- <el-form-item label="触发类型">
- <el-input v-model="dialog.form.triggerType" placeholder="如: micro_action_count" />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="触发阈值">
- <el-input-number v-model="dialog.form.threshold" :min="0" style="width:100%" />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="16">
- <el-col :span="12">
- <el-form-item label="排序">
- <el-input-number v-model="dialog.form.sortOrder" :min="0" style="width:100%" />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="过期天数">
- <el-input-number v-model="dialog.form.expireDays" :min="0" style="width:100%" />
- </el-form-item>
- </el-col>
- </el-row>
- <el-row :gutter="16">
- <el-col :span="12">
- <el-form-item label="是否启用">
- <el-switch v-model="dialog.form._active" active-color="#67C23A" />
- </el-form-item>
- </el-col>
- <el-col :span="12">
- <el-form-item label="需要审批">
- <el-switch v-model="dialog.form._needApproval" active-color="#67C23A" />
- </el-form-item>
- </el-col>
- </el-row>
- </el-form>
- <div slot="footer">
- <el-button @click="dialog.visible = false" size="small">取消</el-button>
- <el-button type="primary" @click="saveDialog" size="small" :loading="dialog.saving">保存</el-button>
- </div>
- </el-dialog>
- </div>
- </template>
- <script>
- import { getBadgeList, createBadge, updateBadge, deleteBadge } from '@/api/badge'
- export default {
- computed: {
- tableHeight() {
- return window.innerHeight - 300
- }
- },
- data() {
- return {
- loading: false,
- list: [],
- searchTimer: null,
- filters: { name: '', category: '', level: '' },
- categoryOptions: [
- { value: '学习', label: '学习' },
- { value: '运动', label: '运动' },
- { value: '家务', label: '家务' },
- { value: '阅读', label: '阅读' },
- { value: '打卡', label: '打卡' },
- { value: '综合', label: '综合' }
- ],
- levelOptions: [
- { value: 'bronze', label: '铜牌' },
- { value: 'silver', label: '银牌' },
- { value: 'gold', label: '金牌' },
- { value: 'diamond', label: '钻石' }
- ],
- rarityOptions: [
- { value: 'common', label: '普通' },
- { value: 'rare', label: '稀有' },
- { value: 'epic', label: '史诗' },
- { value: 'legendary', label: '传说' }
- ],
- levelMap: { bronze: '铜牌', silver: '银牌', gold: '金牌', diamond: '钻石' },
- rarityMap: { common: '普通', rare: '稀有', epic: '史诗', legendary: '传说' },
- dialog: {
- visible: false,
- isEdit: false,
- saving: false,
- form: {
- id: null,
- name: '',
- description: '',
- icon: '',
- category: '',
- level: '',
- rarity: '',
- triggerType: '',
- threshold: 0,
- sortOrder: 0,
- expireDays: 0,
- _active: true,
- _needApproval: false
- }
- }
- }
- },
- mounted() { this.fetchList() },
- methods: {
- onSearchInput() {
- if (this.searchTimer) clearTimeout(this.searchTimer)
- this.searchTimer = setTimeout(() => { this.fetchList() }, 300)
- },
- async fetchList() {
- this.loading = true
- try {
- const res = await getBadgeList()
- var data = res.data || []
- // Apply client-side filters
- if (this.filters.name) {
- var q = this.filters.name.toLowerCase()
- data = data.filter(function(d) { return d.name && d.name.toLowerCase().indexOf(q) !== -1 })
- }
- if (this.filters.category) {
- data = data.filter(function(d) { return d.category === this.filters.category }.bind(this))
- }
- if (this.filters.level) {
- data = data.filter(function(d) { return d.level === this.filters.level }.bind(this))
- }
- this.list = data
- } catch (e) {
- console.error('加载勋章列表失败', e)
- this.$message.error('加载失败')
- } finally {
- this.loading = false
- }
- },
- showAddDialog() {
- this.dialog.isEdit = false
- this.dialog.form = {
- id: null,
- name: '',
- description: '',
- icon: '',
- category: '',
- level: '',
- rarity: '',
- triggerType: '',
- threshold: 0,
- sortOrder: 0,
- expireDays: 0,
- _active: true,
- _needApproval: false
- }
- this.dialog.visible = true
- },
- editRow(row) {
- this.dialog.isEdit = true
- this.dialog.form = {
- id: row.id,
- name: row.name || '',
- description: row.description || '',
- icon: row.icon || '',
- category: row.category || '',
- level: row.level || '',
- rarity: row.rarity || '',
- triggerType: row.triggerType || '',
- threshold: row.threshold != null ? row.threshold : 0,
- sortOrder: row.sortOrder != null ? row.sortOrder : 0,
- expireDays: row.expireDays != null ? row.expireDays : 0,
- _active: row.isActive === 1,
- _needApproval: !!row.needApproval
- }
- this.dialog.visible = true
- },
- async saveDialog() {
- var form = this.dialog.form
- if (!form.name) {
- this.$message.warning('请填写勋章名称')
- return
- }
- if (!form.category) {
- this.$message.warning('请选择分类')
- return
- }
- this.dialog.saving = true
- try {
- var payload = {
- id: form.id,
- name: form.name,
- description: form.description,
- icon: form.icon,
- category: form.category,
- level: form.level,
- rarity: form.rarity,
- triggerType: form.triggerType,
- threshold: form.threshold,
- sortOrder: form.sortOrder,
- expireDays: form.expireDays,
- isActive: form._active ? 1 : 0,
- needApproval: form._needApproval
- }
- if (form.id) {
- await updateBadge(payload)
- this.$message.success('更新成功')
- } else {
- await createBadge(payload)
- this.$message.success('创建成功')
- }
- this.dialog.visible = false
- this.fetchList()
- } catch (e) {
- console.error('保存失败', e)
- this.$message.error('保存失败')
- } finally {
- this.dialog.saving = false
- }
- },
- async deleteRow(row) {
- try {
- await deleteBadge(row.id)
- this.$message.success('删除成功')
- this.fetchList()
- } catch (e) {
- console.error('删除失败', e)
- this.$message.error('删除失败')
- }
- },
- async onToggleActive(row) {
- try {
- var newVal = row.isActive === 1 ? 0 : 1
- await updateBadge({ id: row.id, isActive: newVal })
- this.$message.success(newVal === 1 ? '已启用' : '已禁用')
- row.isActive = newVal
- } catch (e) {
- console.error('操作失败', e)
- this.$message.error('操作失败')
- }
- }
- }
- }
- </script>
- <style scoped>
- .badge-manage-page {
- padding: 16px;
- }
- </style>
|