refactor(admin): 权限码对齐后端 kebab/trade/通道统一

perm-codes 与页面引用同步:交易域 Trade、IAM 缩短、通道 App/Isv 统一码、配置类 MANAGE 等。
This commit is contained in:
DaxPay Dev
2026-07-13 11:58:49 +08:00
parent 56650f6a8a
commit 2aaa2b50e5
47 changed files with 165 additions and 224 deletions

View File

@@ -93,7 +93,7 @@ function filterButtonMenus(menus: PermMenuResult[]): PermMenuResult[] {
/**
* 过滤仅作权限锚点、无路由信息的菜单节点
* 中文:如 payment:alipay:isv / payment:wechat:isv 仅用于 @PermCode menuCode 挂载,无 path/component
* 中文:如 payment:isv / payment:isv 仅用于 @PermCode menuCode 挂载,无 path/component
*/
function filterPermissionAnchorMenus(menus: PermMenuResult[]): PermMenuResult[] {
return menus

View File

@@ -59,7 +59,7 @@ function filterButtonMenus(menus: PermMenu[]): PermMenu[] {
/**
* 过滤仅作权限锚点、无路由信息的菜单节点
* 中文:如 payment:alipay:isv / payment:wechat:isv 仅用于 @PermCode menuCode 挂载,无 path/component
* 中文:如 payment:isv / payment:isv 仅用于 @PermCode menuCode 挂载,无 path/component
*/
function filterPermissionAnchorMenus(menus: PermMenu[]): PermMenu[] {
return menus

View File

@@ -5,239 +5,187 @@
*
* | 要点 | 说明 |
* |------|------|
* | 与后端对齐 | 值必须等于 @PermCode 扫描出的完整码 `menuCode:code` |
* | 后端常量 | `daxpay-platform-core` → `cn.daxpay.open.platform.core.code.PermCodes`(嵌套 interface`MENU` + `Action`,非完整码) |
* | 命名约定 | 全部使用下划线(`security_config` `securityConfig`),键名用业务语义 |
* | 粒度约定 | 标准为 `VIEW` + `MANAGE``MANAGE` 含增删改);仅查看的只保留 `VIEW` |
* | 特殊操作 | `PUBLISH`/`KICKOUT`/`RESET_PASSWORD`/`ASSIGN_ROLE`/`STATUS`/`SIGN`/`PAY`/`CREDENTIAL_CONFIG_UPDATE` 独立保留 |
* | menu_code | 菜单注册iam_perm_menu**不**写入本文件;后端 `PermCodes.*.MENU` 与之对应 |
* | 顶级域 | merchant / channel / payment / develop / device / iam / system 七域 |
* | 使用方式 | 模板:`v-if="hasPermission(PermCodes....)"` / `hasAnyPermission([...])``usePermission`);脚本:同上 |
* | 已移除 | v-access 指令已删除,仅用 `usePermission` |
* | 与后端对齐 | 值 = `menuCode:action`;后端 `platform.core.code.PermCodes`MENU + Action非完整码 |
* | 命名 | 码字符串 kebab-case`a-z0-9:-`TS 键 SCREAMING_SNAKE |
* | 粒度 | 标准 `VIEW` + `MANAGE`MANAGE 含增删改与配置保存);无全局 update |
* | 特殊操作 | PUBLISH / KICKOUT / RESET_PASSWORD / ASSIGN_ROLE / STATUS / SIGN / RESEND / TEST |
* | 顶级域 | merchant / channel / payment / **trade** / develop / device / iam / system |
* | 通道相关 | 商户 `channel:merchant`;应用 `channel:app`ISV `payment:isv`(均不按通道拆) |
* | 使用 | `hasPermission(PermCodes....)` / `hasAnyPermission([...])` |
*/
export const PermCodes = {
/** IAM 身份与访问 */
Iam: {
PermMenu: {
VIEW: 'iam:perm:menu:view',
MANAGE: 'iam:perm:menu:manage',
Menu: {
VIEW: 'iam:menu:view',
MANAGE: 'iam:menu:manage',
},
Role: {
VIEW: 'iam:role:view',
MANAGE: 'iam:role:manage',
},
UserManager: {
VIEW: 'iam:user:manager:view',
MANAGE: 'iam:user:manager:manage',
RESET_PASSWORD: 'iam:user:manager:reset_password',
ASSIGN_ROLE: 'iam:user:manager:assign_role',
STATUS: 'iam:user:manager:status',
User: {
VIEW: 'iam:user:view',
MANAGE: 'iam:user:manage',
RESET_PASSWORD: 'iam:user:reset-password',
ASSIGN_ROLE: 'iam:user:assign-role',
STATUS: 'iam:user:status',
},
OnlineUser: {
VIEW: 'iam:online:user:view',
KICKOUT: 'iam:online:user:kickout',
Online: {
VIEW: 'iam:online:view',
KICKOUT: 'iam:online:kickout',
},
Social: {
VIEW: 'iam:social:login-config:view',
MANAGE: 'iam:social:login-config:manage',
VIEW: 'iam:social:view',
MANAGE: 'iam:social:manage',
},
},
/** 商户管理(独立顶级域) */
/** 商户管理 */
Merchant: {
/** 商户主体 menuCode=merchant:info */
Info: {
VIEW: 'merchant:info:view',
MANAGE: 'merchant:info:manage',
},
/** 对接配置 menuCode=merchant:credential */
Credential: {
VIEW: 'merchant:credential:view',
CREDENTIAL_CONFIG_UPDATE: 'merchant:credential:credential_config_update',
MANAGE: 'merchant:credential:manage',
},
/** 通知配置 menuCode=merchant:notify_config */
NotifyConfig: {
VIEW: 'merchant:notify_config:view',
UPDATE: 'merchant:notify_config:notify_config_update',
VIEW: 'merchant:notify-config:view',
MANAGE: 'merchant:notify-config:manage',
},
/** 商户应用 menuCode=merchant:app */
App: {
VIEW: 'merchant:app:view',
MANAGE: 'merchant:app:manage',
},
/** 通道路由 menuCode=merchant:app:route */
AppRoute: {
VIEW: 'merchant:app:route:view',
MANAGE: 'merchant:app:route:manage',
},
/** 码牌和聚合支付配置 menuCode=merchant:gateway-aggregate */
GatewayAggregate: {
VIEW: 'merchant:gateway-aggregate:view',
MANAGE: 'merchant:gateway-aggregate:update',
MANAGE: 'merchant:gateway-aggregate:manage',
},
/** 收银台配置 menuCode=merchant:gateway-cashier */
GatewayCashier: {
VIEW: 'merchant:gateway-cashier:view',
MANAGE: 'merchant:gateway-cashier:update',
MANAGE: 'merchant:gateway-cashier:manage',
},
/** 门店 menuCode=merchant:store */
Store: {
VIEW: 'merchant:store:view',
MANAGE: 'merchant:store:manage',
},
/** 商户用户 menuCode=merchant:user预留待 Controller 实现) */
/** 预留 */
User: {
VIEW: 'merchant:user:view',
MANAGE: 'merchant:user:manage',
},
/** 微信域名验证文件 menuCode=merchant:wx_verify */
WxDomainVerify: {
VIEW: 'merchant:wx_verify:view',
MANAGE: 'merchant:wx_verify:manage',
VIEW: 'merchant:wx-verify:view',
MANAGE: 'merchant:wx-verify:manage',
},
},
/** 渠道管理(独立顶级域 */
/** 渠道(通道商户 / 通道应用均统一码,不按通道拆 */
Channel: {
/** 通道商户 menuCode=channel:merchant */
Merchant: {
VIEW: 'channel:merchant:view',
MANAGE: 'channel:merchant:manage',
},
/** 支付宝直连应用 menuCode=channel:alipay:app */
AlipayApp: {
VIEW: 'channel:alipay:app:view',
MANAGE: 'channel:alipay:app:manage',
},
/** 微信直连应用 menuCode=channel:wechat:app */
WechatApp: {
VIEW: 'channel:wechat:app:view',
MANAGE: 'channel:wechat:app:manage',
},
/** 抖音直连应用 menuCode=channel:douyin:app */
DouyinApp: {
VIEW: 'channel:douyin:app:view',
MANAGE: 'channel:douyin:app:manage',
/** 通道应用(直连 + 子商户应用等)menuCode=channel:app */
App: {
VIEW: 'channel:app:view',
MANAGE: 'channel:app:manage',
},
},
/** 支付核心(瘦身后:主数据 + 配置 + 服务商 */
/** 支付平台(主数据 + 配置 + ISV */
Payment: {
/** 支付宝服务商 menuCode=payment:alipay:isv */
AlipayIsv: {
VIEW: 'payment:alipay:isv:view',
MANAGE: 'payment:alipay:isv:manage',
/** 服务商 ISV 配置(全通道共用)menuCode=payment:isv */
Isv: {
VIEW: 'payment:isv:view',
MANAGE: 'payment:isv:manage',
},
/** 微信服务商 menuCode=payment:wechat:isv */
WechatIsv: {
VIEW: 'payment:wechat:isv:view',
MANAGE: 'payment:wechat:isv:manage',
},
/** 拉卡拉服务商 menuCode=payment:lakala:isv */
Lakala: {
VIEW: 'payment:lakala:isv:view',
MANAGE: 'payment:lakala:isv:manage',
},
/** 海科融通服务商 menuCode=payment:hkrt:isv */
Hkrt: {
VIEW: 'payment:hkrt:isv:view',
MANAGE: 'payment:hkrt:isv:manage',
},
/** 斗拱服务商 menuCode=payment:dougong:isv */
Dougong: {
VIEW: 'payment:dougong:isv:view',
MANAGE: 'payment:dougong:isv:manage',
},
/** 随行付服务商 menuCode=payment:vbill:isv */
Vbill: {
VIEW: 'payment:vbill:isv:view',
MANAGE: 'payment:vbill:isv:manage',
},
/** 富友服务商 menuCode=payment:fuyou:isv */
Fuyou: {
VIEW: 'payment:fuyou:isv:view',
MANAGE: 'payment:fuyou:isv:manage',
},
/** 支付主数据 menuCode=payment:platform:* */
Platform: {
Product: {
VIEW: 'payment:platform:product:view',
MANAGE: 'payment:platform:product:manage',
},
/** 支付方式 */
PayMethod: {
VIEW: 'payment:platform:pay-method:view',
MANAGE: 'payment:platform:pay-method:manage',
},
/** 支付渠道 */
Provider: {
VIEW: 'payment:platform:provider:view',
MANAGE: 'payment:platform:provider:manage',
},
PayChannel: {
VIEW: 'payment:platform:pay_channel:view',
VIEW: 'payment:platform:pay-channel:view',
},
Capability: {
VIEW: 'payment:platform:capability:view',
},
},
/** 支付产品配置 menuCode=payment:config:product_config */
ProductConfig: {
VIEW: 'payment:config:product_config:view',
MANAGE: 'payment:config:product_config:manage',
VIEW: 'payment:config:product-config:view',
MANAGE: 'payment:config:product-config:manage',
},
/** 微信域名验证文件 menuCode=payment:config:wx_verify */
Config: {
WxDomainVerify: {
VIEW: 'payment:config:wx_verify:view',
MANAGE: 'payment:config:wx_verify:manage',
VIEW: 'payment:config:wx-verify:view',
MANAGE: 'payment:config:wx-verify:manage',
},
},
/** 普通支付业务订单 menuCode=payment:order */
Order: {
VIEW: 'payment:order:view',
MANAGE: 'payment:order:manage',
},
/** 退款订单 menuCode=payment:refund */
Refund: {
VIEW: 'payment:refund:view',
MANAGE: 'payment:refund:manage',
},
/** 资金交易凭证 menuCode=payment:trade */
Trade: {
VIEW: 'payment:trade:view',
MANAGE: 'payment:trade:manage',
},
},
/** 开发调试(独立顶级域) */
/** 交易单据 */
Trade: {
Order: {
VIEW: 'trade:order:view',
MANAGE: 'trade:order:manage',
},
Refund: {
VIEW: 'trade:refund:view',
MANAGE: 'trade:refund:manage',
},
Fund: {
VIEW: 'trade:fund:view',
MANAGE: 'trade:fund:manage',
},
GatewayOrder: {
VIEW: 'trade:gateway-order:view',
MANAGE: 'trade:gateway-order:manage',
},
},
Develop: {
/** 支付调试 menuCode=develop:trade真实支付走 unipay, 无 develop:trade:pay 后门) */
Trade: {
VIEW: 'develop:trade:view',
SIGN: 'develop:trade:sign',
},
/** 签名调试 menuCode=develop:sign */
Sign: {
VIEW: 'develop:sign:view',
},
/** 认证调试 menuCode=develop:auth */
Auth: {
VIEW: 'develop:auth:view',
},
},
/** 设备管理(独立命名空间;开源仅码牌,硬件对接归商业版) */
Device: {
/** 码牌 menuCode=device:qrcode */
QrCode: {
VIEW: 'device:qrcode:view',
MANAGE: 'device:qrcode:manage',
},
},
/** 系统域 */
System: {
/** 字典含字典项menuCode=system:dict */
Dict: {
VIEW: 'system:dict:view',
MANAGE: 'system:dict:manage',
},
/** 日志 menuCode=system:log:* */
Log: {
Login: {
VIEW: 'system:log:login:view',
@@ -248,39 +196,32 @@ export const PermCodes = {
MANAGE: 'system:log:operate:manage',
},
},
/** 通知中心 menuCode=system:notify → 公告通知 menuCode=system:notify:notice */
Notify: {
VIEW: 'system:notify:notice:view',
MANAGE: 'system:notify:notice:manage',
PUBLISH: 'system:notify:notice:publish',
},
/** 微信消息通知 menuCode=system:notify:wechat-config配置 + 发送记录 Tabs */
WechatNotify: {
MANAGE: 'system:notify:wechat-config:manage',
VIEW: 'system:notify:wechat-config:view',
RESEND: 'system:notify:wechat-config:resend',
TEST: 'system:notify:wechat-config:test',
},
/** 存储文件 menuCode=system:file:platform */
FilePlatform: {
VIEW: 'system:file:platform:view',
File: {
VIEW: 'system:file:view',
},
/** 平台配置 menuCode=system:platform_config */
PlatformConfig: {
VIEW: 'system:platform_config:view',
MANAGE: 'system:platform_config:manage',
VIEW: 'system:platform-config:view',
MANAGE: 'system:platform-config:manage',
},
/** OSS 配置 menuCode=system:oss_config */
OssConfig: {
VIEW: 'system:oss_config:view',
MANAGE: 'system:oss_config:manage',
VIEW: 'system:oss-config:view',
MANAGE: 'system:oss-config:manage',
},
/** 安全配置 menuCode=system:security_config */
SecurityConfig: {
VIEW: 'system:security_config:view',
MANAGE: 'system:security_config:manage',
VIEW: 'system:security-config:view',
MANAGE: 'system:security-config:manage',
},
/** 用户协议 menuCode=system:protocol */
Protocol: {
VIEW: 'system:protocol:view',
MANAGE: 'system:protocol:manage',

View File

@@ -76,7 +76,7 @@ export const ENTRY_CATALOG: QuickEntryMeta[] = [
icon: 'lucide:users-round',
titleKey: 'dashboard.workspace.quickEntry.user',
color: 'bg-rose-500',
perms: [PermCodes.Iam.UserManager.VIEW],
perms: [PermCodes.Iam.User.VIEW],
defaultVisible: true,
defaultOrder: 5,
},
@@ -117,7 +117,7 @@ export const ENTRY_CATALOG: QuickEntryMeta[] = [
icon: 'lucide:receipt',
titleKey: 'dashboard.workspace.quickEntry.payOrder',
color: 'bg-blue-600',
perms: [PermCodes.Payment.Order.VIEW],
perms: [PermCodes.Trade.Order.VIEW],
defaultVisible: false,
defaultOrder: 9,
},
@@ -127,7 +127,7 @@ export const ENTRY_CATALOG: QuickEntryMeta[] = [
icon: 'lucide:rotate-ccw',
titleKey: 'dashboard.workspace.quickEntry.refundOrder',
color: 'bg-orange-500',
perms: [PermCodes.Payment.Refund.VIEW],
perms: [PermCodes.Trade.Refund.VIEW],
defaultVisible: false,
defaultOrder: 10,
},
@@ -137,7 +137,7 @@ export const ENTRY_CATALOG: QuickEntryMeta[] = [
icon: 'lucide:arrow-left-right',
titleKey: 'dashboard.workspace.quickEntry.payTrade',
color: 'bg-teal-500',
perms: [PermCodes.Payment.Trade.VIEW],
perms: [PermCodes.Trade.Fund.VIEW],
defaultVisible: false,
defaultOrder: 11,
},
@@ -157,7 +157,7 @@ export const ENTRY_CATALOG: QuickEntryMeta[] = [
icon: 'lucide:panel-top',
titleKey: 'dashboard.workspace.quickEntry.menu',
color: 'bg-sky-500',
perms: [PermCodes.Iam.PermMenu.VIEW],
perms: [PermCodes.Iam.Menu.VIEW],
defaultVisible: false,
defaultOrder: 13,
},
@@ -207,7 +207,7 @@ export const ENTRY_CATALOG: QuickEntryMeta[] = [
icon: 'lucide:users',
titleKey: 'dashboard.workspace.quickEntry.onlineUser',
color: 'bg-green-500',
perms: [PermCodes.Iam.OnlineUser.VIEW],
perms: [PermCodes.Iam.Online.VIEW],
defaultVisible: false,
defaultOrder: 18,
},

View File

@@ -241,7 +241,7 @@
style="width: 280px"
/>
<a-button
v-if="panelMode === 'menuChildren' && hasPermission(PermCodes.Iam.PermMenu.MANAGE)"
v-if="panelMode === 'menuChildren' && hasPermission(PermCodes.Iam.Menu.MANAGE)"
type="primary"
@click="emits('addGroup', selectedNode!)"
>
@@ -250,7 +250,7 @@
<a-button
v-if="
(panelMode === 'menuChildren' || panelMode === 'groupSubpages') &&
hasPermission(PermCodes.Iam.PermMenu.MANAGE)
hasPermission(PermCodes.Iam.Menu.MANAGE)
"
type="primary"
@click="emits('addSubpage', selectedNode!)"
@@ -271,7 +271,7 @@
<vxe-column field="titleCn" :title="$t('iam.menu.titleCn')" :min-width="140">
<template #default="{ row }">
<a
v-if="hasPermission(PermCodes.Iam.PermMenu.VIEW)"
v-if="hasPermission(PermCodes.Iam.Menu.VIEW)"
href="javascript:"
class="vben-link"
@click="emits('view', row)"
@@ -296,7 +296,7 @@
<a-divider type="vertical" />
</template>
<a-button
v-if="hasPermission(PermCodes.Iam.PermMenu.MANAGE)"
v-if="hasPermission(PermCodes.Iam.Menu.MANAGE)"
type="link"
size="small"
@click="emits('edit', row)"
@@ -304,7 +304,7 @@
{{ $t('common.edit') }}
</a-button>
<a-button
v-if="canManagePermCode(row) && hasPermission(PermCodes.Iam.PermMenu.MANAGE)"
v-if="canManagePermCode(row) && hasPermission(PermCodes.Iam.Menu.MANAGE)"
type="link"
size="small"
@click="emits('managePermCode', row)"
@@ -312,7 +312,7 @@
{{ $t('iam.menu.managePermCode') }}
</a-button>
<a-button
v-if="hasPermission(PermCodes.Iam.PermMenu.MANAGE)"
v-if="hasPermission(PermCodes.Iam.Menu.MANAGE)"
type="link"
size="small"
danger

View File

@@ -368,11 +368,11 @@
<vxe-toolbar ref="skeletonToolbar" custom refresh :refresh-options="{ queryMethod: queryPage }">
<template #buttons>
<a-space>
<a-button v-if="hasPermission(PermCodes.Iam.PermMenu.MANAGE)" type="primary" @click="handleAdd">
<a-button v-if="hasPermission(PermCodes.Iam.Menu.MANAGE)" type="primary" @click="handleAdd">
{{ $t('common.add') }}
</a-button>
<a-button
v-if="hasPermission(PermCodes.Iam.PermMenu.MANAGE)"
v-if="hasPermission(PermCodes.Iam.Menu.MANAGE)"
:loading="scanLoading"
@click="handleScanPermCode"
>
@@ -439,7 +439,7 @@
<a-divider type="vertical" />
</template>
<a-button
v-if="hasPermission(PermCodes.Iam.PermMenu.VIEW)"
v-if="hasPermission(PermCodes.Iam.Menu.VIEW)"
type="link"
size="small"
@click.stop="handleView(row)"
@@ -447,7 +447,7 @@
{{ $t('common.view') }}
</a-button>
<a-button
v-if="hasPermission(PermCodes.Iam.PermMenu.MANAGE)"
v-if="hasPermission(PermCodes.Iam.Menu.MANAGE)"
type="link"
size="small"
@click.stop="handleEdit(row)"
@@ -455,7 +455,7 @@
{{ $t('common.edit') }}
</a-button>
<a-button
v-if="canManagePermCode(row) && hasPermission(PermCodes.Iam.PermMenu.MANAGE)"
v-if="canManagePermCode(row) && hasPermission(PermCodes.Iam.Menu.MANAGE)"
type="link"
size="small"
@click.stop="handleManagePermCode(row)"
@@ -463,7 +463,7 @@
{{ $t('iam.menu.managePermCode') }}
</a-button>
<a-dropdown
v-if="hasPermission(PermCodes.Iam.PermMenu.MANAGE)"
v-if="hasPermission(PermCodes.Iam.Menu.MANAGE)"
:menu="getActionMenu(row)"
@click.stop
>

View File

@@ -201,32 +201,32 @@
{
key: 'assignRole',
label: $t('iam.user.action.assignRole'),
disabled: !hasPermission(PermCodes.Iam.UserManager.ASSIGN_ROLE) || !isAdminClient.value,
disabled: !hasPermission(PermCodes.Iam.User.ASSIGN_ROLE) || !isAdminClient.value,
},
// 重置密码
{
key: 'resetPassword',
label: $t('iam.user.action.resetPassword'),
disabled: !hasPermission(PermCodes.Iam.UserManager.RESET_PASSWORD),
disabled: !hasPermission(PermCodes.Iam.User.RESET_PASSWORD),
},
// 三方绑定
{
key: 'socialBind',
label: $t('iam.user.action.socialBind'),
disabled: !hasPermission(PermCodes.Iam.UserManager.VIEW),
disabled: !hasPermission(PermCodes.Iam.User.VIEW),
},
{ type: 'divider' },
// 封禁
{
key: 'ban',
label: $t('iam.user.action.ban'),
disabled: !hasPermission(PermCodes.Iam.UserManager.STATUS) || row.status === 'ban',
disabled: !hasPermission(PermCodes.Iam.User.STATUS) || row.status === 'ban',
},
// 解锁(后端 unlock 无条件置为 NORMAL对 lock/ban 均生效)
{
key: 'unlock',
label: $t('iam.user.action.unlock'),
disabled: !hasPermission(PermCodes.Iam.UserManager.STATUS) || row.status === 'normal',
disabled: !hasPermission(PermCodes.Iam.User.STATUS) || row.status === 'normal',
},
],
onClick: ({ key }: { key: string }) => {
@@ -272,19 +272,19 @@
{
key: 'ban',
label: $t('iam.user.action.batchBan'),
disabled: selectedRows.value.length === 0 || !hasPermission(PermCodes.Iam.UserManager.STATUS),
disabled: selectedRows.value.length === 0 || !hasPermission(PermCodes.Iam.User.STATUS),
},
// 批量解锁
{
key: 'unlock',
label: $t('iam.user.action.batchUnlock'),
disabled: selectedRows.value.length === 0 || !hasPermission(PermCodes.Iam.UserManager.STATUS),
disabled: selectedRows.value.length === 0 || !hasPermission(PermCodes.Iam.User.STATUS),
},
// 批量重置密码
{
key: 'resetPassword',
label: $t('iam.user.action.batchResetPassword'),
disabled: selectedRows.value.length === 0 || !hasPermission(PermCodes.Iam.UserManager.RESET_PASSWORD),
disabled: selectedRows.value.length === 0 || !hasPermission(PermCodes.Iam.User.RESET_PASSWORD),
},
],
onClick: ({ key }: { key: string }) => {
@@ -438,14 +438,14 @@
<a-space>
<!-- 新增 -->
<a-button
v-if="showAddButton && hasPermission(PermCodes.Iam.UserManager.MANAGE)"
v-if="showAddButton && hasPermission(PermCodes.Iam.User.MANAGE)"
type="primary"
@click="handleAdd"
>
{{ $t('common.add') }}
</a-button>
<a-dropdown
v-if="hasAnyPermission([PermCodes.Iam.UserManager.STATUS, PermCodes.Iam.UserManager.RESET_PASSWORD])"
v-if="hasAnyPermission([PermCodes.Iam.User.STATUS, PermCodes.Iam.User.RESET_PASSWORD])"
:menu="getBatchActionMenu()"
>
<!-- 操作 -->
@@ -509,12 +509,12 @@
<a-divider type="vertical" />
</template>
<!-- 查看 -->
<a v-if="hasPermission(PermCodes.Iam.UserManager.VIEW)" href="javascript:" @click="handleView(row)">{{
<a v-if="hasPermission(PermCodes.Iam.User.VIEW)" href="javascript:" @click="handleView(row)">{{
$t('common.view')
}}</a>
<!-- 编辑 -->
<a
v-if="hasPermission(PermCodes.Iam.UserManager.MANAGE)"
v-if="hasPermission(PermCodes.Iam.User.MANAGE)"
href="javascript:"
:class="isAdminClient ? '' : 'ant-typography-disabled'"
:style="isAdminClient ? '' : 'pointer-events: none; color: rgba(0, 0, 0, 0.25);'"

View File

@@ -52,7 +52,7 @@
<!-- 底部操作栏 -->
<div class="card-footer flex shrink-0 items-center justify-end border-t border-border px-3 py-1.5">
<div class="flex items-center">
<a-tooltip v-if="hasPermission(PermCodes.Payment.AlipayIsv.MANAGE)" :title="$t('payment.channel.alipayManage.edit')">
<a-tooltip v-if="hasPermission(PermCodes.Payment.Isv.MANAGE)" :title="$t('payment.channel.alipayManage.edit')">
<a-button
type="text"
size="small"
@@ -64,7 +64,7 @@
</template>
</a-button>
</a-tooltip>
<a-tooltip v-if="hasPermission(PermCodes.Payment.AlipayIsv.MANAGE)" :title="$t('payment.channel.alipayManage.actionMore')">
<a-tooltip v-if="hasPermission(PermCodes.Payment.Isv.MANAGE)" :title="$t('payment.channel.alipayManage.actionMore')">
<a-button
type="text"
size="small"

View File

@@ -24,7 +24,7 @@
const editRef = ref<InstanceType<typeof AlipayIsvAppEdit>>();
const detailRef = ref<InstanceType<typeof AlipayIsvAppDetail>>();
const canAdd = computed(() => hasPermission(PermCodes.Payment.AlipayIsv.MANAGE));
const canAdd = computed(() => hasPermission(PermCodes.Payment.Isv.MANAGE));
/**
* 加载应用列表

View File

@@ -26,7 +26,7 @@
userIdType: 'openid',
});
const canEdit = computed(() => hasPermission(PermCodes.Payment.AlipayIsv.MANAGE));
const canEdit = computed(() => hasPermission(PermCodes.Payment.Isv.MANAGE));
/** 表单校验规则 */
const formRules = computed(() => ({

View File

@@ -52,7 +52,7 @@
</a-descriptions-item>
</a-descriptions>
<div v-if="hasPermission(PermCodes.Payment.AlipayIsv.MANAGE)" class="basic-info-panel__actions">
<div v-if="hasPermission(PermCodes.Payment.Isv.MANAGE)" class="basic-info-panel__actions">
<!-- 国际化删除 -->
<a-button danger @click="handleDelete">{{ $t('payment.channel.alipayManage.delete') }}</a-button>
</div>

View File

@@ -34,7 +34,7 @@
// 原始脱敏数据,用于 diffForm 比对
const originalForm = ref<AlipayIsvAppKeyConfig>({});
const canEdit = computed(() => hasPermission(PermCodes.Payment.AlipayIsv.MANAGE));
const canEdit = computed(() => hasPermission(PermCodes.Payment.Isv.MANAGE));
/** 表单校验规则 */
const formRules = computed(() => ({

View File

@@ -67,7 +67,7 @@
<div class="card-footer flex shrink-0 items-center justify-end border-t border-border px-3 py-1.5">
<div class="flex items-center">
<a-tooltip
v-if="hasPermission(PermCodes.Channel.AlipayApp.MANAGE)"
v-if="hasPermission(PermCodes.Channel.App.MANAGE)"
:title="$t('payment.channel.alipayMchApp.edit')"
>
<a-button
@@ -82,7 +82,7 @@
</a-button>
</a-tooltip>
<a-tooltip
v-if="hasPermission(PermCodes.Channel.AlipayApp.MANAGE)"
v-if="hasPermission(PermCodes.Channel.App.MANAGE)"
:title="$t('payment.channel.alipayMchApp.actionMore')"
>
<a-button

View File

@@ -51,7 +51,7 @@
const editRef = ref<InstanceType<typeof AlipayMchAppEdit>>();
const detailRef = ref<InstanceType<typeof AlipayMchAppDetail>>();
const canAdd = computed(() => hasPermission(PermCodes.Channel.AlipayApp.MANAGE));
const canAdd = computed(() => hasPermission(PermCodes.Channel.App.MANAGE));
const pageTitle = computed(() => {
const base = $t('payment.channel.alipayMchManage.cardMchApp');

View File

@@ -28,7 +28,7 @@
userIdType: 'openid',
});
const canEdit = computed(() => hasPermission(PermCodes.Channel.AlipayApp.MANAGE));
const canEdit = computed(() => hasPermission(PermCodes.Channel.App.MANAGE));
/** 表单校验规则 */
const formRules = computed(() => ({

View File

@@ -47,7 +47,7 @@
</a-descriptions-item>
</a-descriptions>
<div v-if="hasPermission(PermCodes.Channel.AlipayApp.MANAGE)" class="basic-info-panel__actions">
<div v-if="hasPermission(PermCodes.Channel.App.MANAGE)" class="basic-info-panel__actions">
<a-button danger @click="handleDelete">{{ $t('payment.channel.alipayMchApp.delete') }}</a-button>
</div>
</div>

View File

@@ -36,7 +36,7 @@
});
const originalForm = ref<AlipayMchAppKeyConfig>({});
const canEdit = computed(() => hasPermission(PermCodes.Channel.AlipayApp.MANAGE));
const canEdit = computed(() => hasPermission(PermCodes.Channel.App.MANAGE));
const formRules = computed(() => ({
authType: [{ required: true, message: $t('payment.channel.alipayIsv.validation.authType') }],

View File

@@ -31,7 +31,7 @@
const form = ref<DougongIsvKeyConfig>({} as DougongIsvKeyConfig);
let rawForm: Record<string, any> = {};
const canEdit = computed(() => hasPermission(PermCodes.Payment.Dougong.MANAGE));
const canEdit = computed(() => hasPermission(PermCodes.Payment.Isv.MANAGE));
// 斗拱服务商密钥配置
const drawerTitle = $t('payment.channel.dougongIsv.configTitle');

View File

@@ -63,7 +63,7 @@
<div class="card-footer flex shrink-0 items-center justify-end border-t border-border px-3 py-1.5">
<div class="flex items-center">
<a-tooltip
v-if="hasPermission(PermCodes.Channel.DouyinApp.MANAGE)"
v-if="hasPermission(PermCodes.Channel.App.MANAGE)"
:title="$t('payment.channel.douyinMchApp.edit')"
>
<a-button
@@ -78,7 +78,7 @@
</a-button>
</a-tooltip>
<a-tooltip
v-if="hasPermission(PermCodes.Channel.DouyinApp.VIEW)"
v-if="hasPermission(PermCodes.Channel.App.VIEW)"
:title="$t('payment.channel.douyinMchApp.actionMore')"
>
<a-button

View File

@@ -53,7 +53,7 @@
const editRef = ref<InstanceType<typeof DouyinMchAppEdit>>();
const detailRef = ref<InstanceType<typeof DouyinMchAppDetail>>();
const canAdd = computed(() => hasPermission(PermCodes.Channel.DouyinApp.MANAGE));
const canAdd = computed(() => hasPermission(PermCodes.Channel.App.MANAGE));
const pageTitle = computed(() => {
const base = $t('payment.channel.douyinMchApp.appManageTitle');

View File

@@ -30,7 +30,7 @@
const formState = ref<DouyinMchAppAuthConfig>({});
const originalForm = ref<DouyinMchAppAuthConfig>({});
const canEdit = computed(() => hasPermission(PermCodes.Channel.DouyinApp.MANAGE));
const canEdit = computed(() => hasPermission(PermCodes.Channel.App.MANAGE));
// 是否为小程序类型
const isMiniProgram = computed(() => props.appType === 'mini_program');

View File

@@ -61,7 +61,7 @@
</a-descriptions-item>
</a-descriptions>
<div v-if="hasPermission(PermCodes.Channel.DouyinApp.MANAGE)" class="basic-info-panel__actions">
<div v-if="hasPermission(PermCodes.Channel.App.MANAGE)" class="basic-info-panel__actions">
<a-button danger @click="handleDelete">{{ $t('payment.channel.douyinMchApp.delete') }}</a-button>
</div>
</div>

View File

@@ -31,7 +31,7 @@
const sandbox = ref(false);
// 富友权限码
const canEdit = computed(() => hasPermission(PermCodes.Payment.Fuyou.MANAGE));
const canEdit = computed(() => hasPermission(PermCodes.Payment.Isv.MANAGE));
const drawerTitle = $t('payment.channel.fuyouIsv.configTitle');

View File

@@ -30,7 +30,7 @@
// 当前环境(由管理页传入)
const sandbox = ref(false);
const canEdit = computed(() => hasPermission(PermCodes.Payment.Hkrt.MANAGE));
const canEdit = computed(() => hasPermission(PermCodes.Payment.Isv.MANAGE));
const drawerTitle = $t('payment.channel.hkrtIsv.configTitle');

View File

@@ -33,7 +33,7 @@
// 当前环境(由管理页传入)
const sandbox = ref(false);
const canEdit = computed(() => hasPermission(PermCodes.Payment.Lakala.MANAGE));
const canEdit = computed(() => hasPermission(PermCodes.Payment.Isv.MANAGE));
const drawerTitle = $t('payment.channel.lakalaIsv.configTitle');

View File

@@ -31,7 +31,7 @@
const sandbox = ref(false);
// 乐刷权限码(参考 lakala, 需在 PermCodes 中注册)
const canEdit = computed(() => hasPermission(PermCodes.Payment.Lakala.MANAGE));
const canEdit = computed(() => hasPermission(PermCodes.Payment.Isv.MANAGE));
const drawerTitle = $t('payment.channel.leshuaIsv.configTitle');

View File

@@ -30,7 +30,7 @@
// 当前环境(由管理页传入)
const sandbox = ref(false);
const canEdit = computed(() => hasPermission(PermCodes.Payment.Vbill.MANAGE));
const canEdit = computed(() => hasPermission(PermCodes.Payment.Isv.MANAGE));
const drawerTitle = $t('payment.channel.vbillIsv.configTitle');

View File

@@ -28,7 +28,7 @@
const form = ref<WechatIsvKeyConfig>({} as WechatIsvKeyConfig);
let rawForm: Record<string, any> = {};
const canEdit = computed(() => hasPermission(PermCodes.Payment.WechatIsv.MANAGE));
const canEdit = computed(() => hasPermission(PermCodes.Payment.Isv.MANAGE));
const drawerTitle = $t('payment.channel.wechatManage.mchKeyTitle');

View File

@@ -63,7 +63,7 @@
<div class="card-footer flex shrink-0 items-center justify-end border-t border-border px-3 py-1.5">
<div class="flex items-center">
<a-tooltip v-if="hasPermission(PermCodes.Payment.WechatIsv.MANAGE)" :title="$t('payment.channel.wechatManage.edit')">
<a-tooltip v-if="hasPermission(PermCodes.Payment.Isv.MANAGE)" :title="$t('payment.channel.wechatManage.edit')">
<a-button
type="text"
size="small"
@@ -75,7 +75,7 @@
</template>
</a-button>
</a-tooltip>
<a-tooltip v-if="hasPermission(PermCodes.Payment.WechatIsv.MANAGE)" :title="$t('payment.channel.wechatManage.actionMore')">
<a-tooltip v-if="hasPermission(PermCodes.Payment.Isv.MANAGE)" :title="$t('payment.channel.wechatManage.actionMore')">
<a-button
type="text"
size="small"

View File

@@ -24,7 +24,7 @@
const editRef = ref<InstanceType<typeof WechatIsvAppEdit>>();
const detailRef = ref<InstanceType<typeof WechatIsvAppDetail>>();
const canAdd = computed(() => hasPermission(PermCodes.Payment.WechatIsv.MANAGE));
const canAdd = computed(() => hasPermission(PermCodes.Payment.Isv.MANAGE));
function loadAppList() {
loading.value = true;

View File

@@ -25,7 +25,7 @@
const formState = ref<WechatIsvAppAuthConfig>({});
const originalForm = ref<WechatIsvAppAuthConfig>({});
const canEdit = computed(() => hasPermission(PermCodes.Payment.WechatIsv.MANAGE));
const canEdit = computed(() => hasPermission(PermCodes.Payment.Isv.MANAGE));
/** AppSecret 提示文案(按应用类型) */
const appSecretTooltip = computed(() => {

View File

@@ -62,7 +62,7 @@
</a-descriptions-item>
</a-descriptions>
<div v-if="hasPermission(PermCodes.Payment.WechatIsv.MANAGE)" class="basic-info-panel__actions">
<div v-if="hasPermission(PermCodes.Payment.Isv.MANAGE)" class="basic-info-panel__actions">
<a-button danger @click="handleDelete">{{ $t('payment.channel.wechatManage.delete') }}</a-button>
</div>
</div>

View File

@@ -64,7 +64,7 @@
<div class="card-footer flex shrink-0 items-center justify-end border-t border-border px-3 py-1.5">
<div class="flex items-center">
<a-tooltip
v-if="hasPermission(PermCodes.Channel.WechatApp.MANAGE)"
v-if="hasPermission(PermCodes.Channel.App.MANAGE)"
:title="$t('payment.channel.wechatMchApp.edit')"
>
<a-button
@@ -79,7 +79,7 @@
</a-button>
</a-tooltip>
<a-tooltip
v-if="hasPermission(PermCodes.Channel.WechatApp.VIEW)"
v-if="hasPermission(PermCodes.Channel.App.VIEW)"
:title="$t('payment.channel.wechatMchApp.actionMore')"
>
<a-button

View File

@@ -55,7 +55,7 @@
const editRef = ref<InstanceType<typeof WechatMchAppEdit>>();
const detailRef = ref<InstanceType<typeof WechatMchAppDetail>>();
const canAdd = computed(() => hasPermission(PermCodes.Channel.WechatApp.MANAGE));
const canAdd = computed(() => hasPermission(PermCodes.Channel.App.MANAGE));
const pageTitle = computed(() => {
const base = $t('payment.channel.wechatMchApp.appManageTitle');

View File

@@ -30,7 +30,7 @@
const formState = ref<WechatMchAppAuthConfig>({});
const originalForm = ref<WechatMchAppAuthConfig>({});
const canEdit = computed(() => hasPermission(PermCodes.Channel.WechatApp.MANAGE));
const canEdit = computed(() => hasPermission(PermCodes.Channel.App.MANAGE));
/** AppSecret 提示文案(按应用类型) */
const appSecretTooltip = computed(() => {

View File

@@ -62,7 +62,7 @@
</a-descriptions-item>
</a-descriptions>
<div v-if="hasPermission(PermCodes.Channel.WechatApp.MANAGE)" class="basic-info-panel__actions">
<div v-if="hasPermission(PermCodes.Channel.App.MANAGE)" class="basic-info-panel__actions">
<a-button danger @click="handleDelete">{{ $t('payment.channel.wechatMchApp.delete') }}</a-button>
</div>
</div>

View File

@@ -62,7 +62,7 @@
<div class="card-footer flex shrink-0 items-center justify-end border-t border-border px-3 py-1.5">
<div class="flex items-center">
<a-tooltip
v-if="hasPermission(PermCodes.Channel.WechatApp.MANAGE)"
v-if="hasPermission(PermCodes.Channel.App.MANAGE)"
:title="$t('payment.channel.wechatMchApp.edit')"
>
<a-button
@@ -77,7 +77,7 @@
</a-button>
</a-tooltip>
<a-tooltip
v-if="hasPermission(PermCodes.Channel.WechatApp.VIEW)"
v-if="hasPermission(PermCodes.Channel.App.VIEW)"
:title="$t('payment.channel.wechatMchApp.actionMore')"
>
<a-button

View File

@@ -50,7 +50,7 @@
const editRef = ref<InstanceType<typeof WechatIsvMchAppEdit>>();
const detailRef = ref<InstanceType<typeof WechatIsvMchAppDetail>>();
const canAdd = computed(() => hasPermission(PermCodes.Channel.WechatApp.MANAGE));
const canAdd = computed(() => hasPermission(PermCodes.Channel.App.MANAGE));
const pageTitle = computed(() => {
const base = $t('payment.channel.wechatMchApp.appManageTitleIsv');

View File

@@ -27,7 +27,7 @@
const formState = ref<WechatIsvMchAppAuthConfig>({});
const originalForm = ref<WechatIsvMchAppAuthConfig>({});
const canEdit = computed(() => hasPermission(PermCodes.Channel.WechatApp.MANAGE));
const canEdit = computed(() => hasPermission(PermCodes.Channel.App.MANAGE));
/** AppSecret 提示文案(按应用类型) */
const appSecretTooltip = computed(() => {

View File

@@ -62,7 +62,7 @@
</a-descriptions-item>
</a-descriptions>
<div v-if="hasPermission(PermCodes.Channel.WechatApp.MANAGE)" class="basic-info-panel__actions">
<div v-if="hasPermission(PermCodes.Channel.App.MANAGE)" class="basic-info-panel__actions">
<a-button danger @click="handleDelete">{{ $t('payment.channel.wechatMchApp.delete') }}</a-button>
</div>
</div>

View File

@@ -227,14 +227,14 @@
<a-button @click="emit('update:visible', false)">
{{ $t('common.close') }}
</a-button>
<a-button v-if="hasPermission(PermCodes.Merchant.NotifyConfig.UPDATE)" type="primary" @click="handleEdit">
<a-button v-if="hasPermission(PermCodes.Merchant.NotifyConfig.MANAGE)" type="primary" @click="handleEdit">
{{ $t('common.edit') }}
</a-button>
</template>
<template v-else>
<a-button @click="handleCancel">{{ $t('common.cancelText') }}</a-button>
<a-button
v-if="hasPermission(PermCodes.Merchant.NotifyConfig.UPDATE)"
v-if="hasPermission(PermCodes.Merchant.NotifyConfig.MANAGE)"
type="primary"
:loading="saving"
@click="handleSave"

View File

@@ -248,7 +248,7 @@
<template #extra>
<template v-if="!isEditing">
<a-button v-if="hasPermission(PermCodes.Merchant.Credential.CREDENTIAL_CONFIG_UPDATE)" type="primary" @click="handleEdit">{{
<a-button v-if="hasPermission(PermCodes.Action.MANAGE)" type="primary" @click="handleEdit">{{
$t('common.edit')
}}</a-button>
</template>
@@ -256,7 +256,7 @@
<a-space>
<a-button @click="handleCancel">{{ $t('common.cancelText') }}</a-button>
<a-button
v-if="hasPermission(PermCodes.Merchant.Credential.CREDENTIAL_CONFIG_UPDATE)"
v-if="hasPermission(PermCodes.Action.MANAGE)"
type="primary"
:loading="saving"
@click="handleSave"

View File

@@ -356,8 +356,8 @@
*/
function getActionMenu(row: NormalOrderResult): MenuProps {
const items: { danger?: boolean; key: string; label: string }[] = [];
const canManage = hasPermission(PermCodes.Payment.Order.MANAGE);
const canRefund = hasPermission(PermCodes.Payment.Refund.MANAGE);
const canManage = hasPermission(PermCodes.Trade.Order.MANAGE);
const canRefund = hasPermission(PermCodes.Trade.Refund.MANAGE);
const isTerminal = row.status === 'closed' || row.status === 'expired';
// 退款(已支付 + 退款权限)
if (canRefund && row.status === 'paid') {

View File

@@ -291,7 +291,7 @@
{{ $t('common.view') }}
</a-button>
<a-button
v-if="hasPermission(PermCodes.Payment.Trade.MANAGE)"
v-if="hasPermission(PermCodes.Trade.Fund.MANAGE)"
type="link"
size="small"
:loading="actionLoading"
@@ -300,7 +300,7 @@
{{ $t('payment.order.action.sync') }}
</a-button>
<a-button
v-if="hasPermission(PermCodes.Payment.Trade.MANAGE)"
v-if="hasPermission(PermCodes.Trade.Fund.MANAGE)"
type="link"
size="small"
danger

View File

@@ -242,7 +242,7 @@
{{ $t('common.view') }}
</a-button>
<a-button
v-if="hasPermission(PermCodes.Payment.Refund.MANAGE)"
v-if="hasPermission(PermCodes.Trade.Refund.MANAGE)"
type="link"
size="small"
:loading="actionLoading"

View File

@@ -162,7 +162,7 @@
<!-- 文件名称 -->
<vxe-column field="filename" :title="$t('system.file.platform.field.filename')" :min-width="220">
<template #default="{ row }">
<a v-if="hasPermission(PermCodes.System.FilePlatform.VIEW)" href="javascript:" @click="handleView(row)">{{
<a v-if="hasPermission(PermCodes.System.File.VIEW)" href="javascript:" @click="handleView(row)">{{
row.filename
}}</a>
<span v-else>{{ row.filename }}</span>
@@ -214,11 +214,11 @@
<a-divider type="vertical" />
</template>
<!-- 预览 -->
<a v-if="hasPermission(PermCodes.System.FilePlatform.VIEW)" href="javascript:" @click="handlePreview(row)">{{
<a v-if="hasPermission(PermCodes.System.File.VIEW)" href="javascript:" @click="handlePreview(row)">{{
$t('system.file.platform.action.preview')
}}</a>
<!-- 下载 -->
<a v-if="hasPermission(PermCodes.System.FilePlatform.VIEW)" href="javascript:" @click="handleDownload(row)">{{
<a v-if="hasPermission(PermCodes.System.File.VIEW)" href="javascript:" @click="handleDownload(row)">{{
$t('system.file.platform.action.download')
}}</a>
</a-space>

View File

@@ -123,7 +123,7 @@
{
key: 'kickout',
label: $t('system.monitor.online-user.kickout'),
disabled: !hasPermission(PermCodes.Iam.OnlineUser.KICKOUT),
disabled: !hasPermission(PermCodes.Iam.Online.KICKOUT),
},
],
onClick: ({ key }: { key: string }) => {
@@ -144,7 +144,7 @@
{
key: 'kickout',
label: $t('system.monitor.online-user.batchKickout'),
disabled: selectedRows.value.length === 0 || !hasPermission(PermCodes.Iam.OnlineUser.KICKOUT),
disabled: selectedRows.value.length === 0 || !hasPermission(PermCodes.Iam.Online.KICKOUT),
},
],
onClick: ({ key }: { key: string }) => {
@@ -190,7 +190,7 @@
<vxe-toolbar ref="xToolbar" custom refresh :refresh-options="{ queryMethod: queryPage }">
<template #buttons>
<a-space>
<a-dropdown v-if="hasPermission(PermCodes.Iam.OnlineUser.KICKOUT)" :menu="getBatchActionMenu()">
<a-dropdown v-if="hasPermission(PermCodes.Iam.Online.KICKOUT)" :menu="getBatchActionMenu()">
<a-button>
{{ $t('common.operation') }}
<IconifyIcon icon="ant-design:down-outlined" class="inline" />