CTWing界面

This commit is contained in:
ChenYi 2025-07-30 11:29:39 +08:00
parent c6b8339a02
commit 73c66e6b38
9 changed files with 1898 additions and 2236 deletions

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

@ -281,5 +281,27 @@
"IoTPlatformProductCreateTime": "ProductCreateTime",
"CreationTime": "CreationTime",
"LastModificationTime": "LastModificationTime"
},
"CTWingManagement": {
"AccountName": "AccountName",
"PhoneNumber": "PhoneNumber",
"BelongingAccountName": "BelongingAccountName",
"AccountAccesskey": "AccountAccesskey",
"ProductCount": "ProductCount",
"CTWingAccountId": "CTWingAccountId",
"CTWingProductId": "CTWingProductId",
"IoTPlatformProductId": "IoTPlatformProductId",
"ProductName": "ProductName",
"ProductAccesskey": "ProductAccesskey",
"IsEncrypted": "IsEncrypted",
"BelongingProductName": "Belonging ProductName",
"CommunicationAddress": "Communication Address",
"CommunicationAddressTLS": "TLS Communication Address",
"DeviceThingModelFileName": "DeviceThingModelFileName",
"IoTPlatformProductUpdateTime": "ProductUpdateTime",
"IoTPlatformProductCreateTime": "ProductCreateTime",
"CreationTime": "CreationTime",
"LastModificationTime": "LastModificationTime",
"CannotDeleteAccountWithProducts": "Cannot delete account with products"
}
}

View File

@ -283,5 +283,27 @@
"IoTPlatformProductCreateTime": "平台创建时间",
"CreationTime": "创建时间",
"LastModificationTime": "更新时间"
},
"CTWingManagement": {
"AccountName": "账号名称",
"BelongingAccountName": "所属账号",
"PhoneNumber": "手机号码",
"AccountAccesskey": "账户通信密钥",
"ProductCount": "产品数量",
"CTWingAccountId": "CTWing账户Id",
"CTWingProductId": "CTWing产品Id",
"IoTPlatformProductId": "物联网平台对应的产品Id",
"ProductName": "产品名称",
"ProductAccesskey": "产品密钥",
"IsEncrypted": "是否加密",
"BelongingProductName": "所属产品",
"CommunicationAddress": "通讯地址",
"CommunicationAddressTLS": "TLS通讯地址",
"DeviceThingModelFileName": "物模型文件",
"IoTPlatformProductUpdateTime": "平台更新时间",
"IoTPlatformProductCreateTime": "平台创建时间",
"CreationTime": "创建时间",
"LastModificationTime": "更新时间",
"CannotDeleteAccountWithProducts": "该账号下存在产品,无法删除"
}
}

View File

@ -2,35 +2,33 @@
import type { VbenFormProps } from '#/adapter/form';
import type { VxeGridProps } from '#/adapter/vxe-table';
import { h, ref } from 'vue';
import { ref } from 'vue';
import { useRouter } from 'vue-router';
import { Page, useVbenModal } from '@vben/common-ui';
import { message as Message, Modal, Tag } from 'ant-design-vue';
import { message as Message } from 'ant-design-vue';
import { useVbenForm } from '#/adapter/form';
import { useVbenVxeGrid } from '#/adapter/vxe-table';
import {
postDeviceInfoPage,
postAggregationDeviceDeleteAsync,
postDeviceInfoPage,
postAggregationDeviceCreateAsync,
postCtWingAccountDeleteAsync,
postCtWingAccountListAsync,
postCtWingAccountInsertAsync,
postCtWingAccountModifyAsync,
} from '#/api-client';
import { TableAction } from '#/components/table-action';
import { $t } from '#/locales';
import {
addUserFormSchema,
editUserFormSchemaEdit,
meterTypeOptions,
addAccountFormSchema,
editAccountFormSchemaEdit,
querySchema,
rateOptions,
tableSchema,
} from './schema';
defineOptions({
name: 'AbpUser',
name: 'CTWingAccount',
});
const router = useRouter();
@ -55,7 +53,7 @@ const gridOptions: VxeGridProps<any> = {
proxyConfig: {
ajax: {
query: async ({ page }, formValues) => {
const { data } = await postDeviceInfoPage({
const { data } = await postCtWingAccountListAsync({
body: {
pageIndex: page.currentPage,
pageSize: page.pageSize,
@ -75,7 +73,7 @@ const [UserModal, userModalApi] = useVbenModal({
draggable: true,
onConfirm: submit,
onBeforeClose: () => {
editRow.value = {};
//
return true;
},
});
@ -91,7 +89,7 @@ const [AddForm, addFormApi] = useVbenForm({
},
},
layout: 'horizontal',
schema: addUserFormSchema.value,
schema: addAccountFormSchema.value,
showCollapseButton: false,
showDefaultActions: false,
wrapperClass: 'grid-cols-2',
@ -109,7 +107,7 @@ const [EditForm, editFormApi] = useVbenForm({
},
//
layout: 'horizontal',
schema: editUserFormSchemaEdit.value,
schema: editAccountFormSchemaEdit.value,
showCollapseButton: false,
showDefaultActions: false,
wrapperClass: 'grid-cols-2',
@ -119,8 +117,7 @@ const [EditForm, editFormApi] = useVbenForm({
async function submit() {
const isEdit = !!editRow.value.id;
const formApi = isEdit ? editFormApi : addFormApi;
// TODO: 使
const api = postAggregationDeviceCreateAsync;
const api = isEdit ? postCtWingAccountModifyAsync : postCtWingAccountInsertAsync;
const { valid } = await formApi.validate();
if (!valid) return;
@ -129,11 +126,9 @@ async function submit() {
? {
id: editRow.value.id,
...formValues,
password: formValues.password || '000000',
}
: {
...formValues,
password: formValues.password || '000000',
};
try {
@ -144,6 +139,7 @@ async function submit() {
editRow.value.id ? $t('common.editSuccess') : $t('common.addSuccess'),
);
userModalApi.close();
editRow.value = {};
gridApi.reload();
} else {
Message.error(
@ -161,35 +157,30 @@ async function onEdit(record: any) {
editFormApi.setValues({ ...record });
}
function onDel(row: any) {
Modal.confirm({
title: `${$t('common.confirmDelete')}${row.meterName} ?`,
onOk: async () => {
const result = await postAggregationDeviceDeleteAsync({ body: { id: row.id } });
if (result) {
gridApi.reload();
Message.success($t('common.deleteSuccess'));
} else {
Message.error($t('common.deleteFail'));
}
},
});
}
const toStatusData = (row: Record<string, any>) => {
// 使
router.push({
path: '/iotdb/point',
query: {
DeviceType: row.meterType,
DeviceId: row.meterId,
FocusAddress: row.focusAddress,
},
});
};
const openAddModal = async () => {
editRow.value = {};
userModalApi.open();
};
//
async function onDel(record: any) {
if (record.productCount > 0) {
Message.warning($t('abp.CTWingManagement.CannotDeleteAccountWithProducts'));
return;
}
try {
const resp = await postCtWingAccountDeleteAsync({ body: { id: record.id } });
if (resp.data) {
Message.success($t('common.deleteSuccess'));
gridApi.reload();
} else {
Message.error($t('common.deleteFail'));
}
} catch {
Message.error($t('common.deleteFail'));
}
}
</script>
<template>
@ -209,57 +200,6 @@ const openAddModal = async () => {
/>
</template>
<template #isMeterType="{ row }">
{{ meterTypeOptions[row.meterType - 1]?.label }}
</template>
<template #isSingleRate="{ row }">
{{ rateOptions.find((item) => item.value === row.singleRate)?.label }}
</template>
<template #isArchiveStatus="{ row }">
{{
row.archiveStatus ? $t('common.Issued') : $t('common.Undistributed')
}}
</template>
<template #isTripState="{ row }">
{{ row.tripState ? $t('common.SwitchOff') : $t('common.Closing') }}
</template>
<template #isHaveValve="{ row }">
<component
:is="
h(Tag, { color: row.haveValve ? 'green' : 'red' }, () =>
row.haveValve ? $t('common.yes') : $t('common.no'),
)
"
/>
</template>
<template #isSelfDevelop="{ row }">
<component
:is="
h(Tag, { color: row.selfDevelop ? 'green' : 'red' }, () =>
row.selfDevelop ? $t('common.yes') : $t('common.no'),
)
"
/>
</template>
<template #isDynamicPassword="{ row }">
<component
:is="
h(Tag, { color: row.dynamicPassword ? 'green' : 'red' }, () =>
row.dynamicPassword ? $t('common.yes') : $t('common.no'),
)
"
/>
</template>
<template #isEnable="{ row }">
<component
:is="
h(Tag, { color: row.enabled ? 'green' : 'red' }, () =>
row.enabled ? $t('common.yes') : $t('common.no'),
)
"
/>
</template>
<template #action="{ row }">
<TableAction
:actions="[
@ -277,25 +217,15 @@ const openAddModal = async () => {
icon: 'ant-design:delete-outlined',
type: 'primary',
auth: ['AbpIdentity.Users.Delete'],
disabled: row.productCount > 0,
popConfirm: {
title: $t('common.askConfirmDelete'),
title:
row.productCount > 0
? $t('abp.CTWingManagement.CannotDeleteAccountWithProducts')
: $t('common.askConfirmDelete'),
confirm: onDel.bind(null, row),
},
},
{
label: $t('abp.meters.pointData'),
icon: 'ant-design:profile-outlined',
type: 'primary',
auth: ['AbpIdentity.Users.Delete'],
onClick: toStatusData.bind(null, row),
},
{
label: $t('abp.meters.archivesIssued'),
icon: 'ant-design:cloud-download-outlined',
type: 'primary',
auth: ['AbpIdentity.Users.Delete'],
onClick: archivesIssued.bind(null, row),
},
]"
/>
</template>

View File

@ -9,109 +9,37 @@ import { $t } from '#/locales';
export const querySchema = computed(() => [
{
component: 'Input',
fieldName: 'meterAddress',
label: $t('abp.meters.meterAddress'),
fieldName: 'phoneNumber',
label: $t('abp.CTWingManagement.PhoneNumber'),
},
]);
export const meterTypeOptions = [
{
label: $t('abp.meters.ElectricityMeter'),
value: 1,
},
{
label: $t('abp.meters.waterMeter'),
value: 2,
},
{
label: $t('abp.meters.GasMeter'),
value: 3,
},
{
label: $t('abp.meters.HeatMeter'),
value: 4,
},
{
label: $t('abp.meters.WaterMeterFlowmeter'),
value: 5,
},
{
label: $t('abp.meters.GasMeterFlowmeter'),
value: 6,
},
];
export const rateOptions = [
{
label: $t('abp.meters.MultipleRate'),
value: false,
},
{
label: $t('abp.meters.SingleRate'),
value: true,
},
];
export const tableSchema: any = computed((): VxeGridProps['columns'] => [
{ title: $t('common.seq'), type: 'seq', width: 50 },
{ field: 'meterName', title: $t('abp.meters.meterName'), minWidth: '150' },
{
field: 'meterAddress',
title: $t('abp.meters.meterAddress'),
field: 'ctWingAccountId',
title: $t('abp.CTWingManagement.CTWingAccountId'),
minWidth: '150',
},
{
field: 'meterType',
title: $t('abp.meters.meterType'),
field: 'accountName',
title: $t('abp.CTWingManagement.AccountName'),
minWidth: '150',
slots: { default: 'isMeterType' },
},
{
field: 'dynamicPassword',
title: $t('abp.meters.dynamicPassword'),
field: 'phoneNumber',
title: $t('abp.CTWingManagement.PhoneNumber'),
minWidth: '150',
slots: { default: 'isDynamicPassword' },
},
{
field: 'password',
title: $t('abp.meters.password'),
minWidth: '100',
field: 'accountAccesskey',
title: $t('abp.CTWingManagement.AccountAccesskey'),
minWidth: '150',
},
{
field: 'singleRate',
title: $t('abp.meters.singleRate'),
field: 'productCount',
title: $t('abp.CTWingManagement.ProductCount'),
minWidth: '150',
slots: { default: 'isSingleRate' },
},
{
field: 'selfDevelop',
title: $t('abp.meters.selfDevelop'),
minWidth: '150',
slots: { default: 'isSelfDevelop' },
},
{ field: 'brandType', title: $t('abp.meters.brandType'), minWidth: '150' },
{
field: 'archiveStatus',
title: $t('abp.meters.archiveStatus'),
minWidth: '150',
slots: { default: 'isArchiveStatus' },
},
{
field: 'tripState',
title: $t('abp.meters.tripState'),
minWidth: '150',
slots: { default: 'isTripState' },
},
{ field: 'timesA', title: $t('abp.meters.timesA'), minWidth: '100' },
{ field: 'timev', title: $t('abp.meters.timev'), minWidth: '100' },
{
field: 'haveValve',
title: $t('abp.meters.haveValve'),
minWidth: '150',
slots: { default: 'isHaveValve' },
},
{
field: 'enabled',
title: $t('common.isEnable'),
minWidth: '150',
slots: { default: 'isEnable' },
},
{
title: $t('common.action'),
@ -122,321 +50,80 @@ export const tableSchema: any = computed((): VxeGridProps['columns'] => [
},
]);
export const addUserFormSchema: any = computed(() => [
export const addAccountFormSchema: any = computed(() => [
{
component: 'Input',
fieldName: 'meterName',
label: $t('abp.meters.meterName'),
fieldName: 'ctWingAccountId',
label: $t('abp.CTWingManagement.CTWingAccountId'),
rules: z.string().min(1, {
message: `${$t('common.pleaseInput')}${$t('common.info')}${$t('abp.meters.meterName')}`,
message: `${$t('common.pleaseInput')}${$t('common.info')}${$t('abp.CTWingManagement.CTWingAccountId')}`,
}),
},
{
component: 'Input',
fieldName: 'meterAddress',
label: $t('abp.meters.meterAddress'),
fieldName: 'accountName',
label: $t('abp.CTWingManagement.AccountName'),
rules: z.string().min(1, {
message: `${$t('common.pleaseInput')}${$t('common.info')}${$t('abp.CTWingManagement.AccountName')}`,
}),
},
{
component: 'Input',
fieldName: 'accountAccesskey',
label: $t('abp.CTWingManagement.AccountAccesskey'),
rules: z.string().min(1, {
message: `${$t('common.pleaseInput')}${$t('common.info')}${$t('abp.CTWingManagement.AccountAccesskey')}`,
}),
},
{
component: 'Input',
fieldName: 'phoneNumber',
label: $t('abp.CTWingManagement.PhoneNumber'),
rules: z
.string()
.min(1, {
message: `${$t('common.pleaseInput')}${$t('common.numberType')}${$t('abp.meters.meterAddress')}`,
message: `${$t('common.pleaseInput')}${$t('abp.CTWingManagement.PhoneNumber')}`,
})
.refine((value) => /^\d+$/.test(value), {
message: $t('abp.meters.checkmeterAddress'),
.refine((value) => /^1[3-9]\d{9}$/.test(value), {
message: $t('common.PhoneNumberFormatError'),
}),
},
{
component: 'Select',
componentProps: {
allowClear: true,
options: meterTypeOptions,
placeholder: `${$t('common.pleaseSelect')}${$t('abp.meters.meterType')}`,
},
fieldName: 'meterType',
label: $t('abp.meters.meterType'),
rules: z
.number()
.min(1, {
message: `${$t('common.pleaseSelect')}${$t('abp.meters.meterType')}`,
})
.default(1),
},
{
component: 'Select',
componentProps: {
allowClear: true,
options: rateOptions,
placeholder: `${$t('common.pleaseSelect')}${$t('abp.meters.singleRate')}`,
},
dependencies: {
show(values: any) {
return values.meterType === 1;
},
rules(values: any) {
if (values.meterType === 1) {
return 'required';
}
return null;
},
triggerFields: ['meterType'],
},
fieldName: 'singleRate',
label: $t('abp.meters.singleRate'),
},
{
component: 'Switch',
componentProps: {
class: 'w-auto',
},
fieldName: 'selfDevelop',
label: $t('abp.meters.selfDevelop'),
},
{
component: 'Input',
fieldName: 'brandType',
label: $t('abp.meters.brandType'),
rules: z.string().optional(),
},
{
component: 'Switch',
componentProps: {
class: 'w-auto',
},
fieldName: 'dynamicPassword',
label: $t('abp.meters.dynamicPassword'),
},
{
component: 'Input',
fieldName: 'password',
label: $t('abp.meters.password'),
rules: z.string().optional(),
},
{
component: 'Switch',
componentProps: {
class: 'w-auto',
},
dependencies: {
show(values: any) {
return values.meterType === 2;
},
triggerFields: ['meterType'],
},
fieldName: 'haveValve',
label: $t('abp.meters.haveValve'),
},
{
component: 'Input',
fieldName: 'timesA',
label: $t('abp.meters.timesA'),
componentProps: {
allowClear: true,
placeholder: `${$t('common.pleaseInput')}${$t('abp.meters.timesA')}`,
},
dependencies: {
show(values: any) {
return values.meterType === 1;
},
triggerFields: ['meterType'],
},
rules: z
.string({
message: `${$t('common.pleaseInput')}${$t('abp.meters.timesA')}`,
})
.default('1'),
},
{
component: 'Input',
fieldName: 'timev',
label: $t('abp.meters.timev'),
componentProps: {
allowClear: true,
placeholder: `${$t('common.pleaseInput')}${$t('abp.meters.timev')}`,
},
dependencies: {
show(values: any) {
return values.meterType === 1;
},
triggerFields: ['meterType'],
},
rules: z
.string({
message: `${$t('common.pleaseInput')}${$t('abp.meters.timesA')}`,
})
.default('1'),
},
{
component: 'Input',
fieldName: 'meteringCode',
label: $t('abp.meters.meteringCode'),
componentProps: {
allowClear: true,
placeholder: `${$t('common.pleaseInput')}${$t('abp.meters.meteringCode')}`,
},
rules: z
.string({
message: `${$t('common.pleaseInput')}${$t('abp.meters.meteringCode')}`,
})
.default('1'),
},
]);
export const editUserFormSchemaEdit: any = computed(() => [
export const editAccountFormSchemaEdit: any = computed(() => [
{
component: 'Input',
fieldName: 'meterName',
label: $t('abp.meters.meterName'),
fieldName: 'ctWingAccountId',
label: $t('abp.CTWingManagement.CTWingAccountId'),
disabled: true,
},
{
component: 'Input',
fieldName: 'accountName',
label: $t('abp.CTWingManagement.AccountName'),
rules: z.string().min(1, {
message: `${$t('common.pleaseInput')}${$t('common.info')}${$t('abp.meters.meterName')}`,
message: `${$t('common.pleaseInput')}${$t('common.info')}${$t('abp.CTWingManagement.AccountName')}`,
}),
},
{
component: 'Input',
fieldName: 'meterAddress',
label: $t('abp.meters.meterAddress'),
fieldName: 'accountAccesskey',
label: $t('abp.CTWingManagement.AccountAccesskey'),
rules: z.string().min(1, {
message: `${$t('common.pleaseInput')}${$t('common.info')}${$t('abp.CTWingManagement.AccountAccesskey')}`,
}),
},
{
component: 'Input',
fieldName: 'phoneNumber',
label: $t('abp.CTWingManagement.PhoneNumber'),
rules: z
.string()
.min(1, {
message: `${$t('common.pleaseInput')}${$t('common.numberType')}${$t('abp.meters.meterAddress')}`,
message: `${$t('common.pleaseInput')}${$t('abp.CTWingManagement.PhoneNumber')}`,
})
.refine((value) => /^\d+$/.test(value), {
message: $t('abp.meters.checkmeterAddress'),
.refine((value) => /^1[3-9]\d{9}$/.test(value), {
message: $t('common.PhoneNumberFormatError'),
}),
},
{
component: 'Select',
componentProps: {
allowClear: true,
options: meterTypeOptions,
placeholder: `${$t('common.pleaseSelect')}${$t('abp.meters.meterType')}`,
},
fieldName: 'meterType',
label: $t('abp.meters.meterType'),
rules: z
.number()
.min(1, {
message: `${$t('common.pleaseSelect')}${$t('abp.meters.meterType')}`,
})
.default(1),
},
{
component: 'Select',
componentProps: {
allowClear: true,
options: rateOptions,
placeholder: `${$t('common.pleaseSelect')}${$t('abp.meters.singleRate')}`,
},
dependencies: {
show(values: any) {
return values.meterType === 1;
},
rules(values: any) {
if (values.meterType === 1) {
return 'required';
}
return null;
},
triggerFields: ['meterType'],
},
fieldName: 'singleRate',
label: $t('abp.meters.singleRate'),
},
{
component: 'Switch',
componentProps: {
class: 'w-auto',
},
fieldName: 'selfDevelop',
label: $t('abp.meters.selfDevelop'),
},
{
component: 'Input',
fieldName: 'brandType',
label: $t('abp.meters.brandType'),
rules: z.string().optional(),
},
{
component: 'Switch',
componentProps: {
class: 'w-auto',
},
fieldName: 'dynamicPassword',
label: $t('abp.meters.dynamicPassword'),
},
{
component: 'Input',
fieldName: 'password',
label: $t('abp.meters.password'),
rules: z.string().optional(),
},
{
component: 'Switch',
componentProps: {
class: 'w-auto',
},
dependencies: {
show(values: any) {
return values.meterType === 2;
},
triggerFields: ['meterType'],
},
fieldName: 'haveValve',
label: $t('abp.meters.haveValve'),
},
{
component: 'Input',
fieldName: 'timesA',
label: $t('abp.meters.timesA'),
componentProps: {
allowClear: true,
placeholder: `${$t('common.pleaseInput')}${$t('abp.meters.timesA')}`,
},
dependencies: {
show(values: any) {
return values.meterType === 1;
},
triggerFields: ['meterType'],
},
rules: z
.string({
message: `${$t('common.pleaseInput')}${$t('abp.meters.timesA')}`,
})
.default('1'),
},
{
component: 'Input',
fieldName: 'timev',
label: $t('abp.meters.timev'),
componentProps: {
allowClear: true,
placeholder: `${$t('common.pleaseInput')}${$t('abp.meters.timev')}`,
},
dependencies: {
show(values: any) {
return values.meterType === 1;
},
triggerFields: ['meterType'],
},
rules: z
.string({
message: `${$t('common.pleaseInput')}${$t('abp.meters.timev')}`,
})
.default('1'),
},
{
component: 'Input',
fieldName: 'meteringCode',
label: $t('abp.meters.meteringCode'),
componentProps: {
allowClear: true,
placeholder: `${$t('common.pleaseInput')}${$t('abp.meters.meteringCode')}`,
},
rules: z
.string({
message: `${$t('common.pleaseInput')}${$t('abp.meters.meteringCode')}`,
})
.min(1, {
message: `${$t('common.MustGreaterTthan0')}`,
})
.default('1'),
},
]);

View File

@ -2,35 +2,37 @@
import type { VbenFormProps } from '#/adapter/form';
import type { VxeGridProps } from '#/adapter/vxe-table';
import { h, ref } from 'vue';
import { h, nextTick, ref } from 'vue';
import { useRouter } from 'vue-router';
import { Page, useVbenModal } from '@vben/common-ui';
import { message as Message, Modal, Tag } from 'ant-design-vue';
import { message as Message, Tag } from 'ant-design-vue';
import { useVbenForm } from '#/adapter/form';
import { useVbenVxeGrid } from '#/adapter/vxe-table';
import {
postDeviceInfoPage,
postAggregationDeviceDeleteAsync,
postDeviceInfoPage,
postAggregationDeviceCreateAsync,
postFilesDownload,
postFilesUpload,
postCtWingProductDeleteAsync,
postCtWingProductInsertAsync,
postCtWingProductListAsync,
postCtWingProductModifyAsync,
postCtWingProductProductStatusChangeAsync,
} from '#/api-client';
import { TableAction } from '#/components/table-action';
import { $t } from '#/locales';
import {
addUserFormSchema,
editUserFormSchemaEdit,
meterTypeOptions,
addProductFormSchema,
editProductFormSchemaEdit,
querySchema,
rateOptions,
setFileSelectedCallback,
tableSchema,
} from './schema';
defineOptions({
name: 'AbpUser',
name: 'CTWingProduct',
});
const router = useRouter();
@ -55,7 +57,7 @@ const gridOptions: VxeGridProps<any> = {
proxyConfig: {
ajax: {
query: async ({ page }, formValues) => {
const { data } = await postDeviceInfoPage({
const { data } = await postCtWingProductListAsync({
body: {
pageIndex: page.currentPage,
pageSize: page.pageSize,
@ -71,13 +73,41 @@ const gridOptions: VxeGridProps<any> = {
const [Grid, gridApi] = useVbenVxeGrid({ formOptions, gridOptions });
const editRow: Record<string, any> = ref({});
//
let selectedFile: File | null = null;
//
setFileSelectedCallback((file) => {
selectedFile = file;
});
const [UserModal, userModalApi] = useVbenModal({
draggable: true,
footer: true,
showCancelButton: true,
showConfirmButton: true,
onConfirm: submit,
onBeforeClose: () => {
editRow.value = {};
//
return true;
},
onOpen: () => {
//
selectedFile = null;
},
onOpenChange: (isOpen: boolean) => {
if (isOpen && editRow.value.id) {
//
nextTick(() => {
editFormApi.setValues({ ...editRow.value });
});
}
},
onCancel: () => {
//
selectedFile = null;
//
userModalApi.close();
},
});
const [AddForm, addFormApi] = useVbenForm({
@ -91,7 +121,7 @@ const [AddForm, addFormApi] = useVbenForm({
},
},
layout: 'horizontal',
schema: addUserFormSchema.value,
schema: addProductFormSchema.value,
showCollapseButton: false,
showDefaultActions: false,
wrapperClass: 'grid-cols-2',
@ -109,7 +139,7 @@ const [EditForm, editFormApi] = useVbenForm({
},
//
layout: 'horizontal',
schema: editUserFormSchemaEdit.value,
schema: editProductFormSchemaEdit.value,
showCollapseButton: false,
showDefaultActions: false,
wrapperClass: 'grid-cols-2',
@ -119,31 +149,69 @@ const [EditForm, editFormApi] = useVbenForm({
async function submit() {
const isEdit = !!editRow.value.id;
const formApi = isEdit ? editFormApi : addFormApi;
// TODO: 使
const api = postAggregationDeviceCreateAsync;
const api = isEdit
? postCtWingProductModifyAsync
: postCtWingProductInsertAsync;
const { valid } = await formApi.validate();
if (!valid) return;
const formValues = await formApi.getValues();
//
if (!formValues.deviceThingModelFileName) {
Message.error('请选择设备模型文件');
return;
}
//
if (selectedFile) {
try {
userModalApi.setState({ loading: true, confirmLoading: true });
const result = await postFilesUpload({ body: { files: [selectedFile] } });
if (result.status === 204 || result.status === 200) {
const fileInfo = result.data?.[0];
if (fileInfo && fileInfo.id) {
formValues.deviceThingModelFileId = fileInfo.id;
//
} else {
Message.error('文件上传成功但未获取到文件ID');
userModalApi.setState({ loading: false, confirmLoading: false });
return;
}
} else {
Message.error('文件上传失败');
userModalApi.setState({ loading: false, confirmLoading: false });
return;
}
} catch {
Message.error('文件上传失败');
userModalApi.setState({ loading: false, confirmLoading: false });
return;
}
}
//
selectedFile = null;
//
const fetchParams: any = isEdit
? {
id: editRow.value.id,
...formValues,
password: formValues.password || '000000',
}
: {
...formValues,
password: formValues.password || '000000',
};
try {
userModalApi.setState({ loading: true, confirmLoading: true });
const resp = await api({ body: fetchParams });
if (resp.data) {
Message.success(
editRow.value.id ? $t('common.editSuccess') : $t('common.addSuccess'),
);
userModalApi.close();
editRow.value = {};
gridApi.reload();
} else {
Message.error(
@ -158,47 +226,91 @@ async function submit() {
async function onEdit(record: any) {
editRow.value = record;
userModalApi.open();
editFormApi.setValues({ ...record });
//
selectedFile = null;
}
function onDel(row: any) {
Modal.confirm({
title: `${$t('common.confirmDelete')}${row.meterName} ?`,
onOk: async () => {
const result = await postAggregationDeviceDeleteAsync({ body: { id: row.id } });
if (result) {
gridApi.reload();
Message.success($t('common.deleteSuccess'));
} else {
Message.error($t('common.deleteFail'));
}
},
});
}
const toStatusData = (row: Record<string, any>) => {
// 使
router.push({
path: '/iotdb/point',
query: {
DeviceType: row.meterType,
DeviceId: row.meterId,
FocusAddress: row.focusAddress,
},
});
};
const openAddModal = async () => {
editRow.value = {};
userModalApi.open();
//
selectedFile = null;
};
//
async function onDel(record: any) {
try {
const resp = await postCtWingProductDeleteAsync({
body: { id: record.id },
});
if (resp.data) {
Message.success($t('common.deleteSuccess'));
//
selectedFile = null;
gridApi.reload();
} else {
Message.error($t('common.deleteFail'));
}
} catch {
Message.error($t('common.deleteFail'));
}
}
//
async function onDownloadFile(record: any) {
if (!record.deviceThingModelFileId) {
Message.error('文件ID不存在无法下载');
return;
}
try {
const { data } = await postFilesDownload({
body: { id: record.deviceThingModelFileId },
responseType: 'blob',
});
const url = window.URL.createObjectURL(new Blob([data as Blob]));
const link = document.createElement('a');
link.href = url;
link.setAttribute(
'download',
record.deviceThingModelFileName || 'device-model-file',
);
document.body.append(link);
link.click();
link.remove();
window.URL.revokeObjectURL(url);
Message.success('文件下载成功');
} catch {
Message.error('文件下载失败');
}
}
//
async function onStatusChange(record: any) {
try {
const resp = await postCtWingProductProductStatusChangeAsync({
body: {
id: record.id,
enabled: !record.isEnabled,
},
});
if (resp.data) {
Message.success(record.isEnabled ? '禁用成功' : '启用成功');
gridApi.reload();
} else {
Message.error(record.isEnabled ? '禁用失败' : '启用失败');
}
} catch {
Message.error(record.isEnabled ? '禁用失败' : '启用失败');
}
}
</script>
<template>
<Page auto-content-height>
<Grid>
<template #toolbar-actions>
<TableAction
:actions="[
<TableAction :actions="[
{
label: $t('common.add'),
type: 'primary',
@ -206,64 +318,26 @@ const openAddModal = async () => {
onClick: openAddModal.bind(null),
auth: ['AbpIdentity.Users.Create'],
},
]"
/>
]" />
</template>
<template #isMeterType="{ row }">
{{ meterTypeOptions[row.meterType - 1]?.label }}
</template>
<template #isSingleRate="{ row }">
{{ rateOptions.find((item) => item.value === row.singleRate)?.label }}
</template>
<template #isArchiveStatus="{ row }">
{{
row.archiveStatus ? $t('common.Issued') : $t('common.Undistributed')
}}
</template>
<template #isTripState="{ row }">
{{ row.tripState ? $t('common.SwitchOff') : $t('common.Closing') }}
</template>
<template #isHaveValve="{ row }">
<component
:is="
h(Tag, { color: row.haveValve ? 'green' : 'red' }, () =>
row.haveValve ? $t('common.yes') : $t('common.no'),
)
"
/>
</template>
<template #isSelfDevelop="{ row }">
<component
:is="
h(Tag, { color: row.selfDevelop ? 'green' : 'red' }, () =>
row.selfDevelop ? $t('common.yes') : $t('common.no'),
)
"
/>
</template>
<template #isDynamicPassword="{ row }">
<component
:is="
h(Tag, { color: row.dynamicPassword ? 'green' : 'red' }, () =>
row.dynamicPassword ? $t('common.yes') : $t('common.no'),
)
"
/>
</template>
<template #isEnable="{ row }">
<component
:is="
h(Tag, { color: row.enabled ? 'green' : 'red' }, () =>
row.enabled ? $t('common.yes') : $t('common.no'),
<component :is="h(Tag, { color: row.isEnabled ? 'green' : 'red' }, () =>
row.isEnabled ? $t('common.yes') : $t('common.no'),
)
"
/>
" />
</template>
<template #deviceThingModelFileName="{ row }">
<a v-if="row.deviceThingModelFileName && row.deviceThingModelFileId" @click="onDownloadFile(row)"
style="color: #1890ff; text-decoration: underline; cursor: pointer">
{{ row.deviceThingModelFileName }}
</a>
<span v-else>{{ row.deviceThingModelFileName || '-' }}</span>
</template>
<template #action="{ row }">
<TableAction
:actions="[
<TableAction :actions="[
{
label: $t('common.edit'),
type: 'link',
@ -271,8 +345,18 @@ const openAddModal = async () => {
auth: ['AbpIdentity.Users.Update'],
onClick: onEdit.bind(null, row),
},
]"
:drop-down-actions="[
{
label: row.isEnabled ? '禁用' : '启用',
type: 'link',
danger: row.isEnabled,
size: 'small',
auth: ['AbpIdentity.Users.Update'],
popConfirm: {
title: `确定要${row.isEnabled ? '禁用' : '启用'}该产品吗?`,
confirm: onStatusChange.bind(null, row),
},
},
]" :drop-down-actions="[
{
label: $t('common.delete'),
icon: 'ant-design:delete-outlined',
@ -283,28 +367,10 @@ const openAddModal = async () => {
confirm: onDel.bind(null, row),
},
},
{
label: $t('abp.meters.pointData'),
icon: 'ant-design:profile-outlined',
type: 'primary',
auth: ['AbpIdentity.Users.Delete'],
onClick: toStatusData.bind(null, row),
},
{
label: $t('abp.meters.archivesIssued'),
icon: 'ant-design:cloud-download-outlined',
type: 'primary',
auth: ['AbpIdentity.Users.Delete'],
onClick: archivesIssued.bind(null, row),
},
]"
/>
]" />
</template>
</Grid>
<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" />
</UserModal>
</Page>

View File

@ -1,114 +1,136 @@
import type { VxeGridProps } from '#/adapter/vxe-table';
import { computed } from 'vue';
import { computed, h } from 'vue';
import { z } from '@vben/common-ui';
import { postCtWingAccountListAsync } from '#/api-client';
import { $t } from '#/locales';
export const querySchema = computed(() => [
{
component: 'Input',
fieldName: 'meterAddress',
label: $t('abp.meters.meterAddress'),
fieldName: 'productName',
label: $t('abp.CTWingManagement.ProductName'),
},
]);
export const meterTypeOptions = [
{
label: $t('abp.meters.ElectricityMeter'),
value: 1,
},
{
label: $t('abp.meters.waterMeter'),
value: 2,
},
{
label: $t('abp.meters.GasMeter'),
value: 3,
},
{
label: $t('abp.meters.HeatMeter'),
value: 4,
},
{
label: $t('abp.meters.WaterMeterFlowmeter'),
value: 5,
},
{
label: $t('abp.meters.GasMeterFlowmeter'),
value: 6,
},
];
export const rateOptions = [
{
label: $t('abp.meters.MultipleRate'),
value: false,
},
{
label: $t('abp.meters.SingleRate'),
value: true,
},
];
export const tableSchema: any = computed((): VxeGridProps['columns'] => [
{ title: $t('common.seq'), type: 'seq', width: 50 },
{ field: 'meterName', title: $t('abp.meters.meterName'), minWidth: '150' },
{
field: 'meterAddress',
title: $t('abp.meters.meterAddress'),
field: 'ctWingAccountName',
title: $t('abp.CTWingManagement.BelongingAccountName'),
minWidth: '150',
},
{
field: 'meterType',
title: $t('abp.meters.meterType'),
field: 'ioTPlatformProductId',
title: $t('abp.CTWingManagement.CTWingProductId'),
minWidth: '150',
slots: { default: 'isMeterType' },
},
{
field: 'dynamicPassword',
title: $t('abp.meters.dynamicPassword'),
field: 'productName',
title: $t('abp.CTWingManagement.ProductName'),
minWidth: '150',
slots: { default: 'isDynamicPassword' },
},
{
field: 'password',
title: $t('abp.meters.password'),
minWidth: '100',
},
{
field: 'singleRate',
title: $t('abp.meters.singleRate'),
field: 'productAccesskey',
title: $t('abp.CTWingManagement.ProductAccesskey'),
minWidth: '150',
slots: { default: 'isSingleRate' },
},
{
field: 'selfDevelop',
title: $t('abp.meters.selfDevelop'),
field: 'communicationAddress',
title: $t('abp.CTWingManagement.CommunicationAddress'),
minWidth: '150',
slots: { default: 'isSelfDevelop' },
},
{ field: 'brandType', title: $t('abp.meters.brandType'), minWidth: '150' },
{
field: 'archiveStatus',
title: $t('abp.meters.archiveStatus'),
field: 'communicationAddressTLS',
title: $t('abp.CTWingManagement.CommunicationAddressTLS'),
minWidth: '150',
slots: { default: 'isArchiveStatus' },
},
{
field: 'tripState',
title: $t('abp.meters.tripState'),
field: 'deviceThingModelFileName',
title: $t('abp.CTWingManagement.DeviceThingModelFileName'),
minWidth: '150',
slots: { default: 'isTripState' },
slots: { default: 'deviceThingModelFileName' },
},
{ field: 'timesA', title: $t('abp.meters.timesA'), minWidth: '100' },
{ field: 'timev', title: $t('abp.meters.timev'), minWidth: '100' },
{
field: 'haveValve',
title: $t('abp.meters.haveValve'),
field: 'productCreateTime',
title: $t('abp.CTWingManagement.IoTPlatformProductCreateTime'),
minWidth: '150',
slots: { default: 'isHaveValve' },
formatter: ({ cellValue }: any) => {
if (!cellValue) return '-';
const date = new Date(cellValue);
if (isNaN(date.getTime())) return '-';
return date.toLocaleString('zh-CN', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: false,
}).replace(/\//g, '-');
},
},
{
field: 'enabled',
field: 'productUpdateTime',
title: $t('abp.CTWingManagement.IoTPlatformProductUpdateTime'),
minWidth: '150',
formatter: ({ cellValue }: any) => {
if (!cellValue) return '-';
const date = new Date(cellValue);
if (isNaN(date.getTime())) return '-';
return date.toLocaleString('zh-CN', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: false,
}).replace(/\//g, '-');
},
},
{
field: 'creationTime',
title: $t('abp.CTWingManagement.CreationTime'),
minWidth: '150',
formatter: ({ cellValue }: any) => {
if (!cellValue) return '-';
const date = new Date(cellValue);
if (isNaN(date.getTime())) return '-';
return date.toLocaleString('zh-CN', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: false,
}).replace(/\//g, '-');
},
},
{
field: 'lastModificationTime',
title: $t('abp.CTWingManagement.LastModificationTime'),
minWidth: '150',
formatter: ({ cellValue }: any) => {
if (!cellValue) return '-';
const date = new Date(cellValue);
if (isNaN(date.getTime())) return '-';
return date.toLocaleString('zh-CN', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: false,
}).replace(/\//g, '-');
},
},
{
field: 'isEnabled',
title: $t('common.isEnable'),
minWidth: '150',
slots: { default: 'isEnable' },
@ -117,326 +139,318 @@ export const tableSchema: any = computed((): VxeGridProps['columns'] => [
title: $t('common.action'),
field: 'action',
fixed: 'right',
width: '150',
width: '200',
slots: { default: 'action' },
},
]);
export const addUserFormSchema: any = computed(() => [
{
component: 'Input',
fieldName: 'meterName',
label: $t('abp.meters.meterName'),
rules: z.string().min(1, {
message: `${$t('common.pleaseInput')}${$t('common.info')}${$t('abp.meters.meterName')}`,
}),
},
{
component: 'Input',
fieldName: 'meterAddress',
label: $t('abp.meters.meterAddress'),
rules: z
.string()
.min(1, {
message: `${$t('common.pleaseInput')}${$t('common.numberType')}${$t('abp.meters.meterAddress')}`,
})
.refine((value) => /^\d+$/.test(value), {
message: $t('abp.meters.checkmeterAddress'),
}),
},
{
component: 'Select',
componentProps: {
allowClear: true,
options: meterTypeOptions,
placeholder: `${$t('common.pleaseSelect')}${$t('abp.meters.meterType')}`,
},
fieldName: 'meterType',
label: $t('abp.meters.meterType'),
rules: z
.number()
.min(1, {
message: `${$t('common.pleaseSelect')}${$t('abp.meters.meterType')}`,
})
.default(1),
},
{
component: 'Select',
componentProps: {
allowClear: true,
options: rateOptions,
placeholder: `${$t('common.pleaseSelect')}${$t('abp.meters.singleRate')}`,
},
dependencies: {
show(values: any) {
return values.meterType === 1;
},
rules(values: any) {
if (values.meterType === 1) {
return 'required';
// 全局变量存储选择的文件
export let selectedFile: File | null = null;
// 文件选择回调函数
let _onFileSelected: ((file: File) => void) | null = null;
export function setFileSelectedCallback(callback: (file: File) => void) {
_onFileSelected = callback;
}
return null;
},
triggerFields: ['meterType'],
},
fieldName: 'singleRate',
label: $t('abp.meters.singleRate'),
},
export const addProductFormSchema: any = computed(() => [
{
component: 'Switch',
component: 'ApiSelect',
fieldName: 'ctWingAccountId',
label: $t('abp.CTWingManagement.BelongingAccountName'),
componentProps: {
class: 'w-auto',
api: postCtWingAccountListAsync,
params: {
body: {
pageIndex: 1,
pageSize: 1000,
},
fieldName: 'selfDevelop',
label: $t('abp.meters.selfDevelop'),
},
labelField: 'accountName',
valueField: 'ctWingAccountId',
immediate: true,
afterFetch: (res: any) => {
// 如果是 Axios 响应对象,提取 data
if (res && res.data) {
const data = res.data;
// 确保返回的是数组格式
if (Array.isArray(data)) {
return data;
}
// 如果是包装在 items 中的,提取出来
if (data && Array.isArray(data.items)) {
return data.items;
}
// 如果是包装在 data 中的,提取出来
if (data && Array.isArray(data.data)) {
return data.data;
}
}
// 如果都不是,返回空数组
return [];
},
placeholder: `${$t('common.pleaseSelect')}${$t('abp.CTWingManagement.BelongingAccountName')}`,
},
rules: z.string().min(1, {
message: `${$t('common.pleaseSelect')}${$t('abp.CTWingManagement.BelongingAccountName')}`,
}),
},
{
component: 'Input',
fieldName: 'brandType',
label: $t('abp.meters.brandType'),
rules: z.string().optional(),
},
{
component: 'Switch',
componentProps: {
class: 'w-auto',
},
fieldName: 'dynamicPassword',
label: $t('abp.meters.dynamicPassword'),
fieldName: 'ioTPlatformProductId',
label: $t('abp.CTWingManagement.CTWingProductId'),
rules: z.string().min(1, {
message: `${$t('common.pleaseInput')}${$t('common.info')}${$t('abp.CTWingManagement.CTWingProductId')}`,
}),
},
{
component: 'Input',
fieldName: 'password',
label: $t('abp.meters.password'),
rules: z.string().optional(),
},
{
component: 'Switch',
componentProps: {
class: 'w-auto',
},
dependencies: {
show(values: any) {
return values.meterType === 2;
},
triggerFields: ['meterType'],
},
fieldName: 'haveValve',
label: $t('abp.meters.haveValve'),
fieldName: 'productAccesskey',
label: $t('abp.CTWingManagement.ProductAccesskey'),
rules: z.string().min(1, {
message: `${$t('common.pleaseInput')}${$t('common.info')}${$t('abp.CTWingManagement.ProductAccesskey')}`,
}),
},
{
component: 'Input',
fieldName: 'timesA',
label: $t('abp.meters.timesA'),
componentProps: {
allowClear: true,
placeholder: `${$t('common.pleaseInput')}${$t('abp.meters.timesA')}`,
},
dependencies: {
show(values: any) {
return values.meterType === 1;
},
triggerFields: ['meterType'],
},
rules: z
.string({
message: `${$t('common.pleaseInput')}${$t('abp.meters.timesA')}`,
})
.default('1'),
fieldName: 'communicationAddress',
label: $t('abp.CTWingManagement.CommunicationAddress'),
rules: z.string().min(1, {
message: `${$t('common.pleaseInput')}${$t('common.info')}${$t('abp.CTWingManagement.CommunicationAddress')}`,
}),
},
{
component: 'Input',
fieldName: 'timev',
label: $t('abp.meters.timev'),
componentProps: {
allowClear: true,
placeholder: `${$t('common.pleaseInput')}${$t('abp.meters.timev')}`,
},
dependencies: {
show(values: any) {
return values.meterType === 1;
},
triggerFields: ['meterType'],
},
rules: z
.string({
message: `${$t('common.pleaseInput')}${$t('abp.meters.timesA')}`,
})
.default('1'),
fieldName: 'communicationAddressTLS',
label: $t('abp.CTWingManagement.CommunicationAddressTLS'),
rules: z.string().min(1, {
message: `${$t('common.pleaseInput')}${$t('common.info')}${$t('abp.CTWingManagement.CommunicationAddressTLS')}`,
}),
},
{
component: 'Input',
fieldName: 'meteringCode',
label: $t('abp.meters.meteringCode'),
fieldName: 'deviceThingModelFileName',
label: $t('abp.CTWingManagement.DeviceThingModelFileName'),
componentProps: {
allowClear: true,
placeholder: `${$t('common.pleaseInput')}${$t('abp.meters.meteringCode')}`,
placeholder: '请选择文件',
readonly: true,
addonAfter: h(
'button',
{
type: 'button',
style:
'border: none; background: #1890ff; color: white; padding: 4px 8px; border-radius: 4px; cursor: pointer;',
onClick: () => {
const input = document.createElement('input');
input.type = 'file';
input.accept = '.json,.xlsx,.xls';
input.addEventListener('change', (e: any) => {
const file = e.target.files[0];
if (file) {
// 只显示文件名,不上传
const currentInput = document.querySelector(
'input[placeholder="请选择文件"]',
) as HTMLInputElement;
if (currentInput) {
currentInput.value = file.name;
// 触发change事件
currentInput.dispatchEvent(
new Event('input', { bubbles: true }),
);
currentInput.dispatchEvent(
new Event('change', { bubbles: true }),
);
// 存储文件对象到全局变量,用于后续上传
selectedFile = file;
// 调用回调函数
if (_onFileSelected) {
_onFileSelected(file);
}
}
console.log(
'文件已选择:',
file.name,
'大小:',
file.size,
'字节',
);
}
});
input.click();
},
},
'选择文件',
),
},
rules: z.string().min(1, {
message: `${$t('common.pleaseSelect')}${$t('abp.CTWingManagement.DeviceThingModelFileName')}`,
}),
},
{
component: 'Input',
fieldName: 'deviceThingModelFileId',
label: '',
componentProps: {
type: 'hidden',
},
rules: z
.string({
message: `${$t('common.pleaseInput')}${$t('abp.meters.meteringCode')}`,
})
.default('1'),
},
]);
export const editUserFormSchemaEdit: any = computed(() => [
export const editProductFormSchemaEdit: any = computed(() => [
{
component: 'Input',
fieldName: 'meterName',
label: $t('abp.meters.meterName'),
rules: z.string().min(1, {
message: `${$t('common.pleaseInput')}${$t('common.info')}${$t('abp.meters.meterName')}`,
}),
},
{
component: 'Input',
fieldName: 'meterAddress',
label: $t('abp.meters.meterAddress'),
rules: z
.string()
.min(1, {
message: `${$t('common.pleaseInput')}${$t('common.numberType')}${$t('abp.meters.meterAddress')}`,
})
.refine((value) => /^\d+$/.test(value), {
message: $t('abp.meters.checkmeterAddress'),
}),
},
{
component: 'Select',
component: 'ApiSelect',
fieldName: 'ctWingAccountId',
label: $t('abp.CTWingManagement.BelongingAccountName'),
componentProps: {
allowClear: true,
options: meterTypeOptions,
placeholder: `${$t('common.pleaseSelect')}${$t('abp.meters.meterType')}`,
api: postCtWingAccountListAsync,
params: {
body: {
pageIndex: 1,
pageSize: 1000,
},
fieldName: 'meterType',
label: $t('abp.meters.meterType'),
rules: z
.number()
.min(1, {
message: `${$t('common.pleaseSelect')}${$t('abp.meters.meterType')}`,
})
.default(1),
},
{
component: 'Select',
componentProps: {
allowClear: true,
options: rateOptions,
placeholder: `${$t('common.pleaseSelect')}${$t('abp.meters.singleRate')}`,
},
dependencies: {
show(values: any) {
return values.meterType === 1;
},
rules(values: any) {
if (values.meterType === 1) {
return 'required';
labelField: 'accountName',
valueField: 'ctWingAccountId',
immediate: true,
disabled: true, // 编辑时禁用
afterFetch: (res: any) => {
// 如果是 Axios 响应对象,提取 data
if (res && res.data) {
const data = res.data;
// 确保返回的是数组格式
if (Array.isArray(data)) {
return data;
}
return null;
// 如果是包装在 items 中的,提取出来
if (data && Array.isArray(data.items)) {
return data.items;
}
// 如果是包装在 data 中的,提取出来
if (data && Array.isArray(data.data)) {
return data.data;
}
}
// 如果都不是,返回空数组
return [];
},
triggerFields: ['meterType'],
placeholder: `${$t('common.pleaseSelect')}${$t('abp.CTWingManagement.BelongingAccountName')}`,
},
fieldName: 'singleRate',
label: $t('abp.meters.singleRate'),
},
{
component: 'Switch',
componentProps: {
class: 'w-auto',
},
fieldName: 'selfDevelop',
label: $t('abp.meters.selfDevelop'),
rules: z.string().min(1, {
message: `${$t('common.pleaseSelect')}${$t('abp.CTWingManagement.BelongingAccountName')}`,
}),
},
{
component: 'Input',
fieldName: 'brandType',
label: $t('abp.meters.brandType'),
rules: z.string().optional(),
},
{
component: 'Switch',
fieldName: 'ioTPlatformProductId',
label: $t('abp.CTWingManagement.CTWingProductId'),
disabled: true,
componentProps: {
class: 'w-auto',
readonly: true, // 编辑时只读
},
fieldName: 'dynamicPassword',
label: $t('abp.meters.dynamicPassword'),
rules: z.string().min(1, {
message: `${$t('common.pleaseInput')}${$t('common.info')}${$t('abp.CTWingManagement.CTWingProductId')}`,
}),
},
{
component: 'Input',
fieldName: 'password',
label: $t('abp.meters.password'),
rules: z.string().optional(),
},
{
component: 'Switch',
fieldName: 'productAccesskey',
label: $t('abp.CTWingManagement.ProductAccesskey'),
disabled: true,
componentProps: {
class: 'w-auto',
readonly: true, // 编辑时只读
},
dependencies: {
show(values: any) {
return values.meterType === 2;
},
triggerFields: ['meterType'],
},
fieldName: 'haveValve',
label: $t('abp.meters.haveValve'),
rules: z.string().min(1, {
message: `${$t('common.pleaseInput')}${$t('common.info')}${$t('abp.CTWingManagement.ProductAccesskey')}`,
}),
},
{
component: 'Input',
fieldName: 'timesA',
label: $t('abp.meters.timesA'),
componentProps: {
allowClear: true,
placeholder: `${$t('common.pleaseInput')}${$t('abp.meters.timesA')}`,
},
dependencies: {
show(values: any) {
return values.meterType === 1;
},
triggerFields: ['meterType'],
},
rules: z
.string({
message: `${$t('common.pleaseInput')}${$t('abp.meters.timesA')}`,
})
.default('1'),
fieldName: 'communicationAddress',
label: $t('abp.CTWingManagement.CommunicationAddress'),
rules: z.string().min(1, {
message: `${$t('common.pleaseInput')}${$t('common.info')}${$t('abp.CTWingManagement.CommunicationAddress')}`,
}),
},
{
component: 'Input',
fieldName: 'timev',
label: $t('abp.meters.timev'),
componentProps: {
allowClear: true,
placeholder: `${$t('common.pleaseInput')}${$t('abp.meters.timev')}`,
},
dependencies: {
show(values: any) {
return values.meterType === 1;
},
triggerFields: ['meterType'],
},
rules: z
.string({
message: `${$t('common.pleaseInput')}${$t('abp.meters.timev')}`,
})
.default('1'),
fieldName: 'communicationAddressTLS',
label: $t('abp.CTWingManagement.CommunicationAddressTLS'),
rules: z.string().min(1, {
message: `${$t('common.pleaseInput')}${$t('common.info')}${$t('abp.CTWingManagement.CommunicationAddressTLS')}`,
}),
},
{
component: 'Input',
fieldName: 'meteringCode',
label: $t('abp.meters.meteringCode'),
fieldName: 'deviceThingModelFileName',
label: $t('abp.CTWingManagement.DeviceThingModelFileName'),
componentProps: {
allowClear: true,
placeholder: `${$t('common.pleaseInput')}${$t('abp.meters.meteringCode')}`,
placeholder: '请选择文件',
readonly: true,
addonAfter: h(
'button',
{
type: 'button',
style:
'border: none; background: #1890ff; color: white; padding: 4px 8px; border-radius: 4px; cursor: pointer;',
onClick: () => {
const input = document.createElement('input');
input.type = 'file';
input.accept = '.json,.xlsx,.xls';
input.addEventListener('change', (e: any) => {
const file = e.target.files[0];
if (file) {
// 只显示文件名,不上传
const currentInput = document.querySelector(
'input[placeholder="请选择文件"]',
) as HTMLInputElement;
if (currentInput) {
currentInput.value = file.name;
// 触发change事件
currentInput.dispatchEvent(
new Event('input', { bubbles: true }),
);
currentInput.dispatchEvent(
new Event('change', { bubbles: true }),
);
// 存储文件对象到全局变量,用于后续上传
selectedFile = file;
// 调用回调函数
if (_onFileSelected) {
_onFileSelected(file);
}
}
console.log(
'文件已选择:',
file.name,
'大小:',
file.size,
'字节',
);
}
});
input.click();
},
},
'选择文件',
),
},
rules: z.string().min(1, {
message: `${$t('common.pleaseSelect')}${$t('abp.CTWingManagement.DeviceThingModelFileName')}`,
}),
},
{
component: 'Input',
fieldName: 'deviceThingModelFileId',
label: '',
componentProps: {
type: 'hidden',
},
rules: z
.string({
message: `${$t('common.pleaseInput')}${$t('abp.meters.meteringCode')}`,
})
.min(1, {
message: `${$t('common.MustGreaterTthan0')}`,
})
.default('1'),
},
]);