Commit 055fb44c1f650e3bbf74716eca7a908d7dcc6bd4

Authored by ww
2 parents c75b2494 36bebfb5

Merge branch 'main_dev' into feat/rule-engine-designer

Showing 100 changed files with 1383 additions and 334 deletions

Too many changes to show.

To preserve performance only 100 of 142 files are displayed.

@@ -127,6 +127,9 @@ export interface MasterDeviceList { @@ -127,6 +127,9 @@ export interface MasterDeviceList {
127 label?: string; 127 label?: string;
128 value?: string; 128 value?: string;
129 alias?: string; 129 alias?: string;
  130 + codeType?: string;
  131 + code?: string;
  132 + [key: string]: string | undefined;
130 } 133 }
131 134
132 export interface ComponentInfoDetail { 135 export interface ComponentInfoDetail {
@@ -167,6 +167,7 @@ export interface DeviceRecord { @@ -167,6 +167,7 @@ export interface DeviceRecord {
167 creator: string; 167 creator: string;
168 createTime: string; 168 createTime: string;
169 codeType?: string; 169 codeType?: string;
  170 + code?: string;
170 name: string; 171 name: string;
171 tenantId: string; 172 tenantId: string;
172 transportType: string; 173 transportType: string;
@@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
16 :formProps="getProps" 16 :formProps="getProps"
17 :allDefaultValues="defaultValueRef" 17 :allDefaultValues="defaultValueRef"
18 :formModel="formModel" 18 :formModel="formModel"
  19 + :validateFields="validateFields"
19 :setFormModel="setFormModel" 20 :setFormModel="setFormModel"
20 > 21 >
21 <template #[item]="data" v-for="item in Object.keys($slots)"> 22 <template #[item]="data" v-for="item in Object.keys($slots)">
@@ -229,10 +230,10 @@ @@ -229,10 +230,10 @@
229 230
230 function setFormModel(key: string, value: any) { 231 function setFormModel(key: string, value: any) {
231 formModel[key] = value; 232 formModel[key] = value;
232 - const { validateTrigger } = unref(getBindValue);  
233 - if (!validateTrigger || validateTrigger === 'change') {  
234 - validateFields([key]).catch((_) => {});  
235 - } 233 + // const { validateTrigger } = unref(getBindValue);
  234 + // if (!validateTrigger || validateTrigger === 'change') {
  235 + // validateFields([key]).catch((_) => {});
  236 + // }
236 } 237 }
237 238
238 function handleEnterPress(e: KeyboardEvent) { 239 function handleEnterPress(e: KeyboardEvent) {
@@ -14,6 +14,7 @@ @@ -14,6 +14,7 @@
14 import { upperFirst, cloneDeep } from 'lodash-es'; 14 import { upperFirst, cloneDeep } from 'lodash-es';
15 import { useItemLabelWidth } from '../hooks/useLabelWidth'; 15 import { useItemLabelWidth } from '../hooks/useLabelWidth';
16 import { useI18n } from '/@/hooks/web/useI18n'; 16 import { useI18n } from '/@/hooks/web/useI18n';
  17 + import { NamePath, ValidateOptions } from 'ant-design-vue/lib/form/interface';
17 18
18 export default defineComponent({ 19 export default defineComponent({
19 name: 'BasicFormItem', 20 name: 'BasicFormItem',
@@ -39,6 +40,12 @@ @@ -39,6 +40,12 @@
39 type: Function as PropType<(key: string, value: any) => void>, 40 type: Function as PropType<(key: string, value: any) => void>,
40 default: null, 41 default: null,
41 }, 42 },
  43 + validateFields: {
  44 + type: Function as PropType<
  45 + (nameList?: NamePath[], options?: ValidateOptions) => Promise<any>
  46 + >,
  47 + default: null,
  48 + },
42 tableAction: { 49 tableAction: {
43 type: Object as PropType<TableActionType>, 50 type: Object as PropType<TableActionType>,
44 }, 51 },
@@ -208,6 +215,7 @@ @@ -208,6 +215,7 @@
208 rules[characterInx].message || 215 rules[characterInx].message ||
209 t('component.form.maxTip', [rules[characterInx].max] as Recordable); 216 t('component.form.maxTip', [rules[characterInx].max] as Recordable);
210 } 217 }
  218 + rules.forEach((item) => !item.trigger && (item.trigger = 'change'));
211 return rules; 219 return rules;
212 } 220 }
213 221
@@ -234,6 +242,10 @@ @@ -234,6 +242,10 @@
234 const value = target ? (isCheck ? target.checked : target.value) : e; 242 const value = target ? (isCheck ? target.checked : target.value) : e;
235 props.setFormModel(field, value); 243 props.setFormModel(field, value);
236 }, 244 },
  245 + onBlur: (...args) => {
  246 + unref(getComponentsProps)?.onBlur?.(...args);
  247 + props.validateFields([field], { triggerName: 'blur' }).catch((_) => {});
  248 + },
237 }; 249 };
238 const Comp = componentMap.get(component) as ReturnType<typeof defineComponent>; 250 const Comp = componentMap.get(component) as ReturnType<typeof defineComponent>;
239 251
1 <script lang="ts" setup> 1 <script lang="ts" setup>
2 import { Button } from 'ant-design-vue'; 2 import { Button } from 'ant-design-vue';
3 - import { nextTick, ref, unref, watch } from 'vue'; 3 + import { nextTick, ref, watch } from 'vue';
4 import { BasicForm, useForm } from '/@/components/Form'; 4 import { BasicForm, useForm } from '/@/components/Form';
5 import { BasicModal } from '/@/components/Modal'; 5 import { BasicModal } from '/@/components/Modal';
6 import { PlusCircleOutlined } from '@ant-design/icons-vue'; 6 import { PlusCircleOutlined } from '@ant-design/icons-vue';
@@ -19,8 +19,6 @@ @@ -19,8 +19,6 @@
19 } 19 }
20 ); 20 );
21 21
22 - const dataType = ref(props.dataType); //获取数据类型  
23 -  
24 const emit = defineEmits(['update:value']); 22 const emit = defineEmits(['update:value']);
25 23
26 const [ 24 const [
@@ -46,15 +44,17 @@ @@ -46,15 +44,17 @@
46 show.value = false; 44 show.value = false;
47 }; 45 };
48 46
49 - watch(  
50 - () => props.dataType,  
51 - (value) => {  
52 - dataType.value = value; 47 + watch(show, async (value) => {
  48 + if (value) {
  49 + await nextTick();
53 updateSchema([ 50 updateSchema([
54 - { field: FormFieldsEnum.ZOOM_FACTOR, ifShow: unref(dataType) == 'BOOL' ? false : true }, 51 + {
  52 + field: FormFieldsEnum.ZOOM_FACTOR,
  53 + ifShow: props.dataType == DataTypeEnum.IS_BOOL ? false : true,
  54 + },
55 ]); 55 ]);
56 } 56 }
57 - ); 57 + });
58 58
59 watch( 59 watch(
60 () => props.value, 60 () => props.value,
1 import type { FormProps, FormActionType, UseFormReturnType, FormSchema } from '../types/form'; 1 import type { FormProps, FormActionType, UseFormReturnType, FormSchema } from '../types/form';
2 -import type { NamePath } from 'ant-design-vue/lib/form/interface'; 2 +import type { NamePath, ValidateOptions } from 'ant-design-vue/lib/form/interface';
3 import type { DynamicProps } from '/#/utils'; 3 import type { DynamicProps } from '/#/utils';
4 import { ref, onUnmounted, unref, nextTick, watch } from 'vue'; 4 import { ref, onUnmounted, unref, nextTick, watch } from 'vue';
5 import { isProdMode } from '/@/utils/env'; 5 import { isProdMode } from '/@/utils/env';
@@ -112,9 +112,12 @@ export function useForm(props?: Props): UseFormReturnType { @@ -112,9 +112,12 @@ export function useForm(props?: Props): UseFormReturnType {
112 return form.validate(nameList); 112 return form.validate(nameList);
113 }, 113 },
114 114
115 - validateFields: async (nameList?: NamePath[]): Promise<Recordable> => { 115 + validateFields: async (
  116 + nameList?: NamePath[],
  117 + options?: ValidateOptions
  118 + ): Promise<Recordable> => {
116 const form = await getForm(); 119 const form = await getForm();
117 - return form.validateFields(nameList); 120 + return form.validateFields(nameList, options);
118 }, 121 },
119 }; 122 };
120 123
1 import type { ComputedRef, Ref } from 'vue'; 1 import type { ComputedRef, Ref } from 'vue';
2 import type { FormProps, FormSchema, FormActionType } from '../types/form'; 2 import type { FormProps, FormSchema, FormActionType } from '../types/form';
3 -import type { NamePath } from 'ant-design-vue/lib/form/interface'; 3 +import type { NamePath, ValidateOptions } from 'ant-design-vue/lib/form/interface';
4 import { unref, toRaw } from 'vue'; 4 import { unref, toRaw } from 'vue';
5 import { isArray, isFunction, isObject, isString } from '/@/utils/is'; 5 import { isArray, isFunction, isObject, isString } from '/@/utils/is';
6 import { deepMerge } from '/@/utils'; 6 import { deepMerge } from '/@/utils';
@@ -206,8 +206,8 @@ export function useFormEvents({ @@ -206,8 +206,8 @@ export function useFormEvents({
206 }); 206 });
207 } 207 }
208 208
209 - async function validateFields(nameList?: NamePath[] | undefined) {  
210 - return unref(formElRef)?.validateFields(nameList); 209 + async function validateFields(nameList?: NamePath[] | undefined, options?: ValidateOptions) {
  210 + return unref(formElRef)?.validateFields(nameList, options);
211 } 211 }
212 212
213 async function validate(nameList?: NamePath[] | undefined) { 213 async function validate(nameList?: NamePath[] | undefined) {
1 -import type { NamePath, RuleObject } from 'ant-design-vue/lib/form/interface'; 1 +import type { NamePath, RuleObject, ValidateOptions } from 'ant-design-vue/lib/form/interface';
2 import type { VNode } from 'vue'; 2 import type { VNode } from 'vue';
3 import type { ButtonProps as AntdButtonProps } from '/@/components/Button'; 3 import type { ButtonProps as AntdButtonProps } from '/@/components/Button';
4 import type { FormItem } from './formItem'; 4 import type { FormItem } from './formItem';
@@ -39,7 +39,7 @@ export interface FormActionType { @@ -39,7 +39,7 @@ export interface FormActionType {
39 prefixField: string | undefined, 39 prefixField: string | undefined,
40 first?: boolean | undefined 40 first?: boolean | undefined
41 ) => Promise<void>; 41 ) => Promise<void>;
42 - validateFields: (nameList?: NamePath[]) => Promise<any>; 42 + validateFields: (nameList?: NamePath[], options?: ValidateOptions) => Promise<any>;
43 validate: (nameList?: NamePath[]) => Promise<any>; 43 validate: (nameList?: NamePath[]) => Promise<any>;
44 scrollToField: (name: NamePath, options?: ScrollOptions) => Promise<void>; 44 scrollToField: (name: NamePath, options?: ScrollOptions) => Promise<void>;
45 } 45 }
@@ -33,6 +33,7 @@ @@ -33,6 +33,7 @@
33 import { openWindow } from '/@/utils'; 33 import { openWindow } from '/@/utils';
34 34
35 import { useOpenKeys } from './useOpenKeys'; 35 import { useOpenKeys } from './useOpenKeys';
  36 + import { useMenuActiveFix } from '/@/hooks/business/useMenuActiveFix';
36 export default defineComponent({ 37 export default defineComponent({
37 name: 'SimpleMenu', 38 name: 'SimpleMenu',
38 components: { 39 components: {
@@ -120,7 +121,9 @@ @@ -120,7 +121,9 @@
120 isClickGo.value = false; 121 isClickGo.value = false;
121 return; 122 return;
122 } 123 }
123 - const path = (route || unref(currentRoute)).path; 124 +
  125 + let { flag, path } = useMenuActiveFix(route || unref(currentRoute));
  126 + path = flag ? path : (route || unref(currentRoute)).path;
124 127
125 menuState.activeName = path; 128 menuState.activeName = path;
126 129
@@ -29,7 +29,6 @@ export function useOpenKeys( @@ -29,7 +29,6 @@ export function useOpenKeys(
29 return; 29 return;
30 } 30 }
31 const keys = getAllParentPath(menuList, path); 31 const keys = getAllParentPath(menuList, path);
32 -  
33 if (!unref(accordion)) { 32 if (!unref(accordion)) {
34 menuState.openNames = uniq([...menuState.openNames, ...keys]); 33 menuState.openNames = uniq([...menuState.openNames, ...keys]);
35 } else { 34 } else {
@@ -48,6 +48,7 @@ @@ -48,6 +48,7 @@
48 'update:value', 48 'update:value',
49 'change', 49 'change',
50 'check', 50 'check',
  51 + 'unSelectAll',
51 'update:searchValue', 52 'update:searchValue',
52 ], 53 ],
53 setup(props, { attrs, slots, emit, expose }) { 54 setup(props, { attrs, slots, emit, expose }) {
@@ -188,6 +189,7 @@ @@ -188,6 +189,7 @@
188 } 189 }
189 190
190 function checkAll(checkAll: boolean) { 191 function checkAll(checkAll: boolean) {
  192 + if (!checkAll) emit('unSelectAll');
191 state.checkedKeys = checkAll ? getEnabledKeys() : ([] as Keys); 193 state.checkedKeys = checkAll ? getEnabledKeys() : ([] as Keys);
192 } 194 }
193 195
@@ -2,17 +2,23 @@ @@ -2,17 +2,23 @@
2 import { isNumber } from 'lodash'; 2 import { isNumber } from 'lodash';
3 import videoJs, { VideoJsPlayer, VideoJsPlayerOptions } from 'video.js'; 3 import videoJs, { VideoJsPlayer, VideoJsPlayerOptions } from 'video.js';
4 import 'video.js/dist/video-js.css'; 4 import 'video.js/dist/video-js.css';
5 - import { computed, CSSProperties, onMounted, onUnmounted, ref, unref } from 'vue'; 5 + import { computed, CSSProperties, onMounted, onUnmounted, ref, toRaw, unref } from 'vue';
6 import { useDesign } from '/@/hooks/web/useDesign'; 6 import { useDesign } from '/@/hooks/web/useDesign';
7 import { getJwtToken, getShareJwtToken } from '/@/utils/auth'; 7 import { getJwtToken, getShareJwtToken } from '/@/utils/auth';
8 import { isShareMode } from '/@/views/sys/share/hook'; 8 import { isShareMode } from '/@/views/sys/share/hook';
9 import 'videojs-flvjs-es6'; 9 import 'videojs-flvjs-es6';
10 const { prefixCls } = useDesign('basic-video-play'); 10 const { prefixCls } = useDesign('basic-video-play');
11 11
12 - const props = defineProps<{  
13 - options?: VideoJsPlayerOptions;  
14 - withToken?: boolean;  
15 - }>(); 12 + const props = withDefaults(
  13 + defineProps<{
  14 + options?: VideoJsPlayerOptions;
  15 + withToken?: boolean;
  16 + immediateInitOnMounted?: boolean;
  17 + }>(),
  18 + {
  19 + immediateInitOnMounted: true,
  20 + }
  21 + );
16 22
17 const emit = defineEmits<{ 23 const emit = defineEmits<{
18 (event: 'ready', instance?: Nullable<VideoJsPlayer>): void; 24 (event: 'ready', instance?: Nullable<VideoJsPlayer>): void;
@@ -68,8 +74,18 @@ @@ -68,8 +74,18 @@
68 }); 74 });
69 }; 75 };
70 76
  77 + const customInit = (getOptionsFn: (optios: VideoJsPlayerOptions) => VideoJsPlayerOptions) => {
  78 + return (videoPlayInstance.value = videoJs(
  79 + unref(videoPlayEl)!,
  80 + getOptionsFn(toRaw(unref(getOptions))),
  81 + () => {
  82 + emit('ready', unref(videoPlayInstance));
  83 + }
  84 + ));
  85 + };
  86 +
71 onMounted(() => { 87 onMounted(() => {
72 - init(); 88 + props.immediateInitOnMounted && init();
73 }); 89 });
74 90
75 onUnmounted(() => { 91 onUnmounted(() => {
@@ -79,6 +95,7 @@ @@ -79,6 +95,7 @@
79 }); 95 });
80 96
81 defineExpose({ 97 defineExpose({
  98 + customInit,
82 reloadPlayer: init, 99 reloadPlayer: init,
83 getInstance: () => unref(videoPlayInstance), 100 getInstance: () => unref(videoPlayInstance),
84 }); 101 });
  1 +import { RouteLocationNormalizedLoaded } from 'vue-router';
  2 +
  3 +const menuMap = new Map();
  4 +
  5 +menuMap.set('/visual/board/detail/:boardId/:boardName?', '/visual/board');
  6 +
  7 +export const useMenuActiveFix = (route: RouteLocationNormalizedLoaded) => {
  8 + let flag = false;
  9 + let path;
  10 +
  11 + const matchPath = route.matched.map((item) => item.path);
  12 + const needFixMenus: string[] = Array.from(menuMap.keys());
  13 +
  14 + for (const item of matchPath) {
  15 + for (const menu of needFixMenus) {
  16 + if (menu === item) {
  17 + flag = true;
  18 + path = menuMap.get(menu);
  19 + break;
  20 + }
  21 + }
  22 + }
  23 +
  24 + return {
  25 + flag,
  26 + path,
  27 + };
  28 +};
@@ -54,10 +54,11 @@ @@ -54,10 +54,11 @@
54 field: FiledKey.WEBSITE, 54 field: FiledKey.WEBSITE,
55 label: handleDecode(t('routes.aboutSoftware.websiteLabel')), 55 label: handleDecode(t('routes.aboutSoftware.websiteLabel')),
56 render: (val: string) => { 56 render: (val: string) => {
  57 + let joinWww = val.substring(0, 8) + 'www.' + val.substring(8);
57 return h( 58 return h(
58 'span', 59 'span',
59 - { class: 'text-blue-500 cursor-pointer', onClick: () => open(val) },  
60 - val 60 + { class: 'text-blue-500 cursor-pointer', onClick: () => open(joinWww) },
  61 + joinWww
61 ); 62 );
62 }, 63 },
63 }, 64 },
@@ -19,6 +19,7 @@ @@ -19,6 +19,7 @@
19 import { useRootSetting } from '/@/hooks/setting/useRootSetting'; 19 import { useRootSetting } from '/@/hooks/setting/useRootSetting';
20 import { useAppInject } from '/@/hooks/web/useAppInject'; 20 import { useAppInject } from '/@/hooks/web/useAppInject';
21 import { useDesign } from '/@/hooks/web/useDesign'; 21 import { useDesign } from '/@/hooks/web/useDesign';
  22 + import { OUTSIDE_LINK_PREFIX } from '/@/router/helper/routeHelper';
22 23
23 export default defineComponent({ 24 export default defineComponent({
24 name: 'LayoutMenu', 25 name: 'LayoutMenu',
@@ -113,6 +114,11 @@ @@ -113,6 +114,11 @@
113 */ 114 */
114 115
115 function handleMenuClick(path: string) { 116 function handleMenuClick(path: string) {
  117 + if (path.startsWith(OUTSIDE_LINK_PREFIX)) {
  118 + path = path.replace(OUTSIDE_LINK_PREFIX, '');
  119 + window.open(path);
  120 + return;
  121 + }
116 go(path); 122 go(path);
117 } 123 }
118 124
@@ -183,7 +189,6 @@ @@ -183,7 +189,6 @@
183 padding: 10px 4px 10px 10px; 189 padding: 10px 4px 10px 10px;
184 190
185 img { 191 img {
186 - width: @logo-width;  
187 height: @logo-width; 192 height: @logo-width;
188 } 193 }
189 } 194 }
@@ -6,6 +6,7 @@ import { cloneDeep, omit } from 'lodash-es'; @@ -6,6 +6,7 @@ import { cloneDeep, omit } from 'lodash-es';
6 import { warn } from '/@/utils/log'; 6 import { warn } from '/@/utils/log';
7 import { createRouter, createWebHashHistory } from 'vue-router'; 7 import { createRouter, createWebHashHistory } from 'vue-router';
8 8
  9 +export const OUTSIDE_LINK_PREFIX = '/outside/link';
9 export type LayoutMapKey = 'LAYOUT'; 10 export type LayoutMapKey = 'LAYOUT';
10 const IFRAME = () => import('/@/views/sys/iframe/FrameBlank.vue'); 11 const IFRAME = () => import('/@/views/sys/iframe/FrameBlank.vue');
11 12
@@ -81,6 +82,9 @@ export function transformObjToRoute<T = AppRouteModule>(routeList: AppRouteModul @@ -81,6 +82,9 @@ export function transformObjToRoute<T = AppRouteModule>(routeList: AppRouteModul
81 route.meta = meta; 82 route.meta = meta;
82 } 83 }
83 } 84 }
  85 + if (!route.path.startsWith('/') && route.meta.isLink) {
  86 + route.path = `${OUTSIDE_LINK_PREFIX}${route.path}`;
  87 + }
84 route.children && asyncImportRoute(route.children); 88 route.children && asyncImportRoute(route.children);
85 }); 89 });
86 return routeList as unknown as T[]; 90 return routeList as unknown as T[];
@@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
16 mode="multiple" 16 mode="multiple"
17 v-model:value="model[field]" 17 v-model:value="model[field]"
18 :options="alarmContactOptions.map((item) => ({ value: item.value, label: item.label }))" 18 :options="alarmContactOptions.map((item) => ({ value: item.value, label: item.label }))"
  19 + @change="handleChange"
19 > 20 >
20 <template #dropdownRender="{ menuNode: menu }"> 21 <template #dropdownRender="{ menuNode: menu }">
21 <v-nodes :vnodes="menu" /> 22 <v-nodes :vnodes="menu" />
@@ -82,6 +83,7 @@ @@ -82,6 +83,7 @@
82 const [registerAlarmContactDrawer, { openDrawer }] = useDrawer(); 83 const [registerAlarmContactDrawer, { openDrawer }] = useDrawer();
83 async function handleSuccess() { 84 async function handleSuccess() {
84 //获取告警联系人 85 //获取告警联系人
  86 + if (!unref(orgId)) return;
85 const res = await byOrgIdGetAlarmContact(orgId.value); 87 const res = await byOrgIdGetAlarmContact(orgId.value);
86 if (res) { 88 if (res) {
87 alarmContactOptions.value = res.map((m) => { 89 alarmContactOptions.value = res.map((m) => {
@@ -91,6 +93,10 @@ @@ -91,6 +93,10 @@
91 alarmContactOptions.value = []; 93 alarmContactOptions.value = [];
92 } 94 }
93 } 95 }
  96 +
  97 + const handleChange = () => {
  98 + validateFields(['alarmContactId']);
  99 + };
94 // 新增或编辑 100 // 新增或编辑
95 const handleOpenAlarmContact = () => { 101 const handleOpenAlarmContact = () => {
96 openDrawer(true, { 102 openDrawer(true, {
@@ -100,7 +106,10 @@ @@ -100,7 +106,10 @@
100 const isUpdate = ref(true); 106 const isUpdate = ref(true);
101 let allData: any = reactive({}); 107 let allData: any = reactive({});
102 const editId = ref(''); 108 const editId = ref('');
103 - const [registerForm, { validate, setFieldsValue, resetFields, updateSchema }] = useForm({ 109 + const [
  110 + registerForm,
  111 + { validate, setFieldsValue, resetFields, updateSchema, validateFields },
  112 + ] = useForm({
104 labelWidth: 120, 113 labelWidth: 120,
105 schemas: formSchema, 114 schemas: formSchema,
106 showActionButtonGroup: false, 115 showActionButtonGroup: false,
@@ -191,6 +200,7 @@ @@ -191,6 +200,7 @@
191 handleOpenAlarmContact, 200 handleOpenAlarmContact,
192 registerAlarmContactDrawer, 201 registerAlarmContactDrawer,
193 handleSuccess, 202 handleSuccess,
  203 + handleChange,
194 }; 204 };
195 }, 205 },
196 }); 206 });
@@ -37,13 +37,21 @@ @@ -37,13 +37,21 @@
37 </a-button> 37 </a-button>
38 </template> 38 </template>
39 <template #status="{ record }"> 39 <template #status="{ record }">
40 - <Switch  
41 - :checked="record.status === 1"  
42 - :loading="record.pendingStatus"  
43 - checkedChildren="启用"  
44 - unCheckedChildren="禁用"  
45 - @change="(checked:boolean)=>statusChange(checked,record)"  
46 - /> 40 + <Authority value="api:yt:alarm:profile:status">
  41 + <Switch
  42 + :checked="record.status === 1"
  43 + :loading="record.pendingStatus"
  44 + checkedChildren="启用"
  45 + unCheckedChildren="禁用"
  46 + @change="(checked:boolean)=>statusChange(checked,record)"
  47 + />
  48 + </Authority>
  49 + <Tag
  50 + v-if="!hasPermission('api:yt:alarm:profile:status')"
  51 + :color="record.status ? 'green' : 'red'"
  52 + >
  53 + {{ record.status ? '启用' : '禁用' }}
  54 + </Tag>
47 </template> 55 </template>
48 <template #action="{ record }"> 56 <template #action="{ record }">
49 <TableAction 57 <TableAction
@@ -88,7 +96,7 @@ @@ -88,7 +96,7 @@
88 import { useResetOrganizationTree, OrganizationIdTree } from '/@/views/common/organizationIdTree'; 96 import { useResetOrganizationTree, OrganizationIdTree } from '/@/views/common/organizationIdTree';
89 import { deleteAlarmConfig, queryAlarmConfig } from '/@/api/alarm/config/alarmConfig'; 97 import { deleteAlarmConfig, queryAlarmConfig } from '/@/api/alarm/config/alarmConfig';
90 import { searchFormSchema, columns } from './config.data'; 98 import { searchFormSchema, columns } from './config.data';
91 - import { Modal, Popconfirm } from 'ant-design-vue'; 99 + import { Modal, Popconfirm, Tag } from 'ant-design-vue';
92 import { JsonPreview } from '/@/components/CodeEditor'; 100 import { JsonPreview } from '/@/components/CodeEditor';
93 import { findDictItemByCode } from '/@/api/system/dict'; 101 import { findDictItemByCode } from '/@/api/system/dict';
94 import { alarmContactGetPage } from '/@/api/device/deviceConfigApi'; 102 import { alarmContactGetPage } from '/@/api/device/deviceConfigApi';
@@ -97,6 +105,7 @@ @@ -97,6 +105,7 @@
97 import { putAlarmConfigStatus } from '/@/api/alarm/config/alarmConfig'; 105 import { putAlarmConfigStatus } from '/@/api/alarm/config/alarmConfig';
98 import { useMessage } from '/@/hooks/web/useMessage'; 106 import { useMessage } from '/@/hooks/web/useMessage';
99 import { Authority } from '/@/components/Authority'; 107 import { Authority } from '/@/components/Authority';
  108 + import { usePermission } from '/@/hooks/web/usePermission';
100 109
101 export default defineComponent({ 110 export default defineComponent({
102 components: { 111 components: {
@@ -108,8 +117,10 @@ @@ -108,8 +117,10 @@
108 Switch, 117 Switch,
109 Authority, 118 Authority,
110 Popconfirm, 119 Popconfirm,
  120 + Tag,
111 }, 121 },
112 setup() { 122 setup() {
  123 + const { hasPermission } = usePermission();
113 const searchInfo = reactive<Recordable>({}); 124 const searchInfo = reactive<Recordable>({});
114 const { organizationIdTreeRef, resetFn } = useResetOrganizationTree(searchInfo); 125 const { organizationIdTreeRef, resetFn } = useResetOrganizationTree(searchInfo);
115 // 刷新 126 // 刷新
@@ -250,6 +261,7 @@ @@ -250,6 +261,7 @@
250 showAlarmContact, 261 showAlarmContact,
251 showMessageMode, 262 showMessageMode,
252 statusChange, 263 statusChange,
  264 + hasPermission,
253 }; 265 };
254 }, 266 },
255 }); 267 });
@@ -17,10 +17,21 @@ export enum ConfigurationPermission { @@ -17,10 +17,21 @@ export enum ConfigurationPermission {
17 UPDATE = 'api:yt:dataview:center:update', 17 UPDATE = 'api:yt:dataview:center:update',
18 DELETE = 'api:yt:dataview:center:delete', 18 DELETE = 'api:yt:dataview:center:delete',
19 SHARE = 'api:yt:dataview:center:share', 19 SHARE = 'api:yt:dataview:center:share',
20 - DESIGN = 'api:yt:dataview:center:get_configuration_info:design', 20 + // DESIGN = 'api:yt:dataview:center:get_configuration_info:design',
  21 + DESIGN = 'api:yt:dataview:center:get_dataview_info:design',
21 PREVIEW = 'api:yt:dataview:center:get_configuration_info:preview', 22 PREVIEW = 'api:yt:dataview:center:get_configuration_info:preview',
22 PUBLISH = 'api:yt:dataview:center:publish', 23 PUBLISH = 'api:yt:dataview:center:publish',
23 // CANCEL_PUBLISH = 'api:yt:dataview:center:cancel_publish', 24 // CANCEL_PUBLISH = 'api:yt:dataview:center:cancel_publish',
  25 + PUBLISH_INTERFACE = 'api:yt:dataview:center:public_interface',
  26 +}
  27 +
  28 +export enum PublicInterface {
  29 + CREATE = 'api:yt:dataview:center:public_interface:post',
  30 + LIST = 'api:yt:dataview:center:public_interface:list',
  31 + UPDATE = 'api:yt:dataview:center:public_interface:update',
  32 + DELETE = 'api:yt:dataview:center:public_interface:delete',
  33 + PUBLISH = 'api:yt:dataview:center:public_interface:publish',
  34 + CANCEL_PUBLISH = 'api:yt:dataview:center:public_interface:cancel',
24 } 35 }
25 36
26 // 查询字段 37 // 查询字段
@@ -218,7 +218,10 @@ @@ -218,7 +218,10 @@
218 <Authority v-if="!isCustomerUser" :value="ConfigurationPermission.CREATE"> 218 <Authority v-if="!isCustomerUser" :value="ConfigurationPermission.CREATE">
219 <Button type="primary" @click="handleCreateOrUpdate()"> 新增大屏 </Button> 219 <Button type="primary" @click="handleCreateOrUpdate()"> 新增大屏 </Button>
220 </Authority> 220 </Authority>
221 - <Authority v-if="hasPublicInterfacePermission" :value="ConfigurationPermission.CREATE"> 221 + <Authority
  222 + v-if="hasPublicInterfacePermission"
  223 + :value="ConfigurationPermission.PUBLISH_INTERFACE"
  224 + >
222 <Button type="primary" @click="handleCreateOrUpdatePublicApi()">公共接口管理</Button> 225 <Button type="primary" @click="handleCreateOrUpdatePublicApi()">公共接口管理</Button>
223 </Authority> 226 </Authority>
224 <CardLayoutButton v-model:value="listColumn" @change="handleCardLayoutChange" /> 227 <CardLayoutButton v-model:value="listColumn" @change="handleCardLayoutChange" />
@@ -280,6 +283,7 @@ @@ -280,6 +283,7 @@
280 </Tooltip> 283 </Tooltip>
281 <Tooltip v-if="!isCustomerUser" title="设计"> 284 <Tooltip v-if="!isCustomerUser" title="设计">
282 <AuthIcon 285 <AuthIcon
  286 + :auth="ConfigurationPermission.DESIGN"
283 :disabled="item.state === 1" 287 :disabled="item.state === 1"
284 icon="ant-design:edit-outlined" 288 icon="ant-design:edit-outlined"
285 @click="handleDesign(item)" 289 @click="handleDesign(item)"
@@ -9,23 +9,30 @@ @@ -9,23 +9,30 @@
9 <a-button type="link" class="ml-2" @click="handleRecordContent(record)"> 查看 </a-button> 9 <a-button type="link" class="ml-2" @click="handleRecordContent(record)"> 查看 </a-button>
10 </template> 10 </template>
11 <template #toolbar> 11 <template #toolbar>
12 - <a-button type="primary" @click="handleCreateOrEdit(null)"> 新增公共接口 </a-button>  
13 - <Popconfirm  
14 - title="您确定要批量删除数据"  
15 - ok-text="确定"  
16 - cancel-text="取消"  
17 - @confirm="handleDeleteOrBatchDelete(null)"  
18 - >  
19 - <a-button color="error" :disabled="hasBatchDelete"> 批量删除 </a-button>  
20 - </Popconfirm>  
21 - <Popconfirm  
22 - title="您确定要批量发布"  
23 - ok-text="确定"  
24 - cancel-text="取消"  
25 - @confirm="handleBatchPublish('batchPublish')"  
26 - >  
27 - <a-button color="error" :disabled="hasBatchPublish"> 批量发布 </a-button>  
28 - </Popconfirm> 12 + <Authority :value="PublicInterface.CREATE">
  13 + <a-button type="primary" @click="handleCreateOrEdit(null)"> 新增公共接口 </a-button>
  14 + </Authority>
  15 +
  16 + <Authority :value="PublicInterface.DELETE">
  17 + <Popconfirm
  18 + title="您确定要批量删除数据"
  19 + ok-text="确定"
  20 + cancel-text="取消"
  21 + @confirm="handleDeleteOrBatchDelete(null)"
  22 + >
  23 + <a-button color="error" :disabled="hasBatchDelete"> 批量删除 </a-button>
  24 + </Popconfirm>
  25 + </Authority>
  26 + <Authority :value="PublicInterface.PUBLISH">
  27 + <Popconfirm
  28 + title="您确定要批量发布"
  29 + ok-text="确定"
  30 + cancel-text="取消"
  31 + @confirm="handleBatchPublish('batchPublish')"
  32 + >
  33 + <a-button color="error" :disabled="hasBatchPublish"> 批量发布 </a-button>
  34 + </Popconfirm>
  35 + </Authority>
29 <!-- <Popconfirm 36 <!-- <Popconfirm
30 title="您确定要批量取消发布" 37 title="您确定要批量取消发布"
31 ok-text="确定" 38 ok-text="确定"
@@ -41,6 +48,7 @@ @@ -41,6 +48,7 @@
41 { 48 {
42 label: '发布', 49 label: '发布',
43 icon: 'ant-design:node-expand-outlined', 50 icon: 'ant-design:node-expand-outlined',
  51 + auth: PublicInterface.PUBLISH,
44 onClick: handlePublish.bind(null, 'publish', record), 52 onClick: handlePublish.bind(null, 'publish', record),
45 ifShow: () => { 53 ifShow: () => {
46 return record.state === 0 && record.creator === userId; 54 return record.state === 0 && record.creator === userId;
@@ -49,6 +57,7 @@ @@ -49,6 +57,7 @@
49 { 57 {
50 label: '取消发布', 58 label: '取消发布',
51 icon: 'ant-design:node-collapse-outlined', 59 icon: 'ant-design:node-collapse-outlined',
  60 + auth: PublicInterface.CANCEL_PUBLISH,
52 onClick: handlePublish.bind(null, 'canelPublish', record), 61 onClick: handlePublish.bind(null, 'canelPublish', record),
53 ifShow: () => { 62 ifShow: () => {
54 return record.state === 1 && record.creator === userId; 63 return record.state === 1 && record.creator === userId;
@@ -57,6 +66,7 @@ @@ -57,6 +66,7 @@
57 { 66 {
58 label: '修改', 67 label: '修改',
59 icon: 'clarity:note-edit-line', 68 icon: 'clarity:note-edit-line',
  69 + auth: PublicInterface.UPDATE,
60 onClick: handleCreateOrEdit.bind(null, record), 70 onClick: handleCreateOrEdit.bind(null, record),
61 ifShow: () => { 71 ifShow: () => {
62 return record.state === 0 && record.creator === userId; 72 return record.state === 0 && record.creator === userId;
@@ -65,6 +75,7 @@ @@ -65,6 +75,7 @@
65 { 75 {
66 label: '删除', 76 label: '删除',
67 icon: 'ant-design:delete-outlined', 77 icon: 'ant-design:delete-outlined',
  78 + auth: PublicInterface.DELETE,
68 color: 'error', 79 color: 'error',
69 ifShow: () => { 80 ifShow: () => {
70 return record.state === 0 && record.creator === userId; 81 return record.state === 0 && record.creator === userId;
@@ -99,6 +110,8 @@ @@ -99,6 +110,8 @@
99 import { useMessage } from '/@/hooks/web/useMessage'; 110 import { useMessage } from '/@/hooks/web/useMessage';
100 import { USER_INFO_KEY } from '/@/enums/cacheEnum'; 111 import { USER_INFO_KEY } from '/@/enums/cacheEnum';
101 import { getAuthCache } from '/@/utils/auth'; 112 import { getAuthCache } from '/@/utils/auth';
  113 + import { PublicInterface } from '../config';
  114 + import { Authority } from '/@/components/Authority';
102 115
103 const userInfo = getAuthCache(USER_INFO_KEY) as any; 116 const userInfo = getAuthCache(USER_INFO_KEY) as any;
104 117
@@ -119,7 +132,7 @@ @@ -119,7 +132,7 @@
119 }, 132 },
120 useSearchForm: true, 133 useSearchForm: true,
121 actionColumn: { 134 actionColumn: {
122 - width: 150, 135 + width: 180,
123 title: '操作', 136 title: '操作',
124 dataIndex: 'action', 137 dataIndex: 'action',
125 slots: { customRender: 'action' }, 138 slots: { customRender: 'action' },
@@ -125,23 +125,25 @@ export const step1Schemas: FormSchema[] = [ @@ -125,23 +125,25 @@ export const step1Schemas: FormSchema[] = [
125 dynamicRules({ values }) { 125 dynamicRules({ values }) {
126 return [ 126 return [
127 { 127 {
128 - required:  
129 - (values?.transportType === TransportTypeEnum.TCP &&  
130 - values?.deviceType === DeviceTypeEnum.SENSOR) ||  
131 - values?.deviceType === DeviceTypeEnum.GATEWAY, 128 + required: values?.transportType === TransportTypeEnum.TCP,
132 message: '请输入设备标识符', 129 message: '请输入设备标识符',
133 }, 130 },
134 ]; 131 ];
135 }, 132 },
136 - ifShow: ({ values }) =>  
137 - values?.transportType === TransportTypeEnum.TCP &&  
138 - (values.deviceType === DeviceTypeEnum.SENSOR || values.deviceType === DeviceTypeEnum.GATEWAY),  
139 - componentProps: ({}) => { 133 + // ifShow: ({ values }) =>
  134 + // values?.transportType === TransportTypeEnum.TCP &&
  135 + // (values.deviceType === DeviceTypeEnum.SENSOR || values.deviceType === DeviceTypeEnum.GATEWAY),
  136 + ifShow: ({ values }) => values?.transportType === TransportTypeEnum.TCP,
  137 + componentProps: ({ formActionType }) => {
  138 + const { setFieldsValue } = formActionType;
140 return { 139 return {
141 options: [ 140 options: [
142 { label: '自定义', value: TaskTypeEnum.CUSTOM }, 141 { label: '自定义', value: TaskTypeEnum.CUSTOM },
143 { label: 'ModBus', value: TaskTypeEnum.MODBUS_RTU }, 142 { label: 'ModBus', value: TaskTypeEnum.MODBUS_RTU },
144 ], 143 ],
  144 + onChange() {
  145 + setFieldsValue({ addressCode: null });
  146 + },
145 }; 147 };
146 }, 148 },
147 }, 149 },
@@ -167,11 +169,17 @@ export const step1Schemas: FormSchema[] = [ @@ -167,11 +169,17 @@ export const step1Schemas: FormSchema[] = [
167 minValue: 0, 169 minValue: 0,
168 disabledSwitch: true, 170 disabledSwitch: true,
169 }, 171 },
  172 + // ifShow: ({ values }) => {
  173 + // return (
  174 + // values?.transportType === TransportTypeEnum.TCP &&
  175 + // (values.deviceType === DeviceTypeEnum.SENSOR ||
  176 + // values.deviceType === DeviceTypeEnum.GATEWAY) &&
  177 + // values?.codeType === TaskTypeEnum.MODBUS_RTU
  178 + // );
  179 + // },
170 ifShow: ({ values }) => { 180 ifShow: ({ values }) => {
171 return ( 181 return (
172 values?.transportType === TransportTypeEnum.TCP && 182 values?.transportType === TransportTypeEnum.TCP &&
173 - (values.deviceType === DeviceTypeEnum.SENSOR ||  
174 - values.deviceType === DeviceTypeEnum.GATEWAY) &&  
175 values?.codeType === TaskTypeEnum.MODBUS_RTU 183 values?.codeType === TaskTypeEnum.MODBUS_RTU
176 ); 184 );
177 }, 185 },
@@ -43,7 +43,9 @@ export const descSchema = (emit: EmitType): DescItem[] => { @@ -43,7 +43,9 @@ export const descSchema = (emit: EmitType): DescItem[] => {
43 type: 'link', 43 type: 'link',
44 style: { padding: 0 }, 44 style: { padding: 0 },
45 onClick: () => 45 onClick: () =>
46 - !isCustomer ? go(PageEnum.DEVICE_PROFILE + '?name=' + String(val)) : '', 46 + !isCustomer
  47 + ? go(PageEnum.DEVICE_PROFILE + '?name=' + encodeURIComponent(String(val)))
  48 + : '',
47 }, 49 },
48 { default: () => val } 50 { default: () => val }
49 ); 51 );
@@ -167,12 +169,12 @@ export const alarmColumns: BasicColumn[] = [ @@ -167,12 +169,12 @@ export const alarmColumns: BasicColumn[] = [
167 { 169 {
168 title: '告警时间', 170 title: '告警时间',
169 dataIndex: 'createdTime', 171 dataIndex: 'createdTime',
170 - width: 120, 172 + width: 180,
171 }, 173 },
172 { 174 {
173 title: '告警设备', 175 title: '告警设备',
174 dataIndex: 'deviceName', 176 dataIndex: 'deviceName',
175 - width: 100, 177 + width: 120,
176 }, 178 },
177 { 179 {
178 title: '告警场景', 180 title: '告警场景',
@@ -182,14 +184,20 @@ export const alarmColumns: BasicColumn[] = [ @@ -182,14 +184,20 @@ export const alarmColumns: BasicColumn[] = [
182 { 184 {
183 title: '告警级别', 185 title: '告警级别',
184 dataIndex: 'severity', 186 dataIndex: 'severity',
185 - width: 160, 187 + width: 90,
186 format: (text) => alarmLevel(text), 188 format: (text) => alarmLevel(text),
187 }, 189 },
188 { 190 {
  191 + title: '告警详情',
  192 + dataIndex: 'details',
  193 + slots: { customRender: 'details' },
  194 + width: 160,
  195 + },
  196 + {
189 title: '状态', 197 title: '状态',
190 dataIndex: 'status', 198 dataIndex: 'status',
191 format: (text) => statusType(text), 199 format: (text) => statusType(text),
192 - width: 160, 200 + width: 100,
193 }, 201 },
194 ]; 202 ];
195 203
@@ -261,14 +269,6 @@ export const alarmSchemasForm: FormSchema[] = [ @@ -261,14 +269,6 @@ export const alarmSchemasForm: FormSchema[] = [
261 disabled: true, 269 disabled: true,
262 }, 270 },
263 }, 271 },
264 - {  
265 - field: 'details',  
266 - label: '详情',  
267 - component: 'InputTextArea',  
268 - componentProps: {  
269 - maxLength: 255,  
270 - },  
271 - },  
272 ]; 272 ];
273 // 子设备 273 // 子设备
274 export const childDeviceSchemas: FormSchema[] = [ 274 export const childDeviceSchemas: FormSchema[] = [
@@ -54,10 +54,6 @@ @@ -54,10 +54,6 @@
54 await resetFields(); 54 await resetFields();
55 await setFieldsValue({ 55 await setFieldsValue({
56 ...data, 56 ...data,
57 - details: JSON.stringify(data?.details?.data).slice(  
58 - 1,  
59 - JSON.stringify(data?.details?.data).length - 1  
60 - ),  
61 severity: alarmLevel(data.severity), 57 severity: alarmLevel(data.severity),
62 status: statusType(data.status), 58 status: statusType(data.status),
63 }); 59 });
@@ -145,6 +145,8 @@ @@ -145,6 +145,8 @@
145 // !!!此处需要删除地图的属性,否则会报堆栈溢出的错误 Uncaught RangeError: Maximum call stack size exceeded 145 // !!!此处需要删除地图的属性,否则会报堆栈溢出的错误 Uncaught RangeError: Maximum call stack size exceeded
146 Reflect.deleteProperty(DeviceStep1Ref.value.positionState, 'map'); 146 Reflect.deleteProperty(DeviceStep1Ref.value.positionState, 'map');
147 Reflect.deleteProperty(DeviceStep1Ref.value.positionState, 'marker'); 147 Reflect.deleteProperty(DeviceStep1Ref.value.positionState, 'marker');
  148 + Reflect.deleteProperty(DeviceStep1Ref.value.devicePositionState, 'map');
  149 + Reflect.deleteProperty(DeviceStep1Ref.value.devicePositionState, 'marker');
148 setModalProps({ 150 setModalProps({
149 confirmLoading: true, 151 confirmLoading: true,
150 }); 152 });
@@ -156,7 +158,7 @@ @@ -156,7 +158,7 @@
156 customerId: currentDeviceData.customerId, 158 customerId: currentDeviceData.customerId,
157 deviceInfo: { 159 deviceInfo: {
158 avatar: DeviceStep1Ref.value?.devicePic, 160 avatar: DeviceStep1Ref.value?.devicePic,
159 - ...DeviceStep1Ref.value?.positionState, 161 + ...DeviceStep1Ref.value?.devicePositionState,
160 }, 162 },
161 }; 163 };
162 validateNameLength(stepRecord.name); 164 validateNameLength(stepRecord.name);
@@ -168,7 +170,7 @@ @@ -168,7 +170,7 @@
168 sn: stepRecord.name, 170 sn: stepRecord.name,
169 deviceInfo: { 171 deviceInfo: {
170 avatar: DeviceStep1Ref.value?.devicePic, 172 avatar: DeviceStep1Ref.value?.devicePic,
171 - ...DeviceStep1Ref.value?.positionState, 173 + ...DeviceStep1Ref.value?.devicePositionState,
172 }, 174 },
173 deviceToken: 175 deviceToken:
174 unref(current) === 0 || !unref(stepState).addAgree 176 unref(current) === 0 || !unref(stepState).addAgree
@@ -46,7 +46,7 @@ @@ -46,7 +46,7 @@
46 </div> 46 </div>
47 </template> 47 </template>
48 <template #deviceAddress> 48 <template #deviceAddress>
49 - <Input disabled v-model:value="positionState.address"> 49 + <Input disabled v-model:value="devicePositionState.address">
50 <template #addonAfter> 50 <template #addonAfter>
51 <EnvironmentTwoTone @click="selectPosition" /> 51 <EnvironmentTwoTone @click="selectPosition" />
52 </template> 52 </template>
@@ -128,6 +128,7 @@ @@ -128,6 +128,7 @@
128 import { useDrawer } from '/@/components/Drawer'; 128 import { useDrawer } from '/@/components/Drawer';
129 import DeptDrawer from '/@/views/system/organization/OrganizationDrawer.vue'; 129 import DeptDrawer from '/@/views/system/organization/OrganizationDrawer.vue';
130 import { TaskTypeEnum } from '/@/views/task/center/config'; 130 import { TaskTypeEnum } from '/@/views/task/center/config';
  131 + import { toRaw } from 'vue';
131 132
132 export default defineComponent({ 133 export default defineComponent({
133 components: { 134 components: {
@@ -239,8 +240,14 @@ @@ -239,8 +240,14 @@
239 const selectPosition = () => { 240 const selectPosition = () => {
240 visible.value = true; 241 visible.value = true;
241 if (!positionState.longitude) { 242 if (!positionState.longitude) {
242 - positionState.longitude = '104.04666605565338';  
243 - positionState.latitude = '30.543516387560476'; 243 + positionState.longitude = '104.05326410962411';
  244 + positionState.latitude = '30.54855093076791';
  245 +
  246 + // 根据经纬度获取详细位置
  247 + if (positionState.longitude && positionState.latitude) {
  248 + var pt = new BMap.Point(positionState.longitude, positionState.latitude);
  249 + getAddrByPoint(pt);
  250 + }
244 initMap(positionState.longitude, positionState.latitude); 251 initMap(positionState.longitude, positionState.latitude);
245 } else { 252 } else {
246 initMap(positionState.longitude, positionState.latitude); 253 initMap(positionState.longitude, positionState.latitude);
@@ -261,6 +268,15 @@ @@ -261,6 +268,15 @@
261 map: null, 268 map: null,
262 marker: null, 269 marker: null,
263 }); 270 });
  271 +
  272 + const devicePositionState = ref({
  273 + longitude: '',
  274 + latitude: '',
  275 + address: '',
  276 + map: null,
  277 + marker: null,
  278 + });
  279 +
264 /** 280 /**
265 * 逆地址解析函数(根据坐标点获取详细地址) 281 * 逆地址解析函数(根据坐标点获取详细地址)
266 * @param {Object} point 百度地图坐标点,必传 282 * @param {Object} point 百度地图坐标点,必传
@@ -371,6 +387,7 @@ @@ -371,6 +387,7 @@
371 // 确定选择的位置 387 // 确定选择的位置
372 const handleOk = () => { 388 const handleOk = () => {
373 visible.value = false; 389 visible.value = false;
  390 + devicePositionState.value = { ...toRaw(positionState) };
374 }; 391 };
375 // 取消选择位置 392 // 取消选择位置
376 const handleCancel = () => { 393 const handleCancel = () => {
@@ -385,6 +402,7 @@ @@ -385,6 +402,7 @@
385 positionState.longitude = deviceInfo.longitude; 402 positionState.longitude = deviceInfo.longitude;
386 positionState.latitude = deviceInfo.latitude; 403 positionState.latitude = deviceInfo.latitude;
387 positionState.address = deviceInfo.address; 404 positionState.address = deviceInfo.address;
  405 + devicePositionState.value = { ...toRaw(positionState) };
388 devicePic.value = deviceInfo.avatar; 406 devicePic.value = deviceInfo.avatar;
389 setFieldsValue({ 407 setFieldsValue({
390 ...data, 408 ...data,
@@ -418,11 +436,13 @@ @@ -418,11 +436,13 @@
418 function parentResetDevicePic(deviceInfo) { 436 function parentResetDevicePic(deviceInfo) {
419 devicePic.value = deviceInfo.avatar; 437 devicePic.value = deviceInfo.avatar;
420 } 438 }
  439 +
421 // 父组件重置位置 440 // 父组件重置位置
422 function parentResetPositionState() { 441 function parentResetPositionState() {
423 for (let key in positionState) { 442 for (let key in positionState) {
424 positionState[key] = ''; 443 positionState[key] = '';
425 } 444 }
  445 + devicePositionState.value = { ...toRaw(positionState) };
426 } 446 }
427 // 禁用设备类型 447 // 禁用设备类型
428 function disabledDeviceType(disabled: boolean) { 448 function disabledDeviceType(disabled: boolean) {
@@ -474,6 +494,7 @@ @@ -474,6 +494,7 @@
474 handleOpenOrgDrawer, 494 handleOpenOrgDrawer,
475 handleSuccess, 495 handleSuccess,
476 handleTreeOrg, 496 handleTreeOrg,
  497 + devicePositionState,
477 }; 498 };
478 }, 499 },
479 }); 500 });
@@ -12,17 +12,31 @@ @@ -12,17 +12,31 @@
12 ]" 12 ]"
13 /> 13 />
14 </template> 14 </template>
  15 + <template #details="{ record }">
  16 + <a-button type="link" class="ml-2" @click="handleViewAlarmDetails(record)">
  17 + 查看告警详情
  18 + </a-button>
  19 + </template>
15 </BasicTable> 20 </BasicTable>
16 <AlarmDetailModal @register="registerDetailModal" @success="handleSuccess" /> 21 <AlarmDetailModal @register="registerDetailModal" @success="handleSuccess" />
17 </div> 22 </div>
18 </template> 23 </template>
19 <script lang="ts"> 24 <script lang="ts">
20 - import { defineComponent } from 'vue'; 25 + import { defineComponent, h, nextTick } from 'vue';
21 import { BasicTable, useTable, TableAction } from '/@/components/Table'; 26 import { BasicTable, useTable, TableAction } from '/@/components/Table';
22 import { alarmColumns, alarmSearchSchemas } from '../../config/detail.config'; 27 import { alarmColumns, alarmSearchSchemas } from '../../config/detail.config';
23 import { getDeviceAlarm } from '/@/api/device/deviceManager'; 28 import { getDeviceAlarm } from '/@/api/device/deviceManager';
24 import AlarmDetailModal from '../modal/AlarmDetailModal.vue'; 29 import AlarmDetailModal from '../modal/AlarmDetailModal.vue';
25 import { useModal } from '/@/components/Modal'; 30 import { useModal } from '/@/components/Modal';
  31 + import { Modal } from 'ant-design-vue';
  32 + import { JsonPreview } from '/@/components/CodeEditor';
  33 + import { getDeviceDetail } from '/@/api/device/deviceManager';
  34 + import { getAttribute } from '/@/api/ruleengine/ruleengineApi';
  35 + import {
  36 + operationNumber_OR_TIME,
  37 + operationString,
  38 + operationBoolean,
  39 + } from '/@/views/rule/linkedge/config/formatData';
26 export default defineComponent({ 40 export default defineComponent({
27 name: 'DeviceManagement', 41 name: 'DeviceManagement',
28 components: { 42 components: {
@@ -66,11 +80,86 @@ @@ -66,11 +80,86 @@
66 const handleSuccess = () => { 80 const handleSuccess = () => {
67 reload(); 81 reload();
68 }; 82 };
  83 + const handleViewAlarmDetails = async (record: Recordable) => {
  84 + await nextTick();
  85 + const { details } = record;
  86 + const deviceIdKeys = Object.keys(details);
  87 + const detailObject = deviceIdKeys.map((key) => ({ label: key, value: details[key] }));
  88 + const dataFormat = await handleAlarmDetailFormat(deviceIdKeys);
  89 + console.log(detailObject, dataFormat, 'dataFormat');
  90 + const dataFormats = detailObject.reduce((acc: any, curr: any) => {
  91 + dataFormat.forEach((item) => {
  92 + if (item.tbDeviceId === curr.label) {
  93 + const findName = item.attribute.find(
  94 + (item) => item.identifier === curr.value.key
  95 + )?.name;
  96 + const findLogin = [
  97 + ...operationNumber_OR_TIME,
  98 + ...operationString,
  99 + ...operationBoolean,
  100 + ].find((item) => item.value === curr.value.logic)?.symbol;
  101 + const findAttribute = item.attribute.find(
  102 + (findItem) => findItem.identifier === curr.value.key
  103 + );
  104 + const value = {
  105 + ['触发属性']: findName,
  106 + ['触发条件']: `${findLogin}${curr.value.logicValue}`,
  107 + ['触发值']: `${curr.value.realValue}${findAttribute.detail?.dataType?.specs?.unit?.key}`,
  108 + };
  109 + const data = {
  110 + [item.name]: value,
  111 + };
  112 + acc.push(data);
  113 + }
  114 + });
  115 + return [...acc];
  116 + }, []);
  117 + const objectFormat = dataFormats.reduce((acc: any, curr: any) => {
  118 + return {
  119 + ...acc,
  120 + ...curr,
  121 + };
  122 + }, {});
  123 + Modal.info({
  124 + title: '告警详情',
  125 + width: 600,
  126 + centered: true,
  127 + maskClosable: true,
  128 + content: h(JsonPreview, { data: JSON.parse(JSON.stringify(objectFormat)) }),
  129 + });
  130 + };
  131 + const handleAlarmDetailFormat = async (keys: string[]) => {
  132 + const temp: any = [];
  133 + for (let item of keys) {
  134 + if (item === 'key' || item === 'data') return []; //旧数据则终止
  135 + const deviceDetailRes = await getDeviceDetail(item);
  136 + const { deviceProfileId } = deviceDetailRes;
  137 + if (!deviceProfileId) return [];
  138 + const attributeRes = await getAttribute(deviceProfileId);
  139 + const dataFormat: any = handleDataFormat(deviceDetailRes, attributeRes);
  140 + temp.push(dataFormat);
  141 + }
  142 + return temp;
  143 + };
  144 + const handleDataFormat = (deviceDetail: any, attributes: any) => {
  145 + const { name, tbDeviceId } = deviceDetail;
  146 + const attribute = attributes.map((item) => ({
  147 + identifier: item.identifier,
  148 + name: item.name,
  149 + detail: item.detail,
  150 + }));
  151 + return {
  152 + name,
  153 + tbDeviceId,
  154 + attribute,
  155 + };
  156 + };
69 return { 157 return {
70 registerTable, 158 registerTable,
71 registerDetailModal, 159 registerDetailModal,
72 handleDetail, 160 handleDetail,
73 handleSuccess, 161 handleSuccess,
  162 + handleViewAlarmDetails,
74 }; 163 };
75 }, 164 },
76 }); 165 });
@@ -52,7 +52,9 @@ @@ -52,7 +52,9 @@
52 <div class="mt-4" v-if="!isCustomer"> 52 <div class="mt-4" v-if="!isCustomer">
53 <a-button type="primary" class="mr-4" @click="copyTbDeviceId">复制设备ID</a-button> 53 <a-button type="primary" class="mr-4" @click="copyTbDeviceId">复制设备ID</a-button>
54 <a-button type="primary" class="mr-4" @click="copyDeviceToken">复制访问令牌</a-button> 54 <a-button type="primary" class="mr-4" @click="copyDeviceToken">复制访问令牌</a-button>
55 - <a-button type="primary" class="mr-4" @click="manageDeviceToken">管理设备凭证</a-button> 55 + <Authority value="api:yt:device:equipment">
  56 + <a-button type="primary" class="mr-4" @click="manageDeviceToken">管理设备凭证</a-button>
  57 + </Authority>
56 <ManageDeviceTokenModal @register="registerModal" /> 58 <ManageDeviceTokenModal @register="registerModal" />
57 </div> 59 </div>
58 <div class="mt-4"> 60 <div class="mt-4">
@@ -84,10 +86,10 @@ @@ -84,10 +86,10 @@
84 import { DeviceTypeEnum } from '/@/api/device/model/deviceModel'; 86 import { DeviceTypeEnum } from '/@/api/device/model/deviceModel';
85 import { useAuthDeviceDetail } from '../../hook/useAuthDeviceDetail'; 87 import { useAuthDeviceDetail } from '../../hook/useAuthDeviceDetail';
86 import { useClipboard } from '@vueuse/core'; 88 import { useClipboard } from '@vueuse/core';
87 -  
88 import wz from '/@/assets/images/wz.png'; 89 import wz from '/@/assets/images/wz.png';
89 import { useAsyncQueue } from '../../../localtion/useAsyncQueue'; 90 import { useAsyncQueue } from '../../../localtion/useAsyncQueue';
90 import locationImage from '/@/assets/icons/location.svg'; 91 import locationImage from '/@/assets/icons/location.svg';
  92 + import { Authority } from '/@/components/Authority';
91 93
92 export default defineComponent({ 94 export default defineComponent({
93 components: { 95 components: {
@@ -98,6 +100,7 @@ @@ -98,6 +100,7 @@
98 BasicModal, 100 BasicModal,
99 Tooltip, 101 Tooltip,
100 Empty, 102 Empty,
  103 + Authority,
101 }, 104 },
102 props: { 105 props: {
103 deviceDetail: { 106 deviceDetail: {
@@ -72,7 +72,7 @@ export const formSchemas: FormSchema[] = [ @@ -72,7 +72,7 @@ export const formSchemas: FormSchema[] = [
72 }, 72 },
73 { 73 {
74 field: 'eventType', 74 field: 'eventType',
75 - label: '告警类型', 75 + label: '事件类型',
76 component: 'ApiSelect', 76 component: 'ApiSelect',
77 componentProps: { 77 componentProps: {
78 placeholder: '请选择事件类型', 78 placeholder: '请选择事件类型',
@@ -167,6 +167,7 @@ @@ -167,6 +167,7 @@
167 mode.value = value; 167 mode.value = value;
168 await nextTick(); 168 await nextTick();
169 setTableData(socketInfo.originData); 169 setTableData(socketInfo.originData);
  170 + socketInfo.dataSource = socketInfo.originData;
170 }; 171 };
171 172
172 const { createMessage } = useMessage(); 173 const { createMessage } = useMessage();
@@ -315,10 +316,10 @@ @@ -315,10 +316,10 @@
315 <ModeSwitchButton v-model:value="mode" @change="switchMode" /> 316 <ModeSwitchButton v-model:value="mode" @change="switchMode" />
316 </div> 317 </div>
317 <List 318 <List
318 - v-if="mode === EnumTableCardMode.CARD" 319 + v-show="mode === EnumTableCardMode.CARD"
319 ref="listElRef" 320 ref="listElRef"
320 class="list-mode !px-2" 321 class="list-mode !px-2"
321 - :data-source="socketInfo.originData" 322 + :data-source="socketInfo.dataSource"
322 :grid="grid" 323 :grid="grid"
323 :pagination="pagination" 324 :pagination="pagination"
324 > 325 >
@@ -129,17 +129,20 @@ const SingleToHexBatch = (t) => { @@ -129,17 +129,20 @@ const SingleToHexBatch = (t) => {
129 129
130 const formSchemasConfig = (schemas, actionType): FormSchema[] => { 130 const formSchemasConfig = (schemas, actionType): FormSchema[] => {
131 const { identifier, functionName } = schemas; 131 const { identifier, functionName } = schemas;
132 - console.log(identifier, 'identifier', actionType, 'actionType');  
133 if (actionType == '06') { 132 if (actionType == '06') {
134 return [ 133 return [
135 { 134 {
136 field: identifier, 135 field: identifier,
137 label: functionName, 136 label: functionName,
138 component: 'InputNumber', 137 component: 'InputNumber',
139 - rules: [{ required: true, message: '请输入' }], 138 + rules: [{ required: true, message: '请输入正数' }],
140 componentProps: { 139 componentProps: {
141 - precision: 0,  
142 - placeholder: `请输入整数`, 140 + min: 0,
  141 + formatter: (e) => {
  142 + const value = `${e}`.replace('-', '').replace(/^(-)*(\d+)\.(\d\d).*$/, '$1$2.$3');
  143 + return value;
  144 + },
  145 + placeholder: `请输入正数`,
143 }, 146 },
144 }, 147 },
145 ]; 148 ];
@@ -166,7 +169,7 @@ const formSchemasConfig = (schemas, actionType): FormSchema[] => { @@ -166,7 +169,7 @@ const formSchemasConfig = (schemas, actionType): FormSchema[] => {
166 component: 'InputNumber', 169 component: 'InputNumber',
167 rules: [{ required: true, message: '请输入值' }], 170 rules: [{ required: true, message: '请输入值' }],
168 componentProps: { 171 componentProps: {
169 - placeholder: `请输入`, 172 + placeholder: `请输入数字`,
170 formatter: (e) => 173 formatter: (e) =>
171 `${e}`.replace(/\B(?=(\d{3})+(?!\d))/g, '').replace(/^(-)*(\d+)\.(\d\d).*$/, '$1$2.$3'), 174 `${e}`.replace(/\B(?=(\d{3})+(?!\d))/g, '').replace(/^(-)*(\d+)\.(\d\d).*$/, '$1$2.$3'),
172 }, 175 },
@@ -39,10 +39,9 @@ @@ -39,10 +39,9 @@
39 const { name, detail, identifier, deviceDetail, extensionDesc } = record; 39 const { name, detail, identifier, deviceDetail, extensionDesc } = record;
40 const { dataType } = detail; 40 const { dataType } = detail;
41 const { type } = dataType || {}; 41 const { type } = dataType || {};
42 - const { codeType, deviceProfile } = deviceDetail || {}; 42 + const { codeType, deviceProfile, code } = deviceDetail || {};
43 const { transportType } = deviceProfile || {}; 43 const { transportType } = deviceProfile || {};
44 const { registerAddress, actionType, zoomFactor } = extensionDesc || {}; //获取扩展描述内容 44 const { registerAddress, actionType, zoomFactor } = extensionDesc || {}; //获取扩展描述内容
45 -  
46 formField.value = identifier; 45 formField.value = identifier;
47 zoomFactorValue.value = zoomFactor ? Number(zoomFactor) : 1; 46 zoomFactorValue.value = zoomFactor ? Number(zoomFactor) : 1;
48 isShowMultiply.value = type == 'INT' || type == 'DOUBLE' ? true : false; 47 isShowMultiply.value = type == 'INT' || type == 'DOUBLE' ? true : false;
@@ -64,7 +63,7 @@ @@ -64,7 +63,7 @@
64 isShowModBUS.value = true; 63 isShowModBUS.value = true;
65 modBUSForm.value = { 64 modBUSForm.value = {
66 crc: 'CRC_16_LOWER', 65 crc: 'CRC_16_LOWER',
67 - deviceCode: '01', 66 + deviceCode: code,
68 method: actionType == '16' ? '10' : actionType, 67 method: actionType == '16' ? '10' : actionType,
69 registerAddress, 68 registerAddress,
70 registerNumber: 1, 69 registerNumber: 1,
@@ -91,6 +90,17 @@ @@ -91,6 +90,17 @@
91 return array; 90 return array;
92 }; 91 };
93 92
  93 + // 获取小数
  94 + const getFloatPart = (number: string | number) => {
  95 + const isLessZero = Number(number) < 0;
  96 + number = number.toString();
  97 + const floatPartStartIndex = number.indexOf('.');
  98 + const value = ~floatPartStartIndex
  99 + ? `${isLessZero ? '-' : ''}0.${number.substring(floatPartStartIndex + 1)}`
  100 + : '0';
  101 + return Number(value);
  102 + };
  103 +
94 const { createMessage } = useMessage(); 104 const { createMessage } = useMessage();
95 const loading = ref(false); 105 const loading = ref(false);
96 const handleSend = async () => { 106 const handleSend = async () => {
@@ -111,15 +121,37 @@ @@ -111,15 +121,37 @@
111 const oldValue = getFieldsValue()[unref(formField)]; 121 const oldValue = getFieldsValue()[unref(formField)];
112 modBUSForm.value.registerNumber = 1; 122 modBUSForm.value.registerNumber = 1;
113 modBUSForm.value.registerValues = [oldValue]; 123 modBUSForm.value.registerValues = [oldValue];
  124 +
114 if (unref(isShowMultiply) && unref(modBUSForm).method == '06') { 125 if (unref(isShowMultiply) && unref(modBUSForm).method == '06') {
  126 + const newValue =
  127 + Math.trunc(oldValue) * unref(zoomFactorValue) +
  128 + getFloatPart(oldValue) * unref(zoomFactorValue);
  129 + if (newValue % 1 != 0) {
  130 + createMessage.warning(`属性下发类型必须是整数,缩放因子为${unref(zoomFactorValue)}`);
  131 + return;
  132 + }
  133 +
  134 + if (oldValue * unref(zoomFactorValue) > 65535) {
  135 + createMessage.warning(`属性下发值不能超过65535,缩放因子是${unref(zoomFactorValue)}`);
  136 + return;
  137 + }
115 //bool类型的就不用去乘缩放因子了 138 //bool类型的就不用去乘缩放因子了
116 - modBUSForm.value.registerValues = [oldValue * unref(zoomFactorValue)]; 139 + modBUSForm.value.registerValues = [newValue];
117 } 140 }
118 141
119 if (unref(modBUSForm).method == '16' || unref(modBUSForm).method == '10') { 142 if (unref(modBUSForm).method == '16' || unref(modBUSForm).method == '10') {
120 - const newValue = getArray(  
121 - SingleToHex(unref(isShowMultiply) ? oldValue * unref(zoomFactorValue) : oldValue)  
122 - ); 143 + const regex = /^-?\d+(\.\d{0,2})?$/;
  144 + const values =
  145 + Math.trunc(oldValue) * unref(zoomFactorValue) +
  146 + getFloatPart(oldValue) * unref(zoomFactorValue);
  147 +
  148 + if (!regex.test(values as any)) {
  149 + createMessage.warning(`属性下发值精确到两位小数,缩放因子是${unref(zoomFactorValue)}`);
  150 + return;
  151 + }
  152 +
  153 + const newValue =
  154 + values == 0 ? [0, 0] : getArray(SingleToHex(unref(isShowMultiply) ? values : oldValue));
123 modBUSForm.value.registerValues = newValue; 155 modBUSForm.value.registerValues = newValue;
124 modBUSForm.value.registerNumber = 2; 156 modBUSForm.value.registerNumber = 2;
125 modBUSForm.value.method = '10'; 157 modBUSForm.value.method = '10';
@@ -5,7 +5,9 @@ @@ -5,7 +5,9 @@
5 > 5 >
6 <template #toolbar> 6 <template #toolbar>
7 <Space> 7 <Space>
8 - <Button type="primary" @click="openModal(true)">命令下发</Button> 8 + <Authority value="api:yt:device:rpc">
  9 + <Button type="primary" @click="openModal(true)">命令下发</Button>
  10 + </Authority>
9 </Space> 11 </Space>
10 </template> 12 </template>
11 <template #recordContent="{ record }"> 13 <template #recordContent="{ record }">
@@ -43,6 +45,7 @@ @@ -43,6 +45,7 @@
43 import { DeviceRecord } from '/@/api/device/model/deviceModel'; 45 import { DeviceRecord } from '/@/api/device/model/deviceModel';
44 import { BasicModal, useModal } from '/@/components/Modal'; 46 import { BasicModal, useModal } from '/@/components/Modal';
45 import CommandIssuance from '../CommandIssuance.vue'; 47 import CommandIssuance from '../CommandIssuance.vue';
  48 + import { Authority } from '/@/components/Authority';
46 49
47 const props = defineProps({ 50 const props = defineProps({
48 fromId: { 51 fromId: {
@@ -85,7 +88,8 @@ @@ -85,7 +88,8 @@
85 }; 88 };
86 const handleRecordContent = (record) => { 89 const handleRecordContent = (record) => {
87 if (!record?.request?.body) return; 90 if (!record?.request?.body) return;
88 - const jsonParams = record?.request?.body; 91 + if (Object.prototype.toString.call(record?.request?.body) !== '[object Object]') return;
  92 + const jsonParams = record?.request?.body?.params;
89 commonModalInfo('命令下发内容', jsonParams); 93 commonModalInfo('命令下发内容', jsonParams);
90 }; 94 };
91 const handleRecordResponseContent = (record) => { 95 const handleRecordResponseContent = (record) => {
@@ -24,14 +24,16 @@ @@ -24,14 +24,16 @@
24 <Authority value="api:yt:device:import"> 24 <Authority value="api:yt:device:import">
25 <Button type="primary" @click="handleBatchImport">导入</Button> 25 <Button type="primary" @click="handleBatchImport">导入</Button>
26 </Authority> 26 </Authority>
27 - <a-button  
28 - v-if="authBtn(role)"  
29 - type="primary"  
30 - @click="handleBatchAssign"  
31 - :disabled="!isExistOption"  
32 - >  
33 - 批量分配  
34 - </a-button> 27 + <Authority value="api:yt:device:assign">
  28 + <a-button
  29 + v-if="authBtn(role)"
  30 + type="primary"
  31 + @click="handleBatchAssign"
  32 + :disabled="!isExistOption"
  33 + >
  34 + 批量分配
  35 + </a-button>
  36 + </Authority>
35 </template> 37 </template>
36 <template #img="{ record }"> 38 <template #img="{ record }">
37 <TableImg 39 <TableImg
@@ -134,6 +136,7 @@ @@ -134,6 +136,7 @@
134 label: '分配客户', 136 label: '分配客户',
135 icon: 'mdi:account-arrow-right', 137 icon: 'mdi:account-arrow-right',
136 ifShow: authBtn(role), 138 ifShow: authBtn(role),
  139 + auth: 'api:yt:device:assign',
137 onClick: handleDispatchCustomer.bind(null, record), 140 onClick: handleDispatchCustomer.bind(null, record),
138 }, 141 },
139 { 142 {
@@ -33,9 +33,15 @@ @@ -33,9 +33,15 @@
33 </Button> 33 </Button>
34 </Authority> 34 </Authority>
35 <Button type="primary" @click="handleOpenTsl"> 物模型TSL </Button> 35 <Button type="primary" @click="handleOpenTsl"> 物模型TSL </Button>
36 - <Upload v-if="isShowBtn" :show-upload-list="false" :customRequest="handleImportModel">  
37 - <Button type="primary" :loading="importLoading"> 导入物模型 </Button>  
38 - </Upload> 36 + <Authority value="api:yt:things_model:import">
  37 + <Upload
  38 + v-if="isShowBtn"
  39 + :show-upload-list="false"
  40 + :customRequest="handleImportModel"
  41 + >
  42 + <Button type="primary" :loading="importLoading"> 导入物模型 </Button>
  43 + </Upload>
  44 + </Authority>
39 </div> 45 </div>
40 <div class="flex gap-2"> 46 <div class="flex gap-2">
41 <Authority :value="ModelOfMatterPermission.RELEASE"> 47 <Authority :value="ModelOfMatterPermission.RELEASE">
@@ -19,6 +19,6 @@ @@ -19,6 +19,6 @@
19 </template> 19 </template>
20 <style scoped> 20 <style scoped>
21 :deep(.ant-table-body) { 21 :deep(.ant-table-body) {
22 - overflow: hidden !important; 22 + overflow: scroll !important;
23 } 23 }
24 </style> 24 </style>
@@ -78,8 +78,7 @@ @@ -78,8 +78,7 @@
78 return deviceType === DeviceTypeEnum.SENSOR && transportType === 'TCP'; 78 return deviceType === DeviceTypeEnum.SENSOR && transportType === 'TCP';
79 }); 79 });
80 80
81 - const blockContent = `属性一般是设备的运行状态,如当前温度等;服务是设备可被调用的方法,支持定义参数,如执行某项任务;事件则是设备上报的  
82 -通知,如告警,需要被及时处理。`; 81 + const blockContent = `属性一般是指设备的运行状态,如当前温度等;服务是指设备可被调用的方法,支持定义参数,如执行某项任务;事件则是指设备上报的通知,如告警,需要被及时处理。`;
83 const activeKey = ref<FunctionType>(FunctionType.PROPERTIES); 82 const activeKey = ref<FunctionType>(FunctionType.PROPERTIES);
84 const size = ref('small'); 83 const size = ref('small');
85 84
@@ -89,7 +89,9 @@ @@ -89,7 +89,9 @@
89 functionJson: { 89 functionJson: {
90 inputData, 90 inputData,
91 outputData, 91 outputData,
92 - ...(serviceCommand ? { inputData: [{ serviceCommand }] } : {}), 92 + ...(serviceCommand
  93 + ? { inputData: [{ serviceCommand: serviceCommand.replaceAll(/\s/g, '').toUpperCase() }] }
  94 + : {}),
93 }, 95 },
94 } as ModelOfMatterParams; 96 } as ModelOfMatterParams;
95 97
@@ -117,7 +117,18 @@ export const serviceSchemas = (tcpDeviceFlag: boolean): FormSchema[] => { @@ -117,7 +117,18 @@ export const serviceSchemas = (tcpDeviceFlag: boolean): FormSchema[] => {
117 field: FormField.SERVICE_COMMAND, 117 field: FormField.SERVICE_COMMAND,
118 label: '输入参数', 118 label: '输入参数',
119 component: 'Input', 119 component: 'Input',
120 - rules: [{ message: '输入参数为必填项', required: true }], 120 + rules: [
  121 + { message: '输入参数为必填项', required: true },
  122 + {
  123 + message: '请输入ASCII或HEX服务命令(0~9/A~F)',
  124 + validator(_rule, value, _callback) {
  125 + const reg = /^[\s0-9a-fA-F]+$/;
  126 +
  127 + if (reg.test(value)) return Promise.resolve();
  128 + return Promise.reject('请输入ASCII或HEX服务命令(0~9/A~F)');
  129 + },
  130 + },
  131 + ],
121 ifShow: tcpDeviceFlag, 132 ifShow: tcpDeviceFlag,
122 componentProps: { 133 componentProps: {
123 placeholder: '请输入ASCII或HEX服务命令', 134 placeholder: '请输入ASCII或HEX服务命令',
@@ -17,16 +17,26 @@ @@ -17,16 +17,26 @@
17 </Authority> 17 </Authority>
18 </template> 18 </template>
19 <template #config="{ record }"> 19 <template #config="{ record }">
20 - <a-button type="link" class="ml-2" @click="showData(record)"> 查看配置 </a-button> 20 + <Authority value="api:yt:message:get:config">
  21 + <a-button type="link" class="ml-2" @click="showData(record)"> 查看配置 </a-button>
  22 + </Authority>
21 </template> 23 </template>
22 <template #status="{ record }"> 24 <template #status="{ record }">
23 - <Switch  
24 - :checked="record.status === 1"  
25 - :loading="record.pendingStatus"  
26 - checkedChildren="启用"  
27 - unCheckedChildren="禁用"  
28 - @change="(checked:boolean)=>statusChange(checked,record)"  
29 - /> 25 + <Authority value="api:yt:message:status">
  26 + <Switch
  27 + :checked="record.status === 1"
  28 + :loading="record.pendingStatus"
  29 + checkedChildren="启用"
  30 + unCheckedChildren="禁用"
  31 + @change="(checked:boolean)=>statusChange(checked,record)"
  32 + />
  33 + </Authority>
  34 + <Tag
  35 + v-if="!hasPermission('api:yt:message:status')"
  36 + :color="record.status ? 'green' : 'red'"
  37 + >
  38 + {{ record.status ? '启用' : '禁用' }}
  39 + </Tag>
30 </template> 40 </template>
31 <template #action="{ record }"> 41 <template #action="{ record }">
32 <TableAction 42 <TableAction
@@ -62,18 +72,20 @@ @@ -62,18 +72,20 @@
62 import { useDrawer } from '/@/components/Drawer'; 72 import { useDrawer } from '/@/components/Drawer';
63 import ConfigDrawer from './ConfigDrawer.vue'; 73 import ConfigDrawer from './ConfigDrawer.vue';
64 import { columns, searchFormSchema } from './config.data'; 74 import { columns, searchFormSchema } from './config.data';
65 - import { Modal, Popconfirm } from 'ant-design-vue'; 75 + import { Modal, Popconfirm, Tag } from 'ant-design-vue';
66 import { JsonPreview } from '/@/components/CodeEditor'; 76 import { JsonPreview } from '/@/components/CodeEditor';
67 import { useMessage } from '/@/hooks/web/useMessage'; 77 import { useMessage } from '/@/hooks/web/useMessage';
68 import { useBatchDelete } from '/@/hooks/web/useBatchDelete'; 78 import { useBatchDelete } from '/@/hooks/web/useBatchDelete';
69 import { Switch } from 'ant-design-vue'; 79 import { Switch } from 'ant-design-vue';
70 import { setMessageConfigStatus } from '/@/api/message/config'; 80 import { setMessageConfigStatus } from '/@/api/message/config';
71 import { Authority } from '/@/components/Authority'; 81 import { Authority } from '/@/components/Authority';
  82 + import { usePermission } from '/@/hooks/web/usePermission';
72 83
73 export default defineComponent({ 84 export default defineComponent({
74 name: 'MessageConfigManagement', 85 name: 'MessageConfigManagement',
75 - components: { BasicTable, ConfigDrawer, TableAction, Switch, Authority, Popconfirm }, 86 + components: { BasicTable, ConfigDrawer, TableAction, Switch, Authority, Popconfirm, Tag },
76 setup() { 87 setup() {
  88 + const { hasPermission } = usePermission();
77 const [registerDrawer, { openDrawer }] = useDrawer(); 89 const [registerDrawer, { openDrawer }] = useDrawer();
78 function handleSuccess() { 90 function handleSuccess() {
79 reload(); 91 reload();
@@ -168,6 +180,7 @@ @@ -168,6 +180,7 @@
168 handleDeleteOrBatchDelete, 180 handleDeleteOrBatchDelete,
169 hasBatchDelete, 181 hasBatchDelete,
170 statusChange, 182 statusChange,
  183 + hasPermission,
171 }; 184 };
172 }, 185 },
173 }); 186 });
@@ -22,13 +22,21 @@ @@ -22,13 +22,21 @@
22 </a-button> 22 </a-button>
23 </template> 23 </template>
24 <template #status="{ record }"> 24 <template #status="{ record }">
25 - <Switch  
26 - :checked="record.status === 1"  
27 - :loading="record.pendingStatus"  
28 - checkedChildren="启用"  
29 - unCheckedChildren="禁用"  
30 - @change="(checked:boolean)=>statusChange(checked,record)"  
31 - /> 25 + <Authority value="api:yt:template:status">
  26 + <Switch
  27 + :checked="record.status === 1"
  28 + :loading="record.pendingStatus"
  29 + checkedChildren="启用"
  30 + unCheckedChildren="禁用"
  31 + @change="(checked:boolean)=>statusChange(checked,record)"
  32 + />
  33 + </Authority>
  34 + <Tag
  35 + v-if="!hasPermission('api:yt:template:status')"
  36 + :color="record.status ? 'green' : 'red'"
  37 + >
  38 + {{ record.status ? '启用' : '禁用' }}
  39 + </Tag>
32 </template> 40 </template>
33 <template #action="{ record }"> 41 <template #action="{ record }">
34 <TableAction 42 <TableAction
@@ -80,9 +88,10 @@ @@ -80,9 +88,10 @@
80 import SendEmail from '/@/views/message/template/SendEmail.vue'; 88 import SendEmail from '/@/views/message/template/SendEmail.vue';
81 import { useMessage } from '/@/hooks/web/useMessage'; 89 import { useMessage } from '/@/hooks/web/useMessage';
82 import { useBatchDelete } from '/@/hooks/web/useBatchDelete'; 90 import { useBatchDelete } from '/@/hooks/web/useBatchDelete';
83 - import { Switch, Popconfirm } from 'ant-design-vue'; 91 + import { Switch, Popconfirm, Tag } from 'ant-design-vue';
84 import { setMessageTemplateStatus } from '/@/api/message/template'; 92 import { setMessageTemplateStatus } from '/@/api/message/template';
85 import { Authority } from '/@/components/Authority'; 93 import { Authority } from '/@/components/Authority';
  94 + import { usePermission } from '/@/hooks/web/usePermission';
86 95
87 export default defineComponent({ 96 export default defineComponent({
88 name: 'MessageTemplateManagement', 97 name: 'MessageTemplateManagement',
@@ -95,8 +104,10 @@ @@ -95,8 +104,10 @@
95 Switch, 104 Switch,
96 Authority, 105 Authority,
97 Popconfirm, 106 Popconfirm,
  107 + Tag,
98 }, 108 },
99 setup() { 109 setup() {
  110 + const { hasPermission } = usePermission();
100 const [registerModal, { openModal: openModal }] = useModal(); 111 const [registerModal, { openModal: openModal }] = useModal();
101 const [registerMailModal, { openModal: openMailModal }] = useModal(); 112 const [registerMailModal, { openModal: openMailModal }] = useModal();
102 const go = useGo(); 113 const go = useGo();
@@ -218,6 +229,7 @@ @@ -218,6 +229,7 @@
218 handleDeleteOrBatchDelete, 229 handleDeleteOrBatchDelete,
219 statusChange, 230 statusChange,
220 hasBatchDelete, 231 hasBatchDelete,
  232 + hasPermission,
221 }; 233 };
222 }, 234 },
223 }); 235 });
@@ -135,10 +135,14 @@ @@ -135,10 +135,14 @@
135 <Tabs.TabPane tab="详情" key="detail"> 135 <Tabs.TabPane tab="详情" key="detail">
136 <Space> 136 <Space>
137 <!-- <Button type="primary" @click="openDetailPage">打开详情页</Button> --> 137 <!-- <Button type="primary" @click="openDetailPage">打开详情页</Button> -->
138 - <Button type="primary" @click="downloadPackage" :disabled="!!otaRecord.url">  
139 - 下载包  
140 - </Button>  
141 - <Button type="primary" @click="deletePackage" danger>删除包</Button> 138 + <Authority :value="OtaPermissionKey.DOWNLOAD">
  139 + <Button type="primary" @click="downloadPackage" :disabled="!!otaRecord.url">
  140 + 下载包
  141 + </Button>
  142 + </Authority>
  143 + <Authority :value="OtaPermissionKey.DELETE">
  144 + <Button type="primary" @click="deletePackage" danger>删除包</Button>
  145 + </Authority>
142 </Space> 146 </Space>
143 <div class="mt-3"> 147 <div class="mt-3">
144 <Space> 148 <Space>
@@ -9,6 +9,7 @@ export enum PermissionReportConfigEnum { @@ -9,6 +9,7 @@ export enum PermissionReportConfigEnum {
9 PERMISSION_GET = 'api:yt:report:get', 9 PERMISSION_GET = 'api:yt:report:get',
10 PERMISSION_DELETE = 'api:yt:report_form:config:delete', 10 PERMISSION_DELETE = 'api:yt:report_form:config:delete',
11 PERMISSION_UPDATE = 'api:yt:report_form:config:update', 11 PERMISSION_UPDATE = 'api:yt:report_form:config:update',
  12 + PERMISSION_STATUS = 'api:yt:report_form:config:status',
12 } 13 }
13 14
14 //业务文字描述配置枚举 15 //业务文字描述配置枚举
@@ -74,14 +74,22 @@ @@ -74,14 +74,22 @@
74 /> 74 />
75 </template> 75 </template>
76 <template #configStatus="{ record }"> 76 <template #configStatus="{ record }">
77 - <Switch  
78 - :disabled="disabledSwitch"  
79 - :checked="record.status === 1"  
80 - :loading="record.pendingStatus"  
81 - :checkedChildren="BusinessReportConfigTextEnum.BUSINESS_ENABLE_TEXT"  
82 - :unCheckedChildren="BusinessReportConfigTextEnum.BUSINESS_DISABLE_TEXT"  
83 - @change="(checked: boolean) => statusChange(checked, record)"  
84 - /> 77 + <Authority :value="PermissionReportConfigEnum.PERMISSION_STATUS">
  78 + <Switch
  79 + :disabled="disabledSwitch"
  80 + :checked="record.status === 1"
  81 + :loading="record.pendingStatus"
  82 + :checkedChildren="BusinessReportConfigTextEnum.BUSINESS_ENABLE_TEXT"
  83 + :unCheckedChildren="BusinessReportConfigTextEnum.BUSINESS_DISABLE_TEXT"
  84 + @change="(checked: boolean) => statusChange(checked, record)"
  85 + />
  86 + </Authority>
  87 + <Tag
  88 + v-if="!hasPermission(PermissionReportConfigEnum.PERMISSION_STATUS)"
  89 + :color="record.status ? 'green' : 'red'"
  90 + >
  91 + {{ record.status ? '启用' : '禁用' }}
  92 + </Tag>
85 </template> 93 </template>
86 </BasicTable> 94 </BasicTable>
87 <ReportConfigDrawer @register="registerDrawer" @success="handleSuccess" /> 95 <ReportConfigDrawer @register="registerDrawer" @success="handleSuccess" />
@@ -101,7 +109,7 @@ @@ -101,7 +109,7 @@
101 import { defaultTableAttribtes } from './config'; 109 import { defaultTableAttribtes } from './config';
102 import { Authority } from '/@/components/Authority'; 110 import { Authority } from '/@/components/Authority';
103 import { useBatchDelete } from '/@/hooks/web/useBatchDelete'; 111 import { useBatchDelete } from '/@/hooks/web/useBatchDelete';
104 - import { Popconfirm, Switch } from 'ant-design-vue'; 112 + import { Popconfirm, Switch, Tag } from 'ant-design-vue';
105 import { useModal } from '/@/components/Modal'; 113 import { useModal } from '/@/components/Modal';
106 import { useGo } from '/@/hooks/web/usePage'; 114 import { useGo } from '/@/hooks/web/usePage';
107 import { useMessage } from '/@/hooks/web/useMessage'; 115 import { useMessage } from '/@/hooks/web/useMessage';
@@ -111,6 +119,9 @@ @@ -111,6 +119,9 @@
111 BusinessReportConfigTextEnum, 119 BusinessReportConfigTextEnum,
112 BusinessReportConfigStatusEnum, 120 BusinessReportConfigStatusEnum,
113 } from './enum'; 121 } from './enum';
  122 + import { usePermission } from '/@/hooks/web/usePermission';
  123 +
  124 + const { hasPermission } = usePermission();
114 125
115 const disabledSwitch = ref(false); 126 const disabledSwitch = ref(false);
116 127
@@ -192,8 +192,8 @@ @@ -192,8 +192,8 @@
192 }, 192 },
193 toolbox: {}, 193 toolbox: {},
194 grid: { 194 grid: {
195 - left: '8%',  
196 - right: '8%', 195 + left: '14%',
  196 + right: '20%',
197 bottom: 80, 197 bottom: 80,
198 containLabel: true, 198 containLabel: true,
199 }, 199 },
@@ -8,6 +8,7 @@ export enum PermissionDataFlowEnum { @@ -8,6 +8,7 @@ export enum PermissionDataFlowEnum {
8 PERMISSION_GET = 'api:yt:convert:config:get', 8 PERMISSION_GET = 'api:yt:convert:config:get',
9 PERMISSION_DELETE = 'api:yt:convert:config:delete', 9 PERMISSION_DELETE = 'api:yt:convert:config:delete',
10 PERMISSION_UPDATE = 'api:yt:convert:config:update', 10 PERMISSION_UPDATE = 'api:yt:convert:config:update',
  11 + PERMISSION_STATUS = 'api:yt:convert:config:status',
11 } 12 }
12 13
13 //业务文字描述配置枚举 14 //业务文字描述配置枚举
@@ -79,13 +79,21 @@ @@ -79,13 +79,21 @@
79 /> 79 />
80 </template> 80 </template>
81 <template #status="{ record }"> 81 <template #status="{ record }">
82 - <Switch  
83 - :checked="record.status === 1"  
84 - :loading="record.pendingStatus"  
85 - checkedChildren="启用"  
86 - unCheckedChildren="禁用"  
87 - @change="(checked:boolean)=>hanldeSwitch(checked,record)"  
88 - /> 82 + <Authority :value="PermissionDataFlowEnum.PERMISSION_STATUS">
  83 + <Switch
  84 + :checked="record.status === 1"
  85 + :loading="record.pendingStatus"
  86 + checkedChildren="启用"
  87 + unCheckedChildren="禁用"
  88 + @change="(checked:boolean)=>hanldeSwitch(checked,record)"
  89 + />
  90 + </Authority>
  91 + <Tag
  92 + v-if="!hasPermission(PermissionDataFlowEnum.PERMISSION_STATUS)"
  93 + :color="record.status ? 'green' : 'red'"
  94 + >
  95 + {{ record.status ? '启用' : '禁用' }}
  96 + </Tag>
89 </template> 97 </template>
90 </BasicTable> 98 </BasicTable>
91 <DataFlowModal @register="registerModal" @success="handleSuccess" /> 99 <DataFlowModal @register="registerModal" @success="handleSuccess" />
@@ -103,15 +111,18 @@ @@ -103,15 +111,18 @@
103 import { useMessage } from '/@/hooks/web/useMessage'; 111 import { useMessage } from '/@/hooks/web/useMessage';
104 import { Authority } from '/@/components/Authority'; 112 import { Authority } from '/@/components/Authority';
105 import { useBatchDelete } from '/@/hooks/web/useBatchDelete'; 113 import { useBatchDelete } from '/@/hooks/web/useBatchDelete';
106 - import { Switch, Popconfirm } from 'ant-design-vue'; 114 + import { Switch, Popconfirm, Tag } from 'ant-design-vue';
107 import { PermissionDataFlowEnum, BusinessDataFlowTextEnum } from './enum'; 115 import { PermissionDataFlowEnum, BusinessDataFlowTextEnum } from './enum';
108 import { DataFlowModal } from './components/dataflowmodal'; 116 import { DataFlowModal } from './components/dataflowmodal';
109 import { defaultTableAttribute } from './config'; 117 import { defaultTableAttribute } from './config';
  118 + import { usePermission } from '/@/hooks/web/usePermission';
110 119
111 const { createMessage } = useMessage(); 120 const { createMessage } = useMessage();
112 121
113 const loading = ref(true); 122 const loading = ref(true);
114 123
  124 + const { hasPermission } = usePermission();
  125 +
115 const handleSuccess = () => { 126 const handleSuccess = () => {
116 reload(); 127 reload();
117 }; 128 };
@@ -31,6 +31,7 @@ export type TOption = { @@ -31,6 +31,7 @@ export type TOption = {
31 export enum CommandTypeEnum { 31 export enum CommandTypeEnum {
32 CUSTOM = 0, 32 CUSTOM = 0,
33 SERVICE = 1, 33 SERVICE = 1,
  34 + ATTRIBUTE = 2,
34 } 35 }
35 36
36 /** 37 /**
@@ -164,26 +164,26 @@ export const genActionData = (actionData) => { @@ -164,26 +164,26 @@ export const genActionData = (actionData) => {
164 }; 164 };
165 165
166 export const operationNumber_OR_TIME = [ 166 export const operationNumber_OR_TIME = [
167 - { label: '等于', value: Number_Operation.EQUAL },  
168 - { label: '不等于', value: Number_Operation.NOT_EQUAL },  
169 - { label: '小于', value: Number_Operation.LESS },  
170 - { label: '小于等于', value: Number_Operation.LESS_OR_EQUAL },  
171 - { label: '大于', value: Number_Operation.GREATER },  
172 - { label: '大于等于', value: Number_Operation.GREATER_OR_EQUAL }, 167 + { label: '等于', value: Number_Operation.EQUAL, symbol: '=' },
  168 + { label: '不等于', value: Number_Operation.NOT_EQUAL, symbol: '!=' },
  169 + { label: '小于', value: Number_Operation.LESS, symbol: '<' },
  170 + { label: '小于等于', value: Number_Operation.LESS_OR_EQUAL, symbol: '<=' },
  171 + { label: '大于', value: Number_Operation.GREATER, symbol: '>' },
  172 + { label: '大于等于', value: Number_Operation.GREATER_OR_EQUAL, symbol: '>=' },
173 ]; 173 ];
174 174
175 export const operationString = [ 175 export const operationString = [
176 - { label: '等于', value: String_Operation.EQUAL },  
177 - { label: '不等于', value: String_Operation.NOT_EQUAL },  
178 - { label: '开始于', value: String_Operation.BEGAN_IN },  
179 - { label: '结束于', value: String_Operation.END_IN },  
180 - { label: '包含', value: String_Operation.INCLUDE },  
181 - { label: '不包含', value: String_Operation.NOT_INCLUDE }, 176 + { label: '等于', value: String_Operation.EQUAL, symbol: '=' },
  177 + { label: '不等于', value: String_Operation.NOT_EQUAL, symbol: '!=' },
  178 + { label: '开始于', value: String_Operation.BEGAN_IN, symbol: '开始于' },
  179 + { label: '结束于', value: String_Operation.END_IN, symbol: '结束于' },
  180 + { label: '包含', value: String_Operation.INCLUDE, symbol: '包含' },
  181 + { label: '不包含', value: String_Operation.NOT_INCLUDE, symbol: '不包含' },
182 ]; 182 ];
183 183
184 export const operationBoolean = [ 184 export const operationBoolean = [
185 - { label: '等于', value: Boolean_Operation.EQUAL },  
186 - { label: '不等于', value: Boolean_Operation.NOT_EQUAL }, 185 + { label: '等于', value: Boolean_Operation.EQUAL, symbol: '=' },
  186 + { label: '不等于', value: Boolean_Operation.NOT_EQUAL, symbol: '!=' },
187 ]; 187 ];
188 188
189 export const scheduleOptions = [ 189 export const scheduleOptions = [
@@ -50,13 +50,21 @@ @@ -50,13 +50,21 @@
50 </template> 50 </template>
51 51
52 <template #status="{ record }"> 52 <template #status="{ record }">
53 - <Switch  
54 - :checked="record.status === 1"  
55 - :loading="record.pendingStatus"  
56 - checkedChildren="启用"  
57 - unCheckedChildren="禁用"  
58 - @change="(checked:boolean)=>statusChange(checked,record)"  
59 - /> 53 + <Authority value="api:yt:sceneLinkage:status">
  54 + <Switch
  55 + :checked="record.status === 1"
  56 + :loading="record.pendingStatus"
  57 + checkedChildren="启用"
  58 + unCheckedChildren="禁用"
  59 + @change="(checked:boolean)=>statusChange(checked,record)"
  60 + />
  61 + </Authority>
  62 + <Tag
  63 + v-if="!hasPermission('api:yt:sceneLinkage:status')"
  64 + :color="record.status ? 'green' : 'red'"
  65 + >
  66 + {{ record.status ? '启用' : '禁用' }}
  67 + </Tag>
60 </template> 68 </template>
61 </BasicTable> 69 </BasicTable>
62 <SceneLinkAgeDrawer @register="registerDrawer" @success="handleSuccess" /> 70 <SceneLinkAgeDrawer @register="registerDrawer" @success="handleSuccess" />
@@ -72,16 +80,18 @@ @@ -72,16 +80,18 @@
72 screenLinkPagePutApi, 80 screenLinkPagePutApi,
73 } from '/@/api/ruleengine/ruleengineApi'; 81 } from '/@/api/ruleengine/ruleengineApi';
74 import { useBatchDelete } from '/@/hooks/web/useBatchDelete'; 82 import { useBatchDelete } from '/@/hooks/web/useBatchDelete';
75 - import { Switch, Popconfirm } from 'ant-design-vue'; 83 + import { Switch, Popconfirm, Tag } from 'ant-design-vue';
76 import { columns, searchFormSchema } from './config/config.data'; 84 import { columns, searchFormSchema } from './config/config.data';
77 import { USER_INFO_KEY } from '/@/enums/cacheEnum'; 85 import { USER_INFO_KEY } from '/@/enums/cacheEnum';
78 import { getAuthCache } from '/@/utils/auth'; 86 import { getAuthCache } from '/@/utils/auth';
79 import SceneLinkAgeDrawer from './SceneLinkAgeDrawer.vue'; 87 import SceneLinkAgeDrawer from './SceneLinkAgeDrawer.vue';
80 import { useMessage } from '/@/hooks/web/useMessage'; 88 import { useMessage } from '/@/hooks/web/useMessage';
81 import { Authority } from '/@/components/Authority'; 89 import { Authority } from '/@/components/Authority';
  90 + import { usePermission } from '/@/hooks/web/usePermission';
82 91
83 const userInfo: any = getAuthCache(USER_INFO_KEY); 92 const userInfo: any = getAuthCache(USER_INFO_KEY);
84 const userId = userInfo.userId; 93 const userId = userInfo.userId;
  94 + const { hasPermission } = usePermission();
85 95
86 const [registerDrawer, { openDrawer }] = useDrawer(); 96 const [registerDrawer, { openDrawer }] = useDrawer();
87 const [registerTable, { reload, setProps, setSelectedRowKeys }] = useTable({ 97 const [registerTable, { reload, setProps, setSelectedRowKeys }] = useTable({
@@ -17,13 +17,21 @@ @@ -17,13 +17,21 @@
17 </Authority> 17 </Authority>
18 </template> 18 </template>
19 <template #status="{ record }"> 19 <template #status="{ record }">
20 - <Switch  
21 - :checked="record.status === 1"  
22 - :loading="record.pendingStatus"  
23 - checkedChildren="启用"  
24 - unCheckedChildren="禁用"  
25 - @change="(checked:boolean)=>statusChange(checked,record)"  
26 - /> 20 + <Authority value="api:yt:convert:js:status">
  21 + <Switch
  22 + :checked="record.status === 1"
  23 + :loading="record.pendingStatus"
  24 + checkedChildren="启用"
  25 + unCheckedChildren="禁用"
  26 + @change="(checked:boolean)=>statusChange(checked,record)"
  27 + />
  28 + </Authority>
  29 + <Tag
  30 + v-if="!hasPermission('api:yt:convert:js:status')"
  31 + :color="record.status ? 'green' : 'red'"
  32 + >
  33 + {{ record.status ? '启用' : '禁用' }}
  34 + </Tag>
27 </template> 35 </template>
28 <template #action="{ record }"> 36 <template #action="{ record }">
29 <TableAction 37 <TableAction
@@ -69,7 +77,7 @@ @@ -69,7 +77,7 @@
69 77
70 <script lang="ts" setup> 78 <script lang="ts" setup>
71 import { ref, nextTick } from 'vue'; 79 import { ref, nextTick } from 'vue';
72 - import { Switch, Popconfirm } from 'ant-design-vue'; 80 + import { Switch, Popconfirm, Tag } from 'ant-design-vue';
73 import { BasicTable, useTable, TableAction } from '/@/components/Table'; 81 import { BasicTable, useTable, TableAction } from '/@/components/Table';
74 import { columns } from '../config/config.data'; 82 import { columns } from '../config/config.data';
75 import { getConvertApi, deleteTransformApi } from '/@/api/device/TransformScriptApi'; 83 import { getConvertApi, deleteTransformApi } from '/@/api/device/TransformScriptApi';
@@ -81,11 +89,14 @@ @@ -81,11 +89,14 @@
81 import { useBatchDelete } from '/@/hooks/web/useBatchDelete'; 89 import { useBatchDelete } from '/@/hooks/web/useBatchDelete';
82 import { Authority } from '/@/components/Authority'; 90 import { Authority } from '/@/components/Authority';
83 import { computed, unref } from 'vue'; 91 import { computed, unref } from 'vue';
  92 + import { usePermission } from '/@/hooks/web/usePermission';
84 93
85 const props = defineProps<{ searchInfo: Recordable }>(); 94 const props = defineProps<{ searchInfo: Recordable }>();
86 95
87 const getSearchInfo = computed(() => props.searchInfo); 96 const getSearchInfo = computed(() => props.searchInfo);
88 97
  98 + const { hasPermission } = usePermission();
  99 +
89 const handleSuccess = () => { 100 const handleSuccess = () => {
90 reload(); 101 reload();
91 }; 102 };
@@ -16,8 +16,8 @@ @@ -16,8 +16,8 @@
16 <div class="hidden min-h-full pl-4 mr-4 xl:flex xl:flex-col xl:w-6/12"> 16 <div class="hidden min-h-full pl-4 mr-4 xl:flex xl:flex-col xl:w-6/12">
17 <!-- <AppLogo class="-enter-x" /> --> 17 <!-- <AppLogo class="-enter-x" /> -->
18 <div style="display: flex; margin-top: 10px"> 18 <div style="display: flex; margin-top: 10px">
19 - <img v-if="defaultLogo" :src="defaultLogo" style="width: 48px; height: 48px" />  
20 - <img style="width: 48px; height: 48px" v-else src="/src/assets/images/logo.png" /> 19 + <img v-if="defaultLogo" :src="defaultLogo" class="h-12" />
  20 + <img class="h-12" v-else src="/src/assets/images/logo.png" />
21 <div 21 <div
22 class="ml-2 truncate md:opacity-100" 22 class="ml-2 truncate md:opacity-100"
23 style=" 23 style="
@@ -24,8 +24,9 @@ @@ -24,8 +24,9 @@
24 :customRequest="customUploadIconPic" 24 :customRequest="customUploadIconPic"
25 :before-upload="beforeUploadIconPic" 25 :before-upload="beforeUploadIconPic"
26 > 26 >
27 - <div v-if="iconPic"> 27 + <div v-if="iconPic" class="relative">
28 <img :src="iconPic" class="m-auto fill-img" /> 28 <img :src="iconPic" class="m-auto fill-img" />
  29 + <CloseCircleOutlined class="absolute icon-delete" @click.stop="handleDelete" />
29 <div style="background-color: #ccc; margin-top: 20px">重新上传</div> 30 <div style="background-color: #ccc; margin-top: 20px">重新上传</div>
30 </div> 31 </div>
31 <div v-else> 32 <div v-else>
@@ -81,7 +82,7 @@ @@ -81,7 +82,7 @@
81 import { useMessage } from '/@/hooks/web/useMessage'; 82 import { useMessage } from '/@/hooks/web/useMessage';
82 import type { FileItem } from '/@/components/Upload/src/typing'; 83 import type { FileItem } from '/@/components/Upload/src/typing';
83 import { iconUpload, getPlatForm, updatePlatForm, resetPlateInfo } from '/@/api/oem/index'; 84 import { iconUpload, getPlatForm, updatePlatForm, resetPlateInfo } from '/@/api/oem/index';
84 - import { PlusOutlined } from '@ant-design/icons-vue'; 85 + import { PlusOutlined, CloseCircleOutlined } from '@ant-design/icons-vue';
85 import { useUserStore } from '/@/store/modules/user'; 86 import { useUserStore } from '/@/store/modules/user';
86 import { createLocalStorage } from '/@/utils/cache/index'; 87 import { createLocalStorage } from '/@/utils/cache/index';
87 import { Authority } from '/@/components/Authority'; 88 import { Authority } from '/@/components/Authority';
@@ -100,6 +101,7 @@ @@ -100,6 +101,7 @@
100 ContentUploadText, 101 ContentUploadText,
101 Spin, 102 Spin,
102 CustomUploadComp, 103 CustomUploadComp,
  104 + CloseCircleOutlined,
103 }, 105 },
104 setup() { 106 setup() {
105 const loading = ref(false); 107 const loading = ref(false);
@@ -188,6 +190,11 @@ @@ -188,6 +190,11 @@
188 storage.set('platformInfo', newFieldValue); 190 storage.set('platformInfo', newFieldValue);
189 } 191 }
190 192
  193 + // 删除浏览器ico图标
  194 + const handleDelete = () => {
  195 + iconPic.value = '';
  196 + };
  197 +
191 onMounted(async () => { 198 onMounted(async () => {
192 const res = await getPlatForm(); 199 const res = await getPlatForm();
193 setFieldsValue(res); 200 setFieldsValue(res);
@@ -227,6 +234,7 @@ @@ -227,6 +234,7 @@
227 handleResetInfo, 234 handleResetInfo,
228 handleSetBgImgUrl, 235 handleSetBgImgUrl,
229 handleSetLogoImgUrl, 236 handleSetLogoImgUrl,
  237 + handleDelete,
230 }; 238 };
231 }, 239 },
232 }); 240 });
@@ -251,4 +259,12 @@ @@ -251,4 +259,12 @@
251 width: 100%; 259 width: 100%;
252 height: 100%; 260 height: 100%;
253 } 261 }
  262 +
  263 + .icon-delete {
  264 + top: -13px;
  265 + right: -13px;
  266 + color: rgb(146, 145, 145);
  267 + font-size: 1rem;
  268 + z-index: 9999;
  269 + }
254 </style> 270 </style>
1 <script setup name="CustomUploadComp" lang="ts"> 1 <script setup name="CustomUploadComp" lang="ts">
2 - import { PlusOutlined } from '@ant-design/icons-vue'; 2 + import { PlusOutlined, CloseCircleOutlined } from '@ant-design/icons-vue';
3 import { Upload, Spin } from 'ant-design-vue'; 3 import { Upload, Spin } from 'ant-design-vue';
4 import { ref, watchEffect } from 'vue'; 4 import { ref, watchEffect } from 'vue';
5 import { useUpload } from './hooks/useUploadFile.hook'; 5 import { useUpload } from './hooks/useUploadFile.hook';
@@ -40,6 +40,12 @@ @@ -40,6 +40,12 @@
40 } 40 }
41 }; 41 };
42 42
  43 + // 删除图片
  44 + const handleDelete = () => {
  45 + uploadImgUrl.value = '';
  46 + emit('setImg', uploadImgUrl.value);
  47 + };
  48 +
43 watchEffect(() => { 49 watchEffect(() => {
44 init(); 50 init();
45 }); 51 });
@@ -59,7 +65,10 @@ @@ -59,7 +65,10 @@
59 :customRequest="customUpload" 65 :customRequest="customUpload"
60 :before-upload="beforeUploadVerify" 66 :before-upload="beforeUploadVerify"
61 > 67 >
62 - <img v-if="uploadImgUrl" class="fill-img" :src="uploadImgUrl" alt="avatar" /> 68 + <div v-if="uploadImgUrl" class="w-full h-full modal-div relative">
  69 + <img class="fill-img" :src="uploadImgUrl" alt="avatar" />
  70 + <CloseCircleOutlined class="absolute icon-delete" @click.stop="handleDelete" />
  71 + </div>
63 <div v-else> 72 <div v-else>
64 <Spin v-if="uploadLoading" tip="正在上传中..." /> 73 <Spin v-if="uploadLoading" tip="正在上传中..." />
65 <PlusOutlined v-else /> 74 <PlusOutlined v-else />
@@ -74,4 +83,12 @@ @@ -74,4 +83,12 @@
74 width: 100%; 83 width: 100%;
75 height: 100%; 84 height: 100%;
76 } 85 }
  86 +
  87 + .icon-delete {
  88 + top: -13px;
  89 + right: -13px;
  90 + color: rgb(146, 145, 145);
  91 + font-size: 1rem;
  92 + z-index: 9999;
  93 + }
77 </style> 94 </style>
@@ -21,13 +21,18 @@ @@ -21,13 +21,18 @@
21 </Authority> 21 </Authority>
22 </template> 22 </template>
23 <template #status="{ record }"> 23 <template #status="{ record }">
24 - <Switch  
25 - :checked="record.status === 1"  
26 - :loading="record.pendingStatus"  
27 - checkedChildren="启用"  
28 - unCheckedChildren="禁用"  
29 - @change="(checked:boolean)=>statusChange(checked,record)"  
30 - /> 24 + <Authority value="api:yt:role:status">
  25 + <Switch
  26 + :checked="record.status === 1"
  27 + :loading="record.pendingStatus"
  28 + checkedChildren="启用"
  29 + unCheckedChildren="禁用"
  30 + @change="(checked:boolean)=>statusChange(checked,record)"
  31 + />
  32 + </Authority>
  33 + <Tag v-if="!hasPermission('api:yt:role:status')" :color="record.status ? 'green' : 'red'">
  34 + {{ record.status ? '启用' : '禁用' }}
  35 + </Tag>
31 </template> 36 </template>
32 <template #action="{ record }"> 37 <template #action="{ record }">
33 <TableAction 38 <TableAction
@@ -67,12 +72,14 @@ @@ -67,12 +72,14 @@
67 import { Authority } from '/@/components/Authority'; 72 import { Authority } from '/@/components/Authority';
68 import { useBatchDelete } from '/@/hooks/web/useBatchDelete'; 73 import { useBatchDelete } from '/@/hooks/web/useBatchDelete';
69 import { useMessage } from '/@/hooks/web/useMessage'; 74 import { useMessage } from '/@/hooks/web/useMessage';
70 - import { Switch, Popconfirm } from 'ant-design-vue'; 75 + import { Switch, Popconfirm, Tag } from 'ant-design-vue';
  76 + import { usePermission } from '/@/hooks/web/usePermission';
71 77
72 export default defineComponent({ 78 export default defineComponent({
73 name: 'RoleManagement', 79 name: 'RoleManagement',
74 - components: { BasicTable, RoleDrawer, TableAction, Authority, Switch, Popconfirm }, 80 + components: { BasicTable, RoleDrawer, TableAction, Authority, Switch, Popconfirm, Tag },
75 setup() { 81 setup() {
  82 + const { hasPermission } = usePermission();
76 const [registerDrawer, { openDrawer }] = useDrawer(); 83 const [registerDrawer, { openDrawer }] = useDrawer();
77 function handleSuccess() { 84 function handleSuccess() {
78 reload(); 85 reload();
@@ -157,6 +164,7 @@ @@ -157,6 +164,7 @@
157 hasBatchDelete, 164 hasBatchDelete,
158 handleDeleteOrBatchDelete, 165 handleDeleteOrBatchDelete,
159 statusChange, 166 statusChange,
  167 + hasPermission,
160 }; 168 };
161 }, 169 },
162 }); 170 });
@@ -7,7 +7,7 @@ export const validateDevicePicker = () => { @@ -7,7 +7,7 @@ export const validateDevicePicker = () => {
7 validateTrigger: 'blur', 7 validateTrigger: 'blur',
8 validator(_rule: Recordable, value: Recordable, _callback: Fn) { 8 validator(_rule: Recordable, value: Recordable, _callback: Fn) {
9 const device = Reflect.get(value || {}, FormFieldsEnum.DEVICE); 9 const device = Reflect.get(value || {}, FormFieldsEnum.DEVICE);
10 - if (!device) return Promise.reject('请选择设备'); 10 + if (!device || !device.length) return Promise.reject('请选择设备');
11 return Promise.resolve(); 11 return Promise.resolve();
12 }, 12 },
13 } as Rule; 13 } as Rule;
@@ -41,7 +41,9 @@ @@ -41,7 +41,9 @@
41 const inputType = ref(props.type); 41 const inputType = ref(props.type);
42 42
43 const getInputValue = computed(() => { 43 const getInputValue = computed(() => {
44 - const { type, value, toUpperCase } = props; 44 + const { type, toUpperCase } = props;
  45 + let { value } = props;
  46 + if (isNaN(value as number)) value = undefined;
45 47
46 if (isNullOrUnDef(value)) return value; 48 if (isNullOrUnDef(value)) return value;
47 49
@@ -133,6 +133,7 @@ @@ -133,6 +133,7 @@
133 text: '详情', 133 text: '详情',
134 event: DropMenuEvent.DETAIL, 134 event: DropMenuEvent.DETAIL,
135 icon: 'ant-design:eye-outlined', 135 icon: 'ant-design:eye-outlined',
  136 + auth: PermissionEnum.DETAIL,
136 onClick: emit.bind(null, 'detail', getRecord), 137 onClick: emit.bind(null, 'detail', getRecord),
137 }, 138 },
138 { 139 {
@@ -7,6 +7,7 @@ export enum PermissionEnum { @@ -7,6 +7,7 @@ export enum PermissionEnum {
7 DELETE = 'api:yt:task_center:delete', 7 DELETE = 'api:yt:task_center:delete',
8 ALLOW = 'api:yt:task_center:cancel:allow', 8 ALLOW = 'api:yt:task_center:cancel:allow',
9 EXECUTE = 'api:yt:task_center:immediate:execute', 9 EXECUTE = 'api:yt:task_center:immediate:execute',
  10 + DETAIL = 'api:yt:task_center:get',
10 } 11 }
11 12
12 export enum FormFieldsEnum { 13 export enum FormFieldsEnum {
@@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
16 :replaceFields="{ title: 'name', key: 'id' }" 16 :replaceFields="{ title: 'name', key: 'id' }"
17 :checkedKeys="roleMenus" 17 :checkedKeys="roleMenus"
18 @check="handleCheckClick" 18 @check="handleCheckClick"
  19 + @unSelectAll="handleUnSelectAll"
19 checkable 20 checkable
20 toolbar 21 toolbar
21 ref="treeRef" 22 ref="treeRef"
@@ -128,6 +129,11 @@ @@ -128,6 +129,11 @@
128 }); 129 });
129 const getTitle = computed(() => (!unref(isUpdate) ? '新增角色' : '编辑角色')); 130 const getTitle = computed(() => (!unref(isUpdate) ? '新增角色' : '编辑角色'));
130 131
  132 + // 取消全部的时候清除回显时获取的
  133 + const handleUnSelectAll = () => {
  134 + checkedKeysWithHalfChecked.value = [];
  135 + };
  136 +
131 async function handleSubmit() { 137 async function handleSubmit() {
132 setDrawerProps({ loading: true, confirmLoading: true }); 138 setDrawerProps({ loading: true, confirmLoading: true });
133 const { createMessage } = useMessage(); 139 const { createMessage } = useMessage();
@@ -143,7 +149,8 @@ @@ -143,7 +149,8 @@
143 roleType: RoleEnum.TENANT_ADMIN, 149 roleType: RoleEnum.TENANT_ADMIN,
144 menu, 150 menu,
145 }; 151 };
146 - if (req.menu == undefined) return createMessage.error('请勾选权限菜单'); 152 + if (req.menu == undefined || !req.menu.length)
  153 + return createMessage.error('请勾选权限菜单');
147 const res = await saveOrUpdateRoleInfoWithMenu(req); 154 const res = await saveOrUpdateRoleInfoWithMenu(req);
148 if (res) { 155 if (res) {
149 closeDrawer(); 156 closeDrawer();
@@ -247,6 +254,7 @@ @@ -247,6 +254,7 @@
247 roleMenus, 254 roleMenus,
248 treeRef, 255 treeRef,
249 handleCheckClick, 256 handleCheckClick,
  257 + handleUnSelectAll,
250 }; 258 };
251 }, 259 },
252 }); 260 });
@@ -9,6 +9,7 @@ export enum VisualBoardPermission { @@ -9,6 +9,7 @@ export enum VisualBoardPermission {
9 UPDATE = 'api:yt:data_board:update:update', 9 UPDATE = 'api:yt:data_board:update:update',
10 DELETE = 'api:yt:data_board:delete', 10 DELETE = 'api:yt:data_board:delete',
11 CREATE = '', 11 CREATE = '',
  12 + SHARE = 'api:yt:data_board:share',
12 DETAIL = 'api:yt:data_component:list', 13 DETAIL = 'api:yt:data_component:list',
13 } 14 }
14 15
@@ -99,19 +99,22 @@ @@ -99,19 +99,22 @@
99 const dropMenuList = computed<DropMenu[]>(() => { 99 const dropMenuList = computed<DropMenu[]>(() => {
100 const hasUpdatePermission = hasPermission(VisualBoardPermission.UPDATE); 100 const hasUpdatePermission = hasPermission(VisualBoardPermission.UPDATE);
101 const hasDeletePermission = hasPermission(VisualBoardPermission.DELETE); 101 const hasDeletePermission = hasPermission(VisualBoardPermission.DELETE);
102 - const basicMenu: DropMenu[] = [  
103 - {  
104 - text: '分享',  
105 - event: MoreActionEvent.SHARE,  
106 - icon: 'ant-design:share-alt-outlined',  
107 - },  
108 - ]; 102 + const hasSharePermission = hasPermission(VisualBoardPermission.SHARE);
  103 + let basicMenu: DropMenu[] = [];
109 if (hasUpdatePermission) 104 if (hasUpdatePermission)
110 basicMenu.push({ 105 basicMenu.push({
111 text: '编辑', 106 text: '编辑',
112 event: MoreActionEvent.EDIT, 107 event: MoreActionEvent.EDIT,
113 icon: 'ant-design:edit-outlined', 108 icon: 'ant-design:edit-outlined',
114 }); 109 });
  110 + if (hasSharePermission) {
  111 + basicMenu.push({
  112 + text: '分享',
  113 + event: MoreActionEvent.SHARE,
  114 + icon: 'ant-design:share-alt-outlined',
  115 + });
  116 + }
  117 +
115 if (hasDeletePermission) 118 if (hasDeletePermission)
116 basicMenu.push({ 119 basicMenu.push({
117 text: '删除', 120 text: '删除',
@@ -122,7 +122,7 @@ @@ -122,7 +122,7 @@
122 }); 122 });
123 }; 123 };
124 124
125 - const handleCopy = (record: DataSourceType) => { 125 + const handleCopy = async (record: DataSourceType) => {
126 const { key } = props.componentConfig || {}; 126 const { key } = props.componentConfig || {};
127 if (key == 'HumidityComponent2' && props.dataSource.length >= 6) { 127 if (key == 'HumidityComponent2' && props.dataSource.length >= 6) {
128 createMessage.warning('绑定的数据源不能超过6条~'); 128 createMessage.warning('绑定的数据源不能超过6条~');
@@ -134,7 +134,7 @@ @@ -134,7 +134,7 @@
134 return; 134 return;
135 } 135 }
136 136
137 - const allValues = getFormValues(); 137 + const allValues = await getFormValues();
138 const currentRecord = getFormValueByUUID(record.uuid); 138 const currentRecord = getFormValueByUUID(record.uuid);
139 const uuid = trackUpdate(); 139 const uuid = trackUpdate();
140 const raw = toRaw(record); 140 const raw = toRaw(record);
@@ -173,7 +173,7 @@ @@ -173,7 +173,7 @@
173 173
174 const handleSettingOk = (data: DataSourceType) => { 174 const handleSettingOk = (data: DataSourceType) => {
175 const { uuid } = data; 175 const { uuid } = data;
176 - const _dataSource = cloneDeep(props.dataSource); 176 + const _dataSource = cloneDeep(getFormValues());
177 177
178 const index = _dataSource.findIndex((item) => item.uuid === uuid); 178 const index = _dataSource.findIndex((item) => item.uuid === uuid);
179 179
@@ -95,6 +95,11 @@ @@ -95,6 +95,11 @@
95 }; 95 };
96 setFormValues(record); 96 setFormValues(record);
97 } else { 97 } else {
  98 + selectWidgetKeys.value = {
  99 + componentKey: TextComponent1Config.key,
  100 + categoryKey: PackagesCategoryEnum.TEXT,
  101 + };
  102 + activeKey.value = TabKeyEnum.BASIC;
98 dataSource.value = [genNewDataSourceItem()]; 103 dataSource.value = [genNewDataSourceItem()];
99 } 104 }
100 } 105 }
@@ -16,6 +16,7 @@ export const option: PublicPresetOptions = { @@ -16,6 +16,7 @@ export const option: PublicPresetOptions = {
16 [ComponentConfigFieldEnum.CLOSE_COLOR]: '#FF0000', 16 [ComponentConfigFieldEnum.CLOSE_COLOR]: '#FF0000',
17 [ComponentConfigFieldEnum.SHOW_DEVICE_NAME]: true, 17 [ComponentConfigFieldEnum.SHOW_DEVICE_NAME]: true,
18 [ComponentConfigFieldEnum.SHOW_TIME]: false, 18 [ComponentConfigFieldEnum.SHOW_TIME]: false,
  19 + [ComponentConfigFieldEnum.FONT_SIZE]: 14,
19 }; 20 };
20 21
21 export default class Config extends PublicConfigClass implements CreateComponentType { 22 export default class Config extends PublicConfigClass implements CreateComponentType {
@@ -36,6 +36,23 @@ @@ -36,6 +36,23 @@
36 component: 'Checkbox', 36 component: 'Checkbox',
37 defaultValue: option.showTime, 37 defaultValue: option.showTime,
38 }, 38 },
  39 + {
  40 + field: ComponentConfigFieldEnum.FONT_SIZE,
  41 + label: '文本字体大小',
  42 + component: 'InputNumber',
  43 + defaultValue: 14,
  44 + componentProps: {
  45 + min: 0,
  46 + formatter: (e) => {
  47 + const value = e.replace(/^0/g, '');
  48 + if (value) {
  49 + return value.replace(/^0/g, '');
  50 + } else {
  51 + return 0;
  52 + }
  53 + },
  54 + },
  55 + },
39 ], 56 ],
40 showActionButtonGroup: false, 57 showActionButtonGroup: false,
41 labelWidth: 120, 58 labelWidth: 120,
@@ -24,6 +24,7 @@ @@ -24,6 +24,7 @@
24 showTime: boolean; 24 showTime: boolean;
25 status: IStatus; 25 status: IStatus;
26 time: number; 26 time: number;
  27 + fontSize?: number;
27 } 28 }
28 29
29 const props = defineProps<{ 30 const props = defineProps<{
@@ -53,7 +54,11 @@ @@ -53,7 +54,11 @@
53 const getDesign = computed(() => { 54 const getDesign = computed(() => {
54 const { persetOption = {}, option } = props.config; 55 const { persetOption = {}, option } = props.config;
55 const { dataSource } = option; 56 const { dataSource } = option;
56 - const { showDeviceName: presetShowDeviceName, showTime: persetShowTime } = persetOption; 57 + const {
  58 + showDeviceName: presetShowDeviceName,
  59 + showTime: persetShowTime,
  60 + fontSize: persetFontSize,
  61 + } = persetOption;
57 62
58 return { 63 return {
59 dataSource: dataSource?.map((item) => { 64 dataSource: dataSource?.map((item) => {
@@ -63,6 +68,7 @@ @@ -63,6 +68,7 @@
63 deviceName: deviceRename || deviceName, 68 deviceName: deviceRename || deviceName,
64 showDeviceName: componentInfo.showDeviceName ?? presetShowDeviceName, 69 showDeviceName: componentInfo.showDeviceName ?? presetShowDeviceName,
65 showTime: componentInfo.showTime ?? persetShowTime, 70 showTime: componentInfo.showTime ?? persetShowTime,
  71 + fontSize: componentInfo.fontSize || persetFontSize,
66 }; 72 };
67 }), 73 }),
68 }; 74 };
@@ -82,6 +88,7 @@ @@ -82,6 +88,7 @@
82 time: 1689574726, 88 time: 1689574726,
83 showDeviceName: true, 89 showDeviceName: true,
84 showTime: true, 90 showTime: true,
  91 + fontSize: 14,
85 }, 92 },
86 ]); 93 ]);
87 94
@@ -133,6 +140,7 @@ @@ -133,6 +140,7 @@
133 showTime: item.showTime, 140 showTime: item.showTime,
134 status: { text: '', color: '' }, 141 status: { text: '', color: '' },
135 time: 0, 142 time: 0,
  143 + fontSize: item.fontSize,
136 }; 144 };
137 }) as any; 145 }) as any;
138 const { data, update } = message; 146 const { data, update } = message;
@@ -163,7 +171,7 @@ @@ -163,7 +171,7 @@
163 <main :style="getScale" class="w-full h-full flex justify-center items-center"> 171 <main :style="getScale" class="w-full h-full flex justify-center items-center">
164 <div v-for="item in alarmStatusList" :key="item.id" class="flex flex-col items-center"> 172 <div v-for="item in alarmStatusList" :key="item.id" class="flex flex-col items-center">
165 <div class="flex justify-center items-center flex-col"> 173 <div class="flex justify-center items-center flex-col">
166 - <div class="text-gray-500 text-sm truncate" 174 + <div class="text-gray-500 truncate" :style="{ fontSize: item.fontSize + 'px' }"
167 >{{ 175 >{{
168 item.status.text 176 item.status.text
169 ? item.showDeviceName 177 ? item.showDeviceName
@@ -11,6 +11,7 @@ import { ComponentConfigFieldEnum } from '../../../enum'; @@ -11,6 +11,7 @@ import { ComponentConfigFieldEnum } from '../../../enum';
11 11
12 export const option: PublicPresetOptions = { 12 export const option: PublicPresetOptions = {
13 [ComponentConfigFieldEnum.SHOW_DEVICE_NAME]: false, 13 [ComponentConfigFieldEnum.SHOW_DEVICE_NAME]: false,
  14 + [ComponentConfigFieldEnum.FONT_SIZE]: 14,
14 // [ComponentConfigFieldEnum.FONT_COLOR]: '#000', 15 // [ComponentConfigFieldEnum.FONT_COLOR]: '#000',
15 }; 16 };
16 17
@@ -19,6 +19,12 @@ @@ -19,6 +19,12 @@
19 component: 'Checkbox', 19 component: 'Checkbox',
20 defaultValue: option.showDeviceName, 20 defaultValue: option.showDeviceName,
21 }, 21 },
  22 + {
  23 + field: ComponentConfigFieldEnum.FONT_SIZE,
  24 + label: '文本字体大小',
  25 + component: 'InputNumber',
  26 + defaultValue: 14,
  27 + },
22 ], 28 ],
23 showActionButtonGroup: false, 29 showActionButtonGroup: false,
24 labelWidth: 120, 30 labelWidth: 120,
@@ -32,6 +32,10 @@ @@ -32,6 +32,10 @@
32 transportType: value.transportType, 32 transportType: value.transportType,
33 service: value.service, 33 service: value.service,
34 command: value.command, 34 command: value.command,
  35 + openService: value.openService,
  36 + closeService: value.closeService,
  37 + openCommand: value.openCommand,
  38 + closeCommand: value.closeCommand,
35 commandType: value.commandType, 39 commandType: value.commandType,
36 callType: value.callType, 40 callType: value.callType,
37 }, 41 },
@@ -45,6 +49,10 @@ @@ -45,6 +49,10 @@
45 ...record, 49 ...record,
46 transportType: customCommand?.transportType || (record as Recordable).transportType, 50 transportType: customCommand?.transportType || (record as Recordable).transportType,
47 service: customCommand?.service || (record as Recordable).service, 51 service: customCommand?.service || (record as Recordable).service,
  52 + openService: customCommand?.openService || (record as Recordable).openService,
  53 + closeService: customCommand?.closeService || (record as Recordable).closeService,
  54 + openCommand: customCommand?.openCommand || (record as Recordable).openCommand,
  55 + closeCommand: customCommand?.closeCommand || (record as Recordable).closeCommand,
48 command: customCommand?.command || (record as Recordable).command, 56 command: customCommand?.command || (record as Recordable).command,
49 commandType: customCommand?.commandType || (record as Recordable).commandType, 57 commandType: customCommand?.commandType || (record as Recordable).commandType,
50 callType: customCommand?.callType || (record as Recordable).callType, 58 callType: customCommand?.callType || (record as Recordable).callType,
@@ -2,12 +2,13 @@ @@ -2,12 +2,13 @@
2 import { ComponentPropsConfigType } from '/@/views/visual/packages/index.type'; 2 import { ComponentPropsConfigType } from '/@/views/visual/packages/index.type';
3 import { option } from './config'; 3 import { option } from './config';
4 import { Spin } from 'ant-design-vue'; 4 import { Spin } from 'ant-design-vue';
5 - import { computed, ref } from 'vue'; 5 + import { computed, ref, unref } from 'vue';
6 import { useComponentScale } from '../../../hook/useComponentScale'; 6 import { useComponentScale } from '../../../hook/useComponentScale';
7 import { useSendCommand } from '../../../hook/useSendCommand'; 7 import { useSendCommand } from '../../../hook/useSendCommand';
8 import { DeviceName } from '/@/views/visual/commonComponents/DeviceName'; 8 import { DeviceName } from '/@/views/visual/commonComponents/DeviceName';
9 import { DataFetchUpdateFn } from '../../../hook/socket/useSocket.type'; 9 import { DataFetchUpdateFn } from '../../../hook/socket/useSocket.type';
10 import { useDataFetch } from '../../../hook/socket/useSocket'; 10 import { useDataFetch } from '../../../hook/socket/useSocket';
  11 + import { getSendValues } from '../config';
11 12
12 const props = defineProps<{ 13 const props = defineProps<{
13 config: ComponentPropsConfigType<typeof option>; 14 config: ComponentPropsConfigType<typeof option>;
@@ -18,10 +19,28 @@ @@ -18,10 +19,28 @@
18 const currentValue = ref(false); 19 const currentValue = ref(false);
19 20
20 const getDesign = computed(() => { 21 const getDesign = computed(() => {
21 - const { option } = props.config;  
22 - const { attribute, attributeRename, attributeName } = option; 22 + const { option, persetOption } = props.config;
  23 + const {
  24 + attribute,
  25 + attributeRename,
  26 + attributeName,
  27 + componentInfo,
  28 + commandType,
  29 + extensionDesc,
  30 + codeType,
  31 + deviceCode,
  32 + customCommand,
  33 + } = option;
  34 + const { fontSize: persetFontSize } = persetOption || {};
  35 + const { fontSize } = componentInfo || {};
23 return { 36 return {
24 attribute: attributeRename || attributeName || attribute, 37 attribute: attributeRename || attributeName || attribute,
  38 + fontSize: fontSize || persetFontSize || 14,
  39 + extensionDesc: extensionDesc ? JSON.parse(extensionDesc) : {},
  40 + commandType,
  41 + codeType,
  42 + deviceCode,
  43 + customCommand,
25 }; 44 };
26 }); 45 });
27 46
@@ -29,8 +48,12 @@ @@ -29,8 +48,12 @@
29 const handleChange = async (event: Event) => { 48 const handleChange = async (event: Event) => {
30 const target = event.target as HTMLInputElement; 49 const target = event.target as HTMLInputElement;
31 const value = target.checked; 50 const value = target.checked;
  51 + const { option } = props.config || {};
32 52
33 - const flag = await sendCommand(props.config.option, value); 53 + const { values, isModbusCommand, sendValue } =
  54 + (await getSendValues(option, unref(getDesign), value)) || {};
  55 +
  56 + const flag = await sendCommand(values, isModbusCommand ? sendValue : value, isModbusCommand);
34 if (flag) currentValue.value = value; 57 if (flag) currentValue.value = value;
35 flag ? (currentValue.value = value) : (target.checked = !value); 58 flag ? (currentValue.value = value) : (target.checked = !value);
36 }; 59 };
@@ -61,7 +84,10 @@ @@ -61,7 +84,10 @@
61 <span class="on">ON</span> 84 <span class="on">ON</span>
62 <span class="off">OFF</span> 85 <span class="off">OFF</span>
63 </label> 86 </label>
64 - <div class="text-center mt-2 text-gray-700" :style="getScale"> 87 + <div
  88 + class="text-center mt-2 text-gray-700"
  89 + :style="{ ...getScale, fontSize: getDesign.fontSize + 'px' }"
  90 + >
65 {{ getDesign.attribute || '属性' }} 91 {{ getDesign.attribute || '属性' }}
66 </div> 92 </div>
67 </Spin> 93 </Spin>
@@ -13,6 +13,7 @@ export const option: PublicPresetOptions = { @@ -13,6 +13,7 @@ export const option: PublicPresetOptions = {
13 [ComponentConfigFieldEnum.ICON]: 'shuiwen', 13 [ComponentConfigFieldEnum.ICON]: 'shuiwen',
14 [ComponentConfigFieldEnum.ICON_COLOR]: '#377DFF', 14 [ComponentConfigFieldEnum.ICON_COLOR]: '#377DFF',
15 [ComponentConfigFieldEnum.SHOW_DEVICE_NAME]: false, 15 [ComponentConfigFieldEnum.SHOW_DEVICE_NAME]: false,
  16 + [ComponentConfigFieldEnum.FONT_SIZE]: 14,
16 }; 17 };
17 18
18 export default class Config extends PublicConfigClass implements CreateComponentType { 19 export default class Config extends PublicConfigClass implements CreateComponentType {
@@ -32,6 +32,12 @@ @@ -32,6 +32,12 @@
32 component: 'Checkbox', 32 component: 'Checkbox',
33 defaultValue: option.showDeviceName, 33 defaultValue: option.showDeviceName,
34 }, 34 },
  35 + {
  36 + field: ComponentConfigFieldEnum.FONT_SIZE,
  37 + label: '文本字体大小',
  38 + component: 'InputNumber',
  39 + defaultValue: option.fontSize,
  40 + },
35 ], 41 ],
36 showActionButtonGroup: false, 42 showActionButtonGroup: false,
37 labelWidth: 120, 43 labelWidth: 120,
@@ -32,6 +32,10 @@ @@ -32,6 +32,10 @@
32 transportType: value.transportType, 32 transportType: value.transportType,
33 service: value.service, 33 service: value.service,
34 command: value.command, 34 command: value.command,
  35 + openService: value.openService,
  36 + closeService: value.closeService,
  37 + openCommand: value.openCommand,
  38 + closeCommand: value.closeCommand,
35 commandType: value.commandType, 39 commandType: value.commandType,
36 callType: value.callType, 40 callType: value.callType,
37 }, 41 },
@@ -41,14 +45,20 @@ @@ -41,14 +45,20 @@
41 45
42 const setFormValues = (record: DataSource) => { 46 const setFormValues = (record: DataSource) => {
43 const { customCommand } = record; 47 const { customCommand } = record;
44 - return setFieldsValue({ 48 + const values = {
45 ...record, 49 ...record,
46 transportType: customCommand?.transportType || (record as Recordable).transportType, 50 transportType: customCommand?.transportType || (record as Recordable).transportType,
47 service: customCommand?.service || (record as Recordable).service, 51 service: customCommand?.service || (record as Recordable).service,
48 command: customCommand?.command || (record as Recordable).command, 52 command: customCommand?.command || (record as Recordable).command,
  53 + openService: customCommand?.openService || (record as Recordable).openService,
  54 + closeService: customCommand?.closeService || (record as Recordable).closeService,
  55 + openCommand: customCommand?.openCommand || (record as Recordable).openCommand,
  56 + closeCommand: customCommand?.closeCommand || (record as Recordable).closeCommand,
49 commandType: customCommand?.commandType || (record as Recordable).commandType, 57 commandType: customCommand?.commandType || (record as Recordable).commandType,
50 callType: customCommand?.callType || (record as Recordable).callType, 58 callType: customCommand?.callType || (record as Recordable).callType,
51 - } as unknown as Partial<CommonDataSourceBindValueType>); 59 + } as unknown as Partial<CommonDataSourceBindValueType>;
  60 +
  61 + return setFieldsValue(values);
52 }; 62 };
53 63
54 defineExpose({ 64 defineExpose({
@@ -10,6 +10,7 @@ @@ -10,6 +10,7 @@
10 import { DeviceName } from '/@/views/visual/commonComponents/DeviceName'; 10 import { DeviceName } from '/@/views/visual/commonComponents/DeviceName';
11 import { DataFetchUpdateFn } from '../../../hook/socket/useSocket.type'; 11 import { DataFetchUpdateFn } from '../../../hook/socket/useSocket.type';
12 import { useDataFetch } from '../../../hook/socket/useSocket'; 12 import { useDataFetch } from '../../../hook/socket/useSocket';
  13 + import { getSendValues } from '../config';
13 14
14 const props = defineProps<{ 15 const props = defineProps<{
15 config: ComponentPropsConfigType<typeof option>; 16 config: ComponentPropsConfigType<typeof option>;
@@ -19,19 +20,50 @@ @@ -19,19 +20,50 @@
19 20
20 const getDesign = computed(() => { 21 const getDesign = computed(() => {
21 const { option, persetOption } = props.config; 22 const { option, persetOption } = props.config;
22 - const { componentInfo, attribute, attributeRename, attributeName } = option;  
23 - const { icon: presetIcon, iconColor: presetIconColor } = persetOption || {};  
24 - const { icon, iconColor } = componentInfo || {}; 23 + const {
  24 + componentInfo,
  25 + attribute,
  26 + attributeRename,
  27 + attributeName,
  28 + commandType,
  29 + extensionDesc,
  30 + codeType,
  31 + deviceCode,
  32 + customCommand,
  33 + } = option;
  34 + const {
  35 + icon: presetIcon,
  36 + iconColor: presetIconColor,
  37 + fontSize: persetFontSize,
  38 + } = persetOption || {};
  39 + const { icon, iconColor, fontSize } = componentInfo || {};
  40 +
25 return { 41 return {
26 icon: icon ?? presetIcon, 42 icon: icon ?? presetIcon,
27 iconColor: iconColor || presetIconColor, 43 iconColor: iconColor || presetIconColor,
28 attribute: attributeRename || attributeName || attribute, 44 attribute: attributeRename || attributeName || attribute,
  45 + extensionDesc: extensionDesc ? JSON.parse(extensionDesc) : {},
  46 + fontSize: fontSize || persetFontSize || 14,
  47 + commandType,
  48 + codeType,
  49 + deviceCode,
  50 + customCommand,
29 }; 51 };
30 }); 52 });
31 53
32 const { sendCommand, loading } = useSendCommand(); 54 const { sendCommand, loading } = useSendCommand();
  55 +
33 const handleChange = async () => { 56 const handleChange = async () => {
34 - const flag = await sendCommand(props.config.option, unref(checked)); 57 + const { option } = props.config || {};
  58 +
  59 + const { values, isModbusCommand, sendValue } =
  60 + (await getSendValues(option, unref(getDesign), unref(checked))) || {};
  61 +
  62 + const flag = await sendCommand(
  63 + values,
  64 + isModbusCommand ? sendValue : unref(checked),
  65 + isModbusCommand
  66 + );
35 if (!flag) checked.value = !unref(checked); 67 if (!flag) checked.value = !unref(checked);
36 }; 68 };
37 69
@@ -57,7 +89,10 @@ @@ -57,7 +89,10 @@
57 :style="{ color: getDesign.iconColor }" 89 :style="{ color: getDesign.iconColor }"
58 :size="50" 90 :size="50"
59 /> 91 />
60 - <span class="mt-3 truncate text-gray-500 text-xs text-center"> 92 + <span
  93 + class="mt-3 truncate text-gray-500 text-center"
  94 + :style="{ fontSize: getDesign.fontSize + 'px' }"
  95 + >
61 {{ getDesign.attribute || '属性' }} 96 {{ getDesign.attribute || '属性' }}
62 </span> 97 </span>
63 </div> 98 </div>
@@ -11,6 +11,7 @@ import { ComponentConfigFieldEnum } from '../../../enum'; @@ -11,6 +11,7 @@ import { ComponentConfigFieldEnum } from '../../../enum';
11 11
12 export const option: PublicPresetOptions = { 12 export const option: PublicPresetOptions = {
13 [ComponentConfigFieldEnum.SHOW_DEVICE_NAME]: false, 13 [ComponentConfigFieldEnum.SHOW_DEVICE_NAME]: false,
  14 + [ComponentConfigFieldEnum.FONT_SIZE]: 14,
14 // [ComponentConfigFieldEnum.FONT_COLOR]: '#000', 15 // [ComponentConfigFieldEnum.FONT_COLOR]: '#000',
15 }; 16 };
16 17
@@ -18,6 +18,12 @@ @@ -18,6 +18,12 @@
18 component: 'Checkbox', 18 component: 'Checkbox',
19 defaultValue: option.showDeviceName, 19 defaultValue: option.showDeviceName,
20 }, 20 },
  21 + {
  22 + field: ComponentConfigFieldEnum.FONT_SIZE,
  23 + label: '文本字体大小',
  24 + component: 'InputNumber',
  25 + defaultValue: option.fontSize,
  26 + },
21 ], 27 ],
22 showActionButtonGroup: false, 28 showActionButtonGroup: false,
23 labelWidth: 120, 29 labelWidth: 120,
@@ -32,6 +32,10 @@ @@ -32,6 +32,10 @@
32 transportType: value.transportType, 32 transportType: value.transportType,
33 service: value.service, 33 service: value.service,
34 command: value.command, 34 command: value.command,
  35 + openService: value.openService,
  36 + closeService: value.closeService,
  37 + openCommand: value.openCommand,
  38 + closeCommand: value.closeCommand,
35 commandType: value.commandType, 39 commandType: value.commandType,
36 callType: value.callType, 40 callType: value.callType,
37 }, 41 },
@@ -45,6 +49,10 @@ @@ -45,6 +49,10 @@
45 ...record, 49 ...record,
46 transportType: customCommand?.transportType || (record as Recordable).transportType, 50 transportType: customCommand?.transportType || (record as Recordable).transportType,
47 service: customCommand?.service || (record as Recordable).service, 51 service: customCommand?.service || (record as Recordable).service,
  52 + openService: customCommand?.openService || (record as Recordable).openService,
  53 + closeService: customCommand?.closeService || (record as Recordable).closeService,
  54 + openCommand: customCommand?.openCommand || (record as Recordable).openCommand,
  55 + closeCommand: customCommand?.closeCommand || (record as Recordable).closeCommand,
48 command: customCommand?.command || (record as Recordable).command, 56 command: customCommand?.command || (record as Recordable).command,
49 commandType: customCommand?.commandType || (record as Recordable).commandType, 57 commandType: customCommand?.commandType || (record as Recordable).commandType,
50 callType: customCommand?.callType || (record as Recordable).callType, 58 callType: customCommand?.callType || (record as Recordable).callType,
@@ -2,12 +2,13 @@ @@ -2,12 +2,13 @@
2 import { ComponentPropsConfigType } from '/@/views/visual/packages/index.type'; 2 import { ComponentPropsConfigType } from '/@/views/visual/packages/index.type';
3 import { option } from './config'; 3 import { option } from './config';
4 import { Spin } from 'ant-design-vue'; 4 import { Spin } from 'ant-design-vue';
5 - import { computed, ref } from 'vue'; 5 + import { computed, ref, unref } from 'vue';
6 import { useComponentScale } from '../../../hook/useComponentScale'; 6 import { useComponentScale } from '../../../hook/useComponentScale';
7 import { useSendCommand } from '../../../hook/useSendCommand'; 7 import { useSendCommand } from '../../../hook/useSendCommand';
8 import { DeviceName } from '/@/views/visual/commonComponents/DeviceName'; 8 import { DeviceName } from '/@/views/visual/commonComponents/DeviceName';
9 import { DataFetchUpdateFn } from '../../../hook/socket/useSocket.type'; 9 import { DataFetchUpdateFn } from '../../../hook/socket/useSocket.type';
10 import { useDataFetch } from '../../../hook/socket/useSocket'; 10 import { useDataFetch } from '../../../hook/socket/useSocket';
  11 + import { getSendValues } from '../config';
11 12
12 const props = defineProps<{ 13 const props = defineProps<{
13 config: ComponentPropsConfigType<typeof option>; 14 config: ComponentPropsConfigType<typeof option>;
@@ -18,10 +19,28 @@ @@ -18,10 +19,28 @@
18 const currentValue = ref(false); 19 const currentValue = ref(false);
19 20
20 const getDesign = computed(() => { 21 const getDesign = computed(() => {
21 - const { option } = props.config;  
22 - const { attribute, attributeRename, attributeName } = option; 22 + const { option, persetOption } = props.config;
  23 + const {
  24 + attribute,
  25 + attributeRename,
  26 + attributeName,
  27 + commandType,
  28 + extensionDesc,
  29 + codeType,
  30 + deviceCode,
  31 + customCommand,
  32 + componentInfo,
  33 + } = option;
  34 + const { fontSize: persetFontSize } = persetOption || {};
  35 + const { fontSize } = componentInfo || {};
23 return { 36 return {
24 attribute: attributeRename || attributeName || attribute, 37 attribute: attributeRename || attributeName || attribute,
  38 + extensionDesc: extensionDesc ? JSON.parse(extensionDesc) : {},
  39 + commandType,
  40 + codeType,
  41 + deviceCode,
  42 + customCommand,
  43 + fontSize: fontSize || persetFontSize || 14,
25 }; 44 };
26 }); 45 });
27 46
@@ -29,7 +48,12 @@ @@ -29,7 +48,12 @@
29 const handleChange = async (event: Event) => { 48 const handleChange = async (event: Event) => {
30 const target = event.target as HTMLInputElement; 49 const target = event.target as HTMLInputElement;
31 const value = target.checked; 50 const value = target.checked;
32 - const flag = await sendCommand(props.config.option, value); 51 + const { option } = props.config || {};
  52 +
  53 + const { values, isModbusCommand, sendValue } =
  54 + (await getSendValues(option, unref(getDesign), value)) || {};
  55 +
  56 + const flag = await sendCommand(values, isModbusCommand ? sendValue : value, isModbusCommand);
33 flag ? (currentValue.value = value) : (target.checked = !value); 57 flag ? (currentValue.value = value) : (target.checked = !value);
34 }; 58 };
35 59
@@ -60,9 +84,11 @@ @@ -60,9 +84,11 @@
60 </div> 84 </div>
61 </label> 85 </label>
62 </div> 86 </div>
63 - <div class="text-center mt-2 text-gray-500" :style="getScale">{{  
64 - getDesign.attribute || '属性'  
65 - }}</div> 87 + <div
  88 + class="text-center mt-2 text-gray-500"
  89 + :style="{ ...getScale, fontSize: getDesign.fontSize + 'px' }"
  90 + >{{ getDesign.attribute || '属性' }}</div
  91 + >
66 </Spin> 92 </Spin>
67 </main> 93 </main>
68 </main> 94 </main>
@@ -13,8 +13,11 @@ export const option: PublicPresetOptions = { @@ -13,8 +13,11 @@ export const option: PublicPresetOptions = {
13 [ComponentConfigFieldEnum.SHOW_DEVICE_NAME]: false, 13 [ComponentConfigFieldEnum.SHOW_DEVICE_NAME]: false,
14 [ComponentConfigFieldEnum.CONTROL_BAR_COLOR]: '#0072ff', 14 [ComponentConfigFieldEnum.CONTROL_BAR_COLOR]: '#0072ff',
15 [ComponentConfigFieldEnum.FONT_COLOR]: '#000000', 15 [ComponentConfigFieldEnum.FONT_COLOR]: '#000000',
  16 + [ComponentConfigFieldEnum.TEXT_COLOR]: '#000000',
16 [ComponentConfigFieldEnum.MIN_NUMBER]: 0, 17 [ComponentConfigFieldEnum.MIN_NUMBER]: 0,
17 [ComponentConfigFieldEnum.MAX_NUMBER]: 100, 18 [ComponentConfigFieldEnum.MAX_NUMBER]: 100,
  19 + [ComponentConfigFieldEnum.FONT_SIZE]: 14,
  20 + [ComponentConfigFieldEnum.VALUE_SIZE]: 20,
18 }; 21 };
19 22
20 export default class Config extends PublicConfigClass implements CreateComponentType { 23 export default class Config extends PublicConfigClass implements CreateComponentType {
@@ -8,20 +8,39 @@ @@ -8,20 +8,39 @@
8 const [register, { getFieldsValue, setFieldsValue, resetFields }] = useForm({ 8 const [register, { getFieldsValue, setFieldsValue, resetFields }] = useForm({
9 schemas: [ 9 schemas: [
10 { 10 {
11 - field: ComponentConfigFieldEnum.CONTROL_BAR_COLOR,  
12 - label: '控制栏背景色', 11 + field: ComponentConfigFieldEnum.FONT_COLOR,
  12 + label: '数值字体颜色',
13 component: 'ColorPicker', 13 component: 'ColorPicker',
14 changeEvent: 'update:value', 14 changeEvent: 'update:value',
15 - defaultValue: option.controlBarColor, 15 + defaultValue: option.fontColor,
16 }, 16 },
17 { 17 {
18 - field: ComponentConfigFieldEnum.FONT_COLOR,  
19 - label: '数值字体颜色', 18 + field: ComponentConfigFieldEnum.VALUE_SIZE,
  19 + label: '数值字体大小',
  20 + component: 'InputNumber',
  21 + defaultValue: option.fontSize,
  22 + },
  23 + {
  24 + field: ComponentConfigFieldEnum.TEXT_COLOR,
  25 + label: '文本字体颜色',
20 component: 'ColorPicker', 26 component: 'ColorPicker',
21 changeEvent: 'update:value', 27 changeEvent: 'update:value',
22 defaultValue: option.fontColor, 28 defaultValue: option.fontColor,
23 }, 29 },
24 { 30 {
  31 + field: ComponentConfigFieldEnum.FONT_SIZE,
  32 + label: '文本字体大小',
  33 + component: 'InputNumber',
  34 + defaultValue: option.fontSize,
  35 + },
  36 + {
  37 + field: ComponentConfigFieldEnum.CONTROL_BAR_COLOR,
  38 + label: '控制栏背景色',
  39 + component: 'ColorPicker',
  40 + changeEvent: 'update:value',
  41 + defaultValue: option.controlBarColor,
  42 + },
  43 + {
25 field: ComponentConfigFieldEnum.MIN_NUMBER, 44 field: ComponentConfigFieldEnum.MIN_NUMBER,
26 label: '最小值', 45 label: '最小值',
27 component: 'InputNumber', 46 component: 'InputNumber',
@@ -61,6 +80,7 @@ @@ -61,6 +80,7 @@
61 }; 80 };
62 }, 81 },
63 }, 82 },
  83 +
64 { 84 {
65 field: ComponentConfigFieldEnum.SHOW_DEVICE_NAME, 85 field: ComponentConfigFieldEnum.SHOW_DEVICE_NAME,
66 label: '显示设备名称', 86 label: '显示设备名称',
@@ -32,6 +32,10 @@ @@ -32,6 +32,10 @@
32 transportType: value.transportType, 32 transportType: value.transportType,
33 service: value.service, 33 service: value.service,
34 command: value.command, 34 command: value.command,
  35 + openService: value.openService,
  36 + closeService: value.closeService,
  37 + openCommand: value.openCommand,
  38 + closeCommand: value.closeCommand,
35 commandType: value.commandType, 39 commandType: value.commandType,
36 }, 40 },
37 }; 41 };
@@ -42,10 +46,14 @@ @@ -42,10 +46,14 @@
42 const { customCommand } = record; 46 const { customCommand } = record;
43 return setFieldsValue({ 47 return setFieldsValue({
44 ...record, 48 ...record,
45 - transportType: customCommand?.transportType,  
46 - service: customCommand?.service,  
47 - command: customCommand?.command,  
48 - commandType: customCommand?.commandType, 49 + transportType: customCommand?.transportType || (record as Recordable).transportType,
  50 + service: customCommand?.service || (record as Recordable).service,
  51 + openService: customCommand?.openService || (record as Recordable).openService,
  52 + closeService: customCommand?.closeService || (record as Recordable).closeService,
  53 + openCommand: customCommand?.openCommand || (record as Recordable).openCommand,
  54 + closeCommand: customCommand?.closeCommand || (record as Recordable).closeCommand,
  55 + command: customCommand?.command || (record as Recordable).command,
  56 + commandType: customCommand?.commandType || (record as Recordable).command,
49 } as unknown as Partial<CommonDataSourceBindValueType>); 57 } as unknown as Partial<CommonDataSourceBindValueType>);
50 }; 58 };
51 59
@@ -9,6 +9,10 @@ @@ -9,6 +9,10 @@
9 import { useReceiveValue } from '../../../hook/useReceiveValue'; 9 import { useReceiveValue } from '../../../hook/useReceiveValue';
10 import { DataFetchUpdateFn } from '../../../hook/socket/useSocket.type'; 10 import { DataFetchUpdateFn } from '../../../hook/socket/useSocket.type';
11 import { useDataFetch } from '../../../hook/socket/useSocket'; 11 import { useDataFetch } from '../../../hook/socket/useSocket';
  12 + import { TaskTypeEnum } from '/@/views/task/center/config';
  13 + import { useMessage } from '/@/hooks/web/useMessage';
  14 + import { SingleToHex } from '/@/views/device/list/cpns/tabs/ObjectModelCommandDeliveryModal/config';
  15 + import { genModbusCommand } from '/@/api/task';
12 16
13 const props = defineProps<{ 17 const props = defineProps<{
14 config: ComponentPropsConfigType<typeof option>; 18 config: ComponentPropsConfigType<typeof option>;
@@ -23,20 +27,42 @@ @@ -23,20 +27,42 @@
23 27
24 const getDesign = computed(() => { 28 const getDesign = computed(() => {
25 const { option, persetOption } = props.config; 29 const { option, persetOption } = props.config;
26 - const { componentInfo, attribute, attributeRename, attributeName } = option; 30 + const {
  31 + componentInfo,
  32 + attribute,
  33 + attributeRename,
  34 + attributeName,
  35 + commandType,
  36 + extensionDesc,
  37 + codeType,
  38 + deviceCode,
  39 + customCommand,
  40 + } = option;
27 const { 41 const {
28 controlBarColor: persetControlBarColor, 42 controlBarColor: persetControlBarColor,
29 fonColor: persetFontColor, 43 fonColor: persetFontColor,
30 minNumber: persetMinNumber, 44 minNumber: persetMinNumber,
31 maxNumber: persetMaxNumber, 45 maxNumber: persetMaxNumber,
  46 + textColor: persetTextColor,
  47 + valueSize: persetValueSize,
  48 + fontSize: persetFontSize,
32 } = persetOption || {}; 49 } = persetOption || {};
33 - const { controlBarColor, fontColor, minNumber, maxNumber } = componentInfo || {}; 50 + const { controlBarColor, fontColor, minNumber, maxNumber, textColor, valueSize, fontSize } =
  51 + componentInfo || {};
34 return { 52 return {
35 attribute: attributeRename || attributeName || attribute, 53 attribute: attributeRename || attributeName || attribute,
36 controlBarColor: controlBarColor ?? persetControlBarColor, 54 controlBarColor: controlBarColor ?? persetControlBarColor,
37 fontColor: fontColor ?? persetFontColor, 55 fontColor: fontColor ?? persetFontColor,
38 minNumber: minNumber ?? persetMinNumber, 56 minNumber: minNumber ?? persetMinNumber,
39 maxNumber: maxNumber ?? persetMaxNumber, 57 maxNumber: maxNumber ?? persetMaxNumber,
  58 + extensionDesc: extensionDesc ? JSON.parse(extensionDesc) : {},
  59 + commandType,
  60 + codeType,
  61 + deviceCode,
  62 + customCommand,
  63 + textColor: textColor || persetTextColor,
  64 + valueSize: valueSize || persetValueSize || 20,
  65 + fontSize: fontSize || persetFontSize || 14,
40 }; 66 };
41 }); 67 });
42 68
@@ -59,9 +85,98 @@ @@ -59,9 +85,98 @@
59 sliderValue.value = afterValue.value; //这一步是因为当我们是点击不是拖动时候,会让值更新不了,所以需要赋值一次 85 sliderValue.value = afterValue.value; //这一步是因为当我们是点击不是拖动时候,会让值更新不了,所以需要赋值一次
60 }; 86 };
61 87
  88 + const { createMessage } = useMessage();
  89 +
  90 + // 获取小数
  91 + const getFloatPart = (number: string | number) => {
  92 + const isLessZero = Number(number) < 0;
  93 + number = number.toString();
  94 + const floatPartStartIndex = number.indexOf('.');
  95 + const value = ~floatPartStartIndex
  96 + ? `${isLessZero ? '-' : ''}0.${number.substring(floatPartStartIndex + 1)}`
  97 + : '0';
  98 + return Number(value);
  99 + };
  100 +
  101 + const getArray = (values) => {
  102 + const str = values.replace(/\s+/g, '');
  103 + const array: any = [];
  104 +
  105 + for (let i = 0; i < str.length; i += 4) {
  106 + const chunk = parseInt(str.substring(i, i + 4), 16);
  107 + array.push(chunk);
  108 + }
  109 + return array;
  110 + };
  111 +
  112 + const getSendValue = async (value: number) => {
  113 + const { extensionDesc, codeType, deviceCode, customCommand } = unref(getDesign) || {};
  114 + const { transportType } = customCommand || {};
  115 + const { registerAddress, actionType, zoomFactor } = extensionDesc || {};
  116 + const newZoomValue = zoomFactor ? Number(zoomFactor) : 1;
  117 + if (transportType == 'TCP' && codeType == TaskTypeEnum.MODBUS_RTU) {
  118 + if (!deviceCode) {
  119 + createMessage.warning('当前设备没有设置地址码');
  120 + return;
  121 + }
  122 + const modbusForm = ref({
  123 + crc: 'CRC_16_LOWER',
  124 + deviceCode: deviceCode,
  125 + method: actionType == '16' ? '10' : actionType,
  126 + registerAddress,
  127 + registerNumber: 1,
  128 + registerValues: [value],
  129 + }) as any;
  130 + if (!actionType) {
  131 + createMessage.warning('当前物模型扩展描述没有填写');
  132 + return;
  133 + }
  134 + if (actionType == '06') {
  135 + const newValue = Math.trunc(value) * newZoomValue + getFloatPart(value) * newZoomValue;
  136 + if (newValue % 1 != 0) {
  137 + createMessage.warning(`值必须是整数,缩放因子为${unref(newZoomValue)}`);
  138 + return;
  139 + }
  140 +
  141 + if (newValue > 65535) {
  142 + createMessage.warning(`值不能超过65535,缩放因子是${unref(newZoomValue)}`);
  143 + return;
  144 + }
  145 + modbusForm.value.registerValues = [newValue];
  146 + }
  147 + if (actionType == '05') {
  148 + if (Number(value) != 0 || Number(value) != 1) {
  149 + createMessage.warning(`当前物模型仅支持值为0和1`);
  150 + return;
  151 + }
  152 + }
  153 + if (actionType == '16' || actionType == '10') {
  154 + const regex = /^-?\d+(\.\d{0,2})?$/;
  155 + const values =
  156 + Math.trunc(value) * unref(newZoomValue) + getFloatPart(value) * unref(newZoomValue);
  157 + if (!regex.test(values as any)) {
  158 + createMessage.warning(`值精确到两位小数,缩放因子是${unref(newZoomValue)}`);
  159 + return;
  160 + }
  161 + const newValue = values == 0 ? [0, 0] : getArray(SingleToHex(values));
  162 + modbusForm.value.registerValues = newValue;
  163 + modbusForm.value.registerNumber = 2;
  164 + modbusForm.value.method = '10';
  165 + }
  166 + const sendValue = await genModbusCommand(unref(modbusForm));
  167 + return sendValue;
  168 + }
  169 + };
  170 +
62 const handleBlur = async () => { 171 const handleBlur = async () => {
63 if (unref(oldSliderValue) !== unref(sliderValue)) { 172 if (unref(oldSliderValue) !== unref(sliderValue)) {
64 - const flag = await sendCommand(props.config.option, unref(sliderValue)); 173 + const { codeType, customCommand } = unref(getDesign) || {};
  174 + const { transportType } = customCommand || {};
  175 + const sendValue = ref<any>(unref(sliderValue));
  176 + if (transportType == 'TCP' && codeType == TaskTypeEnum.MODBUS_RTU) {
  177 + sendValue.value = await getSendValue(unref(sliderValue));
  178 + }
  179 + const flag = await sendCommand(props.config.option, unref(sendValue), true);
65 flag 180 flag
66 ? ((sliderValue.value = unref(sliderValue)), 181 ? ((sliderValue.value = unref(sliderValue)),
67 (oldSliderValue.value = sliderValue.value), 182 (oldSliderValue.value = sliderValue.value),
@@ -90,7 +205,7 @@ @@ -90,7 +205,7 @@
90 <Spin :spinning="loading" class="w-full h-full"> 205 <Spin :spinning="loading" class="w-full h-full">
91 <div class="flex flex-col" style="width: 80%"> 206 <div class="flex flex-col" style="width: 80%">
92 <span 207 <span
93 - :style="{ color: getDesign.fontColor }" 208 + :style="{ color: getDesign.fontColor, fontSize: getDesign.valueSize + 'px' }"
94 class="font-bold text-xl mt-3 truncate text-center" 209 class="font-bold text-xl mt-3 truncate text-center"
95 >{{ sliderValue }}</span 210 >{{ sliderValue }}</span
96 > 211 >
@@ -107,7 +222,7 @@ @@ -107,7 +222,7 @@
107 /> 222 />
108 223
109 <span 224 <span
110 - :style="{ color: getDesign.fontColor }" 225 + :style="{ color: getDesign.textColor, fontSize: getDesign.fontSize + 'px' }"
111 class="mt-3 truncate font-bold text-xs text-center" 226 class="mt-3 truncate font-bold text-xs text-center"
112 > 227 >
113 {{ getDesign.attribute || '属性' }} 228 {{ getDesign.attribute || '属性' }}
@@ -14,6 +14,7 @@ export const option: PublicPresetOptions = { @@ -14,6 +14,7 @@ export const option: PublicPresetOptions = {
14 [ComponentConfigFieldEnum.ICON]: 'shuiwen', 14 [ComponentConfigFieldEnum.ICON]: 'shuiwen',
15 [ComponentConfigFieldEnum.ICON_COLOR]: '#377DFF', 15 [ComponentConfigFieldEnum.ICON_COLOR]: '#377DFF',
16 [ComponentConfigFieldEnum.SHOW_DEVICE_NAME]: false, 16 [ComponentConfigFieldEnum.SHOW_DEVICE_NAME]: false,
  17 + [ComponentConfigFieldEnum.FONT_SIZE]: 14,
17 }; 18 };
18 19
19 export default class Config extends PublicConfigClass implements CreateComponentType { 20 export default class Config extends PublicConfigClass implements CreateComponentType {
@@ -27,6 +27,12 @@ @@ -27,6 +27,12 @@
27 }, 27 },
28 }, 28 },
29 { 29 {
  30 + field: ComponentConfigFieldEnum.FONT_SIZE,
  31 + label: '文本字体大小',
  32 + component: 'InputNumber',
  33 + defaultValue: option.fontSize,
  34 + },
  35 + {
30 field: ComponentConfigFieldEnum.SHOW_DEVICE_NAME, 36 field: ComponentConfigFieldEnum.SHOW_DEVICE_NAME,
31 label: '显示设备名称', 37 label: '显示设备名称',
32 component: 'Checkbox', 38 component: 'Checkbox',
@@ -32,6 +32,10 @@ @@ -32,6 +32,10 @@
32 transportType: value.transportType, 32 transportType: value.transportType,
33 service: value.service, 33 service: value.service,
34 command: value.command, 34 command: value.command,
  35 + openService: value.openService,
  36 + closeService: value.closeService,
  37 + openCommand: value.openCommand,
  38 + closeCommand: value.closeCommand,
35 commandType: value.commandType, 39 commandType: value.commandType,
36 callType: value.callType, 40 callType: value.callType,
37 }, 41 },
@@ -45,6 +49,10 @@ @@ -45,6 +49,10 @@
45 ...record, 49 ...record,
46 transportType: customCommand?.transportType || (record as Recordable).transportType, 50 transportType: customCommand?.transportType || (record as Recordable).transportType,
47 service: customCommand?.service || (record as Recordable).service, 51 service: customCommand?.service || (record as Recordable).service,
  52 + openService: customCommand?.openService || (record as Recordable).openService,
  53 + closeService: customCommand?.closeService || (record as Recordable).closeService,
  54 + openCommand: customCommand?.openCommand || (record as Recordable).openCommand,
  55 + closeCommand: customCommand?.closeCommand || (record as Recordable).closeCommand,
48 command: customCommand?.command || (record as Recordable).command, 56 command: customCommand?.command || (record as Recordable).command,
49 commandType: customCommand?.commandType || (record as Recordable).commandType, 57 commandType: customCommand?.commandType || (record as Recordable).commandType,
50 callType: customCommand?.callType || (record as Recordable).callType, 58 callType: customCommand?.callType || (record as Recordable).callType,
@@ -5,6 +5,6 @@ const componentKeys = useComponentKeys('SwitchList'); @@ -5,6 +5,6 @@ const componentKeys = useComponentKeys('SwitchList');
5 5
6 export const SwitchListConfig: ConfigType = { 6 export const SwitchListConfig: ConfigType = {
7 ...componentKeys, 7 ...componentKeys,
8 - title: '开关控制列表', 8 + title: '开关控制列表',
9 package: PackagesCategoryEnum.CONTROL, 9 package: PackagesCategoryEnum.CONTROL,
10 }; 10 };
@@ -13,6 +13,7 @@ @@ -13,6 +13,7 @@
13 import { useReceiveMessage } from '../../../hook/useReceiveMessage'; 13 import { useReceiveMessage } from '../../../hook/useReceiveMessage';
14 import { useReceiveValue } from '../../../hook/useReceiveValue'; 14 import { useReceiveValue } from '../../../hook/useReceiveValue';
15 import { DataSource } from '/@/views/visual/palette/types'; 15 import { DataSource } from '/@/views/visual/palette/types';
  16 + import { getSendValues, CommandTypeEnumLIst } from '../config';
16 17
17 const props = defineProps<{ 18 const props = defineProps<{
18 config: ComponentPropsConfigType<typeof option>; 19 config: ComponentPropsConfigType<typeof option>;
@@ -51,12 +52,24 @@ @@ -51,12 +52,24 @@
51 fontColor: persetFontColor, 52 fontColor: persetFontColor,
52 icon: persetIcon, 53 icon: persetIcon,
53 iconColor: persetIconColor, 54 iconColor: persetIconColor,
  55 + fontSize: persetFontSize,
54 } = persetOption || {}; 56 } = persetOption || {};
55 return { 57 return {
56 dataSource: dataSource.map((item) => { 58 dataSource: dataSource.map((item) => {
57 - const { fontColor, icon, iconColor, unit, showDeviceName } = item.componentInfo;  
58 - const { attribute, attributeRename, attributeName, deviceId, deviceName, deviceRename } =  
59 - item; 59 + const { fontColor, icon, iconColor, unit, showDeviceName, fontSize } = item.componentInfo;
  60 + const {
  61 + attribute,
  62 + attributeRename,
  63 + attributeName,
  64 + deviceId,
  65 + deviceName,
  66 + deviceRename,
  67 + commandType,
  68 + extensionDesc,
  69 + codeType,
  70 + deviceCode,
  71 + customCommand,
  72 + } = item;
60 return { 73 return {
61 unit: unit ?? persetUnit, 74 unit: unit ?? persetUnit,
62 fontColor: fontColor ?? persetFontColor, 75 fontColor: fontColor ?? persetFontColor,
@@ -67,6 +80,12 @@ @@ -67,6 +80,12 @@
67 showDeviceName, 80 showDeviceName,
68 deviceName: deviceRename || deviceName, 81 deviceName: deviceRename || deviceName,
69 id: deviceId, 82 id: deviceId,
  83 + extensionDesc: extensionDesc ? JSON.parse(extensionDesc) : {},
  84 + commandType,
  85 + codeType,
  86 + deviceCode,
  87 + customCommand,
  88 + fontSize: fontSize || persetFontSize || 14,
70 }; 89 };
71 }), 90 }),
72 }; 91 };
@@ -76,7 +95,6 @@ @@ -76,7 +95,6 @@
76 const handleChange = async (index: number, checked: Boolean) => { 95 const handleChange = async (index: number, checked: Boolean) => {
77 const { heightPx, itemHeightRatio, itemWidthRatio, mode, widthPx, dataSource } = 96 const { heightPx, itemHeightRatio, itemWidthRatio, mode, widthPx, dataSource } =
78 props.config.option; 97 props.config.option;
79 -  
80 const data = { 98 const data = {
81 ...dataSource?.[index], 99 ...dataSource?.[index],
82 heightPx, 100 heightPx,
@@ -85,8 +103,10 @@ @@ -85,8 +103,10 @@
85 mode, 103 mode,
86 widthPx, 104 widthPx,
87 } as DataSource; 105 } as DataSource;
  106 + const { values, isModbusCommand, sendValue } =
  107 + (await getSendValues(data, unref(getDesign).dataSource[index], checked)) || {};
88 108
89 - const flag = await sendCommand(data, checked); 109 + const flag = await sendCommand(values, isModbusCommand ? sendValue : checked, isModbusCommand);
90 if (!flag) controlList.value[index].checked = !checked; 110 if (!flag) controlList.value[index].checked = !checked;
91 }; 111 };
92 112
@@ -128,15 +148,15 @@ @@ -128,15 +148,15 @@
128 <SvgIcon 148 <SvgIcon
129 :name="item.icon!" 149 :name="item.icon!"
130 prefix="iconfont" 150 prefix="iconfont"
131 - :size="getRatio ? 30 * getRatio : 30" 151 + :size="getRatio ? 25 * getRatio : 25"
132 :style="{ color: item.iconColor }" 152 :style="{ color: item.iconColor }"
133 /> 153 />
134 154
135 - <div  
136 - class="text-gray-500 truncate ml-6"  
137 - :style="{ fontSize: getRatio ? '18px' : getRatio * 18 + 'px' }"  
138 - >{{ `${item.deviceName} - ${item.attributeName}` }}</div  
139 - > 155 + <div class="text-gray-500 truncate ml-6" :style="{ fontSize: item.fontSize + 'px' }">{{
  156 + `${item.deviceName} - ${
  157 + item.commandType ? CommandTypeEnumLIst[item.commandType].name : item.attributeName
  158 + }`
  159 + }}</div>
140 </div> 160 </div>
141 161
142 <Switch 162 <Switch
  1 +import { ref, unref } from 'vue';
  2 +import { TransportTypeEnum } from '/@/views/device/profiles/components/TransportDescript/const';
  3 +import { CommandTypeEnum } from '/@/views/rule/linkedge/config/config.data';
  4 +import { TaskTypeEnum } from '/@/views/task/center/config';
  5 +import { genModbusCommand } from '/@/api/task';
  6 +import { useMessage } from '/@/hooks/web/useMessage';
  7 +import { SingleToHex } from '/@/views/device/list/cpns/tabs/ObjectModelCommandDeliveryModal/config';
  8 +
  9 +const getArray = (values) => {
  10 + const str = values.replace(/\s+/g, '');
  11 + const array: any = [];
  12 +
  13 + for (let i = 0; i < str.length; i += 4) {
  14 + const chunk = parseInt(str.substring(i, i + 4), 16);
  15 + array.push(chunk);
  16 + }
  17 + return array;
  18 +};
  19 +
  20 +export const getSendValues = async (option, getDesign, checked) => {
  21 + const values: any = option;
  22 + const isModbusCommand = ref<boolean>(false); //判断是否是TCP设备-> 且设备标识符是modeBUs,切选择是下发命令类型是属性
  23 + const { extensionDesc, commandType, codeType, deviceCode, customCommand } = getDesign || {};
  24 + const { registerAddress, actionType } = extensionDesc || {};
  25 + const { openCommand, closeCommand, transportType } = customCommand || {};
  26 + const modBUS = ref<any>({});
  27 + const sendValue = ref();
  28 +
  29 + const { createMessage } = useMessage();
  30 + //判断是不是TCP类型设备
  31 + if (transportType === TransportTypeEnum.TCP) {
  32 + if (
  33 + //判断TCP下发类型是否是自定义还是服务
  34 + commandType === CommandTypeEnum.CUSTOM.toString() ||
  35 + commandType == CommandTypeEnum.SERVICE.toString()
  36 + ) {
  37 + values.customCommand.command = checked ? openCommand : closeCommand;
  38 + values.customCommand.command = values.customCommand.command
  39 + .replaceAll(/\s/g, '')
  40 + .toUpperCase();
  41 + }
  42 + if (
  43 + //判断命令下发类型是不是属性 且是modbus
  44 + commandType === CommandTypeEnum.ATTRIBUTE.toString() &&
  45 + codeType === TaskTypeEnum.MODBUS_RTU
  46 + ) {
  47 + if (!deviceCode) {
  48 + createMessage.warning('当前设备没有设置地址码');
  49 + return;
  50 + }
  51 + if (!actionType) {
  52 + createMessage.warning('当前物模型扩展描述没有填写');
  53 + return;
  54 + }
  55 + isModbusCommand.value = true;
  56 + modBUS.value = {
  57 + crc: 'CRC_16_LOWER',
  58 + deviceCode: deviceCode,
  59 + method: actionType == '16' ? '10' : actionType,
  60 + registerAddress,
  61 + registerNumber: 1,
  62 + registerValues: [Number(checked)],
  63 + };
  64 +
  65 + if (actionType == '16' || actionType == '10') {
  66 + const newValue = Number(checked) == 0 ? [0, 0] : getArray(SingleToHex(Number(checked)));
  67 + modBUS.value.registerValues = newValue;
  68 + modBUS.value.registerNumber = 2;
  69 + modBUS.value.method = '10';
  70 + }
  71 +
  72 + sendValue.value = await genModbusCommand(unref(modBUS));
  73 + }
  74 + }
  75 +
  76 + return { values, sendValue: unref(sendValue), isModbusCommand: unref(isModbusCommand) };
  77 +};
  78 +
  79 +export const CommandTypeEnumLIst = {
  80 + '0': { CUSTOM: 0, name: '自定义' },
  81 + '1': { CUSTOM: 0, name: '服务' },
  82 + '2': { CUSTOM: 0, name: '属性' },
  83 +};
@@ -13,6 +13,8 @@ export const option: PublicPresetOptions = { @@ -13,6 +13,8 @@ export const option: PublicPresetOptions = {
13 [ComponentConfigFieldEnum.SHOW_DEVICE_NAME]: false, 13 [ComponentConfigFieldEnum.SHOW_DEVICE_NAME]: false,
14 [ComponentConfigFieldEnum.UNIT]: 'm', 14 [ComponentConfigFieldEnum.UNIT]: 'm',
15 [ComponentConfigFieldEnum.MAX_NUMBER]: 100, 15 [ComponentConfigFieldEnum.MAX_NUMBER]: 100,
  16 + [ComponentConfigFieldEnum.VALUE_SIZE]: 20,
  17 + [ComponentConfigFieldEnum.FONT_SIZE]: 14,
16 [ComponentConfigFieldEnum.FONT_COLOR]: '#fff', 18 [ComponentConfigFieldEnum.FONT_COLOR]: '#fff',
17 [ComponentConfigFieldEnum.SHOW_TIME]: false, 19 [ComponentConfigFieldEnum.SHOW_TIME]: false,
18 [ComponentConfigFieldEnum.FLOWMETER_CONFIG]: { 20 [ComponentConfigFieldEnum.FLOWMETER_CONFIG]: {
@@ -10,7 +10,7 @@ @@ -10,7 +10,7 @@
10 schemas: [ 10 schemas: [
11 { 11 {
12 field: ComponentConfigFieldEnum.FONT_COLOR, 12 field: ComponentConfigFieldEnum.FONT_COLOR,
13 - label: '字体颜色', 13 + label: '数值字体颜色',
14 component: 'ColorPicker', 14 component: 'ColorPicker',
15 changeEvent: 'update:value', 15 changeEvent: 'update:value',
16 defaultValue: option.fontColor, 16 defaultValue: option.fontColor,
@@ -50,6 +50,40 @@ @@ -50,6 +50,40 @@
50 defaultValue: option.unit, 50 defaultValue: option.unit,
51 }, 51 },
52 { 52 {
  53 + field: ComponentConfigFieldEnum.VALUE_SIZE,
  54 + label: '数值字体大小',
  55 + component: 'InputNumber',
  56 + defaultValue: 14,
  57 + componentProps: {
  58 + min: 0,
  59 + formatter: (e) => {
  60 + const value = e.replace(/^0/g, '');
  61 + if (value) {
  62 + return value.replace(/^0/g, '');
  63 + } else {
  64 + return 0;
  65 + }
  66 + },
  67 + },
  68 + },
  69 + {
  70 + field: ComponentConfigFieldEnum.FONT_SIZE,
  71 + label: '文本字体大小',
  72 + component: 'InputNumber',
  73 + defaultValue: 14,
  74 + componentProps: {
  75 + min: 0,
  76 + formatter: (e) => {
  77 + const value = e.replace(/^0/g, '');
  78 + if (value) {
  79 + return value.replace(/^0/g, '');
  80 + } else {
  81 + return 0;
  82 + }
  83 + },
  84 + },
  85 + },
  86 + {
53 field: ComponentConfigFieldEnum.MAX_NUMBER, 87 field: ComponentConfigFieldEnum.MAX_NUMBER,
54 label: '最大值', 88 label: '最大值',
55 component: 'InputNumber', 89 component: 'InputNumber',
@@ -20,7 +20,8 @@ @@ -20,7 +20,8 @@
20 const getDesign = computed(() => { 20 const getDesign = computed(() => {
21 const { option, persetOption } = props.config; 21 const { option, persetOption } = props.config;
22 const { componentInfo, attribute, attributeName, attributeRename } = option; 22 const { componentInfo, attribute, attributeName, attributeRename } = option;
23 - const { flowmeterConfig, unit, fontColor, showTime, maxNumber } = componentInfo || {}; 23 + const { flowmeterConfig, unit, fontColor, showTime, maxNumber, valueSize, fontSize } =
  24 + componentInfo || {};
24 const { backgroundColor, waveFirst, waveSecond, waveThird } = flowmeterConfig || {}; 25 const { backgroundColor, waveFirst, waveSecond, waveThird } = flowmeterConfig || {};
25 const { 26 const {
26 flowmeterConfig: presetFlowmeterConfig, 27 flowmeterConfig: presetFlowmeterConfig,
@@ -28,6 +29,8 @@ @@ -28,6 +29,8 @@
28 fontColor: presetFontColor, 29 fontColor: presetFontColor,
29 showTime: persetShowTime, 30 showTime: persetShowTime,
30 maxNumber: persetMaxNumber, 31 maxNumber: persetMaxNumber,
  32 + valueSize: persetValueSize,
  33 + fontSize: persetFontSize,
31 } = persetOption || {}; 34 } = persetOption || {};
32 const { 35 const {
33 backgroundColor: presetBackgroundColor, 36 backgroundColor: presetBackgroundColor,
@@ -45,6 +48,8 @@ @@ -45,6 +48,8 @@
45 attribute: attributeRename || attributeName || attribute, 48 attribute: attributeRename || attributeName || attribute,
46 showTime: showTime ?? persetShowTime, 49 showTime: showTime ?? persetShowTime,
47 maxNumber: maxNumber ?? persetMaxNumber, 50 maxNumber: maxNumber ?? persetMaxNumber,
  51 + valueSize: valueSize || persetValueSize || 20,
  52 + fontSize: fontSize || persetFontSize || 14,
48 }; 53 };
49 }); 54 });
50 55
@@ -129,14 +134,17 @@ @@ -129,14 +134,17 @@
129 134
130 <div 135 <div
131 class="absolute w-full h-full top-0 left-0 text-center text-lg flex items-center justify-center" 136 class="absolute w-full h-full top-0 left-0 text-center text-lg flex items-center justify-center"
132 - :style="{ color: getDesign.fontColor }" 137 + :style="{ color: getDesign.fontColor, fontSize: getDesign.valueSize + 'px' }"
133 > 138 >
134 <div>{{ currentValue }}</div> 139 <div>{{ currentValue }}</div>
135 <div class="ml-1">{{ getDesign.unit }}</div> 140 <div class="ml-1">{{ getDesign.unit }}</div>
136 </div> 141 </div>
137 - <div class="text-gray-500 text-sm truncate" style="flex: 0 0 20px">{{  
138 - getDesign.attribute || '属性'  
139 - }}</div> 142 + <div
  143 + class="text-gray-500 text-sm truncate"
  144 + style="flex: 0 0 20px"
  145 + :style="{ fontSize: getDesign.fontSize + 'px' }"
  146 + >{{ getDesign.attribute || '属性' }}</div
  147 + >
140 <UpdateTime v-show="getDesign.showTime" :time="time" /> 148 <UpdateTime v-show="getDesign.showTime" :time="time" />
141 </main> 149 </main>
142 </template> 150 </template>
@@ -14,6 +14,8 @@ export const option: PublicPresetOptions = { @@ -14,6 +14,8 @@ export const option: PublicPresetOptions = {
14 [ComponentConfigFieldEnum.SHOW_TIME]: false, 14 [ComponentConfigFieldEnum.SHOW_TIME]: false,
15 [ComponentConfigFieldEnum.UNIT]: 'm', 15 [ComponentConfigFieldEnum.UNIT]: 'm',
16 [ComponentConfigFieldEnum.MAX_NUMBER]: 100, 16 [ComponentConfigFieldEnum.MAX_NUMBER]: 100,
  17 + [ComponentConfigFieldEnum.FONT_SIZE]: 14,
  18 + [ComponentConfigFieldEnum.VALUE_SIZE]: 20,
17 [ComponentConfigFieldEnum.FLOWMETER_CONFIG]: { 19 [ComponentConfigFieldEnum.FLOWMETER_CONFIG]: {
18 [ComponentConfigFieldEnum.BACKGROUND_COLOR]: '#8badcb', 20 [ComponentConfigFieldEnum.BACKGROUND_COLOR]: '#8badcb',
19 [ComponentConfigFieldEnum.WAVE_FIRST]: '#4579e2', 21 [ComponentConfigFieldEnum.WAVE_FIRST]: '#4579e2',
@@ -10,7 +10,7 @@ @@ -10,7 +10,7 @@
10 schemas: [ 10 schemas: [
11 { 11 {
12 field: ComponentConfigFieldEnum.FONT_COLOR, 12 field: ComponentConfigFieldEnum.FONT_COLOR,
13 - label: '字体颜色', 13 + label: '数值字体颜色',
14 component: 'ColorPicker', 14 component: 'ColorPicker',
15 changeEvent: 'update:value', 15 changeEvent: 'update:value',
16 defaultValue: option.fontColor, 16 defaultValue: option.fontColor,
@@ -56,6 +56,40 @@ @@ -56,6 +56,40 @@
56 // defaultValue: 0, 56 // defaultValue: 0,
57 // }, 57 // },
58 { 58 {
  59 + field: ComponentConfigFieldEnum.VALUE_SIZE,
  60 + label: '数值字体大小',
  61 + component: 'InputNumber',
  62 + defaultValue: 14,
  63 + componentProps: {
  64 + min: 0,
  65 + formatter: (e) => {
  66 + const value = e.replace(/^0/g, '');
  67 + if (value) {
  68 + return value.replace(/^0/g, '');
  69 + } else {
  70 + return 0;
  71 + }
  72 + },
  73 + },
  74 + },
  75 + {
  76 + field: ComponentConfigFieldEnum.FONT_SIZE,
  77 + label: '文本字体大小',
  78 + component: 'InputNumber',
  79 + defaultValue: 14,
  80 + componentProps: {
  81 + min: 0,
  82 + formatter: (e) => {
  83 + const value = e.replace(/^0/g, '');
  84 + if (value) {
  85 + return value.replace(/^0/g, '');
  86 + } else {
  87 + return 0;
  88 + }
  89 + },
  90 + },
  91 + },
  92 + {
59 field: ComponentConfigFieldEnum.MAX_NUMBER, 93 field: ComponentConfigFieldEnum.MAX_NUMBER,
60 label: '最大值', 94 label: '最大值',
61 component: 'InputNumber', 95 component: 'InputNumber',
@@ -20,7 +20,8 @@ @@ -20,7 +20,8 @@
20 const getDesign = computed(() => { 20 const getDesign = computed(() => {
21 const { option, persetOption } = props.config; 21 const { option, persetOption } = props.config;
22 const { componentInfo, attribute, attributeName, attributeRename } = option; 22 const { componentInfo, attribute, attributeName, attributeRename } = option;
23 - const { flowmeterConfig, unit, fontColor, showTime, maxNumber } = componentInfo || {}; 23 + const { flowmeterConfig, unit, fontColor, showTime, maxNumber, fontSize, valueSize } =
  24 + componentInfo || {};
24 const { backgroundColor, waveFirst, waveSecond, waveThird } = flowmeterConfig || {}; 25 const { backgroundColor, waveFirst, waveSecond, waveThird } = flowmeterConfig || {};
25 const { 26 const {
26 flowmeterConfig: presetFlowmeterConfig, 27 flowmeterConfig: presetFlowmeterConfig,
@@ -28,6 +29,8 @@ @@ -28,6 +29,8 @@
28 fontColor: presetFontColor, 29 fontColor: presetFontColor,
29 showTime: persetShowTime, 30 showTime: persetShowTime,
30 maxNumber: persetMaxNumber, 31 maxNumber: persetMaxNumber,
  32 + fontSize: persetFontSize,
  33 + valueSize: persetValueSize,
31 } = persetOption || {}; 34 } = persetOption || {};
32 const { 35 const {
33 backgroundColor: presetBackgroundColor, 36 backgroundColor: presetBackgroundColor,
@@ -45,6 +48,8 @@ @@ -45,6 +48,8 @@
45 attribute: attributeRename || attributeName || attribute, 48 attribute: attributeRename || attributeName || attribute,
46 showTime: showTime ?? persetShowTime, 49 showTime: showTime ?? persetShowTime,
47 maxNumber: maxNumber ?? persetMaxNumber, 50 maxNumber: maxNumber ?? persetMaxNumber,
  51 + fontSize: fontSize || persetFontSize || 14,
  52 + valueSize: valueSize || persetValueSize || 20,
48 }; 53 };
49 }); 54 });
50 55
@@ -122,14 +127,17 @@ @@ -122,14 +127,17 @@
122 </svg> 127 </svg>
123 <div 128 <div
124 class="absolute w-full h-full top-0 left-0 text-center text-lg flex items-center justify-center" 129 class="absolute w-full h-full top-0 left-0 text-center text-lg flex items-center justify-center"
125 - :style="{ color: getDesign.fontColor }" 130 + :style="{ color: getDesign.fontColor, fontSize: getDesign.valueSize + 'px' }"
126 > 131 >
127 <div>{{ currentValue }}</div> 132 <div>{{ currentValue }}</div>
128 <div class="ml-1">{{ getDesign.unit }}</div> 133 <div class="ml-1">{{ getDesign.unit }}</div>
129 </div> 134 </div>
130 - <div class="text-gray-500 text-sm truncate" style="flex: 0 0 20px">{{  
131 - getDesign.attribute || '属性'  
132 - }}</div> 135 + <div
  136 + class="text-gray-500"
  137 + style="flex: 0 0 20px"
  138 + :style="{ fontSize: getDesign.fontSize + 'px', height: getDesign.fontSize + 'px' }"
  139 + >{{ getDesign.attribute || '属性' }}</div
  140 + >
133 <UpdateTime v-show="getDesign.showTime" :time="time" /> 141 <UpdateTime v-show="getDesign.showTime" :time="time" />
134 </main> 142 </main>
135 </template> 143 </template>
@@ -27,6 +27,8 @@ export const option: PublicPresetOptions = { @@ -27,6 +27,8 @@ export const option: PublicPresetOptions = {
27 [ComponentConfigFieldEnum.UNIT]: '℃', 27 [ComponentConfigFieldEnum.UNIT]: '℃',
28 [ComponentConfigFieldEnum.POINTER_COLOR]: '#15E2C6', 28 [ComponentConfigFieldEnum.POINTER_COLOR]: '#15E2C6',
29 [ComponentConfigFieldEnum.INSTRUMENT_PANEL_COLOR]: '#61D4C5', 29 [ComponentConfigFieldEnum.INSTRUMENT_PANEL_COLOR]: '#61D4C5',
  30 + [ComponentConfigFieldEnum.FONT_SIZE]: 14,
  31 + [ComponentConfigFieldEnum.VALUE_SIZE]: 14,
30 [ComponentConfigFieldEnum.GRADIENT_INFO]: [ 32 [ComponentConfigFieldEnum.GRADIENT_INFO]: [
31 { key: Gradient.FIRST, value: 0, color: GradientColor.FIRST }, 33 { key: Gradient.FIRST, value: 0, color: GradientColor.FIRST },
32 { key: Gradient.SECOND, value: 1, color: GradientColor.SECOND }, 34 { key: Gradient.SECOND, value: 1, color: GradientColor.SECOND },
@@ -43,26 +43,6 @@ @@ -43,26 +43,6 @@
43 changeEvent: 'update:value', 43 changeEvent: 'update:value',
44 defaultValue: GradientColor.SECOND, 44 defaultValue: GradientColor.SECOND,
45 }, 45 },
46 - // {  
47 - // field: ComponentConfigFieldEnum.INSTRUMENT_PANEL_WIDTH,  
48 - // label: '仪表盘宽度',  
49 - // component: 'Slider',  
50 - // changeEvent: 'update:value',  
51 - // defaultValue: option.pointerColor,  
52 - // },  
53 - {  
54 - field: ComponentConfigFieldEnum.SHOW_DEVICE_NAME,  
55 - label: '显示设备名称',  
56 - component: 'Checkbox',  
57 - defaultValue: option.showDeviceName,  
58 - },  
59 - {  
60 - field: ComponentConfigFieldEnum.SHOW_TIME,  
61 - label: '显示时间',  
62 - component: 'Checkbox',  
63 - defaultValue: option.showTime,  
64 - },  
65 -  
66 { 46 {
67 field: ComponentConfigFieldEnum.UNIT, 47 field: ComponentConfigFieldEnum.UNIT,
68 label: '数值单位', 48 label: '数值单位',
@@ -70,6 +50,40 @@ @@ -70,6 +50,40 @@
70 defaultValue: option.unit, 50 defaultValue: option.unit,
71 }, 51 },
72 { 52 {
  53 + field: ComponentConfigFieldEnum.VALUE_SIZE,
  54 + label: '数值字体大小',
  55 + component: 'InputNumber',
  56 + defaultValue: 14,
  57 + componentProps: {
  58 + min: 0,
  59 + formatter: (e) => {
  60 + const value = e.replace(/^0/g, '');
  61 + if (value) {
  62 + return value.replace(/^0/g, '');
  63 + } else {
  64 + return 0;
  65 + }
  66 + },
  67 + },
  68 + },
  69 + {
  70 + field: ComponentConfigFieldEnum.FONT_SIZE,
  71 + label: '文本字体大小',
  72 + component: 'InputNumber',
  73 + defaultValue: 14,
  74 + componentProps: {
  75 + min: 0,
  76 + formatter: (e) => {
  77 + const value = e.replace(/^0/g, '');
  78 + if (value) {
  79 + return value.replace(/^0/g, '');
  80 + } else {
  81 + return 0;
  82 + }
  83 + },
  84 + },
  85 + },
  86 + {
73 field: ComponentConfigFieldEnum.MAX_NUMBER, 87 field: ComponentConfigFieldEnum.MAX_NUMBER,
74 label: '最大值', 88 label: '最大值',
75 component: 'InputNumber', 89 component: 'InputNumber',
@@ -90,6 +104,18 @@ @@ -90,6 +104,18 @@
90 }; 104 };
91 }, 105 },
92 }, 106 },
  107 + {
  108 + field: ComponentConfigFieldEnum.SHOW_DEVICE_NAME,
  109 + label: '显示设备名称',
  110 + component: 'Checkbox',
  111 + defaultValue: option.showDeviceName,
  112 + },
  113 + {
  114 + field: ComponentConfigFieldEnum.SHOW_TIME,
  115 + label: '显示时间',
  116 + component: 'Checkbox',
  117 + defaultValue: option.showTime,
  118 + },
93 ], 119 ],
94 showActionButtonGroup: false, 120 showActionButtonGroup: false,
95 labelWidth: 120, 121 labelWidth: 120,
@@ -120,13 +146,24 @@ @@ -120,13 +146,24 @@
120 showTime: item[ComponentConfigFieldEnum.SHOW_TIME], 146 showTime: item[ComponentConfigFieldEnum.SHOW_TIME],
121 pointerColor: item[ComponentConfigFieldEnum.POINTER_COLOR], 147 pointerColor: item[ComponentConfigFieldEnum.POINTER_COLOR],
122 maxNumber: item[ComponentConfigFieldEnum.MAX_NUMBER], 148 maxNumber: item[ComponentConfigFieldEnum.MAX_NUMBER],
  149 + fontSize: item[ComponentConfigFieldEnum.FONT_SIZE],
  150 + valueSize: item[ComponentConfigFieldEnum.VALUE_SIZE],
123 } as ComponentInfo; 151 } as ComponentInfo;
124 }; 152 };
125 153
126 const setFormValues = (data: Recordable) => { 154 const setFormValues = (data: Recordable) => {
127 // return setFieldsValue(data); 155 // return setFieldsValue(data);
128 - const { gradientInfo, unit, fontColor, showDeviceName, pointerColor, showTime, maxNumber } =  
129 - data; 156 + const {
  157 + gradientInfo,
  158 + unit,
  159 + fontColor,
  160 + showDeviceName,
  161 + pointerColor,
  162 + showTime,
  163 + maxNumber,
  164 + fontSize,
  165 + valueSize,
  166 + } = data;
130 const firstRecord = gradientInfo.find((item) => item.key === Gradient.FIRST); 167 const firstRecord = gradientInfo.find((item) => item.key === Gradient.FIRST);
131 const secondRecord = gradientInfo.find((item) => item.key === Gradient.SECOND); 168 const secondRecord = gradientInfo.find((item) => item.key === Gradient.SECOND);
132 169
@@ -141,6 +178,8 @@ @@ -141,6 +178,8 @@
141 [ComponentConfigFieldEnum.SECOND_PHASE_COLOR]: secondRecord?.color, 178 [ComponentConfigFieldEnum.SECOND_PHASE_COLOR]: secondRecord?.color,
142 [ComponentConfigFieldEnum.POINTER_COLOR]: pointerColor, 179 [ComponentConfigFieldEnum.POINTER_COLOR]: pointerColor,
143 [ComponentConfigFieldEnum.MAX_NUMBER]: maxNumber, 180 [ComponentConfigFieldEnum.MAX_NUMBER]: maxNumber,
  181 + [ComponentConfigFieldEnum.FONT_SIZE]: fontSize,
  182 + [ComponentConfigFieldEnum.VALUE_SIZE]: valueSize,
144 }; 183 };
145 return setFieldsValue(value); 184 return setFieldsValue(value);
146 }; 185 };
@@ -32,6 +32,8 @@ @@ -32,6 +32,8 @@
32 gradientInfo: presetGradientInfo, 32 gradientInfo: presetGradientInfo,
33 showTime: persetShowTime, 33 showTime: persetShowTime,
34 maxNumber: persetMaxNumber, 34 maxNumber: persetMaxNumber,
  35 + fontSize: persetFontSize,
  36 + valueSize: persetValueSize,
35 } = persetOption || {}; 37 } = persetOption || {};
36 const { 38 const {
37 unit, 39 unit,
@@ -41,6 +43,8 @@ @@ -41,6 +43,8 @@
41 gradientInfo, 43 gradientInfo,
42 showTime, 44 showTime,
43 maxNumber, 45 maxNumber,
  46 + fontSize,
  47 + valueSize,
44 } = componentInfo || {}; 48 } = componentInfo || {};
45 return { 49 return {
46 unit: unit ?? presetUnit, 50 unit: unit ?? presetUnit,
@@ -51,6 +55,8 @@ @@ -51,6 +55,8 @@
51 gradientInfo: gradientInfo ?? presetGradientInfo, 55 gradientInfo: gradientInfo ?? presetGradientInfo,
52 showTime: showTime ?? persetShowTime, 56 showTime: showTime ?? persetShowTime,
53 maxNumber: maxNumber || persetMaxNumber, 57 maxNumber: maxNumber || persetMaxNumber,
  58 + fontSize: fontSize || persetFontSize || 14,
  59 + valueSize: valueSize || persetValueSize || 14,
54 }; 60 };
55 }); 61 });
56 62
@@ -66,7 +72,7 @@ @@ -66,7 +72,7 @@
66 }; 72 };
67 73
68 const options = (): EChartsOption => { 74 const options = (): EChartsOption => {
69 - const { unit, fontColor, pointerColor, gradientInfo, maxNumber } = unref(getDesign); 75 + const { unit, fontColor, pointerColor, gradientInfo, maxNumber, valueSize } = unref(getDesign);
70 76
71 const instrumentPanelColor = getStageColor(gradientInfo); 77 const instrumentPanelColor = getStageColor(gradientInfo);
72 // getStageColor(gradientInfo); 78 // getStageColor(gradientInfo);
@@ -108,7 +114,7 @@ @@ -108,7 +114,7 @@
108 //指针 114 //指针
109 show: true, 115 show: true,
110 icon: 'path://M2090.36389,615.30999 L2090.36389,615.30999 C2091.48372,615.30999 2092.40383,616.194028 2092.44859,617.312956 L2096.90698,728.755929 C2097.05155,732.369577 2094.2393,735.416212 2090.62566,735.56078 C2090.53845,735.564269 2090.45117,735.566014 2090.36389,735.566014 L2090.36389,735.566014 C2086.74736,735.566014 2083.81557,732.63423 2083.81557,729.017692 C2083.81557,728.930412 2083.81732,728.84314 2083.82081,728.755929 L2088.2792,617.312956 C2088.32396,616.194028 2089.24407,615.30999 2090.36389,615.30999 Z', 116 icon: 'path://M2090.36389,615.30999 L2090.36389,615.30999 C2091.48372,615.30999 2092.40383,616.194028 2092.44859,617.312956 L2096.90698,728.755929 C2097.05155,732.369577 2094.2393,735.416212 2090.62566,735.56078 C2090.53845,735.564269 2090.45117,735.566014 2090.36389,735.566014 L2090.36389,735.566014 C2086.74736,735.566014 2083.81557,732.63423 2083.81557,729.017692 C2083.81557,728.930412 2083.81732,728.84314 2083.82081,728.755929 L2088.2792,617.312956 C2088.32396,616.194028 2089.24407,615.30999 2090.36389,615.30999 Z',
111 - width: 4 * unref(getRatio) ? 4 * unref(getRatio) : 4, 117 + width: unref(getRatio) ? 4 * unref(getRatio) : 4,
112 length: '100%', 118 length: '100%',
113 itemStyle: { 119 itemStyle: {
114 color: pointerColor, 120 color: pointerColor,
@@ -128,7 +134,7 @@ @@ -128,7 +134,7 @@
128 }, 134 },
129 detail: { 135 detail: {
130 valueAnimation: true, 136 valueAnimation: true,
131 - fontSize: 14 * unref(getRatio), 137 + fontSize: unref(getRatio) ? valueSize * unref(getRatio) : valueSize,
132 fontWeight: 'bolder', 138 fontWeight: 'bolder',
133 formatter: `{value} ${unit ?? ''}`, 139 formatter: `{value} ${unit ?? ''}`,
134 color: fontColor || 'inherit', 140 color: fontColor || 'inherit',
@@ -199,7 +205,7 @@ @@ -199,7 +205,7 @@
199 width: 4 * unref(getRatio), 205 width: 4 * unref(getRatio),
200 }, 206 },
201 detail: { 207 detail: {
202 - fontSize: 14 * unref(getRatio), 208 + fontSize: unref(getDesign).valueSize * unref(getRatio),
203 }, 209 },
204 }, 210 },
205 ], 211 ],
@@ -219,9 +225,11 @@ @@ -219,9 +225,11 @@
219 <div class="w-full h-full flex flex-1 flex-col justify-center items-center"> 225 <div class="w-full h-full flex flex-1 flex-col justify-center items-center">
220 <div ref="chartRefEl" class="flex-1 w-full h-6/7 flex flex-col justify-center items-center"> 226 <div ref="chartRefEl" class="flex-1 w-full h-6/7 flex flex-col justify-center items-center">
221 </div> 227 </div>
222 - <div class="text-gray-500 text-xs text-center truncate">{{  
223 - getDesign.attribute || '湿度'  
224 - }}</div> 228 + <div
  229 + class="text-gray-500 text-center truncate"
  230 + :style="{ fontSize: getDesign.fontSize + 'px' }"
  231 + >{{ getDesign.attribute || '湿度' }}</div
  232 + >
225 </div> 233 </div>
226 <UpdateTime v-if="getDesign.showTime" :time="time" /> 234 <UpdateTime v-if="getDesign.showTime" :time="time" />
227 </main> 235 </main>
@@ -26,6 +26,8 @@ export const option: PublicPresetOptions = { @@ -26,6 +26,8 @@ export const option: PublicPresetOptions = {
26 [ComponentConfigFieldEnum.POINTER_COLOR]: '#15E2C6', 26 [ComponentConfigFieldEnum.POINTER_COLOR]: '#15E2C6',
27 [ComponentConfigFieldEnum.INSTRUMENT_PANEL_COLOR]: '#61D4C5', 27 [ComponentConfigFieldEnum.INSTRUMENT_PANEL_COLOR]: '#61D4C5',
28 [ComponentConfigFieldEnum.MAX_NUMBER]: 100, 28 [ComponentConfigFieldEnum.MAX_NUMBER]: 100,
  29 + [ComponentConfigFieldEnum.FONT_SIZE]: 14,
  30 + [ComponentConfigFieldEnum.VALUE_SIZE]: 14,
29 [ComponentConfigFieldEnum.GRADIENT_INFO]: [ 31 [ComponentConfigFieldEnum.GRADIENT_INFO]: [
30 { key: Gradient.FIRST, value: 0, color: GradientColor.FIRST }, 32 { key: Gradient.FIRST, value: 0, color: GradientColor.FIRST },
31 { key: Gradient.SECOND, value: 1, color: GradientColor.SECOND }, 33 { key: Gradient.SECOND, value: 1, color: GradientColor.SECOND },
@@ -43,24 +43,6 @@ @@ -43,24 +43,6 @@
43 defaultValue: GradientColor.SECOND, 43 defaultValue: GradientColor.SECOND,
44 }, 44 },
45 { 45 {
46 - field: ComponentConfigFieldEnum.PROGRESS_BAR_CIRCLE,  
47 - label: '显示进度条圆形',  
48 - component: 'Checkbox',  
49 - defaultValue: option.progressBarCircle,  
50 - },  
51 - {  
52 - field: ComponentConfigFieldEnum.SHOW_DEVICE_NAME,  
53 - label: '显示设备名称',  
54 - component: 'Checkbox',  
55 - defaultValue: option.showDeviceName,  
56 - },  
57 - {  
58 - field: ComponentConfigFieldEnum.SHOW_TIME,  
59 - label: '显示时间',  
60 - component: 'Checkbox',  
61 - defaultValue: option.showTime,  
62 - },  
63 - {  
64 field: ComponentConfigFieldEnum.MAX_NUMBER, 46 field: ComponentConfigFieldEnum.MAX_NUMBER,
65 label: '最大值', 47 label: '最大值',
66 component: 'InputNumber', 48 component: 'InputNumber',
@@ -81,6 +63,58 @@ @@ -81,6 +63,58 @@
81 }; 63 };
82 }, 64 },
83 }, 65 },
  66 + {
  67 + field: ComponentConfigFieldEnum.VALUE_SIZE,
  68 + label: '数值字体大小',
  69 + component: 'InputNumber',
  70 + defaultValue: 14,
  71 + componentProps: {
  72 + min: 0,
  73 + formatter: (e) => {
  74 + const value = e.replace(/^0/g, '');
  75 + if (value) {
  76 + return value.replace(/^0/g, '');
  77 + } else {
  78 + return 0;
  79 + }
  80 + },
  81 + },
  82 + },
  83 + {
  84 + field: ComponentConfigFieldEnum.FONT_SIZE,
  85 + label: '文本字体大小',
  86 + component: 'InputNumber',
  87 + defaultValue: 14,
  88 + componentProps: {
  89 + min: 0,
  90 + formatter: (e) => {
  91 + const value = e.replace(/^0/g, '');
  92 + if (value) {
  93 + return value.replace(/^0/g, '');
  94 + } else {
  95 + return 0;
  96 + }
  97 + },
  98 + },
  99 + },
  100 + {
  101 + field: ComponentConfigFieldEnum.PROGRESS_BAR_CIRCLE,
  102 + label: '显示进度条圆形',
  103 + component: 'Checkbox',
  104 + defaultValue: option.progressBarCircle,
  105 + },
  106 + {
  107 + field: ComponentConfigFieldEnum.SHOW_DEVICE_NAME,
  108 + label: '显示设备名称',
  109 + component: 'Checkbox',
  110 + defaultValue: option.showDeviceName,
  111 + },
  112 + {
  113 + field: ComponentConfigFieldEnum.SHOW_TIME,
  114 + label: '显示时间',
  115 + component: 'Checkbox',
  116 + defaultValue: option.showTime,
  117 + },
84 ], 118 ],
85 showActionButtonGroup: false, 119 showActionButtonGroup: false,
86 labelWidth: 120, 120 labelWidth: 120,
@@ -111,6 +145,8 @@ @@ -111,6 +145,8 @@
111 showTime: item[ComponentConfigFieldEnum.SHOW_TIME], 145 showTime: item[ComponentConfigFieldEnum.SHOW_TIME],
112 progressBarCircle: item[ComponentConfigFieldEnum.PROGRESS_BAR_CIRCLE], 146 progressBarCircle: item[ComponentConfigFieldEnum.PROGRESS_BAR_CIRCLE],
113 maxNumber: item[ComponentConfigFieldEnum.MAX_NUMBER], 147 maxNumber: item[ComponentConfigFieldEnum.MAX_NUMBER],
  148 + valueSize: item[ComponentConfigFieldEnum.VALUE_SIZE],
  149 + fontSize: item[ComponentConfigFieldEnum.FONT_SIZE],
114 } as ComponentInfo; 150 } as ComponentInfo;
115 }; 151 };
116 152
@@ -124,6 +160,8 @@ @@ -124,6 +160,8 @@
124 progressBarCircle, 160 progressBarCircle,
125 showTime, 161 showTime,
126 maxNumber, 162 maxNumber,
  163 + valueSize,
  164 + fontSize,
127 } = data; 165 } = data;
128 const firstRecord = gradientInfo.find((item) => item.key === Gradient.FIRST); 166 const firstRecord = gradientInfo.find((item) => item.key === Gradient.FIRST);
129 const secondRecord = gradientInfo.find((item) => item.key === Gradient.SECOND); 167 const secondRecord = gradientInfo.find((item) => item.key === Gradient.SECOND);
@@ -139,6 +177,8 @@ @@ -139,6 +177,8 @@
139 [ComponentConfigFieldEnum.SECOND_PHASE_COLOR]: secondRecord?.color, 177 [ComponentConfigFieldEnum.SECOND_PHASE_COLOR]: secondRecord?.color,
140 [ComponentConfigFieldEnum.PROGRESS_BAR_CIRCLE]: progressBarCircle, 178 [ComponentConfigFieldEnum.PROGRESS_BAR_CIRCLE]: progressBarCircle,
141 [ComponentConfigFieldEnum.MAX_NUMBER]: maxNumber, 179 [ComponentConfigFieldEnum.MAX_NUMBER]: maxNumber,
  180 + [ComponentConfigFieldEnum.VALUE_SIZE]: valueSize,
  181 + [ComponentConfigFieldEnum.FONT_SIZE]: fontSize,
142 }; 182 };
143 return setFieldsValue(value); 183 return setFieldsValue(value);
144 }; 184 };