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

View File

@ -2,24 +2,21 @@
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 { h, nextTick, ref, watch } from 'vue';
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 { useVbenVxeGrid } from '#/adapter/vxe-table';
import {
postCtWingProductListAsync,
postIoTplatformThingModelInfoCopyAnotherThingModelAsync,
postIoTplatformThingModelInfoCopyStandardThingModel,
postIoTplatformThingModelInfoCreateAsync,
postIoTplatformThingModelInfoDeleteAsync,
postIoTplatformThingModelInfoPageAsync,
postIoTplatformThingModelInfoUpdateAsync,
postOneNetProductListAsync,
} from '#/api-client';
import { TableAction } from '#/components/table-action';
import { $t } from '#/locales';
@ -33,88 +30,32 @@ import {
} from './schema';
defineOptions({
name: 'IoTPlatformThingModelInfo',
name: 'ThingModelInfoModal',
});
const route = useRoute();
const props = withDefaults(defineProps<Props>(), {
visible: false,
productId: '',
productName: '',
ioTPlatform: '2',
});
//
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');
// emits
const emit = defineEmits<{
close: [];
'update:visible': [value: boolean];
}>();
// props
interface Props {
visible?: boolean;
productId?: string;
productName?: string;
ioTPlatform?: string;
}
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);
//
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> = {
@ -135,40 +76,20 @@ const gridOptions: VxeGridProps<any> = {
proxyConfig: {
ajax: {
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({
body: {
const { data } = await postIoTplatformThingModelInfoPageAsync({
query: {
input: {
pageIndex: page.currentPage,
pageSize: page.pageSize,
ioTPlatform: Number.parseInt(String(currentPlatform)) as 1 | 2,
ioTPlatformProductId: String(currentProductId),
ioTPlatform: Number.parseInt(props.ioTPlatform) as 1 | 2,
ioTPlatformProductId: props.productId,
...(formValues?.SearchKeyWords && { searchKeyWords: formValues.SearchKeyWords }),
},
});
//
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,
};
}
},
});
//
hasData.value = data?.items && data.items.length > 0;
return data;
},
},
},
@ -262,84 +183,41 @@ const [CopyForm, copyFormApi] = useVbenForm({
wrapperClass: 'grid-cols-2',
});
//
// props
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) {
() => [props.visible, props.productId, props.ioTPlatform],
async ([visible, productId, ioTPlatform]) => {
console.log('物模型模态框props变化:', { visible, productId, ioTPlatform });
console.log('所有props:', props);
if (visible && productId) {
//
setTimeout(async () => {
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();
} catch (error) {
console.error('加载数据时出错:', error);
console.error('设置筛选条件时出错:', error);
}
}, 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() {
// ID
if (!productId.value) {
Message.error('产品ID不存在无法保存物模型信息');
return;
}
const isEdit = !!editRow.value.id;
const formApi = isEdit ? editFormApi : addFormApi;
const api = isEdit
@ -352,14 +230,14 @@ async function submit() {
const fetchParams: any = {
...formValues,
//
ioTPlatform: Number.parseInt(ioTPlatform.value) as 1 | 2,
ioTPlatformProductId: productId.value,
ioTPlatform: Number.parseInt(props.ioTPlatform) as 1 | 2,
ioTPlatformProductId: props.productId,
// ID
...(isEdit && { id: editRow.value.id }),
};
try {
const resp = await api({ body: fetchParams });
const resp = await api({ query: { input: fetchParams } });
if (resp.data) {
Message.success(
editRow.value.id ? $t('common.editSuccess') : $t('common.addSuccess'),
@ -392,22 +270,16 @@ const openAddModal = async () => {
//
const openCopyAnotherThingModelModal = async () => {
console.log('打开复制模态框,当前参数:', {
productId: productId.value,
productName: productName.value,
ioTPlatform: ioTPlatform.value,
console.log('打开复制模态框,当前props:', {
productId: props.productId,
productName: props.productName,
ioTPlatform: props.ioTPlatform,
});
copyModalApi.open();
};
//
async function submitCopy() {
// ID
if (!productId.value) {
Message.error('产品ID不存在无法复制物模型信息');
return;
}
const { valid } = await copyFormApi.validate();
if (!valid) return;
@ -415,19 +287,21 @@ async function submitCopy() {
console.log('复制提交参数:', {
formValues,
params: {
productId: productId.value,
productName: productName.value,
ioTPlatform: ioTPlatform.value,
props: {
productId: props.productId,
productName: props.productName,
ioTPlatform: props.ioTPlatform,
},
});
try {
const resp = await postIoTplatformThingModelInfoCopyAnotherThingModelAsync({
body: {
ioTPlatform: Number.parseInt(ioTPlatform.value) as 1 | 2,
ioTPlatformProductId: productId.value,
sourceProductId: formValues.ioTPlatformProductId,
query: {
input: {
ioTPlatform: Number.parseInt(props.ioTPlatform) as 1 | 2,
ioTPlatformProductId: props.productId,
sourceProductId: formValues.ioTPlatformProductId,
},
},
});
@ -448,7 +322,9 @@ async function submitCopy() {
async function onDel(record: any) {
try {
const resp = await postIoTplatformThingModelInfoDeleteAsync({
body: { id: record.id },
query: {
input: { id: record.id },
},
});
if (resp.data) {
Message.success($t('common.deleteSuccess'));
@ -464,17 +340,13 @@ async function onDel(record: any) {
//
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,
query: {
input: {
ioTPlatform: Number.parseInt(props.ioTPlatform) as 1 | 2,
ioTPlatformProductId: props.productId,
},
},
});
if (resp.data) {
@ -488,73 +360,80 @@ async function copyStandardThingModel() {
Message.error('复制标准模型失败');
}
}
//
function closeModal() {
emit('update:visible', false);
emit('close');
}
</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),
<Modal :open="visible" :title="`${props.ioTPlatform === 1 ? 'CTWing' : 'OneNET'}物模型管理 - ${productName || '产品'}`"
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>
<TableAction :actions="[
{
label: $t('common.add'),
type: 'primary',
icon: 'ant-design:plus-outlined',
onClick: openAddModal.bind(null),
auth: ['AbpIdentity.Users.Create'],
},
},
]" />
</template>
</Grid>
{
label: $t('abp.thingModelInfos.copyStandardThingModel'),
type: 'default',
icon: 'ant-design:copy-outlined',
onClick: copyStandardThingModel,
auth: ['AbpIdentity.Users.Create'],
},
{
label: $t('abp.thingModelInfos.copyAnotherThingModelModal'),
type: 'default',
icon: 'ant-design:copy-outlined',
onClick: openCopyAnotherThingModelModal,
auth: ['AbpIdentity.Users.Create'],
ifShow: !hasData,
},
]" />
</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>
</div>
<ThingModelModal :title="editRow.id ? $t('common.edit') : $t('common.add')" class="w-[800px]">
<component :is="editRow.id ? EditForm : AddForm" />
</ThingModelModal>
@ -563,5 +442,5 @@ async function copyStandardThingModel() {
<CopyModal title="复制已有模型" class="w-[600px]">
<CopyForm />
</CopyModal>
</Page>
</Modal>
</template>

View File

@ -6,95 +6,11 @@ import dayjs from 'dayjs';
import {
getCommonGetSelectList,
postAggregationIoTplatformGetIoTplatformProductInfoAsync,
postOneNetProductListAsync,
} from '#/api-client';
import { $t } from '#/locales';
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',
fieldName: 'SearchKeyWords',