完善智能气阀新建归属选择

新建页面明确说明当前归属四选一,选择新归属时自动清空其他归属;字段改用业务名称并补充选择提示,同时扩展专项检查和中文文档。
This commit is contained in:
czl231
2026-08-13 21:50:57 +08:00
parent f8e91fb00a
commit e5289e8f8a
6 changed files with 141 additions and 8 deletions

View File

@@ -10,6 +10,11 @@ const componentUrl = new URL(
import.meta.url,
);
const source = await readFile(fileURLToPath(componentUrl), 'utf8');
const recordPageUrl = new URL(
'../src/views/resource/ResourceRecordPage.vue',
import.meta.url,
);
const recordPageSource = await readFile(fileURLToPath(recordPageUrl), 'utf8');
const requiredFragments = [
'@change-relation="changeRelation"',
'ownershipKeys.includes(field.key)',
@@ -24,4 +29,20 @@ for (const fragment of requiredFragments) {
}
}
console.log('智能气阀归属互斥检查通过:选择时自动清空,提交时保留防御校验。');
const createPageFragments = [
'@change-relation="changeRelation"',
"mode === 'create' && definition.name === 'product_info'",
'当前归属只能选择库房、气站、配送点或用户中的一个;选择新归属时会自动清空其他归属。',
"definition.value.name === 'product_info'",
'productOwnershipKeys.includes(field.key)',
'if (key !== field.key) form[key] = undefined',
'await relationLinkage.change(field, value)',
];
for (const fragment of createPageFragments) {
if (!recordPageSource.includes(fragment)) {
throw new Error(`智能气阀新建页归属互斥检查缺少实现:${fragment}`);
}
}
console.log('智能气阀归属互斥检查通过:新建页与专用弹窗均自动清空,提交时保留防御校验。');

View File

@@ -8,10 +8,10 @@ import { fileURLToPath } from 'node:url';
const resourcesUrl = new URL('../src/api/resources.ts', import.meta.url);
const source = await readFile(fileURLToPath(resourcesUrl), 'utf8');
const ownershipRelations = [
"relation('warehouse_identity', '/product_warehouse', false, { emptyText: '未填写' })",
"relation('gas_basic_identity', '/gas_basic', false, { emptyText: '未填写' })",
"relation('delivery_basic_identity', '/delivery_basic', false, { emptyText: '未填写' })",
"relation('user_account_identity', '/user_account', false, { emptyText: '未填写' })",
"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: '请选择用户' })",
];
for (const relation of ownershipRelations) {

View File

@@ -447,7 +447,7 @@ 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, { emptyText: '未填写' }), relation('gas_basic_identity', '/gas_basic', false, { emptyText: '未填写' }), relation('delivery_basic_identity', '/delivery_basic', false, { emptyText: '未填写' }), relation('user_account_identity', '/user_account', false, { emptyText: '未填写' }), f('produced_at', { required: true })], 'list', [
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 }] })] },
{ 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')] },
]),

View File

@@ -116,6 +116,14 @@
<div class="form-shell">基本信息</div>
</template>
<div class="form-shell form-content">
<a-alert
v-if="mode === 'create' && definition.name === 'product_info'"
class="workflow-alert"
type="warning"
show-icon
>
当前归属只能选择库房气站配送点或用户中的一个选择新归属时会自动清空其他归属
</a-alert>
<a-form :model="form" layout="vertical">
<ResourceFieldForm
v-model="form"
@@ -126,7 +134,7 @@
:relation-loading="relations.loading"
:role-options="roleOptions"
:contract-attachment="contractAttachmentState"
@change-relation="relationLinkage.change"
@change-relation="changeRelation"
@search-relation="relationLinkage.search"
@select-attachment="contractAttachment.select"
@remove-attachment="confirmRemoveContractAttachment"
@@ -188,7 +196,11 @@ import {
recordStatusColor,
recordStatusLabel,
} from '@/api/resource-display';
import { getResource, type DetailAction } from '@/api/resources';
import {
getResource,
type DetailAction,
type ResourceField,
} from '@/api/resources';
import { useUserStore } from '@/store';
import ResourceAccountSummary from './ResourceAccountSummary.vue';
import ResourceActionDialog from './ResourceActionDialog.vue';
@@ -246,6 +258,12 @@ const staffOwnerGuard = useStaffCredentialOwnerGuard({
const resolvedStaffType = staffOwnerGuard.resolvedStaffType;
const relations = staffOwnerGuard.relations;
const relationLinkage = useResourceRelationLinkage(form, relations);
const productOwnershipKeys = [
'warehouse_identity',
'gas_basic_identity',
'delivery_basic_identity',
'user_account_identity',
];
const actionVisible = ref(false);
const activeAction = ref<DetailAction>();
const avatar = useResourceAvatar();
@@ -262,6 +280,22 @@ const contractAttachmentState = computed(() => ({
removed: contractAttachment.removed.value,
}));
/** 新建智能气阀选择归属时清空其他互斥归属,再执行字段原有联动。 */
async function changeRelation(field: ResourceField, value: unknown) {
if (
mode.value === 'create' &&
definition.value.name === 'product_info' &&
productOwnershipKeys.includes(field.key) &&
value != null &&
String(value).trim() !== ''
) {
for (const key of productOwnershipKeys) {
if (key !== field.key) form[key] = undefined;
}
}
await relationLinkage.change(field, value);
}
const accountSummary = computed(() => usesAccountSummary(definition.value));
const accountSummaryVisible = computed(
() =>