Commit 06e498d544c28b192d9fc8d44a493a1543b55e8d

Authored by gesilong
1 parent 33f0225a

commit: 设备台账联调;相关组件开发

  1 +import {defHttp} from "/@/utils/http/axios";
  2 +import {omit} from "lodash-es";
  3 +
  4 +/**
  5 + * 列表
  6 + */
  7 +
  8 +export const getLedgerList = (params) => {
  9 + const { page, pageSize } = params;
  10 + const otherParams = omit(params, ['page', 'pageSize']);
  11 + return defHttp.post<any>({
  12 + url: `/da/pageData?page=${page}&pageSize=${pageSize}`,
  13 + params: otherParams,
  14 + });
  15 +};
  16 +
  17 +
  18 +/**
  19 +*组织
  20 +*/
  21 +export const getOrgList = () => {
  22 + return defHttp.get<any>({
  23 + url: `/organization/me/list`,
  24 + });
  25 +};
  26 +
  27 +/**
  28 +*组织
  29 +*/
  30 +export const getUserListByOrg = (params) => {
  31 + return defHttp.get<any>({
  32 + url: `/user/tenant/page`,
  33 + params,
  34 + });
  35 +};
  36 +
  37 +/**
  38 + * 新增
  39 + */
  40 +export const saveLedger = (params) => {
  41 + return defHttp.post<any>({
  42 + url: `/da/save`,
  43 + params,
  44 + });
  45 +};
  46 +
  47 +/**
  48 + *详情
  49 + */
  50 +export const ledgerEditDetailPage = (params) => {
  51 + return defHttp.get<any>({
  52 + url: `/da/detail`,
  53 + params,
  54 + });
  55 +};
  56 +/**
  57 + *删除
  58 + */
  59 +export const deleteLedger = (params) => {
  60 + return defHttp.get<any>({
  61 + url: `/da/delete`,
  62 + params,
  63 + });
  64 +};
@@ -132,6 +132,7 @@ export type ComponentType = @@ -132,6 +132,7 @@ export type ComponentType =
132 | 'ControlGroup' 132 | 'ControlGroup'
133 | 'JSONEditor' 133 | 'JSONEditor'
134 | 'OrgTreeSelect' 134 | 'OrgTreeSelect'
  135 + | 'CategoryTreeSelect'
135 | 'CreateSpeed' 136 | 'CreateSpeed'
136 | 'ExtendDesc' 137 | 'ExtendDesc'
137 | 'JavaScriptFunctionEditor' 138 | 'JavaScriptFunctionEditor'
@@ -51,6 +51,12 @@ export enum DeviceStatusEnum { @@ -51,6 +51,12 @@ export enum DeviceStatusEnum {
51 OFFLINE = 'OFFLINE', 51 OFFLINE = 'OFFLINE',
52 } 52 }
53 53
  54 +export enum SbStatusEnum {
  55 + FAULT = 'FAULT',
  56 + NORMAL = 'NORMAL',
  57 + SCRAP = 'SCRAP',
  58 +}
  59 +
54 export enum CommandStatusEnum { 60 export enum CommandStatusEnum {
55 QUEUED = 'QUEUED', 61 QUEUED = 'QUEUED',
56 SENT = 'SENT', 62 SENT = 'SENT',
1 export default { 1 export default {
2 productText: '产品', 2 productText: '产品',
3 deviceText: '设备', 3 deviceText: '设备',
  4 + codeText: '设备编码',
  5 + brandText: '设备品牌',
4 attributeText: '属性', 6 attributeText: '属性',
5 organizationText: '组织', 7 organizationText: '组织',
6 tenantText: '租户', 8 tenantText: '租户',
@@ -29,4 +31,5 @@ export default { @@ -29,4 +31,5 @@ export default {
29 commandDeliveryText: '命令下发', 31 commandDeliveryText: '命令下发',
30 serviceText: '服务', 32 serviceText: '服务',
31 dateRangeText: '时间范围', 33 dateRangeText: '时间范围',
  34 + directorName: '负责人',
32 }; 35 };
@@ -85,6 +85,12 @@ export default { @@ -85,6 +85,12 @@ export default {
85 ONLINE: '在线', 85 ONLINE: '在线',
86 OFFLINE: '离线', 86 OFFLINE: '离线',
87 }, 87 },
  88 + sbStatus: {
  89 + ALL: '全部',
  90 + FAULT: '故障',
  91 + NORMAL: '正常',
  92 + SCRAP: '报废',
  93 + },
88 commandStatus: { 94 commandStatus: {
89 QUEUED: '队列中', 95 QUEUED: '队列中',
90 SENT: '已发送', 96 SENT: '已发送',
@@ -6,4 +6,5 @@ export default { @@ -6,4 +6,5 @@ export default {
6 orderText: '排序', 6 orderText: '排序',
7 description: '描述', 7 description: '描述',
8 operationSuccessText: '操作成功', 8 operationSuccessText: '操作成功',
  9 + categoryPlaceholderText: '请选择设备类别',
9 }; 10 };
1 export default { 1 export default {
2 ledgerListText: '台账列表', 2 ledgerListText: '台账列表',
  3 + nameCode: '设备编码',
  4 + brandText: '设备编码',
  5 + modelNumText: '型号',
  6 + buyDate: '购买时间',
  7 + productDate: '出厂日期',
  8 + registeDate: '登记日期',
  9 + receiveDate: '验收日期',
  10 + priceText: '价格',
  11 + specificationsText: '规格',
  12 + manufacturerText: '生产厂家',
  13 + description: '备注',
3 createLedgerText: '创建台账', 14 createLedgerText: '创建台账',
  15 + editLedgerText: '编辑台账',
4 importLedgerText: '导入台账', 16 importLedgerText: '导入台账',
5 deviceName: '设备名称', 17 deviceName: '设备名称',
6 deviceCode: '设备编码', 18 deviceCode: '设备编码',
7 deviceType: '设备类型', 19 deviceType: '设备类型',
8 status: '状态', 20 status: '状态',
9 - description: '负责人',  
10 operationSuccessText: '操作成功', 21 operationSuccessText: '操作成功',
11 editProductText: '编辑台账', 22 editProductText: '编辑台账',
12 updateOrganization: '修改组织', 23 updateOrganization: '修改组织',
13 batchActionText: '批量操作', 24 batchActionText: '批量操作',
  25 + FAULT: '故障',
  26 + NORMAL: '正常',
  27 + SCRAP: '报废',
14 } 28 }
  1 +export { default as CategoryTreeSelect } from './index.vue';
  1 +<template>
  2 + <section class="!flex">
  3 + <ApiTreeSelect v-bind="getBindProps" class="flex-auto" />
  4 + <Button v-if="getShowCreate" type="link" @click="handleOpenCreate" :disabled="disabled">
  5 + {{ t('component.orgSelect.createOrganizationText') }}
  6 + </Button>
  7 + <OrganizationDrawer v-if="getShowCreate" @register="registerDrawer" @success="handleReload" />
  8 + </section>
  9 +</template>
  10 +<script setup lang="ts">
  11 +import { ApiTreeSelect } from '/@/components/Form';
  12 +import { Button } from 'ant-design-vue';
  13 +import {computed, ref, unref} from "vue";
  14 +import {getAllCategory} from "/@/api/equipment/category";
  15 +import {useI18n} from "/@/hooks/web/useI18n";
  16 +const { t } = useI18n();
  17 +const emit = defineEmits(['change', 'optionsChange']);
  18 +
  19 +const props = withDefaults(
  20 + defineProps<{
  21 + value?: string | string[];
  22 + apiTreeSelectProps?: Recordable;
  23 + showCreate?: boolean;
  24 + disabled?: boolean;
  25 + }>(),
  26 + {
  27 + showCreate: true,
  28 + disabled: false,
  29 + }
  30 +);
  31 +const timespan = ref(Date.now());
  32 +const needReload = ref(true);
  33 +const cateList = ref<Recordable[]>([]);
  34 +const getBindProps = computed<Recordable>(() => {
  35 + const { value, apiTreeSelectProps = {}, disabled } = props;
  36 + const { params = {} } = apiTreeSelectProps;
  37 + return {
  38 + replaceFields: { children: 'children', key: 'id', title: 'name', value: 'id' },
  39 + getPopupContainer: () => document.body,
  40 + placeholder: t('equipment.category.categoryPlaceholderText'),
  41 + maxLength: 250,
  42 + disabled,
  43 + ...apiTreeSelectProps,
  44 + value,
  45 + dropdownStyle: { maxHeight: '300px' },
  46 + api: async (params: any) => {
  47 + try {
  48 + if (!unref(needReload)) return unref(cateList);
  49 + const result = ((await getAllCategory(params)) as unknown as Recordable[]) || [];
  50 + cateList.value = result;
  51 + needReload.value = false;
  52 + return result;
  53 + } catch (error) {
  54 + return unref(cateList);
  55 + }
  56 + },
  57 + params: {
  58 + ...params,
  59 + _t: unref(timespan),
  60 + },
  61 + onChange: (...args: any[]) => {
  62 + emit('change', ...args);
  63 + },
  64 + onOptionsChange: (...args: any[]) => emit('optionsChange', ...args),
  65 + };
  66 +});
  67 +
  68 +</script>
@@ -8,11 +8,15 @@ @@ -8,11 +8,15 @@
8 8
9 import { ref } from 'vue'; 9 import { ref } from 'vue';
10 import organizationIdTree from '../OrganizationIdTree.vue'; 10 import organizationIdTree from '../OrganizationIdTree.vue';
11 -export const useResetOrganizationTree = (searchInfo: Recordable) => { 11 +export const useResetOrganizationTree = (searchInfo: Recordable, type?: string) => {
12 const organizationIdTreeRef = ref<InstanceType<typeof organizationIdTree>>(); 12 const organizationIdTreeRef = ref<InstanceType<typeof organizationIdTree>>();
13 async function resetFn() { 13 async function resetFn() {
14 organizationIdTreeRef.value.resetOrganization(); 14 organizationIdTreeRef.value.resetOrganization();
15 - searchInfo.organizationId = null; 15 + if (type === 'equipment') {
  16 + searchInfo.categoryId = null;
  17 + }else {
  18 + searchInfo.organizationId = null;
  19 + }
16 } 20 }
17 return { organizationIdTreeRef, resetFn }; 21 return { organizationIdTreeRef, resetFn };
18 }; 22 };
@@ -25,6 +25,7 @@ @@ -25,6 +25,7 @@
25 import { computed, onMounted, ref, unref, useAttrs } from 'vue'; 25 import { computed, onMounted, ref, unref, useAttrs } from 'vue';
26 import { BasicTree, TreeItem } from '/@/components/Tree'; 26 import { BasicTree, TreeItem } from '/@/components/Tree';
27 import { getOrganizationList } from '/@/api/system/system'; 27 import { getOrganizationList } from '/@/api/system/system';
  28 + import { getAllCategory } from '/@/api/equipment/category';
28 import { CaretRightOutlined } from '@ant-design/icons-vue'; 29 import { CaretRightOutlined } from '@ant-design/icons-vue';
29 import { getBoundingClientRect } from '/@/utils/domUtils'; 30 import { getBoundingClientRect } from '/@/utils/domUtils';
30 import { BasicTreePropsType, OrganizationTreeActionType } from './types'; 31 import { BasicTreePropsType, OrganizationTreeActionType } from './types';
@@ -34,7 +35,6 @@ @@ -34,7 +35,6 @@
34 const props = defineProps<OrganizationTreePropsType>(); 35 const props = defineProps<OrganizationTreePropsType>();
35 36
36 const attrs = useAttrs(); 37 const attrs = useAttrs();
37 -  
38 const tree = ref<Nullable<HTMLDivElement>>(); 38 const tree = ref<Nullable<HTMLDivElement>>();
39 const emit = defineEmits(['select', 'register']); 39 const emit = defineEmits(['select', 'register']);
40 const treeData = ref<TreeItem[]>([]); 40 const treeData = ref<TreeItem[]>([]);
@@ -75,7 +75,14 @@ @@ -75,7 +75,14 @@
75 }; 75 };
76 76
77 onMounted(async () => { 77 onMounted(async () => {
78 - treeData.value = (await getOrganizationList()) as unknown as TreeItem[]; 78 + let api:any;
  79 + if (attrs?.listType === 'equipment') {
  80 + api = getAllCategory()
  81 + }else {
  82 + api = getOrganizationList()
  83 + }
  84 +
  85 + treeData.value = (await api) as unknown as TreeItem[];
79 const getAllIds = findForAllId(treeData.value as any, []); 86 const getAllIds = findForAllId(treeData.value as any, []);
80 //设置要展开的id 87 //设置要展开的id
81 treeExpandData.value = getAllIds; 88 treeExpandData.value = getAllIds;
@@ -88,12 +95,11 @@ @@ -88,12 +95,11 @@
88 }); 95 });
89 96
90 const getProps = computed<OrganizationTreePropsType>(() => ({ ...props, ...unref(innerProps) })); 97 const getProps = computed<OrganizationTreePropsType>(() => ({ ...props, ...unref(innerProps) }));
91 -  
92 const { t } = useI18n(); 98 const { t } = useI18n();
93 99
94 const getBindData = computed(() => { 100 const getBindData = computed(() => {
95 return { 101 return {
96 - title: t('common.organizationList'), 102 + title: attrs?.listType === 'equipment' ? t('equipment.category.categoryText') : t('common.organizationList'),
97 toolbar: true, 103 toolbar: true,
98 search: true, 104 search: true,
99 clickRowToExpand: false, 105 clickRowToExpand: false,
1 export interface OrganizationTreePropsType { 1 export interface OrganizationTreePropsType {
2 onSelect?: (selectKeys: string) => any; 2 onSelect?: (selectKeys: string) => any;
  3 + listType?: string;
3 } 4 }
  1 +<template>
  2 + <BasicDrawer
  3 + destroyOnClose
  4 + v-bind="$attrs"
  5 + showFooter
  6 + width="35%"
  7 + :maskClosable="true"
  8 + :title="businessText"
  9 + @register="registerDrawer"
  10 + wrapClassName="report-drawer"
  11 + @ok="handleSubmit"
  12 + @close="handleClose"
  13 + >
  14 + <BasicForm @register="registerForm">
  15 +
  16 + </BasicForm>
  17 + </BasicDrawer>
  18 +</template>
  19 +<script setup lang="ts">
  20 +import {nextTick, reactive, ref} from "vue";
  21 +import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
  22 +import { SchemaFiled} from "../../config/enum";
  23 +import {BasicForm,useForm} from "/@/components/Form";
  24 +import {formSchema} from "../../config/data";
  25 +import {useHooks} from "/@/views/report/config/hooks/index.hooks";
  26 +import {getUserListByOrg,ledgerEditDetailPage,saveLedger } from "/@/api/equipment/ledger"
  27 +import {useUserStore} from "/@/store/modules/user";
  28 +import {useThrottleFn} from "@vueuse/shared/index";
  29 +import {useMessage} from "/@/hooks/web/useMessage";
  30 +import {useI18n} from "/@/hooks/web/useI18n";
  31 +const {
  32 + setDefaultTime,
  33 + disableCustomWeekly,
  34 + setPropsForModal,
  35 + removeFields,
  36 +} = useHooks();
  37 +const userInfo = useUserStore();
  38 +const restData = reactive({
  39 + data: {},
  40 +});
  41 +const { createMessage } = useMessage();
  42 +const { t } = useI18n();
  43 +const emits = defineEmits(['success', 'register']);
  44 +const [registerForm, { validate, resetFields, setFieldsValue, updateSchema, setProps }] = useForm(
  45 + {
  46 + labelWidth: 140,
  47 + schemas: formSchema,
  48 + showActionButtonGroup: false,
  49 + fieldMapToTime: [[SchemaFiled.DATE_RANGE, [SchemaFiled.START_TS, SchemaFiled.END_TS]]],
  50 + }
  51 +);
  52 +// 定义人员选项
  53 +const userOptions = ref<any[]>([]);
  54 +
  55 +// 监听 org 字段的变化
  56 +const handleOrgChange = async (orgId: string) => {
  57 + if (!orgId) {
  58 + userOptions.value = []; // 清空人员选项
  59 + updateSchema({
  60 + field: 'directorId',
  61 + componentProps: { options: [] },
  62 + });
  63 + return;
  64 + }
  65 + const _data = {
  66 + page: '1',
  67 + pageSize: '999',
  68 + tenantId: userInfo.getUserInfo.tenantId!,
  69 + organizationId: orgId
  70 + }
  71 + // 调用接口 B 获取人员数据
  72 + const userList = await getUserListByOrg(_data);
  73 + console.log(userList,'userList')
  74 + userOptions.value = userList?.items.map(user => ({
  75 + label: user.username,
  76 + value: user.id,
  77 + }));
  78 +
  79 + // 更新 user 字段的选项
  80 + updateSchema({
  81 + field: 'directorId',
  82 + componentProps: { options: userOptions.value },
  83 + });
  84 +};
  85 +
  86 +
  87 +
  88 +
  89 +const businessText = ref('');
  90 +const [registerDrawer, { setDrawerProps, closeDrawer }] = useDrawerInner(async (data) => {
  91 + try {
  92 + await nextTick();
  93 + handleClose();
  94 + businessText.value = data.text;
  95 + // 更新 formSchema 中的 org 字段,绑定 change 事件
  96 + updateSchema({
  97 + field: 'org',
  98 + componentProps: {
  99 + onChange: handleOrgChange,
  100 + },
  101 + });
  102 + setFieldsValue(setDefaultTime());
  103 + updateSchema(disableCustomWeekly(0));
  104 + setDrawerProps(setPropsForModal(businessText.value));
  105 + if (businessText.value === 'add') return;
  106 + const rest = await ledgerEditDetailPage({id: data.record?.id});
  107 + restData.data = rest ?? {};
  108 +
  109 + await setFieldsValue({
  110 + ...restData.data,
  111 + });
  112 +
  113 + } finally {
  114 + setDrawerProps({ loading: false });
  115 + }
  116 +});
  117 +const handleClose = () => {
  118 + resetValue();
  119 +}
  120 +//重置表单
  121 +const resetValue = () => {
  122 + resetFields();
  123 +};
  124 +
  125 +const handleSubmit = () => {
  126 + useThrottle();
  127 +};
  128 +
  129 +const useThrottle = useThrottleFn(() => {
  130 + getValue();
  131 +}, 2000);
  132 +
  133 +const getValue = async () => {
  134 + try {
  135 + setDrawerProps({ confirmLoading: true });
  136 + const values = await validate();
  137 + if (!values) return;
  138 + const data = {
  139 + ...values,
  140 + buyDate: values.buyDate?.format('YYYY-MM-DD hh:mm:ss'),
  141 + productDate: values.productDate?.format('YYYY-MM-DD hh:mm:ss'),
  142 + receiveDate: values.receiveDate?.format('YYYY-MM-DD hh:mm:ss'),
  143 + registeDate: values.registeDate?.format('YYYY-MM-DD hh:mm:ss'),
  144 + };
  145 + removeFields.forEach((item) => {
  146 + Reflect.deleteProperty(data, item);
  147 + });
  148 + businessText.value === 'add'
  149 + ? await saveLedger(data)
  150 + : saveLedger({ ...restData.data, ...data });
  151 + createMessage.success(
  152 + t(businessText.value !== 'add' ? 'common.editSuccessText' : 'common.createSuccessText')
  153 + );
  154 + closeDrawer();
  155 + handleClose();
  156 + setTimeout(() => {
  157 + emits('success');
  158 + }, 500);
  159 + } finally {
  160 + setDrawerProps({ confirmLoading: false });
  161 + }
  162 +};
  163 +
  164 +</script>
  1 +import LedgerDrawer from './LedgerDrawer.vue';
  2 +
  3 +export { LedgerDrawer };
1 -import { FormSchema, useComponentRegister } from '/@/components/Form';  
2 -import { findDictItemByCode } from '/@/api/system/dict';  
3 -import { getGatewayDevice, queryDeviceProfileBy } from '/@/api/device/deviceManager';  
4 -import { JSONEditor } from '/@/components/CodeEditor';  
5 -import { DeviceRecord, DeviceTypeEnum } from '/@/api/device/model/deviceModel';  
6 -import { h } from 'vue';  
7 -import { TaskTypeEnum } from '/@/views/task/center/config';  
8 -import { createImgPreview } from '/@/components/Preview';  
9 -import { uploadThumbnail } from '/@/api/configuration/center/configurationCenter';  
10 -import LockControlGroup from '/@/components/Form/src/components/LockControlGroup.vue';  
11 -import { OrgTreeSelect } from '/@/views/common/OrgTreeSelect';  
12 -import { TCPProtocolTypeEnum, TransportTypeEnum } from '/@/enums/deviceEnum';  
13 -import { HexInput, InputTypeEnum } from '../../profiles/components/ObjectModelForm/HexInput';  
14 -import { DeviceProfileDetail } from '/@/api/device/model/deviceConfigModel';  
15 -import { getDeviceProfileOtaPackages, getOtaPackageInfo } from '/@/api/ota';  
16 -import { QueryDeviceProfileOtaPackagesType } from '/@/api/ota/model';  
17 -import { OTAPackageType } from '/@/enums/otaEnum';  
18 -import { createPickerSearch } from '/@/utils/pickerSearch';  
19 -import { useI18n } from '/@/hooks/web/useI18n';  
20 -  
21 -useComponentRegister('JSONEditor', JSONEditor);  
22 -useComponentRegister('LockControlGroup', LockControlGroup);  
23 -useComponentRegister('OrgTreeSelect', OrgTreeSelect);  
24 -useComponentRegister('HexInput', HexInput);  
25 - 1 +import {FormSchema as BFormSchema, useComponentRegister} from "../../../../components/Form";
  2 +import {useI18n} from "../../../../hooks/web/useI18n";
26 const { t } = useI18n(); 3 const { t } = useI18n();
27 -  
28 -export enum TypeEnum {  
29 - IS_GATEWAY = 'GATEWAY',  
30 - SENSOR = 'SENSOR',  
31 -}  
32 -  
33 -export const isGateWay = (type: string) => {  
34 - return type === TypeEnum.IS_GATEWAY;  
35 -};  
36 -  
37 -const updateProductHelpMessage = [  
38 - t('deviceManagement.device.updateProductHelpMessage.text1'),  
39 - t('deviceManagement.device.updateProductHelpMessage.text2'),  
40 -];  
41 -  
42 -export const updateOrgHelpMessage = [  
43 - t('deviceManagement.device.updateOrgHelpMessage.text1'),  
44 - t('deviceManagement.device.updateOrgHelpMessage.text2'),  
45 - t('deviceManagement.device.updateOrgHelpMessage.text3'), 4 +import { CategoryTreeSelect } from '../../../common/CategoryTreeSelect';
  5 +import { OrgTreeSelect } from '../../../common/OrgTreeSelect';
  6 +useComponentRegister('OrgTreeSelect', OrgTreeSelect);
  7 +useComponentRegister('CategoryTreeSelect', CategoryTreeSelect);
  8 +const statusOptions = [
  9 + { label: t('equipment.ledger.NORMAL'), value: 'NORMAL' },
  10 + { label: t('equipment.ledger.FAULT'), value: 'FAULT' },
  11 + { label: t('equipment.ledger.SCRAP'), value: 'SCRAP' },
46 ]; 12 ];
47 -// 第一步的表单  
48 -export const step1Schemas: FormSchema[] = [  
49 - {  
50 - field: 'icon',  
51 - label: t('business.deviceImageText'),  
52 - component: 'ApiUpload',  
53 - changeEvent: 'update:fileList',  
54 - valueField: 'fileList',  
55 - componentProps: ({ formModel }) => {  
56 - return {  
57 - listType: 'picture-card',  
58 - maxFileLimit: 1,  
59 - accept: '.png,.jpg,.jpeg,.gif',  
60 - api: async (file: File) => {  
61 - try {  
62 - const formData = new FormData();  
63 - formData.set('file', file);  
64 - const { fileStaticUri, fileName } = await uploadThumbnail(formData);  
65 - return {  
66 - uid: fileStaticUri,  
67 - name: fileName,  
68 - url: fileStaticUri,  
69 - };  
70 - } catch (error) {  
71 - return {};  
72 - }  
73 - },  
74 - onPreview: (fileList) => {  
75 - createImgPreview({ imageList: [fileList.url!] });  
76 - },  
77 - onDelete(url: string) {  
78 - formModel.deleteUrl = url!;  
79 - },  
80 - };  
81 - },  
82 - }, 13 +export const formSchema: BFormSchema[] = [
83 { 14 {
84 - field: 'deleteUrl',  
85 - label: '',  
86 - component: 'Input',  
87 - show: false,  
88 - },  
89 - {  
90 - field: 'alias',  
91 - label: t('business.aliasText'), 15 + field: 'code',
  16 + label: t('equipment.ledger.nameCode'),
92 component: 'Input', 17 component: 'Input',
  18 + colProps: { span: 24 },
  19 + required: true,
93 componentProps: { 20 componentProps: {
94 - maxLength: 32, 21 + maxLength: 20,
95 }, 22 },
96 }, 23 },
97 { 24 {
98 field: 'name', 25 field: 'name',
99 - label: t('business.deviceNameText'), 26 + label: t('equipment.ledger.deviceName'),
100 component: 'Input', 27 component: 'Input',
  28 + colProps: { span: 24 },
  29 + required: true,
101 componentProps: { 30 componentProps: {
102 - maxLength: 32, 31 + maxLength: 20,
103 }, 32 },
104 - required: true,  
105 - slot: 'snCode',  
106 }, 33 },
107 { 34 {
108 - field: 'transportType',  
109 - label: '类型',  
110 - component: 'Input',  
111 - show: false,  
112 - },  
113 - {  
114 - field: 'deviceProfileId',  
115 - label: '',  
116 - component: 'Input',  
117 - show: false,  
118 - },  
119 - {  
120 - field: 'isUpdate',  
121 - label: '编辑模式',  
122 - component: 'Switch',  
123 - show: false,  
124 - },  
125 - {  
126 - field: 'tcpDeviceProtocol',  
127 - label: 'TCP设备协议类型',  
128 - component: 'Input',  
129 - show: false,  
130 - },  
131 -  
132 - {  
133 - field: 'profileId',  
134 - label: t('business.affiliatedProductText'), 35 + field: 'categoryId',
  36 + label: t('equipment.category.categoryText'),
  37 + colProps: { span: 24 },
  38 + component: 'CategoryTreeSelect',
135 required: true, 39 required: true,
136 - component: 'LockControlGroup',  
137 - helpMessage: updateProductHelpMessage,  
138 - renderComponentContent: () => ({  
139 - popconfirmTitle: () =>  
140 - updateProductHelpMessage.map((text) => h('div', { style: { maxWidth: '200px' } }, text)),  
141 - }),  
142 - componentProps: ({ formActionType, formModel }) => {  
143 - const { setFieldsValue } = formActionType;  
144 - return {  
145 - component: 'ApiSelect',  
146 - defaultLockStatus: !!formModel?.isUpdate,  
147 - componentProps: {  
148 - api: async () => {  
149 - const options = await queryDeviceProfileBy({  
150 - deviceType: formModel?.isUpdate ? formModel?.deviceType : null,  
151 - });  
152 -  
153 - return options;  
154 - },  
155 - labelField: 'name',  
156 - valueField: 'tbProfileId',  
157 - onChange(_value: string, option: DeviceProfileDetail) {  
158 - const { deviceType, transportType, id } = option;  
159 - setFieldsValue({  
160 - deviceType: deviceType,  
161 - transportType,  
162 - deviceProfileId: id,  
163 - gatewayId: null,  
164 - code: null,  
165 - addressCode: null,  
166 - tcpDeviceProtocol: option?.profileData?.transportConfiguration?.protocol,  
167 - });  
168 - },  
169 - onOptionsChange(options: (DeviceProfileDetail & Record<'value', string>)[]) {  
170 - const { profileId } = formModel;  
171 - if (profileId) {  
172 - const selectRecord = options.find((item) => item.value === profileId);  
173 - selectRecord &&  
174 - setFieldsValue({  
175 - transportType: selectRecord!.transportType,  
176 - tcpDeviceProtocol: selectRecord?.profileData?.transportConfiguration?.protocol,  
177 - });  
178 - }  
179 - },  
180 - placeholder: t('deviceManagement.device.productPlaceholderText'),  
181 - ...createPickerSearch(),  
182 - },  
183 - };  
184 - },  
185 }, 40 },
186 { 41 {
187 - field: 'deviceType',  
188 - label: t('business.deviceTypeText'), 42 + field: 'status',
  43 + component: 'Select',
  44 + label: t('equipment.ledger.status'),
189 required: true, 45 required: true,
190 - component: 'ApiSelect',  
191 - dynamicDisabled: true,  
192 - helpMessage: t('deviceManagement.device.deviceTypeHelpText'), 46 + colProps: { span: 24 },
  47 + defaultValue: 'NORMAL',
193 componentProps: { 48 componentProps: {
194 - api: findDictItemByCode,  
195 - params: {  
196 - dictCode: 'device_type',  
197 - },  
198 - labelField: 'itemText',  
199 - valueField: 'itemValue',  
200 - },  
201 - },  
202 - {  
203 - field: 'addressType',  
204 - label: '',  
205 - component: 'Input',  
206 - show: false,  
207 - defaultValue: 'HEX',  
208 - },  
209 - {  
210 - field: 'deviceState',  
211 - label: '',  
212 - component: 'Input',  
213 - show: false,  
214 - },  
215 - {  
216 - field: 'addressCode',  
217 - label: t('deviceManagement.device.addressCodeText'),  
218 - dynamicDisabled({ values }) {  
219 - return (  
220 - values.isUpdate &&  
221 - values.deviceType === DeviceTypeEnum.SENSOR &&  
222 - values.deviceState === 'ONLINE' &&  
223 - values.transportType === TransportTypeEnum.TCP  
224 - );  
225 - },  
226 - dynamicRules({ values }) {  
227 - return [  
228 - {  
229 - required:  
230 - values?.transportType === TransportTypeEnum.TCP &&  
231 - values?.tcpDeviceProtocol === TCPProtocolTypeEnum.MODBUS_RTU,  
232 - message: t('deviceManagement.device.addressCodeHelpText'),  
233 - pattern: values?.addressType === 'HEX' ? /^[0-9A-Fa-f]{2}$/ : /^[0-9A-Fa-f]{1,2}$/,  
234 - },  
235 - ];  
236 - },  
237 - helpMessage({ values }) {  
238 - return [  
239 - t('deviceManagement.device.addressCodeHelpText'),  
240 - values.transportType === TransportTypeEnum.TCP &&  
241 - values.deviceType === DeviceTypeEnum.SENSOR  
242 - ? t('deviceManagement.device.tcpAddressCodeHelpText')  
243 - : '',  
244 - ];  
245 - },  
246 - component: 'HexInput',  
247 - changeEvent: 'update:value',  
248 - valueField: 'value',  
249 - componentProps: ({ formModel }) => {  
250 - return {  
251 - type: InputTypeEnum.HEX,  
252 - maxValue: parseInt('FF', 16),  
253 - onHexChange: (e) => {  
254 - formModel.addressType = e;  
255 - },  
256 - };  
257 - },  
258 - ifShow: ({ values }) => {  
259 - return (  
260 - values?.transportType === TransportTypeEnum.TCP &&  
261 - values?.tcpDeviceProtocol === TCPProtocolTypeEnum.MODBUS_RTU  
262 - );  
263 - },  
264 - },  
265 - {  
266 - field: 'code',  
267 - label: t('deviceManagement.device.codeText'),  
268 - dynamicRules({ values }) {  
269 - return [  
270 - {  
271 - required:  
272 - values?.transportType === TransportTypeEnum.TCP &&  
273 - values.deviceType === DeviceTypeEnum.SENSOR,  
274 - },  
275 - ];  
276 - },  
277 - dynamicDisabled({ values }) {  
278 - return (  
279 - values.isUpdate &&  
280 - values.deviceType === DeviceTypeEnum.SENSOR &&  
281 - values.deviceState === 'ONLINE' &&  
282 - values.transportType === TransportTypeEnum.TCP  
283 - );  
284 - },  
285 - helpMessage({ values }) {  
286 - return (  
287 - values.transportType === TransportTypeEnum.TCP &&  
288 - values.deviceType === DeviceTypeEnum.SENSOR  
289 - ? ['tcp网关子设备在线时,不能修改设备标识或地址码']  
290 - : false  
291 - ) as any;  
292 - },  
293 - component: 'Input',  
294 - componentProps: () => {  
295 - return {  
296 - maxLength: 255,  
297 - placeholder: t('deviceManagement.device.codePlaceholderText'),  
298 - };  
299 - },  
300 - ifShow: ({ values }) => {  
301 - return (  
302 - values?.transportType === TransportTypeEnum.TCP &&  
303 - values?.tcpDeviceProtocol === TaskTypeEnum.CUSTOM  
304 - ); 49 + options: statusOptions,
305 }, 50 },
306 }, 51 },
307 -  
308 { 52 {
309 - field: 'brand',  
310 - component: 'ApiRadioGroup',  
311 - label: t('deviceManagement.device.brandText'), 53 + field: 'org',
  54 + component: 'OrgTreeSelect',
  55 + label: '负责人组织',
312 required: true, 56 required: true,
313 - defaultValue: 'DIY_', 57 + colProps: { span: 24 },
314 componentProps: { 58 componentProps: {
315 - api: findDictItemByCode,  
316 - params: {  
317 - dictCode: 'device_brand_gateway', 59 + // 添加 change 事件
  60 + onChange: (value: string) => {
  61 + // 这里需要触发加载人员数据的逻辑
  62 + console.log(value,'value')
318 }, 63 },
319 - labelField: 'itemText',  
320 - valueField: 'itemValue',  
321 - },  
322 - ifShow: ({ values }) => isGateWay(values.deviceType),  
323 - },  
324 - {  
325 - field: 'gatewayId',  
326 - label: t('enum.deviceType.GATEWAY'),  
327 - required: true,  
328 - component: 'ApiSelect',  
329 - ifShow: ({ values }) => values.deviceType === 'SENSOR',  
330 - componentProps: ({ formModel, formActionType }) => {  
331 - const { transportType, deviceType, gatewayId } = formModel;  
332 - const { setFieldsValue } = formActionType;  
333 - if (!transportType) return {};  
334 - return {  
335 - api: async (params: Recordable) => {  
336 - try {  
337 - const result = await getGatewayDevice(params as any);  
338 - return result.map((item) => ({ ...item, alias: item.alias || item.name }));  
339 - } catch (e) {  
340 - return [];  
341 - }  
342 - },  
343 - params: {  
344 - transportType,  
345 - gatewayId: deviceType === DeviceTypeEnum.SENSOR && gatewayId ? gatewayId : null,  
346 - },  
347 - valueField: 'tbDeviceId',  
348 - labelField: 'alias',  
349 - onChange: async (_value: string, option: DeviceRecord) => {  
350 - setFieldsValue({ sensorOrganizationId: option?.organizationId, organizationId: null });  
351 - },  
352 - onOptionsChange(options: (DeviceRecord & Record<'value', string>)[]) {  
353 - if (formModel?.deviceType === DeviceTypeEnum.SENSOR && formModel?.gatewayId) {  
354 - const result = options.find((item) => item.value === formModel?.gatewayId);  
355 - result && setFieldsValue({ sensorOrganizationId: result?.organizationId });  
356 - }  
357 - },  
358 - ...createPickerSearch(),  
359 - };  
360 - },  
361 - },  
362 - {  
363 - field: 'sensorOrganizationId',  
364 - label: '依据网关设备请求的组织数组',  
365 - component: 'Input',  
366 - ifShow: false,  
367 - },  
368 - {  
369 - field: 'customerId',  
370 - label: '用来判断编辑时禁用组织修改',  
371 - component: 'Input',  
372 - ifShow: false,  
373 - },  
374 - {  
375 - field: 'organizationId',  
376 - label: t('business.affiliatedOrganizationText'),  
377 - component: 'LockControlGroup',  
378 - required: true,  
379 - helpMessage: updateOrgHelpMessage,  
380 - renderComponentContent: () => ({  
381 - popconfirmTitle: () =>  
382 - updateOrgHelpMessage.map((text) => h('div', { style: { maxWidth: '240px' } }, text)),  
383 - }),  
384 - componentProps: ({ formModel, formActionType }) => {  
385 - return {  
386 - component: 'OrgTreeSelect',  
387 - defaultLockStatus: !!formModel?.isUpdate,  
388 - disabled: !!formModel?.customerId,  
389 - componentProps: {  
390 - apiTreeSelectProps: {  
391 - params: {  
392 - organizationId: formModel?.sensorOrganizationId,  
393 - },  
394 - },  
395 - onOptionsChange: (options: Recordable[]) => {  
396 - if (!formModel?.organizationId && formModel?.deviceType === DeviceTypeEnum.SENSOR) {  
397 - const firstItem = options?.[0];  
398 -  
399 - if (firstItem && firstItem?.id) {  
400 - const { setFieldsValue, clearValidate } = formActionType;  
401 - setFieldsValue({ organizationId: firstItem.id });  
402 - clearValidate('organizationId');  
403 - }  
404 - }  
405 - },  
406 - placeholder: t('deviceManagement.device.organizationPlaceholderText'),  
407 - },  
408 - };  
409 }, 64 },
410 }, 65 },
411 { 66 {
412 field: 'directorId', 67 field: 'directorId',
413 - label: t('deviceManagement.device.directorName'),  
414 - component: 'Input',  
415 - componentProps: {  
416 - maxLength: 255,  
417 - },  
418 - },  
419 - {  
420 - field: 'label',  
421 - label: t('deviceManagement.device.deviceLabelText'),  
422 - component: 'Input',  
423 - componentProps: {  
424 - maxLength: 255,  
425 - },  
426 - },  
427 - {  
428 - field: 'deviceAddress',  
429 - label: t('business.deviceLocationText'),  
430 - component: 'Input',  
431 - slot: 'deviceAddress',  
432 - },  
433 -  
434 - {  
435 - field: 'firmwareId',  
436 - label: t('deviceManagement.product.assignHardwareText'),  
437 - component: 'ApiSearchSelect',  
438 - ifShow: ({ model }) => model?.isUpdate,  
439 - componentProps: ({ formModel }) => {  
440 - return {  
441 - api: async (params: QueryDeviceProfileOtaPackagesType) => {  
442 - if (!params.deviceProfileId) return [];  
443 - const result = await getDeviceProfileOtaPackages(params);  
444 - return result.data.map((item) => ({  
445 - label: `${item.title}(${item.version})`,  
446 - value: item.id.id,  
447 - }));  
448 - },  
449 - params: (textSearch: string) => {  
450 - return {  
451 - textSearch,  
452 - page: 0,  
453 - type: OTAPackageType.FIRMWARE,  
454 - pageSize: 10,  
455 - deviceProfileId: formModel?.profileId,  
456 - };  
457 - },  
458 - queryApi: async (id: string) => {  
459 - const result = await getOtaPackageInfo(id);  
460 - return { label: `${result.title}(${result.version})`, value: result.id.id };  
461 - },  
462 - };  
463 - },  
464 - },  
465 - {  
466 - field: 'softwareId',  
467 - label: t('deviceManagement.product.assignSoftwareText'),  
468 - component: 'ApiSearchSelect',  
469 - ifShow: ({ model }) => model?.isUpdate,  
470 - componentProps: ({ formModel }) => {  
471 - return {  
472 - api: async (params: QueryDeviceProfileOtaPackagesType) => {  
473 - if (!params.deviceProfileId) return [];  
474 - const result = await getDeviceProfileOtaPackages(params);  
475 - return result.data.map((item) => ({  
476 - label: `${item.title}(${item.version})`,  
477 - value: item.id.id,  
478 - }));  
479 - },  
480 - params: (textSearch: string) => {  
481 - return {  
482 - textSearch,  
483 - page: 0,  
484 - type: OTAPackageType.SOFTWARE,  
485 - pageSize: 10,  
486 - deviceProfileId: formModel?.profileId,  
487 - };  
488 - },  
489 - queryApi: async (id: string) => {  
490 - const result = await getOtaPackageInfo(id);  
491 - return { label: `${result.title}(${result.version})`, value: result.id.id };  
492 - },  
493 - };  
494 - },  
495 - },  
496 - {  
497 - field: 'description',  
498 - label: t('common.remarkText'),  
499 - component: 'InputTextArea',  
500 - componentProps: {  
501 - maxLength: 500,  
502 - },  
503 - },  
504 - {  
505 - field: 'id',  
506 - label: 'id',  
507 - component: 'Input',  
508 - show: false,  
509 - componentProps: {  
510 - maxLength: 36,  
511 - placeholder: '请输入id',  
512 - },  
513 - },  
514 - {  
515 - field: 'tenantId',  
516 - label: '租户Code',  
517 - component: 'Input',  
518 - show: false,  
519 - componentProps: {  
520 - maxLength: 36,  
521 - placeholder: '请输入租户Code',  
522 - },  
523 - },  
524 - {  
525 - field: 'tbDeviceId',  
526 - label: 'tbDeviceId',  
527 - component: 'Input',  
528 - show: false, 68 + component: 'Select',
  69 + label: '负责人',
  70 + required: true,
  71 + colProps: { span: 24 },
529 componentProps: { 72 componentProps: {
530 - maxLength: 36,  
531 - placeholder: '请输入tbDeviceId', 73 + // 动态加载的选项
  74 + options: [], // 初始为空,后续动态加载
532 }, 75 },
533 }, 76 },
534 -];  
535 -  
536 -export enum credentialTypeEnum {  
537 - ACCESS_TOKEN = 'ACCESS_TOKEN',  
538 - X_509 = 'X509_CERTIFICATE',  
539 - MQTT_BASIC = 'MQTT_BASIC',  
540 -}  
541 -// 第二步的表单  
542 -export const step2Schemas: FormSchema[] = [  
543 - {  
544 - label: '',  
545 - component: 'Checkbox',  
546 - field: 'addAgree',  
547 - slot: 'addAgree',  
548 - },  
549 { 77 {
550 - label: t('deviceManagement.device.certificateTypeText'), 78 + field: 'isOnline',
551 component: 'Select', 79 component: 'Select',
552 - field: 'credentialType', 80 + label: '是否联网',
553 required: true, 81 required: true,
554 - componentProps({ formActionType }) {  
555 - const { updateSchema, setFieldsValue } = formActionType;  
556 - return {  
557 - options: [  
558 - {  
559 - value: credentialTypeEnum.ACCESS_TOKEN,  
560 - label: 'Access Token',  
561 - },  
562 - {  
563 - value: credentialTypeEnum.X_509,  
564 - label: 'X.509',  
565 - },  
566 - {  
567 - value: credentialTypeEnum.MQTT_BASIC,  
568 - label: 'MQTT Basic',  
569 - },  
570 - ],  
571 - onChange(value) {  
572 - setFieldsValue({  
573 - publicKey: '',  
574 - credentialsId: '',  
575 - clientId: '',  
576 - username: '',  
577 - password: '',  
578 - });  
579 - if (value === credentialTypeEnum.ACCESS_TOKEN) {  
580 - updateSchema([  
581 - {  
582 - field: 'credentialsId',  
583 - ifShow: true,  
584 - },  
585 - {  
586 - field: 'clientId',  
587 - ifShow: false,  
588 - },  
589 - {  
590 - field: 'username',  
591 - ifShow: false,  
592 - },  
593 - {  
594 - field: 'password',  
595 - ifShow: false,  
596 - },  
597 - {  
598 - field: 'publicKey',  
599 - ifShow: false,  
600 - },  
601 - ]);  
602 - } else if (value === credentialTypeEnum.X_509) {  
603 - updateSchema([  
604 - {  
605 - field: 'publicKey',  
606 - ifShow: true,  
607 - },  
608 - {  
609 - field: 'credentialsId',  
610 - ifShow: false,  
611 - },  
612 - {  
613 - field: 'clientId',  
614 - ifShow: false,  
615 - },  
616 - {  
617 - field: 'username',  
618 - ifShow: false,  
619 - },  
620 - {  
621 - field: 'password',  
622 - ifShow: false,  
623 - },  
624 - ]);  
625 - } else if (value === credentialTypeEnum.MQTT_BASIC) {  
626 - updateSchema([  
627 - {  
628 - field: 'clientId',  
629 - ifShow: true,  
630 - },  
631 - {  
632 - field: 'username',  
633 - ifShow: true,  
634 - },  
635 - {  
636 - field: 'password',  
637 - ifShow: true,  
638 - },  
639 - {  
640 - field: 'publicKey',  
641 - ifShow: false,  
642 - },  
643 - {  
644 - field: 'credentialsId',  
645 - ifShow: false,  
646 - },  
647 - ]);  
648 - } else {  
649 - updateSchema([  
650 - {  
651 - field: 'clientId',  
652 - ifShow: false,  
653 - },  
654 - {  
655 - field: 'username',  
656 - ifShow: false,  
657 - },  
658 - {  
659 - field: 'password',  
660 - ifShow: false,  
661 - },  
662 - {  
663 - field: 'publicKey',  
664 - ifShow: false,  
665 - },  
666 - {  
667 - field: 'credentialsId',  
668 - ifShow: false,  
669 - },  
670 - ]);  
671 - } 82 + colProps: { span: 24 },
  83 + componentProps: {
  84 + options: [
  85 + {
  86 + label: '是',
  87 + value: true,
672 }, 88 },
673 - }; 89 + {
  90 + label: '否',
  91 + value: false,
  92 + }
  93 + ],
674 }, 94 },
675 - ifShow: ({ values }) => values.addAgree,  
676 }, 95 },
677 { 96 {
678 - label: t('deviceManagement.device.accessTokenText'), 97 + field: 'brand',
  98 + label: t('equipment.ledger.brandText'),
679 component: 'Input', 99 component: 'Input',
680 - field: 'credentialsId',  
681 - required: true,  
682 - ifShow: false,  
683 - slot: 'credentialsId', 100 + colProps: { span: 24 },
684 componentProps: { 101 componentProps: {
685 - maxLength: 36, 102 + maxLength: 20,
686 }, 103 },
687 }, 104 },
688 { 105 {
689 - label: t('deviceManagement.device.rsaPublicKeyText'),  
690 - component: 'InputTextArea',  
691 - field: 'publicKey',  
692 - required: true,  
693 - ifShow: false, 106 + field: 'modelNum',
  107 + label: t('equipment.ledger.modelNumText'),
  108 + component: 'Input',
  109 + colProps: { span: 24 },
694 componentProps: { 110 componentProps: {
695 - rows: 8, 111 + maxLength: 20,
696 }, 112 },
697 }, 113 },
698 { 114 {
699 - label: t('deviceManagement.device.clientIdText'), 115 + field: 'specifications',
  116 + label: t('equipment.ledger.specificationsText'),
700 component: 'Input', 117 component: 'Input',
701 - field: 'clientId',  
702 - ifShow: false,  
703 - slot: 'clientId', 118 + colProps: { span: 24 },
704 componentProps: { 119 componentProps: {
705 - maxLength: 36, 120 + maxLength: 20,
706 }, 121 },
707 }, 122 },
708 { 123 {
709 - label: t('deviceManagement.device.usernameText'), 124 + field: 'specifications',
  125 + label: t('equipment.ledger.manufacturerText'),
710 component: 'Input', 126 component: 'Input',
711 - field: 'username',  
712 - required: true,  
713 - ifShow: false, 127 + colProps: { span: 24 },
714 componentProps: { 128 componentProps: {
715 - maxLength: 255, 129 + maxLength: 20,
716 }, 130 },
717 }, 131 },
718 { 132 {
719 - label: t('deviceManagement.device.passwordText'),  
720 - component: 'InputPassword',  
721 - field: 'password', 133 + field: 'buyDate',
  134 + label: t('equipment.ledger.buyDate'),
  135 + component: 'DatePicker',
  136 + colProps: { span: 24 },
722 componentProps: { 137 componentProps: {
723 - maxLength: 36,  
724 - },  
725 - ifShow: false,  
726 - },  
727 -];  
728 -  
729 -// 管理凭证的表单配置项  
730 -export const TokenSchemas: FormSchema[] = [  
731 - {  
732 - label: t('deviceManagement.device.certificateTypeText'),  
733 - component: 'Select',  
734 - field: 'credentialType',  
735 - required: true,  
736 - componentProps({ formActionType }) {  
737 - const { updateSchema, setFieldsValue } = formActionType;  
738 - return {  
739 - options: [  
740 - {  
741 - value: credentialTypeEnum.ACCESS_TOKEN,  
742 - label: 'Access Token',  
743 - },  
744 - {  
745 - value: credentialTypeEnum.X_509,  
746 - label: 'X.509',  
747 - },  
748 - {  
749 - value: credentialTypeEnum.MQTT_BASIC,  
750 - label: 'MQTT Basic',  
751 - },  
752 - ],  
753 - onChange(value) {  
754 - setFieldsValue({  
755 - publicKey: '',  
756 - credentialsId: '',  
757 - clientId: '',  
758 - username: '',  
759 - password: '',  
760 - });  
761 - if (value === credentialTypeEnum.ACCESS_TOKEN) {  
762 - updateSchema([  
763 - {  
764 - field: 'credentialsId',  
765 - ifShow: true,  
766 - },  
767 - {  
768 - field: 'clientId',  
769 - ifShow: false,  
770 - },  
771 - {  
772 - field: 'username',  
773 - ifShow: false,  
774 - },  
775 - {  
776 - field: 'password',  
777 - ifShow: false,  
778 - },  
779 - {  
780 - field: 'publicKey',  
781 - ifShow: false,  
782 - },  
783 - ]);  
784 - } else if (value === credentialTypeEnum.X_509) {  
785 - updateSchema([  
786 - {  
787 - field: 'publicKey',  
788 - ifShow: true,  
789 - },  
790 - {  
791 - field: 'credentialsId',  
792 - ifShow: false,  
793 - },  
794 - {  
795 - field: 'clientId',  
796 - ifShow: false,  
797 - },  
798 - {  
799 - field: 'username',  
800 - ifShow: false,  
801 - },  
802 - {  
803 - field: 'password',  
804 - ifShow: false,  
805 - },  
806 - ]);  
807 - } else if (value === credentialTypeEnum.MQTT_BASIC) {  
808 - updateSchema([  
809 - {  
810 - field: 'clientId',  
811 - ifShow: true,  
812 - },  
813 - {  
814 - field: 'username',  
815 - ifShow: true,  
816 - },  
817 - {  
818 - field: 'password',  
819 - ifShow: true,  
820 - },  
821 - {  
822 - field: 'publicKey',  
823 - ifShow: false,  
824 - },  
825 - {  
826 - field: 'credentialsId',  
827 - ifShow: false,  
828 - },  
829 - ]);  
830 - } else {  
831 - updateSchema([  
832 - {  
833 - field: 'clientId',  
834 - ifShow: false,  
835 - },  
836 - {  
837 - field: 'username',  
838 - ifShow: false,  
839 - },  
840 - {  
841 - field: 'password',  
842 - ifShow: false,  
843 - },  
844 - {  
845 - field: 'publicKey',  
846 - ifShow: false,  
847 - },  
848 - {  
849 - field: 'credentialsId',  
850 - ifShow: false,  
851 - },  
852 - ]);  
853 - }  
854 - },  
855 - }; 138 + format: 'YYYY-MM-DD hh:mm:ss', // 设置日期格式
  139 + showTime: true, // 显示时间选择器
856 }, 140 },
857 }, 141 },
858 - {  
859 - label: t('deviceManagement.device.accessTokenText'),  
860 - component: 'Input',  
861 - field: 'credentialsId',  
862 - required: true,  
863 - ifShow: false,  
864 - slot: 'credentialsId', 142 +{
  143 + field: 'price',
  144 + label: t('equipment.ledger.priceText'),
  145 + component: 'InputNumber',
  146 + colProps: { span: 24 },
865 componentProps: { 147 componentProps: {
866 - maxLength: 36,  
867 }, 148 },
868 }, 149 },
869 { 150 {
870 - label: t('deviceManagement.device.rsaPublicKeyText'),  
871 - component: 'InputTextArea',  
872 - field: 'publicKey',  
873 - required: true,  
874 - ifShow: false, 151 + field: 'productDate',
  152 + label: t('equipment.ledger.productDate'),
  153 + component: 'DatePicker',
  154 + colProps: { span: 24 },
875 componentProps: { 155 componentProps: {
876 - rows: 8, 156 + format: 'YYYY-MM-DD hh:mm:ss', // 设置日期格式
  157 + showTime: true, // 显示时间选择器
877 }, 158 },
878 }, 159 },
879 { 160 {
880 - label: t('deviceManagement.device.clientIdText'),  
881 - component: 'Input',  
882 - field: 'clientId',  
883 - ifShow: false,  
884 - slot: 'clientId', 161 + field: 'receiveDate',
  162 + label: t('equipment.ledger.receiveDate'),
  163 + component: 'DatePicker',
  164 + colProps: { span: 24 },
885 componentProps: { 165 componentProps: {
886 - maxLength: 36, 166 + format: 'YYYY-MM-DD hh:mm:ss', // 设置日期格式
  167 + showTime: true, // 显示时间选择器
887 }, 168 },
888 }, 169 },
889 { 170 {
890 - label: t('deviceManagement.device.usernameText'),  
891 - component: 'Input',  
892 - field: 'username',  
893 - required: true,  
894 - ifShow: false, 171 + field: 'registeDate',
  172 + label: t('equipment.ledger.registeDate'),
  173 + component: 'DatePicker',
  174 + colProps: { span: 24 },
895 componentProps: { 175 componentProps: {
896 - maxLength: 255, 176 + format: 'YYYY-MM-DD hh:mm:ss', // 设置日期格式
  177 + showTime: true, // 显示时间选择器
897 }, 178 },
898 }, 179 },
899 { 180 {
900 - label: t('deviceManagement.device.passwordText'),  
901 - component: 'InputPassword',  
902 - field: 'password',  
903 - ifShow: false, 181 + field: 'supplierId',
  182 + component: 'OrgTreeSelect',
  183 + label: '供应商',
  184 + colProps: { span: 24 },
904 componentProps: { 185 componentProps: {
905 - maxLength: 36,  
906 - },  
907 - },  
908 - {  
909 - label: 'id',  
910 - component: 'Input',  
911 - field: 'id',  
912 - show: false,  
913 - componentProps: {  
914 - maxLength: 36,  
915 - placeholder: '请输入id', 186 + // 添加 change 事件
  187 + onChange: (value: string) => {
  188 + // 这里需要触发加载人员数据的逻辑
  189 + console.log(value,'value')
  190 + },
916 }, 191 },
917 }, 192 },
918 { 193 {
919 - label: 'tbDeviceId',  
920 - component: 'Input',  
921 - field: 'tbDeviceId',  
922 - show: false, 194 + field: 'description',
  195 + label: t('equipment.ledger.description'),
  196 + component: 'InputTextArea',
  197 + colProps: { span: 24 },
923 componentProps: { 198 componentProps: {
924 - maxLength: 36,  
925 - placeholder: '请输入tbDeviceId',  
926 - },  
927 - dynamicRules: () => {  
928 - return [  
929 - {  
930 - required: false,  
931 - validator: (_, value) => {  
932 - if (String(value).length > 36) {  
933 - return Promise.reject('字数不超过36个字');  
934 - }  
935 - return Promise.resolve();  
936 - },  
937 - },  
938 - ]; 199 + maxLength: 200,
939 }, 200 },
940 }, 201 },
  202 +
941 ]; 203 ];
  1 +export enum SchemaFiled {
  2 + WAY = 'queryMode',
  3 + TIME_PERIOD = 'timePeriod',
  4 + KEYS = 'keys',
  5 + DATE_RANGE = 'dataRange',
  6 + START_TS = 'startTs',
  7 + END_TS = 'endTs',
  8 + INTERVAL = 'interval',
  9 + LIMIT = 'limit',
  10 + AGG = 'agg',
  11 + ORDER_BY = 'orderBy',
  12 + DATA_TYPE = 'dataType',
  13 +}
1 -import { formatToDate } from '/@/utils/dateUtil';  
2 import { BasicColumn } from '/@/components/Table'; 1 import { BasicColumn } from '/@/components/Table';
3 import { FormSchema } from '/@/components/Table'; 2 import { FormSchema } from '/@/components/Table';
4 -import { DeviceRecord } from '/@/api/device/model/deviceModel';  
5 -// import { deviceProfile } from '/@/api/device/deviceManager';  
6 import { h } from 'vue'; 3 import { h } from 'vue';
7 -import { Tag, Tooltip } from 'ant-design-vue'; 4 +import { Tooltip } from 'ant-design-vue';
8 import { handeleCopy } from '../../../device/profiles/step/topic'; 5 import { handeleCopy } from '../../../device/profiles/step/topic';
9 import { useI18n } from '/@/hooks/web/useI18n'; 6 import { useI18n } from '/@/hooks/web/useI18n';
10 -import { DeviceStatusEnum, DeviceTypeEnum } from '/@/enums/deviceEnum'; 7 +import { SbStatusEnum } from '/@/enums/deviceEnum';
11 8
12 const { t } = useI18n(); 9 const { t } = useI18n();
13 import edgefornt from '/@/assets/icons/edgefornt.svg'; 10 import edgefornt from '/@/assets/icons/edgefornt.svg';
@@ -73,16 +70,15 @@ export enum DeviceListAuthEnum { @@ -73,16 +70,15 @@ export enum DeviceListAuthEnum {
73 export const columns: BasicColumn[] = [ 70 export const columns: BasicColumn[] = [
74 { 71 {
75 title: t('business.deviceStatusText'), 72 title: t('business.deviceStatusText'),
76 - dataIndex: 'deviceState', 73 + dataIndex: 'status',
77 width: 110, 74 width: 110,
78 className: 'device-status', 75 className: 'device-status',
79 - slots: { customRender: 'deviceState' }, 76 + slots: { customRender: 'status' },
80 }, 77 },
81 { 78 {
82 - title: t('business.deviceImageText'),  
83 - dataIndex: 'deviceInfo.avatar',  
84 - width: 70,  
85 - slots: { customRender: 'img' }, 79 + title: t('business.codeText'),
  80 + dataIndex: 'code',
  81 + width: 100,
86 }, 82 },
87 { 83 {
88 dataIndex: 'name', 84 dataIndex: 'name',
@@ -142,53 +138,18 @@ export const columns: BasicColumn[] = [ @@ -142,53 +138,18 @@ export const columns: BasicColumn[] = [
142 }, 138 },
143 { 139 {
144 title: t('business.deviceTypeText'), 140 title: t('business.deviceTypeText'),
145 - dataIndex: 'deviceType',  
146 - width: 130,  
147 - customRender({ text }) {  
148 - return h(Tag, { color: 'success' }, () => t(`enum.deviceType.${text}`));  
149 - },  
150 - },  
151 - {  
152 - title: t('business.affiliatedProductText'),  
153 - dataIndex: 'deviceProfile.name',  
154 - width: 180,  
155 - slots: { customRender: 'deviceProfile' },  
156 - ellipsis: true,  
157 - },  
158 - {  
159 - title: t('business.affiliatedOrganizationText'),  
160 - dataIndex: 'organizationDTO.name',  
161 - width: 100,  
162 - },  
163 - // {  
164 - // title: '客户',  
165 - // dataIndex: 'customerName',  
166 - // width: 100,  
167 - // },  
168 - {  
169 - title: t('business.publicText'),  
170 - dataIndex: 'public',  
171 - width: 100,  
172 - customRender({ record }: { record: DeviceRecord }) {  
173 - const flag = record?.customerAdditionalInfo?.isPublic;  
174 - return h(Tag, { color: flag ? 'blue' : 'orange' }, () =>  
175 - flag ? t('business.publicText') : t('business.privateText')  
176 - );  
177 - }, 141 + dataIndex: 'categoryName',
  142 + width: 120,
178 }, 143 },
179 { 144 {
180 - title: t('deviceManagement.device.lastOnlineTimeText'),  
181 - dataIndex: 'lastOnlineTime',  
182 - format: (text) => text && formatToDate(text, 'YYYY-MM-DD HH:mm:ss'),  
183 - width: 160, 145 + title: t('business.directorName'),
  146 + dataIndex: 'directorName',
  147 + width: 120,
184 }, 148 },
185 { 149 {
186 - title: t('deviceManagement.device.lastOfflineTimeText'),  
187 - dataIndex: 'lastOfflineTime',  
188 - format: (text) => {  
189 - return text ? formatToDate(text, 'YYYY-MM-DD HH:mm:ss') : '';  
190 - },  
191 - width: 160, 150 + title: t('business.brandText'),
  151 + dataIndex: 'brand',
  152 + width: 120,
192 }, 153 },
193 ]; 154 ];
194 155
@@ -204,24 +165,12 @@ export const searchFormSchema: FormSchema[] = [ @@ -204,24 +165,12 @@ export const searchFormSchema: FormSchema[] = [
204 }, 165 },
205 }, 166 },
206 { 167 {
207 - field: 'deviceType',  
208 - label: t('equipment.ledger.deviceType'),  
209 - component: 'Select',  
210 - componentProps: {  
211 - options: Object.values(DeviceTypeEnum).map((value) => ({  
212 - label: t(`enum.deviceType.${value}`),  
213 - value,  
214 - })),  
215 - },  
216 - colProps: { span: 6 },  
217 - },  
218 - {  
219 - field: 'deviceState', 168 + field: 'status',
220 label: t('business.deviceStatusText'), 169 label: t('business.deviceStatusText'),
221 component: 'Select', 170 component: 'Select',
222 componentProps: { 171 componentProps: {
223 - options: Object.values(DeviceStatusEnum).map((value) => ({  
224 - label: t(`enum.deviceStatus.${value}`), 172 + options: Object.values(SbStatusEnum).map((value) => ({
  173 + label: t(`enum.sbStatus.${value}`),
225 value, 174 value,
226 })), 175 })),
227 }, 176 },
1 <template> 1 <template>
2 <div> 2 <div>
3 <PageWrapper dense contentFullHeight contentClass="flex"> 3 <PageWrapper dense contentFullHeight contentClass="flex">
4 - <OrganizationIdTree @select="handleSelect" ref="organizationIdTreeRef" /> 4 + <OrganizationIdTree @select="handleSelect" ref="organizationIdTreeRef" listType="equipment"/>
5 <BasicTable style="flex: auto" @register="registerTable" class="w-5/6 xl:w-4/5 device-table"> 5 <BasicTable style="flex: auto" @register="registerTable" class="w-5/6 xl:w-4/5 device-table">
6 <template #toolbar> 6 <template #toolbar>
7 <Authority :value="DeviceListAuthEnum.CREATE"> 7 <Authority :value="DeviceListAuthEnum.CREATE">
8 - <a-button type="primary" @click="handleCreate" v-if="authBtn(role)"> 8 + <a-button type="primary" @click="handleBussinessDrawer('add', null)" v-if="authBtn(role)">
9 {{ t('equipment.ledger.createLedgerText') }} 9 {{ t('equipment.ledger.createLedgerText') }}
10 </a-button> 10 </a-button>
11 </Authority> 11 </Authority>
12 -  
13 - <Authority :value="DeviceListAuthEnum.IMPORT">  
14 - <Button type="primary" >  
15 - {{ t('equipment.ledger.importLedgerText') }}  
16 - </Button>  
17 - </Authority>  
18 -  
19 - <Authority  
20 - :value="[  
21 - DeviceListAuthEnum.DELETE,  
22 - DeviceListAuthEnum.ASSIGN,  
23 - DeviceListAuthEnum.UPDATE_PRODUCT,  
24 - ]"  
25 - >  
26 - <AuthDropDown  
27 - v-if="authBtn(role)"  
28 - :disabled="isPublicAndPrivateFlag || !isExistOption"  
29 - :dropMenuList="[  
30 - {  
31 - text: t('common.delText'),  
32 - auth: DeviceListAuthEnum.DELETE,  
33 - icon: 'ant-design:delete-outlined',  
34 - event: '',  
35 - disabled: !batchPrivateFlag,  
36 - popconfirm: {  
37 - title: t('common.deleteConfirmText'),  
38 - onConfirm: () => handleDelete(),  
39 - },  
40 - },  
41 - {  
42 - text: t('equipment.ledger.editProductText'),  
43 - auth: DeviceListAuthEnum.UPDATE_PRODUCT,  
44 - icon: 'clarity:note-edit-line',  
45 - event: '',  
46 - disabled: !batchPrivateFlag || batchUpdateProductFlag,  
47 - onClick: handelOpenBatchUpdateProductModal,  
48 - },  
49 - {  
50 - text: t('business.publicText'),  
51 - icon: 'ant-design:wallet-outlined',  
52 - event: '',  
53 - disabled: !batchPrivateFlag,  
54 - onClick: handleBatchPublic.bind(null),  
55 - },  
56 - {  
57 - text: t('business.privateText'),  
58 - icon: 'ant-design:wallet-outlined',  
59 - event: '',  
60 - disabled: batchPrivateFlag,  
61 - onClick: handleBatchPrivate.bind(null),  
62 - },  
63 - {  
64 - text: t('equipment.ledger.updateOrganization'),  
65 - icon: 'ant-design:wallet-outlined',  
66 - event: '',  
67 - disabled: !batchPrivateFlag || batchSensorFlag || diffBatchSensorFlag,  
68 - onClick: handleBatchOrg.bind(null),  
69 - },  
70 - ]"  
71 - >  
72 - <Button type="primary" :disabled="isPublicAndPrivateFlag || !isExistOption">  
73 - {{ t('equipment.ledger.batchActionText') }}  
74 - </Button>  
75 - </AuthDropDown>  
76 - </Authority>  
77 - </template>  
78 - <template #img="{ record }">  
79 - <TableImg  
80 - :size="30"  
81 - :showBadge="false"  
82 - :simpleShow="true"  
83 - :imgList="  
84 - typeof record?.deviceInfo?.avatar !== 'undefined' &&  
85 - record?.deviceInfo?.avatar !== '' &&  
86 - record?.deviceInfo?.avatar != null  
87 - ? [record.deviceInfo.avatar]  
88 - : null  
89 - "  
90 - />  
91 </template> 12 </template>
92 - <template #deviceProfile="{ record }">  
93 - <Button  
94 - @click="!isCustomer ? goDeviceProfile(record.deviceProfile.name) : null"  
95 - type="link"  
96 - >  
97 - {{ record.deviceProfile.name }}  
98 - </Button>  
99 - </template>  
100 - <template #deviceState="{ record }">  
101 - <div v-if="record.isCollect">  
102 - <div class="absolute top-0 left-0 device-collect"> </div>  
103 - <Icon  
104 - icon="ph:star-fill"  
105 - class="fill-light-50 absolute top-0.5 left-0.5"  
106 - color="#fff"  
107 - :size="12"  
108 - />  
109 - </div>  
110 - 13 + <template #status="{ record }">
111 <Tag 14 <Tag
112 :color=" 15 :color="
113 - record.deviceState == DeviceState.INACTIVE 16 + record.status == SbStatusEnum.SCRAP
114 ? 'warning' 17 ? 'warning'
115 - : record.deviceState == DeviceState.ONLINE  
116 - ? 'success'  
117 - : record.deviceState == DeviceState.ACTIVE 18 + : record.status == SbStatusEnum.NORMAL
118 ? 'success' 19 ? 'success'
  20 + : record.status == SbStatusEnum.FAULT
  21 + ? 'error'
119 : 'error' 22 : 'error'
120 " 23 "
121 class="ml-2" 24 class="ml-2"
122 > 25 >
123 - {{ t(`enum.deviceStatus.${record.deviceState}`) }} 26 + {{ t(`enum.sbStatus.${record.status}`) }}
124 </Tag> 27 </Tag>
125 </template> 28 </template>
126 <template #action="{ record }"> 29 <template #action="{ record }">
127 <TableAction 30 <TableAction
128 :actions="[ 31 :actions="[
129 - {  
130 - label: AlarmDetailActionButton({ hasAlarm: !!record.alarmStatus }),  
131 - icon: 'ant-design:eye-outlined',  
132 - auth: DeviceListAuthEnum.DETAIL,  
133 - // onClick: handleDetail.bind(null, record),  
134 - },  
135 - {  
136 - label: t('common.editText'),  
137 - auth: DeviceListAuthEnum.UPDATE,  
138 - icon: 'clarity:note-edit-line',  
139 - ifShow: authBtn(role),  
140 - // onClick: handleEdit.bind(null, record),  
141 - },  
142 - ]"  
143 - :dropDownActions="[  
144 - // record.customerId  
145 - // ? {  
146 - // label: t('deviceManagement.device.cancelAssignText'),  
147 - // icon: 'mdi:account-arrow-left',  
148 - // ifShow: authBtn(role) && !record?.customerAdditionalInfo?.isPublic,  
149 - // auth: DeviceListAuthEnum.ASSIGN,  
150 - // popConfirm: {  
151 - // title: t('deviceManagement.device.cancelAssignConfirmText'),  
152 - // confirm: handleCancelDispatchCustomer.bind(null, record),  
153 - // },  
154 - // }  
155 - // : {  
156 - // label: t('deviceManagement.device.assignCustomerText'),  
157 - // icon: 'mdi:account-arrow-right',  
158 - // ifShow: authBtn(role),  
159 - // auth: DeviceListAuthEnum.ASSIGN,  
160 - // onClick: handleDispatchCustomer.bind(null, record),  
161 - // },  
162 - {  
163 - label: record?.customerAdditionalInfo?.isPublic  
164 - ? t('business.privateText')  
165 - : t('business.publicText'),  
166 - auth: DeviceListAuthEnum.PUBLIC,  
167 - icon: record?.customerAdditionalInfo?.isPublic  
168 - ? 'ant-design:lock-outlined'  
169 - : 'ant-design:unlock-outlined',  
170 - // onClick: handlePublicDevice.bind(null, record),  
171 - },  
172 - {  
173 - label: t('deviceManagement.device.onlineRecordText'),  
174 - auth: DeviceListAuthEnum.ONLINE,  
175 - icon: 'ant-design:rise-outlined',  
176 - // onClick: handleUpAndDownRecord.bind(null, record), 32 + {
  33 + label: t('common.viewText'),
  34 + icon: 'ant-design:eye-outlined',
  35 + onClick: handleBussinessDrawer.bind(null, 'view', record),
  36 + },
  37 + {
  38 + label: t('common.editText'),
  39 + icon: 'clarity:note-edit-line',
  40 + onClick: handleBussinessDrawer.bind(null, 'edit', record),
  41 + },
  42 + {
  43 + label: t('common.delText'),
  44 + icon: 'ant-design:delete-outlined',
  45 + color: 'error',
  46 + popConfirm: {
  47 + title: t('common.isDelete'),
  48 + confirm: handleDelete.bind(null, record),
177 }, 49 },
178 - !record.isCollect  
179 - ? {  
180 - label: t('deviceManagement.device.collectText'),  
181 - icon: 'ant-design:heart-outlined',  
182 - // onClick: handelCollect.bind(null, record),  
183 - }  
184 - : {  
185 - label: t('deviceManagement.device.cancelCollectText'),  
186 - icon: 'ant-design:heart-outlined',  
187 - popConfirm: {  
188 - title: t('deviceManagement.device.cancelCollectConfirmText'),  
189 - // confirm: handelCollect.bind(null, record),  
190 - },  
191 - },  
192 - {  
193 - label: t('common.delText'),  
194 - auth: DeviceListAuthEnum.DELETE,  
195 - icon: 'ant-design:delete-outlined',  
196 - ifShow: authBtn(role) && record.customerId === undefined,  
197 - color: 'error',  
198 - popConfirm: {  
199 - title: !!record.isEdge  
200 - ? t('common.edgeDeviceOperationConfirm')  
201 - : t('common.deleteConfirmText'),  
202 - confirm: handleDelete.bind(null, record),  
203 - },  
204 - },  
205 - ]"  
206 - /> 50 + },
  51 + ]"
  52 + >
  53 + </TableAction>
207 </template> 54 </template>
208 </BasicTable> 55 </BasicTable>
209 -<!-- <LedgerDetailDrawer-->  
210 -<!-- @register="registerDetailDrawer"-->  
211 -<!-- @open-tb-device-detail="handleOpenTbDeviceDetail"-->  
212 -<!-- @open-gateway-device-detail="handleOpenGatewayDetail"-->  
213 -<!-- />--> 56 + <LedgerDrawer @register="registerDrawer" @success="handleSuccess" @reload="handleSuccess" />
214 </PageWrapper> 57 </PageWrapper>
215 </div> 58 </div>
216 </template> 59 </template>
217 <script setup lang="ts"> 60 <script setup lang="ts">
218 -import {CSSProperties, h, reactive, ref} from "vue"; 61 +import { reactive} from "vue";
219 import { PageWrapper } from '/@/components/Page'; 62 import { PageWrapper } from '/@/components/Page';
  63 +import { LedgerDrawer } from "./components/modal/index"
220 const searchInfo = reactive<Recordable>({}); 64 const searchInfo = reactive<Recordable>({});
221 -const { organizationIdTreeRef, resetFn } = useResetOrganizationTree(searchInfo);  
222 -import {BasicTable, TableAction, TableImg, useTable} from "/@/components/Table"; 65 +const { organizationIdTreeRef, resetFn } = useResetOrganizationTree(searchInfo,'equipment');
  66 +import {BasicTable, TableAction, useTable} from "/@/components/Table";
223 import {OrganizationIdTree, useResetOrganizationTree} from "/@/views/common/organizationIdTree"; 67 import {OrganizationIdTree, useResetOrganizationTree} from "/@/views/common/organizationIdTree";
224 -import {  
225 - deleteDevice,  
226 - devicePage,  
227 - doBatchPrivateDevice,  
228 - doBatchPublicDevice  
229 -} from "/@/api/device/deviceManager"; 68 +import { getLedgerList, deleteLedger } from "/@/api/equipment/ledger"
230 import { 69 import {
231 columns, 70 columns,
232 DeviceListAuthEnum, 71 DeviceListAuthEnum,
233 searchFormSchema 72 searchFormSchema
234 } from "/@/views/equipment/ledger/config/ledger.data"; 73 } from "/@/views/equipment/ledger/config/ledger.data";
235 -import {DeviceModel, DeviceRecord, DeviceState} from "/@/api/device/model/deviceModel"; 74 +import { SbStatusEnum } from '/@/enums/deviceEnum';
  75 +
236 import {useI18n} from "/@/hooks/web/useI18n"; 76 import {useI18n} from "/@/hooks/web/useI18n";
237 import {authBtn} from "/@/enums/roleEnum"; 77 import {authBtn} from "/@/enums/roleEnum";
238 -import {Badge, Button, Tag} from "ant-design-vue"; 78 +import {Button, Tag} from "ant-design-vue";
239 import {Authority} from "/@/components/Authority"; 79 import {Authority} from "/@/components/Authority";
240 -import {AuthDropDown} from "/@/components/Widget";  
241 import {getAuthCache} from "/@/utils/auth"; 80 import {getAuthCache} from "/@/utils/auth";
242 import {USER_INFO_KEY} from "/@/enums/cacheEnum"; 81 import {USER_INFO_KEY} from "/@/enums/cacheEnum";
243 -import {useBatchOperation} from "/@/utils/useBatchOperation";  
244 import {useMessage} from "/@/hooks/web/useMessage"; 82 import {useMessage} from "/@/hooks/web/useMessage";
245 -import {DataActionModeEnum} from "/@/enums/toolEnum";  
246 -import {  
247 - BatchUpdateProductModalParamsType  
248 -} from "/@/views/device/list/cpns/modal/BatchUpdateProductModal/index";  
249 -import {useModal} from "/@/components/Modal";  
250 -import Icon from "/@/components/Icon";  
251 -// import LedgerDetailDrawer from "./cpns/modal/LedgerDetailDrawer.vue"; 83 +
  84 +import {useDrawer} from "/@/components/Drawer";
  85 +
  86 +// 业务弹窗
  87 +const [registerDrawer, { openDrawer }] = useDrawer();
252 const { t } = useI18n(); 88 const { t } = useI18n();
253 const userInfo: any = getAuthCache(USER_INFO_KEY); 89 const userInfo: any = getAuthCache(USER_INFO_KEY);
254 const role: string = userInfo.roles[0]; 90 const role: string = userInfo.roles[0];
255 -const isPublicAndPrivateFlag = ref(false);  
256 -const batchPrivateFlag = ref(true);  
257 -const batchUpdateProductFlag = ref(true);  
258 -const batchSensorFlag = ref(false);  
259 -const { createMessage } = useMessage();  
260 -const diffBatchSensorFlag = ref(false);  
261 -const [registerOrgModal, { openModal: openOrgodal }] = useModal();  
262 -const [registerBatchUpdateProductModal, { openModal: openBatchUpdateProductModal }] = useModal();  
263 91
264 -const AlarmDetailActionButton = ({ hasAlarm }: { hasAlarm?: boolean }) =>  
265 - h(  
266 - Badge,  
267 - { offset: [0, -5] },  
268 - {  
269 - default: () => h('span', { style: { color: '#377dff' } }, t('common.detailText')),  
270 - count: () =>  
271 - h(  
272 - 'div',  
273 - {  
274 - style: {  
275 - visibility: hasAlarm ? 'visible' : 'hidden',  
276 - width: '14px',  
277 - height: '14px',  
278 - display: 'flex',  
279 - justifyContent: 'center',  
280 - alignItems: 'center',  
281 - border: '1px solid #f46161',  
282 - borderRadius: '50%',  
283 - } as CSSProperties,  
284 - },  
285 - h(Icon, { icon: 'mdi:bell-warning', color: '#f46161', size: 12 })  
286 - ),  
287 - }  
288 - ); 92 +const { createMessage } = useMessage();
289 93
290 const [ 94 const [
291 registerTable, 95 registerTable,
@@ -295,13 +99,13 @@ const [ @@ -295,13 +99,13 @@ const [
295 setSelectedRowKeys, 99 setSelectedRowKeys,
296 getForm, 100 getForm,
297 getSelectRowKeys, 101 getSelectRowKeys,
298 - getSelectRows, 102 + setProps,
299 getRowSelection, 103 getRowSelection,
300 clearSelectedRowKeys, 104 clearSelectedRowKeys,
301 }, 105 },
302 ] = useTable({ 106 ] = useTable({
303 title: t('equipment.ledger.ledgerListText'), 107 title: t('equipment.ledger.ledgerListText'),
304 - api: devicePage, 108 + api: getLedgerList,
305 columns, 109 columns,
306 beforeFetch: (params) => { 110 beforeFetch: (params) => {
307 const { deviceProfileId } = params; 111 const { deviceProfileId } = params;
@@ -327,7 +131,7 @@ const [ @@ -327,7 +131,7 @@ const [
327 rowKey: 'id', 131 rowKey: 'id',
328 searchInfo: searchInfo, 132 searchInfo: searchInfo,
329 clickToRowSelect: false, 133 clickToRowSelect: false,
330 - rowClassName: (record) => ((record as DeviceRecord).alarmStatus ? 'device-alarm-badge' : ''), 134 + rowClassName: (record) => ((record as any).alarmStatus ? 'device-alarm-badge' : ''),
331 actionColumn: { 135 actionColumn: {
332 width: 200, 136 width: 200,
333 title: t('common.actionText'), 137 title: t('common.actionText'),
@@ -336,126 +140,27 @@ const [ @@ -336,126 +140,27 @@ const [
336 }, 140 },
337 rowSelection: { 141 rowSelection: {
338 type: 'checkbox', 142 type: 'checkbox',
339 - getCheckboxProps: (record: DeviceModel) => {  
340 - return { disabled: !!record.customerId && record.customerName !== 'Public' };  
341 - },  
342 - onSelect(_record, _selected, selectedRows) {  
343 - const [firstItem] = selectedRows as DeviceRecord[];  
344 - const { deviceType } = firstItem || {};  
345 - batchUpdateProductFlag.value =  
346 - !selectedRows.length ||  
347 - !selectedRows.every((item) => (item as DeviceRecord).deviceType === deviceType);  
348 -  
349 - batchPrivateFlag.value = selectedRows.some((item: DeviceRecord) => !item?.customerId);  
350 - const filterSensor = selectedRows.map((filterItem: DeviceRecord) => filterItem.deviceType);  
351 - batchSensorFlag.value =  
352 - filterSensor.includes('SENSOR') &&  
353 - (filterSensor.includes('DIRECT_CONNECTION') || filterSensor.includes('GATEWAY')); // 网关子和直连设备或者网关设备,则禁用组织修改  
354 - const filterGatewayId = selectedRows  
355 - .filter((filterItem: DeviceRecord) => filterItem.deviceType === 'SENSOR')  
356 - .map((mapItem: DeviceRecord) => mapItem.gatewayId);  
357 - diffBatchSensorFlag.value = [...new Set(filterGatewayId)].length > 1; // 数组长度大于1,说明选择的网关子设备所属网关为多个,则禁用组织修改  
358 - isPublicAndPrivateFlag.value =  
359 - selectedRows.some((item: DeviceRecord) => !item?.customerId) &&  
360 - selectedRows.some((item: DeviceRecord) => item?.customerAdditionalInfo?.isPublic);  
361 - },  
362 - onSelectAll(_selected, selectedRows) {  
363 - const [firstItem] = selectedRows as DeviceRecord[];  
364 - const { deviceType } = firstItem || {};  
365 - batchUpdateProductFlag.value =  
366 - !selectedRows.length ||  
367 - !selectedRows.every((item) => (item as DeviceRecord).deviceType === deviceType);  
368 -  
369 - batchPrivateFlag.value = selectedRows.some((item) => !item?.customerId);  
370 - const filterSensor = selectedRows.map((filterItem) => filterItem.deviceType);  
371 - batchSensorFlag.value =  
372 - filterSensor.includes('SENSOR') &&  
373 - (filterSensor.includes('DIRECT_CONNECTION') || filterSensor.includes('GATEWAY')); // 网关子和直连设备或者网关设备,则禁用组织修改  
374 - const filterGatewayId = selectedRows  
375 - .filter((filterItem: DeviceRecord) => filterItem.deviceType === 'SENSOR')  
376 - .map((mapItem: DeviceRecord) => mapItem.gatewayId);  
377 - diffBatchSensorFlag.value = [...new Set(filterGatewayId)].length > 1; // 数组长度大于1,说明选择的网关子设备所属网关为多个,则禁用组织修改  
378 - isPublicAndPrivateFlag.value =  
379 - selectedRows.some((item) => !item?.customerId) &&  
380 - selectedRows.some((item) => item?.customerAdditionalInfo?.isPublic);  
381 - }, 143 + getCheckboxProps: (record: any) => {},
382 }, 144 },
383 }); 145 });
384 146
385 -const { isExistOption } = useBatchOperation(getRowSelection, setSelectedRowKeys);  
386 -function handleCreate() {  
387 - // openModal(true, {  
388 - // isUpdate: false,  
389 - // });  
390 -}  
391 147
392 -// 批量公开设备  
393 -const handleBatchPublic = async () => {  
394 - setLoading(true);  
395 - try {  
396 - const options = getSelectRows();  
397 - const tbDeviceIdJoinStr = options.map((item) => item.tbDeviceId).join(',');  
398 - const res = await doBatchPublicDevice(tbDeviceIdJoinStr);  
399 - createMessage.success(  
400 - res === '公开成功' ? t('common.publicSuccess') : t('common.publicError')  
401 - );  
402 - } finally {  
403 - handleReload();  
404 - setLoading(false);  
405 - } 148 +// 业务弹窗
  149 +const handleBussinessDrawer = (text, record) => {
  150 + const modalParams = {
  151 + text,
  152 + record,
  153 + };
  154 + openDrawer(true, modalParams);
406 }; 155 };
407 156
408 -function handleReload() {  
409 - setSelectedRowKeys([]);  
410 - handleSuccess();  
411 -}  
412 157
413 -// 批量私有设备  
414 -const handleBatchPrivate = async () => {  
415 - setLoading(true);  
416 - try {  
417 - const options = getSelectRows();  
418 - const tbDeviceIdJoinStr = options.map((item) => item.tbDeviceId).join(',');  
419 - const res = await doBatchPrivateDevice(tbDeviceIdJoinStr);  
420 - createMessage.success(  
421 - res === '私有成功' ? t('common.privateSuccess') : t('common.privateError')  
422 - );  
423 - } finally {  
424 - handleReload();  
425 - setLoading(false);  
426 - }  
427 -}; 158 +const handleDelete = async (record?: any) => {
  159 + let _id: string = record.id;
428 160
429 -const handleBatchOrg = () => {  
430 - const options = getSelectRows();  
431 - openOrgodal(true, options);  
432 -};  
433 -  
434 -const handelOpenBatchUpdateProductModal = () => {  
435 - const rows: DeviceRecord[] = getSelectRows();  
436 - const [firstItem] = rows;  
437 -  
438 - openBatchUpdateProductModal(true, {  
439 - mode: DataActionModeEnum.UPDATE,  
440 - record: {  
441 - sourceDeviceProfileName: firstItem.deviceProfile.name,  
442 - deviceType: firstItem.deviceType,  
443 - deviceIds: rows.map((item) => item.tbDeviceId),  
444 - deviceProfile: firstItem.deviceProfile,  
445 - },  
446 - } as BatchUpdateProductModalParamsType);  
447 -};  
448 -  
449 -const handleDelete = async (record?: DeviceRecord) => {  
450 - let ids: string[] = [];  
451 - if (record) {  
452 - ids.push(record.id);  
453 - } else {  
454 - ids = getSelectRowKeys();  
455 - }  
456 try { 161 try {
457 setLoading(true); 162 setLoading(true);
458 - await deleteDevice(ids); 163 + await deleteLedger({id: _id});
459 createMessage.success(t('common.deleteSuccessText')); 164 createMessage.success(t('common.deleteSuccessText'));
460 handleReload(); 165 handleReload();
461 } catch (error) { 166 } catch (error) {
@@ -465,12 +170,19 @@ const handleDelete = async (record?: DeviceRecord) => { @@ -465,12 +170,19 @@ const handleDelete = async (record?: DeviceRecord) => {
465 } 170 }
466 }; 171 };
467 172
  173 +
  174 +function handleReload() {
  175 + setSelectedRowKeys([]);
  176 + handleSuccess();
  177 +}
  178 +
  179 +
468 function handleSuccess() { 180 function handleSuccess() {
469 reload(); 181 reload();
470 } 182 }
471 183
472 function handleSelect(organization) { 184 function handleSelect(organization) {
473 - searchInfo.organizationId = organization; 185 + searchInfo.categoryId = organization;
474 handleSuccess(); 186 handleSuccess();
475 } 187 }
476 188