2025-12-22 10:49:46 +08:00

555 lines
15 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.

<script setup lang="ts">
import type { VbenFormProps } from '#/adapter/form';
import type { VxeGridProps } from '#/adapter/vxe-table';
import { h, nextTick, onMounted, ref, watch } from 'vue';
import { useRoute } from 'vue-router';
import { Page, useVbenModal } from '@vben/common-ui';
import { message as Message, Tag } from 'ant-design-vue';
import { useVbenForm } from '#/adapter/form';
import { useVbenVxeGrid } from '#/adapter/vxe-table';
import {
postIoTplatformThingModelInfoCopyAnotherThingModelAsync,
postIoTplatformThingModelInfoCopyStandardThingModel,
postIoTplatformThingModelInfoCreateAsync,
postIoTplatformThingModelInfoDeleteAsync,
postIoTplatformThingModelInfoPageAsync,
postIoTplatformThingModelInfoUpdateAsync,
} from '#/api-client';
import { TableAction } from '#/components/table-action';
import { $t } from '#/locales';
import {
addThingModelFormSchema,
copyThingModelFormSchema,
editThingModelFormSchema,
querySchema,
tableSchema,
} from './schema';
defineOptions({
name: 'IoTPlatformThingModelInfo',
});
const route = useRoute();
// 从路由参数获取产品信息
const productId = ref<string>((route.query.productId as string) || '');
const productName = ref<string>((route.query.productName as string) || '');
const ioTPlatform = ref<string>((route.query.ioTPlatform as string) || '2');
const formOptions: VbenFormProps = {
schema: querySchema.value,
initialValues: {
ioTPlatform: route.query.ioTPlatform ? String(route.query.ioTPlatform) : undefined,
ioTPlatformProductId: route.query.productId ? String(route.query.productId) : undefined,
},
submitOnChange: false,
handleValuesChange: async (values, changedFields) => {
// 当平台类型变化时清空产品ID
if (changedFields.includes('ioTPlatform')) {
if (values.ioTPlatform) {
ioTPlatform.value = String(values.ioTPlatform);
// 清空产品ID因为平台变化了
if (gridApi?.formApi) {
await gridApi.formApi.setValues({
ioTPlatformProductId: undefined,
});
}
productId.value = '';
productName.value = '';
}
}
// 当产品ID变化时更新响应式变量并重新加载数据
if (changedFields.includes('ioTPlatformProductId')) {
if (values.ioTPlatformProductId) {
productId.value = String(values.ioTPlatformProductId);
// 产品名称可以从 ApiSelect 的选项中获取,不需要额外请求
// 如果需要产品名称,可以通过表单字段的选项来获取
} else {
productId.value = '';
productName.value = '';
}
// 延迟重新加载数据,确保表单值已更新
await nextTick();
setTimeout(async () => {
if (gridApi && gridApi.reload) {
try {
// 确保使用最新的表单值进行查询
await gridApi.reload();
} catch (error) {
console.error('重新加载数据时出错:', error);
}
}
}, 100);
}
},
};
const gridOptions: VxeGridProps<any> = {
checkboxConfig: {
highlight: true,
labelField: 'thingModelName',
},
columns: tableSchema.value,
height: 'auto',
keepSource: true,
pagerConfig: {},
toolbarConfig: {
custom: true,
},
customConfig: {
storage: true,
},
proxyConfig: {
ajax: {
query: async ({ page }, formValues) => {
// 总是从表单API获取最新的表单值确保参数完整分页、刷新时formValues可能不完整
const currentFormValues = gridApi?.formApi
? await gridApi.formApi.getValues()
: formValues || {};
// 优先使用从表单API获取的值最新的如果没有则使用传入的formValues
const finalFormValues = { ...(formValues || {}), ...currentFormValues };
const currentPlatform = finalFormValues?.ioTPlatform;
const currentProductId = finalFormValues?.ioTPlatformProductId;
// 即使没有产品ID或平台也触发查询让后端处理参数验证
try {
// 构建查询参数
const queryParams: any = {
pageIndex: page.currentPage,
pageSize: page.pageSize,
};
// 添加搜索关键词
if (finalFormValues?.SearchKeyWords) {
queryParams.searchKeyWords = finalFormValues.SearchKeyWords;
}
// 添加平台参数(必须)
if (currentPlatform) {
queryParams.ioTPlatform = Number.parseInt(String(currentPlatform)) as 1 | 2;
}
// 添加产品ID参数必须
if (currentProductId) {
queryParams.ioTPlatformProductId = String(currentProductId);
}
const { data } = await postIoTplatformThingModelInfoPageAsync({
body: queryParams,
});
// 更新数据状态,检查是否有数据
hasData.value = data?.items && data.items.length > 0;
return data || { items: [], totalCount: 0 };
} catch (error) {
console.error('查询物模型信息失败:', error);
hasData.value = false;
return {
items: [],
totalCount: 0,
};
}
},
},
},
};
const [Grid, gridApi] = useVbenVxeGrid({ formOptions, gridOptions });
const editRow: Record<string, any> = ref({});
// 跟踪数据状态,用于控制按钮显示
const hasData = ref(true);
const [ThingModelModal, thingModelModalApi] = useVbenModal({
draggable: true,
footer: true,
showCancelButton: true,
showConfirmButton: true,
onConfirm: submit,
onBeforeClose: () => {
return true;
},
onOpenChange: (isOpen: boolean) => {
if (isOpen && editRow.value.id) {
// 编辑模式下,模态框打开后设置表单值
nextTick(() => {
editFormApi.setValues({ ...editRow.value });
});
}
},
onCancel: () => {
thingModelModalApi.close();
},
});
const [CopyModal, copyModalApi] = useVbenModal({
draggable: true,
footer: true,
showCancelButton: true,
showConfirmButton: true,
onConfirm: submitCopy,
onBeforeClose: () => {
return true;
},
onCancel: () => {
copyModalApi.close();
},
});
const [AddForm, addFormApi] = useVbenForm({
collapsed: false,
commonConfig: {
labelWidth: 110,
componentProps: {
class: 'w-4/5',
},
},
layout: 'horizontal',
schema: addThingModelFormSchema.value,
showCollapseButton: false,
showDefaultActions: false,
wrapperClass: 'grid-cols-2',
});
const [EditForm, editFormApi] = useVbenForm({
collapsed: false,
commonConfig: {
labelWidth: 110,
componentProps: {
class: 'w-4/5',
},
},
layout: 'horizontal',
schema: editThingModelFormSchema.value,
showCollapseButton: false,
showDefaultActions: false,
wrapperClass: 'grid-cols-2',
});
const [CopyForm, copyFormApi] = useVbenForm({
collapsed: false,
commonConfig: {
labelWidth: 110,
componentProps: {
class: 'w-4/5',
},
},
layout: 'horizontal',
schema: copyThingModelFormSchema.value,
showCollapseButton: false,
showDefaultActions: false,
wrapperClass: 'grid-cols-2',
});
// 监听路由参数变化,自动加载数据
watch(
() => [route.query.productId, route.query.ioTPlatform],
async ([newProductId, newIoTPlatform]) => {
if (newProductId) {
productId.value = newProductId as string;
}
if (newIoTPlatform) {
ioTPlatform.value = newIoTPlatform as string;
}
if (route.query.productName) {
productName.value = route.query.productName as string;
}
// 延迟执行,确保组件完全初始化
if (gridApi) {
setTimeout(async () => {
try {
await gridApi.reload();
} catch (error) {
console.error('加载数据时出错:', error);
}
}, 100);
}
},
{ immediate: false },
);
// 页面初始化时加载数据
onMounted(async () => {
// 从路由参数初始化
if (route.query.productId) {
productId.value = route.query.productId as string;
}
if (route.query.productName) {
productName.value = route.query.productName as string;
}
if (route.query.ioTPlatform) {
ioTPlatform.value = route.query.ioTPlatform as string;
}
// 延迟加载数据,确保表格已初始化
// 即使没有 productId也要触发一次查询让表格显示空白状态
await nextTick();
setTimeout(async () => {
if (gridApi && gridApi.reload) {
try {
// 设置表单值(如果有路由参数)
const formValues = await gridApi.formApi.getValues();
if (route.query.ioTPlatform && !formValues.ioTPlatform) {
await gridApi.formApi.setValues({
ioTPlatform: route.query.ioTPlatform,
});
}
if (route.query.productId && !formValues.ioTPlatformProductId) {
await gridApi.formApi.setValues({
ioTPlatformProductId: route.query.productId,
});
}
await nextTick();
// 无论是否有参数,都触发查询
await gridApi.reload();
} catch (error) {
console.error('初始化加载数据时出错:', error);
}
}
}, 300);
});
// 新增和编辑提交的逻辑
async function submit() {
// 检查是否有产品ID
if (!productId.value) {
Message.error('产品ID不存在无法保存物模型信息');
return;
}
const isEdit = !!editRow.value.id;
const formApi = isEdit ? editFormApi : addFormApi;
const api = isEdit
? postIoTplatformThingModelInfoUpdateAsync
: postIoTplatformThingModelInfoCreateAsync;
const { valid } = await formApi.validate();
if (!valid) return;
const formValues = await formApi.getValues();
const fetchParams: any = {
...formValues,
// 自动添加平台和产品信息
ioTPlatform: Number.parseInt(ioTPlatform.value) as 1 | 2,
ioTPlatformProductId: productId.value,
// 编辑时需要添加ID
...(isEdit && { id: editRow.value.id }),
};
try {
const resp = await api({ body: fetchParams });
if (resp.data) {
Message.success(
editRow.value.id ? $t('common.editSuccess') : $t('common.addSuccess'),
);
thingModelModalApi.close();
editRow.value = {};
gridApi.reload();
} else {
Message.error(
editRow.value.id ? $t('common.editFail') : $t('common.addFail'),
);
}
} catch (error) {
console.error('提交失败:', error);
Message.error(
editRow.value.id ? $t('common.editFail') : $t('common.addFail'),
);
}
}
async function onEdit(record: any) {
editRow.value = record;
thingModelModalApi.open();
}
const openAddModal = async () => {
editRow.value = {};
thingModelModalApi.open();
};
// 打开复制已有模型模态框
const openCopyAnotherThingModelModal = async () => {
console.log('打开复制模态框,当前参数:', {
productId: productId.value,
productName: productName.value,
ioTPlatform: ioTPlatform.value,
});
copyModalApi.open();
};
// 复制提交逻辑
async function submitCopy() {
// 检查是否有产品ID
if (!productId.value) {
Message.error('产品ID不存在无法复制物模型信息');
return;
}
const { valid } = await copyFormApi.validate();
if (!valid) return;
const formValues = await copyFormApi.getValues();
console.log('复制提交参数:', {
formValues,
params: {
productId: productId.value,
productName: productName.value,
ioTPlatform: ioTPlatform.value,
},
});
try {
const resp = await postIoTplatformThingModelInfoCopyAnotherThingModelAsync({
body: {
ioTPlatform: Number.parseInt(ioTPlatform.value) as 1 | 2,
ioTPlatformProductId: productId.value,
sourceProductId: formValues.ioTPlatformProductId,
},
});
if (resp.data) {
Message.success('复制模型成功');
copyModalApi.close();
gridApi.reload();
} else {
Message.error('复制模型失败');
}
} catch (error) {
console.error('复制模型失败:', error);
Message.error('复制模型失败');
}
}
// 删除函数
async function onDel(record: any) {
try {
const resp = await postIoTplatformThingModelInfoDeleteAsync({
body: { id: record.id },
});
if (resp.data) {
Message.success($t('common.deleteSuccess'));
gridApi.reload();
} else {
Message.error($t('common.deleteFail'));
}
} catch (error) {
console.error('删除失败:', error);
Message.error($t('common.deleteFail'));
}
}
// 复制标准模型函数
async function copyStandardThingModel() {
// 检查是否有产品ID
if (!productId.value) {
Message.error('产品ID不存在无法复制标准模型');
return;
}
try {
const resp = await postIoTplatformThingModelInfoCopyStandardThingModel({
body: {
ioTPlatform: Number.parseInt(ioTPlatform.value) as 1 | 2,
ioTPlatformProductId: productId.value,
},
});
if (resp.data) {
Message.success('复制标准模型成功');
gridApi.reload();
} else {
Message.error('复制标准模型失败');
}
} catch (error) {
console.error('复制标准模型失败:', error);
Message.error('复制标准模型失败');
}
}
</script>
<template>
<Page auto-content-height>
<Grid>
<template #toolbar-actions>
<TableAction :actions="[
{
label: $t('common.add'),
type: 'primary',
icon: 'ant-design:plus-outlined',
onClick: openAddModal.bind(null),
auth: ['AbpIdentity.Users.Create'],
disabled: !productId,
},
{
label: $t('abp.thingModelInfos.copyStandardThingModel'),
type: 'default',
icon: 'ant-design:copy-outlined',
onClick: copyStandardThingModel,
auth: ['AbpIdentity.Users.Create'],
disabled: !productId,
},
{
label: $t('abp.thingModelInfos.copyAnotherThingModelModal'),
type: 'default',
icon: 'ant-design:copy-outlined',
onClick: openCopyAnotherThingModelModal,
auth: ['AbpIdentity.Users.Create'],
ifShow: !hasData,
disabled: !productId,
},
]" />
</template>
<template #isValueNeedConvert="{ row }">
<component :is="h(
Tag,
{ color: row.isValueNeedConvert ? 'blue' : 'default' },
() => (row.isValueNeedConvert ? '是' : '否'),
)
" />
</template>
<template #action="{ row }">
<TableAction :actions="[
{
label: $t('common.edit'),
type: 'link',
size: 'small',
auth: ['AbpIdentity.Users.Update'],
onClick: onEdit.bind(null, row),
},
{
label: $t('common.delete'),
icon: 'ant-design:delete-outlined',
type: 'link',
size: 'small',
auth: ['AbpIdentity.Users.Delete'],
popConfirm: {
title: $t('common.askConfirmDelete'),
confirm: onDel.bind(null, row),
},
},
]" />
</template>
</Grid>
<ThingModelModal :title="editRow.id ? $t('common.edit') : $t('common.add')" class="w-[800px]">
<component :is="editRow.id ? EditForm : AddForm" />
</ThingModelModal>
<!-- 复制已有模型模态框 -->
<CopyModal title="复制已有模型" class="w-[600px]">
<CopyForm />
</CopyModal>
</Page>
</template>