Compare commits

..

No commits in common. "288b153e439b6958ba3ddff5f2fb7695c7e4b0ff" and "28479396f9bc8392d59ba01881ba681623483b4f" have entirely different histories.

7 changed files with 216 additions and 2545 deletions

12
.vscode/settings.json vendored
View File

@ -237,15 +237,5 @@
"nolebase", "nolebase",
"rollup", "rollup",
"vitest" "vitest"
], ]
"editor.gotoLocation.alternativeDeclarationCommand": "editor.action.revealDefinition",
"editor.gotoLocation.alternativeDefinitionCommand": "editor.action.revealDefinition",
"editor.gotoLocation.alternativeTypeDefinitionCommand": "editor.action.revealDefinition",
"editor.selectionHighlight": false,
"files.autoSave": "onFocusChange",
"editor.quickSuggestions": {
"other": "on",
"comments": "off",
"strings": "on"
}
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -23,6 +23,8 @@ import {
import { TableAction } from '#/components/table-action'; import { TableAction } from '#/components/table-action';
import { $t } from '#/locales'; import { $t } from '#/locales';
import ThingModelInfoModal from '#/views/thingmodelinfo/ioTPlatformThingModelInfo/index.vue';
import { import {
addProductFormSchema, addProductFormSchema,
editProductFormSchemaEdit, editProductFormSchemaEdit,
@ -76,6 +78,10 @@ const editRow: Record<string, any> = ref({});
// //
let selectedFile: File | null = null; let selectedFile: File | null = null;
//
const thingModelModalVisible = ref(false);
const currentProductInfo = ref<any>({});
// //
setFileSelectedCallback((file) => { setFileSelectedCallback((file) => {
selectedFile = file; selectedFile = file;
@ -324,15 +330,22 @@ function onDeviceManagement(record: any) {
// //
function onThingModelManagement(record: any) { function onThingModelManagement(record: any) {
console.log('物模型管理按钮被点击', record); console.log('物模型管理按钮被点击', record);
// ID //
router.push({ currentProductInfo.value = {
path: '/thingmodelinfo/ioTPlatformThingModelInfo', productId: record.ioTPlatformProductId,
query: {
productId: record.ioTPlatformProductId, // ID
productName: record.productName, productName: record.productName,
ioTPlatform: '2', // OneNET2 ioTPlatform: '2', // OneNET2
}, };
}); console.log('设置产品信息:', currentProductInfo.value);
//
thingModelModalVisible.value = true;
console.log('模态框状态设置为:', thingModelModalVisible.value);
}
//
function closeThingModelModal() {
thingModelModalVisible.value = false;
currentProductInfo.value = {};
} }
</script> </script>
@ -415,5 +428,14 @@ function onThingModelManagement(record: any) {
<UserModal :title="editRow.id ? $t('common.edit') : $t('common.add')" class="w-[800px]"> <UserModal :title="editRow.id ? $t('common.edit') : $t('common.add')" class="w-[800px]">
<component :is="editRow.id ? EditForm : AddForm" /> <component :is="editRow.id ? EditForm : AddForm" />
</UserModal> </UserModal>
<!-- 物模型信息模态框 -->
<ThingModelInfoModal
v-model:visible="thingModelModalVisible"
:product-id="currentProductInfo.productId"
:product-name="currentProductInfo.productName"
:io-t-platform="currentProductInfo.ioTPlatform"
@close="closeThingModelModal"
/>
</Page> </Page>
</template> </template>

View File

@ -2,24 +2,21 @@
import type { VbenFormProps } from '#/adapter/form'; import type { VbenFormProps } from '#/adapter/form';
import type { VxeGridProps } from '#/adapter/vxe-table'; import type { VxeGridProps } from '#/adapter/vxe-table';
import { h, nextTick, onMounted, ref, watch } from 'vue'; import { h, nextTick, ref, watch } from 'vue';
import { useRoute } from 'vue-router';
import { Page, useVbenModal } from '@vben/common-ui'; import { useVbenModal } from '@vben/common-ui';
import { message as Message, Tag } from 'ant-design-vue'; import { message as Message, Modal, Tag } from 'ant-design-vue';
import { useVbenForm } from '#/adapter/form'; import { useVbenForm } from '#/adapter/form';
import { useVbenVxeGrid } from '#/adapter/vxe-table'; import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { import {
postCtWingProductListAsync,
postIoTplatformThingModelInfoCopyAnotherThingModelAsync, postIoTplatformThingModelInfoCopyAnotherThingModelAsync,
postIoTplatformThingModelInfoCopyStandardThingModel, postIoTplatformThingModelInfoCopyStandardThingModel,
postIoTplatformThingModelInfoCreateAsync, postIoTplatformThingModelInfoCreateAsync,
postIoTplatformThingModelInfoDeleteAsync, postIoTplatformThingModelInfoDeleteAsync,
postIoTplatformThingModelInfoPageAsync, postIoTplatformThingModelInfoPageAsync,
postIoTplatformThingModelInfoUpdateAsync, postIoTplatformThingModelInfoUpdateAsync,
postOneNetProductListAsync,
} from '#/api-client'; } from '#/api-client';
import { TableAction } from '#/components/table-action'; import { TableAction } from '#/components/table-action';
import { $t } from '#/locales'; import { $t } from '#/locales';
@ -33,88 +30,32 @@ import {
} from './schema'; } from './schema';
defineOptions({ defineOptions({
name: 'IoTPlatformThingModelInfo', name: 'ThingModelInfoModal',
}); });
const route = useRoute(); const props = withDefaults(defineProps<Props>(), {
visible: false,
productId: '',
productName: '',
ioTPlatform: '2',
});
// // emits
const productId = ref<string>((route.query.productId as string) || ''); const emit = defineEmits<{
const productName = ref<string>((route.query.productName as string) || ''); close: [];
const ioTPlatform = ref<string>((route.query.ioTPlatform as string) || '2'); 'update:visible': [value: boolean];
}>();
// props
interface Props {
visible?: boolean;
productId?: string;
productName?: string;
ioTPlatform?: string;
}
const formOptions: VbenFormProps = { const formOptions: VbenFormProps = {
schema: querySchema.value, 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);
//
const platform = values.ioTPlatform;
if (platform) {
try {
const api = platform === 2 || platform === '2'
? postOneNetProductListAsync
: platform === 1 || platform === '1'
? postCtWingProductListAsync
: null;
if (api) {
const { data } = await api({
body: {
pageIndex: 1,
pageSize: 1000,
},
});
const items = data?.items || [];
const selectedProduct = items.find((item: any) =>
String(item.ioTPlatformProductId) === String(values.ioTPlatformProductId)
);
if (selectedProduct) {
productName.value = selectedProduct.productName || '';
}
}
} catch (error) {
console.error('获取产品名称失败:', error);
}
}
} else {
productId.value = '';
productName.value = '';
}
//
setTimeout(async () => {
if (gridApi && gridApi.reload) {
try {
await gridApi.reload();
} catch (error) {
console.error('重新加载数据时出错:', error);
}
}
}, 100);
}
},
}; };
const gridOptions: VxeGridProps<any> = { const gridOptions: VxeGridProps<any> = {
@ -135,40 +76,20 @@ const gridOptions: VxeGridProps<any> = {
proxyConfig: { proxyConfig: {
ajax: { ajax: {
query: async ({ page }, formValues) => { query: async ({ page }, formValues) => {
// 使使
const currentPlatform = formValues?.ioTPlatform || ioTPlatform.value;
const currentProductId = formValues?.ioTPlatformProductId || productId.value;
// ID
if (!currentProductId || !currentPlatform) {
hasData.value = false;
return {
items: [],
totalCount: 0,
};
}
try {
const { data } = await postIoTplatformThingModelInfoPageAsync({ const { data } = await postIoTplatformThingModelInfoPageAsync({
body: { query: {
input: {
pageIndex: page.currentPage, pageIndex: page.currentPage,
pageSize: page.pageSize, pageSize: page.pageSize,
ioTPlatform: Number.parseInt(String(currentPlatform)) as 1 | 2, ioTPlatform: Number.parseInt(props.ioTPlatform) as 1 | 2,
ioTPlatformProductId: String(currentProductId), ioTPlatformProductId: props.productId,
...(formValues?.SearchKeyWords && { searchKeyWords: formValues.SearchKeyWords }), ...(formValues?.SearchKeyWords && { searchKeyWords: formValues.SearchKeyWords }),
}, },
},
}); });
// //
hasData.value = data?.items && data.items.length > 0; hasData.value = data?.items && data.items.length > 0;
return data || { items: [], totalCount: 0 }; return data;
} catch (error) {
console.error('查询物模型信息失败:', error);
hasData.value = false;
return {
items: [],
totalCount: 0,
};
}
}, },
}, },
}, },
@ -262,84 +183,41 @@ const [CopyForm, copyFormApi] = useVbenForm({
wrapperClass: 'grid-cols-2', wrapperClass: 'grid-cols-2',
}); });
// // props
watch( watch(
() => [route.query.productId, route.query.ioTPlatform], () => [props.visible, props.productId, props.ioTPlatform],
async ([newProductId, newIoTPlatform]) => { async ([visible, productId, ioTPlatform]) => {
if (newProductId) { console.log('物模型模态框props变化:', { visible, productId, ioTPlatform });
productId.value = newProductId as string; console.log('所有props:', props);
} if (visible && productId) {
if (newIoTPlatform) {
ioTPlatform.value = newIoTPlatform as string;
}
if (route.query.productName) {
productName.value = route.query.productName as string;
}
// //
if (gridApi) {
setTimeout(async () => { setTimeout(async () => {
try { try {
//
const filterValues: any = {};
// ioTPlatformProductId API props.productId
// SearchKeyWords
console.log('设置筛选条件:', filterValues);
//
if (Object.keys(filterValues).length > 0) {
await gridApi.formApi.setValues(filterValues);
}
// 使 productId
await gridApi.reload(); await gridApi.reload();
} catch (error) { } catch (error) {
console.error('加载数据时出错:', error); console.error('设置筛选条件时出错:', error);
} }
}, 100); }, 100);
} }
}, },
{ immediate: false }, { immediate: true },
); );
//
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 {
//
if (route.query.ioTPlatform || route.query.productId) {
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() { async function submit() {
// ID
if (!productId.value) {
Message.error('产品ID不存在无法保存物模型信息');
return;
}
const isEdit = !!editRow.value.id; const isEdit = !!editRow.value.id;
const formApi = isEdit ? editFormApi : addFormApi; const formApi = isEdit ? editFormApi : addFormApi;
const api = isEdit const api = isEdit
@ -352,14 +230,14 @@ async function submit() {
const fetchParams: any = { const fetchParams: any = {
...formValues, ...formValues,
// //
ioTPlatform: Number.parseInt(ioTPlatform.value) as 1 | 2, ioTPlatform: Number.parseInt(props.ioTPlatform) as 1 | 2,
ioTPlatformProductId: productId.value, ioTPlatformProductId: props.productId,
// ID // ID
...(isEdit && { id: editRow.value.id }), ...(isEdit && { id: editRow.value.id }),
}; };
try { try {
const resp = await api({ body: fetchParams }); const resp = await api({ query: { input: fetchParams } });
if (resp.data) { if (resp.data) {
Message.success( Message.success(
editRow.value.id ? $t('common.editSuccess') : $t('common.addSuccess'), editRow.value.id ? $t('common.editSuccess') : $t('common.addSuccess'),
@ -392,22 +270,16 @@ const openAddModal = async () => {
// //
const openCopyAnotherThingModelModal = async () => { const openCopyAnotherThingModelModal = async () => {
console.log('打开复制模态框,当前参数:', { console.log('打开复制模态框,当前props:', {
productId: productId.value, productId: props.productId,
productName: productName.value, productName: props.productName,
ioTPlatform: ioTPlatform.value, ioTPlatform: props.ioTPlatform,
}); });
copyModalApi.open(); copyModalApi.open();
}; };
// //
async function submitCopy() { async function submitCopy() {
// ID
if (!productId.value) {
Message.error('产品ID不存在无法复制物模型信息');
return;
}
const { valid } = await copyFormApi.validate(); const { valid } = await copyFormApi.validate();
if (!valid) return; if (!valid) return;
@ -415,20 +287,22 @@ async function submitCopy() {
console.log('复制提交参数:', { console.log('复制提交参数:', {
formValues, formValues,
params: { props: {
productId: productId.value, productId: props.productId,
productName: productName.value, productName: props.productName,
ioTPlatform: ioTPlatform.value, ioTPlatform: props.ioTPlatform,
}, },
}); });
try { try {
const resp = await postIoTplatformThingModelInfoCopyAnotherThingModelAsync({ const resp = await postIoTplatformThingModelInfoCopyAnotherThingModelAsync({
body: { query: {
ioTPlatform: Number.parseInt(ioTPlatform.value) as 1 | 2, input: {
ioTPlatformProductId: productId.value, ioTPlatform: Number.parseInt(props.ioTPlatform) as 1 | 2,
ioTPlatformProductId: props.productId,
sourceProductId: formValues.ioTPlatformProductId, sourceProductId: formValues.ioTPlatformProductId,
}, },
},
}); });
if (resp.data) { if (resp.data) {
@ -448,7 +322,9 @@ async function submitCopy() {
async function onDel(record: any) { async function onDel(record: any) {
try { try {
const resp = await postIoTplatformThingModelInfoDeleteAsync({ const resp = await postIoTplatformThingModelInfoDeleteAsync({
body: { id: record.id }, query: {
input: { id: record.id },
},
}); });
if (resp.data) { if (resp.data) {
Message.success($t('common.deleteSuccess')); Message.success($t('common.deleteSuccess'));
@ -464,17 +340,13 @@ async function onDel(record: any) {
// //
async function copyStandardThingModel() { async function copyStandardThingModel() {
// ID
if (!productId.value) {
Message.error('产品ID不存在无法复制标准模型');
return;
}
try { try {
const resp = await postIoTplatformThingModelInfoCopyStandardThingModel({ const resp = await postIoTplatformThingModelInfoCopyStandardThingModel({
body: { query: {
ioTPlatform: Number.parseInt(ioTPlatform.value) as 1 | 2, input: {
ioTPlatformProductId: productId.value, ioTPlatform: Number.parseInt(props.ioTPlatform) as 1 | 2,
ioTPlatformProductId: props.productId,
},
}, },
}); });
if (resp.data) { if (resp.data) {
@ -488,11 +360,20 @@ async function copyStandardThingModel() {
Message.error('复制标准模型失败'); Message.error('复制标准模型失败');
} }
} }
//
function closeModal() {
emit('update:visible', false);
emit('close');
}
</script> </script>
<template> <template>
<Page auto-content-height> <Modal :open="visible" :title="`${props.ioTPlatform === 1 ? 'CTWing' : 'OneNET'}物模型管理 - ${productName || '产品'}`"
<Grid> width="90%" :footer="null" @cancel="closeModal" @ok="closeModal"
:body-style="{ height: '70vh', overflow: 'hidden' }">
<div style="display: flex; flex-direction: column; height: 100%">
<Grid style="flex: 1; overflow: hidden">
<template #toolbar-actions> <template #toolbar-actions>
<TableAction :actions="[ <TableAction :actions="[
{ {
@ -501,7 +382,6 @@ async function copyStandardThingModel() {
icon: 'ant-design:plus-outlined', icon: 'ant-design:plus-outlined',
onClick: openAddModal.bind(null), onClick: openAddModal.bind(null),
auth: ['AbpIdentity.Users.Create'], auth: ['AbpIdentity.Users.Create'],
disabled: !productId,
}, },
{ {
label: $t('abp.thingModelInfos.copyStandardThingModel'), label: $t('abp.thingModelInfos.copyStandardThingModel'),
@ -509,7 +389,6 @@ async function copyStandardThingModel() {
icon: 'ant-design:copy-outlined', icon: 'ant-design:copy-outlined',
onClick: copyStandardThingModel, onClick: copyStandardThingModel,
auth: ['AbpIdentity.Users.Create'], auth: ['AbpIdentity.Users.Create'],
disabled: !productId,
}, },
{ {
label: $t('abp.thingModelInfos.copyAnotherThingModelModal'), label: $t('abp.thingModelInfos.copyAnotherThingModelModal'),
@ -518,7 +397,6 @@ async function copyStandardThingModel() {
onClick: openCopyAnotherThingModelModal, onClick: openCopyAnotherThingModelModal,
auth: ['AbpIdentity.Users.Create'], auth: ['AbpIdentity.Users.Create'],
ifShow: !hasData, ifShow: !hasData,
disabled: !productId,
}, },
]" /> ]" />
</template> </template>
@ -555,6 +433,7 @@ async function copyStandardThingModel() {
]" /> ]" />
</template> </template>
</Grid> </Grid>
</div>
<ThingModelModal :title="editRow.id ? $t('common.edit') : $t('common.add')" class="w-[800px]"> <ThingModelModal :title="editRow.id ? $t('common.edit') : $t('common.add')" class="w-[800px]">
<component :is="editRow.id ? EditForm : AddForm" /> <component :is="editRow.id ? EditForm : AddForm" />
</ThingModelModal> </ThingModelModal>
@ -563,5 +442,5 @@ async function copyStandardThingModel() {
<CopyModal title="复制已有模型" class="w-[600px]"> <CopyModal title="复制已有模型" class="w-[600px]">
<CopyForm /> <CopyForm />
</CopyModal> </CopyModal>
</Page> </Modal>
</template> </template>

View File

@ -6,95 +6,11 @@ import dayjs from 'dayjs';
import { import {
getCommonGetSelectList, getCommonGetSelectList,
postAggregationIoTplatformGetIoTplatformProductInfoAsync,
postOneNetProductListAsync, postOneNetProductListAsync,
} from '#/api-client'; } from '#/api-client';
import { $t } from '#/locales'; import { $t } from '#/locales';
export const querySchema = computed(() => [ export const querySchema = computed(() => [
{
component: 'ApiSelect',
fieldName: 'ioTPlatform',
label: $t('abp.deviceInfos.ioTPlatform'),
componentProps: {
api: getCommonGetSelectList,
params: {
query: {
typeName: 'IoTPlatformTypeEnum',
},
},
labelField: 'value',
valueField: 'key',
optionsPropName: 'options',
immediate: true,
allowClear: true,
placeholder: `${$t('common.pleaseSelect')}${$t('abp.deviceInfos.ioTPlatform')}`,
afterFetch: (res: any) => {
// 确保返回的是数组格式
if (Array.isArray(res)) {
return res;
}
if (res && Array.isArray(res.items)) {
return res.items;
}
if (res && Array.isArray(res.data)) {
return res.data;
}
return [];
},
},
},
{
component: 'ApiSelect',
fieldName: 'ioTPlatformProductId',
label: $t('common.BelongingProductName'),
dependencies: {
show(values: any) {
return !!values.ioTPlatform;
},
triggerFields: ['ioTPlatform'],
},
componentProps: (formValues: any) => {
const platform = formValues?.ioTPlatform;
return {
api: platform
? postAggregationIoTplatformGetIoTplatformProductInfoAsync
: null,
params: {
body: {
// 聚合服务要求 JSON Body 格式参数
ioTPlatformType:
typeof platform === 'string'
? Number.parseInt(platform)
: platform,
},
},
labelField: 'productName',
valueField: 'ioTPlatformProductId',
optionsPropName: 'options',
immediate: false,
allowClear: true,
placeholder: `${$t('common.pleaseSelect')}${$t('common.BelongingProductName')}`,
afterFetch: (res: any) => {
// 确保返回的是数组格式
if (Array.isArray(res)) {
return res;
}
if (res && Array.isArray(res.items)) {
return res.items;
}
if (res && Array.isArray(res.data)) {
return res.data;
}
if (res && res.data && Array.isArray(res.data.items)) {
return res.data.items;
}
return [];
},
};
},
},
{ {
component: 'Input', component: 'Input',
fieldName: 'SearchKeyWords', fieldName: 'SearchKeyWords',