feat: 统一账户角色展示并优化资源页面
This commit is contained in:
@@ -33,7 +33,7 @@ export type PlatformMenu = { identity: string; parent_identity?: string; group_c
|
||||
export const platformApi = {
|
||||
overview: () => request<DashboardOverview>('/dashboard/overview'),
|
||||
listAccount: () => request<{ total: number; list: Record<string, unknown>[] }>('/platform_account'),
|
||||
listRole: () => resourceApi.list<PlatformRole>('/platform_role'),
|
||||
listRole: () => resourceApi.list<PlatformRole>('/platform_role', 1, 100),
|
||||
createRole: (data: Record<string, unknown>) => resourceApi.create<PlatformRole>('/platform_role', data),
|
||||
listMenu: () => request<{ total: number; list: PlatformMenu[] }>('/gas_menu'),
|
||||
listRoleMenuIdentities: (identity: string) =>
|
||||
|
||||
@@ -25,6 +25,9 @@ export type ResourceField = {
|
||||
required?: boolean;
|
||||
relation?: string;
|
||||
options?: Array<{ label: string; value: string | number }>;
|
||||
defaultValue?: string | number | boolean;
|
||||
readonly?: boolean;
|
||||
unknownValueLabel?: string;
|
||||
};
|
||||
|
||||
export type DetailAction = {
|
||||
@@ -63,7 +66,7 @@ const fieldLabels: Record<string, string> = {
|
||||
username: '用户名',
|
||||
password: '密码',
|
||||
display_name: '显示名称',
|
||||
role_code: '角色编码',
|
||||
role_code: '角色',
|
||||
platform_role_code: '平台角色',
|
||||
credit_code: '统一社会信用代码',
|
||||
principal: '负责人',
|
||||
@@ -272,6 +275,18 @@ function relation(key: string, resource: string, required = false): ResourceFiel
|
||||
return f(key, { type: 'identity', relation: resource, required });
|
||||
}
|
||||
|
||||
/** 创建固定管理员角色字段,确保页面仅展示后端支持的角色。 */
|
||||
function fixedAdminRole(label: string): ResourceField {
|
||||
return f('role_code', {
|
||||
type: 'select',
|
||||
required: true,
|
||||
options: [{ label, value: 'admin' }],
|
||||
defaultValue: 'admin',
|
||||
readonly: true,
|
||||
unknownValueLabel: '未知角色',
|
||||
});
|
||||
}
|
||||
|
||||
function define(
|
||||
name: string,
|
||||
title: string,
|
||||
@@ -310,9 +325,9 @@ const reason = [f('reason', { required: true })];
|
||||
|
||||
const platformResources: ResourceUiDefinition[] = [
|
||||
{ ...define('gas_basic', '气站管理', 'writable', [f('code', { required: true }), f('name', { required: true }), f('credit_code'), f('principal'), f('address'), f('longitude'), f('latitude')]), accountManagement: { resource: '/gas_account', relationKey: 'gas_basic_identity', title: '气站账户' }, walletOwnerType: 'gas' },
|
||||
define('gas_account', '气站账户', 'writable', [f('username', { required: true }), f('password', { required: true }), f('display_name'), f('role_code'), relation('gas_basic_identity', '/gas_basic', true)]),
|
||||
define('gas_account', '气站账户', 'writable', [f('username', { required: true }), f('password', { required: true }), f('display_name'), fixedAdminRole('气站管理员'), relation('gas_basic_identity', '/gas_basic', true)]),
|
||||
{ ...define('delivery_basic', '配送点管理', 'writable', [f('delivery_code', { required: true }), f('name', { required: true }), relation('gas_basic_identity', '/gas_basic'), f('principal'), f('address')]), accountManagement: { resource: '/delivery_account', relationKey: 'delivery_basic_identity', title: '配送点账户' }, walletOwnerType: 'delivery' },
|
||||
define('delivery_account', '配送站账户', 'writable', [f('username', { required: true }), f('password', { required: true }), f('display_name'), f('role_code'), relation('delivery_basic_identity', '/delivery_basic', true)]),
|
||||
define('delivery_account', '配送点账户', 'writable', [f('username', { required: true }), f('password', { required: true }), f('display_name'), fixedAdminRole('配送点管理员'), relation('delivery_basic_identity', '/delivery_basic', true)]),
|
||||
{ ...define('staff_account', '工作人员', 'writable', [f('username', { required: true }), f('password', { required: true }), f('name', { required: true }), f('phone'), f('avatar'), f('role_code', { required: true, type: 'select', options: [{ label: '安装人员', value: 'installer' }, { label: '配送人员', value: 'delivery' }, { label: '运维人员', value: 'operations' }] }), relation('gas_basic_identity', '/gas_basic'), relation('delivery_basic_identity', '/delivery_basic'), f('work_status', { type: 'select', options: [{ label: '在岗', value: 'on_duty' }, { label: '离岗', value: 'off_duty' }] })]), walletOwnerType: 'staff' },
|
||||
define('staff_credential', '工作人员资质', 'writable', [relation('staff_account_identity', '/staff_account', true), f('credential_type', { required: true }), f('credential_no'), f('expired_at')]),
|
||||
{ ...define('user_account', '用户账户', 'writable', [f('username', { required: true }), f('password', { required: true }), f('name', { required: true }), f('phone'), f('avatar'), f('real_name')]), walletOwnerType: 'user' },
|
||||
@@ -409,7 +424,7 @@ const platformResources: ResourceUiDefinition[] = [
|
||||
|
||||
const gasOverrides: ResourceUiDefinition[] = [
|
||||
{ ...define('delivery_basic', '配送点管理', 'writable', [f('delivery_code', { required: true }), f('name', { required: true }), f('principal'), f('address')]), accountManagement: { resource: '/delivery_account', relationKey: 'delivery_basic_identity', title: '配送点账户' } },
|
||||
define('delivery_account', '配送点账户', 'writable', [f('username', { required: true }), f('password', { required: true }), f('display_name')], 'list', [
|
||||
define('delivery_account', '配送点账户', 'writable', [f('username', { required: true }), f('password', { required: true }), f('display_name'), fixedAdminRole('配送点管理员')], 'list', [
|
||||
{ name: '重置密码', resource: '/delivery_account/:identity/password', method: 'PUT', fields: [f('password', { required: true })] },
|
||||
]),
|
||||
define('staff_account', '工作人员', 'writable', [f('username', { required: true }), f('password', { required: true }), f('name', { required: true }), f('phone'), f('avatar'), f('role_code', { required: true, type: 'select', options: [{ label: '安装人员', value: 'installer' }, { label: '配送人员', value: 'delivery' }, { label: '运维人员', value: 'operations' }] }), relation('delivery_basic_identity', '/delivery_basic'), f('work_status', { type: 'select', options: [{ label: '在岗', value: 'on_duty' }, { label: '离岗', value: 'off_duty' }] })], 'list', [
|
||||
|
||||
@@ -102,7 +102,9 @@
|
||||
<a-table-column title="唯一标识" :width="150"><template #cell="{ record }"><IdentityText :value="String(record.identity)" /></template></a-table-column>
|
||||
<a-table-column title="用户名" data-index="username" :width="130" ellipsis tooltip />
|
||||
<a-table-column title="显示名称" data-index="display_name" :width="130" ellipsis tooltip />
|
||||
<a-table-column title="角色编码" data-index="role_code" :width="100" ellipsis tooltip />
|
||||
<a-table-column title="角色" :width="130" ellipsis tooltip>
|
||||
<template #cell="{ record }">{{ accountRoleLabel(definition.accountManagement?.resource, record.role_code) }}</template>
|
||||
</a-table-column>
|
||||
<a-table-column title="状态" :width="90">
|
||||
<template #cell="{ record }">
|
||||
<a-tag :color="Number(record.status) === 1 ? 'green' : 'red'">
|
||||
@@ -151,8 +153,8 @@
|
||||
<a-form-item label="显示名称">
|
||||
<a-input v-model="accountForm.display_name" />
|
||||
</a-form-item>
|
||||
<a-form-item label="角色编码">
|
||||
<a-input v-model="accountForm.role_code" />
|
||||
<a-form-item label="角色">
|
||||
<a-input :model-value="accountRoleLabel(definition.accountManagement?.resource, accountForm.role_code || 'admin')" disabled />
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
@@ -166,8 +168,8 @@
|
||||
<a-date-picker v-else-if="field.type === 'datetime'" v-model="form[field.key]" show-time value-format="YYYY-MM-DDTHH:mm:ssZ" />
|
||||
<a-textarea v-else-if="field.type === 'textarea'" v-model="form[field.key]" :auto-size="{ minRows: 3, maxRows: 8 }" />
|
||||
<a-input-password v-else-if="field.type === 'password'" v-model="form[field.key]" />
|
||||
<a-select v-else-if="field.type === 'select'" v-model="form[field.key]" allow-clear>
|
||||
<a-option v-for="option in field.options" :key="option.value" :value="option.value">{{ option.label }}</a-option>
|
||||
<a-select v-else-if="field.type === 'select'" v-model="form[field.key]" :disabled="field.readonly" allow-clear>
|
||||
<a-option v-for="option in selectFieldOptions(field)" :key="option.value" :value="option.value">{{ option.label }}</a-option>
|
||||
</a-select>
|
||||
<a-select v-else-if="field.type === 'identity' || field.type === 'identity-list'" v-model="form[field.key]" :multiple="field.type === 'identity-list'" allow-clear allow-search :loading="relationLoading[field.relation ?? '']" @search="(value: string) => searchRelation(field.relation, value)">
|
||||
<a-option v-for="option in relationOptions[field.relation ?? ''] ?? []" :key="String(option.identity)" :value="String(option.identity)">
|
||||
@@ -437,7 +439,7 @@ function resetForm(data?: Row) {
|
||||
const value = data?.[field.key];
|
||||
form[field.key] =
|
||||
value == null
|
||||
? undefined
|
||||
? field.defaultValue
|
||||
: field.type === 'money'
|
||||
? Number(value) / 100
|
||||
: value;
|
||||
@@ -655,7 +657,6 @@ async function saveAccount() {
|
||||
try {
|
||||
const payload: Record<string, unknown> = {
|
||||
display_name: String(accountForm.display_name ?? '').trim(),
|
||||
role_code: String(accountForm.role_code ?? '').trim(),
|
||||
[management.relationKey]: ownerIdentity,
|
||||
};
|
||||
if (!accountEditingIdentity.value) {
|
||||
@@ -1010,6 +1011,8 @@ function displayFieldValue(field: ResourceField, row: Row) {
|
||||
if (field.options) {
|
||||
const option = field.options.find((item) => item.value === value);
|
||||
if (option) return option.label;
|
||||
if (field.unknownValueLabel && value != null && value !== '')
|
||||
return `${field.unknownValueLabel}(${String(value)})`;
|
||||
}
|
||||
if (
|
||||
(field.type === 'identity' || field.type === 'identity-list') &&
|
||||
@@ -1021,6 +1024,8 @@ function displayFieldValue(field: ResourceField, row: Row) {
|
||||
|
||||
function displayValue(key: string, value: unknown) {
|
||||
if (value == null || value === '') return '-';
|
||||
if (key === 'role_code')
|
||||
return accountRoleLabel(props.definition.resource, value);
|
||||
if (typeof value === 'boolean') return value ? '是' : '否';
|
||||
if (
|
||||
key === 'amount' ||
|
||||
@@ -1045,6 +1050,40 @@ function displayValue(key: string, value: unknown) {
|
||||
return String(value);
|
||||
}
|
||||
|
||||
/** 将各管理端稳定角色编码转换为中文名称,未知编码保留审计线索。 */
|
||||
function accountRoleLabel(resource: string | undefined, value: unknown) {
|
||||
const code = String(value ?? '');
|
||||
const labels: Record<string, Record<string, string>> = {
|
||||
'/gas_account': { admin: '气站管理员' },
|
||||
'/delivery_account': { admin: '配送点管理员' },
|
||||
'/staff_account': {
|
||||
installer: '安装人员',
|
||||
delivery: '配送人员',
|
||||
operations: '运维人员',
|
||||
},
|
||||
};
|
||||
const label = labels[resource ?? '']?.[code];
|
||||
return label ?? (code ? `未知角色(${code})` : '-');
|
||||
}
|
||||
|
||||
/** 给只读角色下拉补充历史未知值,避免直接暴露裸编码。 */
|
||||
function selectFieldOptions(field: ResourceField) {
|
||||
const options = [...(field.options ?? [])];
|
||||
const value = form[field.key];
|
||||
if (
|
||||
field.unknownValueLabel &&
|
||||
value != null &&
|
||||
value !== '' &&
|
||||
!options.some((option) => String(option.value) === String(value))
|
||||
) {
|
||||
options.push({
|
||||
label: `${field.unknownValueLabel}(${String(value)})`,
|
||||
value,
|
||||
});
|
||||
}
|
||||
return options;
|
||||
}
|
||||
|
||||
async function loadRelation(resource: string, keyword = '') {
|
||||
relationLoading[resource] = true;
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user