From 3f7bf0d7f0bc509b6c779bb00b4c0021b7b143c3 Mon Sep 17 00:00:00 2001 From: zhx Date: Thu, 23 Jul 2026 19:21:40 +0800 Subject: [PATCH] feat(emoji): manage grouped access rules --- src/lang/messages/pages/en.js | 19 ++++-- src/lang/messages/pages/zh.js | 19 ++++-- src/views/sys/emoji-config/emoji/index.vue | 16 ++++- .../sys/emoji-config/group/form-edit.vue | 66 +++++++++++++++++-- src/views/sys/emoji-config/group/index.vue | 35 +++++++++- src/views/sys/emoji-config/index.vue | 20 +++++- 6 files changed, 159 insertions(+), 16 deletions(-) diff --git a/src/lang/messages/pages/en.js b/src/lang/messages/pages/en.js index b5fd3f8..67eff27 100644 --- a/src/lang/messages/pages/en.js +++ b/src/lang/messages/pages/en.js @@ -5276,7 +5276,11 @@ export default { }, table: { salePrice: 'Sale Price', - shelfStatus: 'On/Off Shelf' + shelfStatus: 'On/Off Shelf', + vipRange: 'VIP Range', + wealthRange: 'Wealth Range', + charmRange: 'Charm Range', + manageResources: 'Emojis' }, form: { groupCode: 'Group Code', @@ -5284,7 +5288,12 @@ export default { amount: 'Sale Price', shelfStatus: 'On/Off Shelf', ktvStatus: 'KTV Emoji', - weight: 'Weight' + weight: 'Weight', + accessRules: 'Access Rules', + vipRange: 'VIP Level Range', + wealthRange: 'Wealth Level Range', + charmRange: 'Charm Level Range', + rangeHelp: '0 means that boundary is unrestricted. Users must meet every configured level rule.' }, placeholder: { groupCode: 'Group Code', @@ -5321,14 +5330,16 @@ export default { offShelf: 'Off Shelf', yes: 'Yes', no: 'No', - free: 'Free' + free: 'Free', + unrestricted: 'Unrestricted' }, dialog: { add: 'Add', edit: 'Edit' }, validation: { - required: 'This field is required' + required: 'This field is required', + invalidLevelRange: 'Invalid level range: max must be 0 or greater than or equal to min' }, message: { onShelfSuccess: 'Listed successfully', diff --git a/src/lang/messages/pages/zh.js b/src/lang/messages/pages/zh.js index 7752099..46e45a3 100644 --- a/src/lang/messages/pages/zh.js +++ b/src/lang/messages/pages/zh.js @@ -5273,7 +5273,11 @@ export default { }, table: { salePrice: '售卖价格', - shelfStatus: '上/下架' + shelfStatus: '上/下架', + vipRange: 'VIP区间', + wealthRange: '财富区间', + charmRange: '魅力区间', + manageResources: '表情资源' }, form: { groupCode: '分组Code', @@ -5281,7 +5285,12 @@ export default { amount: '售卖价格', shelfStatus: '上/下架', ktvStatus: 'KTV表情', - weight: '权重' + weight: '权重', + accessRules: '使用权限', + vipRange: 'VIP等级区间', + wealthRange: '财富等级区间', + charmRange: '魅力等级区间', + rangeHelp: '0表示该边界不限制;配置多类等级时,用户需要同时满足全部条件。' }, placeholder: { groupCode: '分组Code', @@ -5318,14 +5327,16 @@ export default { offShelf: '下架', yes: '是', no: '否', - free: '免费' + free: '免费', + unrestricted: '不限' }, dialog: { add: '添加', edit: '修改' }, validation: { - required: '必填字段不可为空' + required: '必填字段不可为空', + invalidLevelRange: '等级区间无效:最大值必须为0或不小于最小值' }, message: { onShelfSuccess: '上架成功', diff --git a/src/views/sys/emoji-config/emoji/index.vue b/src/views/sys/emoji-config/emoji/index.vue index 3c1b732..adb37c3 100644 --- a/src/views/sys/emoji-config/emoji/index.vue +++ b/src/views/sys/emoji-config/emoji/index.vue @@ -317,6 +317,12 @@ function getFormData() { export default { name: 'EmojiConfig', components: { Pagination }, + props: { + initialGroup: { + type: Object, + default: null + } + }, data() { const commonRules = [ { required: true, message: this.$t('pages.emojiManagement.validation.required'), trigger: 'blur' } @@ -389,10 +395,16 @@ export default { created() { const that = this const querySystem = this.permissionsSysOriginPlatforms[0] - if (!querySystem) { + const sysOrigin = this.initialGroup && this.initialGroup.sysOrigin + ? this.initialGroup.sysOrigin + : querySystem && querySystem.value + if (!sysOrigin) { return } - that.listQuery.sysOrigin = querySystem.value + that.listQuery.sysOrigin = sysOrigin + that.listQuery.groupId = this.initialGroup && this.initialGroup.id + ? this.initialGroup.id + : '' that.renderData() that.loadGroupList() }, diff --git a/src/views/sys/emoji-config/group/form-edit.vue b/src/views/sys/emoji-config/group/form-edit.vue index 14cf968..411f793 100644 --- a/src/views/sys/emoji-config/group/form-edit.vue +++ b/src/views/sys/emoji-config/group/form-edit.vue @@ -7,10 +7,10 @@ :append-to-body="true" :before-close="handleClose" :close-on-click-modal="false" - width="450px" + width="720px" >
- + + {{ $t('pages.emojiManagement.group.form.accessRules') }} + + + - + + + + + - + + + + + - + + + + {{ $t('common.save') }} {{ $t('common.cancel') }} @@ -117,7 +140,13 @@ export default { sysOrigin: '', shelfStatus: '', ktvStatus: '', - amount: '' + amount: '', + minVipLevel: 0, + maxVipLevel: 0, + minWealthLevel: 0, + maxWealthLevel: 0, + minCharmLevel: 0, + maxCharmLevel: 0 }, formRules: { cover: commonRules, @@ -155,6 +184,17 @@ export default { } this.form = deepClone(newVal) + const accessLevelFields = [ + 'minVipLevel', + 'maxVipLevel', + 'minWealthLevel', + 'maxWealthLevel', + 'minCharmLevel', + 'maxCharmLevel' + ] + accessLevelFields.forEach(field => { + this.$set(this.form, field, Number(newVal[field] || 0)) + }) if (this.form.cover) { this.coverFileList = getElementUiUploadFile(this.form.cover) } @@ -187,6 +227,11 @@ export default { console.error('error submit!!') return false } + // 0 表示该边界不限制;非 0 的最大值必须覆盖最小值. + if (!that.validateAccessLevelRanges()) { + that.$message.error(that.$t('pages.emojiManagement.validation.invalidLevelRange')) + return false + } that.submitLoading = true addOrUpdateGroup(that.form).then(res => { that.submitLoading = false @@ -198,10 +243,23 @@ export default { }) return }) + }, + validateAccessLevelRanges() { + return [ + [this.form.minVipLevel, this.form.maxVipLevel], + [this.form.minWealthLevel, this.form.maxWealthLevel], + [this.form.minCharmLevel, this.form.maxCharmLevel] + ].every(([minLevel, maxLevel]) => { + const min = Number(minLevel || 0) + const max = Number(maxLevel || 0) + return min >= 0 && max >= 0 && (max === 0 || min <= max) + }) } } } diff --git a/src/views/sys/emoji-config/group/index.vue b/src/views/sys/emoji-config/group/index.vue index 2844c8f..f49ab48 100644 --- a/src/views/sys/emoji-config/group/index.vue +++ b/src/views/sys/emoji-config/group/index.vue @@ -105,16 +105,32 @@
+ + + + + + + + + - + @@ -210,6 +226,23 @@ export default { this.thisClickRow = Object.assign({}, row) this.formEditVisiable = true }, + clickManageResources(row) { + this.$emit('manage-resources', Object.assign({}, row)) + }, + formatLevelRange(minLevel, maxLevel, prefix = '') { + const min = Number(minLevel || 0) + const max = Number(maxLevel || 0) + const value = min === 0 && max === 0 + ? this.$t('pages.emojiManagement.options.unrestricted') + : max === 0 + ? `${min}+` + : min === 0 + ? `≤${max}` + : `${min}-${max}` + return prefix && value !== this.$t('pages.emojiManagement.options.unrestricted') + ? `${prefix}${value}` + : value + }, formEditSuccess() { this.handleSearch() this.formEditVisiable = false diff --git a/src/views/sys/emoji-config/index.vue b/src/views/sys/emoji-config/index.vue index 3ff4b32..85e4cae 100644 --- a/src/views/sys/emoji-config/index.vue +++ b/src/views/sys/emoji-config/index.vue @@ -2,7 +2,11 @@
- +
@@ -15,6 +19,7 @@ export default { data() { return { activeName: 'EmojiGroup', + selectedGroup: null, tables: [ { titleKey: 'pages.emojiManagement.tabs.group', @@ -26,6 +31,19 @@ export default { } ] } + }, + computed: { + activeComponentProps() { + return this.activeName === 'EmojiConf' + ? { initialGroup: this.selectedGroup } + : {} + } + }, + methods: { + handleManageResources(group) { + this.selectedGroup = group + this.activeName = 'EmojiConf' + } } }