Files
platforms/frontend/platform_admin/src/views/resource/ResourceActionDialog.vue
czl231 74c5e34275 修复工作人员资质关联与角色过滤
按安装、配送、运维菜单显式过滤工作人员,锁定资质所有者并使用姓名和角色回显。

扩展工作人员状态与多角色查询,补充权限校验、回归测试、操作日志和项目文档。
2026-08-11 19:15:53 +08:00

170 lines
5.0 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!--
功能承载资源详情页中的审核流转归属调整和菜单分配等短业务操作
版本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="searchRelation"
/>
</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, ResourceField } 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',
];
/** 业务动作字段不启用记录页联动,只沿用普通关联搜索。 */
function searchRelation(field: ResourceField, keyword: string) {
relations.searchField(field, keyword);
}
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>