diff --git a/src/config/router.js b/src/config/router.js index 500e15a..2a81f69 100644 --- a/src/config/router.js +++ b/src/config/router.js @@ -73,6 +73,14 @@ module.exports = [ ['/api/mp/unreadCount', 'mp/unreadCount'], ['/api/mp/subscribeConfig', 'mp/subscribeConfig'], + // 瘤种管理 + ['/admin/tag', 'admin/tag/index'], + ['/admin/tag/list', 'admin/tag/list'], + ['/admin/tag/add', 'admin/tag/add', 'post'], + ['/admin/tag/edit', 'admin/tag/edit', 'post'], + ['/admin/tag/delete', 'admin/tag/delete', 'post'], + ['/admin/tag/sort', 'admin/tag/sort', 'post'], + // 内容管理 ['/admin/content', 'admin/content/index'], ['/admin/content/list', 'admin/content/list'], diff --git a/src/config/sms.js b/src/config/sms.js index d05cd39..27e2298 100644 --- a/src/config/sms.js +++ b/src/config/sms.js @@ -26,7 +26,7 @@ module.exports = { length: 6, expireMinutes: 5, intervalSeconds: 60, - dailyLimit: 10 + dailyLimit: 3 }, // 是否启用短信发送(关闭时仅打印日志不真实发送) diff --git a/src/controller/admin/system/role.js b/src/controller/admin/system/role.js index 8d5dde5..044a7bb 100644 --- a/src/controller/admin/system/role.js +++ b/src/controller/admin/system/role.js @@ -259,6 +259,15 @@ module.exports = class extends Base { { name: '删除', key: 'patient:delete' } ] }, + { + name: '瘤种管理', key: 'tag', + children: [ + { name: '查看', key: 'tag:view' }, + { name: '新增', key: 'tag:add' }, + { name: '编辑', key: 'tag:edit' }, + { name: '删除', key: 'tag:delete' } + ] + }, { name: '内容管理', key: 'content', children: [ diff --git a/src/controller/admin/tag.js b/src/controller/admin/tag.js new file mode 100644 index 0000000..b110f62 --- /dev/null +++ b/src/controller/admin/tag.js @@ -0,0 +1,86 @@ +const Base = require('../base'); + +const CONFIG_KEY = 'tag_options'; + +module.exports = class extends Base { + // 瘤种管理页面 + async indexAction() { + this.assign('currentPage', 'tag'); + this.assign('pageTitle', '瘤种管理'); + this.assign('breadcrumb', [{ name: '瘤种管理' }]); + this.assign('adminUser', this.adminUser || {}); + this.assign('canAdd', this.isSuperAdmin || (this.userPermissions || []).includes('tag:add')); + this.assign('canEdit', this.isSuperAdmin || (this.userPermissions || []).includes('tag:edit')); + this.assign('canDelete', this.isSuperAdmin || (this.userPermissions || []).includes('tag:delete')); + return this.display(); + } + + // 获取瘤种列表 + async listAction() { + const tags = await this.model('sys_config').getByKey(CONFIG_KEY) || []; + return this.success(tags); + } + + // 新增瘤种 + async addAction() { + const { name } = this.post(); + if (!name || !name.trim()) return this.fail('瘤种名称不能为空'); + + const tags = await this.model('sys_config').getByKey(CONFIG_KEY) || []; + if (tags.includes(name.trim())) return this.fail('该瘤种已存在'); + + tags.push(name.trim()); + await this.model('sys_config').setByKey(CONFIG_KEY, tags, '瘤种选项'); + + await this.log('add', '瘤种管理', `新增瘤种「${name.trim()}」`); + return this.success(); + } + + // 编辑瘤种 + async editAction() { + const { oldName, newName } = this.post(); + if (!oldName || !newName || !newName.trim()) return this.fail('参数错误'); + + const tags = await this.model('sys_config').getByKey(CONFIG_KEY) || []; + const idx = tags.indexOf(oldName); + if (idx === -1) return this.fail('原瘤种不存在'); + if (oldName !== newName.trim() && tags.includes(newName.trim())) return this.fail('该瘤种已存在'); + + tags[idx] = newName.trim(); + await this.model('sys_config').setByKey(CONFIG_KEY, tags, '瘤种选项'); + + // 同步更新患者表中的瘤种名称 + if (oldName !== newName.trim()) { + await this.model('patient').where({ tag: oldName }).update({ tag: newName.trim() }); + } + + await this.log('edit', '瘤种管理', `编辑瘤种「${oldName}」→「${newName.trim()}」`); + return this.success(); + } + + // 删除瘤种 + async deleteAction() { + const { name } = this.post(); + if (!name) return this.fail('参数错误'); + + const tags = await this.model('sys_config').getByKey(CONFIG_KEY) || []; + const idx = tags.indexOf(name); + if (idx === -1) return this.fail('瘤种不存在'); + + tags.splice(idx, 1); + await this.model('sys_config').setByKey(CONFIG_KEY, tags, '瘤种选项'); + + await this.log('delete', '瘤种管理', `删除瘤种「${name}」`); + return this.success(); + } + + // 排序瘤种 + async sortAction() { + const { tags } = this.post(); + if (!Array.isArray(tags)) return this.fail('参数错误'); + + await this.model('sys_config').setByKey(CONFIG_KEY, tags, '瘤种选项'); + await this.log('edit', '瘤种管理', '调整瘤种排序'); + return this.success(); + } +}; diff --git a/src/controller/base.js b/src/controller/base.js index f22ebe1..7a2979b 100644 --- a/src/controller/base.js +++ b/src/controller/base.js @@ -201,7 +201,12 @@ module.exports = class extends think.Controller { }); if (!sendResult.success) { - return { success: false, message: sendResult.message || '短信发送失败' }; + // 腾讯云超限错误转为友好提示 + const msg = sendResult.message || ''; + if (msg.toLowerCase().includes('exceeds the upper limit')) { + return { success: false, message: '今日发送次数已达上限' }; + } + return { success: false, message: msg || '短信发送失败' }; } // 存入缓存 diff --git a/view/admin/common/_sidebar.html b/view/admin/common/_sidebar.html index e868448..a5e7ad1 100644 --- a/view/admin/common/_sidebar.html +++ b/view/admin/common/_sidebar.html @@ -22,6 +22,16 @@ {% endif %} + {# 瘤种管理 #} + {% if isSuperAdmin or (userPermissions and 'tag' in userPermissions) %} + + {% endif %} + {# 内容管理 #} {% if isSuperAdmin or (userPermissions and 'content' in userPermissions) %}