feat: 标准资源使用独立页面并优化详情布局
This commit is contained in:
@@ -0,0 +1,164 @@
|
||||
<!--
|
||||
功能:承载资源详情页中的审核、流转、归属调整和菜单分配等短业务操作。
|
||||
版本:v1.0.0
|
||||
-->
|
||||
<template>
|
||||
<a-modal
|
||||
:visible="visible"
|
||||
:title="action?.name"
|
||||
:width="680"
|
||||
:ok-loading="submitting"
|
||||
:ok-button-props="{ status: action?.danger ? 'danger' : 'normal' }"
|
||||
@cancel="close"
|
||||
@ok="submit"
|
||||
>
|
||||
<a-alert v-if="action?.danger" class="action-alert" type="error" show-icon>
|
||||
这是高风险操作,可能改变业务状态且无法直接撤销。请确认目标记录和填写内容准确。
|
||||
</a-alert>
|
||||
<a-alert v-if="isOwnershipAction" class="action-alert" type="warning" show-icon>
|
||||
智能气阀只能有一个当前归属。选择新归属前请清空原归属,操作会写入审计记录。
|
||||
</a-alert>
|
||||
<a-form :model="form" layout="vertical">
|
||||
<ResourceFieldForm
|
||||
v-model="form"
|
||||
:fields="action?.fields ?? []"
|
||||
:required-keys="requiredKeys"
|
||||
:relation-options="relations.options"
|
||||
:relation-loading="relations.loading"
|
||||
@search-relation="relations.search"
|
||||
/>
|
||||
</a-form>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { Message } from '@arco-design/web-vue';
|
||||
import { computed, reactive, ref, watch } from 'vue';
|
||||
import { buildResourcePayload, isMissingField } from '@/api/resource-form';
|
||||
import { resourceApi } from '@/api/resource';
|
||||
import { platformApi } from '@/api/platform';
|
||||
import type { DetailAction } from '@/api/resources';
|
||||
import type { ResourceRow } from '@/api/resource-page-rules';
|
||||
import ResourceFieldForm from './ResourceFieldForm.vue';
|
||||
import { useResourceRelations } from './use-resource-relations';
|
||||
|
||||
const props = defineProps<{
|
||||
visible: boolean;
|
||||
action?: DetailAction;
|
||||
identity: string;
|
||||
record: ResourceRow;
|
||||
}>();
|
||||
const emit = defineEmits<{
|
||||
'update:visible': [value: boolean];
|
||||
completed: [];
|
||||
}>();
|
||||
const form = reactive<Record<string, any>>({});
|
||||
const submitting = ref(false);
|
||||
const relations = useResourceRelations();
|
||||
const requiredKeys = computed(() =>
|
||||
(props.action?.fields ?? [])
|
||||
.filter((field) => field.required)
|
||||
.map((field) => field.key),
|
||||
);
|
||||
const isOwnershipAction = computed(
|
||||
() => props.action?.resource === '/product_info/:identity',
|
||||
);
|
||||
const ownershipKeys = [
|
||||
'warehouse_identity',
|
||||
'gas_basic_identity',
|
||||
'delivery_basic_identity',
|
||||
'user_account_identity',
|
||||
];
|
||||
|
||||
watch(
|
||||
() => [props.visible, props.action?.name] as const,
|
||||
async ([visible]) => {
|
||||
if (!visible || !props.action) return;
|
||||
for (const field of props.action.fields ?? []) {
|
||||
form[field.key] = isOwnershipAction.value
|
||||
? props.record[field.key]
|
||||
: undefined;
|
||||
}
|
||||
await relations.preload(props.action.fields ?? []);
|
||||
if (props.action.resource.includes('/menu')) {
|
||||
try {
|
||||
const [menus, assigned] = await Promise.all([
|
||||
platformApi.listMenu(),
|
||||
platformApi.listRoleMenuIdentities(props.identity),
|
||||
]);
|
||||
relations.options['/platform_menu'] = menus.list;
|
||||
form.menu_identities = assigned.menu_identities;
|
||||
} catch (error) {
|
||||
Message.error((error as Error).message);
|
||||
close();
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
function close() {
|
||||
emit('update:visible', false);
|
||||
}
|
||||
|
||||
async function submit() {
|
||||
const action = props.action;
|
||||
if (!action) return;
|
||||
if (
|
||||
(action.fields ?? []).some(
|
||||
(field) => field.required && isMissingField(form[field.key]),
|
||||
)
|
||||
) {
|
||||
Message.warning('请填写必填字段');
|
||||
return;
|
||||
}
|
||||
const invalidPassword = (action.fields ?? []).find(
|
||||
(field) =>
|
||||
field.type === 'password' &&
|
||||
!isMissingField(form[field.key]) &&
|
||||
String(form[field.key]).length < 6,
|
||||
);
|
||||
if (invalidPassword) {
|
||||
Message.warning(`${invalidPassword.label}长度不能少于 6 位`);
|
||||
return;
|
||||
}
|
||||
if (isOwnershipAction.value) {
|
||||
const selected = ownershipKeys.filter((key) => !isMissingField(form[key]));
|
||||
if (selected.length > 1) {
|
||||
Message.warning('智能气阀只能选择一个当前归属');
|
||||
return;
|
||||
}
|
||||
}
|
||||
submitting.value = true;
|
||||
try {
|
||||
const payload = buildResourcePayload(action.fields ?? [], form, 'create');
|
||||
if (isOwnershipAction.value) {
|
||||
for (const key of ownershipKeys) payload[key] = String(form[key] ?? '');
|
||||
}
|
||||
if (action.resource.includes('/menu')) {
|
||||
await platformApi.replaceRoleMenus(
|
||||
props.identity,
|
||||
payload.menu_identities as string[],
|
||||
);
|
||||
} else {
|
||||
await resourceApi.action(
|
||||
action.resource.replace(':identity', props.identity),
|
||||
action.method ?? 'POST',
|
||||
payload,
|
||||
);
|
||||
}
|
||||
Message.success('操作成功');
|
||||
close();
|
||||
emit('completed');
|
||||
} catch (error) {
|
||||
Message.error((error as Error).message);
|
||||
} finally {
|
||||
submitting.value = false;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
.action-alert {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user