优化智能气阀状态中文展示
列表和详情统一显示中文状态,状态弹窗区分当前状态与目标状态并排除原状态,同时保留服务端业务校验,补充专项检查和中文文档。
This commit is contained in:
@@ -24,6 +24,7 @@
|
||||
"user-address-display:check": "node scripts/check-user-address-relation-display.mjs",
|
||||
"product-ownership:check": "node scripts/check-product-ownership-action.mjs",
|
||||
"product-ownership-display:check": "node scripts/check-product-ownership-display.mjs",
|
||||
"product-lifecycle-display:check": "node scripts/check-product-lifecycle-display.mjs",
|
||||
"resource-search:check": "node scripts/check-resource-search.mjs",
|
||||
"audit:platform": "node scripts/check-backend-contract.mjs",
|
||||
"lint": "biome lint .",
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* 功能:检查智能气阀状态的中文展示和目标状态选择规则。
|
||||
* 版本:v1.0.0
|
||||
*/
|
||||
import { readFile } from 'node:fs/promises';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
const resources = await readFile(
|
||||
fileURLToPath(new URL('../src/api/resources.ts', import.meta.url)),
|
||||
'utf8',
|
||||
);
|
||||
const dialog = await readFile(
|
||||
fileURLToPath(
|
||||
new URL('../src/views/resource/ResourceActionDialog.vue', import.meta.url),
|
||||
),
|
||||
'utf8',
|
||||
);
|
||||
const rules = await readFile(
|
||||
fileURLToPath(new URL('../src/api/resource-page-rules.ts', import.meta.url)),
|
||||
'utf8',
|
||||
);
|
||||
|
||||
const checks = [
|
||||
[resources, "f('product_status', { type: 'select', options: productStatusOptions"],
|
||||
[resources, "label: '目标状态'"],
|
||||
[resources, "placeholder: '请选择目标状态'"],
|
||||
[rules, "createHiddenKeys: ['product_status']"],
|
||||
[dialog, '当前状态:{{ currentProductStatusLabel }}'],
|
||||
[dialog, "option.value) !== String(props.record.product_status)"],
|
||||
[dialog, ':fields="actionFields"'],
|
||||
];
|
||||
|
||||
for (const [source, fragment] of checks) {
|
||||
if (!source.includes(fragment)) {
|
||||
throw new Error(`智能气阀状态展示检查缺少实现:${fragment}`);
|
||||
}
|
||||
}
|
||||
|
||||
console.log('智能气阀状态展示检查通过:中文展示当前状态,目标选项排除原状态。');
|
||||
@@ -94,6 +94,7 @@ const pageRules: Record<string, ResourcePageRule> = {
|
||||
editKeys: ['code', 'name', 'address', 'manager', 'phone'],
|
||||
},
|
||||
product_info: {
|
||||
createHiddenKeys: ['product_status'],
|
||||
editKeys: [
|
||||
'name',
|
||||
'producer_account_identity',
|
||||
|
||||
@@ -385,6 +385,14 @@ function define(
|
||||
}
|
||||
|
||||
const reason = [f('reason', { required: true })];
|
||||
const productStatusOptions = [
|
||||
{ label: '待处理', value: 10 },
|
||||
{ label: '在库', value: 28 },
|
||||
{ label: '运输中', value: 29 },
|
||||
{ label: '使用中', value: 30 },
|
||||
{ label: '维修中', value: 31 },
|
||||
{ label: '已报废', value: 27 },
|
||||
];
|
||||
|
||||
export const resources: 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' },
|
||||
@@ -447,8 +455,8 @@ export const resources: ResourceUiDefinition[] = [
|
||||
define('producer_account', '生产商管理', 'writable', [f('producer_code', { required: true }), f('name', { required: true }), f('credit_code'), f('principal'), f('phone'), f('address', { emptyText: '未填写', placeholder: '请输入地址' }), f('username', { required: true }), f('password', { required: true }), f('display_name'), producerAdminRole(), f('remark')]),
|
||||
define('product_type', '智能气阀类型', 'editable', [f('code', { required: true }), f('name', { required: true })]),
|
||||
define('product_warehouse', '智能气阀库房', 'editable', [f('code', { required: true }), f('name', { required: true }), f('address', { emptyText: '未填写', placeholder: '请输入地址' }), f('manager'), f('phone')]),
|
||||
define('product_info', '智能气阀', 'editable', [f('code', { required: true }), f('name', { required: true }), relation('producer_account_identity', '/producer_account', true, { label: '生产商', listLabel: '生产商', listRelationNameOnly: true, displayRelationLabel: true, showIdentityCopy: true, emptyText: '未填写', placeholder: '请选择生产商' }), relation('product_type_identity', '/product_type', true, { label: '智能气阀类型', listLabel: '智能气阀类型', listRelationNameOnly: true, displayRelationLabel: true, showIdentityCopy: true, emptyText: '未填写', placeholder: '请选择智能气阀类型' }), f('params', { required: true }), relation('warehouse_identity', '/product_warehouse', false, { label: '库房', emptyText: '未填写', placeholder: '请选择库房' }), relation('gas_basic_identity', '/gas_basic', false, { label: '气站', emptyText: '未填写', placeholder: '请选择气站' }), relation('delivery_basic_identity', '/delivery_basic', false, { label: '配送点', emptyText: '未填写', placeholder: '请选择配送点' }), relation('user_account_identity', '/user_account', false, { label: '用户', emptyText: '未填写', placeholder: '请选择用户' }), f('produced_at', { required: true })], 'list', [
|
||||
{ name: '修改智能气阀状态', resource: '/product_info/:identity/lifecycle', method: 'PATCH', fields: [f('product_status', { required: true, type: 'select', options: [{ label: '待处理', value: 10 }, { label: '在库', value: 28 }, { label: '运输中', value: 29 }, { label: '使用中', value: 30 }, { label: '维修中', value: 31 }, { label: '已报废', value: 27 }] })] },
|
||||
define('product_info', '智能气阀', 'editable', [f('code', { required: true }), f('name', { required: true }), f('product_status', { type: 'select', options: productStatusOptions, unknownValueLabel: '未知状态' }), relation('producer_account_identity', '/producer_account', true, { label: '生产商', listLabel: '生产商', listRelationNameOnly: true, displayRelationLabel: true, showIdentityCopy: true, emptyText: '未填写', placeholder: '请选择生产商' }), relation('product_type_identity', '/product_type', true, { label: '智能气阀类型', listLabel: '智能气阀类型', listRelationNameOnly: true, displayRelationLabel: true, showIdentityCopy: true, emptyText: '未填写', placeholder: '请选择智能气阀类型' }), f('params', { required: true }), relation('warehouse_identity', '/product_warehouse', false, { label: '库房', emptyText: '未填写', placeholder: '请选择库房' }), relation('gas_basic_identity', '/gas_basic', false, { label: '气站', emptyText: '未填写', placeholder: '请选择气站' }), relation('delivery_basic_identity', '/delivery_basic', false, { label: '配送点', emptyText: '未填写', placeholder: '请选择配送点' }), relation('user_account_identity', '/user_account', false, { label: '用户', emptyText: '未填写', placeholder: '请选择用户' }), f('produced_at', { required: true })], 'list', [
|
||||
{ name: '修改智能气阀状态', resource: '/product_info/:identity/lifecycle', method: 'PATCH', fields: [f('product_status', { label: '目标状态', required: true, type: 'select', options: productStatusOptions, placeholder: '请选择目标状态' })] },
|
||||
{ name: '变更智能气阀归属', resource: '/product_info/:identity', method: 'PUT', fields: [relation('warehouse_identity', '/product_warehouse'), relation('gas_basic_identity', '/gas_basic'), relation('delivery_basic_identity', '/delivery_basic'), relation('user_account_identity', '/user_account'), f('action', { required: true, type: 'select', options: [{ label: '入库', value: 'warehouse' }, { label: '分配', value: 'assigned' }, { label: '归还', value: 'returned' }, { label: '人工调整', value: 'manual' }] }), f('reason', { required: true }), f('remark')] },
|
||||
]),
|
||||
define('product_repair', '智能气阀检修记录', 'editable', [relation('product_info_identity', '/product_info', true), f('repair_no', { required: true }), f('repair_type', { required: true }), f('started_at', { required: true }), f('completed_at'), f('result', { type: 'select', options: resourceSearchEnumOptions('product_repair', 'result') }), f('target_product_status', { type: 'select', options: [{ label: '在库', value: 28 }, { label: '运输中', value: 29 }, { label: '使用中', value: 30 }, { label: '报废', value: 27 }] }), f('content'), f('operator'), f('remark')]),
|
||||
|
||||
@@ -18,10 +18,13 @@
|
||||
<a-alert v-if="isOwnershipAction" class="action-alert" type="warning" show-icon>
|
||||
智能气阀只能有一个当前归属。选择新归属后会自动清空其他归属,操作会写入审计记录。
|
||||
</a-alert>
|
||||
<a-alert v-if="isProductLifecycleAction" class="action-alert" type="info" show-icon>
|
||||
当前状态:{{ currentProductStatusLabel }}。请选择一个不同的目标状态,服务端会校验检修和订单占用情况。
|
||||
</a-alert>
|
||||
<a-form :model="form" layout="vertical">
|
||||
<ResourceFieldForm
|
||||
v-model="form"
|
||||
:fields="action?.fields ?? []"
|
||||
:fields="actionFields"
|
||||
:required-keys="requiredKeys"
|
||||
:relation-options="relations.options"
|
||||
:relation-loading="relations.loading"
|
||||
@@ -56,14 +59,39 @@ const emit = defineEmits<{
|
||||
const form = reactive<Record<string, any>>({});
|
||||
const submitting = ref(false);
|
||||
const relations = useResourceRelations();
|
||||
const isProductLifecycleAction = computed(
|
||||
() => props.action?.resource === '/product_info/:identity/lifecycle',
|
||||
);
|
||||
const actionFields = computed(() =>
|
||||
(props.action?.fields ?? []).map((field) =>
|
||||
isProductLifecycleAction.value && field.key === 'product_status'
|
||||
? {
|
||||
...field,
|
||||
options: (field.options ?? []).filter(
|
||||
(option) => String(option.value) !== String(props.record.product_status),
|
||||
),
|
||||
}
|
||||
: field,
|
||||
),
|
||||
);
|
||||
const requiredKeys = computed(() =>
|
||||
(props.action?.fields ?? [])
|
||||
actionFields.value
|
||||
.filter((field) => field.required)
|
||||
.map((field) => field.key),
|
||||
);
|
||||
const isOwnershipAction = computed(
|
||||
() => props.action?.resource === '/product_info/:identity',
|
||||
);
|
||||
const currentProductStatusLabel = computed(() => {
|
||||
const statusField = props.action?.fields?.find(
|
||||
(field) => field.key === 'product_status',
|
||||
);
|
||||
return (
|
||||
statusField?.options?.find(
|
||||
(option) => String(option.value) === String(props.record.product_status),
|
||||
)?.label ?? `未知状态(${String(props.record.product_status ?? '')})`
|
||||
);
|
||||
});
|
||||
const ownershipKeys = [
|
||||
'warehouse_identity',
|
||||
'gas_basic_identity',
|
||||
@@ -95,12 +123,12 @@ watch(
|
||||
() => [props.visible, props.action?.name] as const,
|
||||
async ([visible]) => {
|
||||
if (!visible || !props.action) return;
|
||||
for (const field of props.action.fields ?? []) {
|
||||
for (const field of actionFields.value) {
|
||||
form[field.key] = isOwnershipAction.value
|
||||
? props.record[field.key]
|
||||
: undefined;
|
||||
}
|
||||
await relations.preload(props.action.fields ?? []);
|
||||
await relations.preload(actionFields.value);
|
||||
if (props.action.resource.includes('/menu')) {
|
||||
try {
|
||||
const [menus, assigned] = await Promise.all([
|
||||
@@ -125,14 +153,14 @@ async function submit() {
|
||||
const action = props.action;
|
||||
if (!action) return;
|
||||
if (
|
||||
(action.fields ?? []).some(
|
||||
actionFields.value.some(
|
||||
(field) => field.required && isMissingField(form[field.key]),
|
||||
)
|
||||
) {
|
||||
Message.warning('请填写必填字段');
|
||||
return;
|
||||
}
|
||||
const invalidPassword = (action.fields ?? []).find(
|
||||
const invalidPassword = actionFields.value.find(
|
||||
(field) =>
|
||||
field.type === 'password' &&
|
||||
!isMissingField(form[field.key]) &&
|
||||
@@ -151,7 +179,7 @@ async function submit() {
|
||||
}
|
||||
submitting.value = true;
|
||||
try {
|
||||
const payload = buildResourcePayload(action.fields ?? [], form, 'create');
|
||||
const payload = buildResourcePayload(actionFields.value, form, 'create');
|
||||
if (isOwnershipAction.value) {
|
||||
for (const key of ownershipKeys) payload[key] = String(form[key] ?? '');
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user