完善报价单填表与币种回填,并补齐账号末次登录、角色按钮权限与陆运全线匹配。
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
/**
|
||||
* 角色管理:对接 Jeecg /sys/role 与菜单权限树。
|
||||
* 数据权限用线路标签写入角色 description,避免伪造第二套 RBAC。
|
||||
* 数据权限按 Excel 线路目录树勾选,写入角色 description 的 [dataPerms:…],不另造 RBAC。
|
||||
*/
|
||||
import { computed, onMounted, reactive, ref } from "vue";
|
||||
import { message, Modal } from "ant-design-vue";
|
||||
@@ -15,6 +15,14 @@ import {
|
||||
saveRolePermission,
|
||||
type RoleRow,
|
||||
} from "/@/views/inquiry/role/role.api";
|
||||
import {
|
||||
DATA_PERM_TREE,
|
||||
SYSTEM_EXCEPTION_NOTIFY_KEY,
|
||||
SYSTEM_EXCEPTION_NOTIFY_TITLE,
|
||||
dataPermTitle,
|
||||
leafDataPermKeys,
|
||||
normalizeDataPermKeys,
|
||||
} from "/@/views/inquiry/shared/dataPermCatalog";
|
||||
import ProtoIcon from "/@/views/inquiry/components/ProtoIcon.vue";
|
||||
import AdminModal from "/@/views/inquiry/components/AdminModal.vue";
|
||||
|
||||
@@ -30,19 +38,12 @@ const form = reactive({
|
||||
status: "active" as RoleRow["status"],
|
||||
checkedKeys: [] as string[],
|
||||
dataPerms: [] as string[],
|
||||
/** 旧后台独立项:系统异常消息通知 */
|
||||
systemExceptionNotify: false,
|
||||
});
|
||||
|
||||
const dataOptions = [
|
||||
"空运·全部线路",
|
||||
"空运·CGO-KUL",
|
||||
"空运·HKG-KUL",
|
||||
"海运·全部线路",
|
||||
"海运·海运全线",
|
||||
"陆运·全部线路",
|
||||
"陆运·中港/中亚/中欧",
|
||||
"陆运·东南亚",
|
||||
"系统异常·消息通知",
|
||||
];
|
||||
const dataPermTree = DATA_PERM_TREE;
|
||||
const systemExceptionNotifyTitle = SYSTEM_EXCEPTION_NOTIFY_TITLE;
|
||||
|
||||
const modalTitle = computed(() => (editing.value ? "编辑角色" : "新增角色"));
|
||||
const modalOkText = computed(() => "保存");
|
||||
@@ -68,15 +69,29 @@ function parseDataPerms(desc: string | undefined): string[] {
|
||||
if (!desc) return [];
|
||||
const m = desc.match(/\[dataPerms:(.+?)\]/);
|
||||
if (!m) return [];
|
||||
return m[1]
|
||||
.split("|")
|
||||
.map((s) => s.trim())
|
||||
.filter(Boolean);
|
||||
return normalizeDataPermKeys(
|
||||
m[1]
|
||||
.split("|")
|
||||
.map((s) => s.trim())
|
||||
.filter(Boolean),
|
||||
);
|
||||
}
|
||||
|
||||
function buildDescription(dataPerms: string[]) {
|
||||
if (!dataPerms.length) return "";
|
||||
return `[dataPerms:${dataPerms.join("|")}]`;
|
||||
function buildDescription(dataPerms: string[], systemExceptionNotify: boolean) {
|
||||
const keys = leafDataPermKeys(dataPerms);
|
||||
if (systemExceptionNotify && !keys.includes(SYSTEM_EXCEPTION_NOTIFY_KEY)) {
|
||||
keys.push(SYSTEM_EXCEPTION_NOTIFY_KEY);
|
||||
}
|
||||
if (!keys.length) return "";
|
||||
return `[dataPerms:${keys.join("|")}]`;
|
||||
}
|
||||
|
||||
function displayDataPerms(keys: string[]): string[] {
|
||||
return keys.map((k) => dataPermTitle(k));
|
||||
}
|
||||
|
||||
function routeDataPermsOnly(keys: string[]): string[] {
|
||||
return keys.filter((k) => k !== SYSTEM_EXCEPTION_NOTIFY_KEY);
|
||||
}
|
||||
|
||||
async function loadMenuTree() {
|
||||
@@ -143,18 +158,21 @@ function openCreate() {
|
||||
status: "active",
|
||||
checkedKeys: [],
|
||||
dataPerms: [],
|
||||
systemExceptionNotify: false,
|
||||
});
|
||||
modalOpen.value = true;
|
||||
}
|
||||
|
||||
async function openEdit(row: RoleRow) {
|
||||
editing.value = row;
|
||||
const allPerms = [...row.dataPerms];
|
||||
Object.assign(form, {
|
||||
name: row.name,
|
||||
roleCode: row.roleCode,
|
||||
status: row.status,
|
||||
checkedKeys: [] as string[],
|
||||
dataPerms: [...row.dataPerms],
|
||||
dataPerms: routeDataPermsOnly(allPerms),
|
||||
systemExceptionNotify: allPerms.includes(SYSTEM_EXCEPTION_NOTIFY_KEY),
|
||||
});
|
||||
try {
|
||||
const perms: any = await queryRolePermission({ roleId: row.id });
|
||||
@@ -179,7 +197,7 @@ async function save() {
|
||||
id: editing.value?.id,
|
||||
roleName: form.name.trim(),
|
||||
roleCode,
|
||||
description: buildDescription(form.dataPerms),
|
||||
description: buildDescription(form.dataPerms, form.systemExceptionNotify),
|
||||
},
|
||||
Boolean(editing.value),
|
||||
);
|
||||
@@ -214,6 +232,12 @@ function removeRole(row: RoleRow) {
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/** a-tree 可能回传对象或数组;统一成叶子 key 列表 */
|
||||
function onDataPermCheck(checked: string[] | { checked: string[] }) {
|
||||
const keys = Array.isArray(checked) ? checked : checked?.checked || [];
|
||||
form.dataPerms = leafDataPermKeys(keys.map(String));
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -252,7 +276,7 @@ function removeRole(row: RoleRow) {
|
||||
</td>
|
||||
<td>
|
||||
<div class="role-perm-summary">
|
||||
<span v-for="d in row.dataPerms" :key="d" class="tag">{{ d }}</span>
|
||||
<span v-for="d in displayDataPerms(row.dataPerms)" :key="d" class="tag">{{ d }}</span>
|
||||
<span v-if="!row.dataPerms.length" style="color: #94a3b8">—</span>
|
||||
</div>
|
||||
</td>
|
||||
@@ -306,14 +330,20 @@ function removeRole(row: RoleRow) {
|
||||
|
||||
<div class="admin-modal-field">
|
||||
<label class="admin-modal-label">数据权限</label>
|
||||
<a-select
|
||||
v-model:value="form.dataPerms"
|
||||
mode="multiple"
|
||||
style="width: 100%"
|
||||
:options="dataOptions.map((d) => ({ value: d, label: d }))"
|
||||
placeholder="选择线路 / 通知范围"
|
||||
:max-tag-count="3"
|
||||
/>
|
||||
<div class="perm-tree-box">
|
||||
<a-tree
|
||||
:checkedKeys="form.dataPerms"
|
||||
checkable
|
||||
default-expand-all
|
||||
:tree-data="dataPermTree"
|
||||
:field-names="{ title: 'title', key: 'key', children: 'children' }"
|
||||
@check="onDataPermCheck"
|
||||
/>
|
||||
</div>
|
||||
<label class="notify-check">
|
||||
<input v-model="form.systemExceptionNotify" type="checkbox" />
|
||||
{{ systemExceptionNotifyTitle }}
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="admin-modal-field">
|
||||
@@ -340,4 +370,14 @@ function removeRole(row: RoleRow) {
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.notify-check {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin-top: 10px;
|
||||
font-size: 13px;
|
||||
color: #0f172a;
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user