Showing
58 changed files
with
2405 additions
and
905 deletions
Too many changes to show.
To preserve performance only 58 of 99 files are displayed.
@@ -6,12 +6,18 @@ VITE_PUBLIC_PATH = / | @@ -6,12 +6,18 @@ VITE_PUBLIC_PATH = / | ||
6 | 6 | ||
7 | # Cross-domain proxy, you can configure multiple | 7 | # Cross-domain proxy, you can configure multiple |
8 | # Please note that no line breaks | 8 | # Please note that no line breaks |
9 | -# VITE_PROXY = [["/api","http://192.168.10.118:8080/api"],["/upload","http://192.168.10.116:3300/upload"]] | ||
10 | -VITE_PROXY = [["/api","http://101.133.234.90:8080/api"],["/upload","http://192.168.10.116:3300/upload"]] | ||
11 | -# VITE_PROXY=[["/api","https://vvbin.cn/test"]] | 9 | + |
10 | +# 本地 | ||
11 | +# VITE_PROXY = [["/api","http://localhost:8080/api"]] | ||
12 | + | ||
13 | +# 线上 | ||
14 | +VITE_PROXY = [["/api","http://101.133.234.90:8080/api"]] | ||
15 | + | ||
16 | +# 实时数据的ws地址 | ||
17 | +VITE_WEB_SOCKET = ws://101.133.234.90:8080/api/ws/plugins/telemetry?token= | ||
12 | 18 | ||
13 | # Delete console | 19 | # Delete console |
14 | -VITE_DROP_CONSOLE = false | 20 | +VITE_DROP_CONSOLE = true |
15 | 21 | ||
16 | # Basic interface address SPA | 22 | # Basic interface address SPA |
17 | VITE_GLOB_API_URL=/api | 23 | VITE_GLOB_API_URL=/api |
@@ -10,26 +10,29 @@ VITE_DROP_CONSOLE = true | @@ -10,26 +10,29 @@ VITE_DROP_CONSOLE = true | ||
10 | # Whether to enable gzip or brotli compression | 10 | # Whether to enable gzip or brotli compression |
11 | # Optional: gzip | brotli | none | 11 | # Optional: gzip | brotli | none |
12 | # If you need multiple forms, you can use `,` to separate | 12 | # If you need multiple forms, you can use `,` to separate |
13 | -VITE_BUILD_COMPRESS = 'none' | 13 | +VITE_BUILD_COMPRESS = 'gzip' |
14 | 14 | ||
15 | # Whether to delete origin files when using compress, default false | 15 | # Whether to delete origin files when using compress, default false |
16 | VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE = false | 16 | VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE = false |
17 | 17 | ||
18 | # Basic interface address SPA | 18 | # Basic interface address SPA |
19 | -VITE_GLOB_API_URL=/api | 19 | +VITE_GLOB_API_URL=http://localhost:8080/api |
20 | 20 | ||
21 | # File upload address, optional | 21 | # File upload address, optional |
22 | # It can be forwarded by nginx or write the actual address directly | 22 | # It can be forwarded by nginx or write the actual address directly |
23 | -VITE_GLOB_UPLOAD_URL=/upload | 23 | +VITE_GLOB_UPLOAD_URL=http://localhost:8080/upload |
24 | 24 | ||
25 | # Interface prefix | 25 | # Interface prefix |
26 | -VITE_GLOB_API_URL_PREFIX=/v1 | 26 | +VITE_GLOB_API_URL_PREFIX=/yt |
27 | 27 | ||
28 | # Whether to enable image compression | 28 | # Whether to enable image compression |
29 | -VITE_USE_IMAGEMIN= true | 29 | +VITE_USE_IMAGEMIN= false |
30 | 30 | ||
31 | # use pwa | 31 | # use pwa |
32 | VITE_USE_PWA = false | 32 | VITE_USE_PWA = false |
33 | 33 | ||
34 | # Is it compatible with older browsers | 34 | # Is it compatible with older browsers |
35 | -VITE_LEGACY = false | 35 | +VITE_LEGACY = true |
36 | + | ||
37 | +# 实时数据的ws地址 | ||
38 | +VITE_WEB_SOCKET = ws://101.133.234.90:8080/api/ws/plugins/telemetry?token= |
configModel.ts
deleted
100644 → 0
1 | -import { BasicPageParams, BasicFetchResult } from '/@/api/model/baseModel'; | ||
2 | -/** | ||
3 | - * @description: Request list interface parameters | ||
4 | - */ | ||
5 | -export type MessageConfigParams = BasicPageParams & MessageParams; | ||
6 | - | ||
7 | -export type MessageParams = { | ||
8 | - status?: number; | ||
9 | - messageType?: string; | ||
10 | -}; | ||
11 | - | ||
12 | -export interface MessageConfig { | ||
13 | - id: string; | ||
14 | - configName: string; | ||
15 | - messageType: string; | ||
16 | - platformType: string; | ||
17 | - config: ConfigParams; | ||
18 | - createTime: string; | ||
19 | - updateTime: string; | ||
20 | - status: number; | ||
21 | -} | ||
22 | -export interface ConfigParams { | ||
23 | - host: string; | ||
24 | - port: number; | ||
25 | - username: string; | ||
26 | - password: string; | ||
27 | - accessKeyId: string; | ||
28 | - accessKeySecret: string; | ||
29 | -} | ||
30 | - | ||
31 | -/** | ||
32 | - * @description: Request list return value | ||
33 | - */ | ||
34 | -export type MessageConfigResultModel = BasicFetchResult<MessageConfig>; | ||
35 | - | ||
36 | -export type MessageConfigResult = MessageConfig; |
@@ -30,3 +30,14 @@ export const getDeviceDataKeys = (id: string) => { | @@ -30,3 +30,14 @@ export const getDeviceDataKeys = (id: string) => { | ||
30 | } | 30 | } |
31 | ); | 31 | ); |
32 | }; | 32 | }; |
33 | +// 获取设备状态,在线 or 离线时间 | ||
34 | +export const getDeviceActiveTime = (entityId: string) => { | ||
35 | + return defHttp.get( | ||
36 | + { | ||
37 | + url: `/plugins/telemetry/DEVICE/${entityId}/values/attributes?keys=active`, | ||
38 | + }, | ||
39 | + { | ||
40 | + joinPrefix: false, | ||
41 | + } | ||
42 | + ); | ||
43 | +}; |
src/api/dashboard/index.ts
0 → 100644
1 | +import { BasicPageParams } from './../model/baseModel'; | ||
2 | +import { defHttp } from '/@/utils/http/axios'; | ||
3 | +enum HomeEnum { | ||
4 | + home = '/homepage/left/top', | ||
5 | + TenantExpireTimeList = '/homepage/right', | ||
6 | + EntitiesQueryFind = '/entitiesQuery/find', | ||
7 | +} | ||
8 | + | ||
9 | +export const getHomeData = () => { | ||
10 | + return defHttp.get({ | ||
11 | + url: HomeEnum.home, | ||
12 | + }); | ||
13 | +}; | ||
14 | + | ||
15 | +// 获取即将过期租户列表 | ||
16 | +export const getTenantExpireTimeList = (params: BasicPageParams) => { | ||
17 | + return defHttp.get({ | ||
18 | + url: HomeEnum.TenantExpireTimeList, | ||
19 | + params, | ||
20 | + }); | ||
21 | +}; | ||
22 | + | ||
23 | +// 获取entities实体ID | ||
24 | +export const getEntitiesId = () => { | ||
25 | + return defHttp.post( | ||
26 | + { | ||
27 | + url: HomeEnum.EntitiesQueryFind, | ||
28 | + data: { | ||
29 | + entityFilter: { | ||
30 | + type: 'apiUsageState', | ||
31 | + resolveMultiple: false, | ||
32 | + }, | ||
33 | + pageLink: { | ||
34 | + pageSize: 1, | ||
35 | + page: 0, | ||
36 | + sortOrder: { | ||
37 | + key: { | ||
38 | + type: 'ENTITY_FIELD', | ||
39 | + key: 'createdTime', | ||
40 | + }, | ||
41 | + direction: 'DESC', | ||
42 | + }, | ||
43 | + }, | ||
44 | + entityFields: [ | ||
45 | + { | ||
46 | + type: 'ENTITY_FIELD', | ||
47 | + key: 'name', | ||
48 | + }, | ||
49 | + { | ||
50 | + type: 'ENTITY_FIELD', | ||
51 | + key: 'label', | ||
52 | + }, | ||
53 | + { | ||
54 | + type: 'ENTITY_FIELD', | ||
55 | + key: 'additionalInfo', | ||
56 | + }, | ||
57 | + ], | ||
58 | + }, | ||
59 | + }, | ||
60 | + { | ||
61 | + joinPrefix: false, | ||
62 | + } | ||
63 | + ); | ||
64 | +}; |
src/api/demo/error.ts
deleted
100644 → 0
src/api/demo/model/test.ts
deleted
100644 → 0
src/api/demo/tree.ts
deleted
100644 → 0
1 | -import { defHttp } from '/@/utils/http/axios'; | ||
2 | - | ||
3 | -enum Api { | ||
4 | - TREE_OPTIONS_LIST = '/tree/getDemoOptions', | ||
5 | -} | ||
6 | - | ||
7 | -/** | ||
8 | - * @description: Get sample options value | ||
9 | - */ | ||
10 | -export const treeOptionsListApi = (params?: Recordable) => | ||
11 | - defHttp.get<Recordable[]>({ url: Api.TREE_OPTIONS_LIST, params }); |
1 | -import { UploadApiResult } from './model/uploadModel'; | 1 | +import { FileUploadResponse } from './model/uploadModel'; |
2 | import { IPutPersonal } from './model/index'; | 2 | import { IPutPersonal } from './model/index'; |
3 | import { defHttp } from '/@/utils/http/axios'; | 3 | import { defHttp } from '/@/utils/http/axios'; |
4 | -import { UploadFileParams } from '/#/axios'; | ||
5 | 4 | ||
6 | enum API { | 5 | enum API { |
7 | - BaseUploadUrl = '/api/yt/oss/upload', | 6 | + BaseUploadUrl = '/oss/upload', |
8 | PutPersonalUrl = '/user/center', | 7 | PutPersonalUrl = '/user/center', |
9 | GetPersonalUrl = '/user/', | 8 | GetPersonalUrl = '/user/', |
10 | } | 9 | } |
11 | -/** | ||
12 | - * @description: Upload interface | ||
13 | - */ | ||
14 | -export const uploadApi = ( | ||
15 | - params: UploadFileParams, | ||
16 | - onUploadProgress: (progressEvent: ProgressEvent) => void | ||
17 | -) => { | ||
18 | - return defHttp.uploadFile<UploadApiResult>( | ||
19 | - { | ||
20 | - url: API.BaseUploadUrl, | ||
21 | - onUploadProgress, | ||
22 | - }, | ||
23 | - params | ||
24 | - ); | 10 | +export const uploadApi = (file) => { |
11 | + return defHttp.post<FileUploadResponse>({ url: API.BaseUploadUrl, params: file }); | ||
25 | }; | 12 | }; |
26 | 13 | ||
27 | export const personalGet = (id: string) => { | 14 | export const personalGet = (id: string) => { |
@@ -17,7 +17,7 @@ enum Api { | @@ -17,7 +17,7 @@ enum Api { | ||
17 | export const getMenuList = () => { | 17 | export const getMenuList = () => { |
18 | const userStore = useUserStore(); | 18 | const userStore = useUserStore(); |
19 | let url = Api.GetMenuList; | 19 | let url = Api.GetMenuList; |
20 | - if (userStore.getRoleList.find((v) => v == RoleEnum.ROLE_SYS_ADMIN)) { | 20 | + if (userStore.getRoleList.find((v) => v == RoleEnum.SYS_ADMIN)) { |
21 | url = Api.SysAdminMenuList; | 21 | url = Api.SysAdminMenuList; |
22 | } | 22 | } |
23 | return defHttp.get<getMenuListResultModel>({ url }); | 23 | return defHttp.get<getMenuListResultModel>({ url }); |
src/assets/images/kf.png
0 → 100644
1.1 KB
src/assets/images/zh.png
0 → 100644
1.45 KB
@@ -4,13 +4,14 @@ | @@ -4,13 +4,14 @@ | ||
4 | --> | 4 | --> |
5 | 5 | ||
6 | <template> | 6 | <template> |
7 | - <div class="anticon" :class="getAppLogoClass" @click="goHome"> | ||
8 | - <img :src="getLogo" /> | 7 | + <div class="application" :class="getAppLogoClass"> |
8 | + <img v-if="getLogo" :src="getLogo" /> | ||
9 | + <img v-else src="/src/assets/images/logo.png" /> | ||
9 | <span | 10 | <span |
10 | class="ml-2 md:opacity-100" | 11 | class="ml-2 md:opacity-100" |
11 | :class="getTitleClass" | 12 | :class="getTitleClass" |
12 | v-show="showTitle" | 13 | v-show="showTitle" |
13 | - style="white-space: nowrap" | 14 | + style="white-space: nowrap; font-size: small" |
14 | > | 15 | > |
15 | {{ getTitle }} | 16 | {{ getTitle }} |
16 | </span> | 17 | </span> |
@@ -19,10 +20,8 @@ | @@ -19,10 +20,8 @@ | ||
19 | <script lang="ts" setup> | 20 | <script lang="ts" setup> |
20 | import { computed, unref } from 'vue'; | 21 | import { computed, unref } from 'vue'; |
21 | import { useGlobSetting } from '/@/hooks/setting'; | 22 | import { useGlobSetting } from '/@/hooks/setting'; |
22 | - import { useGo } from '/@/hooks/web/usePage'; | ||
23 | import { useMenuSetting } from '/@/hooks/setting/useMenuSetting'; | 23 | import { useMenuSetting } from '/@/hooks/setting/useMenuSetting'; |
24 | import { useDesign } from '/@/hooks/web/useDesign'; | 24 | import { useDesign } from '/@/hooks/web/useDesign'; |
25 | - import { PageEnum } from '/@/enums/pageEnum'; | ||
26 | import { useUserStore } from '/@/store/modules/user'; | 25 | import { useUserStore } from '/@/store/modules/user'; |
27 | const props = defineProps({ | 26 | const props = defineProps({ |
28 | /** | 27 | /** |
@@ -43,7 +42,6 @@ | @@ -43,7 +42,6 @@ | ||
43 | const { getCollapsedShowTitle } = useMenuSetting(); | 42 | const { getCollapsedShowTitle } = useMenuSetting(); |
44 | const userStore = useUserStore(); | 43 | const userStore = useUserStore(); |
45 | const { title } = useGlobSetting(); | 44 | const { title } = useGlobSetting(); |
46 | - const go = useGo(); | ||
47 | 45 | ||
48 | const getAppLogoClass = computed(() => [ | 46 | const getAppLogoClass = computed(() => [ |
49 | prefixCls, | 47 | prefixCls, |
@@ -56,12 +54,8 @@ | @@ -56,12 +54,8 @@ | ||
56 | 'xs:opacity-0': !props.alwaysShowTitle, | 54 | 'xs:opacity-0': !props.alwaysShowTitle, |
57 | }, | 55 | }, |
58 | ]); | 56 | ]); |
59 | - | ||
60 | - function goHome() { | ||
61 | - go(userStore.getUserInfo.homePath || PageEnum.BASE_HOME); | ||
62 | - } | ||
63 | const getLogo = computed(() => { | 57 | const getLogo = computed(() => { |
64 | - return userStore.platInfo?.logo ?? '/src/assets/images/logo.png'; | 58 | + return userStore.platInfo?.logo; |
65 | }); | 59 | }); |
66 | const getTitle = computed(() => { | 60 | const getTitle = computed(() => { |
67 | // 设置icon | 61 | // 设置icon |
@@ -82,7 +76,6 @@ | @@ -82,7 +76,6 @@ | ||
82 | padding-left: 7px; | 76 | padding-left: 7px; |
83 | cursor: pointer; | 77 | cursor: pointer; |
84 | transition: all 0.2s ease; | 78 | transition: all 0.2s ease; |
85 | - | ||
86 | &.light { | 79 | &.light { |
87 | border-bottom: 1px solid @border-color-base; | 80 | border-bottom: 1px solid @border-color-base; |
88 | } | 81 | } |
1 | export enum RoleEnum { | 1 | export enum RoleEnum { |
2 | - ROLE_SYS_ADMIN = 'SYS_ADMIN', | ||
3 | - ROLE_TENANT_ADMIN = 'TENANT_ADMIN', | ||
4 | - ROLE_NORMAL_USER = 'CUSTOMER_USER', | ||
5 | - ROLE_PLATFORM_ADMIN = 'PLATFORM_ADMIN', | 2 | + SYS_ADMIN = 'SYS_ADMIN', |
3 | + PLATFORM_ADMIN = 'PLATFORM_ADMIN', | ||
4 | + TENANT_ADMIN = 'TENANT_ADMIN', | ||
5 | + CUSTOMER_USER = 'CUSTOMER_USER', | ||
6 | +} | ||
7 | + | ||
8 | +export function isAdmin(role: string) { | ||
9 | + if (role === RoleEnum.SYS_ADMIN || role === RoleEnum.PLATFORM_ADMIN) { | ||
10 | + return true; | ||
11 | + } else if (role === RoleEnum.TENANT_ADMIN || role === RoleEnum.CUSTOMER_USER) { | ||
12 | + return false; | ||
13 | + } | ||
6 | } | 14 | } |
src/hooks/web/useBatchDelete.ts
0 → 100644
1 | +import { ref, computed } from 'vue'; | ||
2 | +import { useMessage } from '/@/hooks/web/useMessage'; | ||
3 | +/** | ||
4 | + * | ||
5 | + * @param deleteFn 要删除的API接口方法 | ||
6 | + * @param handleSuccess 刷新表格的方法 | ||
7 | + * @returns { | ||
8 | + * hasBatchDelete: 是否可以删除 | ||
9 | + * selectionOptions 表格复选框配置项 | ||
10 | + * handleDeleteOrBatchDelete 删除方法,适用单一删除和批量删除。参数为null为批量删除 | ||
11 | + * } | ||
12 | + * | ||
13 | + */ | ||
14 | +export interface selectionOptions { | ||
15 | + rowKey: string; | ||
16 | + clickToRowSelect: boolean; | ||
17 | + rowSelection: { | ||
18 | + onChange: (selectedRowKeys: string[]) => void; | ||
19 | + type: 'radio' | 'checkbox'; | ||
20 | + }; | ||
21 | +} | ||
22 | +export const useBatchDelete = ( | ||
23 | + deleteFn: (deleteIds: string[]) => Promise<void>, | ||
24 | + handleSuccess: () => void | ||
25 | +) => { | ||
26 | + const { createMessage } = useMessage(); | ||
27 | + const selectedRowIds = ref<string[]>([]); | ||
28 | + const hasBatchDelete = computed(() => selectedRowIds.value.length <= 0); | ||
29 | + // 复选框事件 | ||
30 | + const onSelectRowChange = (selectedRowKeys: string[]) => { | ||
31 | + selectedRowIds.value = selectedRowKeys; | ||
32 | + }; | ||
33 | + const handleDeleteOrBatchDelete = async (record: Recordable | null) => { | ||
34 | + if (record) { | ||
35 | + try { | ||
36 | + await deleteFn([record.id]); | ||
37 | + createMessage.success('删除联系人成功'); | ||
38 | + handleSuccess(); | ||
39 | + } catch (e) { | ||
40 | + createMessage.error('删除失败'); | ||
41 | + } | ||
42 | + } else { | ||
43 | + try { | ||
44 | + await deleteFn(selectedRowIds.value); | ||
45 | + createMessage.success('批量删除联系人成功'); | ||
46 | + selectedRowIds.value = []; | ||
47 | + handleSuccess(); | ||
48 | + } catch (e) { | ||
49 | + createMessage.info('删除失败'); | ||
50 | + } | ||
51 | + } | ||
52 | + }; | ||
53 | + const selectionOptions: selectionOptions = { | ||
54 | + rowKey: 'id', | ||
55 | + clickToRowSelect: false, | ||
56 | + rowSelection: { | ||
57 | + onChange: onSelectRowChange, | ||
58 | + type: 'checkbox', | ||
59 | + }, | ||
60 | + }; | ||
61 | + return { hasBatchDelete, selectionOptions, handleDeleteOrBatchDelete }; | ||
62 | +}; |
1 | import { FormSchema } from '/@/components/Table'; | 1 | import { FormSchema } from '/@/components/Table'; |
2 | +import { phoneRule, emailRule } from '/@/utils/rules'; | ||
2 | 3 | ||
3 | export const formSchema: FormSchema[] = [ | 4 | export const formSchema: FormSchema[] = [ |
4 | { | 5 | { |
5 | - field: 'nickName', | 6 | + field: 'realName', |
6 | label: '用户昵称', | 7 | label: '用户昵称', |
7 | colProps: { span: 13 }, | 8 | colProps: { span: 13 }, |
8 | required: true, | 9 | required: true, |
@@ -20,6 +21,7 @@ export const formSchema: FormSchema[] = [ | @@ -20,6 +21,7 @@ export const formSchema: FormSchema[] = [ | ||
20 | componentProps: { | 21 | componentProps: { |
21 | placeholder: '请输入手机号码', | 22 | placeholder: '请输入手机号码', |
22 | }, | 23 | }, |
24 | + rules: phoneRule, | ||
23 | }, | 25 | }, |
24 | { | 26 | { |
25 | field: 'email', | 27 | field: 'email', |
@@ -30,5 +32,6 @@ export const formSchema: FormSchema[] = [ | @@ -30,5 +32,6 @@ export const formSchema: FormSchema[] = [ | ||
30 | componentProps: { | 32 | componentProps: { |
31 | placeholder: '请输入邮箱', | 33 | placeholder: '请输入邮箱', |
32 | }, | 34 | }, |
35 | + rules: emailRule, | ||
33 | }, | 36 | }, |
34 | ]; | 37 | ]; |
1 | <template> | 1 | <template> |
2 | <BasicModal | 2 | <BasicModal |
3 | :useWrapper="true" | 3 | :useWrapper="true" |
4 | - width="80vw" | 4 | + width="82vw" |
5 | :height="compHeight" | 5 | :height="compHeight" |
6 | v-bind="$attrs" | 6 | v-bind="$attrs" |
7 | @register="registerModal" | 7 | @register="registerModal" |
@@ -22,15 +22,34 @@ | @@ -22,15 +22,34 @@ | ||
22 | ><p style="font-size: 17px; margin-top: 7px; margin-left: 10px">个人信息</p></div | 22 | ><p style="font-size: 17px; margin-top: 7px; margin-left: 10px">个人信息</p></div |
23 | > | 23 | > |
24 | <div class="change-avatar" style="text-align: center"> | 24 | <div class="change-avatar" style="text-align: center"> |
25 | - <div class="mb-2">头像</div> | ||
26 | - <CropperAvatar | ||
27 | - :uploadApi="uploadApi" | ||
28 | - :value="avatar" | ||
29 | - btnText="更换头像" | ||
30 | - :btnProps="{ preIcon: 'ant-design:cloud-upload-outlined' }" | ||
31 | - @change="updateAvatar" | ||
32 | - width="150" | ||
33 | - /> | 25 | + <div class="mb-2" style="font-weight: 700">个人头像</div> |
26 | + <Upload | ||
27 | + style="width: 20vw" | ||
28 | + name="avatar" | ||
29 | + list-type="picture-card" | ||
30 | + class="avatar-uploader" | ||
31 | + :show-upload-list="false" | ||
32 | + :customRequest="customUploadqrcodePic" | ||
33 | + :before-upload="beforeUploadqrcodePic" | ||
34 | + > | ||
35 | + <img | ||
36 | + style="text-align: center; border-radius: 50%; width: 10vw; height: 15vh" | ||
37 | + v-if="peresonalPic" | ||
38 | + :src="peresonalPic" | ||
39 | + alt="avatar" | ||
40 | + /> | ||
41 | + <div v-else> | ||
42 | + <div style="margin-top: 30px"> | ||
43 | + <PlusOutlined style="font-size: 30px" /> | ||
44 | + </div> | ||
45 | + <div | ||
46 | + class="ant-upload-text flex" | ||
47 | + style="width: 280px; height: 130px; align-items: center" | ||
48 | + > | ||
49 | + 支持.PNG、.JPG、.SVG格式,建议尺寸为300px × 300px(及以上),大小不超过2M。</div | ||
50 | + > | ||
51 | + </div> | ||
52 | + </Upload> | ||
34 | </div> | 53 | </div> |
35 | <Description | 54 | <Description |
36 | class="mt-8" | 55 | class="mt-8" |
@@ -66,13 +85,13 @@ | @@ -66,13 +85,13 @@ | ||
66 | import { BasicForm, useForm } from '/@/components/Form/index'; | 85 | import { BasicForm, useForm } from '/@/components/Form/index'; |
67 | import { formSchema } from './config'; | 86 | import { formSchema } from './config'; |
68 | import { Description, DescItem, useDescription } from '/@/components/Description/index'; | 87 | import { Description, DescItem, useDescription } from '/@/components/Description/index'; |
69 | - import { CropperAvatar } from '/@/components/Cropper'; | ||
70 | - import defaultImage from '/@/assets/images/logo.png'; | ||
71 | import { uploadApi, personalPut } from '/@/api/personal/index'; | 88 | import { uploadApi, personalPut } from '/@/api/personal/index'; |
72 | import { useMessage } from '/@/hooks/web/useMessage'; | 89 | import { useMessage } from '/@/hooks/web/useMessage'; |
73 | import { USER_INFO_KEY } from '/@/enums/cacheEnum'; | 90 | import { USER_INFO_KEY } from '/@/enums/cacheEnum'; |
74 | import { getAuthCache } from '/@/utils/auth'; | 91 | import { getAuthCache } from '/@/utils/auth'; |
75 | - import { useUserStore } from '/@/store/modules/user'; | 92 | + import { Upload } from 'ant-design-vue'; |
93 | + import { PlusOutlined } from '@ant-design/icons-vue'; | ||
94 | + import type { FileItem } from '/@/components/Upload/src/typing'; | ||
76 | 95 | ||
77 | const schema: DescItem[] = [ | 96 | const schema: DescItem[] = [ |
78 | { | 97 | { |
@@ -102,68 +121,91 @@ | @@ -102,68 +121,91 @@ | ||
102 | ]; | 121 | ]; |
103 | export default defineComponent({ | 122 | export default defineComponent({ |
104 | name: 'index', | 123 | name: 'index', |
105 | - components: { BasicModal, BasicForm, Description, CropperAvatar }, | ||
106 | - setup() { | ||
107 | - const userStore = useUserStore(); | 124 | + components: { BasicModal, BasicForm, Description, Upload, PlusOutlined }, |
125 | + emits: ['refreshPersonl', 'register'], | ||
126 | + setup(_, { emit }) { | ||
108 | const userInfo = getAuthCache(USER_INFO_KEY); | 127 | const userInfo = getAuthCache(USER_INFO_KEY); |
109 | const { createMessage } = useMessage(); | 128 | const { createMessage } = useMessage(); |
110 | const getPersonalValue: any = ref({}); | 129 | const getPersonalValue: any = ref({}); |
111 | const getPersonalDetailValue: any = ref({}); | 130 | const getPersonalDetailValue: any = ref({}); |
112 | - const avatarUrl: any = ref(''); | 131 | + const updatePersonalData: any = ref({}); |
113 | const getBackendV: any = ref({}); | 132 | const getBackendV: any = ref({}); |
114 | const [registerDesc] = useDescription({ | 133 | const [registerDesc] = useDescription({ |
115 | title: '个人详情', | 134 | title: '个人详情', |
116 | schema: schema, | 135 | schema: schema, |
117 | }); | 136 | }); |
118 | 137 | ||
119 | - const [registerModal, { closeModal }] = useModalInner(); | ||
120 | - const [registerForm, { validate, resetFields }] = useForm({ | 138 | + const peresonalPic = ref(); |
139 | + | ||
140 | + const customUploadqrcodePic = async ({ file }) => { | ||
141 | + if (beforeUploadqrcodePic(file)) { | ||
142 | + const formData = new FormData(); | ||
143 | + formData.append('file', file); | ||
144 | + const response = await uploadApi(formData); | ||
145 | + if (response.fileStaticUri) { | ||
146 | + peresonalPic.value = response.fileStaticUri; | ||
147 | + } | ||
148 | + } | ||
149 | + }; | ||
150 | + | ||
151 | + const beforeUploadqrcodePic = (file: FileItem) => { | ||
152 | + const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png'; | ||
153 | + if (!isJpgOrPng) { | ||
154 | + createMessage.error('只能上传图片文件!'); | ||
155 | + } | ||
156 | + const isLt2M = (file.size as number) / 1024 / 1024 < 2; | ||
157 | + if (!isLt2M) { | ||
158 | + createMessage.error('图片大小不能超过2MB!'); | ||
159 | + } | ||
160 | + return isJpgOrPng && isLt2M; | ||
161 | + }; | ||
162 | + | ||
163 | + const [registerForm, { validate, resetFields, setFieldsValue }] = useForm({ | ||
121 | showActionButtonGroup: false, | 164 | showActionButtonGroup: false, |
122 | schemas: formSchema, | 165 | schemas: formSchema, |
123 | }); | 166 | }); |
124 | - const avatar = computed(() => { | ||
125 | - const { avatar } = userStore.getUserInfo; | ||
126 | - return avatar || defaultImage; | 167 | + |
168 | + const [registerModal, { closeModal }] = useModalInner(async (data) => { | ||
169 | + (peresonalPic.value = data.userInfo.avatar), | ||
170 | + setFieldsValue({ | ||
171 | + realName: data.userInfo.realName, | ||
172 | + phoneNumber: data.userInfo.phoneNumber, | ||
173 | + email: data.userInfo.email, | ||
174 | + }); | ||
175 | + if (data.userInfo) { | ||
176 | + getPersonalDetailValue.value = data.userInfo; | ||
177 | + } | ||
178 | + if (Object.keys(updatePersonalData.value).length != 0) { | ||
179 | + getPersonalDetailValue.value = updatePersonalData.value; | ||
180 | + peresonalPic.value = updatePersonalData.value.avatar; | ||
181 | + setFieldsValue({ | ||
182 | + realName: updatePersonalData.value.realName, | ||
183 | + phoneNumber: updatePersonalData.value.phoneNumber, | ||
184 | + email: updatePersonalData.value.email, | ||
185 | + }); | ||
186 | + } | ||
127 | }); | 187 | }); |
128 | const handleSubmit = async () => { | 188 | const handleSubmit = async () => { |
129 | - // console.log(userStore.getUserInfo); | ||
130 | const getUserInfo = await userInfo; | 189 | const getUserInfo = await userInfo; |
131 | - // console.log(getUserInfo); | ||
132 | getPersonalValue.value = await validate(); | 190 | getPersonalValue.value = await validate(); |
133 | getPersonalValue.value.id = getUserInfo.userId; | 191 | getPersonalValue.value.id = getUserInfo.userId; |
134 | getPersonalValue.value.username = getBackendV.value.username; | 192 | getPersonalValue.value.username = getBackendV.value.username; |
135 | - getPersonalValue.value.avatar = avatarUrl.value; | ||
136 | - await personalPut(getPersonalValue.value); | 193 | + getPersonalValue.value.avatar = peresonalPic.value; |
194 | + const data = await personalPut(getPersonalValue.value); | ||
195 | + updatePersonalData.value = data; | ||
137 | createMessage.success('修改成功'); | 196 | createMessage.success('修改成功'); |
138 | closeModal(); | 197 | closeModal(); |
139 | resetFields(); | 198 | resetFields(); |
199 | + emit('refreshPersonl', updatePersonalData.value); | ||
140 | }; | 200 | }; |
141 | - const updateAvatar = async (v) => { | ||
142 | - avatarUrl.value = v.data.fileStaticUri; | ||
143 | - // console.log(avatarUrl.value); | ||
144 | - // await personalPut({ avatar: v }); | ||
145 | - }; | ||
146 | - const getPersonalDetail = async () => { | ||
147 | - try { | ||
148 | - const getUserInfo = await userInfo; | ||
149 | - getPersonalDetailValue.value = getUserInfo; | ||
150 | - } catch (e) { | ||
151 | - return e; | ||
152 | - } | ||
153 | - }; | ||
154 | - getPersonalDetail(); | ||
155 | - | ||
156 | - // onMounted(async () => { | ||
157 | - // getPersonalDetail(); | ||
158 | - // }); | ||
159 | const compHeight = computed(() => { | 201 | const compHeight = computed(() => { |
160 | return 1000; | 202 | return 1000; |
161 | }); | 203 | }); |
162 | return { | 204 | return { |
163 | - uploadApi, | 205 | + peresonalPic, |
206 | + beforeUploadqrcodePic, | ||
207 | + customUploadqrcodePic, | ||
164 | compHeight, | 208 | compHeight, |
165 | - updateAvatar, | ||
166 | - avatar, | ||
167 | handleSubmit, | 209 | handleSubmit, |
168 | getPersonalDetailValue, | 210 | getPersonalDetailValue, |
169 | registerDesc, | 211 | registerDesc, |
@@ -174,4 +216,22 @@ | @@ -174,4 +216,22 @@ | ||
174 | }, | 216 | }, |
175 | }); | 217 | }); |
176 | </script> | 218 | </script> |
177 | -<style lang="less"></style> | 219 | +<style scoped lang="less"> |
220 | + .change-avatar { | ||
221 | + /deep/ .ant-upload-select-picture-card { | ||
222 | + display: inherit; | ||
223 | + float: none; | ||
224 | + width: 10vw; | ||
225 | + height: 17vh; | ||
226 | + margin-right: 8px; | ||
227 | + margin-bottom: 8px; | ||
228 | + text-align: center; | ||
229 | + vertical-align: top; | ||
230 | + background-color: #fafafa; | ||
231 | + border: 1px dashed #d9d9d9; | ||
232 | + border-radius: 50%; | ||
233 | + cursor: pointer; | ||
234 | + transition: border-color 0.3s ease; | ||
235 | + } | ||
236 | + } | ||
237 | +</style> |
1 | <template> | 1 | <template> |
2 | <Dropdown placement="bottomLeft" :overlayClassName="`${prefixCls}-dropdown-overlay`"> | 2 | <Dropdown placement="bottomLeft" :overlayClassName="`${prefixCls}-dropdown-overlay`"> |
3 | <span :class="[prefixCls, `${prefixCls}--${theme}`]" class="flex"> | 3 | <span :class="[prefixCls, `${prefixCls}--${theme}`]" class="flex"> |
4 | - <img :class="`${prefixCls}__header`" :src="getUserInfo.avatar" /> | 4 | + <img |
5 | + :class="`${prefixCls}__header`" | ||
6 | + :src="refreshPersonlData.avatar ? refreshPersonlData.avatar : getUserInfo.avatar" | ||
7 | + /> | ||
5 | <span :class="`${prefixCls}__info hidden md:block`"> | 8 | <span :class="`${prefixCls}__info hidden md:block`"> |
6 | <span :class="`${prefixCls}__name `" class="truncate"> | 9 | <span :class="`${prefixCls}__name `" class="truncate"> |
7 | - {{ getUserInfo.realName }} | 10 | + {{ refreshPersonlData.realName ? refreshPersonlData.realName : getUserInfo.realName }} |
8 | </span> | 11 | </span> |
9 | </span> | 12 | </span> |
10 | </span> | 13 | </span> |
@@ -12,12 +15,10 @@ | @@ -12,12 +15,10 @@ | ||
12 | <template #overlay> | 15 | <template #overlay> |
13 | <Menu @click="handleMenuClick"> | 16 | <Menu @click="handleMenuClick"> |
14 | <MenuItem | 17 | <MenuItem |
15 | - key="doc" | ||
16 | - :text="t('layout.header.dropdownItemDoc')" | 18 | + key="personal" |
19 | + :text="t('layout.header.dropdownItemPersonal')" | ||
17 | icon="ion:document-text-outline" | 20 | icon="ion:document-text-outline" |
18 | - v-if="getShowDoc" | ||
19 | /> | 21 | /> |
20 | - <MenuDivider v-if="getShowDoc" /> | ||
21 | <MenuItem | 22 | <MenuItem |
22 | v-if="getUseLockPage" | 23 | v-if="getUseLockPage" |
23 | key="lock" | 24 | key="lock" |
@@ -29,22 +30,21 @@ | @@ -29,22 +30,21 @@ | ||
29 | :text="t('layout.header.dropdownItemLoginOut')" | 30 | :text="t('layout.header.dropdownItemLoginOut')" |
30 | icon="ion:power-outline" | 31 | icon="ion:power-outline" |
31 | /> | 32 | /> |
32 | - <MenuItem | ||
33 | - key="personal" | ||
34 | - :text="t('layout.header.dropdownItemPersonal')" | ||
35 | - icon="ion:build-outlined" | ||
36 | - /> | ||
37 | </Menu> | 33 | </Menu> |
38 | </template> | 34 | </template> |
39 | </Dropdown> | 35 | </Dropdown> |
40 | <LockAction @register="register" /> | 36 | <LockAction @register="register" /> |
41 | - <PersonalChild @register="registerPersonal" /> | 37 | + <PersonalChild |
38 | + @refreshPersonl="refreshPersonlFunc" | ||
39 | + ref="personalRef" | ||
40 | + @register="registerPersonal" | ||
41 | + /> | ||
42 | </template> | 42 | </template> |
43 | <script lang="ts"> | 43 | <script lang="ts"> |
44 | // components | 44 | // components |
45 | import { Dropdown, Menu } from 'ant-design-vue'; | 45 | import { Dropdown, Menu } from 'ant-design-vue'; |
46 | 46 | ||
47 | - import { defineComponent, computed } from 'vue'; | 47 | + import { defineComponent, computed, getCurrentInstance, ref, reactive } from 'vue'; |
48 | 48 | ||
49 | import { DOC_URL } from '/@/settings/siteSetting'; | 49 | import { DOC_URL } from '/@/settings/siteSetting'; |
50 | 50 | ||
@@ -53,13 +53,12 @@ | @@ -53,13 +53,12 @@ | ||
53 | import { useI18n } from '/@/hooks/web/useI18n'; | 53 | import { useI18n } from '/@/hooks/web/useI18n'; |
54 | import { useDesign } from '/@/hooks/web/useDesign'; | 54 | import { useDesign } from '/@/hooks/web/useDesign'; |
55 | import { useModal } from '/@/components/Modal'; | 55 | import { useModal } from '/@/components/Modal'; |
56 | - | ||
57 | import headerImg from '/@/assets/images/header.jpg'; | 56 | import headerImg from '/@/assets/images/header.jpg'; |
58 | import { propTypes } from '/@/utils/propTypes'; | 57 | import { propTypes } from '/@/utils/propTypes'; |
59 | import { openWindow } from '/@/utils'; | 58 | import { openWindow } from '/@/utils'; |
60 | - | ||
61 | import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent'; | 59 | import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent'; |
62 | - | 60 | + import { USER_INFO_KEY } from '/@/enums/cacheEnum'; |
61 | + import { getAuthCache } from '/@/utils/auth'; | ||
63 | type MenuEvent = 'logout' | 'doc' | 'lock' | 'personal'; | 62 | type MenuEvent = 'logout' | 'doc' | 'lock' | 'personal'; |
64 | 63 | ||
65 | export default defineComponent({ | 64 | export default defineComponent({ |
@@ -68,7 +67,6 @@ | @@ -68,7 +67,6 @@ | ||
68 | Dropdown, | 67 | Dropdown, |
69 | Menu, | 68 | Menu, |
70 | MenuItem: createAsyncComponent(() => import('./DropMenuItem.vue')), | 69 | MenuItem: createAsyncComponent(() => import('./DropMenuItem.vue')), |
71 | - MenuDivider: Menu.Divider, | ||
72 | LockAction: createAsyncComponent(() => import('../lock/LockModal.vue')), | 70 | LockAction: createAsyncComponent(() => import('../lock/LockModal.vue')), |
73 | PersonalChild: createAsyncComponent(() => import('../personal/index.vue')), | 71 | PersonalChild: createAsyncComponent(() => import('../personal/index.vue')), |
74 | }, | 72 | }, |
@@ -76,14 +74,21 @@ | @@ -76,14 +74,21 @@ | ||
76 | theme: propTypes.oneOf(['dark', 'light']), | 74 | theme: propTypes.oneOf(['dark', 'light']), |
77 | }, | 75 | }, |
78 | setup() { | 76 | setup() { |
77 | + const refreshPersonlData = reactive({ | ||
78 | + avatar: '', | ||
79 | + realName: '', | ||
80 | + }); | ||
81 | + const userInfo = getAuthCache(USER_INFO_KEY); | ||
82 | + const { proxy } = getCurrentInstance(); | ||
83 | + const personalRef = ref(null); | ||
79 | const { prefixCls } = useDesign('header-user-dropdown'); | 84 | const { prefixCls } = useDesign('header-user-dropdown'); |
80 | const { t } = useI18n(); | 85 | const { t } = useI18n(); |
81 | const { getShowDoc, getUseLockPage } = useHeaderSetting(); | 86 | const { getShowDoc, getUseLockPage } = useHeaderSetting(); |
82 | const userStore = useUserStore(); | 87 | const userStore = useUserStore(); |
83 | 88 | ||
84 | const getUserInfo = computed(() => { | 89 | const getUserInfo = computed(() => { |
85 | - const { realName = '', avatar, desc } = userStore.getUserInfo || {}; | ||
86 | - return { realName, avatar: avatar || headerImg, desc }; | 90 | + const { realName = '', avatar } = userStore.getUserInfo || {}; |
91 | + return { realName, avatar: avatar || headerImg }; | ||
87 | }); | 92 | }); |
88 | 93 | ||
89 | const [register, { openModal }] = useModal(); | 94 | const [register, { openModal }] = useModal(); |
@@ -122,11 +127,21 @@ | @@ -122,11 +127,21 @@ | ||
122 | 127 | ||
123 | const openPersonalFunc = () => { | 128 | const openPersonalFunc = () => { |
124 | setTimeout(() => { | 129 | setTimeout(() => { |
125 | - openModalPersonal(true); | 130 | + openModalPersonal(true, { |
131 | + userInfo, | ||
132 | + }); | ||
126 | }, 10); | 133 | }, 10); |
127 | }; | 134 | }; |
128 | 135 | ||
136 | + const refreshPersonlFunc = (v) => { | ||
137 | + refreshPersonlData.avatar = v.avatar; | ||
138 | + refreshPersonlData.realName = v.realName; | ||
139 | + }; | ||
140 | + | ||
129 | return { | 141 | return { |
142 | + refreshPersonlData, | ||
143 | + refreshPersonlFunc, | ||
144 | + personalRef, | ||
130 | registerPersonal, | 145 | registerPersonal, |
131 | openPersonalFunc, | 146 | openPersonalFunc, |
132 | prefixCls, | 147 | prefixCls, |
@@ -21,43 +21,18 @@ | @@ -21,43 +21,18 @@ | ||
21 | </transition> | 21 | </transition> |
22 | </template> | 22 | </template> |
23 | </RouterView> | 23 | </RouterView> |
24 | - <!-- <BasicModal | ||
25 | - @register="register" | ||
26 | - v-bind="$attrs" | ||
27 | - :mask="true" | ||
28 | - :showCancelBtn="false" | ||
29 | - :showOkBtn="false" | ||
30 | - :canFullscreen="false" | ||
31 | - :closable="false" | ||
32 | - :maskStyle="maskColor" | ||
33 | - :height="600" | ||
34 | - :width="1500" | ||
35 | - :maskClosable="false" | ||
36 | - title="请您修改初始密码" | ||
37 | - :helpMessage="['请您修改初始密码']" | ||
38 | - :keyboard="false" | ||
39 | - > | ||
40 | - <PasswordDialog /> | ||
41 | - </BasicModal> --> | 24 | + |
42 | <FrameLayout v-if="getCanEmbedIFramePage" /> | 25 | <FrameLayout v-if="getCanEmbedIFramePage" /> |
43 | </template> | 26 | </template> |
44 | 27 | ||
45 | <script lang="ts"> | 28 | <script lang="ts"> |
46 | - import { computed, defineComponent, unref, onMounted } from 'vue'; | ||
47 | - // import PasswordDialog from '/@/views/system/password/index.vue'; | ||
48 | - | 29 | + import { computed, defineComponent, unref } from 'vue'; |
49 | import FrameLayout from '/@/layouts/iframe/index.vue'; | 30 | import FrameLayout from '/@/layouts/iframe/index.vue'; |
50 | - | ||
51 | import { useRootSetting } from '/@/hooks/setting/useRootSetting'; | 31 | import { useRootSetting } from '/@/hooks/setting/useRootSetting'; |
52 | - | ||
53 | import { useTransitionSetting } from '/@/hooks/setting/useTransitionSetting'; | 32 | import { useTransitionSetting } from '/@/hooks/setting/useTransitionSetting'; |
54 | import { useMultipleTabSetting } from '/@/hooks/setting/useMultipleTabSetting'; | 33 | import { useMultipleTabSetting } from '/@/hooks/setting/useMultipleTabSetting'; |
55 | import { getTransitionName } from './transition'; | 34 | import { getTransitionName } from './transition'; |
56 | - | ||
57 | import { useMultipleTabStore } from '/@/store/modules/multipleTab'; | 35 | import { useMultipleTabStore } from '/@/store/modules/multipleTab'; |
58 | - // import { BasicModal, useModal } from '/@/components/Modal'; | ||
59 | - // import { USER_INFO_KEY } from '/@/enums/cacheEnum'; | ||
60 | - // import { getAuthCache } from '/@/utils/auth'; | ||
61 | export default defineComponent({ | 36 | export default defineComponent({ |
62 | name: 'PageLayout', | 37 | name: 'PageLayout', |
63 | components: { FrameLayout }, | 38 | components: { FrameLayout }, |
@@ -78,17 +53,6 @@ | @@ -78,17 +53,6 @@ | ||
78 | return tabStore.getCachedTabList; | 53 | return tabStore.getCachedTabList; |
79 | }); | 54 | }); |
80 | 55 | ||
81 | - // const [register, { openModal }] = useModal(); | ||
82 | - // const maskColor = ref({ backgroundColor: 'grey' }); | ||
83 | - // const statusModel = ref(false); | ||
84 | - onMounted(() => { | ||
85 | - // const userInfo = getAuthCache(USER_INFO_KEY); | ||
86 | - // if (userInfo.needSetPwd == true) { | ||
87 | - // statusModel.value = true; | ||
88 | - // openModal(statusModel.value); | ||
89 | - // } | ||
90 | - }); | ||
91 | - | ||
92 | return { | 56 | return { |
93 | getTransitionName, | 57 | getTransitionName, |
94 | openCache, | 58 | openCache, |
@@ -96,8 +60,6 @@ | @@ -96,8 +60,6 @@ | ||
96 | getBasicTransition, | 60 | getBasicTransition, |
97 | getCaches, | 61 | getCaches, |
98 | getCanEmbedIFramePage, | 62 | getCanEmbedIFramePage, |
99 | - // register, | ||
100 | - // maskColor, | ||
101 | }; | 63 | }; |
102 | }, | 64 | }, |
103 | }); | 65 | }); |
@@ -12,7 +12,7 @@ export default { | @@ -12,7 +12,7 @@ export default { | ||
12 | networkExceptionMsg: | 12 | networkExceptionMsg: |
13 | 'Please check if your network connection is normal! The network is abnormal', | 13 | 'Please check if your network connection is normal! The network is abnormal', |
14 | 14 | ||
15 | - errMsg401: 'no permission', | 15 | + errMsg401: '', |
16 | errMsg403: 'not authorized', | 16 | errMsg403: 'not authorized', |
17 | errMsg404: 'the resource was not found!', | 17 | errMsg404: 'the resource was not found!', |
18 | errMsg405: 'Network request error, request method not allowed!', | 18 | errMsg405: 'Network request error, request method not allowed!', |
@@ -10,8 +10,7 @@ export default { | @@ -10,8 +10,7 @@ export default { | ||
10 | apiRequestFailed: '请求出错,请稍候重试', | 10 | apiRequestFailed: '请求出错,请稍候重试', |
11 | networkException: '网络异常', | 11 | networkException: '网络异常', |
12 | networkExceptionMsg: '网络异常,请检查您的网络连接是否正常!', | 12 | networkExceptionMsg: '网络异常,请检查您的网络连接是否正常!', |
13 | - | ||
14 | - errMsg401: '没有权限!', | 13 | + errMsg401: '', |
15 | errMsg403: '未授权', | 14 | errMsg403: '未授权', |
16 | errMsg404: '未找到该资源!', | 15 | errMsg404: '未找到该资源!', |
17 | errMsg405: '网络请求错误,请求方法未允许!', | 16 | errMsg405: '网络请求错误,请求方法未允许!', |
@@ -14,13 +14,7 @@ import { setupStore } from '/@/store'; | @@ -14,13 +14,7 @@ import { setupStore } from '/@/store'; | ||
14 | import { setupGlobDirectives } from '/@/directives'; | 14 | import { setupGlobDirectives } from '/@/directives'; |
15 | import { setupI18n } from '/@/locales/setupI18n'; | 15 | import { setupI18n } from '/@/locales/setupI18n'; |
16 | import { registerGlobComp } from '/@/components/registerGlobComp'; | 16 | import { registerGlobComp } from '/@/components/registerGlobComp'; |
17 | -// Do not introduce on-demand in local development? | ||
18 | -// In the local development for introduce on-demand, the number of browser requests will increase by about 20%. | ||
19 | -// Which may slow down the browser refresh. | ||
20 | -// Therefore, all are introduced in local development, and only introduced on demand in the production environment | ||
21 | -if (import.meta.env.DEV) { | ||
22 | - import('ant-design-vue/dist/antd.less'); | ||
23 | -} | 17 | +import 'ant-design-vue/dist/antd.less'; |
24 | 18 | ||
25 | async function bootstrap() { | 19 | async function bootstrap() { |
26 | const app = createApp(App); | 20 | const app = createApp(App); |
@@ -129,7 +129,6 @@ export const useUserStore = defineStore({ | @@ -129,7 +129,6 @@ export const useUserStore = defineStore({ | ||
129 | try { | 129 | try { |
130 | const { goHome = true, mode, ...loginParams } = params; | 130 | const { goHome = true, mode, ...loginParams } = params; |
131 | const data = await loginApi(loginParams, mode); | 131 | const data = await loginApi(loginParams, mode); |
132 | - console.log(data); | ||
133 | return this.process(data, goHome); | 132 | return this.process(data, goHome); |
134 | } catch (error) { | 133 | } catch (error) { |
135 | return Promise.reject(error); | 134 | return Promise.reject(error); |
@@ -10,7 +10,6 @@ import { SessionTimeoutProcessingEnum } from '/@/enums/appEnum'; | @@ -10,7 +10,6 @@ import { SessionTimeoutProcessingEnum } from '/@/enums/appEnum'; | ||
10 | const { createMessage, createErrorModal } = useMessage(); | 10 | const { createMessage, createErrorModal } = useMessage(); |
11 | const error = createMessage.error!; | 11 | const error = createMessage.error!; |
12 | const stp = projectSetting.sessionTimeoutProcessing; | 12 | const stp = projectSetting.sessionTimeoutProcessing; |
13 | - | ||
14 | export function checkStatus( | 13 | export function checkStatus( |
15 | status: number, | 14 | status: number, |
16 | msg: string, | 15 | msg: string, |
@@ -19,7 +18,6 @@ export function checkStatus( | @@ -19,7 +18,6 @@ export function checkStatus( | ||
19 | const { t } = useI18n(); | 18 | const { t } = useI18n(); |
20 | const userStore = useUserStoreWithOut(); | 19 | const userStore = useUserStoreWithOut(); |
21 | let errMessage = ''; | 20 | let errMessage = ''; |
22 | - | ||
23 | switch (status) { | 21 | switch (status) { |
24 | case 400: | 22 | case 400: |
25 | errMessage = `${msg}`; | 23 | errMessage = `${msg}`; |
@@ -10,58 +10,17 @@ import { useGlobSetting } from '/@/hooks/setting'; | @@ -10,58 +10,17 @@ import { useGlobSetting } from '/@/hooks/setting'; | ||
10 | import { useMessage } from '/@/hooks/web/useMessage'; | 10 | import { useMessage } from '/@/hooks/web/useMessage'; |
11 | import { RequestEnum, ContentTypeEnum } from '/@/enums/httpEnum'; | 11 | import { RequestEnum, ContentTypeEnum } from '/@/enums/httpEnum'; |
12 | import { isString } from '/@/utils/is'; | 12 | import { isString } from '/@/utils/is'; |
13 | -import { getJwtToken, getAuthCache } from '/@/utils/auth'; | 13 | +import { getJwtToken } from '/@/utils/auth'; |
14 | import { setObjToUrlParams, deepMerge } from '/@/utils'; | 14 | import { setObjToUrlParams, deepMerge } from '/@/utils'; |
15 | import { useErrorLogStoreWithOut } from '/@/store/modules/errorLog'; | 15 | import { useErrorLogStoreWithOut } from '/@/store/modules/errorLog'; |
16 | import { useI18n } from '/@/hooks/web/useI18n'; | 16 | import { useI18n } from '/@/hooks/web/useI18n'; |
17 | import { joinTimestamp, formatRequestDate } from './helper'; | 17 | import { joinTimestamp, formatRequestDate } from './helper'; |
18 | import { PageEnum } from '/@/enums/pageEnum'; | 18 | import { PageEnum } from '/@/enums/pageEnum'; |
19 | -import { REFRESH_TOKEN_KEY } from '/@/enums/cacheEnum'; | ||
20 | import { router } from '/@/router'; | 19 | import { router } from '/@/router'; |
21 | 20 | ||
22 | -// import { useUserStore } from '/@/store/modules/user'; | ||
23 | -// const userStore = useUserStore(); | ||
24 | -// console.log(userStore.userInfo); | ||
25 | - | ||
26 | -// YUNTENG IOT__DEVELOPMENT__2.7.1__COMMON__LOCAL__KEY__ | ||
27 | - | ||
28 | -function timestampToTime(timestamp) { | ||
29 | - const date = new Date(timestamp); //时间戳为10位需*1000,时间戳为13位的话不需乘1000 | ||
30 | - const Y = date.getFullYear() + '-'; | ||
31 | - const M = (date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1) + '-'; | ||
32 | - const D = date.getDate() + ' '; | ||
33 | - const h = date.getHours() + ':'; | ||
34 | - const m = date.getMinutes() + ':'; | ||
35 | - const s = date.getSeconds(); | ||
36 | - return Y + M + D + h + m + s; | ||
37 | -} | ||
38 | - | ||
39 | -function convertToDate() { | ||
40 | - const date = new Date(); | ||
41 | - const y = date.getFullYear(); | ||
42 | - let m = date.getMonth() + 1; | ||
43 | - let d = date.getDate(); | ||
44 | - let h = date.getHours(); | ||
45 | - let min = date.getMinutes(); | ||
46 | - let s = date.getSeconds(); | ||
47 | - m = m < 10 ? '0' + m : m; //月小于10,加0 | ||
48 | - d = d < 10 ? '0' + d : d; //day小于10,加0 | ||
49 | - h = h < 10 ? '0' + h : h; | ||
50 | - min = min < 10 ? '0' + min : min; | ||
51 | - s = s < 10 ? '0' + s : s; | ||
52 | - return y + '-' + m + '-' + d + ' ' + h + ':' + min + ':' + s; | ||
53 | -} | ||
54 | - | ||
55 | const globSetting = useGlobSetting(); | 21 | const globSetting = useGlobSetting(); |
56 | const urlPrefix = globSetting.urlPrefix; | 22 | const urlPrefix = globSetting.urlPrefix; |
57 | const { createMessage, createErrorModal } = useMessage(); | 23 | const { createMessage, createErrorModal } = useMessage(); |
58 | -const getJwtTokenInfo = getAuthCache(REFRESH_TOKEN_KEY); | ||
59 | -const getExiper = window.localStorage.getItem( | ||
60 | - 'UNDEFINED__DEVELOPMENT__2.7.1__COMMON__LOCAL__KEY__' | ||
61 | -); | ||
62 | -const getExiperValue = JSON.parse(getExiper); | ||
63 | -const expireTime = timestampToTime(getExiperValue.expire); | ||
64 | -const nowTime = convertToDate(); | ||
65 | 24 | ||
66 | /** | 25 | /** |
67 | * @description: 数据处理,方便区分多种处理方式 | 26 | * @description: 数据处理,方便区分多种处理方式 |
@@ -162,32 +121,13 @@ const transform: AxiosTransform = { | @@ -162,32 +121,13 @@ const transform: AxiosTransform = { | ||
162 | const msg: string = response?.data?.msg ?? ''; | 121 | const msg: string = response?.data?.msg ?? ''; |
163 | const err: string = error?.toString?.() ?? ''; | 122 | const err: string = error?.toString?.() ?? ''; |
164 | let errMessage = ''; | 123 | let errMessage = ''; |
165 | - | ||
166 | try { | 124 | try { |
167 | - if (response.data.code === '401' || response.data.msg === 'tenant has expired') { | ||
168 | - if (expireTime < nowTime) { | ||
169 | - // console.log('过期'); | ||
170 | - createMessage.error('token已经过期,请退回登录'); | ||
171 | - } else { | ||
172 | - // console.log('未过期'); | ||
173 | - } | ||
174 | - if (getJwtTokenInfo) { | ||
175 | - if (PageEnum.BASE_LOGIN) { | ||
176 | - router.push(PageEnum.BASE_LOGIN); | ||
177 | - } | ||
178 | - } | ||
179 | - // router.beforeEach((to, from, next) => { | ||
180 | - // if (getJwtTokenInfo) { | ||
181 | - // if (to.path !== '/login') { | ||
182 | - // // doRefresh(); | ||
183 | - // next({ path: '/' }); | ||
184 | - // } | ||
185 | - // } | ||
186 | - // }); | ||
187 | - } else { | ||
188 | - // doRefresh(); | 125 | + console.log(response.data); |
126 | + if (response.data.status == '401' || response.data.message == '"Authentication failed"') { | ||
127 | + window.localStorage.clear(); | ||
128 | + window.sessionStorage.clear(); | ||
129 | + router.push(PageEnum.BASE_HOME); | ||
189 | } | 130 | } |
190 | - | ||
191 | if (code === 'ECONNABORTED' && message.indexOf('timeout') !== -1) { | 131 | if (code === 'ECONNABORTED' && message.indexOf('timeout') !== -1) { |
192 | errMessage = t('sys.api.apiTimeoutMessage'); | 132 | errMessage = t('sys.api.apiTimeoutMessage'); |
193 | } | 133 | } |
@@ -60,3 +60,171 @@ export const EmailRegexp = /^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*\.[a | @@ -60,3 +60,171 @@ export const EmailRegexp = /^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*\.[a | ||
60 | 60 | ||
61 | // 手机号正则 | 61 | // 手机号正则 |
62 | export const PhoneRegexp = /^[1][3,4,5,6,7,8,9][0-9]{9}$/; | 62 | export const PhoneRegexp = /^[1][3,4,5,6,7,8,9][0-9]{9}$/; |
63 | + | ||
64 | +//站内通知 | ||
65 | +export const NotificationTitleMaxLength: Rule[] = [ | ||
66 | + { | ||
67 | + required: true, | ||
68 | + validator: (_, value: string) => { | ||
69 | + if (String(value).length > 50) { | ||
70 | + return Promise.reject('标题长度不超过200字'); | ||
71 | + } | ||
72 | + return Promise.resolve(); | ||
73 | + }, | ||
74 | + validateTrigger: 'blur', | ||
75 | + }, | ||
76 | +]; | ||
77 | + | ||
78 | +export const NotificationContentMaxLength: Rule[] = [ | ||
79 | + { | ||
80 | + required: true, | ||
81 | + validator: (_, value: string) => { | ||
82 | + if (String(value).length > 50) { | ||
83 | + return Promise.reject('内容长度不超过50字'); | ||
84 | + } | ||
85 | + return Promise.resolve(); | ||
86 | + }, | ||
87 | + validateTrigger: 'blur', | ||
88 | + }, | ||
89 | +]; | ||
90 | + | ||
91 | +export const DeviceNameMaxLength: Rule[] = [ | ||
92 | + { | ||
93 | + required: true, | ||
94 | + validator: (_, value: string) => { | ||
95 | + if (String(value).length > 30) { | ||
96 | + return Promise.reject('设备名称长度不超过30字'); | ||
97 | + } | ||
98 | + return Promise.resolve(); | ||
99 | + }, | ||
100 | + validateTrigger: 'blur', | ||
101 | + }, | ||
102 | +]; | ||
103 | + | ||
104 | +export const DeviceProfileIdMaxLength: Rule[] = [ | ||
105 | + { | ||
106 | + required: true, | ||
107 | + validator: (_, value: string) => { | ||
108 | + if (String(value).length > 36) { | ||
109 | + return Promise.reject('设备配置长度不超过36字'); | ||
110 | + } | ||
111 | + return Promise.resolve(); | ||
112 | + }, | ||
113 | + validateTrigger: 'blur', | ||
114 | + }, | ||
115 | +]; | ||
116 | + | ||
117 | +export const DeviceOrgIdMaxLength: Rule[] = [ | ||
118 | + { | ||
119 | + required: true, | ||
120 | + validator: (_, value: string) => { | ||
121 | + if (String(value).length > 36) { | ||
122 | + return Promise.reject('组织长度不超过36字'); | ||
123 | + } | ||
124 | + return Promise.resolve(); | ||
125 | + }, | ||
126 | + validateTrigger: 'blur', | ||
127 | + }, | ||
128 | +]; | ||
129 | + | ||
130 | +export const DeviceLabelMaxLength: Rule[] = [ | ||
131 | + { | ||
132 | + required: true, | ||
133 | + validator: (_, value: string) => { | ||
134 | + if (String(value).length > 255) { | ||
135 | + return Promise.reject('设备标签不超过255字'); | ||
136 | + } | ||
137 | + return Promise.resolve(); | ||
138 | + }, | ||
139 | + validateTrigger: 'blur', | ||
140 | + }, | ||
141 | +]; | ||
142 | +export const DeviceDescriptionlMaxLength: Rule[] = [ | ||
143 | + { | ||
144 | + required: true, | ||
145 | + validator: (_, value: string) => { | ||
146 | + if (String(value).length > 500) { | ||
147 | + return Promise.reject('备注不超过500字'); | ||
148 | + } | ||
149 | + return Promise.resolve(); | ||
150 | + }, | ||
151 | + validateTrigger: 'blur', | ||
152 | + }, | ||
153 | +]; | ||
154 | +export const DeviceIdMaxLength: Rule[] = [ | ||
155 | + { | ||
156 | + required: true, | ||
157 | + validator: (_, value: string) => { | ||
158 | + if (String(value).length > 36) { | ||
159 | + return Promise.reject('id不超过36字'); | ||
160 | + } | ||
161 | + return Promise.resolve(); | ||
162 | + }, | ||
163 | + validateTrigger: 'blur', | ||
164 | + }, | ||
165 | +]; | ||
166 | + | ||
167 | +export const DeviceTenantIdMaxLength: Rule[] = [ | ||
168 | + { | ||
169 | + required: true, | ||
170 | + validator: (_, value: string) => { | ||
171 | + if (String(value).length > 36) { | ||
172 | + return Promise.reject('租户Code不超过36字'); | ||
173 | + } | ||
174 | + return Promise.resolve(); | ||
175 | + }, | ||
176 | + validateTrigger: 'blur', | ||
177 | + }, | ||
178 | +]; | ||
179 | + | ||
180 | +export const DeviceTbDeviceIdMaxLength: Rule[] = [ | ||
181 | + { | ||
182 | + required: true, | ||
183 | + validator: (_, value: string) => { | ||
184 | + if (String(value).length > 36) { | ||
185 | + return Promise.reject('tbDeviceId不超过36字'); | ||
186 | + } | ||
187 | + return Promise.resolve(); | ||
188 | + }, | ||
189 | + validateTrigger: 'blur', | ||
190 | + }, | ||
191 | +]; | ||
192 | + | ||
193 | +export const DeviceUserNameMaxLength: Rule[] = [ | ||
194 | + { | ||
195 | + required: true, | ||
196 | + validator: (_, value: string) => { | ||
197 | + if (String(value).length > 50) { | ||
198 | + return Promise.reject('用户名长度不超过50字'); | ||
199 | + } | ||
200 | + return Promise.resolve(); | ||
201 | + }, | ||
202 | + validateTrigger: 'blur', | ||
203 | + }, | ||
204 | +]; | ||
205 | + | ||
206 | +export const DeviceQueryUserNameMaxLength: Rule[] = [ | ||
207 | + { | ||
208 | + required: true, | ||
209 | + validator: (_, value: string) => { | ||
210 | + if (String(value).length > 50) { | ||
211 | + return Promise.reject('设备名称长度不超过50字'); | ||
212 | + } | ||
213 | + return Promise.resolve(); | ||
214 | + }, | ||
215 | + validateTrigger: 'blur', | ||
216 | + }, | ||
217 | +]; | ||
218 | + | ||
219 | +export const DeviceProfileQueryUserNameMaxLength: Rule[] = [ | ||
220 | + { | ||
221 | + required: true, | ||
222 | + validator: (_, value: string) => { | ||
223 | + if (String(value).length > 255) { | ||
224 | + return Promise.reject('配置名称长度不超过255字'); | ||
225 | + } | ||
226 | + return Promise.resolve(); | ||
227 | + }, | ||
228 | + validateTrigger: 'blur', | ||
229 | + }, | ||
230 | +]; |
@@ -33,6 +33,23 @@ export const alarmSearchSchemas: FormSchema[] = [ | @@ -33,6 +33,23 @@ export const alarmSearchSchemas: FormSchema[] = [ | ||
33 | label: '告警类型', | 33 | label: '告警类型', |
34 | component: 'Input', | 34 | component: 'Input', |
35 | colProps: { span: 6 }, | 35 | colProps: { span: 6 }, |
36 | + componentProps: { | ||
37 | + maxLength: 255, | ||
38 | + placeholder: '请输入告警类型', | ||
39 | + }, | ||
40 | + dynamicRules: () => { | ||
41 | + return [ | ||
42 | + { | ||
43 | + required: false, | ||
44 | + validator: (_, value) => { | ||
45 | + if (String(value).length > 255) { | ||
46 | + return Promise.reject('字数不超过255个字'); | ||
47 | + } | ||
48 | + return Promise.resolve(); | ||
49 | + }, | ||
50 | + }, | ||
51 | + ]; | ||
52 | + }, | ||
36 | }, | 53 | }, |
37 | { | 54 | { |
38 | field: 'endTime', | 55 | field: 'endTime', |
@@ -51,7 +51,6 @@ | @@ -51,7 +51,6 @@ | ||
51 | severity: alarmLevel(data.severity), | 51 | severity: alarmLevel(data.severity), |
52 | status: statusType(data.status), | 52 | status: statusType(data.status), |
53 | }); | 53 | }); |
54 | - console.log(data.status); | ||
55 | alarmStatus.value = data.status; | 54 | alarmStatus.value = data.status; |
56 | alarmId.value = data.id; | 55 | alarmId.value = data.id; |
57 | }); | 56 | }); |
@@ -41,6 +41,7 @@ export const formSchema: FormSchema[] = [ | @@ -41,6 +41,7 @@ export const formSchema: FormSchema[] = [ | ||
41 | label: '', | 41 | label: '', |
42 | component: 'Input', | 42 | component: 'Input', |
43 | componentProps: { | 43 | componentProps: { |
44 | + maxLength: 255, | ||
44 | placeholder: '请输入设备名称', | 45 | placeholder: '请输入设备名称', |
45 | }, | 46 | }, |
46 | }, | 47 | }, |
@@ -34,8 +34,16 @@ | @@ -34,8 +34,16 @@ | ||
34 | :canFullscreen="false" | 34 | :canFullscreen="false" |
35 | > | 35 | > |
36 | <BasicForm @register="registerForm" /> | 36 | <BasicForm @register="registerForm" /> |
37 | - <div ref="chartRef" :style="{ height: '600px', width }"></div> | 37 | + <Alert |
38 | + v-if="!isNull" | ||
39 | + message="当前时间节点暂无历史数据" | ||
40 | + description="请尝试选择其他时间段查询历史数据" | ||
41 | + type="warning" | ||
42 | + show-icon | ||
43 | + /> | ||
44 | + <div v-show="isNull" ref="chartRef" :style="{ height: '600px', width }"></div> | ||
38 | </BasicModal> | 45 | </BasicModal> |
46 | + <DeviceDetailDrawer @register="registerDetailDrawer" /> | ||
39 | </div> | 47 | </div> |
40 | </template> | 48 | </template> |
41 | <script lang="ts"> | 49 | <script lang="ts"> |
@@ -44,22 +52,30 @@ | @@ -44,22 +52,30 @@ | ||
44 | import { formSchema, columns } from './config.data'; | 52 | import { formSchema, columns } from './config.data'; |
45 | import { BasicTable, useTable } from '/@/components/Table'; | 53 | import { BasicTable, useTable } from '/@/components/Table'; |
46 | import { devicePage } from '/@/api/alarm/contact/alarmContact'; | 54 | import { devicePage } from '/@/api/alarm/contact/alarmContact'; |
47 | - import { Tag } from 'ant-design-vue'; | 55 | + import { Tag, Alert } from 'ant-design-vue'; |
48 | import { DeviceState } from '/@/api/device/model/deviceModel'; | 56 | import { DeviceState } from '/@/api/device/model/deviceModel'; |
49 | import { BAI_DU_MAP_URL } from '/@/utils/fnUtils'; | 57 | import { BAI_DU_MAP_URL } from '/@/utils/fnUtils'; |
50 | import { useModal, BasicModal } from '/@/components/Modal'; | 58 | import { useModal, BasicModal } from '/@/components/Modal'; |
51 | import { BasicForm, useForm } from '/@/components/Form'; | 59 | import { BasicForm, useForm } from '/@/components/Form'; |
52 | import { schemas } from './config.data'; | 60 | import { schemas } from './config.data'; |
53 | import { useECharts } from '/@/hooks/web/useECharts'; | 61 | import { useECharts } from '/@/hooks/web/useECharts'; |
54 | - import { getDeviceHistoryInfo, getDeviceDataKeys } from '/@/api/alarm/position'; | 62 | + import { |
63 | + getDeviceHistoryInfo, | ||
64 | + getDeviceDataKeys, | ||
65 | + getDeviceActiveTime, | ||
66 | + } from '/@/api/alarm/position'; | ||
67 | + import { useDrawer } from '/@/components/Drawer'; | ||
68 | + import DeviceDetailDrawer from '/@/views/device/manage/cpns/modal/DeviceDetailDrawer.vue'; | ||
55 | import moment from 'moment'; | 69 | import moment from 'moment'; |
56 | export default defineComponent({ | 70 | export default defineComponent({ |
57 | name: 'BaiduMap', | 71 | name: 'BaiduMap', |
58 | components: { | 72 | components: { |
59 | BasicTable, | 73 | BasicTable, |
60 | Tag, | 74 | Tag, |
75 | + Alert, | ||
61 | BasicModal, | 76 | BasicModal, |
62 | BasicForm, | 77 | BasicForm, |
78 | + DeviceDetailDrawer, | ||
63 | }, | 79 | }, |
64 | props: { | 80 | props: { |
65 | width: { | 81 | width: { |
@@ -74,7 +90,10 @@ | @@ -74,7 +90,10 @@ | ||
74 | setup() { | 90 | setup() { |
75 | const wrapRef = ref<HTMLDivElement | null>(null); | 91 | const wrapRef = ref<HTMLDivElement | null>(null); |
76 | const { toPromise } = useScript({ src: BAI_DU_MAP_URL }); | 92 | const { toPromise } = useScript({ src: BAI_DU_MAP_URL }); |
77 | - const entityId = ref(''); | 93 | + const [registerDetailDrawer, { openDrawer }] = useDrawer(); |
94 | + | ||
95 | + let entityId = ''; | ||
96 | + let globalRecord: any = {}; | ||
78 | async function initMap() { | 97 | async function initMap() { |
79 | await toPromise(); | 98 | await toPromise(); |
80 | await nextTick(); | 99 | await nextTick(); |
@@ -101,13 +120,14 @@ | @@ -101,13 +120,14 @@ | ||
101 | }, | 120 | }, |
102 | }); | 121 | }); |
103 | // 点击表格某一行触发 | 122 | // 点击表格某一行触发 |
104 | - const deviceRowClick = (record) => { | ||
105 | - entityId.value = record.tbDeviceId; | 123 | + const deviceRowClick = async (record) => { |
124 | + entityId = record.tbDeviceId; | ||
125 | + globalRecord = record; | ||
106 | const BMap = (window as any).BMap; | 126 | const BMap = (window as any).BMap; |
107 | const wrapEl = unref(wrapRef); | 127 | const wrapEl = unref(wrapRef); |
108 | const map = new BMap.Map(wrapEl); | 128 | const map = new BMap.Map(wrapEl); |
109 | if (record.deviceInfo.address) { | 129 | if (record.deviceInfo.address) { |
110 | - const { name, organizationDTO, updateTime, deviceState, deviceProfile } = record; | 130 | + const { name, organizationDTO, deviceState, deviceProfile } = record; |
111 | const { longitude, latitude, address } = record.deviceInfo; | 131 | const { longitude, latitude, address } = record.deviceInfo; |
112 | const point = new BMap.Point(longitude, latitude); | 132 | const point = new BMap.Point(longitude, latitude); |
113 | let options = { | 133 | let options = { |
@@ -117,6 +137,10 @@ | @@ -117,6 +137,10 @@ | ||
117 | map.centerAndZoom(point, 15); | 137 | map.centerAndZoom(point, 15); |
118 | map.enableScrollWheelZoom(true); | 138 | map.enableScrollWheelZoom(true); |
119 | // 创建信息窗口对象 | 139 | // 创建信息窗口对象 |
140 | + const res = await getDeviceActiveTime(entityId); | ||
141 | + | ||
142 | + let { value: activeStatus, lastUpdateTs } = res[0]; | ||
143 | + lastUpdateTs = moment(lastUpdateTs).format('YYYY-MM-DD HH:mm:ss'); | ||
120 | let infoWindow = new BMap.InfoWindow( | 144 | let infoWindow = new BMap.InfoWindow( |
121 | ` | 145 | ` |
122 | <div style="display:flex;justify-content:space-between; margin:20px 0px;"> | 146 | <div style="display:flex;justify-content:space-between; margin:20px 0px;"> |
@@ -132,10 +156,9 @@ | @@ -132,10 +156,9 @@ | ||
132 | <div>所属组织:${organizationDTO.name}</div> | 156 | <div>所属组织:${organizationDTO.name}</div> |
133 | <div style="margin-top:6px;">接入协议:${deviceProfile.transportType}</div> | 157 | <div style="margin-top:6px;">接入协议:${deviceProfile.transportType}</div> |
134 | <div style="margin-top:6px;">设备位置:${address}</div> | 158 | <div style="margin-top:6px;">设备位置:${address}</div> |
135 | - <div style="margin-top:6px;">下线时间:${updateTime}</div> | ||
136 | - <div style="display:flex;justify-content:space-between; margin-top:10px"> | ||
137 | - <button style="color:#fff;background-color:#409eff;padding:4px; border-radius:4px;">设备信息</button> | ||
138 | - <button style="color:#fff;background-color:#409eff;padding:4px; border-radius:4px;">报警记录</button> | 159 | + <div style="margin-top:6px;">${activeStatus ? '在' : '离'}线时间:${lastUpdateTs}</div> |
160 | + <div style="display:flex;justify-content:end; margin-top:10px"> | ||
161 | + <button onclick="openDeviceInfoDrawer()" style="margin-right:10px;color:#fff;background-color:#409eff;padding:4px; border-radius:4px;">设备信息</button> | ||
139 | <button onclick="openHistoryModal()" style="color:#fff;background-color:#409eff;padding:4px; border-radius:4px;">历史数据</button> | 162 | <button onclick="openHistoryModal()" style="color:#fff;background-color:#409eff;padding:4px; border-radius:4px;">历史数据</button> |
140 | </div> | 163 | </div> |
141 | `, | 164 | `, |
@@ -185,13 +208,20 @@ | @@ -185,13 +208,20 @@ | ||
185 | endTs = Date.now(); | 208 | endTs = Date.now(); |
186 | // 发送请求 | 209 | // 发送请求 |
187 | const res = await getDeviceHistoryInfo({ | 210 | const res = await getDeviceHistoryInfo({ |
188 | - entityId: entityId.value, | 211 | + entityId, |
189 | keys: keys.join(), | 212 | keys: keys.join(), |
190 | startTs, | 213 | startTs, |
191 | endTs, | 214 | endTs, |
192 | interval, | 215 | interval, |
193 | agg, | 216 | agg, |
194 | }); | 217 | }); |
218 | + // 判断对象是否为空 | ||
219 | + if (Object.keys(res).length === 0) { | ||
220 | + isNull.value = false; | ||
221 | + return; | ||
222 | + } else { | ||
223 | + isNull.value = true; | ||
224 | + } | ||
195 | // 处理数据 | 225 | // 处理数据 |
196 | for (const key in res) { | 226 | for (const key in res) { |
197 | for (const item1 of res[key]) { | 227 | for (const item1 of res[key]) { |
@@ -250,24 +280,38 @@ | @@ -250,24 +280,38 @@ | ||
250 | 280 | ||
251 | const chartRef = ref<HTMLDivElement | null>(null); | 281 | const chartRef = ref<HTMLDivElement | null>(null); |
252 | const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>); | 282 | const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>); |
253 | - | 283 | + const isNull = ref(true); |
284 | + // 设备信息 | ||
285 | + const openDeviceInfoDrawer = async () => { | ||
286 | + const { id, tbDeviceId } = globalRecord; | ||
287 | + openDrawer(true, { | ||
288 | + id, | ||
289 | + tbDeviceId, | ||
290 | + }); | ||
291 | + }; | ||
254 | const openHistoryModal = async () => { | 292 | const openHistoryModal = async () => { |
255 | openModal(true); | 293 | openModal(true); |
256 | - | ||
257 | // 收集参数 | 294 | // 收集参数 |
258 | const dataArray: any[] = []; | 295 | const dataArray: any[] = []; |
259 | const startTs = Date.now() - 86400000; //最近一天 | 296 | const startTs = Date.now() - 86400000; //最近一天 |
260 | const endTs = Date.now(); | 297 | const endTs = Date.now(); |
261 | // 发送请求 | 298 | // 发送请求 |
262 | - keys = await getDeviceDataKeys(entityId.value); | 299 | + keys = await getDeviceDataKeys(entityId); |
263 | const res = await getDeviceHistoryInfo({ | 300 | const res = await getDeviceHistoryInfo({ |
264 | - entityId: entityId.value, | 301 | + entityId, |
265 | keys: keys.join(), | 302 | keys: keys.join(), |
266 | startTs, | 303 | startTs, |
267 | endTs, | 304 | endTs, |
268 | interval: 7200000, //间隔两小时 | 305 | interval: 7200000, //间隔两小时 |
269 | agg: 'AVG', | 306 | agg: 'AVG', |
270 | }); | 307 | }); |
308 | + // 判断对象是否为空 | ||
309 | + if (Object.keys(res).length === 0) { | ||
310 | + isNull.value = false; | ||
311 | + return; | ||
312 | + } else { | ||
313 | + isNull.value = true; | ||
314 | + } | ||
271 | // 处理数据 | 315 | // 处理数据 |
272 | for (const key in res) { | 316 | for (const key in res) { |
273 | for (const item1 of res[key]) { | 317 | for (const item1 of res[key]) { |
@@ -327,12 +371,14 @@ | @@ -327,12 +371,14 @@ | ||
327 | agg: 'AVG', | 371 | agg: 'AVG', |
328 | }); | 372 | }); |
329 | }; | 373 | }; |
374 | + | ||
330 | const cancelHistoryModal = () => { | 375 | const cancelHistoryModal = () => { |
331 | resetFields(); | 376 | resetFields(); |
332 | setOptions({}); | 377 | setOptions({}); |
333 | }; | 378 | }; |
334 | onMounted(() => { | 379 | onMounted(() => { |
335 | initMap(); | 380 | initMap(); |
381 | + (window as any).openDeviceInfoDrawer = openDeviceInfoDrawer; | ||
336 | (window as any).openHistoryModal = openHistoryModal; | 382 | (window as any).openHistoryModal = openHistoryModal; |
337 | }); | 383 | }); |
338 | return { | 384 | return { |
@@ -343,7 +389,9 @@ | @@ -343,7 +389,9 @@ | ||
343 | registerModal, | 389 | registerModal, |
344 | registerForm, | 390 | registerForm, |
345 | chartRef, | 391 | chartRef, |
392 | + isNull, | ||
346 | cancelHistoryModal, | 393 | cancelHistoryModal, |
394 | + registerDetailDrawer, | ||
347 | }; | 395 | }; |
348 | }, | 396 | }, |
349 | }); | 397 | }); |
@@ -56,6 +56,7 @@ export const searchFormSchema: FormSchema[] = [ | @@ -56,6 +56,7 @@ export const searchFormSchema: FormSchema[] = [ | ||
56 | component: 'Input', | 56 | component: 'Input', |
57 | colProps: { span: 6 }, | 57 | colProps: { span: 6 }, |
58 | componentProps: { | 58 | componentProps: { |
59 | + maxLength: 36, | ||
59 | placeholder: '请输入联系人姓名', | 60 | placeholder: '请输入联系人姓名', |
60 | }, | 61 | }, |
61 | }, | 62 | }, |
@@ -70,6 +71,7 @@ export const formSchema: FormSchema[] = [ | @@ -70,6 +71,7 @@ export const formSchema: FormSchema[] = [ | ||
70 | component: 'Input', | 71 | component: 'Input', |
71 | componentProps: { | 72 | componentProps: { |
72 | placeholder: '请输入联系人姓名', | 73 | placeholder: '请输入联系人姓名', |
74 | + maxLength: 255, | ||
73 | }, | 75 | }, |
74 | }, | 76 | }, |
75 | { | 77 | { |
@@ -108,6 +110,7 @@ export const formSchema: FormSchema[] = [ | @@ -108,6 +110,7 @@ export const formSchema: FormSchema[] = [ | ||
108 | component: 'Input', | 110 | component: 'Input', |
109 | componentProps: { | 111 | componentProps: { |
110 | placeholder: '请输入微信号', | 112 | placeholder: '请输入微信号', |
113 | + maxLength: 255, | ||
111 | }, | 114 | }, |
112 | }, | 115 | }, |
113 | { | 116 | { |
@@ -115,7 +118,8 @@ export const formSchema: FormSchema[] = [ | @@ -115,7 +118,8 @@ export const formSchema: FormSchema[] = [ | ||
115 | label: '备注', | 118 | label: '备注', |
116 | component: 'InputTextArea', | 119 | component: 'InputTextArea', |
117 | componentProps: { | 120 | componentProps: { |
118 | - placeholder: '', | 121 | + placeholder: '请输入备注', |
122 | + maxLength: 255, | ||
119 | }, | 123 | }, |
120 | }, | 124 | }, |
121 | { | 125 | { |
@@ -123,5 +127,8 @@ export const formSchema: FormSchema[] = [ | @@ -123,5 +127,8 @@ export const formSchema: FormSchema[] = [ | ||
123 | label: '', | 127 | label: '', |
124 | component: 'Input', | 128 | component: 'Input', |
125 | show: false, | 129 | show: false, |
130 | + componentProps: { | ||
131 | + maxLength: 36, | ||
132 | + }, | ||
126 | }, | 133 | }, |
127 | ]; | 134 | ]; |
1 | +<template> | ||
2 | + 123 | ||
3 | + <div ref="chartRef" :style="{ height, width }"></div> | ||
4 | +</template> | ||
5 | +<script lang="ts" setup> | ||
6 | + import { ref, Ref, withDefaults } from 'vue'; | ||
7 | + import { useECharts } from '/@/hooks/web/useECharts'; | ||
8 | + | ||
9 | + interface Props { | ||
10 | + width?: string; | ||
11 | + height?: string; | ||
12 | + } | ||
13 | + withDefaults(defineProps<Props>(), { | ||
14 | + width: '100%', | ||
15 | + height: '280px', | ||
16 | + }); | ||
17 | + | ||
18 | + const chartRef = ref<HTMLDivElement | null>(null); | ||
19 | + const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>); | ||
20 | +</script> |
1 | <template> | 1 | <template> |
2 | - <div class="md:flex justify-between"> | ||
3 | - <template v-for="(item, index) in growCardList" :key="item.title"> | ||
4 | - <div | ||
5 | - class="growCardItem md:w-1/3 w-full !md:mt-0 !mt-4 bg-white" | ||
6 | - :class="index === 0 ? '!md:ml-0' : '!md:ml-4'" | 2 | + <div class="md:flex"> |
3 | + <Card size="small" class="md:w-1/3 w-full !md:mt-0 !mt-4 !md:mr-4"> | ||
4 | + <div class="flex" style="height: 100px"> | ||
5 | + <div class="mr-4" | ||
6 | + ><img src="/src/assets/images/device-count.png" style="width: 5rem; height: 5rem" | ||
7 | + /></div> | ||
8 | + <div class="flex-auto"> | ||
9 | + <div class="flex justify-between" style="align-items: center"> | ||
10 | + <div style="font-size: 1.625rem; color: #333">{{ | ||
11 | + growCardList?.deviceInfo?.sumCount | ||
12 | + }}</div> | ||
13 | + <img src="/src/assets/images/tip.png" style="width: 1.4rem; height: 1.4rem" /> | ||
14 | + </div> | ||
15 | + <div> 设备数(个) </div> | ||
16 | + <div class="flex mt-2"> | ||
17 | + <div class="flex mr-1" style="align-items: center; font-size: 0.75rem" | ||
18 | + ><img src="/src/assets/images/online.png" class="mr-1" /> | ||
19 | + <span>在线{{ growCardList?.deviceInfo?.onLine }}</span> | ||
20 | + </div> | ||
21 | + <div class="flex mr-1" style="align-items: center; font-size: 0.75rem"> | ||
22 | + <img src="/src/assets/images/offline.png" class="mr-1" /> | ||
23 | + <span> 离线{{ growCardList?.deviceInfo?.offLine }} </span> | ||
24 | + </div> | ||
25 | + <div class="flex mr-1" style="align-items: center; font-size: 0.75rem"> | ||
26 | + <img src="/src/assets/images/inactive.png" class="mr-1" /> | ||
27 | + <span> 未激活{{ growCardList?.deviceInfo?.inActive }} </span> | ||
28 | + </div> | ||
29 | + </div> | ||
30 | + </div> | ||
31 | + </div> | ||
32 | + <div class="ml-2 pt-4" style="border-top: 2px solid #f0f2f5"> | ||
33 | + 今日新增 {{ growCardList?.deviceInfo?.todayAdd }}</div | ||
34 | + > | ||
35 | + </Card> | ||
36 | + <Card size="small" class="md:w-1/3 w-full !md:mt-0 !mt-4 !md:mr-4"> | ||
37 | + <div class="flex" style="height: 100px"> | ||
38 | + <div class="mr-4"> | ||
39 | + <img | ||
40 | + v-if="!isAdmin(role)" | ||
41 | + src="/src/assets/images/alarm-count.png" | ||
42 | + style="width: 5rem; height: 5rem" | ||
43 | + /> | ||
44 | + <img v-else src="/src/assets/images/zh.png" style="width: 5rem; height: 5rem" /> | ||
45 | + </div> | ||
46 | + <div class="flex-auto"> | ||
47 | + <div class="flex justify-between" style="align-items: center"> | ||
48 | + <div v-if="!isAdmin(role)" style="font-size: 1.625rem; color: #333">{{ | ||
49 | + growCardList?.alarmInfo?.sumCount | ||
50 | + }}</div> | ||
51 | + <div style="font-size: 1.625rem; color: #333">{{ | ||
52 | + growCardList?.tenantInfo?.sumCount | ||
53 | + }}</div> | ||
54 | + <img src="/src/assets/images/tip.png" style="width: 1.4rem; height: 1.4rem" /> | ||
55 | + </div> | ||
56 | + <div> {{ !isAdmin(role) ? `${currentMonth}月告警数(条)` : '租户总量(个)' }}</div> | ||
57 | + </div> | ||
58 | + </div> | ||
59 | + <div v-if="!isAdmin(role)" class="ml-2 pt-4" style="border-top: 2px solid #f0f2f5"> | ||
60 | + 今日新增 {{ growCardList?.alarmInfo?.todayAdd }}</div | ||
61 | + > | ||
62 | + <div v-else class="ml-2 pt-4" style="border-top: 2px solid #f0f2f5"> | ||
63 | + 今日新增 {{ growCardList?.tenantInfo?.todayAdd }}</div | ||
7 | > | 64 | > |
8 | - <div | ||
9 | - class=" | ||
10 | - growCardItem-top | ||
11 | - border border-solid border-t-0 border-r-0 border-l-0 border-b-1 | ||
12 | - dark:border-#ccc | ||
13 | - light:border-#F2F2F5 | ||
14 | - " | ||
15 | - > | ||
16 | - <img :src="item.imgUrl" style="width: 5rem; height: 5rem" /> | ||
17 | - <div class="growCardItem-right"> | ||
18 | - <div class="flex justify-between ml-3"> | ||
19 | - <div style="font-size: 1.625rem; color: #333">{{ item.value }}</div> | ||
20 | - <img src="../../../../assets/images/tip.png" style="width: 1.4rem; height: 1.4rem" /> | 65 | + </Card> |
66 | + <Card size="small" class="md:w-1/3 w-full !md:mt-0 !mt-4"> | ||
67 | + <div class="flex" style="height: 100px"> | ||
68 | + <div class="mr-4" | ||
69 | + ><img | ||
70 | + v-if="!isAdmin(role)" | ||
71 | + src="/src/assets/images/msg-count.png" | ||
72 | + style="width: 5rem; height: 5rem" | ||
73 | + /><img v-else src="/src/assets/images/kf.png" style="width: 5rem; height: 5rem" /> | ||
74 | + </div> | ||
75 | + <div v-if="!isAdmin(role)" style="display: flex; align-items: center"> | ||
76 | + <div> | ||
77 | + <div class="flex" style="align-items: center"> | ||
78 | + {{ `${currentMonth}月数据点(条)` }} | ||
79 | + <span style="font-size: 1.625rem; color: #333"> | ||
80 | + {{ growCardList?.messageInfo?.dataPointsCount }}</span | ||
81 | + > | ||
21 | </div> | 82 | </div> |
22 | - <div class="ml-3">{{ item.title }}</div> | ||
23 | - <div class="ml-1.5 mt-3 flex flex-nowrap" style="width: 15rem" v-if="item.offLine"> | ||
24 | - <div class="count"> | ||
25 | - <img | ||
26 | - src="../../../../assets/images/online.png" | ||
27 | - style="width: 0.6rem; height: 0.6rem" | ||
28 | - class="mr-1" | ||
29 | - /> | ||
30 | - 在线 {{ item.onLine }} | ||
31 | - </div> | ||
32 | - <div class="count"> | ||
33 | - <img | ||
34 | - src="../../../../assets/images/offline.png" | ||
35 | - style="width: 0.6rem; height: 0.6rem" | ||
36 | - class="mr-1" | ||
37 | - /> | ||
38 | - 离线 {{ item.offLine }} | ||
39 | - </div> | ||
40 | - <div class="count"> | ||
41 | - <img | ||
42 | - src="../../../../assets/images/inactive.png" | ||
43 | - style="width: 0.6rem; height: 0.6rem" | ||
44 | - class="mr-1" | ||
45 | - /> | ||
46 | - 未激活 {{ item.inactive }} | ||
47 | - </div> | 83 | + <div class="flex" style="align-items: center"> |
84 | + {{ `${currentMonth}月消息量(条)` }} | ||
85 | + <span style="font-size: 1.625rem; color: #333"> | ||
86 | + {{ growCardList?.messageInfo?.messageCount }}</span | ||
87 | + > | ||
48 | </div> | 88 | </div> |
49 | </div> | 89 | </div> |
50 | </div> | 90 | </div> |
51 | - <div class="growCardItem-bottom"> 今日新增 {{ item.newDay }}</div> | 91 | + <div class="flex-auto" v-else> |
92 | + <div class="flex justify-between" style="align-items: center"> | ||
93 | + <div style="font-size: 1.625rem; color: #333">{{ | ||
94 | + growCardList?.customerInfo?.sumCount | ||
95 | + }}</div> | ||
96 | + <img src="/src/assets/images/tip.png" style="width: 1.4rem; height: 1.4rem" /> | ||
97 | + </div> | ||
98 | + <div>客户总量(个)</div> | ||
99 | + </div> | ||
100 | + </div> | ||
101 | + <div v-if="!isAdmin(role)" class="ml-2 pt-4" style="border-top: 2px solid #f0f2f5"> | ||
102 | + 今日新增 | ||
103 | + <span class="ml-8">数据点 ({{ growCardList?.messageInfo?.todayDataPointsAdd }})</span> | ||
104 | + <span class="ml-8">消息量 ({{ growCardList?.messageInfo?.todayMessageAdd }})</span> | ||
52 | </div> | 105 | </div> |
53 | - </template> | 106 | + <div v-else class="ml-2 pt-4" style="border-top: 2px solid #f0f2f5"> |
107 | + 今日新增 {{ growCardList?.customerInfo?.todayAdd }}</div | ||
108 | + > | ||
109 | + </Card> | ||
54 | </div> | 110 | </div> |
55 | </template> | 111 | </template> |
56 | <script lang="ts" setup> | 112 | <script lang="ts" setup> |
57 | - import { growCardList } from '../data'; | ||
58 | -</script> | ||
59 | - | ||
60 | -<style scoped lang="less"> | ||
61 | - .growCardItem { | ||
62 | - height: 11.187rem; | ||
63 | - color: #666; | ||
64 | - .growCardItem-top { | ||
65 | - display: flex; | ||
66 | - margin: 1.25rem; | ||
67 | - padding-bottom: 0.625rem; | ||
68 | - .growCardItem-right { | ||
69 | - width: 18.75rem; | ||
70 | - .count { | ||
71 | - display: flex; | ||
72 | - font-size: 0.75rem; | ||
73 | - align-items: center; | ||
74 | - margin-left: 0.5rem; | ||
75 | - } | ||
76 | - } | ||
77 | - } | ||
78 | - .growCardItem-bottom { | ||
79 | - margin-left: 1.25rem; | ||
80 | - } | 113 | + import { ref, onMounted, computed } from 'vue'; |
114 | + import { Card } from 'ant-design-vue'; | ||
115 | + import { getHomeData } from '/@/api/dashboard'; | ||
116 | + import { isAdmin } from '/@/enums/roleEnum'; | ||
117 | + defineProps<{ | ||
118 | + role: string; | ||
119 | + }>(); | ||
120 | + defineExpose({ | ||
121 | + isAdmin, | ||
122 | + }); | ||
123 | + interface CardList { | ||
124 | + deviceInfo: { | ||
125 | + sumCount: number; | ||
126 | + onLine: number; | ||
127 | + offLine: number; | ||
128 | + inActive: number; | ||
129 | + todayAdd: number; | ||
130 | + }; | ||
131 | + tenantInfo?: { sumCount: number; todayAdd: number }; | ||
132 | + customerInfo?: { sumCount: number; todayAdd: number }; | ||
133 | + alarmInfo?: { | ||
134 | + sumCount: number; | ||
135 | + todayAdd: number; | ||
136 | + }; | ||
137 | + messageInfo?: { | ||
138 | + dataPointsCount: number; | ||
139 | + messageCount: number; | ||
140 | + todayDataPointsAdd: number; | ||
141 | + todayMessageAdd: number; | ||
142 | + }; | ||
81 | } | 143 | } |
82 | -</style> | 144 | + const growCardList = ref<CardList>(); |
145 | + onMounted(async () => { | ||
146 | + const res = await getHomeData(); | ||
147 | + growCardList.value = res; | ||
148 | + }); | ||
149 | + // 获取当前月份0-11 +1 | ||
150 | + const currentMonth = computed(() => { | ||
151 | + return new Date().getMonth() + 1; | ||
152 | + }); | ||
153 | +</script> |
1 | <template> | 1 | <template> |
2 | - <Card title="帮助文档"> | ||
3 | - <div> | ||
4 | - <template v-for="item in helpDoc" :key="item.title"> | ||
5 | - <AnchorLink v-bind="item" /> | ||
6 | - </template> | ||
7 | - </div> | ||
8 | - <Card | ||
9 | - :tab-list="tabListTitle" | ||
10 | - v-bind="$attrs" | ||
11 | - :active-tab-key="activeKey" | ||
12 | - :bordered="false" | ||
13 | - @tabChange="onTabChange" | ||
14 | - :bodyStyle="{ padding: 0 }" | ||
15 | - > | ||
16 | - <div v-if="activeKey === 'tab1'"> | ||
17 | - <List item-layout="horizontal" :dataSource="dataSource"> | ||
18 | - <template #renderItem="{ item }"> | ||
19 | - <ListItem> | ||
20 | - <ListItemMeta> | ||
21 | - <template #avatar> | ||
22 | - <Avatar src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" /> | ||
23 | - </template> | ||
24 | - <template #description> | ||
25 | - <span | ||
26 | - @click="go('/stationnotification/mynotification')" | ||
27 | - class="cursor-pointer noticeTitle" | ||
28 | - >{{ item.sysNotice.title }} | ||
29 | - </span> | ||
30 | - </template> | ||
31 | - <template #title> | ||
32 | - <span>{{ item.user.realName }}</span> | 2 | + <div> |
3 | + <Card title="帮助文档" v-if="!isAdmin(role)"> | ||
4 | + <div> | ||
5 | + <template v-for="item in helpDoc" :key="item.title"> | ||
6 | + <AnchorLink v-bind="item" /> | ||
7 | + </template> | ||
8 | + </div> | ||
9 | + <Card | ||
10 | + v-if="!isAdmin(role)" | ||
11 | + :tab-list="tabListTitle" | ||
12 | + v-bind="$attrs" | ||
13 | + :active-tab-key="activeKey" | ||
14 | + :bordered="false" | ||
15 | + @tabChange="onTabChange" | ||
16 | + :bodyStyle="{ padding: 0 }" | ||
17 | + > | ||
18 | + <div v-if="activeKey === 'tab1'"> | ||
19 | + <List item-layout="horizontal" :dataSource="dataSource"> | ||
20 | + <template #renderItem="{ item }"> | ||
21 | + <ListItem> | ||
22 | + <ListItemMeta> | ||
23 | + <template #avatar> | ||
24 | + <Avatar | ||
25 | + src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" | ||
26 | + /> | ||
27 | + </template> | ||
28 | + <template #description> | ||
29 | + <span | ||
30 | + class="cursor-pointer noticeTitle" | ||
31 | + @click="go('/stationnotification/mynotification')" | ||
32 | + >{{ item.sysNotice.title }} | ||
33 | + </span> | ||
34 | + </template> | ||
35 | + <template #title> | ||
36 | + <span>{{ item.user.realName }}</span> | ||
37 | + </template> | ||
38 | + </ListItemMeta> | ||
39 | + <template #extra> | ||
40 | + <Time :value="item.sysNotice.senderDate" /> | ||
33 | </template> | 41 | </template> |
34 | - </ListItemMeta> | ||
35 | - <template #extra> | ||
36 | - <Time :value="item.sysNotice.senderDate" /> | ||
37 | - </template> | ||
38 | - </ListItem> | ||
39 | - </template> | ||
40 | - </List> | ||
41 | - <Card hoverable title="联系我们" :bordered="false"> | ||
42 | - <template #cover> | ||
43 | - <img :src="getQrCode" alt="" style="width: 150px; height: 150px; margin: 50px auto" /> | ||
44 | - </template> | ||
45 | - <CardMeta> | ||
46 | - <template #description> | ||
47 | - <p>联系人: {{ getContacts }}</p> | ||
48 | - <p>联系电话: {{ getTel }}</p> | ||
49 | - <p>联系地址: {{ getAddress }} </p> | 42 | + </ListItem> |
50 | </template> | 43 | </template> |
51 | - </CardMeta> | ||
52 | - </Card> | ||
53 | - </div> | 44 | + </List> |
45 | + <Card hoverable title="联系我们" :bordered="false"> | ||
46 | + <template #cover> | ||
47 | + <img :src="getQrCode" alt="" style="width: 150px; height: 150px; margin: 50px auto" /> | ||
48 | + </template> | ||
49 | + <CardMeta> | ||
50 | + <template #description> | ||
51 | + <p>联系人: {{ getContacts }}</p> | ||
52 | + <p>联系电话: {{ getTel }}</p> | ||
53 | + <p>联系地址: {{ getAddress }} </p> | ||
54 | + </template> | ||
55 | + </CardMeta> | ||
56 | + </Card> | ||
57 | + </div> | ||
58 | + </Card> | ||
59 | + </Card> | ||
60 | + | ||
61 | + <Card v-if="isAdmin(role)"> | ||
62 | + <Descriptions title="租户消息量TOP10" :column="1"> | ||
63 | + <template v-for="(item, index) in 10" :key="index"> | ||
64 | + <DescriptionsItem> | ||
65 | + <span | ||
66 | + class="mr-2" | ||
67 | + style=" | ||
68 | + width: 1.25rem; | ||
69 | + height: 1.25rem; | ||
70 | + border: 1px solid; | ||
71 | + color: #0b55f1; | ||
72 | + border-radius: 50%; | ||
73 | + display: flex; | ||
74 | + align-items: center; | ||
75 | + justify-content: center; | ||
76 | + " | ||
77 | + :style="{ | ||
78 | + color: | ||
79 | + index === 0 | ||
80 | + ? '#f0a16e' | ||
81 | + : index === 1 | ||
82 | + ? '#868585' | ||
83 | + : index === 2 | ||
84 | + ? '#e78739' | ||
85 | + : '#4e84f5', | ||
86 | + backgroundColor: | ||
87 | + index === 0 ? '#fed36a' : index === 1 ? '#CBCAC9' : index === 2 ? '#F1B889' : '', | ||
88 | + borderColor: | ||
89 | + index === 0 | ||
90 | + ? '#fdee7d' | ||
91 | + : index === 1 | ||
92 | + ? '#e6e6e5' | ||
93 | + : index === 2 | ||
94 | + ? '#f8c296' | ||
95 | + : '#0b55f1;', | ||
96 | + }" | ||
97 | + >{{ index + 1 }}</span | ||
98 | + >兰州天兆猪业</DescriptionsItem | ||
99 | + > | ||
100 | + </template> | ||
101 | + </Descriptions> | ||
102 | + </Card> | ||
103 | + <Card v-if="isAdmin(role)"> | ||
104 | + <BasicTable @register="registerTable" /> | ||
54 | </Card> | 105 | </Card> |
55 | - </Card> | 106 | + </div> |
56 | </template> | 107 | </template> |
57 | 108 | ||
58 | <script lang="ts"> | 109 | <script lang="ts"> |
59 | import { defineComponent, ref, computed, onMounted } from 'vue'; | 110 | import { defineComponent, ref, computed, onMounted } from 'vue'; |
60 | - import { Card, AnchorLink, List, ListItem, ListItemMeta, Avatar, CardMeta } from 'ant-design-vue'; | 111 | + import { Card, Anchor, List, Avatar, Descriptions } from 'ant-design-vue'; |
61 | import { useUserStore } from '/@/store/modules/user'; | 112 | import { useUserStore } from '/@/store/modules/user'; |
62 | import { getEnterPriseDetail } from '/@/api/oem'; | 113 | import { getEnterPriseDetail } from '/@/api/oem'; |
63 | import { notifyMyGetrPageApi } from '/@/api/stationnotification/stationnotifyApi'; | 114 | import { notifyMyGetrPageApi } from '/@/api/stationnotification/stationnotifyApi'; |
64 | import { Time } from '/@/components/Time'; | 115 | import { Time } from '/@/components/Time'; |
65 | import { useGo } from '/@/hooks/web/usePage'; | 116 | import { useGo } from '/@/hooks/web/usePage'; |
117 | + import { BasicTable, useTable } from '/@/components/Table'; | ||
118 | + import { columns } from './props'; | ||
119 | + import { isAdmin } from '/@/enums/roleEnum'; | ||
120 | + import { getTenantExpireTimeList } from '/@/api/dashboard'; | ||
66 | export default defineComponent({ | 121 | export default defineComponent({ |
67 | components: { | 122 | components: { |
68 | Card, | 123 | Card, |
69 | - AnchorLink, | 124 | + CardMeta: Card.Meta, |
125 | + AnchorLink: Anchor.Link, | ||
70 | List, | 126 | List, |
71 | - ListItem, | ||
72 | - ListItemMeta, | 127 | + ListItem: List.Item, |
128 | + ListItemMeta: List.Item.Meta, | ||
129 | + Descriptions, | ||
130 | + DescriptionsItem: Descriptions.Item, | ||
73 | Avatar, | 131 | Avatar, |
74 | Time, | 132 | Time, |
75 | - CardMeta, | 133 | + BasicTable, |
76 | }, | 134 | }, |
77 | - setup() { | ||
78 | - onMounted(async () => { | ||
79 | - const res = await getEnterPriseDetail(); | ||
80 | - userStore.setEnterPriseInfo(res); | ||
81 | - }); | 135 | + props: { |
136 | + role: { | ||
137 | + type: String, | ||
138 | + required: true, | ||
139 | + }, | ||
140 | + }, | ||
141 | + setup(props) { | ||
142 | + // 通知数据 | ||
143 | + const dataSource = ref([]); | ||
144 | + const go = useGo(); | ||
145 | + | ||
82 | const helpDoc = ref([ | 146 | const helpDoc = ref([ |
83 | { | 147 | { |
84 | title: '如何接入设备?', | 148 | title: '如何接入设备?', |
@@ -109,6 +173,18 @@ | @@ -109,6 +173,18 @@ | ||
109 | activeKey.value = key; | 173 | activeKey.value = key; |
110 | }; | 174 | }; |
111 | 175 | ||
176 | + const [registerTable, { redoHeight }] = useTable({ | ||
177 | + api: getTenantExpireTimeList, | ||
178 | + title: '本月即将过期租户', | ||
179 | + showIndexColumn: false, | ||
180 | + useSearchForm: false, | ||
181 | + columns, | ||
182 | + fetchSetting: { | ||
183 | + listField: 'expireTenant.items', | ||
184 | + totalField: 'expireTenant.total', | ||
185 | + }, | ||
186 | + }); | ||
187 | + | ||
112 | const userStore = useUserStore(); | 188 | const userStore = useUserStore(); |
113 | const getContacts = computed(() => { | 189 | const getContacts = computed(() => { |
114 | return userStore.enterPriseInfo?.contacts; | 190 | return userStore.enterPriseInfo?.contacts; |
@@ -122,32 +198,35 @@ | @@ -122,32 +198,35 @@ | ||
122 | const getQrCode = computed(() => { | 198 | const getQrCode = computed(() => { |
123 | return userStore.enterPriseInfo?.qrCode; | 199 | return userStore.enterPriseInfo?.qrCode; |
124 | }); | 200 | }); |
125 | - | ||
126 | - // 通知数据 | ||
127 | - const dataSource = ref([]); | ||
128 | - const go = useGo(); | ||
129 | onMounted(async () => { | 201 | onMounted(async () => { |
130 | - const res = await notifyMyGetrPageApi({ page: 1, pageSize: 5 }); | ||
131 | - dataSource.value = res.items; | 202 | + if (isAdmin(props.role)) return; |
203 | + | ||
204 | + const res = await getEnterPriseDetail(); | ||
205 | + const notice = await notifyMyGetrPageApi({ page: 1, pageSize: 5 }); | ||
206 | + userStore.setEnterPriseInfo(res); | ||
207 | + dataSource.value = notice.items; | ||
132 | }); | 208 | }); |
133 | 209 | ||
134 | return { | 210 | return { |
135 | activeKey, | 211 | activeKey, |
136 | tabListTitle, | 212 | tabListTitle, |
137 | - onTabChange, | ||
138 | helpDoc, | 213 | helpDoc, |
139 | getQrCode, | 214 | getQrCode, |
140 | getContacts, | 215 | getContacts, |
141 | getAddress, | 216 | getAddress, |
142 | getTel, | 217 | getTel, |
143 | dataSource, | 218 | dataSource, |
219 | + onTabChange, | ||
144 | go, | 220 | go, |
221 | + registerTable, | ||
222 | + isAdmin, | ||
223 | + redoHeight, | ||
145 | }; | 224 | }; |
146 | }, | 225 | }, |
147 | }); | 226 | }); |
148 | </script> | 227 | </script> |
149 | 228 | ||
150 | -<style lang="less" scoped> | 229 | +<style scoped> |
151 | .noticeTitle:hover { | 230 | .noticeTitle:hover { |
152 | border-bottom: 1px solid #ccc; | 231 | border-bottom: 1px solid #ccc; |
153 | } | 232 | } |
@@ -4,59 +4,347 @@ | @@ -4,59 +4,347 @@ | ||
4 | v-bind="$attrs" | 4 | v-bind="$attrs" |
5 | :active-tab-key="activeKey" | 5 | :active-tab-key="activeKey" |
6 | @tabChange="onTabChange" | 6 | @tabChange="onTabChange" |
7 | + v-if="!isAdmin(role)" | ||
7 | > | 8 | > |
8 | <template #tabBarExtraContent> | 9 | <template #tabBarExtraContent> |
9 | <div class="extra-date"> | 10 | <div class="extra-date"> |
10 | - <template v-for="(item, index) in dateList" :key="item"> | ||
11 | - <span @click="changeDate(index)" :class="{ active: index === activeIndex }">{{ | ||
12 | - item | ||
13 | - }}</span> | 11 | + <template v-for="(item, index) in dateList" :key="item.value"> |
12 | + <span | ||
13 | + @click="quickQueryDate(index, item.value)" | ||
14 | + :class="{ active: index === activeIndex }" | ||
15 | + >{{ item.label }}</span | ||
16 | + > | ||
14 | </template> | 17 | </template> |
15 | - <DatePicker @change="onDateChange" /> | 18 | + <DatePicker @change="onDateChange" v-model:value="dateValue" /> |
16 | </div> | 19 | </div> |
17 | </template> | 20 | </template> |
18 | - <div v-if="activeKey === 'tab1'"> | ||
19 | - <p class="center">告警数</p> | ||
20 | - <VisitAnalysis /> | 21 | + <div v-show="activeKey === '1'"> |
22 | + <!-- 折线图 --> | ||
23 | + <VisitAnalysis :alarmList="state.alarmList" /> | ||
21 | </div> | 24 | </div> |
22 | - <div v-else> | ||
23 | - <p class="center">消息数</p> | ||
24 | - <VisitAnalysisBar /> | 25 | + <div v-show="activeKey === '2'"> |
26 | + <!-- 柱形图 --> | ||
27 | + <VisitAnalysisBar :dataPointList="state.dataPointList" :messageList="state.messageList" /> | ||
25 | </div> | 28 | </div> |
26 | </Card> | 29 | </Card> |
30 | + <Card v-bind="$attrs" v-if="isAdmin(role)" title="租户趋势"> | ||
31 | + <TenantTrend /> | ||
32 | + </Card> | ||
33 | + <Card v-bind="$attrs" v-if="isAdmin(role)" title="客户趋势"> | ||
34 | + <CustomerTrend /> | ||
35 | + </Card> | ||
27 | </template> | 36 | </template> |
28 | <script lang="ts" setup> | 37 | <script lang="ts" setup> |
29 | - import { ref } from 'vue'; | 38 | + import { ref, reactive } from 'vue'; |
30 | import { Card, DatePicker } from 'ant-design-vue'; | 39 | import { Card, DatePicker } from 'ant-design-vue'; |
31 | import VisitAnalysis from './VisitAnalysis.vue'; | 40 | import VisitAnalysis from './VisitAnalysis.vue'; |
32 | import VisitAnalysisBar from './VisitAnalysisBar.vue'; | 41 | import VisitAnalysisBar from './VisitAnalysisBar.vue'; |
33 | - | ||
34 | - const activeKey = ref('tab1'); | ||
35 | - | 42 | + import { isAdmin } from '/@/enums/roleEnum'; |
43 | + import { useWebSocket } from '@vueuse/core'; | ||
44 | + import { getAuthCache } from '/@/utils/auth'; | ||
45 | + import CustomerTrend from './CustomerTrend.vue'; | ||
46 | + import TenantTrend from './TenantTrend.vue'; | ||
47 | + import { JWT_TOKEN_KEY } from '/@/enums/cacheEnum'; | ||
48 | + import { formatToDateTime } from '/@/utils/dateUtil'; | ||
49 | + import { getEntitiesId } from '/@/api/dashboard/index'; | ||
50 | + defineExpose({ | ||
51 | + isAdmin, | ||
52 | + }); | ||
53 | + const props = defineProps<{ | ||
54 | + role: string; | ||
55 | + }>(); | ||
56 | + const activeKey = ref('1'); | ||
57 | + let entityId = null; | ||
58 | + // 图表tab切换选项卡 | ||
36 | const tabListTitle = [ | 59 | const tabListTitle = [ |
37 | { | 60 | { |
38 | - key: 'tab1', | 61 | + key: '1', |
39 | tab: '告警数统计', | 62 | tab: '告警数统计', |
40 | }, | 63 | }, |
41 | { | 64 | { |
42 | - key: 'tab2', | 65 | + key: '2', |
43 | tab: '消息量统计', | 66 | tab: '消息量统计', |
44 | }, | 67 | }, |
45 | ]; | 68 | ]; |
46 | - const dateList = ref(['1小时', '1天', '7天', '30天']); | ||
47 | - const activeIndex = ref(0); | ||
48 | - function onTabChange(key) { | 69 | + // 快速选择日期 |
70 | + const activeIndex = ref(3); | ||
71 | + const dateValue = ref(); | ||
72 | + const dateList = ref([ | ||
73 | + { label: '1小时', value: 3600000 }, | ||
74 | + { label: '1天', value: 86400000 }, | ||
75 | + { label: '7天', value: 604800000 }, | ||
76 | + { label: '30天', value: 2592000000 }, | ||
77 | + ]); | ||
78 | + // web Socket | ||
79 | + const token: string = getAuthCache(JWT_TOKEN_KEY); | ||
80 | + const state = reactive({ | ||
81 | + server: `${import.meta.env.VITE_WEB_SOCKET}${token}`, | ||
82 | + alarmList: new Array<[number, string]>(), | ||
83 | + alarmItem: new Array<[number, string]>(), | ||
84 | + dataPointList: new Array<[number, string]>(), | ||
85 | + messageList: new Array<[number, string]>(), | ||
86 | + dataPoint: new Array<[number, string]>(), | ||
87 | + MsgCount: new Array<[number, string]>(), | ||
88 | + }); | ||
89 | + const { send, close } = useWebSocket(state.server, { | ||
90 | + async onConnected() { | ||
91 | + if (isAdmin(props.role)) return; | ||
92 | + const res = await getEntitiesId(); | ||
93 | + entityId = res.data[0].entityId; | ||
94 | + const sendValue = JSON.stringify({ | ||
95 | + entityDataCmds: [ | ||
96 | + { | ||
97 | + query: { | ||
98 | + entityFilter: { | ||
99 | + type: 'singleEntity', | ||
100 | + singleEntity: entityId, | ||
101 | + }, | ||
102 | + pageLink: { | ||
103 | + pageSize: 1024, | ||
104 | + page: 0, | ||
105 | + sortOrder: { | ||
106 | + key: { | ||
107 | + type: 'ENTITY_FIELD', | ||
108 | + key: 'createdTime', | ||
109 | + }, | ||
110 | + direction: 'DESC', | ||
111 | + }, | ||
112 | + }, | ||
113 | + entityFields: [ | ||
114 | + { | ||
115 | + type: 'ENTITY_FIELD', | ||
116 | + key: 'name', | ||
117 | + }, | ||
118 | + { | ||
119 | + type: 'ENTITY_FIELD', | ||
120 | + key: 'label', | ||
121 | + }, | ||
122 | + { | ||
123 | + type: 'ENTITY_FIELD', | ||
124 | + key: 'additionalInfo', | ||
125 | + }, | ||
126 | + ], | ||
127 | + latestValues: [ | ||
128 | + { | ||
129 | + type: 'TIME_SERIES', | ||
130 | + key: 'createdAlarmsCountHourly', | ||
131 | + }, | ||
132 | + ], | ||
133 | + }, | ||
134 | + cmdId: activeKey.value, | ||
135 | + }, | ||
136 | + ], | ||
137 | + }); | ||
138 | + const sendValue1 = JSON.stringify({ | ||
139 | + entityDataCmds: [ | ||
140 | + { | ||
141 | + cmdId: activeKey.value, | ||
142 | + historyCmd: { | ||
143 | + keys: ['createdAlarmsCountHourly'], | ||
144 | + startTs: Date.now() - 2592000000, | ||
145 | + endTs: Date.now(), | ||
146 | + interval: 86400000, | ||
147 | + agg: 'COUNT', | ||
148 | + }, | ||
149 | + }, | ||
150 | + ], | ||
151 | + }); | ||
152 | + send(sendValue); | ||
153 | + send(sendValue1); | ||
154 | + console.log('建立连接了'); | ||
155 | + }, | ||
156 | + onMessage(_, e) { | ||
157 | + const { data, update } = JSON.parse(e.data); | ||
158 | + console.log('来新消息了', data, update); | ||
159 | + if (activeKey.value === '1') { | ||
160 | + if (data) { | ||
161 | + const { createdAlarmsCountHourly } = data.data[0].latest.TIME_SERIES; | ||
162 | + state.alarmItem = [createdAlarmsCountHourly.ts, createdAlarmsCountHourly.value]; | ||
163 | + state.alarmList.push([createdAlarmsCountHourly.ts, createdAlarmsCountHourly.value]); | ||
164 | + } | ||
165 | + if (update) { | ||
166 | + const { createdAlarmsCountHourly } = update[0].timeseries; | ||
167 | + const newArray: any = []; | ||
168 | + for (const item of createdAlarmsCountHourly) { | ||
169 | + newArray.push([item.ts, item.value]); | ||
170 | + } | ||
171 | + state.alarmList = newArray; | ||
172 | + } | ||
173 | + } else { | ||
174 | + if (data) { | ||
175 | + const { transportDataPointsCountHourly, transportMsgCountHourly } = | ||
176 | + data.data[0].latest.TIME_SERIES; | ||
177 | + state.dataPoint = [ | ||
178 | + transportDataPointsCountHourly.ts, | ||
179 | + transportDataPointsCountHourly.value, | ||
180 | + ]; | ||
181 | + state.MsgCount = [ | ||
182 | + transportDataPointsCountHourly.ts, | ||
183 | + transportDataPointsCountHourly.value, | ||
184 | + ]; | ||
185 | + state.dataPointList.push([ | ||
186 | + transportDataPointsCountHourly.ts, | ||
187 | + transportDataPointsCountHourly.value, | ||
188 | + ]); | ||
189 | + state.messageList.push([transportMsgCountHourly.ts, transportMsgCountHourly.value]); | ||
190 | + } | ||
191 | + if (update) { | ||
192 | + const { transportDataPointsCountHourly, transportMsgCountHourly } = update[0].timeseries; | ||
193 | + const newArray: any[] = []; | ||
194 | + const newArray1: any[] = []; | ||
195 | + for (const item of transportDataPointsCountHourly) { | ||
196 | + newArray.push([item.ts, item.value]); | ||
197 | + } | ||
198 | + for (const item of transportMsgCountHourly) { | ||
199 | + newArray1.push([item.ts, item.value]); | ||
200 | + } | ||
201 | + state.dataPointList = newArray; | ||
202 | + state.messageList = newArray1; | ||
203 | + } | ||
204 | + } | ||
205 | + }, | ||
206 | + onDisconnected() { | ||
207 | + console.log('断开连接了'); | ||
208 | + close(); | ||
209 | + }, | ||
210 | + }); | ||
211 | + | ||
212 | + // 切换tab页 | ||
213 | + function onTabChange(key: string) { | ||
49 | activeKey.value = key; | 214 | activeKey.value = key; |
215 | + activeIndex.value = 3; | ||
216 | + dateValue.value = ''; | ||
217 | + const sendValue = JSON.stringify({ | ||
218 | + entityDataCmds: [ | ||
219 | + { | ||
220 | + cmdId: activeKey.value, | ||
221 | + historyCmd: { | ||
222 | + keys: | ||
223 | + activeKey.value === '1' | ||
224 | + ? ['createdAlarmsCountHourly'] | ||
225 | + : ['transportMsgCountHourly', 'transportDataPointsCountHourly'], | ||
226 | + startTs: Date.now() - 2592000000, | ||
227 | + endTs: Date.now(), | ||
228 | + interval: 86400000, | ||
229 | + agg: 'COUNT', | ||
230 | + }, | ||
231 | + }, | ||
232 | + ], | ||
233 | + }); | ||
234 | + if (key === '2') { | ||
235 | + const sendMessageValue = JSON.stringify({ | ||
236 | + entityDataCmds: [ | ||
237 | + { | ||
238 | + query: { | ||
239 | + entityFilter: { | ||
240 | + type: 'singleEntity', | ||
241 | + singleEntity: entityId, | ||
242 | + }, | ||
243 | + pageLink: { | ||
244 | + pageSize: 1024, | ||
245 | + page: 0, | ||
246 | + sortOrder: { | ||
247 | + key: { | ||
248 | + type: 'ENTITY_FIELD', | ||
249 | + key: 'createdTime', | ||
250 | + }, | ||
251 | + direction: 'DESC', | ||
252 | + }, | ||
253 | + }, | ||
254 | + entityFields: [ | ||
255 | + { | ||
256 | + type: 'ENTITY_FIELD', | ||
257 | + key: 'name', | ||
258 | + }, | ||
259 | + { | ||
260 | + type: 'ENTITY_FIELD', | ||
261 | + key: 'label', | ||
262 | + }, | ||
263 | + { | ||
264 | + type: 'ENTITY_FIELD', | ||
265 | + key: 'additionalInfo', | ||
266 | + }, | ||
267 | + ], | ||
268 | + latestValues: [ | ||
269 | + { | ||
270 | + type: 'TIME_SERIES', | ||
271 | + key: 'transportMsgCountHourly', | ||
272 | + }, | ||
273 | + { | ||
274 | + type: 'TIME_SERIES', | ||
275 | + key: 'transportDataPointsCountHourly', | ||
276 | + }, | ||
277 | + ], | ||
278 | + }, | ||
279 | + cmdId: activeKey.value, | ||
280 | + }, | ||
281 | + ], | ||
282 | + }); | ||
283 | + send(sendMessageValue); | ||
284 | + } | ||
285 | + send(sendValue); | ||
50 | } | 286 | } |
51 | - function onDateChange(date, dateString) { | ||
52 | - console.log(date, dateString); | 287 | + // 选择日期 |
288 | + function onDateChange(_, dateString) { | ||
289 | + activeIndex.value = -1; | ||
290 | + const dateTime = Number(formatToDateTime(dateString, 'x')); | ||
291 | + // 动态发送ws数据 | ||
292 | + const sendValue = JSON.stringify({ | ||
293 | + entityDataCmds: [ | ||
294 | + { | ||
295 | + cmdId: activeKey.value, | ||
296 | + historyCmd: { | ||
297 | + keys: | ||
298 | + activeKey.value === '1' | ||
299 | + ? ['createdAlarmsCountHourly'] | ||
300 | + : ['transportMsgCountHourly', 'transportDataPointsCountHourly'], | ||
301 | + startTs: dateTime, | ||
302 | + endTs: dateTime + 86400000, | ||
303 | + interval: 7200000, | ||
304 | + limit: 12, | ||
305 | + agg: 'COUNT', | ||
306 | + }, | ||
307 | + }, | ||
308 | + ], | ||
309 | + }); | ||
310 | + send(sendValue); | ||
53 | } | 311 | } |
54 | - function changeDate(index: number) { | 312 | + // 快速选择时间 |
313 | + function quickQueryDate(index: number, value: number) { | ||
314 | + if (activeIndex.value === index) return; | ||
55 | activeIndex.value = index; | 315 | activeIndex.value = index; |
316 | + dateValue.value = ''; | ||
317 | + let interval = 300000; | ||
318 | + if (value === 86400000) { | ||
319 | + interval = 7200000; | ||
320 | + } else if (value === 604800000 || value === 2592000000) { | ||
321 | + interval = 86400000; | ||
322 | + } | ||
323 | + // 动态发送ws数据 | ||
324 | + const sendValue = JSON.stringify({ | ||
325 | + entityDataCmds: [ | ||
326 | + { | ||
327 | + cmdId: activeKey.value, | ||
328 | + historyCmd: { | ||
329 | + keys: | ||
330 | + activeKey.value === '1' | ||
331 | + ? ['createdAlarmsCountHourly'] | ||
332 | + : ['transportMsgCountHourly', 'transportDataPointsCountHourly'], | ||
333 | + startTs: Date.now() - value, | ||
334 | + endTs: Date.now(), | ||
335 | + interval, | ||
336 | + agg: 'COUNT', | ||
337 | + }, | ||
338 | + }, | ||
339 | + ], | ||
340 | + }); | ||
341 | + send(sendValue); | ||
342 | + | ||
343 | + console.log(JSON.parse(sendValue), '----interval', state.alarmList); | ||
56 | } | 344 | } |
57 | </script> | 345 | </script> |
58 | 346 | ||
59 | -<style scoped lang="less"> | 347 | +<style lang="less"> |
60 | .center { | 348 | .center { |
61 | display: flex; | 349 | display: flex; |
62 | justify-content: center; | 350 | justify-content: center; |
1 | +<template> | ||
2 | + 123 | ||
3 | + <div ref="chartRef" :style="{ height, width }"></div> | ||
4 | +</template> | ||
5 | +<script lang="ts" setup> | ||
6 | + import { ref, Ref, withDefaults } from 'vue'; | ||
7 | + import { useECharts } from '/@/hooks/web/useECharts'; | ||
8 | + | ||
9 | + interface Props { | ||
10 | + width?: string; | ||
11 | + height?: string; | ||
12 | + } | ||
13 | + withDefaults(defineProps<Props>(), { | ||
14 | + width: '100%', | ||
15 | + height: '280px', | ||
16 | + }); | ||
17 | + | ||
18 | + const chartRef = ref<HTMLDivElement | null>(null); | ||
19 | + const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>); | ||
20 | +</script> |
1 | <template> | 1 | <template> |
2 | - <div ref="chartRef" :style="{ height, width }"></div> | 2 | + <div> |
3 | + <p class="center">告警数</p> | ||
4 | + <div ref="chartRef" :style="{ height, width }" v-show="alarmList.length"></div> | ||
5 | + <div v-show="!alarmList.length">暂无数据</div> | ||
6 | + </div> | ||
3 | </template> | 7 | </template> |
4 | <script lang="ts" setup> | 8 | <script lang="ts" setup> |
5 | - import { onMounted, ref, Ref } from 'vue'; | 9 | + import { onMounted, ref, Ref, withDefaults, watch } from 'vue'; |
6 | import { useECharts } from '/@/hooks/web/useECharts'; | 10 | import { useECharts } from '/@/hooks/web/useECharts'; |
7 | - import { basicProps } from './props'; | ||
8 | 11 | ||
9 | - defineProps({ | ||
10 | - ...basicProps, | 12 | + interface Props { |
13 | + width?: string; | ||
14 | + height?: string; | ||
15 | + alarmList: [number, string][]; | ||
16 | + } | ||
17 | + const props = withDefaults(defineProps<Props>(), { | ||
18 | + width: '100%', | ||
19 | + height: '280px', | ||
20 | + alarmList: () => [], | ||
11 | }); | 21 | }); |
22 | + | ||
12 | const chartRef = ref<HTMLDivElement | null>(null); | 23 | const chartRef = ref<HTMLDivElement | null>(null); |
13 | const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>); | 24 | const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>); |
14 | 25 | ||
@@ -16,79 +27,60 @@ | @@ -16,79 +27,60 @@ | ||
16 | setOptions({ | 27 | setOptions({ |
17 | tooltip: { | 28 | tooltip: { |
18 | trigger: 'axis', | 29 | trigger: 'axis', |
19 | - axisPointer: { | ||
20 | - lineStyle: { | ||
21 | - width: 1, | ||
22 | - color: '#019680', | ||
23 | - }, | ||
24 | - }, | ||
25 | }, | 30 | }, |
31 | + grid: { | ||
32 | + left: '3%', | ||
33 | + right: '4%', | ||
34 | + bottom: '3%', | ||
35 | + containLabel: true, | ||
36 | + }, | ||
37 | + | ||
26 | xAxis: { | 38 | xAxis: { |
27 | - type: 'category', | ||
28 | - boundaryGap: false, | ||
29 | - data: [ | ||
30 | - '6:00', | ||
31 | - '7:00', | ||
32 | - '8:00', | ||
33 | - '9:00', | ||
34 | - '10:00', | ||
35 | - '11:00', | ||
36 | - '12:00', | ||
37 | - '13:00', | ||
38 | - '14:00', | ||
39 | - '15:00', | ||
40 | - '16:00', | ||
41 | - '17:00', | ||
42 | - '18:00', | ||
43 | - '19:00', | ||
44 | - '20:00', | ||
45 | - '21:00', | ||
46 | - '22:00', | ||
47 | - '23:00', | ||
48 | - ], | ||
49 | - splitLine: { | ||
50 | - show: true, | ||
51 | - lineStyle: { | ||
52 | - width: 1, | ||
53 | - type: 'solid', | ||
54 | - color: 'rgba(226,226,226,0.5)', | ||
55 | - }, | ||
56 | - }, | ||
57 | - axisTick: { | ||
58 | - show: false, | ||
59 | - }, | 39 | + type: 'time', |
40 | + }, | ||
41 | + yAxis: { | ||
42 | + type: 'value', | ||
60 | }, | 43 | }, |
61 | - yAxis: [ | ||
62 | - { | ||
63 | - type: 'value', | ||
64 | - max: 80000, | ||
65 | - splitNumber: 4, | ||
66 | - axisTick: { | ||
67 | - show: false, | ||
68 | - }, | ||
69 | - splitArea: { | ||
70 | - show: true, | ||
71 | - areaStyle: { | ||
72 | - color: ['rgba(255,255,255,0.2)', 'rgba(226,226,226,0.2)'], | ||
73 | - }, | ||
74 | - }, | ||
75 | - }, | ||
76 | - ], | ||
77 | - grid: { left: '1%', right: '1%', top: '2 %', bottom: 0, containLabel: true }, | ||
78 | series: [ | 44 | series: [ |
79 | { | 45 | { |
80 | - smooth: true, | ||
81 | - data: [ | ||
82 | - 111, 222, 4000, 18000, 33333, 55555, 66666, 33333, 14000, 36000, 66666, 44444, 22222, | ||
83 | - 11111, 4000, 2000, 500, 333, 222, 111, | ||
84 | - ], | ||
85 | - type: 'line', | ||
86 | - areaStyle: {}, | ||
87 | - itemStyle: { | ||
88 | - color: '#5ab1ef', | ||
89 | - }, | 46 | + name: '告警数', |
47 | + type: 'bar', | ||
48 | + stack: 'Total', | ||
49 | + data: props.alarmList, | ||
90 | }, | 50 | }, |
91 | ], | 51 | ], |
92 | }); | 52 | }); |
93 | }); | 53 | }); |
54 | + watch( | ||
55 | + () => props.alarmList, | ||
56 | + (newValue) => { | ||
57 | + console.log(newValue); | ||
58 | + setOptions({ | ||
59 | + tooltip: { | ||
60 | + trigger: 'axis', | ||
61 | + }, | ||
62 | + grid: { | ||
63 | + left: '3%', | ||
64 | + right: '4%', | ||
65 | + bottom: '3%', | ||
66 | + containLabel: true, | ||
67 | + }, | ||
68 | + | ||
69 | + xAxis: { | ||
70 | + type: 'time', | ||
71 | + }, | ||
72 | + yAxis: { | ||
73 | + type: 'value', | ||
74 | + }, | ||
75 | + series: [ | ||
76 | + { | ||
77 | + name: '告警数', | ||
78 | + type: 'bar', | ||
79 | + stack: 'Total', | ||
80 | + data: newValue, | ||
81 | + }, | ||
82 | + ], | ||
83 | + }); | ||
84 | + } | ||
85 | + ); | ||
94 | </script> | 86 | </script> |
1 | <template> | 1 | <template> |
2 | - <div ref="chartRef" :style="{ height, width }"></div> | 2 | + <div> |
3 | + <p class="center">消息量</p> | ||
4 | + <div ref="chartRef" :style="{ height, width }" v-show="dataPointList.length"></div> | ||
5 | + <div v-show="!dataPointList.length">暂无数据</div> | ||
6 | + </div> | ||
3 | </template> | 7 | </template> |
4 | <script lang="ts" setup> | 8 | <script lang="ts" setup> |
5 | - import { onMounted, ref, Ref } from 'vue'; | 9 | + import { ref, Ref, watch, withDefaults } from 'vue'; |
6 | import { useECharts } from '/@/hooks/web/useECharts'; | 10 | import { useECharts } from '/@/hooks/web/useECharts'; |
7 | - import { basicProps } from './props'; | ||
8 | - | ||
9 | - defineProps({ | ||
10 | - ...basicProps, | 11 | + type DataItem = [number, string]; |
12 | + interface Props { | ||
13 | + width?: string; | ||
14 | + height?: string; | ||
15 | + dataPointList: DataItem[]; | ||
16 | + messageList: DataItem[]; | ||
17 | + } | ||
18 | + const props = withDefaults(defineProps<Props>(), { | ||
19 | + width: '100%', | ||
20 | + height: '280px', | ||
21 | + dataPointList: () => [], | ||
22 | + messageList: () => [], | ||
11 | }); | 23 | }); |
12 | - | ||
13 | const chartRef = ref<HTMLDivElement | null>(null); | 24 | const chartRef = ref<HTMLDivElement | null>(null); |
14 | const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>); | 25 | const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>); |
15 | - onMounted(() => { | ||
16 | - setOptions({ | ||
17 | - tooltip: { | ||
18 | - trigger: 'axis', | ||
19 | - axisPointer: { | ||
20 | - lineStyle: { | ||
21 | - width: 1, | ||
22 | - color: '#019680', | 26 | + watch( |
27 | + () => [props.dataPointList, props.messageList], | ||
28 | + ([newValue, newValue1]) => { | ||
29 | + // 计算总量 | ||
30 | + let dataPointTotal = 0; | ||
31 | + let messageTotal = 0; | ||
32 | + for (const item of newValue) { | ||
33 | + dataPointTotal += Number(item[1]); | ||
34 | + } | ||
35 | + for (const item of newValue1) { | ||
36 | + messageTotal += Number(item[1]); | ||
37 | + } | ||
38 | + setOptions({ | ||
39 | + tooltip: { | ||
40 | + trigger: 'axis', | ||
41 | + axisPointer: { | ||
42 | + type: 'shadow', | ||
23 | }, | 43 | }, |
24 | }, | 44 | }, |
25 | - }, | ||
26 | - grid: { left: '1%', right: '1%', top: '2 %', bottom: 0, containLabel: true }, | ||
27 | - xAxis: { | ||
28 | - type: 'category', | ||
29 | - data: [ | ||
30 | - '1月', | ||
31 | - '2月', | ||
32 | - '3月', | ||
33 | - '4月', | ||
34 | - '5月', | ||
35 | - '6月', | ||
36 | - '7月', | ||
37 | - '8月', | ||
38 | - '9月', | ||
39 | - '10月', | ||
40 | - '11月', | ||
41 | - '12月', | ||
42 | - ], | ||
43 | - }, | ||
44 | - yAxis: { | ||
45 | - type: 'value', | ||
46 | - max: 8000, | ||
47 | - splitNumber: 4, | ||
48 | - }, | ||
49 | - series: [ | ||
50 | - { | ||
51 | - data: [3000, 2000, 3333, 5000, 3200, 4200, 3200, 2100, 3000, 5100, 6000, 3200, 4800], | ||
52 | - type: 'bar', | ||
53 | - barMaxWidth: 80, | 45 | + xAxis: { |
46 | + type: 'time', | ||
54 | }, | 47 | }, |
55 | - ], | ||
56 | - }); | ||
57 | - }); | 48 | + legend: { |
49 | + data: ['传输数据点', '传输消息量'], | ||
50 | + left: '5%', | ||
51 | + orient: 'vertical', | ||
52 | + formatter: (name) => { | ||
53 | + return name === '传输数据点' ? `${name} ${dataPointTotal}` : `${name} ${messageTotal}`; | ||
54 | + }, | ||
55 | + }, | ||
56 | + | ||
57 | + yAxis: {}, | ||
58 | + grid: { | ||
59 | + left: '3%', | ||
60 | + right: '4%', | ||
61 | + bottom: '3%', | ||
62 | + containLabel: true, | ||
63 | + }, | ||
64 | + series: [ | ||
65 | + { | ||
66 | + name: '传输数据点', | ||
67 | + type: 'bar', | ||
68 | + stack: 'total', | ||
69 | + data: newValue, | ||
70 | + color: '#9fe080', | ||
71 | + }, | ||
72 | + { | ||
73 | + name: '传输消息量', | ||
74 | + type: 'bar', | ||
75 | + stack: 'total', | ||
76 | + data: newValue1, | ||
77 | + color: '#5c7bd9', | ||
78 | + }, | ||
79 | + ], | ||
80 | + }); | ||
81 | + } | ||
82 | + ); | ||
58 | </script> | 83 | </script> |
1 | import { PropType } from 'vue'; | 1 | import { PropType } from 'vue'; |
2 | - | 2 | +import type { BasicColumn } from '/@/components/Table'; |
3 | export interface BasicProps { | 3 | export interface BasicProps { |
4 | width: string; | 4 | width: string; |
5 | height: string; | 5 | height: string; |
@@ -14,3 +14,16 @@ export const basicProps = { | @@ -14,3 +14,16 @@ export const basicProps = { | ||
14 | default: '280px', | 14 | default: '280px', |
15 | }, | 15 | }, |
16 | }; | 16 | }; |
17 | + | ||
18 | +export const columns: BasicColumn[] = [ | ||
19 | + { | ||
20 | + title: '租户名称', | ||
21 | + dataIndex: 'name', | ||
22 | + width: 120, | ||
23 | + }, | ||
24 | + { | ||
25 | + title: '过期时间', | ||
26 | + dataIndex: 'tenantExpireTime', | ||
27 | + width: 120, | ||
28 | + }, | ||
29 | +]; |
src/views/dashboard/workbench/data.ts
deleted
100644 → 0
1 | -export interface GrowCardItem { | ||
2 | - imgUrl: string; | ||
3 | - title: string; | ||
4 | - value: string; | ||
5 | - onLine?: number; | ||
6 | - offLine?: number; | ||
7 | - inactive?: number; | ||
8 | - newDay: string; | ||
9 | -} | ||
10 | - | ||
11 | -export const growCardList: GrowCardItem[] = [ | ||
12 | - { | ||
13 | - imgUrl: '/src/assets/images/device-count.png', | ||
14 | - title: '设备数(个)', | ||
15 | - value: '10,000', | ||
16 | - onLine: 2000, | ||
17 | - offLine: 3000, | ||
18 | - inactive: 4000, | ||
19 | - newDay: '123,45', | ||
20 | - }, | ||
21 | - { | ||
22 | - imgUrl: '/src/assets/images/alarm-count.png', | ||
23 | - title: '11月告警数(条)', | ||
24 | - value: '11,000', | ||
25 | - newDay: '167,45', | ||
26 | - }, | ||
27 | - { | ||
28 | - imgUrl: '/src/assets/images/msg-count.png', | ||
29 | - title: '11月消息量(条)', | ||
30 | - value: '12,000', | ||
31 | - newDay: '198,45', | ||
32 | - }, | ||
33 | -]; |
1 | <template> | 1 | <template> |
2 | <div class="p-4 md:flex"> | 2 | <div class="p-4 md:flex"> |
3 | <div class="md:w-7/10 w-full !mr-4 enter-y"> | 3 | <div class="md:w-7/10 w-full !mr-4 enter-y"> |
4 | - <GrowCard :loading="loading" class="enter-y" /> | ||
5 | - <SiteAnalysis class="!my-4 enter-y" :loading="loading" /> | ||
6 | - <div class="md:flex enter-y"> | 4 | + <GrowCard :loading="loading" class="enter-y" :role="role" /> |
5 | + <SiteAnalysis class="!my-4 enter-y" :loading="loading" :role="role" /> | ||
6 | + <div class="md:flex enter-y" v-if="!isAdmin(role)"> | ||
7 | <Card title="核心流程指南" style="width: 100%"> | 7 | <Card title="核心流程指南" style="width: 100%"> |
8 | - <img alt="核心流程指南" src="../../../assets/images/flow.png" /> | 8 | + <img alt="核心流程指南" src="/src/assets/images/flow.png" /> |
9 | </Card> | 9 | </Card> |
10 | </div> | 10 | </div> |
11 | </div> | 11 | </div> |
12 | <div class="md:w-3/10 w-full enter-y"> | 12 | <div class="md:w-3/10 w-full enter-y"> |
13 | - <HelpDoc /> | 13 | + <HelpDoc :role="role" /> |
14 | </div> | 14 | </div> |
15 | </div> | 15 | </div> |
16 | </template> | 16 | </template> |
@@ -20,8 +20,19 @@ | @@ -20,8 +20,19 @@ | ||
20 | import SiteAnalysis from './components/SiteAnalysis.vue'; | 20 | import SiteAnalysis from './components/SiteAnalysis.vue'; |
21 | import { Card } from 'ant-design-vue'; | 21 | import { Card } from 'ant-design-vue'; |
22 | import HelpDoc from './components/HelpDoc.vue'; | 22 | import HelpDoc from './components/HelpDoc.vue'; |
23 | + import { USER_INFO_KEY } from '/@/enums/cacheEnum'; | ||
24 | + import { getAuthCache } from '/@/utils/auth'; | ||
25 | + import { isAdmin } from '/@/enums/roleEnum'; | ||
26 | + defineExpose({ | ||
27 | + isAdmin, | ||
28 | + }); | ||
23 | 29 | ||
30 | + const userInfo: any = getAuthCache(USER_INFO_KEY); | ||
31 | + const role: string = userInfo.roles[0]; | ||
24 | const loading = ref(true); | 32 | const loading = ref(true); |
33 | + | ||
34 | + console.log(role); | ||
35 | + | ||
25 | setTimeout(() => { | 36 | setTimeout(() => { |
26 | loading.value = false; | 37 | loading.value = false; |
27 | }, 1500); | 38 | }, 1500); |
@@ -3,6 +3,7 @@ import { findDictItemByCode } from '/@/api/system/dict'; | @@ -3,6 +3,7 @@ import { findDictItemByCode } from '/@/api/system/dict'; | ||
3 | import { deviceProfile } from '/@/api/device/deviceManager'; | 3 | import { deviceProfile } from '/@/api/device/deviceManager'; |
4 | import { getOrganizationList } from '/@/api/system/system'; | 4 | import { getOrganizationList } from '/@/api/system/system'; |
5 | import { copyTransFun } from '/@/utils/fnUtils'; | 5 | import { copyTransFun } from '/@/utils/fnUtils'; |
6 | + | ||
6 | // 第一步的表单 | 7 | // 第一步的表单 |
7 | export const step1Schemas: FormSchema[] = [ | 8 | export const step1Schemas: FormSchema[] = [ |
8 | { | 9 | { |
@@ -17,6 +18,7 @@ export const step1Schemas: FormSchema[] = [ | @@ -17,6 +18,7 @@ export const step1Schemas: FormSchema[] = [ | ||
17 | required: true, | 18 | required: true, |
18 | component: 'Input', | 19 | component: 'Input', |
19 | componentProps: { | 20 | componentProps: { |
21 | + placeholder: '设备名称', | ||
20 | maxLength: 30, | 22 | maxLength: 30, |
21 | }, | 23 | }, |
22 | }, | 24 | }, |
@@ -26,6 +28,7 @@ export const step1Schemas: FormSchema[] = [ | @@ -26,6 +28,7 @@ export const step1Schemas: FormSchema[] = [ | ||
26 | required: true, | 28 | required: true, |
27 | component: 'ApiSelect', | 29 | component: 'ApiSelect', |
28 | componentProps: { | 30 | componentProps: { |
31 | + placeholder: '设备类型', | ||
29 | api: findDictItemByCode, | 32 | api: findDictItemByCode, |
30 | params: { | 33 | params: { |
31 | dictCode: 'device_type', | 34 | dictCode: 'device_type', |
@@ -64,6 +67,20 @@ export const step1Schemas: FormSchema[] = [ | @@ -64,6 +67,20 @@ export const step1Schemas: FormSchema[] = [ | ||
64 | component: 'Input', | 67 | component: 'Input', |
65 | componentProps: { | 68 | componentProps: { |
66 | maxLength: 255, | 69 | maxLength: 255, |
70 | + placeholder: '请输入设备标签', | ||
71 | + }, | ||
72 | + dynamicRules: () => { | ||
73 | + return [ | ||
74 | + { | ||
75 | + required: false, | ||
76 | + validator: (_, value) => { | ||
77 | + if (String(value).length > 255) { | ||
78 | + return Promise.reject('字数不超过255个字'); | ||
79 | + } | ||
80 | + return Promise.resolve(); | ||
81 | + }, | ||
82 | + }, | ||
83 | + ]; | ||
67 | }, | 84 | }, |
68 | }, | 85 | }, |
69 | { | 86 | { |
@@ -76,24 +93,92 @@ export const step1Schemas: FormSchema[] = [ | @@ -76,24 +93,92 @@ export const step1Schemas: FormSchema[] = [ | ||
76 | field: 'description', | 93 | field: 'description', |
77 | label: '备注', | 94 | label: '备注', |
78 | component: 'InputTextArea', | 95 | component: 'InputTextArea', |
96 | + componentProps: { | ||
97 | + maxLength: 500, | ||
98 | + placeholder: '请输入备注', | ||
99 | + }, | ||
100 | + dynamicRules: () => { | ||
101 | + return [ | ||
102 | + { | ||
103 | + required: false, | ||
104 | + validator: (_, value) => { | ||
105 | + if (String(value).length > 500) { | ||
106 | + return Promise.reject('字数不超过500个字'); | ||
107 | + } | ||
108 | + return Promise.resolve(); | ||
109 | + }, | ||
110 | + }, | ||
111 | + ]; | ||
112 | + }, | ||
79 | }, | 113 | }, |
80 | { | 114 | { |
81 | field: 'id', | 115 | field: 'id', |
82 | label: 'id', | 116 | label: 'id', |
83 | component: 'Input', | 117 | component: 'Input', |
84 | show: false, | 118 | show: false, |
119 | + componentProps: { | ||
120 | + maxLength: 36, | ||
121 | + placeholder: '请输入id', | ||
122 | + }, | ||
123 | + dynamicRules: () => { | ||
124 | + return [ | ||
125 | + { | ||
126 | + required: false, | ||
127 | + validator: (_, value) => { | ||
128 | + if (String(value).length > 36) { | ||
129 | + return Promise.reject('字数不超过36个字'); | ||
130 | + } | ||
131 | + return Promise.resolve(); | ||
132 | + }, | ||
133 | + }, | ||
134 | + ]; | ||
135 | + }, | ||
85 | }, | 136 | }, |
86 | { | 137 | { |
87 | field: 'tenantId', | 138 | field: 'tenantId', |
88 | label: '租户Code', | 139 | label: '租户Code', |
89 | component: 'Input', | 140 | component: 'Input', |
90 | show: false, | 141 | show: false, |
142 | + componentProps: { | ||
143 | + maxLength: 36, | ||
144 | + placeholder: '请输入租户Code', | ||
145 | + }, | ||
146 | + dynamicRules: () => { | ||
147 | + return [ | ||
148 | + { | ||
149 | + required: false, | ||
150 | + validator: (_, value) => { | ||
151 | + if (String(value).length > 36) { | ||
152 | + return Promise.reject('字数不超过36个字'); | ||
153 | + } | ||
154 | + return Promise.resolve(); | ||
155 | + }, | ||
156 | + }, | ||
157 | + ]; | ||
158 | + }, | ||
91 | }, | 159 | }, |
92 | { | 160 | { |
93 | field: 'tbDeviceId', | 161 | field: 'tbDeviceId', |
94 | label: 'tbDeviceId', | 162 | label: 'tbDeviceId', |
95 | component: 'Input', | 163 | component: 'Input', |
96 | show: false, | 164 | show: false, |
165 | + componentProps: { | ||
166 | + maxLength: 36, | ||
167 | + placeholder: '请输入tbDeviceId', | ||
168 | + }, | ||
169 | + dynamicRules: () => { | ||
170 | + return [ | ||
171 | + { | ||
172 | + required: false, | ||
173 | + validator: (_, value) => { | ||
174 | + if (String(value).length > 36) { | ||
175 | + return Promise.reject('字数不超过36个字'); | ||
176 | + } | ||
177 | + return Promise.resolve(); | ||
178 | + }, | ||
179 | + }, | ||
180 | + ]; | ||
181 | + }, | ||
97 | }, | 182 | }, |
98 | ]; | 183 | ]; |
99 | 184 | ||
@@ -244,6 +329,10 @@ export const step2Schemas: FormSchema[] = [ | @@ -244,6 +329,10 @@ export const step2Schemas: FormSchema[] = [ | ||
244 | field: 'credentialsId', | 329 | field: 'credentialsId', |
245 | required: true, | 330 | required: true, |
246 | ifShow: false, | 331 | ifShow: false, |
332 | + componentProps: { | ||
333 | + maxLength: 36, | ||
334 | + placeholder: '请输入访问令牌', | ||
335 | + }, | ||
247 | }, | 336 | }, |
248 | { | 337 | { |
249 | label: 'RSA公钥', | 338 | label: 'RSA公钥', |
@@ -251,6 +340,10 @@ export const step2Schemas: FormSchema[] = [ | @@ -251,6 +340,10 @@ export const step2Schemas: FormSchema[] = [ | ||
251 | field: 'publicKey', | 340 | field: 'publicKey', |
252 | required: true, | 341 | required: true, |
253 | ifShow: false, | 342 | ifShow: false, |
343 | + componentProps: { | ||
344 | + maxLength: 36, | ||
345 | + placeholder: '请输入RSA公钥', | ||
346 | + }, | ||
254 | }, | 347 | }, |
255 | { | 348 | { |
256 | label: '客户端ID', | 349 | label: '客户端ID', |
@@ -258,6 +351,10 @@ export const step2Schemas: FormSchema[] = [ | @@ -258,6 +351,10 @@ export const step2Schemas: FormSchema[] = [ | ||
258 | field: 'clientId', | 351 | field: 'clientId', |
259 | required: true, | 352 | required: true, |
260 | ifShow: false, | 353 | ifShow: false, |
354 | + componentProps: { | ||
355 | + maxLength: 36, | ||
356 | + placeholder: '请输入客户端ID', | ||
357 | + }, | ||
261 | }, | 358 | }, |
262 | { | 359 | { |
263 | label: '用户名', | 360 | label: '用户名', |
@@ -265,11 +362,32 @@ export const step2Schemas: FormSchema[] = [ | @@ -265,11 +362,32 @@ export const step2Schemas: FormSchema[] = [ | ||
265 | field: 'username', | 362 | field: 'username', |
266 | required: true, | 363 | required: true, |
267 | ifShow: false, | 364 | ifShow: false, |
365 | + componentProps: { | ||
366 | + maxLength: 255, | ||
367 | + placeholder: '请输入用户名', | ||
368 | + }, | ||
268 | }, | 369 | }, |
269 | { | 370 | { |
270 | label: '密码', | 371 | label: '密码', |
271 | component: 'InputPassword', | 372 | component: 'InputPassword', |
272 | field: 'password', | 373 | field: 'password', |
374 | + componentProps: { | ||
375 | + maxLength: 36, | ||
376 | + placeholder: '请输入密码', | ||
377 | + }, | ||
378 | + dynamicRules: () => { | ||
379 | + return [ | ||
380 | + { | ||
381 | + required: false, | ||
382 | + validator: (_, value) => { | ||
383 | + if (String(value).length > 36) { | ||
384 | + return Promise.reject('字数不超过36个字'); | ||
385 | + } | ||
386 | + return Promise.resolve(); | ||
387 | + }, | ||
388 | + }, | ||
389 | + ]; | ||
390 | + }, | ||
273 | ifShow: false, | 391 | ifShow: false, |
274 | }, | 392 | }, |
275 | ]; | 393 | ]; |
@@ -409,6 +527,10 @@ export const TokenSchemas: FormSchema[] = [ | @@ -409,6 +527,10 @@ export const TokenSchemas: FormSchema[] = [ | ||
409 | field: 'credentialsId', | 527 | field: 'credentialsId', |
410 | required: true, | 528 | required: true, |
411 | ifShow: false, | 529 | ifShow: false, |
530 | + componentProps: { | ||
531 | + maxLength: 36, | ||
532 | + placeholder: '请输入访问令牌', | ||
533 | + }, | ||
412 | }, | 534 | }, |
413 | { | 535 | { |
414 | label: 'RSA公钥', | 536 | label: 'RSA公钥', |
@@ -416,6 +538,10 @@ export const TokenSchemas: FormSchema[] = [ | @@ -416,6 +538,10 @@ export const TokenSchemas: FormSchema[] = [ | ||
416 | field: 'publicKey', | 538 | field: 'publicKey', |
417 | required: true, | 539 | required: true, |
418 | ifShow: false, | 540 | ifShow: false, |
541 | + componentProps: { | ||
542 | + maxLength: 36, | ||
543 | + placeholder: '请输入RSA公钥', | ||
544 | + }, | ||
419 | }, | 545 | }, |
420 | { | 546 | { |
421 | label: '客户端ID', | 547 | label: '客户端ID', |
@@ -423,6 +549,10 @@ export const TokenSchemas: FormSchema[] = [ | @@ -423,6 +549,10 @@ export const TokenSchemas: FormSchema[] = [ | ||
423 | field: 'clientId', | 549 | field: 'clientId', |
424 | required: true, | 550 | required: true, |
425 | ifShow: false, | 551 | ifShow: false, |
552 | + componentProps: { | ||
553 | + maxLength: 36, | ||
554 | + placeholder: '请输入客户端ID', | ||
555 | + }, | ||
426 | }, | 556 | }, |
427 | { | 557 | { |
428 | label: '用户名', | 558 | label: '用户名', |
@@ -430,23 +560,78 @@ export const TokenSchemas: FormSchema[] = [ | @@ -430,23 +560,78 @@ export const TokenSchemas: FormSchema[] = [ | ||
430 | field: 'username', | 560 | field: 'username', |
431 | required: true, | 561 | required: true, |
432 | ifShow: false, | 562 | ifShow: false, |
563 | + componentProps: { | ||
564 | + maxLength: 255, | ||
565 | + placeholder: '请输入用户名', | ||
566 | + }, | ||
433 | }, | 567 | }, |
434 | { | 568 | { |
435 | label: '密码', | 569 | label: '密码', |
436 | component: 'InputPassword', | 570 | component: 'InputPassword', |
437 | field: 'password', | 571 | field: 'password', |
438 | ifShow: false, | 572 | ifShow: false, |
573 | + componentProps: { | ||
574 | + maxLength: 36, | ||
575 | + placeholder: '请输入密码', | ||
576 | + }, | ||
577 | + dynamicRules: () => { | ||
578 | + return [ | ||
579 | + { | ||
580 | + required: false, | ||
581 | + validator: (_, value) => { | ||
582 | + if (String(value).length > 36) { | ||
583 | + return Promise.reject('字数不超过36个字'); | ||
584 | + } | ||
585 | + return Promise.resolve(); | ||
586 | + }, | ||
587 | + }, | ||
588 | + ]; | ||
589 | + }, | ||
439 | }, | 590 | }, |
440 | { | 591 | { |
441 | label: 'id', | 592 | label: 'id', |
442 | component: 'Input', | 593 | component: 'Input', |
443 | field: 'id', | 594 | field: 'id', |
444 | show: false, | 595 | show: false, |
596 | + componentProps: { | ||
597 | + maxLength: 36, | ||
598 | + placeholder: '请输入id', | ||
599 | + }, | ||
600 | + dynamicRules: () => { | ||
601 | + return [ | ||
602 | + { | ||
603 | + required: false, | ||
604 | + validator: (_, value) => { | ||
605 | + if (String(value).length > 36) { | ||
606 | + return Promise.reject('字数不超过36个字'); | ||
607 | + } | ||
608 | + return Promise.resolve(); | ||
609 | + }, | ||
610 | + }, | ||
611 | + ]; | ||
612 | + }, | ||
445 | }, | 613 | }, |
446 | { | 614 | { |
447 | label: 'tbDeviceId', | 615 | label: 'tbDeviceId', |
448 | component: 'Input', | 616 | component: 'Input', |
449 | field: 'tbDeviceId', | 617 | field: 'tbDeviceId', |
450 | show: false, | 618 | show: false, |
619 | + componentProps: { | ||
620 | + maxLength: 36, | ||
621 | + placeholder: '请输入tbDeviceId', | ||
622 | + }, | ||
623 | + dynamicRules: () => { | ||
624 | + return [ | ||
625 | + { | ||
626 | + required: false, | ||
627 | + validator: (_, value) => { | ||
628 | + if (String(value).length > 36) { | ||
629 | + return Promise.reject('字数不超过36个字'); | ||
630 | + } | ||
631 | + return Promise.resolve(); | ||
632 | + }, | ||
633 | + }, | ||
634 | + ]; | ||
635 | + }, | ||
451 | }, | 636 | }, |
452 | ]; | 637 | ]; |
1 | import { formatToDateTime } from '/@/utils/dateUtil'; | 1 | import { formatToDateTime } from '/@/utils/dateUtil'; |
2 | import { FormSchema } from '/@/components/Form'; | 2 | import { FormSchema } from '/@/components/Form'; |
3 | import { BasicColumn } from '/@/components/Table'; | 3 | import { BasicColumn } from '/@/components/Table'; |
4 | + | ||
4 | import { DeviceTypeEnum } from '/@/api/device/model/deviceModel'; | 5 | import { DeviceTypeEnum } from '/@/api/device/model/deviceModel'; |
5 | 6 | ||
6 | export const columns: BasicColumn[] = [ | 7 | export const columns: BasicColumn[] = [ |
@@ -8,25 +9,20 @@ export const columns: BasicColumn[] = [ | @@ -8,25 +9,20 @@ export const columns: BasicColumn[] = [ | ||
8 | title: '设备名称', | 9 | title: '设备名称', |
9 | dataIndex: 'name', | 10 | dataIndex: 'name', |
10 | width: 120, | 11 | width: 120, |
11 | - key: 'name', | ||
12 | }, | 12 | }, |
13 | { | 13 | { |
14 | title: '设备标签', | 14 | title: '设备标签', |
15 | dataIndex: 'label', | 15 | dataIndex: 'label', |
16 | width: 100, | 16 | width: 100, |
17 | - key: 'label', | ||
18 | }, | 17 | }, |
19 | { | 18 | { |
20 | title: '设备配置', | 19 | title: '设备配置', |
21 | dataIndex: 'deviceProfile.name', | 20 | dataIndex: 'deviceProfile.name', |
22 | width: 160, | 21 | width: 160, |
23 | - key: 'deviceProfile.name', | ||
24 | }, | 22 | }, |
25 | - | ||
26 | { | 23 | { |
27 | title: '设备类型', | 24 | title: '设备类型', |
28 | dataIndex: 'deviceType', | 25 | dataIndex: 'deviceType', |
29 | - key: 'deviceType', | ||
30 | customRender({ text }) { | 26 | customRender({ text }) { |
31 | return text === DeviceTypeEnum.GATEWAY | 27 | return text === DeviceTypeEnum.GATEWAY |
32 | ? '网关设备' | 28 | ? '网关设备' |
@@ -39,7 +35,6 @@ export const columns: BasicColumn[] = [ | @@ -39,7 +35,6 @@ export const columns: BasicColumn[] = [ | ||
39 | title: '描述', | 35 | title: '描述', |
40 | dataIndex: 'description', | 36 | dataIndex: 'description', |
41 | width: 180, | 37 | width: 180, |
42 | - key: 'description', | ||
43 | }, | 38 | }, |
44 | ]; | 39 | ]; |
45 | // 实时数据表格 | 40 | // 实时数据表格 |
@@ -95,6 +90,9 @@ export const alarmSearchSchemas: FormSchema[] = [ | @@ -95,6 +90,9 @@ export const alarmSearchSchemas: FormSchema[] = [ | ||
95 | label: '告警类型', | 90 | label: '告警类型', |
96 | component: 'Input', | 91 | component: 'Input', |
97 | colProps: { span: 6 }, | 92 | colProps: { span: 6 }, |
93 | + componentProps: { | ||
94 | + maxLength: 36, | ||
95 | + }, | ||
98 | }, | 96 | }, |
99 | { | 97 | { |
100 | field: 'endTime', | 98 | field: 'endTime', |
@@ -208,6 +206,9 @@ export const alarmSchemasForm: FormSchema[] = [ | @@ -208,6 +206,9 @@ export const alarmSchemasForm: FormSchema[] = [ | ||
208 | field: 'details', | 206 | field: 'details', |
209 | label: '详情', | 207 | label: '详情', |
210 | component: 'InputTextArea', | 208 | component: 'InputTextArea', |
209 | + componentProps: { | ||
210 | + maxLength: 255, | ||
211 | + }, | ||
211 | }, | 212 | }, |
212 | ]; | 213 | ]; |
213 | 214 | ||
@@ -218,12 +219,18 @@ export const childDeviceSchemas: FormSchema[] = [ | @@ -218,12 +219,18 @@ export const childDeviceSchemas: FormSchema[] = [ | ||
218 | label: '设备配置', | 219 | label: '设备配置', |
219 | component: 'Select', | 220 | component: 'Select', |
220 | colProps: { span: 12 }, | 221 | colProps: { span: 12 }, |
222 | + componentProps: { | ||
223 | + maxLength: 255, | ||
224 | + }, | ||
221 | }, | 225 | }, |
222 | { | 226 | { |
223 | field: 'icon', | 227 | field: 'icon', |
224 | label: '设备名称', | 228 | label: '设备名称', |
225 | component: 'Input', | 229 | component: 'Input', |
226 | colProps: { span: 12 }, | 230 | colProps: { span: 12 }, |
231 | + componentProps: { | ||
232 | + maxLength: 255, | ||
233 | + }, | ||
227 | }, | 234 | }, |
228 | ]; | 235 | ]; |
229 | export const childDeviceColumns: BasicColumn[] = [ | 236 | export const childDeviceColumns: BasicColumn[] = [ |
1 | +import { formatToDate } from '/@/utils/dateUtil'; | ||
1 | import { BasicColumn } from '/@/components/Table'; | 2 | import { BasicColumn } from '/@/components/Table'; |
2 | import { FormSchema } from '/@/components/Table'; | 3 | import { FormSchema } from '/@/components/Table'; |
3 | import { DeviceTypeEnum, DeviceState } from '/@/api/device/model/deviceModel'; | 4 | import { DeviceTypeEnum, DeviceState } from '/@/api/device/model/deviceModel'; |
5 | + | ||
4 | // 表格列数据 | 6 | // 表格列数据 |
5 | export const columns: BasicColumn[] = [ | 7 | export const columns: BasicColumn[] = [ |
6 | { | 8 | { |
@@ -19,6 +21,7 @@ export const columns: BasicColumn[] = [ | @@ -19,6 +21,7 @@ export const columns: BasicColumn[] = [ | ||
19 | dataIndex: 'deviceProfile.name', | 21 | dataIndex: 'deviceProfile.name', |
20 | width: 160, | 22 | width: 160, |
21 | slots: { customRender: 'deviceProfile' }, | 23 | slots: { customRender: 'deviceProfile' }, |
24 | + ellipsis: true, | ||
22 | }, | 25 | }, |
23 | 26 | ||
24 | { | 27 | { |
@@ -36,10 +39,16 @@ export const columns: BasicColumn[] = [ | @@ -36,10 +39,16 @@ export const columns: BasicColumn[] = [ | ||
36 | width: 120, | 39 | width: 120, |
37 | slots: { customRender: 'deviceState' }, | 40 | slots: { customRender: 'deviceState' }, |
38 | }, | 41 | }, |
39 | - | ||
40 | { | 42 | { |
41 | title: '最后连接时间', | 43 | title: '最后连接时间', |
42 | - dataIndex: 'lastConnectTime', | 44 | + dataIndex: 'lastOnlineTime', |
45 | + format: (text) => formatToDate(text, 'YYYY-MM-DD HH:mm:ss'), | ||
46 | + width: 180, | ||
47 | + }, | ||
48 | + { | ||
49 | + title: '最后断开时间', | ||
50 | + dataIndex: 'lastOfflineTime', | ||
51 | + format: (text) => formatToDate(text, 'YYYY-MM-DD HH:mm:ss'), | ||
43 | width: 180, | 52 | width: 180, |
44 | }, | 53 | }, |
45 | ]; | 54 | ]; |
@@ -76,6 +85,23 @@ export const searchFormSchema: FormSchema[] = [ | @@ -76,6 +85,23 @@ export const searchFormSchema: FormSchema[] = [ | ||
76 | field: 'name', | 85 | field: 'name', |
77 | label: '设备名称', | 86 | label: '设备名称', |
78 | component: 'Input', | 87 | component: 'Input', |
79 | - colProps: { span: 6 }, | 88 | + colProps: { span: 7 }, |
89 | + componentProps: { | ||
90 | + maxLength: 255, | ||
91 | + placeholder: '请输入设备名称', | ||
92 | + }, | ||
93 | + dynamicRules: () => { | ||
94 | + return [ | ||
95 | + { | ||
96 | + required: false, | ||
97 | + validator: (_, value) => { | ||
98 | + if (String(value).length > 255) { | ||
99 | + return Promise.reject('字数不超过255个字'); | ||
100 | + } | ||
101 | + return Promise.resolve(); | ||
102 | + }, | ||
103 | + }, | ||
104 | + ]; | ||
105 | + }, | ||
80 | }, | 106 | }, |
81 | ]; | 107 | ]; |
@@ -6,7 +6,7 @@ | @@ -6,7 +6,7 @@ | ||
6 | :destroyOnClose="true" | 6 | :destroyOnClose="true" |
7 | @close="closeDrawer" | 7 | @close="closeDrawer" |
8 | :title="deviceDetail.name" | 8 | :title="deviceDetail.name" |
9 | - width="78%" | 9 | + width="70%" |
10 | > | 10 | > |
11 | <Tabs v-model:activeKey="activeKey" :size="size" type="card"> | 11 | <Tabs v-model:activeKey="activeKey" :size="size" type="card"> |
12 | <TabPane key="1" tab="详情" | 12 | <TabPane key="1" tab="详情" |
@@ -26,7 +26,7 @@ | @@ -26,7 +26,7 @@ | ||
26 | import { defineComponent, ref } from 'vue'; | 26 | import { defineComponent, ref } from 'vue'; |
27 | import { BasicDrawer, useDrawerInner } from '/@/components/Drawer'; | 27 | import { BasicDrawer, useDrawerInner } from '/@/components/Drawer'; |
28 | 28 | ||
29 | - import { Tabs, TabPane } from 'ant-design-vue'; | 29 | + import { Tabs } from 'ant-design-vue'; |
30 | import Detail from '../tabs/Detail.vue'; | 30 | import Detail from '../tabs/Detail.vue'; |
31 | import RealTimeData from '../tabs/RealTimeData.vue'; | 31 | import RealTimeData from '../tabs/RealTimeData.vue'; |
32 | import Alarm from '../tabs/Alarm.vue'; | 32 | import Alarm from '../tabs/Alarm.vue'; |
@@ -37,13 +37,12 @@ | @@ -37,13 +37,12 @@ | ||
37 | components: { | 37 | components: { |
38 | BasicDrawer, | 38 | BasicDrawer, |
39 | Tabs, | 39 | Tabs, |
40 | - TabPane, | 40 | + TabPane: Tabs.TabPane, |
41 | Detail, | 41 | Detail, |
42 | RealTimeData, | 42 | RealTimeData, |
43 | Alarm, | 43 | Alarm, |
44 | ChildDevice, | 44 | ChildDevice, |
45 | }, | 45 | }, |
46 | - | ||
47 | emits: ['reload', 'register'], | 46 | emits: ['reload', 'register'], |
48 | setup() { | 47 | setup() { |
49 | const activeKey = ref('1'); | 48 | const activeKey = ref('1'); |
@@ -39,9 +39,10 @@ | @@ -39,9 +39,10 @@ | ||
39 | import { createOrEditDevice } from '/@/api/device/deviceManager'; | 39 | import { createOrEditDevice } from '/@/api/device/deviceManager'; |
40 | import DeviceStep1 from '../step/DeviceStep1.vue'; | 40 | import DeviceStep1 from '../step/DeviceStep1.vue'; |
41 | import DeviceStep2 from '../step/DeviceStep2.vue'; | 41 | import DeviceStep2 from '../step/DeviceStep2.vue'; |
42 | - import { Steps, Step } from 'ant-design-vue'; | 42 | + import { Steps } from 'ant-design-vue'; |
43 | import { useMessage } from '/@/hooks/web/useMessage'; | 43 | import { useMessage } from '/@/hooks/web/useMessage'; |
44 | import { credentialTypeEnum } from '../../config/data'; | 44 | import { credentialTypeEnum } from '../../config/data'; |
45 | + | ||
45 | export default defineComponent({ | 46 | export default defineComponent({ |
46 | name: 'DeviceModal', | 47 | name: 'DeviceModal', |
47 | components: { | 48 | components: { |
@@ -49,7 +50,7 @@ | @@ -49,7 +50,7 @@ | ||
49 | DeviceStep1, | 50 | DeviceStep1, |
50 | DeviceStep2, | 51 | DeviceStep2, |
51 | Steps, | 52 | Steps, |
52 | - Step, | 53 | + Step: Steps.Step, |
53 | }, | 54 | }, |
54 | props: { | 55 | props: { |
55 | userData: { type: Object }, | 56 | userData: { type: Object }, |
@@ -44,6 +44,13 @@ | @@ -44,6 +44,13 @@ | ||
44 | labelWidth: 120, | 44 | labelWidth: 120, |
45 | schemas: alarmSearchSchemas, | 45 | schemas: alarmSearchSchemas, |
46 | }, | 46 | }, |
47 | + showTableSetting: true, | ||
48 | + tableSetting: { | ||
49 | + redo: true, | ||
50 | + size: false, | ||
51 | + setting: false, | ||
52 | + fullScreen: false, | ||
53 | + }, | ||
47 | useSearchForm: true, | 54 | useSearchForm: true, |
48 | bordered: true, | 55 | bordered: true, |
49 | showIndexColumn: false, | 56 | showIndexColumn: false, |
@@ -10,8 +10,8 @@ | @@ -10,8 +10,8 @@ | ||
10 | bordered | 10 | bordered |
11 | :columns="columns" | 11 | :columns="columns" |
12 | :data-source="[deviceDetail]" | 12 | :data-source="[deviceDetail]" |
13 | + :rowKey="(_, index) => index" | ||
13 | :pagination="false" | 14 | :pagination="false" |
14 | - rowKey="tbDeviceId" | ||
15 | style="width: 800px" | 15 | style="width: 800px" |
16 | /> | 16 | /> |
17 | </div> | 17 | </div> |
@@ -23,7 +23,7 @@ | @@ -23,7 +23,7 @@ | ||
23 | </div> | 23 | </div> |
24 | <div v-if="deviceDetail?.deviceInfo?.address" class="mt-4"> | 24 | <div v-if="deviceDetail?.deviceInfo?.address" class="mt-4"> |
25 | <p>设备位置</p> | 25 | <p>设备位置</p> |
26 | - <div ref="wrapRef" style="height: 400px; width: 90%"></div> | 26 | + <div ref="wrapRef" style="height: 400px; width: 100%"></div> |
27 | </div> | 27 | </div> |
28 | </div> | 28 | </div> |
29 | </template> | 29 | </template> |
@@ -24,7 +24,7 @@ | @@ -24,7 +24,7 @@ | ||
24 | setup(props) { | 24 | setup(props) { |
25 | const token: string = getAuthCache(JWT_TOKEN_KEY); | 25 | const token: string = getAuthCache(JWT_TOKEN_KEY); |
26 | const state = reactive({ | 26 | const state = reactive({ |
27 | - server: `ws://101.133.234.90:8080/api/ws/plugins/telemetry?token=${token}`, | 27 | + server: `${import.meta.env.VITE_WEB_SOCKET}${token}`, |
28 | sendValue: JSON.stringify({ | 28 | sendValue: JSON.stringify({ |
29 | attrSubCmds: [], | 29 | attrSubCmds: [], |
30 | tsSubCmds: [ | 30 | tsSubCmds: [ |
@@ -8,7 +8,7 @@ | @@ -8,7 +8,7 @@ | ||
8 | @cancel="handleCancel" | 8 | @cancel="handleCancel" |
9 | > | 9 | > |
10 | <div class="step-form-form"> | 10 | <div class="step-form-form"> |
11 | - <a-steps :current="current"> | 11 | + <a-steps :current="current" @change="handleChange"> |
12 | <a-step title="设备配置" /> | 12 | <a-step title="设备配置" /> |
13 | <a-step title="传输配置" /> | 13 | <a-step title="传输配置" /> |
14 | <a-step title="告警配置" /> | 14 | <a-step title="告警配置" /> |
@@ -34,10 +34,9 @@ | @@ -34,10 +34,9 @@ | ||
34 | @next="handleStep3Next" | 34 | @next="handleStep3Next" |
35 | @redo="handleRedo" | 35 | @redo="handleRedo" |
36 | /></div> | 36 | /></div> |
37 | - | ||
38 | <div v-show="current === 3"> | 37 | <div v-show="current === 3"> |
39 | - <DeviceProfileStep4 ref="DeviceProfileStep4Ref" @prev="handleStepPrev" | ||
40 | - /></div> | 38 | + <DeviceProfileStep4 ref="DeviceProfileStep4Ref" @prev="handleStepPrev" /> |
39 | + </div> | ||
41 | </div> | 40 | </div> |
42 | </BasicModal> | 41 | </BasicModal> |
43 | </template> | 42 | </template> |
@@ -86,13 +85,21 @@ | @@ -86,13 +85,21 @@ | ||
86 | const current = ref(0); | 85 | const current = ref(0); |
87 | const isUpdate = ref(true); | 86 | const isUpdate = ref(true); |
88 | const getTitle = computed(() => (!unref(isUpdate) ? '新增设备配置' : '编辑设备配置')); | 87 | const getTitle = computed(() => (!unref(isUpdate) ? '新增设备配置' : '编辑设备配置')); |
88 | + const handleChange = (v) => { | ||
89 | + console.log(v); | ||
90 | + }; | ||
89 | const [register, { closeModal }] = useModalInner(async (data) => { | 91 | const [register, { closeModal }] = useModalInner(async (data) => { |
90 | isUpdate.value = !!data?.isUpdate; | 92 | isUpdate.value = !!data?.isUpdate; |
91 | if (!unref(isUpdate)) { | 93 | if (!unref(isUpdate)) { |
92 | current.value = 0; | 94 | current.value = 0; |
95 | + proxy.$refs.DeviceProfileStep3Ref.clearProfileDataFunc(); | ||
96 | + proxy.$refs.DeviceProfileStep3Ref.addAlarmRule(); | ||
97 | + // proxy.$refs.DeviceProfileStep4Ref.customResetAndFunc(); | ||
98 | + | ||
93 | switch (current.value) { | 99 | switch (current.value) { |
94 | case 0: | 100 | case 0: |
95 | proxy.$refs.DeviceProfileStep1Ref.customResetFunc(); | 101 | proxy.$refs.DeviceProfileStep1Ref.customResetFunc(); |
102 | + proxy.$refs.DeviceProfileStep1Ref.resetIconFunc(); | ||
96 | break; | 103 | break; |
97 | case 1: | 104 | case 1: |
98 | proxy.$refs.DeviceProfileStep2Ref.customResetAndFunc(); | 105 | proxy.$refs.DeviceProfileStep2Ref.customResetAndFunc(); |
@@ -109,32 +116,15 @@ | @@ -109,32 +116,15 @@ | ||
109 | } | 116 | } |
110 | if (unref(isUpdate)) { | 117 | if (unref(isUpdate)) { |
111 | current.value = 0; | 118 | current.value = 0; |
119 | + proxy.$refs.DeviceProfileStep3Ref.clearProfileDataFunc(); | ||
120 | + proxy.$refs.DeviceProfileStep3Ref.addAlarmRule(); | ||
112 | postEditId.value = data.record.id; | 121 | postEditId.value = data.record.id; |
113 | const getBackendData = await deviceConfigGetDetail(postEditId.value); | 122 | const getBackendData = await deviceConfigGetDetail(postEditId.value); |
114 | editEchoData.value = { ...getBackendData }; | 123 | editEchoData.value = { ...getBackendData }; |
115 | - console.log(editEchoData.value); | ||
116 | switch (current.value) { | 124 | switch (current.value) { |
117 | case 0: | 125 | case 0: |
118 | proxy.$refs.DeviceProfileStep1Ref.resetFieldsFunc(editEchoData.value); | 126 | proxy.$refs.DeviceProfileStep1Ref.resetFieldsFunc(editEchoData.value); |
119 | - break; | ||
120 | - case 1: | ||
121 | - proxy.$refs.DeviceProfileStep2Ref.resetFieldsFunc({ | ||
122 | - transportType: editEchoData.value.profileData.transportConfiguration.type, | ||
123 | - }); | ||
124 | - break; | ||
125 | - case 2: | ||
126 | - proxy.$refs.DeviceProfileStep3Ref.retryRegisterFormFunc({ | ||
127 | - alarmType: editEchoData.value.profileData?.alarms[0].alarmType, | ||
128 | - }); | ||
129 | - proxy.$refs.DeviceProfileStep3Ref.retryRegisterFormHighSettingmFunc( | ||
130 | - editEchoData.value | ||
131 | - ); | ||
132 | - proxy.$refs.DeviceProfileStep3Ref.retryRegisterFormCreateAlarmFunc( | ||
133 | - editEchoData.value | ||
134 | - ); | ||
135 | - break; | ||
136 | - case 3: | ||
137 | - proxy.$refs.DeviceProfileStep4Ref.resetFieldsFunc(editEchoData.value); | 127 | + proxy.$refs.DeviceProfileStep1Ref.editIconFunc(editEchoData.value.icon); |
138 | break; | 128 | break; |
139 | } | 129 | } |
140 | } | 130 | } |
@@ -142,18 +132,132 @@ | @@ -142,18 +132,132 @@ | ||
142 | function handleStepPrev() { | 132 | function handleStepPrev() { |
143 | current.value--; | 133 | current.value--; |
144 | } | 134 | } |
145 | - function handleStepNext1(v) { | 135 | + function handleStepNext1(v, v1) { |
136 | + console.log(v, v1); | ||
146 | current.value++; | 137 | current.value++; |
147 | getStepOneData.value = v; | 138 | getStepOneData.value = v; |
139 | + getStepOneData.value.icon = v1; | ||
140 | + console.log(getStepOneData.value); | ||
141 | + if (unref(isUpdate)) { | ||
142 | + proxy.$refs.DeviceProfileStep2Ref.resetFieldsFunc({ | ||
143 | + transportType: editEchoData.value.profileData.transportConfiguration.type, | ||
144 | + }); | ||
145 | + } else { | ||
146 | + // proxy.$refs.DeviceProfileStep2Ref.customResetAndFunc(); | ||
147 | + } | ||
148 | } | 148 | } |
149 | function handleStep2Next(v) { | 149 | function handleStep2Next(v) { |
150 | current.value++; | 150 | current.value++; |
151 | + | ||
151 | getStepTwoData.value = v; | 152 | getStepTwoData.value = v; |
152 | - proxy.$refs.DeviceProfileStep3Ref.addAlarmRule(); | 153 | + if (unref(isUpdate)) { |
154 | + proxy.$refs.DeviceProfileStep3Ref.retryRegisterFormFunc({ | ||
155 | + alarmType: editEchoData.value.profileData.alarms[0].alarmType, | ||
156 | + }); | ||
157 | + proxy.$refs.DeviceProfileStep3Ref.retryRegisterFormHighSettingmFunc({ | ||
158 | + propagate: editEchoData.value.profileData.alarms[0].propagate, | ||
159 | + propagateRelationTypes: | ||
160 | + editEchoData.value.profileData?.alarms[0].propagateRelationTypes, | ||
161 | + }); | ||
162 | + const getKey = Object.keys(editEchoData.value.profileData?.alarms[0].createRules); | ||
163 | + proxy.$refs.DeviceProfileStep3Ref.retryRegisterFormCreateAlarmFunc({ | ||
164 | + default: getKey[0], | ||
165 | + }); | ||
166 | + const findDay = [ | ||
167 | + { label: '等于', value: 'EQUAL' }, | ||
168 | + { label: '不等于', value: 'NOT_EQUAL' }, | ||
169 | + { label: '开始于', value: 'STARTS_WITH' }, | ||
170 | + { label: '结束于', value: 'ENDS_WITH' }, | ||
171 | + { label: '包含', value: 'CONTAINS' }, | ||
172 | + { label: '不包含', value: 'NOT_CONTAINS' }, | ||
173 | + { label: '等于', value: 'EQUAL' }, | ||
174 | + { label: '不等于', value: 'NOT_EQUAL' }, | ||
175 | + { label: '大于', value: 'GREATER' }, | ||
176 | + { label: '小于', value: 'LESS' }, | ||
177 | + { label: '大于或等于', value: 'GREATER_OR_EQUAL' }, | ||
178 | + { label: '小于或等于', value: 'LESS_OR_EQUAL' }, | ||
179 | + ]; | ||
180 | + const findRuleByValue = findDay.find((f) => { | ||
181 | + if ( | ||
182 | + f.value == | ||
183 | + editEchoData.value.profileData?.alarms[0].createRules[getKey[0]].condition | ||
184 | + .condition[0].predicate.operation | ||
185 | + ) { | ||
186 | + return f.label; | ||
187 | + } | ||
188 | + }); | ||
189 | + const findClearRuleByValue = findDay.find((f) => { | ||
190 | + if ( | ||
191 | + f.value == | ||
192 | + editEchoData.value.profileData?.alarms[0].clearRule.condition.condition[0].predicate | ||
193 | + .operation | ||
194 | + ) { | ||
195 | + return f.label; | ||
196 | + } | ||
197 | + }); | ||
198 | + proxy.$refs.DeviceProfileStep3Ref.retryRulesFormDataFunc( | ||
199 | + ` | ||
200 | + 键名:${ | ||
201 | + editEchoData.value.profileData?.alarms[0].createRules[getKey[0]].condition | ||
202 | + .condition[0].key.key | ||
203 | + }...操作:${findRuleByValue?.label}...值:${ | ||
204 | + editEchoData.value.profileData?.alarms[0].createRules[getKey[0]].condition | ||
205 | + .condition[0].predicate.value.defaultValue | ||
206 | + } | ||
207 | + ` | ||
208 | + ); | ||
209 | + proxy.$refs.DeviceProfileStep3Ref.retryEnableFormDataFunc(`始终启用`); | ||
210 | + proxy.$refs.DeviceProfileStep3Ref.retryTemplateFormDataFunc( | ||
211 | + ` | ||
212 | + 报警详细信息:${ | ||
213 | + editEchoData.value.profileData?.alarms[0].createRules[getKey[0]].alarmDetails | ||
214 | + } | ||
215 | + ` | ||
216 | + ); | ||
217 | + //清除报警 | ||
218 | + proxy.$refs.DeviceProfileStep3Ref.retryRulesClearFormDataFunc( | ||
219 | + ` | ||
220 | + 键名:${editEchoData.value.profileData?.alarms[0].clearRule.condition.condition[0].key.key}...操作:${findClearRuleByValue?.label}...值:${editEchoData.value.profileData?.alarms[0].clearRule.condition.condition[0].predicate.value.defaultValue} | ||
221 | + ` | ||
222 | + ); | ||
223 | + proxy.$refs.DeviceProfileStep3Ref.retryEnableClearFormDataFunc(`始终启用`); | ||
224 | + proxy.$refs.DeviceProfileStep3Ref.retryTemplateClearFormDataFunc( | ||
225 | + ` | ||
226 | + 报警详细信息:${editEchoData.value.profileData?.alarms[0].clearRule.alarmDetails} | ||
227 | + ` | ||
228 | + ); | ||
229 | + } else { | ||
230 | + proxy.$refs.DeviceProfileStep3Ref.resetRegisterFormFunc(); | ||
231 | + proxy.$refs.DeviceProfileStep3Ref.resetRegisterFormHighSettingmFunc(); | ||
232 | + proxy.$refs.DeviceProfileStep3Ref.resetRegisterFormCreateAlarmFunc(); | ||
233 | + proxy.$refs.DeviceProfileStep3Ref.resetRulesFormDataFunc(); | ||
234 | + proxy.$refs.DeviceProfileStep3Ref.resetEnableFormDataFunc(); | ||
235 | + proxy.$refs.DeviceProfileStep3Ref.resetTemplateFormDataFunc(); | ||
236 | + proxy.$refs.DeviceProfileStep3Ref.resetRulesClearFormDataFunc(); | ||
237 | + proxy.$refs.DeviceProfileStep3Ref.resetEnableClearFormDataFunc(); | ||
238 | + proxy.$refs.DeviceProfileStep3Ref.resetTemplateClearFormDataFunc(); | ||
239 | + } | ||
153 | } | 240 | } |
154 | function handleStep3Next(v) { | 241 | function handleStep3Next(v) { |
155 | current.value++; | 242 | current.value++; |
156 | getStepThreeData.value = v; | 243 | getStepThreeData.value = v; |
244 | + try { | ||
245 | + if (unref(isUpdate)) { | ||
246 | + setTimeout(() => { | ||
247 | + proxy.$refs.DeviceProfileStep4Ref.resetFieldsFunc({ | ||
248 | + alarmContactId: editEchoData.value.alarmProfile.alarmContactId, | ||
249 | + messageMode: editEchoData.value.alarmProfile.messageMode, | ||
250 | + }); | ||
251 | + }, 1000); | ||
252 | + } | ||
253 | + // if (!unref(isUpdate)) { | ||
254 | + // setTimeout(() => { | ||
255 | + // proxy.$refs.DeviceProfileStep4Ref.customResetAndFunc(); | ||
256 | + // }, 1000); | ||
257 | + // } | ||
258 | + } catch (e) { | ||
259 | + return e; | ||
260 | + } | ||
157 | } | 261 | } |
158 | function handleRedo() { | 262 | function handleRedo() { |
159 | current.value = 0; | 263 | current.value = 0; |
@@ -197,6 +301,7 @@ | @@ -197,6 +301,7 @@ | ||
197 | return; | 301 | return; |
198 | }; | 302 | }; |
199 | return { | 303 | return { |
304 | + handleChange, | ||
200 | DeviceProfileStep2Ref, | 305 | DeviceProfileStep2Ref, |
201 | DeviceProfileStep3Ref, | 306 | DeviceProfileStep3Ref, |
202 | DeviceProfileStep4Ref, | 307 | DeviceProfileStep4Ref, |
@@ -2,8 +2,9 @@ import { BasicColumn } from '/@/components/Table'; | @@ -2,8 +2,9 @@ import { BasicColumn } from '/@/components/Table'; | ||
2 | import { FormSchema } from '/@/components/Table'; | 2 | import { FormSchema } from '/@/components/Table'; |
3 | import { findDictItemByCode } from '/@/api/system/dict'; | 3 | import { findDictItemByCode } from '/@/api/system/dict'; |
4 | import { MessageEnum } from '/@/enums/messageEnum'; | 4 | import { MessageEnum } from '/@/enums/messageEnum'; |
5 | -import { getOrganizationList } from '/@/api/system/system'; | ||
6 | -import { copyTransFun } from '/@/utils/fnUtils'; | 5 | +// import { getOrganizationList } from '/@/api/system/system'; |
6 | +// import { copyTransFun } from '/@/utils/fnUtils'; | ||
7 | +import { numberRule } from '/@/utils/rules'; | ||
7 | 8 | ||
8 | export const columns: BasicColumn[] = [ | 9 | export const columns: BasicColumn[] = [ |
9 | { | 10 | { |
@@ -30,23 +31,27 @@ export const columns: BasicColumn[] = [ | @@ -30,23 +31,27 @@ export const columns: BasicColumn[] = [ | ||
30 | 31 | ||
31 | export const searchFormSchema: FormSchema[] = [ | 32 | export const searchFormSchema: FormSchema[] = [ |
32 | { | 33 | { |
33 | - field: 'organizationId', | ||
34 | - label: '请选择组织', | ||
35 | - component: 'ApiTreeSelect', | ||
36 | - colProps: { span: 6 }, | ||
37 | - componentProps: { | ||
38 | - api: async () => { | ||
39 | - const data = await getOrganizationList(); | ||
40 | - copyTransFun(data as any as any[]); | ||
41 | - return data; | ||
42 | - }, | ||
43 | - }, | ||
44 | - }, | ||
45 | - { | ||
46 | field: 'name', | 34 | field: 'name', |
47 | label: '配置名称', | 35 | label: '配置名称', |
48 | component: 'Input', | 36 | component: 'Input', |
49 | colProps: { span: 8 }, | 37 | colProps: { span: 8 }, |
38 | + componentProps: { | ||
39 | + maxLength: 255, | ||
40 | + placeholder: '请输入配置名称', | ||
41 | + }, | ||
42 | + dynamicRules: () => { | ||
43 | + return [ | ||
44 | + { | ||
45 | + required: false, | ||
46 | + validator: (_, value) => { | ||
47 | + if (String(value).length > 255) { | ||
48 | + return Promise.reject('字数不超过255个字'); | ||
49 | + } | ||
50 | + return Promise.resolve(); | ||
51 | + }, | ||
52 | + }, | ||
53 | + ]; | ||
54 | + }, | ||
50 | }, | 55 | }, |
51 | ]; | 56 | ]; |
52 | 57 | ||
@@ -63,6 +68,10 @@ export const formSchema: FormSchema[] = [ | @@ -63,6 +68,10 @@ export const formSchema: FormSchema[] = [ | ||
63 | label: '配置名称', | 68 | label: '配置名称', |
64 | required: true, | 69 | required: true, |
65 | component: 'Input', | 70 | component: 'Input', |
71 | + componentProps: { | ||
72 | + maxLength: 255, | ||
73 | + placeholder: '请输入配置名称', | ||
74 | + }, | ||
66 | }, | 75 | }, |
67 | { | 76 | { |
68 | field: 'messageType', | 77 | field: 'messageType', |
@@ -98,6 +107,11 @@ export const formSchema: FormSchema[] = [ | @@ -98,6 +107,11 @@ export const formSchema: FormSchema[] = [ | ||
98 | label: 'accessKeyId', | 107 | label: 'accessKeyId', |
99 | required: true, | 108 | required: true, |
100 | component: 'Input', | 109 | component: 'Input', |
110 | + componentProps: { | ||
111 | + maxLength: 36, | ||
112 | + placeholder: '请输入accessKeyId', | ||
113 | + }, | ||
114 | + | ||
101 | ifShow: ({ values }) => isMessage(Reflect.get(values, 'messageType')), | 115 | ifShow: ({ values }) => isMessage(Reflect.get(values, 'messageType')), |
102 | }, | 116 | }, |
103 | { | 117 | { |
@@ -105,6 +119,11 @@ export const formSchema: FormSchema[] = [ | @@ -105,6 +119,11 @@ export const formSchema: FormSchema[] = [ | ||
105 | label: 'accessKeySecret', | 119 | label: 'accessKeySecret', |
106 | required: true, | 120 | required: true, |
107 | component: 'Input', | 121 | component: 'Input', |
122 | + componentProps: { | ||
123 | + maxLength: 36, | ||
124 | + placeholder: '请输入accessKeySecret', | ||
125 | + }, | ||
126 | + | ||
108 | ifShow: ({ values }) => isMessage(Reflect.get(values, 'messageType')), | 127 | ifShow: ({ values }) => isMessage(Reflect.get(values, 'messageType')), |
109 | }, | 128 | }, |
110 | { | 129 | { |
@@ -113,6 +132,11 @@ export const formSchema: FormSchema[] = [ | @@ -113,6 +132,11 @@ export const formSchema: FormSchema[] = [ | ||
113 | defaultValue: 'smtp.163.com', | 132 | defaultValue: 'smtp.163.com', |
114 | required: true, | 133 | required: true, |
115 | component: 'Input', | 134 | component: 'Input', |
135 | + componentProps: { | ||
136 | + maxLength: 36, | ||
137 | + placeholder: '请输入accessKeySecret', | ||
138 | + }, | ||
139 | + | ||
116 | ifShow: ({ values }) => isEmail(Reflect.get(values, 'messageType')), | 140 | ifShow: ({ values }) => isEmail(Reflect.get(values, 'messageType')), |
117 | }, | 141 | }, |
118 | { | 142 | { |
@@ -121,6 +145,12 @@ export const formSchema: FormSchema[] = [ | @@ -121,6 +145,12 @@ export const formSchema: FormSchema[] = [ | ||
121 | defaultValue: 25, | 145 | defaultValue: 25, |
122 | required: true, | 146 | required: true, |
123 | component: 'InputNumber', | 147 | component: 'InputNumber', |
148 | + rules: numberRule, | ||
149 | + componentProps: { | ||
150 | + maxLength: 36, | ||
151 | + placeholder: '请输入端口', | ||
152 | + }, | ||
153 | + | ||
124 | ifShow: ({ values }) => isEmail(Reflect.get(values, 'messageType')), | 154 | ifShow: ({ values }) => isEmail(Reflect.get(values, 'messageType')), |
125 | }, | 155 | }, |
126 | { | 156 | { |
@@ -128,6 +158,11 @@ export const formSchema: FormSchema[] = [ | @@ -128,6 +158,11 @@ export const formSchema: FormSchema[] = [ | ||
128 | label: '用户名', | 158 | label: '用户名', |
129 | required: true, | 159 | required: true, |
130 | component: 'Input', | 160 | component: 'Input', |
161 | + componentProps: { | ||
162 | + maxLength: 255, | ||
163 | + placeholder: '请输入用户名', | ||
164 | + }, | ||
165 | + | ||
131 | ifShow: ({ values }) => isEmail(Reflect.get(values, 'messageType')), | 166 | ifShow: ({ values }) => isEmail(Reflect.get(values, 'messageType')), |
132 | }, | 167 | }, |
133 | { | 168 | { |
@@ -142,12 +177,46 @@ export const formSchema: FormSchema[] = [ | @@ -142,12 +177,46 @@ export const formSchema: FormSchema[] = [ | ||
142 | label: '消息配置', | 177 | label: '消息配置', |
143 | component: 'Input', | 178 | component: 'Input', |
144 | show: false, | 179 | show: false, |
180 | + componentProps: { | ||
181 | + maxLength: 255, | ||
182 | + placeholder: '请输入消息配置', | ||
183 | + }, | ||
184 | + dynamicRules: () => { | ||
185 | + return [ | ||
186 | + { | ||
187 | + required: false, | ||
188 | + validator: (_, value) => { | ||
189 | + if (String(value).length > 255) { | ||
190 | + return Promise.reject('字数不超过255个字'); | ||
191 | + } | ||
192 | + return Promise.resolve(); | ||
193 | + }, | ||
194 | + }, | ||
195 | + ]; | ||
196 | + }, | ||
145 | }, | 197 | }, |
146 | { | 198 | { |
147 | field: 'id', | 199 | field: 'id', |
148 | label: '主键', | 200 | label: '主键', |
149 | component: 'Input', | 201 | component: 'Input', |
150 | show: false, | 202 | show: false, |
203 | + componentProps: { | ||
204 | + maxLength: 36, | ||
205 | + placeholder: '请输入主键', | ||
206 | + }, | ||
207 | + dynamicRules: () => { | ||
208 | + return [ | ||
209 | + { | ||
210 | + required: false, | ||
211 | + validator: (_, value) => { | ||
212 | + if (String(value).length > 36) { | ||
213 | + return Promise.reject('字数不超过36个字'); | ||
214 | + } | ||
215 | + return Promise.resolve(); | ||
216 | + }, | ||
217 | + }, | ||
218 | + ]; | ||
219 | + }, | ||
151 | }, | 220 | }, |
152 | { | 221 | { |
153 | field: 'status', | 222 | field: 'status', |
@@ -165,5 +234,22 @@ export const formSchema: FormSchema[] = [ | @@ -165,5 +234,22 @@ export const formSchema: FormSchema[] = [ | ||
165 | label: '备注', | 234 | label: '备注', |
166 | field: 'remark', | 235 | field: 'remark', |
167 | component: 'InputTextArea', | 236 | component: 'InputTextArea', |
237 | + componentProps: { | ||
238 | + maxLength: 255, | ||
239 | + placeholder: '请输入备注', | ||
240 | + }, | ||
241 | + dynamicRules: () => { | ||
242 | + return [ | ||
243 | + { | ||
244 | + required: false, | ||
245 | + validator: (_, value) => { | ||
246 | + if (String(value).length > 255) { | ||
247 | + return Promise.reject('字数不超过255个字'); | ||
248 | + } | ||
249 | + return Promise.resolve(); | ||
250 | + }, | ||
251 | + }, | ||
252 | + ]; | ||
253 | + }, | ||
168 | }, | 254 | }, |
169 | ]; | 255 | ]; |
@@ -21,65 +21,69 @@ | @@ -21,65 +21,69 @@ | ||
21 | /></TabPane> | 21 | /></TabPane> |
22 | <TabPane key="3" tab="报警规则"> | 22 | <TabPane key="3" tab="报警规则"> |
23 | <div style="padding-top: 10px"> | 23 | <div style="padding-top: 10px"> |
24 | - <div style="border-radius: 10px; border: 1px solid grey"> | ||
25 | - <BasicForm | ||
26 | - :showSubmitButton="false" | ||
27 | - :showResetButton="false" | ||
28 | - @register="registerStep3Schemas" | ||
29 | - /> | ||
30 | - <BasicForm | ||
31 | - :showSubmitButton="false" | ||
32 | - :showResetButton="false" | ||
33 | - @register="registerStep3HighSetting" | ||
34 | - /> | ||
35 | - <BasicForm | ||
36 | - :showSubmitButton="false" | ||
37 | - :showResetButton="false" | ||
38 | - @register="registerStep3CreateAlarm" | ||
39 | - /> | ||
40 | - <BasicForm | ||
41 | - :showSubmitButton="false" | ||
42 | - :showResetButton="false" | ||
43 | - @register="registerStep3RuleAlarm" | ||
44 | - /> | ||
45 | - <BasicForm | ||
46 | - :showSubmitButton="false" | ||
47 | - :showResetButton="false" | ||
48 | - @register="registerStep3Condition" | ||
49 | - /> | ||
50 | - <BasicForm | ||
51 | - :showSubmitButton="false" | ||
52 | - :showResetButton="false" | ||
53 | - @register="registerStep3Enable" | ||
54 | - /> | ||
55 | - <BasicForm | ||
56 | - :showSubmitButton="false" | ||
57 | - :showResetButton="false" | ||
58 | - @register="registerStep3TemplateDetail" | ||
59 | - /> | 24 | + <div style="border-radius: 10px; border: 1px solid #f0f0f0"> |
25 | + <div style="margin-left: 15px"> | ||
26 | + <BasicForm | ||
27 | + :showSubmitButton="false" | ||
28 | + :showResetButton="false" | ||
29 | + @register="registerStep3Schemas" | ||
30 | + /> | ||
31 | + <BasicForm | ||
32 | + :showSubmitButton="false" | ||
33 | + :showResetButton="false" | ||
34 | + @register="registerStep3HighSetting" | ||
35 | + /> | ||
36 | + <BasicForm | ||
37 | + :showSubmitButton="false" | ||
38 | + :showResetButton="false" | ||
39 | + @register="registerStep3CreateAlarm" | ||
40 | + /> | ||
41 | + <BasicForm | ||
42 | + :showSubmitButton="false" | ||
43 | + :showResetButton="false" | ||
44 | + @register="registerStep3RuleAlarm" | ||
45 | + /> | ||
46 | + <BasicForm | ||
47 | + :showSubmitButton="false" | ||
48 | + :showResetButton="false" | ||
49 | + @register="registerStep3Condition" | ||
50 | + /> | ||
51 | + <BasicForm | ||
52 | + :showSubmitButton="false" | ||
53 | + :showResetButton="false" | ||
54 | + @register="registerStep3Enable" | ||
55 | + /> | ||
56 | + <BasicForm | ||
57 | + :showSubmitButton="false" | ||
58 | + :showResetButton="false" | ||
59 | + @register="registerStep3TemplateDetail" | ||
60 | + /> | ||
61 | + </div> | ||
60 | </div> | 62 | </div> |
61 | - <div style="border-radius: 10px; border: 1px solid grey; margin-top: 15px"> | 63 | + <div style="border-radius: 10px; border: 1px solid #f0f0f0; margin-top: 15px"> |
62 | <p>清除报警规则</p> | 64 | <p>清除报警规则</p> |
63 | - <BasicForm | ||
64 | - :showSubmitButton="false" | ||
65 | - :showResetButton="false" | ||
66 | - @register="registerStep3ClearRuleAlarm" | ||
67 | - /> | ||
68 | - <BasicForm | ||
69 | - :showSubmitButton="false" | ||
70 | - :showResetButton="false" | ||
71 | - @register="registerStep3ClearCondition" | ||
72 | - /> | ||
73 | - <BasicForm | ||
74 | - :showSubmitButton="false" | ||
75 | - :showResetButton="false" | ||
76 | - @register="registerStep3ClearEnable" | ||
77 | - /> | ||
78 | - <BasicForm | ||
79 | - :showSubmitButton="false" | ||
80 | - :showResetButton="false" | ||
81 | - @register="registerStep3ClearTemplateDetail" | ||
82 | - /> | 65 | + <div style="margin-left: 15px"> |
66 | + <BasicForm | ||
67 | + :showSubmitButton="false" | ||
68 | + :showResetButton="false" | ||
69 | + @register="registerStep3ClearRuleAlarm" | ||
70 | + /> | ||
71 | + <BasicForm | ||
72 | + :showSubmitButton="false" | ||
73 | + :showResetButton="false" | ||
74 | + @register="registerStep3ClearCondition" | ||
75 | + /> | ||
76 | + <BasicForm | ||
77 | + :showSubmitButton="false" | ||
78 | + :showResetButton="false" | ||
79 | + @register="registerStep3ClearEnable" | ||
80 | + /> | ||
81 | + <BasicForm | ||
82 | + :showSubmitButton="false" | ||
83 | + :showResetButton="false" | ||
84 | + @register="registerStep3ClearTemplateDetail" | ||
85 | + /> | ||
86 | + </div> | ||
83 | </div> | 87 | </div> |
84 | </div> | 88 | </div> |
85 | </TabPane> | 89 | </TabPane> |
@@ -93,7 +97,7 @@ | @@ -93,7 +97,7 @@ | ||
93 | <script lang="ts"> | 97 | <script lang="ts"> |
94 | import { defineComponent, ref, computed, watch } from 'vue'; | 98 | import { defineComponent, ref, computed, watch } from 'vue'; |
95 | import { BasicModal, useModalInner } from '/@/components/Modal'; | 99 | import { BasicModal, useModalInner } from '/@/components/Modal'; |
96 | - import { Tabs, TabPane } from 'ant-design-vue'; | 100 | + import { Tabs } from 'ant-design-vue'; |
97 | import { deviceConfigGetDetail } from '/@/api/device/deviceConfigApi'; | 101 | import { deviceConfigGetDetail } from '/@/api/device/deviceConfigApi'; |
98 | import { BasicForm, useForm } from '/@/components/Form/index'; | 102 | import { BasicForm, useForm } from '/@/components/Form/index'; |
99 | import { | 103 | import { |
@@ -116,14 +120,14 @@ | @@ -116,14 +120,14 @@ | ||
116 | 120 | ||
117 | export default defineComponent({ | 121 | export default defineComponent({ |
118 | name: 'ConfigDrawer', | 122 | name: 'ConfigDrawer', |
119 | - components: { Tabs, TabPane, BasicModal, BasicForm }, | 123 | + components: { Tabs, TabPane: Tabs.TabPane, BasicModal, BasicForm }, |
120 | emits: ['success', 'register'], | 124 | emits: ['success', 'register'], |
121 | setup() { | 125 | setup() { |
122 | const activeKey = ref('1'); | 126 | const activeKey = ref('1'); |
123 | const isUpdate = ref(true); | 127 | const isUpdate = ref(true); |
124 | const descInfo: any = ref(null); | 128 | const descInfo: any = ref(null); |
125 | const dataInfo: any = ref(''); | 129 | const dataInfo: any = ref(''); |
126 | - const [registerDetail, { setFieldsValue: setRegisterDetail }] = useForm({ | 130 | + const [registerDetail, { resetFields, setFieldsValue: setRegisterDetail }] = useForm({ |
127 | schemas: step1Schemas, | 131 | schemas: step1Schemas, |
128 | actionColOptions: { | 132 | actionColOptions: { |
129 | span: 24, | 133 | span: 24, |
@@ -219,8 +223,10 @@ | @@ -219,8 +223,10 @@ | ||
219 | const [register] = useModalInner(async (data) => { | 223 | const [register] = useModalInner(async (data) => { |
220 | activeKey.value = '1'; | 224 | activeKey.value = '1'; |
221 | isUpdate.value = !!data?.isUpdate; | 225 | isUpdate.value = !!data?.isUpdate; |
222 | - descInfo.value = await deviceConfigGetDetail(data.record.id); | 226 | + const getV = await deviceConfigGetDetail(data.record.id); |
227 | + descInfo.value = getV; | ||
223 | try { | 228 | try { |
229 | + resetFields(); | ||
224 | await setRegisterDetail({ ...descInfo.value }); | 230 | await setRegisterDetail({ ...descInfo.value }); |
225 | } catch (e) { | 231 | } catch (e) { |
226 | return e; | 232 | return e; |
@@ -229,84 +235,90 @@ | @@ -229,84 +235,90 @@ | ||
229 | const handleChange = (v) => { | 235 | const handleChange = (v) => { |
230 | try { | 236 | try { |
231 | switch (v) { | 237 | switch (v) { |
232 | - case '1': | ||
233 | - setRegisterDetail({ ...descInfo.value }); | ||
234 | - break; | 238 | + // case '1': |
239 | + // setRegisterDetail({ ...descInfo.value }); | ||
240 | + // break; | ||
235 | case '2': | 241 | case '2': |
236 | setRegisterTrans({ | 242 | setRegisterTrans({ |
237 | transportType: descInfo.value.profileData?.transportConfiguration.type, | 243 | transportType: descInfo.value.profileData?.transportConfiguration.type, |
238 | }); | 244 | }); |
239 | break; | 245 | break; |
240 | case '3': | 246 | case '3': |
241 | - setRegisterStep3Schemas({ | ||
242 | - alarmType: descInfo.value.profileData?.alarms[0].alarmType, | ||
243 | - }); | ||
244 | - setRegisterStep3HighSetting({ | ||
245 | - propagate: descInfo.value.profileData?.alarms[0].propagate, | ||
246 | - propagateRelationTypes: | ||
247 | - descInfo.value.profileData?.alarms[0].propagateRelationTypes, | ||
248 | - }); | ||
249 | - const getKey = Object.keys(descInfo.value.profileData?.alarms[0].createRules); | ||
250 | - setRegisterStep3CreateAlarm({ | ||
251 | - default: getKey[0], | ||
252 | - }); | ||
253 | - setRegisterStep3RuleAlarm({ | ||
254 | - type: descInfo.value.profileData?.alarms[0].createRules[getKey[0]].condition | ||
255 | - .condition[0].key.type, | ||
256 | - key1: descInfo.value.profileData?.alarms[0].createRules[getKey[0]].condition | ||
257 | - .condition[0].key.key, | ||
258 | - type1: | ||
259 | - descInfo.value.profileData?.alarms[0].createRules[getKey[0]].condition | ||
260 | - .condition[0].valueType, | ||
261 | - value1: | ||
262 | - descInfo.value.profileData?.alarms[0].createRules[getKey[0]].condition | ||
263 | - .condition[0].predicate.value.defaultValue, | ||
264 | - operation: | ||
265 | - descInfo.value.profileData?.alarms[0].createRules[getKey[0]].condition | ||
266 | - .condition[0].predicate.operation, | ||
267 | - }); | ||
268 | - setRegisterStep3Condition({ | ||
269 | - conditionType: | ||
270 | - descInfo.value.profileData?.alarms[0].createRules[getKey[0]].condition.spec.type, | ||
271 | - }); | ||
272 | - setRegisterStep3Enable({ | ||
273 | - schedule: | ||
274 | - descInfo.value.profileData?.alarms[0].createRules[getKey[0]].schedule.type, | ||
275 | - }); | ||
276 | - setRegisterStep3TemplateDetail({ | ||
277 | - alarmDetails: | ||
278 | - descInfo.value.profileData?.alarms[0].createRules[getKey[0]].alarmDetails, | ||
279 | - }); | ||
280 | - //清楚报警 | ||
281 | - setRegisterStep3ClearRuleAlarm({ | ||
282 | - type: descInfo.value.profileData?.alarms[0].clearRule.condition.condition[0].key | ||
283 | - .type, | ||
284 | - key1: descInfo.value.profileData?.alarms[0].clearRule.condition.condition[0].key | ||
285 | - .key, | ||
286 | - type1: | ||
287 | - descInfo.value.profileData?.alarms[0].clearRule.condition.condition[0].valueType, | ||
288 | - value1: | ||
289 | - descInfo.value.profileData?.alarms[0].clearRule.condition.condition[0].predicate | ||
290 | - .value.defaultValue, | ||
291 | - operation: | ||
292 | - descInfo.value.profileData?.alarms[0].clearRule.condition.condition[0].predicate | ||
293 | - .operation, | ||
294 | - }); | ||
295 | - setRegisterStep3ClearCondition({ | ||
296 | - conditionType: descInfo.value.profileData?.alarms[0].clearRule.condition.spec.type, | ||
297 | - }); | ||
298 | - setRegisterStep3ClearEnable({ | ||
299 | - schedule: descInfo.value.profileData?.alarms[0].clearRule.schedule.type, | ||
300 | - }); | ||
301 | - setRegisterStep3ClearTemplateDetail({ | ||
302 | - alarmDetails: descInfo.value.profileData?.alarms[0].clearRule.alarmDetails, | ||
303 | - }); | ||
304 | - break; | 247 | + setTimeout(() => { |
248 | + setRegisterStep3Schemas({ | ||
249 | + alarmType: descInfo.value.profileData?.alarms[0]?.alarmType, | ||
250 | + }); | ||
251 | + setRegisterStep3HighSetting({ | ||
252 | + propagate: descInfo.value.profileData?.alarms[0]?.propagate, | ||
253 | + propagateRelationTypes: | ||
254 | + descInfo.value.profileData?.alarms[0]?.propagateRelationTypes, | ||
255 | + }); | ||
256 | + const getKey = Object.keys(descInfo.value.profileData?.alarms[0]?.createRules); | ||
257 | + setRegisterStep3CreateAlarm({ | ||
258 | + default: getKey[0], | ||
259 | + }); | ||
260 | + setRegisterStep3RuleAlarm({ | ||
261 | + type: descInfo.value.profileData?.alarms[0].createRules[getKey[0]].condition | ||
262 | + .condition[0].key.type, | ||
263 | + key1: descInfo.value.profileData?.alarms[0].createRules[getKey[0]].condition | ||
264 | + .condition[0].key.key, | ||
265 | + type1: | ||
266 | + descInfo.value.profileData?.alarms[0].createRules[getKey[0]].condition | ||
267 | + .condition[0].valueType, | ||
268 | + value1: | ||
269 | + descInfo.value.profileData?.alarms[0].createRules[getKey[0]].condition | ||
270 | + .condition[0].predicate.value.defaultValue, | ||
271 | + operation: | ||
272 | + descInfo.value.profileData?.alarms[0].createRules[getKey[0]].condition | ||
273 | + .condition[0].predicate.operation, | ||
274 | + }); | ||
275 | + setRegisterStep3Condition({ | ||
276 | + conditionType: | ||
277 | + descInfo.value.profileData?.alarms[0].createRules[getKey[0]].condition.spec | ||
278 | + .type, | ||
279 | + }); | ||
280 | + setRegisterStep3Enable({ | ||
281 | + schedule: | ||
282 | + descInfo.value.profileData?.alarms[0].createRules[getKey[0]].schedule.type, | ||
283 | + }); | ||
284 | + setRegisterStep3TemplateDetail({ | ||
285 | + alarmDetails: | ||
286 | + descInfo.value.profileData?.alarms[0].createRules[getKey[0]].alarmDetails, | ||
287 | + }); | ||
288 | + //清除报警 | ||
289 | + setRegisterStep3ClearRuleAlarm({ | ||
290 | + type: descInfo.value.profileData?.alarms[0].clearRule.condition.condition[0].key | ||
291 | + .type, | ||
292 | + key1: descInfo.value.profileData?.alarms[0].clearRule.condition.condition[0].key | ||
293 | + .key, | ||
294 | + type1: | ||
295 | + descInfo.value.profileData?.alarms[0].clearRule.condition.condition[0] | ||
296 | + .valueType, | ||
297 | + value1: | ||
298 | + descInfo.value.profileData?.alarms[0].clearRule.condition.condition[0].predicate | ||
299 | + .value.defaultValue, | ||
300 | + operation: | ||
301 | + descInfo.value.profileData?.alarms[0].clearRule.condition.condition[0].predicate | ||
302 | + .operation, | ||
303 | + }); | ||
304 | + setRegisterStep3ClearCondition({ | ||
305 | + conditionType: | ||
306 | + descInfo.value.profileData?.alarms[0].clearRule.condition.spec.type, | ||
307 | + }); | ||
308 | + setRegisterStep3ClearEnable({ | ||
309 | + schedule: descInfo.value.profileData?.alarms[0].clearRule.schedule.type, | ||
310 | + }); | ||
311 | + setRegisterStep3ClearTemplateDetail({ | ||
312 | + alarmDetails: descInfo.value.profileData?.alarms[0].clearRule.alarmDetails, | ||
313 | + }); | ||
314 | + }, 1000); | ||
305 | case '4': | 315 | case '4': |
306 | - setRegisterContact({ | ||
307 | - alarmContactId: descInfo.value.alarmProfile.alarmContactId, | ||
308 | - messageMode: descInfo.value.alarmProfile.messageMode, | ||
309 | - }); | 316 | + setTimeout(() => { |
317 | + setRegisterContact({ | ||
318 | + alarmContactId: descInfo.value?.alarmProfile?.alarmContactId, | ||
319 | + messageMode: descInfo.value?.alarmProfile?.messageMode, | ||
320 | + }); | ||
321 | + }, 1000); | ||
310 | break; | 322 | break; |
311 | } | 323 | } |
312 | } catch (e) { | 324 | } catch (e) { |
@@ -45,12 +45,12 @@ | @@ -45,12 +45,12 @@ | ||
45 | </BasicTable> | 45 | </BasicTable> |
46 | <DeviceProfileModal v-if="isJudgeStatus" @register="registerModal" @success="handleSuccess" /> | 46 | <DeviceProfileModal v-if="isJudgeStatus" @register="registerModal" @success="handleSuccess" /> |
47 | <DeviceConfigDetail @register="registerModalDetail" @success="handleSuccess" /> | 47 | <DeviceConfigDetail @register="registerModalDetail" @success="handleSuccess" /> |
48 | - <ExpExcelModal @register="register1" @success="defaultHeader" /> | 48 | + <!-- <ExpExcelModal @register="register1" @success="defaultHeader" /> --> |
49 | </div> | 49 | </div> |
50 | </template> | 50 | </template> |
51 | <script lang="ts"> | 51 | <script lang="ts"> |
52 | import { defineComponent, ref, reactive } from 'vue'; | 52 | import { defineComponent, ref, reactive } from 'vue'; |
53 | - import { BasicTable, useTable, TableAction } from '/@/components/Table'; | 53 | + import { BasicTable, useTable, TableAction, BasicColumn } from '/@/components/Table'; |
54 | import { columns, searchFormSchema } from './device.profile.data'; | 54 | import { columns, searchFormSchema } from './device.profile.data'; |
55 | import { useMessage } from '/@/hooks/web/useMessage'; | 55 | import { useMessage } from '/@/hooks/web/useMessage'; |
56 | import { deviceConfigGetQuery, deviceConfigDelete } from '/@/api/device/deviceConfigApi'; | 56 | import { deviceConfigGetQuery, deviceConfigDelete } from '/@/api/device/deviceConfigApi'; |
@@ -58,7 +58,7 @@ | @@ -58,7 +58,7 @@ | ||
58 | import DeviceProfileModal from '/@/views/device/profile/DeviceProfileModal.vue'; | 58 | import DeviceProfileModal from '/@/views/device/profile/DeviceProfileModal.vue'; |
59 | import DeviceConfigDetail from '/@/views/device/profile/deviceConfigDetail.vue'; | 59 | import DeviceConfigDetail from '/@/views/device/profile/deviceConfigDetail.vue'; |
60 | import { ImpExcel, ExcelData } from '/@/components/Excel'; | 60 | import { ImpExcel, ExcelData } from '/@/components/Excel'; |
61 | - import { jsonToSheetXlsx, ExportModalResult } from '/@/components/Excel'; | 61 | + // import { jsonToSheetXlsx, ExportModalResult } from '/@/components/Excel'; |
62 | 62 | ||
63 | export default defineComponent({ | 63 | export default defineComponent({ |
64 | name: 'DeviceProfileManagement', | 64 | name: 'DeviceProfileManagement', |
@@ -156,23 +156,23 @@ | @@ -156,23 +156,23 @@ | ||
156 | isJudgeStatus.value = false; | 156 | isJudgeStatus.value = false; |
157 | } | 157 | } |
158 | 158 | ||
159 | - function defaultHeader({ filename, bookType }: ExportModalResult) { | ||
160 | - // 默认Object.keys(data[0])作为header | ||
161 | - jsonToSheetXlsx({ | ||
162 | - data, | ||
163 | - filename, | ||
164 | - write2excelOpts: { | ||
165 | - bookType, | ||
166 | - }, | ||
167 | - }); | ||
168 | - } | 159 | + // function defaultHeader({ filename, bookType }: ExportModalResult) { |
160 | + // // 默认Object.keys(data[0])作为header | ||
161 | + // jsonToSheetXlsx({ | ||
162 | + // data, | ||
163 | + // filename, | ||
164 | + // write2excelOpts: { | ||
165 | + // bookType, | ||
166 | + // }, | ||
167 | + // }); | ||
168 | + // } | ||
169 | 169 | ||
170 | - const [register1, { openModal: openModalExcel }] = useModal(); | 170 | + // const [register1, { openModal: openModalExcel }] = useModal(); |
171 | const handleExport = (record: Recordable) => { | 171 | const handleExport = (record: Recordable) => { |
172 | console.log(record); | 172 | console.log(record); |
173 | - setTimeout(() => { | ||
174 | - openModalExcel(); | ||
175 | - }, 50); | 173 | + // setTimeout(() => { |
174 | + // openModalExcel(); | ||
175 | + // }, 50); | ||
176 | }; | 176 | }; |
177 | function handleImport() { | 177 | function handleImport() { |
178 | console.log('record'); | 178 | console.log('record'); |
@@ -182,8 +182,8 @@ | @@ -182,8 +182,8 @@ | ||
182 | } | 182 | } |
183 | return { | 183 | return { |
184 | registerModalDetail, | 184 | registerModalDetail, |
185 | - register1, | ||
186 | - defaultHeader, | 185 | + // register1, |
186 | + // defaultHeader, | ||
187 | useSelectionChange, | 187 | useSelectionChange, |
188 | handleTableDel, | 188 | handleTableDel, |
189 | isJudgeStatus, | 189 | isJudgeStatus, |
1 | <template> | 1 | <template> |
2 | <div class="step1"> | 2 | <div class="step1"> |
3 | <div class="step1-form"> | 3 | <div class="step1-form"> |
4 | + <div | ||
5 | + style=" | ||
6 | + width: 12vw; | ||
7 | + height: 24vh; | ||
8 | + margin-left: 25px; | ||
9 | + display: flex; | ||
10 | + justify-content: space-between; | ||
11 | + align-items: center; | ||
12 | + " | ||
13 | + > | ||
14 | + <div style="width: 4vw; height: 24vh">请上传图片</div> | ||
15 | + <div style="width: 8vw; height: 24vh"> | ||
16 | + <Upload | ||
17 | + style="width: 20vw" | ||
18 | + name="avatar" | ||
19 | + list-type="picture-card" | ||
20 | + class="avatar-uploader" | ||
21 | + :show-upload-list="false" | ||
22 | + :customRequest="customUploadqrcodePic" | ||
23 | + :before-upload="beforeUploadqrcodePic" | ||
24 | + > | ||
25 | + <img | ||
26 | + style="text-align: center; border-radius: 50%; width: 10vw; height: 15vh" | ||
27 | + v-if="peresonalPic" | ||
28 | + :src="peresonalPic" | ||
29 | + alt="avatar" | ||
30 | + /> | ||
31 | + <div v-else> | ||
32 | + <div style="margin-top: 30px"> | ||
33 | + <PlusOutlined style="font-size: 30px" /> | ||
34 | + </div> | ||
35 | + <div | ||
36 | + class="ant-upload-text flex" | ||
37 | + style="width: 280px; height: 130px; align-items: center" | ||
38 | + > | ||
39 | + 支持.PNG、.JPG、.JPEG格式,建议大小不超过2M。</div | ||
40 | + > | ||
41 | + </div> | ||
42 | + </Upload> | ||
43 | + </div> | ||
44 | + </div> | ||
4 | <BasicForm @register="register" /> | 45 | <BasicForm @register="register" /> |
5 | </div> | 46 | </div> |
6 | </div> | 47 | </div> |
7 | </template> | 48 | </template> |
8 | <script lang="ts"> | 49 | <script lang="ts"> |
9 | - import { defineComponent } from 'vue'; | 50 | + import { defineComponent, ref } from 'vue'; |
10 | import { BasicForm, useForm } from '/@/components/Form'; | 51 | import { BasicForm, useForm } from '/@/components/Form'; |
11 | import { step1Schemas } from './data'; | 52 | import { step1Schemas } from './data'; |
12 | import { Select, Input, Divider } from 'ant-design-vue'; | 53 | import { Select, Input, Divider } from 'ant-design-vue'; |
54 | + import { uploadApi } from '/@/api/personal/index'; | ||
55 | + import { Upload } from 'ant-design-vue'; | ||
56 | + import { PlusOutlined } from '@ant-design/icons-vue'; | ||
57 | + import { useMessage } from '/@/hooks/web/useMessage'; | ||
58 | + import type { FileItem } from '/@/components/Upload/src/typing'; | ||
13 | 59 | ||
14 | export default defineComponent({ | 60 | export default defineComponent({ |
15 | components: { | 61 | components: { |
@@ -18,9 +64,13 @@ | @@ -18,9 +64,13 @@ | ||
18 | [Input.name]: Input, | 64 | [Input.name]: Input, |
19 | [Input.Group.name]: Input.Group, | 65 | [Input.Group.name]: Input.Group, |
20 | [Divider.name]: Divider, | 66 | [Divider.name]: Divider, |
67 | + Upload, | ||
68 | + PlusOutlined, | ||
21 | }, | 69 | }, |
22 | emits: ['next', 'resetFunc'], | 70 | emits: ['next', 'resetFunc'], |
23 | setup(_, { emit }) { | 71 | setup(_, { emit }) { |
72 | + const { createMessage } = useMessage(); | ||
73 | + | ||
24 | const [register, { validate, setFieldsValue, resetFields }] = useForm({ | 74 | const [register, { validate, setFieldsValue, resetFields }] = useForm({ |
25 | labelWidth: 100, | 75 | labelWidth: 100, |
26 | schemas: step1Schemas, | 76 | schemas: step1Schemas, |
@@ -36,16 +86,59 @@ | @@ -36,16 +86,59 @@ | ||
36 | const resetFieldsFunc = (v) => { | 86 | const resetFieldsFunc = (v) => { |
37 | setFieldsValue(v); | 87 | setFieldsValue(v); |
38 | }; | 88 | }; |
89 | + const peresonalPic = ref(); | ||
90 | + | ||
91 | + const resetIconFunc = () => { | ||
92 | + peresonalPic.value = ''; | ||
93 | + }; | ||
94 | + | ||
95 | + const editIconFunc = (v) => { | ||
96 | + peresonalPic.value = v; | ||
97 | + }; | ||
98 | + | ||
99 | + const customUploadqrcodePic = async ({ file }) => { | ||
100 | + if (beforeUploadqrcodePic(file)) { | ||
101 | + const formData = new FormData(); | ||
102 | + formData.append('file', file); | ||
103 | + const response = await uploadApi(formData); | ||
104 | + if (response.fileStaticUri) { | ||
105 | + peresonalPic.value = response.fileStaticUri; | ||
106 | + } | ||
107 | + } | ||
108 | + }; | ||
109 | + | ||
110 | + const beforeUploadqrcodePic = (file: FileItem) => { | ||
111 | + const isJpgOrPng = | ||
112 | + file.type === 'image/jpeg' || file.type === 'image/png' || file.type === 'image/jpg'; | ||
113 | + if (!isJpgOrPng) { | ||
114 | + createMessage.error('只能上传图片文件!'); | ||
115 | + } | ||
116 | + const isLt2M = (file.size as number) / 1024 / 1024 < 2; | ||
117 | + if (!isLt2M) { | ||
118 | + createMessage.error('图片大小不能超过5MB!'); | ||
119 | + } | ||
120 | + return isJpgOrPng && isLt2M; | ||
121 | + }; | ||
39 | async function customSubmitFunc() { | 122 | async function customSubmitFunc() { |
40 | try { | 123 | try { |
41 | const values = await validate(); | 124 | const values = await validate(); |
42 | - emit('next', values); | 125 | + emit('next', values, peresonalPic.value); |
43 | } catch (error) {} | 126 | } catch (error) {} |
44 | } | 127 | } |
45 | const customResetFunc = async () => { | 128 | const customResetFunc = async () => { |
46 | await resetFields(); | 129 | await resetFields(); |
47 | }; | 130 | }; |
48 | - return { register, resetFieldsFunc, customResetFunc }; | 131 | + return { |
132 | + editIconFunc, | ||
133 | + resetIconFunc, | ||
134 | + register, | ||
135 | + resetFieldsFunc, | ||
136 | + customResetFunc, | ||
137 | + uploadApi, | ||
138 | + peresonalPic, | ||
139 | + beforeUploadqrcodePic, | ||
140 | + customUploadqrcodePic, | ||
141 | + }; | ||
49 | }, | 142 | }, |
50 | }); | 143 | }); |
51 | </script> | 144 | </script> |
@@ -31,7 +31,7 @@ | @@ -31,7 +31,7 @@ | ||
31 | <template v-for="(childItem, createIndex) in item.alarms" :key="childItem.id"> | 31 | <template v-for="(childItem, createIndex) in item.alarms" :key="childItem.id"> |
32 | <div class="aic" style="border: 1px solid #bfbfbf"> | 32 | <div class="aic" style="border: 1px solid #bfbfbf"> |
33 | <div class="w-3/4"> | 33 | <div class="w-3/4"> |
34 | - <div style="margin-left: -30px; margin-top: 20px" | 34 | + <div style="margin-left: -33px; margin-top: 20px" |
35 | ><BasicForm @register="registerFormCreateAlarm" /> | 35 | ><BasicForm @register="registerFormCreateAlarm" /> |
36 | </div> | 36 | </div> |
37 | <div style="margin-left: 5px; margin-top: -50px"> | 37 | <div style="margin-left: 5px; margin-top: -50px"> |
@@ -78,7 +78,7 @@ | @@ -78,7 +78,7 @@ | ||
78 | <div style="height: 20px"></div> | 78 | <div style="height: 20px"></div> |
79 | <p>清除报警规则</p> | 79 | <p>清除报警规则</p> |
80 | <template | 80 | <template |
81 | - v-for="(childClearItem, clearIndexItem) in item.alarms[clearIndex].clearRule" | 81 | + v-for="(childClearItem, clearIndexItem) in item.clearRule" |
82 | :key="childClearItem.id" | 82 | :key="childClearItem.id" |
83 | > | 83 | > |
84 | <div class="aic mb-1" style="border: 1px solid #bfbfbf"> | 84 | <div class="aic mb-1" style="border: 1px solid #bfbfbf"> |
@@ -222,12 +222,20 @@ | @@ -222,12 +222,20 @@ | ||
222 | const ruleClearTemplateData: any = ref(null); | 222 | const ruleClearTemplateData: any = ref(null); |
223 | const enableClearTemplateData: any = ref(null); | 223 | const enableClearTemplateData: any = ref(null); |
224 | const detailClearTemplateData: any = ref(null); | 224 | const detailClearTemplateData: any = ref(null); |
225 | + const scheduleCustomValue: any = ref({}); | ||
226 | + const scheduleCustomClearValue: any = ref({}); | ||
225 | const clearIndex = ref(-1); | 227 | const clearIndex = ref(-1); |
228 | + const getSchduleCustomValue: any = ref([]); | ||
229 | + const getSchduleClearCustomValue: any = ref([]); | ||
226 | //告警列表 | 230 | //告警列表 |
227 | let profileData = ref<IProfileData[]>([]); | 231 | let profileData = ref<IProfileData[]>([]); |
228 | const log = (e) => { | 232 | const log = (e) => { |
229 | console.log(e); | 233 | console.log(e); |
230 | }; | 234 | }; |
235 | + //编辑清空操作 | ||
236 | + const clearProfileDataFunc = () => { | ||
237 | + unref(profileData).splice(0, 1); | ||
238 | + }; | ||
231 | //删除告警配置 | 239 | //删除告警配置 |
232 | const deleteAlarmRule = (index: number) => { | 240 | const deleteAlarmRule = (index: number) => { |
233 | unref(profileData).splice(index, 1); | 241 | unref(profileData).splice(index, 1); |
@@ -254,26 +262,27 @@ | @@ -254,26 +262,27 @@ | ||
254 | id: Date.now() + Math.random() + '', | 262 | id: Date.now() + Math.random() + '', |
255 | alarmType: '', | 263 | alarmType: '', |
256 | createRules: {}, | 264 | createRules: {}, |
257 | - clearRule: [ | ||
258 | - { | ||
259 | - id: Date.now() + Math.random() + '', | ||
260 | - alarmDetails: '', | ||
261 | - dashboardId: { | ||
262 | - id: '', | ||
263 | - entityType: '', | ||
264 | - }, | ||
265 | - propagate: '', | ||
266 | - propagateRelationTypes: [''], | ||
267 | - schedule: { | ||
268 | - type: 'string', | ||
269 | - }, | ||
270 | - condition: {}, | ||
271 | - }, | ||
272 | - ], | 265 | + |
273 | propagate: false, | 266 | propagate: false, |
274 | propagateRelationTypes: [''], | 267 | propagateRelationTypes: [''], |
275 | }, | 268 | }, |
276 | ], | 269 | ], |
270 | + clearRule: [ | ||
271 | + { | ||
272 | + id: Date.now() + Math.random() + '', | ||
273 | + alarmDetails: '', | ||
274 | + dashboardId: { | ||
275 | + id: '', | ||
276 | + entityType: '', | ||
277 | + }, | ||
278 | + propagate: '', | ||
279 | + propagateRelationTypes: [''], | ||
280 | + schedule: { | ||
281 | + type: 'string', | ||
282 | + }, | ||
283 | + condition: {}, | ||
284 | + }, | ||
285 | + ], | ||
277 | }); | 286 | }); |
278 | }; | 287 | }; |
279 | //TODO Mobile dashboard: | 288 | //TODO Mobile dashboard: |
@@ -342,6 +351,25 @@ | @@ -342,6 +351,25 @@ | ||
342 | const resetRegisterFormCreateAlarmFunc = () => { | 351 | const resetRegisterFormCreateAlarmFunc = () => { |
343 | resetRegisterFormCreateAlarm(); | 352 | resetRegisterFormCreateAlarm(); |
344 | }; | 353 | }; |
354 | + const resetRulesFormDataFunc = () => { | ||
355 | + ruleTemplateData.value = ``; | ||
356 | + }; | ||
357 | + const resetEnableFormDataFunc = () => { | ||
358 | + enableTemplateData.value = ``; | ||
359 | + }; | ||
360 | + const resetTemplateFormDataFunc = () => { | ||
361 | + detailTemplateData.value = ``; | ||
362 | + }; | ||
363 | + const resetRulesClearFormDataFunc = () => { | ||
364 | + ruleClearTemplateData.value = ``; | ||
365 | + }; | ||
366 | + const resetEnableClearFormDataFunc = () => { | ||
367 | + enableClearTemplateData.value = ``; | ||
368 | + }; | ||
369 | + const resetTemplateClearFormDataFunc = () => { | ||
370 | + detailClearTemplateData.value = ``; | ||
371 | + }; | ||
372 | + | ||
345 | //回显表单数据 | 373 | //回显表单数据 |
346 | const retryRegisterFormFunc = (v) => { | 374 | const retryRegisterFormFunc = (v) => { |
347 | setRegisterForm(v); | 375 | setRegisterForm(v); |
@@ -352,6 +380,25 @@ | @@ -352,6 +380,25 @@ | ||
352 | const retryRegisterFormCreateAlarmFunc = (v) => { | 380 | const retryRegisterFormCreateAlarmFunc = (v) => { |
353 | setRegisterFormCreateAlarm(v); | 381 | setRegisterFormCreateAlarm(v); |
354 | }; | 382 | }; |
383 | + const retryRulesFormDataFunc = (v) => { | ||
384 | + ruleTemplateData.value = v; | ||
385 | + }; | ||
386 | + const retryEnableFormDataFunc = (v) => { | ||
387 | + enableTemplateData.value = v; | ||
388 | + }; | ||
389 | + const retryTemplateFormDataFunc = (v) => { | ||
390 | + detailTemplateData.value = v; | ||
391 | + }; | ||
392 | + const retryRulesClearFormDataFunc = (v) => { | ||
393 | + ruleClearTemplateData.value = v; | ||
394 | + }; | ||
395 | + const retryEnableClearFormDataFunc = (v) => { | ||
396 | + enableClearTemplateData.value = v; | ||
397 | + }; | ||
398 | + const retryTemplateClearFormDataFunc = (v) => { | ||
399 | + detailClearTemplateData.value = v; | ||
400 | + }; | ||
401 | + | ||
355 | const tempValue1: string = ref<string>(''); | 402 | const tempValue1: string = ref<string>(''); |
356 | // 添加‘创建条件’ | 403 | // 添加‘创建条件’ |
357 | const addCreateRole = (index: number) => { | 404 | const addCreateRole = (index: number) => { |
@@ -400,27 +447,26 @@ | @@ -400,27 +447,26 @@ | ||
400 | }; | 447 | }; |
401 | }, | 448 | }, |
402 | }); | 449 | }); |
403 | - | ||
404 | unref(profileData)[index].alarms.push({ | 450 | unref(profileData)[index].alarms.push({ |
405 | id: Date.now() + Math.random() + '', | 451 | id: Date.now() + Math.random() + '', |
406 | alarmType: '', | 452 | alarmType: '', |
407 | createRules: {}, | 453 | createRules: {}, |
408 | - clearRule: [ | ||
409 | - { | ||
410 | - id: Date.now() + Math.random() + '', | ||
411 | - alarmDetails: '', | ||
412 | - dashboardId: { | ||
413 | - id: '', | ||
414 | - entityType: '', | ||
415 | - }, | ||
416 | - propagate: '', | ||
417 | - propagateRelationTypes: [''], | ||
418 | - schedule: { | ||
419 | - type: 'string', | ||
420 | - }, | ||
421 | - condition: {}, | ||
422 | - }, | ||
423 | - ], | 454 | + // clearRule: [ |
455 | + // { | ||
456 | + // id: Date.now() + Math.random() + '', | ||
457 | + // alarmDetails: '', | ||
458 | + // dashboardId: { | ||
459 | + // id: '', | ||
460 | + // entityType: '', | ||
461 | + // }, | ||
462 | + // propagate: '', | ||
463 | + // propagateRelationTypes: [''], | ||
464 | + // schedule: { | ||
465 | + // type: 'string', | ||
466 | + // }, | ||
467 | + // condition: {}, | ||
468 | + // }, | ||
469 | + // ], | ||
424 | propagate: false, | 470 | propagate: false, |
425 | propagateRelationTypes: [''], | 471 | propagateRelationTypes: [''], |
426 | }); | 472 | }); |
@@ -486,12 +532,23 @@ | @@ -486,12 +532,23 @@ | ||
486 | console.log(e); | 532 | console.log(e); |
487 | } | 533 | } |
488 | }); | 534 | }); |
535 | + const findDayCustomByValue = findDay.map((f, i) => { | ||
536 | + try { | ||
537 | + if (f.value == v.daysOfWeek1[i]) { | ||
538 | + return f.label; | ||
539 | + } | ||
540 | + } catch (e) { | ||
541 | + console.log(e); | ||
542 | + } | ||
543 | + }); | ||
489 | enableTemplateData.value = | 544 | enableTemplateData.value = |
490 | - v.startsOn == undefined | 545 | + v.schedule == 'ANY_TIME' |
491 | ? `始终启用` | 546 | ? `始终启用` |
492 | - : ` | 547 | + : v.schedule == 'SPECIFIC_TIME' |
548 | + ? ` | ||
493 | 开始时间:${v.startsOn},结束时间:${v.endsOn},天数:${findDayByValue} | 549 | 开始时间:${v.startsOn},结束时间:${v.endsOn},天数:${findDayByValue} |
494 | - `; | 550 | + ` |
551 | + : `天数:${findDayCustomByValue},开始时间: ${v.startsOn1},结束时间:${v.endsOn1}`; | ||
495 | }; | 552 | }; |
496 | //规则条件 | 553 | //规则条件 |
497 | const getAllFieldsRuleFunc = (v, v1) => { | 554 | const getAllFieldsRuleFunc = (v, v1) => { |
@@ -516,7 +573,7 @@ | @@ -516,7 +573,7 @@ | ||
516 | } | 573 | } |
517 | }); | 574 | }); |
518 | ruleTemplateData.value = ` | 575 | ruleTemplateData.value = ` |
519 | - 键名:${v.key1}...操作:${findRuleByValue?.label}...值:${v.value1} | 576 | + 键名:${v.key1} 操作:${findRuleByValue?.label} 值:${v.value1} |
520 | `; | 577 | `; |
521 | 578 | ||
522 | ruleLastObj.value = v1; | 579 | ruleLastObj.value = v1; |
@@ -607,11 +664,23 @@ | @@ -607,11 +664,23 @@ | ||
607 | console.log(e); | 664 | console.log(e); |
608 | } | 665 | } |
609 | }); | 666 | }); |
667 | + const findDayCustomByValue = findDay.map((f, i) => { | ||
668 | + try { | ||
669 | + if (f.value == v.daysOfWeek1[i]) { | ||
670 | + return f.label; | ||
671 | + } | ||
672 | + } catch (e) { | ||
673 | + console.log(e); | ||
674 | + } | ||
675 | + }); | ||
610 | enableClearTemplateData.value = | 676 | enableClearTemplateData.value = |
611 | - v.startsOn == undefined | 677 | + v.schedule == 'ANY_TIME' |
612 | ? `始终启用` | 678 | ? `始终启用` |
613 | - : `开始时间:${v.startsOn},结束时间:${v.endsOn},天数:${findDayByValue} | ||
614 | - `; | 679 | + : v.schedule == 'SPECIFIC_TIME' |
680 | + ? ` | ||
681 | + 开始时间:${v.startsOn},结束时间:${v.endsOn},天数:${findDayByValue} | ||
682 | + ` | ||
683 | + : `天数:${findDayCustomByValue},开始时间: ${v.startsOn1},结束时间:${v.endsOn1}`; | ||
615 | }; | 684 | }; |
616 | //规则条件 | 685 | //规则条件 |
617 | const getAllClearFieldsRuleFunc = (v, v1) => { | 686 | const getAllClearFieldsRuleFunc = (v, v1) => { |
@@ -636,7 +705,7 @@ | @@ -636,7 +705,7 @@ | ||
636 | } | 705 | } |
637 | }); | 706 | }); |
638 | ruleClearTemplateData.value = ` | 707 | ruleClearTemplateData.value = ` |
639 | - 键名:${v.key1}...操作:${findRuleByValue?.label}...值:${v.value1} | 708 | + 键名:${v.key1} 操作:${findRuleByValue?.label} 值:${v.value1} |
640 | `; | 709 | `; |
641 | 710 | ||
642 | ruleLastObj.value = v1; | 711 | ruleLastObj.value = v1; |
@@ -677,7 +746,7 @@ | @@ -677,7 +746,7 @@ | ||
677 | }; | 746 | }; |
678 | Object.assign(addClearitionalObj.value, getValueConditon); | 747 | Object.assign(addClearitionalObj.value, getValueConditon); |
679 | }; | 748 | }; |
680 | - //用于生成uuid | 749 | + //生成uuid |
681 | function generateUUID() { | 750 | function generateUUID() { |
682 | let d = new Date().getTime(); | 751 | let d = new Date().getTime(); |
683 | if (window.performance && typeof window.performance.now === 'function') { | 752 | if (window.performance && typeof window.performance.now === 'function') { |
@@ -691,28 +760,111 @@ | @@ -691,28 +760,111 @@ | ||
691 | return uuid; | 760 | return uuid; |
692 | } | 761 | } |
693 | const handleFormStep3toStep4Next = async () => { | 762 | const handleFormStep3toStep4Next = async () => { |
763 | + console.log(enableObj.value); | ||
694 | try { | 764 | try { |
765 | + if (enableObj.value.schedule == 'CUSTOM') { | ||
766 | + for (let i in enableObj.value) { | ||
767 | + console.log(enableObj.value[i]); | ||
768 | + console.log(i); | ||
769 | + // let o = {}; | ||
770 | + // if(enableObj.value[i]=='1') | ||
771 | + // o[i] = enableObj.value[i]; | ||
772 | + // getSchduleCustomValue.value.push(o); | ||
773 | + // getSchduleCustomValue.value.push(enableObj.value[i]); | ||
774 | + } | ||
775 | + console.log(getSchduleCustomValue.value); | ||
776 | + // switch (enableObj.value.daysOfWeek1[0]) { | ||
777 | + // case '1': | ||
778 | + // getSchduleCustomValue.value.push({ | ||
779 | + // enabled: true, | ||
780 | + // dayOfWeek: enableObj.value.daysOfWeek1[0], | ||
781 | + // startsOn: enableObj.value.startsOn1, | ||
782 | + // endsOn: enableObj.value.endsOn1, | ||
783 | + // }); | ||
784 | + // break; | ||
785 | + // case '2': | ||
786 | + // getSchduleCustomValue.value.push({ | ||
787 | + // enabled: true, | ||
788 | + // dayOfWeek: enableObj.value.daysOfWeek2[0], | ||
789 | + // startsOn: enableObj.value.startsOn2, | ||
790 | + // endsOn: enableObj.value.endsOn2, | ||
791 | + // }); | ||
792 | + // break; | ||
793 | + // case '3': | ||
794 | + // getSchduleCustomValue.value.push({ | ||
795 | + // enabled: true, | ||
796 | + // dayOfWeek: enableObj.value.daysOfWeek3[0], | ||
797 | + // startsOn: enableObj.value.startsOn3, | ||
798 | + // endsOn: enableObj.value.endsOn3, | ||
799 | + // }); | ||
800 | + // break; | ||
801 | + // } | ||
802 | + scheduleCustomValue.value = { | ||
803 | + type: enableObj.value.schedule, | ||
804 | + timezone: enableObj.value.timezone, | ||
805 | + items: getSchduleCustomValue.value, | ||
806 | + }; | ||
807 | + } | ||
808 | + //清除报警规则---报警日程表 | ||
809 | + if (enableClearObj.value.schedule == 'CUSTOM') { | ||
810 | + switch (enableClearObj.value.daysOfWeek1[0]) { | ||
811 | + case '1': | ||
812 | + getSchduleClearCustomValue.value.push({ | ||
813 | + enabled: true, | ||
814 | + dayOfWeek: enableClearObj.value.daysOfWeek1[0], | ||
815 | + startsOn: enableClearObj.value.startsOn1, | ||
816 | + endsOn: enableClearObj.value.endsOn1, | ||
817 | + }); | ||
818 | + break; | ||
819 | + case '2': | ||
820 | + getSchduleClearCustomValue.value.push({ | ||
821 | + enabled: true, | ||
822 | + dayOfWeek: enableClearObj.value.daysOfWeek2[0], | ||
823 | + startsOn: enableClearObj.value.startsOn2, | ||
824 | + endsOn: enableClearObj.value.endsOn2, | ||
825 | + }); | ||
826 | + break; | ||
827 | + case '3': | ||
828 | + getSchduleClearCustomValue.value.push({ | ||
829 | + enabled: true, | ||
830 | + dayOfWeek: enableClearObj.value.daysOfWeek3[0], | ||
831 | + startsOn: enableClearObj.value.startsOn3, | ||
832 | + endsOn: enableClearObj.value.endsOn3, | ||
833 | + }); | ||
834 | + break; | ||
835 | + } | ||
836 | + scheduleCustomClearValue.value = { | ||
837 | + type: enableClearObj.value.schedule, | ||
838 | + timezone: enableClearObj.value.timezone, | ||
839 | + items: getSchduleClearCustomValue.value, | ||
840 | + }; | ||
841 | + } | ||
695 | const scheduleClearValue = { | 842 | const scheduleClearValue = { |
696 | type: enableClearObj.value.schedule, | 843 | type: enableClearObj.value.schedule, |
697 | daysOfWeek: enableClearObj.value.daysOfWeek, | 844 | daysOfWeek: enableClearObj.value.daysOfWeek, |
698 | - // endsOn: enableClearObj.value.endsOn, | ||
699 | - // startsOn: enableClearObj.value.startOn, | 845 | + endsOn: enableClearObj.value.endsOn, |
846 | + startsOn: enableClearObj.value.startOn, | ||
700 | timezone: enableClearObj.value.timezone, | 847 | timezone: enableClearObj.value.timezone, |
701 | }; | 848 | }; |
702 | const getClearSchedule = { | 849 | const getClearSchedule = { |
703 | - schedule: scheduleClearValue, | 850 | + schedule: |
851 | + enableClearObj.value.schedule == 'CUSTOM' | ||
852 | + ? scheduleCustomClearValue.value | ||
853 | + : scheduleClearValue, | ||
704 | }; | 854 | }; |
705 | const getClearAdditionalProp = Object.assign({}, detailClearObj.value, getClearSchedule); | 855 | const getClearAdditionalProp = Object.assign({}, detailClearObj.value, getClearSchedule); |
706 | const scheduleValue = { | 856 | const scheduleValue = { |
707 | type: enableObj.value.schedule, | 857 | type: enableObj.value.schedule, |
708 | daysOfWeek: enableObj.value.daysOfWeek, | 858 | daysOfWeek: enableObj.value.daysOfWeek, |
709 | - // endsOn: enableObj.value.endsOn, | ||
710 | - // startsOn: enableObj.value.startOn, | 859 | + endsOn: enableObj.value.endsOn, |
860 | + startsOn: enableObj.value.startOn, | ||
711 | timezone: enableObj.value.timezone, | 861 | timezone: enableObj.value.timezone, |
712 | }; | 862 | }; |
713 | const getSchedule = { | 863 | const getSchedule = { |
714 | - schedule: scheduleValue, | 864 | + schedule: |
865 | + enableObj.value.schedule == 'CUSTOM' ? scheduleCustomValue.value : scheduleValue, | ||
715 | }; | 866 | }; |
867 | + | ||
716 | const getAdditionalProp = Object.assign({}, detailObj.value, getSchedule); | 868 | const getAdditionalProp = Object.assign({}, detailObj.value, getSchedule); |
717 | const getScheduleAndAlarmDetails = Object.assign( | 869 | const getScheduleAndAlarmDetails = Object.assign( |
718 | {}, | 870 | {}, |
@@ -746,7 +898,7 @@ | @@ -746,7 +898,7 @@ | ||
746 | console.log(valueRegisterFormCreateAlarm); | 898 | console.log(valueRegisterFormCreateAlarm); |
747 | const getValueRegisterFormHighSetting = { | 899 | const getValueRegisterFormHighSetting = { |
748 | propagate: valueRegisterFormHighSetting?.propagate, | 900 | propagate: valueRegisterFormHighSetting?.propagate, |
749 | - propagateRelationTypes: [valueRegisterFormHighSetting?.propagateRelationTypes], | 901 | + propagateRelationTypes: [valueRegisterFormHighSetting?.propagateRelationTypes].flat(1), |
750 | }; | 902 | }; |
751 | Object.assign( | 903 | Object.assign( |
752 | emptyObj.value, | 904 | emptyObj.value, |
@@ -756,7 +908,9 @@ | @@ -756,7 +908,9 @@ | ||
756 | getClearRulesAllObj, | 908 | getClearRulesAllObj, |
757 | objectId | 909 | objectId |
758 | ); | 910 | ); |
759 | - alarmss.value.push(emptyObj.value); | 911 | + if (alarmss.value.length == 0) { |
912 | + alarmss.value.push(emptyObj.value); | ||
913 | + } | ||
760 | const getAlarms = { | 914 | const getAlarms = { |
761 | alarms: alarmss.value, | 915 | alarms: alarmss.value, |
762 | }; | 916 | }; |
@@ -795,7 +949,11 @@ | @@ -795,7 +949,11 @@ | ||
795 | isRuleAlarmRuleConditions.value = 4; | 949 | isRuleAlarmRuleConditions.value = 4; |
796 | setTimeout(() => { | 950 | setTimeout(() => { |
797 | openModal4(true); | 951 | openModal4(true); |
798 | - proxy.$refs.getChildData1.resetDataFunc(); | 952 | + try { |
953 | + proxy.$refs.getChildData1.resetDataFunc(); | ||
954 | + } catch (e) { | ||
955 | + return e; | ||
956 | + } | ||
799 | }, 50); | 957 | }, 50); |
800 | }; | 958 | }; |
801 | const handleOpenClearEnableRule = () => { | 959 | const handleOpenClearEnableRule = () => { |
@@ -814,6 +972,19 @@ | @@ -814,6 +972,19 @@ | ||
814 | }; | 972 | }; |
815 | 973 | ||
816 | return { | 974 | return { |
975 | + resetEnableClearFormDataFunc, | ||
976 | + resetTemplateClearFormDataFunc, | ||
977 | + resetRulesClearFormDataFunc, | ||
978 | + resetEnableFormDataFunc, | ||
979 | + resetTemplateFormDataFunc, | ||
980 | + resetRulesFormDataFunc, | ||
981 | + retryEnableClearFormDataFunc, | ||
982 | + retryTemplateClearFormDataFunc, | ||
983 | + retryRulesClearFormDataFunc, | ||
984 | + retryEnableFormDataFunc, | ||
985 | + retryTemplateFormDataFunc, | ||
986 | + retryRulesFormDataFunc, | ||
987 | + clearProfileDataFunc, | ||
817 | clearIndex, | 988 | clearIndex, |
818 | retryRegisterFormFunc, | 989 | retryRegisterFormFunc, |
819 | retryRegisterFormHighSettingmFunc, | 990 | retryRegisterFormHighSettingmFunc, |
@@ -99,7 +99,7 @@ export const formSchema: FormSchema[] = [ | @@ -99,7 +99,7 @@ export const formSchema: FormSchema[] = [ | ||
99 | { | 99 | { |
100 | field: 'conditionType', | 100 | field: 'conditionType', |
101 | label: '条件类型', | 101 | label: '条件类型', |
102 | - colProps: { span: 24 }, | 102 | + colProps: { span: 13 }, |
103 | component: 'Select', | 103 | component: 'Select', |
104 | componentProps: { | 104 | componentProps: { |
105 | placeholder: '请选择报警日程表', | 105 | placeholder: '请选择报警日程表', |
@@ -177,11 +177,28 @@ export const formSchema: FormSchema[] = [ | @@ -177,11 +177,28 @@ export const formSchema: FormSchema[] = [ | ||
177 | { | 177 | { |
178 | field: 'defaultValue', | 178 | field: 'defaultValue', |
179 | label: '持续时间值', | 179 | label: '持续时间值', |
180 | - colProps: { span: 24 }, | 180 | + colProps: { span: 13 }, |
181 | component: 'Input', | 181 | component: 'Input', |
182 | componentProps: { | 182 | componentProps: { |
183 | + maxLength: 16, | ||
183 | placeholder: '请输入持续时间值(请输入数字)', | 184 | placeholder: '请输入持续时间值(请输入数字)', |
184 | }, | 185 | }, |
186 | + dynamicRules: () => { | ||
187 | + return [ | ||
188 | + { | ||
189 | + validator: (_, value) => { | ||
190 | + if (!value) { | ||
191 | + return Promise.reject('持续时间值不能为空'); | ||
192 | + } | ||
193 | + const pwdRegex = new RegExp(/-?\d+/); | ||
194 | + if (!pwdRegex.test(value)) { | ||
195 | + return Promise.reject('只能为数字,且最长不超过16位'); | ||
196 | + } | ||
197 | + return Promise.resolve(); | ||
198 | + }, | ||
199 | + }, | ||
200 | + ]; | ||
201 | + }, | ||
185 | ifShow: ({ values }) => isWenDu(Reflect.get(values, 'conditionType')), | 202 | ifShow: ({ values }) => isWenDu(Reflect.get(values, 'conditionType')), |
186 | show: ({ values }) => { | 203 | show: ({ values }) => { |
187 | return !values.field5; | 204 | return !values.field5; |
@@ -210,7 +227,7 @@ export const formSchema: FormSchema[] = [ | @@ -210,7 +227,7 @@ export const formSchema: FormSchema[] = [ | ||
210 | { | 227 | { |
211 | field: 'unit', | 228 | field: 'unit', |
212 | label: '时间单位', | 229 | label: '时间单位', |
213 | - colProps: { span: 24 }, | 230 | + colProps: { span: 13 }, |
214 | component: 'Select', | 231 | component: 'Select', |
215 | componentProps: { | 232 | componentProps: { |
216 | placeholder: '请选择时间单位', | 233 | placeholder: '请选择时间单位', |
@@ -226,12 +243,28 @@ export const formSchema: FormSchema[] = [ | @@ -226,12 +243,28 @@ export const formSchema: FormSchema[] = [ | ||
226 | { | 243 | { |
227 | field: 'defaultValue', | 244 | field: 'defaultValue', |
228 | label: '事件计数值必填', | 245 | label: '事件计数值必填', |
229 | - colProps: { span: 24 }, | 246 | + colProps: { span: 13 }, |
230 | component: 'Input', | 247 | component: 'Input', |
231 | componentProps: { | 248 | componentProps: { |
249 | + maxLength: 2147483637, | ||
232 | placeholder: '请输入事件计数值(应在1到2147483637之间)', | 250 | placeholder: '请输入事件计数值(应在1到2147483637之间)', |
233 | }, | 251 | }, |
234 | - rules: [{ message: '事件计数应在1到2147483637之间', trigger: 'blur' }], | 252 | + dynamicRules: () => { |
253 | + return [ | ||
254 | + { | ||
255 | + validator: (_, value) => { | ||
256 | + if (!value) { | ||
257 | + return Promise.reject('事件计数不能为空'); | ||
258 | + } | ||
259 | + const pwdRegex = new RegExp(/-?\d+/); | ||
260 | + if (!pwdRegex.test(value)) { | ||
261 | + return Promise.reject('只能为数字,且最长不超过16位'); | ||
262 | + } | ||
263 | + return Promise.resolve(); | ||
264 | + }, | ||
265 | + }, | ||
266 | + ]; | ||
267 | + }, | ||
235 | ifShow: ({ values }) => isTimeAll(Reflect.get(values, 'conditionType')), | 268 | ifShow: ({ values }) => isTimeAll(Reflect.get(values, 'conditionType')), |
236 | show: ({ values }) => { | 269 | show: ({ values }) => { |
237 | return !values.field6; | 270 | return !values.field6; |
@@ -240,6 +273,7 @@ export const formSchema: FormSchema[] = [ | @@ -240,6 +273,7 @@ export const formSchema: FormSchema[] = [ | ||
240 | { | 273 | { |
241 | field: 'inherit', | 274 | field: 'inherit', |
242 | label: '', | 275 | label: '', |
276 | + colProps: { span: 13 }, | ||
243 | component: 'Checkbox', | 277 | component: 'Checkbox', |
244 | renderComponentContent: 'Inherit from owner', | 278 | renderComponentContent: 'Inherit from owner', |
245 | ifShow: ({ values }) => | 279 | ifShow: ({ values }) => |