Commit dec40da981ad0b97b0a2235f89ec97abb96bc449

Authored by 1400859700@qq.com
2 parents 37a80607 8484ee22

fix:所有字段验证失效问题

Showing 99 changed files with 3970 additions and 1108 deletions
... ... @@ -6,12 +6,18 @@ VITE_PUBLIC_PATH = /
6 6
7 7 # Cross-domain proxy, you can configure multiple
8 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 19 # Delete console
14   -VITE_DROP_CONSOLE = false
  20 +VITE_DROP_CONSOLE = true
15 21
16 22 # Basic interface address SPA
17 23 VITE_GLOB_API_URL=/api
... ...
... ... @@ -10,26 +10,29 @@ VITE_DROP_CONSOLE = true
10 10 # Whether to enable gzip or brotli compression
11 11 # Optional: gzip | brotli | none
12 12 # If you need multiple forms, you can use `,` to separate
13   -VITE_BUILD_COMPRESS = 'none'
  13 +VITE_BUILD_COMPRESS = 'gzip'
14 14
15 15 # Whether to delete origin files when using compress, default false
16 16 VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE = false
17 17
18 18 # Basic interface address SPA
19   -VITE_GLOB_API_URL=/api
  19 +VITE_GLOB_API_URL=http://localhost:8080/api
20 20
21 21 # File upload address, optional
22 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 25 # Interface prefix
26   -VITE_GLOB_API_URL_PREFIX=/v1
  26 +VITE_GLOB_API_URL_PREFIX=/yt
27 27
28 28 # Whether to enable image compression
29   -VITE_USE_IMAGEMIN= true
  29 +VITE_USE_IMAGEMIN= false
30 30
31 31 # use pwa
32 32 VITE_USE_PWA = false
33 33
34 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=
... ...
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 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 +};
... ...
  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 +};
... ...
1   -import { defHttp } from '/@/utils/http/axios';
2   -
3   -enum Api {
4   - // The address does not exist
5   - Error = '/error',
6   -}
7   -
8   -/**
9   - * @description: Trigger ajax error
10   - */
11   -
12   -export const fireErrorApi = () => defHttp.get({ url: Api.Error });
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 2 import { IPutPersonal } from './model/index';
3 3 import { defHttp } from '/@/utils/http/axios';
4   -import { UploadFileParams } from '/#/axios';
5 4
6 5 enum API {
7   - BaseUploadUrl = '/api/yt/oss/upload',
  6 + BaseUploadUrl = '/oss/upload',
8 7 PutPersonalUrl = '/user/center',
9 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 14 export const personalGet = (id: string) => {
... ...
1   -export interface UploadApiResult {
2   - message: string;
3   - code: number;
4   - url: string;
  1 +export interface FileUploadResponse {
  2 + fileName: string;
  3 + fileDownloadUri: string;
  4 + fileType: string;
  5 + size: number;
  6 + fileStaticUri: string;
5 7 }
... ...
... ... @@ -17,7 +17,7 @@ enum Api {
17 17 export const getMenuList = () => {
18 18 const userStore = useUserStore();
19 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 21 url = Api.SysAdminMenuList;
22 22 }
23 23 return defHttp.get<getMenuListResultModel>({ url });
... ...
... ... @@ -4,13 +4,14 @@
4 4 -->
5 5
6 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 10 <span
10 11 class="ml-2 md:opacity-100"
11 12 :class="getTitleClass"
12 13 v-show="showTitle"
13   - style="white-space: nowrap"
  14 + style="white-space: nowrap; font-size: small"
14 15 >
15 16 {{ getTitle }}
16 17 </span>
... ... @@ -19,10 +20,8 @@
19 20 <script lang="ts" setup>
20 21 import { computed, unref } from 'vue';
21 22 import { useGlobSetting } from '/@/hooks/setting';
22   - import { useGo } from '/@/hooks/web/usePage';
23 23 import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
24 24 import { useDesign } from '/@/hooks/web/useDesign';
25   - import { PageEnum } from '/@/enums/pageEnum';
26 25 import { useUserStore } from '/@/store/modules/user';
27 26 const props = defineProps({
28 27 /**
... ... @@ -43,7 +42,6 @@
43 42 const { getCollapsedShowTitle } = useMenuSetting();
44 43 const userStore = useUserStore();
45 44 const { title } = useGlobSetting();
46   - const go = useGo();
47 45
48 46 const getAppLogoClass = computed(() => [
49 47 prefixCls,
... ... @@ -56,12 +54,8 @@
56 54 'xs:opacity-0': !props.alwaysShowTitle,
57 55 },
58 56 ]);
59   -
60   - function goHome() {
61   - go(userStore.getUserInfo.homePath || PageEnum.BASE_HOME);
62   - }
63 57 const getLogo = computed(() => {
64   - return userStore.platInfo?.logo ?? '/src/assets/images/logo.png';
  58 + return userStore.platInfo?.logo;
65 59 });
66 60 const getTitle = computed(() => {
67 61 // 设置icon
... ... @@ -82,7 +76,6 @@
82 76 padding-left: 7px;
83 77 cursor: pointer;
84 78 transition: all 0.2s ease;
85   -
86 79 &.light {
87 80 border-bottom: 1px solid @border-color-base;
88 81 }
... ...
1 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 }
... ...
  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 +};
... ...
... ... @@ -78,6 +78,7 @@
78 78
79 79 .ant-badge {
80 80 font-size: 18px;
  81 + display: none;
81 82
82 83 .ant-badge-multiple-words {
83 84 padding: 0 4px;
... ...
1 1 import { FormSchema } from '/@/components/Table';
  2 +import { phoneRule, emailRule } from '/@/utils/rules';
2 3
3 4 export const formSchema: FormSchema[] = [
4 5 {
5   - field: 'nickName',
  6 + field: 'realName',
6 7 label: '用户昵称',
7 8 colProps: { span: 13 },
8 9 required: true,
... ... @@ -20,6 +21,7 @@ export const formSchema: FormSchema[] = [
20 21 componentProps: {
21 22 placeholder: '请输入手机号码',
22 23 },
  24 + rules: phoneRule,
23 25 },
24 26 {
25 27 field: 'email',
... ... @@ -30,5 +32,6 @@ export const formSchema: FormSchema[] = [
30 32 componentProps: {
31 33 placeholder: '请输入邮箱',
32 34 },
  35 + rules: emailRule,
33 36 },
34 37 ];
... ...
1 1 <template>
2 2 <BasicModal
3 3 :useWrapper="true"
4   - width="80vw"
  4 + width="82vw"
5 5 :height="compHeight"
6 6 v-bind="$attrs"
7 7 @register="registerModal"
... ... @@ -22,15 +22,34 @@
22 22 ><p style="font-size: 17px; margin-top: 7px; margin-left: 10px">个人信息</p></div
23 23 >
24 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 53 </div>
35 54 <Description
36 55 class="mt-8"
... ... @@ -66,13 +85,13 @@
66 85 import { BasicForm, useForm } from '/@/components/Form/index';
67 86 import { formSchema } from './config';
68 87 import { Description, DescItem, useDescription } from '/@/components/Description/index';
69   - import { CropperAvatar } from '/@/components/Cropper';
70   - import defaultImage from '/@/assets/images/logo.png';
71 88 import { uploadApi, personalPut } from '/@/api/personal/index';
72 89 import { useMessage } from '/@/hooks/web/useMessage';
73 90 import { USER_INFO_KEY } from '/@/enums/cacheEnum';
74 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 96 const schema: DescItem[] = [
78 97 {
... ... @@ -102,68 +121,91 @@
102 121 ];
103 122 export default defineComponent({
104 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 127 const userInfo = getAuthCache(USER_INFO_KEY);
109 128 const { createMessage } = useMessage();
110 129 const getPersonalValue: any = ref({});
111 130 const getPersonalDetailValue: any = ref({});
112   - const avatarUrl: any = ref('');
  131 + const updatePersonalData: any = ref({});
113 132 const getBackendV: any = ref({});
114 133 const [registerDesc] = useDescription({
115 134 title: '个人详情',
116 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 164 showActionButtonGroup: false,
122 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 188 const handleSubmit = async () => {
129   - // console.log(userStore.getUserInfo);
130 189 const getUserInfo = await userInfo;
131   - // console.log(getUserInfo);
132 190 getPersonalValue.value = await validate();
133 191 getPersonalValue.value.id = getUserInfo.userId;
134 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 196 createMessage.success('修改成功');
138 197 closeModal();
139 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 201 const compHeight = computed(() => {
160 202 return 1000;
161 203 });
162 204 return {
163   - uploadApi,
  205 + peresonalPic,
  206 + beforeUploadqrcodePic,
  207 + customUploadqrcodePic,
164 208 compHeight,
165   - updateAvatar,
166   - avatar,
167 209 handleSubmit,
168 210 getPersonalDetailValue,
169 211 registerDesc,
... ... @@ -174,4 +216,22 @@
174 216 },
175 217 });
176 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 1 <template>
2 2 <Dropdown placement="bottomLeft" :overlayClassName="`${prefixCls}-dropdown-overlay`">
3 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 8 <span :class="`${prefixCls}__info hidden md:block`">
6 9 <span :class="`${prefixCls}__name `" class="truncate">
7   - {{ getUserInfo.realName }}
  10 + {{ refreshPersonlData.realName ? refreshPersonlData.realName : getUserInfo.realName }}
8 11 </span>
9 12 </span>
10 13 </span>
... ... @@ -12,12 +15,10 @@
12 15 <template #overlay>
13 16 <Menu @click="handleMenuClick">
14 17 <MenuItem
15   - key="doc"
16   - :text="t('layout.header.dropdownItemDoc')"
  18 + key="personal"
  19 + :text="t('layout.header.dropdownItemPersonal')"
17 20 icon="ion:document-text-outline"
18   - v-if="getShowDoc"
19 21 />
20   - <MenuDivider v-if="getShowDoc" />
21 22 <MenuItem
22 23 v-if="getUseLockPage"
23 24 key="lock"
... ... @@ -29,22 +30,21 @@
29 30 :text="t('layout.header.dropdownItemLoginOut')"
30 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 33 </Menu>
38 34 </template>
39 35 </Dropdown>
40 36 <LockAction @register="register" />
41   - <PersonalChild @register="registerPersonal" />
  37 + <PersonalChild
  38 + @refreshPersonl="refreshPersonlFunc"
  39 + ref="personalRef"
  40 + @register="registerPersonal"
  41 + />
42 42 </template>
43 43 <script lang="ts">
44 44 // components
45 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 49 import { DOC_URL } from '/@/settings/siteSetting';
50 50
... ... @@ -53,13 +53,12 @@
53 53 import { useI18n } from '/@/hooks/web/useI18n';
54 54 import { useDesign } from '/@/hooks/web/useDesign';
55 55 import { useModal } from '/@/components/Modal';
56   -
57 56 import headerImg from '/@/assets/images/header.jpg';
58 57 import { propTypes } from '/@/utils/propTypes';
59 58 import { openWindow } from '/@/utils';
60   -
61 59 import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
62   -
  60 + import { USER_INFO_KEY } from '/@/enums/cacheEnum';
  61 + import { getAuthCache } from '/@/utils/auth';
63 62 type MenuEvent = 'logout' | 'doc' | 'lock' | 'personal';
64 63
65 64 export default defineComponent({
... ... @@ -68,7 +67,6 @@
68 67 Dropdown,
69 68 Menu,
70 69 MenuItem: createAsyncComponent(() => import('./DropMenuItem.vue')),
71   - MenuDivider: Menu.Divider,
72 70 LockAction: createAsyncComponent(() => import('../lock/LockModal.vue')),
73 71 PersonalChild: createAsyncComponent(() => import('../personal/index.vue')),
74 72 },
... ... @@ -76,14 +74,21 @@
76 74 theme: propTypes.oneOf(['dark', 'light']),
77 75 },
78 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 84 const { prefixCls } = useDesign('header-user-dropdown');
80 85 const { t } = useI18n();
81 86 const { getShowDoc, getUseLockPage } = useHeaderSetting();
82 87 const userStore = useUserStore();
83 88
84 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 94 const [register, { openModal }] = useModal();
... ... @@ -122,11 +127,21 @@
122 127
123 128 const openPersonalFunc = () => {
124 129 setTimeout(() => {
125   - openModalPersonal(true);
  130 + openModalPersonal(true, {
  131 + userInfo,
  132 + });
126 133 }, 10);
127 134 };
128 135
  136 + const refreshPersonlFunc = (v) => {
  137 + refreshPersonlData.avatar = v.avatar;
  138 + refreshPersonlData.realName = v.realName;
  139 + };
  140 +
129 141 return {
  142 + refreshPersonlData,
  143 + refreshPersonlFunc,
  144 + personalRef,
130 145 registerPersonal,
131 146 openPersonalFunc,
132 147 prefixCls,
... ...
... ... @@ -21,43 +21,18 @@
21 21 </transition>
22 22 </template>
23 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 25 <FrameLayout v-if="getCanEmbedIFramePage" />
43 26 </template>
44 27
45 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 30 import FrameLayout from '/@/layouts/iframe/index.vue';
50   -
51 31 import { useRootSetting } from '/@/hooks/setting/useRootSetting';
52   -
53 32 import { useTransitionSetting } from '/@/hooks/setting/useTransitionSetting';
54 33 import { useMultipleTabSetting } from '/@/hooks/setting/useMultipleTabSetting';
55 34 import { getTransitionName } from './transition';
56   -
57 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 36 export default defineComponent({
62 37 name: 'PageLayout',
63 38 components: { FrameLayout },
... ... @@ -78,17 +53,6 @@
78 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 56 return {
93 57 getTransitionName,
94 58 openCache,
... ... @@ -96,8 +60,6 @@
96 60 getBasicTransition,
97 61 getCaches,
98 62 getCanEmbedIFramePage,
99   - // register,
100   - // maskColor,
101 63 };
102 64 },
103 65 });
... ...
... ... @@ -12,7 +12,7 @@ export default {
12 12 networkExceptionMsg:
13 13 'Please check if your network connection is normal! The network is abnormal',
14 14
15   - errMsg401: 'no permission',
  15 + errMsg401: '',
16 16 errMsg403: 'not authorized',
17 17 errMsg404: 'the resource was not found!',
18 18 errMsg405: 'Network request error, request method not allowed!',
... ...
... ... @@ -10,8 +10,7 @@ export default {
10 10 apiRequestFailed: '请求出错,请稍候重试',
11 11 networkException: '网络异常',
12 12 networkExceptionMsg: '网络异常,请检查您的网络连接是否正常!',
13   -
14   - errMsg401: '没有权限!',
  13 + errMsg401: '',
15 14 errMsg403: '未授权',
16 15 errMsg404: '未找到该资源!',
17 16 errMsg405: '网络请求错误,请求方法未允许!',
... ...
... ... @@ -14,13 +14,7 @@ import { setupStore } from '/@/store';
14 14 import { setupGlobDirectives } from '/@/directives';
15 15 import { setupI18n } from '/@/locales/setupI18n';
16 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 19 async function bootstrap() {
26 20 const app = createApp(App);
... ...
... ... @@ -129,7 +129,6 @@ export const useUserStore = defineStore({
129 129 try {
130 130 const { goHome = true, mode, ...loginParams } = params;
131 131 const data = await loginApi(loginParams, mode);
132   - console.log(data);
133 132 return this.process(data, goHome);
134 133 } catch (error) {
135 134 return Promise.reject(error);
... ...
... ... @@ -10,7 +10,6 @@ import { SessionTimeoutProcessingEnum } from '/@/enums/appEnum';
10 10 const { createMessage, createErrorModal } = useMessage();
11 11 const error = createMessage.error!;
12 12 const stp = projectSetting.sessionTimeoutProcessing;
13   -
14 13 export function checkStatus(
15 14 status: number,
16 15 msg: string,
... ... @@ -19,7 +18,6 @@ export function checkStatus(
19 18 const { t } = useI18n();
20 19 const userStore = useUserStoreWithOut();
21 20 let errMessage = '';
22   -
23 21 switch (status) {
24 22 case 400:
25 23 errMessage = `${msg}`;
... ...
... ... @@ -10,58 +10,17 @@ import { useGlobSetting } from '/@/hooks/setting';
10 10 import { useMessage } from '/@/hooks/web/useMessage';
11 11 import { RequestEnum, ContentTypeEnum } from '/@/enums/httpEnum';
12 12 import { isString } from '/@/utils/is';
13   -import { getJwtToken, getAuthCache } from '/@/utils/auth';
  13 +import { getJwtToken } from '/@/utils/auth';
14 14 import { setObjToUrlParams, deepMerge } from '/@/utils';
15 15 import { useErrorLogStoreWithOut } from '/@/store/modules/errorLog';
16 16 import { useI18n } from '/@/hooks/web/useI18n';
17 17 import { joinTimestamp, formatRequestDate } from './helper';
18 18 import { PageEnum } from '/@/enums/pageEnum';
19   -import { REFRESH_TOKEN_KEY } from '/@/enums/cacheEnum';
20 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 21 const globSetting = useGlobSetting();
56 22 const urlPrefix = globSetting.urlPrefix;
57 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 26 * @description: 数据处理,方便区分多种处理方式
... ... @@ -162,32 +121,13 @@ const transform: AxiosTransform = {
162 121 const msg: string = response?.data?.msg ?? '';
163 122 const err: string = error?.toString?.() ?? '';
164 123 let errMessage = '';
165   -
166 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 131 if (code === 'ECONNABORTED' && message.indexOf('timeout') !== -1) {
192 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 60
61 61 // 手机号正则
62 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 33 label: '告警类型',
34 34 component: 'Input',
35 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 55 field: 'endTime',
... ...
... ... @@ -51,7 +51,6 @@
51 51 severity: alarmLevel(data.severity),
52 52 status: statusType(data.status),
53 53 });
54   - console.log(data.status);
55 54 alarmStatus.value = data.status;
56 55 alarmId.value = data.id;
57 56 });
... ...
... ... @@ -41,6 +41,7 @@ export const formSchema: FormSchema[] = [
41 41 label: '',
42 42 component: 'Input',
43 43 componentProps: {
  44 + maxLength: 255,
44 45 placeholder: '请输入设备名称',
45 46 },
46 47 },
... ...
... ... @@ -34,8 +34,16 @@
34 34 :canFullscreen="false"
35 35 >
36 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 45 </BasicModal>
  46 + <DeviceDetailDrawer @register="registerDetailDrawer" />
39 47 </div>
40 48 </template>
41 49 <script lang="ts">
... ... @@ -44,22 +52,30 @@
44 52 import { formSchema, columns } from './config.data';
45 53 import { BasicTable, useTable } from '/@/components/Table';
46 54 import { devicePage } from '/@/api/alarm/contact/alarmContact';
47   - import { Tag } from 'ant-design-vue';
  55 + import { Tag, Alert } from 'ant-design-vue';
48 56 import { DeviceState } from '/@/api/device/model/deviceModel';
49 57 import { BAI_DU_MAP_URL } from '/@/utils/fnUtils';
50 58 import { useModal, BasicModal } from '/@/components/Modal';
51 59 import { BasicForm, useForm } from '/@/components/Form';
52 60 import { schemas } from './config.data';
53 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 69 import moment from 'moment';
56 70 export default defineComponent({
57 71 name: 'BaiduMap',
58 72 components: {
59 73 BasicTable,
60 74 Tag,
  75 + Alert,
61 76 BasicModal,
62 77 BasicForm,
  78 + DeviceDetailDrawer,
63 79 },
64 80 props: {
65 81 width: {
... ... @@ -74,7 +90,10 @@
74 90 setup() {
75 91 const wrapRef = ref<HTMLDivElement | null>(null);
76 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 97 async function initMap() {
79 98 await toPromise();
80 99 await nextTick();
... ... @@ -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 126 const BMap = (window as any).BMap;
107 127 const wrapEl = unref(wrapRef);
108 128 const map = new BMap.Map(wrapEl);
109 129 if (record.deviceInfo.address) {
110   - const { name, organizationDTO, updateTime, deviceState, deviceProfile } = record;
  130 + const { name, organizationDTO, deviceState, deviceProfile } = record;
111 131 const { longitude, latitude, address } = record.deviceInfo;
112 132 const point = new BMap.Point(longitude, latitude);
113 133 let options = {
... ... @@ -117,6 +137,10 @@
117 137 map.centerAndZoom(point, 15);
118 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 144 let infoWindow = new BMap.InfoWindow(
121 145 `
122 146 <div style="display:flex;justify-content:space-between; margin:20px 0px;">
... ... @@ -132,10 +156,9 @@
132 156 <div>所属组织:${organizationDTO.name}</div>
133 157 <div style="margin-top:6px;">接入协议:${deviceProfile.transportType}</div>
134 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 162 <button onclick="openHistoryModal()" style="color:#fff;background-color:#409eff;padding:4px; border-radius:4px;">历史数据</button>
140 163 </div>
141 164 `,
... ... @@ -185,13 +208,20 @@
185 208 endTs = Date.now();
186 209 // 发送请求
187 210 const res = await getDeviceHistoryInfo({
188   - entityId: entityId.value,
  211 + entityId,
189 212 keys: keys.join(),
190 213 startTs,
191 214 endTs,
192 215 interval,
193 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 226 for (const key in res) {
197 227 for (const item1 of res[key]) {
... ... @@ -250,24 +280,38 @@
250 280
251 281 const chartRef = ref<HTMLDivElement | null>(null);
252 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 292 const openHistoryModal = async () => {
255 293 openModal(true);
256   -
257 294 // 收集参数
258 295 const dataArray: any[] = [];
259 296 const startTs = Date.now() - 86400000; //最近一天
260 297 const endTs = Date.now();
261 298 // 发送请求
262   - keys = await getDeviceDataKeys(entityId.value);
  299 + keys = await getDeviceDataKeys(entityId);
263 300 const res = await getDeviceHistoryInfo({
264   - entityId: entityId.value,
  301 + entityId,
265 302 keys: keys.join(),
266 303 startTs,
267 304 endTs,
268 305 interval: 7200000, //间隔两小时
269 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 316 for (const key in res) {
273 317 for (const item1 of res[key]) {
... ... @@ -327,12 +371,14 @@
327 371 agg: 'AVG',
328 372 });
329 373 };
  374 +
330 375 const cancelHistoryModal = () => {
331 376 resetFields();
332 377 setOptions({});
333 378 };
334 379 onMounted(() => {
335 380 initMap();
  381 + (window as any).openDeviceInfoDrawer = openDeviceInfoDrawer;
336 382 (window as any).openHistoryModal = openHistoryModal;
337 383 });
338 384 return {
... ... @@ -343,7 +389,9 @@
343 389 registerModal,
344 390 registerForm,
345 391 chartRef,
  392 + isNull,
346 393 cancelHistoryModal,
  394 + registerDetailDrawer,
347 395 };
348 396 },
349 397 });
... ...
... ... @@ -56,6 +56,7 @@ export const searchFormSchema: FormSchema[] = [
56 56 component: 'Input',
57 57 colProps: { span: 6 },
58 58 componentProps: {
  59 + maxLength: 36,
59 60 placeholder: '请输入联系人姓名',
60 61 },
61 62 },
... ... @@ -70,6 +71,7 @@ export const formSchema: FormSchema[] = [
70 71 component: 'Input',
71 72 componentProps: {
72 73 placeholder: '请输入联系人姓名',
  74 + maxLength: 255,
73 75 },
74 76 },
75 77 {
... ... @@ -108,6 +110,7 @@ export const formSchema: FormSchema[] = [
108 110 component: 'Input',
109 111 componentProps: {
110 112 placeholder: '请输入微信号',
  113 + maxLength: 255,
111 114 },
112 115 },
113 116 {
... ... @@ -115,7 +118,8 @@ export const formSchema: FormSchema[] = [
115 118 label: '备注',
116 119 component: 'InputTextArea',
117 120 componentProps: {
118   - placeholder: '',
  121 + placeholder: '请输入备注',
  122 + maxLength: 255,
119 123 },
120 124 },
121 125 {
... ... @@ -123,5 +127,8 @@ export const formSchema: FormSchema[] = [
123 127 label: '',
124 128 component: 'Input',
125 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 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 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 88 </div>
49 89 </div>
50 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 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 110 </div>
55 111 </template>
56 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 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 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 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 105 </Card>
55   - </Card>
  106 + </div>
56 107 </template>
57 108
58 109 <script lang="ts">
59 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 112 import { useUserStore } from '/@/store/modules/user';
62 113 import { getEnterPriseDetail } from '/@/api/oem';
63 114 import { notifyMyGetrPageApi } from '/@/api/stationnotification/stationnotifyApi';
64 115 import { Time } from '/@/components/Time';
65 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 121 export default defineComponent({
67 122 components: {
68 123 Card,
69   - AnchorLink,
  124 + CardMeta: Card.Meta,
  125 + AnchorLink: Anchor.Link,
70 126 List,
71   - ListItem,
72   - ListItemMeta,
  127 + ListItem: List.Item,
  128 + ListItemMeta: List.Item.Meta,
  129 + Descriptions,
  130 + DescriptionsItem: Descriptions.Item,
73 131 Avatar,
74 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 146 const helpDoc = ref([
83 147 {
84 148 title: '如何接入设备?',
... ... @@ -109,6 +173,18 @@
109 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 188 const userStore = useUserStore();
113 189 const getContacts = computed(() => {
114 190 return userStore.enterPriseInfo?.contacts;
... ... @@ -122,32 +198,35 @@
122 198 const getQrCode = computed(() => {
123 199 return userStore.enterPriseInfo?.qrCode;
124 200 });
125   -
126   - // 通知数据
127   - const dataSource = ref([]);
128   - const go = useGo();
129 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 210 return {
135 211 activeKey,
136 212 tabListTitle,
137   - onTabChange,
138 213 helpDoc,
139 214 getQrCode,
140 215 getContacts,
141 216 getAddress,
142 217 getTel,
143 218 dataSource,
  219 + onTabChange,
144 220 go,
  221 + registerTable,
  222 + isAdmin,
  223 + redoHeight,
145 224 };
146 225 },
147 226 });
148 227 </script>
149 228
150   -<style lang="less" scoped>
  229 +<style scoped>
151 230 .noticeTitle:hover {
152 231 border-bottom: 1px solid #ccc;
153 232 }
... ...
... ... @@ -4,59 +4,347 @@
4 4 v-bind="$attrs"
5 5 :active-tab-key="activeKey"
6 6 @tabChange="onTabChange"
  7 + v-if="!isAdmin(role)"
7 8 >
8 9 <template #tabBarExtraContent>
9 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 17 </template>
15   - <DatePicker @change="onDateChange" />
  18 + <DatePicker @change="onDateChange" v-model:value="dateValue" />
16 19 </div>
17 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 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 28 </div>
26 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 36 </template>
28 37 <script lang="ts" setup>
29   - import { ref } from 'vue';
  38 + import { ref, reactive } from 'vue';
30 39 import { Card, DatePicker } from 'ant-design-vue';
31 40 import VisitAnalysis from './VisitAnalysis.vue';
32 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 59 const tabListTitle = [
37 60 {
38   - key: 'tab1',
  61 + key: '1',
39 62 tab: '告警数统计',
40 63 },
41 64 {
42   - key: 'tab2',
  65 + key: '2',
43 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 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 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 345 </script>
58 346
59   -<style scoped lang="less">
  347 +<style lang="less">
60 348 .center {
61 349 display: flex;
62 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 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 7 </template>
4 8 <script lang="ts" setup>
5   - import { onMounted, ref, Ref } from 'vue';
  9 + import { onMounted, ref, Ref, withDefaults, watch } from 'vue';
6 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 23 const chartRef = ref<HTMLDivElement | null>(null);
13 24 const { setOptions } = useECharts(chartRef as Ref<HTMLDivElement>);
14 25
... ... @@ -16,79 +27,60 @@
16 27 setOptions({
17 28 tooltip: {
18 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 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 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 86 </script>
... ...
1 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 7 </template>
4 8 <script lang="ts" setup>
5   - import { onMounted, ref, Ref } from 'vue';
  9 + import { ref, Ref, watch, withDefaults } from 'vue';
6 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 24 const chartRef = ref<HTMLDivElement | null>(null);
14 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 83 </script>
... ...
1 1 import { PropType } from 'vue';
2   -
  2 +import type { BasicColumn } from '/@/components/Table';
3 3 export interface BasicProps {
4 4 width: string;
5 5 height: string;
... ... @@ -14,3 +14,16 @@ export const basicProps = {
14 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 +];
... ...
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 1 <template>
2 2 <div class="p-4 md:flex">
3 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 7 <Card title="核心流程指南" style="width: 100%">
8   - <img alt="核心流程指南" src="../../../assets/images/flow.png" />
  8 + <img alt="核心流程指南" src="/src/assets/images/flow.png" />
9 9 </Card>
10 10 </div>
11 11 </div>
12 12 <div class="md:w-3/10 w-full enter-y">
13   - <HelpDoc />
  13 + <HelpDoc :role="role" />
14 14 </div>
15 15 </div>
16 16 </template>
... ... @@ -20,8 +20,19 @@
20 20 import SiteAnalysis from './components/SiteAnalysis.vue';
21 21 import { Card } from 'ant-design-vue';
22 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 32 const loading = ref(true);
  33 +
  34 + console.log(role);
  35 +
25 36 setTimeout(() => {
26 37 loading.value = false;
27 38 }, 1500);
... ...
... ... @@ -3,6 +3,7 @@ import { findDictItemByCode } from '/@/api/system/dict';
3 3 import { deviceProfile } from '/@/api/device/deviceManager';
4 4 import { getOrganizationList } from '/@/api/system/system';
5 5 import { copyTransFun } from '/@/utils/fnUtils';
  6 +
6 7 // 第一步的表单
7 8 export const step1Schemas: FormSchema[] = [
8 9 {
... ... @@ -17,6 +18,7 @@ export const step1Schemas: FormSchema[] = [
17 18 required: true,
18 19 component: 'Input',
19 20 componentProps: {
  21 + placeholder: '设备名称',
20 22 maxLength: 30,
21 23 },
22 24 },
... ... @@ -26,6 +28,7 @@ export const step1Schemas: FormSchema[] = [
26 28 required: true,
27 29 component: 'ApiSelect',
28 30 componentProps: {
  31 + placeholder: '设备类型',
29 32 api: findDictItemByCode,
30 33 params: {
31 34 dictCode: 'device_type',
... ... @@ -64,6 +67,20 @@ export const step1Schemas: FormSchema[] = [
64 67 component: 'Input',
65 68 componentProps: {
66 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 93 field: 'description',
77 94 label: '备注',
78 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 115 field: 'id',
82 116 label: 'id',
83 117 component: 'Input',
84 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 138 field: 'tenantId',
88 139 label: '租户Code',
89 140 component: 'Input',
90 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 161 field: 'tbDeviceId',
94 162 label: 'tbDeviceId',
95 163 component: 'Input',
96 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 329 field: 'credentialsId',
245 330 required: true,
246 331 ifShow: false,
  332 + componentProps: {
  333 + maxLength: 36,
  334 + placeholder: '请输入访问令牌',
  335 + },
247 336 },
248 337 {
249 338 label: 'RSA公钥',
... ... @@ -251,6 +340,10 @@ export const step2Schemas: FormSchema[] = [
251 340 field: 'publicKey',
252 341 required: true,
253 342 ifShow: false,
  343 + componentProps: {
  344 + maxLength: 36,
  345 + placeholder: '请输入RSA公钥',
  346 + },
254 347 },
255 348 {
256 349 label: '客户端ID',
... ... @@ -258,6 +351,10 @@ export const step2Schemas: FormSchema[] = [
258 351 field: 'clientId',
259 352 required: true,
260 353 ifShow: false,
  354 + componentProps: {
  355 + maxLength: 36,
  356 + placeholder: '请输入客户端ID',
  357 + },
261 358 },
262 359 {
263 360 label: '用户名',
... ... @@ -265,11 +362,32 @@ export const step2Schemas: FormSchema[] = [
265 362 field: 'username',
266 363 required: true,
267 364 ifShow: false,
  365 + componentProps: {
  366 + maxLength: 255,
  367 + placeholder: '请输入用户名',
  368 + },
268 369 },
269 370 {
270 371 label: '密码',
271 372 component: 'InputPassword',
272 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 391 ifShow: false,
274 392 },
275 393 ];
... ... @@ -409,6 +527,10 @@ export const TokenSchemas: FormSchema[] = [
409 527 field: 'credentialsId',
410 528 required: true,
411 529 ifShow: false,
  530 + componentProps: {
  531 + maxLength: 36,
  532 + placeholder: '请输入访问令牌',
  533 + },
412 534 },
413 535 {
414 536 label: 'RSA公钥',
... ... @@ -416,6 +538,10 @@ export const TokenSchemas: FormSchema[] = [
416 538 field: 'publicKey',
417 539 required: true,
418 540 ifShow: false,
  541 + componentProps: {
  542 + maxLength: 36,
  543 + placeholder: '请输入RSA公钥',
  544 + },
419 545 },
420 546 {
421 547 label: '客户端ID',
... ... @@ -423,6 +549,10 @@ export const TokenSchemas: FormSchema[] = [
423 549 field: 'clientId',
424 550 required: true,
425 551 ifShow: false,
  552 + componentProps: {
  553 + maxLength: 36,
  554 + placeholder: '请输入客户端ID',
  555 + },
426 556 },
427 557 {
428 558 label: '用户名',
... ... @@ -430,23 +560,78 @@ export const TokenSchemas: FormSchema[] = [
430 560 field: 'username',
431 561 required: true,
432 562 ifShow: false,
  563 + componentProps: {
  564 + maxLength: 255,
  565 + placeholder: '请输入用户名',
  566 + },
433 567 },
434 568 {
435 569 label: '密码',
436 570 component: 'InputPassword',
437 571 field: 'password',
438 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 592 label: 'id',
442 593 component: 'Input',
443 594 field: 'id',
444 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 615 label: 'tbDeviceId',
448 616 component: 'Input',
449 617 field: 'tbDeviceId',
450 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 1 import { formatToDateTime } from '/@/utils/dateUtil';
2 2 import { FormSchema } from '/@/components/Form';
3 3 import { BasicColumn } from '/@/components/Table';
  4 +
4 5 import { DeviceTypeEnum } from '/@/api/device/model/deviceModel';
5 6
6 7 export const columns: BasicColumn[] = [
... ... @@ -8,25 +9,20 @@ export const columns: BasicColumn[] = [
8 9 title: '设备名称',
9 10 dataIndex: 'name',
10 11 width: 120,
11   - key: 'name',
12 12 },
13 13 {
14 14 title: '设备标签',
15 15 dataIndex: 'label',
16 16 width: 100,
17   - key: 'label',
18 17 },
19 18 {
20 19 title: '设备配置',
21 20 dataIndex: 'deviceProfile.name',
22 21 width: 160,
23   - key: 'deviceProfile.name',
24 22 },
25   -
26 23 {
27 24 title: '设备类型',
28 25 dataIndex: 'deviceType',
29   - key: 'deviceType',
30 26 customRender({ text }) {
31 27 return text === DeviceTypeEnum.GATEWAY
32 28 ? '网关设备'
... ... @@ -39,7 +35,6 @@ export const columns: BasicColumn[] = [
39 35 title: '描述',
40 36 dataIndex: 'description',
41 37 width: 180,
42   - key: 'description',
43 38 },
44 39 ];
45 40 // 实时数据表格
... ... @@ -95,6 +90,9 @@ export const alarmSearchSchemas: FormSchema[] = [
95 90 label: '告警类型',
96 91 component: 'Input',
97 92 colProps: { span: 6 },
  93 + componentProps: {
  94 + maxLength: 36,
  95 + },
98 96 },
99 97 {
100 98 field: 'endTime',
... ... @@ -208,6 +206,9 @@ export const alarmSchemasForm: FormSchema[] = [
208 206 field: 'details',
209 207 label: '详情',
210 208 component: 'InputTextArea',
  209 + componentProps: {
  210 + maxLength: 255,
  211 + },
211 212 },
212 213 ];
213 214
... ... @@ -218,12 +219,18 @@ export const childDeviceSchemas: FormSchema[] = [
218 219 label: '设备配置',
219 220 component: 'Select',
220 221 colProps: { span: 12 },
  222 + componentProps: {
  223 + maxLength: 255,
  224 + },
221 225 },
222 226 {
223 227 field: 'icon',
224 228 label: '设备名称',
225 229 component: 'Input',
226 230 colProps: { span: 12 },
  231 + componentProps: {
  232 + maxLength: 255,
  233 + },
227 234 },
228 235 ];
229 236 export const childDeviceColumns: BasicColumn[] = [
... ...
  1 +import { formatToDate } from '/@/utils/dateUtil';
1 2 import { BasicColumn } from '/@/components/Table';
2 3 import { FormSchema } from '/@/components/Table';
3 4 import { DeviceTypeEnum, DeviceState } from '/@/api/device/model/deviceModel';
  5 +
4 6 // 表格列数据
5 7 export const columns: BasicColumn[] = [
6 8 {
... ... @@ -19,6 +21,7 @@ export const columns: BasicColumn[] = [
19 21 dataIndex: 'deviceProfile.name',
20 22 width: 160,
21 23 slots: { customRender: 'deviceProfile' },
  24 + ellipsis: true,
22 25 },
23 26
24 27 {
... ... @@ -36,10 +39,16 @@ export const columns: BasicColumn[] = [
36 39 width: 120,
37 40 slots: { customRender: 'deviceState' },
38 41 },
39   -
40 42 {
41 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 52 width: 180,
44 53 },
45 54 ];
... ... @@ -76,6 +85,23 @@ export const searchFormSchema: FormSchema[] = [
76 85 field: 'name',
77 86 label: '设备名称',
78 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 6 :destroyOnClose="true"
7 7 @close="closeDrawer"
8 8 :title="deviceDetail.name"
9   - width="78%"
  9 + width="70%"
10 10 >
11 11 <Tabs v-model:activeKey="activeKey" :size="size" type="card">
12 12 <TabPane key="1" tab="详情"
... ... @@ -26,7 +26,7 @@
26 26 import { defineComponent, ref } from 'vue';
27 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 30 import Detail from '../tabs/Detail.vue';
31 31 import RealTimeData from '../tabs/RealTimeData.vue';
32 32 import Alarm from '../tabs/Alarm.vue';
... ... @@ -37,13 +37,12 @@
37 37 components: {
38 38 BasicDrawer,
39 39 Tabs,
40   - TabPane,
  40 + TabPane: Tabs.TabPane,
41 41 Detail,
42 42 RealTimeData,
43 43 Alarm,
44 44 ChildDevice,
45 45 },
46   -
47 46 emits: ['reload', 'register'],
48 47 setup() {
49 48 const activeKey = ref('1');
... ...
... ... @@ -39,9 +39,10 @@
39 39 import { createOrEditDevice } from '/@/api/device/deviceManager';
40 40 import DeviceStep1 from '../step/DeviceStep1.vue';
41 41 import DeviceStep2 from '../step/DeviceStep2.vue';
42   - import { Steps, Step } from 'ant-design-vue';
  42 + import { Steps } from 'ant-design-vue';
43 43 import { useMessage } from '/@/hooks/web/useMessage';
44 44 import { credentialTypeEnum } from '../../config/data';
  45 +
45 46 export default defineComponent({
46 47 name: 'DeviceModal',
47 48 components: {
... ... @@ -49,7 +50,7 @@
49 50 DeviceStep1,
50 51 DeviceStep2,
51 52 Steps,
52   - Step,
  53 + Step: Steps.Step,
53 54 },
54 55 props: {
55 56 userData: { type: Object },
... ...
... ... @@ -44,6 +44,13 @@
44 44 labelWidth: 120,
45 45 schemas: alarmSearchSchemas,
46 46 },
  47 + showTableSetting: true,
  48 + tableSetting: {
  49 + redo: true,
  50 + size: false,
  51 + setting: false,
  52 + fullScreen: false,
  53 + },
47 54 useSearchForm: true,
48 55 bordered: true,
49 56 showIndexColumn: false,
... ...
... ... @@ -10,8 +10,8 @@
10 10 bordered
11 11 :columns="columns"
12 12 :data-source="[deviceDetail]"
  13 + :rowKey="(_, index) => index"
13 14 :pagination="false"
14   - rowKey="tbDeviceId"
15 15 style="width: 800px"
16 16 />
17 17 </div>
... ... @@ -23,7 +23,7 @@
23 23 </div>
24 24 <div v-if="deviceDetail?.deviceInfo?.address" class="mt-4">
25 25 <p>设备位置</p>
26   - <div ref="wrapRef" style="height: 400px; width: 90%"></div>
  26 + <div ref="wrapRef" style="height: 400px; width: 100%"></div>
27 27 </div>
28 28 </div>
29 29 </template>
... ...
... ... @@ -24,7 +24,7 @@
24 24 setup(props) {
25 25 const token: string = getAuthCache(JWT_TOKEN_KEY);
26 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 28 sendValue: JSON.stringify({
29 29 attrSubCmds: [],
30 30 tsSubCmds: [
... ...
... ... @@ -8,7 +8,7 @@
8 8 @cancel="handleCancel"
9 9 >
10 10 <div class="step-form-form">
11   - <a-steps :current="current">
  11 + <a-steps :current="current" @change="handleChange">
12 12 <a-step title="设备配置" />
13 13 <a-step title="传输配置" />
14 14 <a-step title="告警配置" />
... ... @@ -34,10 +34,9 @@
34 34 @next="handleStep3Next"
35 35 @redo="handleRedo"
36 36 /></div>
37   -
38 37 <div v-show="current === 3">
39   - <DeviceProfileStep4 ref="DeviceProfileStep4Ref" @prev="handleStepPrev"
40   - /></div>
  38 + <DeviceProfileStep4 ref="DeviceProfileStep4Ref" @prev="handleStepPrev" />
  39 + </div>
41 40 </div>
42 41 </BasicModal>
43 42 </template>
... ... @@ -86,13 +85,21 @@
86 85 const current = ref(0);
87 86 const isUpdate = ref(true);
88 87 const getTitle = computed(() => (!unref(isUpdate) ? '新增设备配置' : '编辑设备配置'));
  88 + const handleChange = (v) => {
  89 + console.log(v);
  90 + };
89 91 const [register, { closeModal }] = useModalInner(async (data) => {
90 92 isUpdate.value = !!data?.isUpdate;
91 93 if (!unref(isUpdate)) {
92 94 current.value = 0;
  95 + proxy.$refs.DeviceProfileStep3Ref.clearProfileDataFunc();
  96 + proxy.$refs.DeviceProfileStep3Ref.addAlarmRule();
  97 + // proxy.$refs.DeviceProfileStep4Ref.customResetAndFunc();
  98 +
93 99 switch (current.value) {
94 100 case 0:
95 101 proxy.$refs.DeviceProfileStep1Ref.customResetFunc();
  102 + proxy.$refs.DeviceProfileStep1Ref.resetIconFunc();
96 103 break;
97 104 case 1:
98 105 proxy.$refs.DeviceProfileStep2Ref.customResetAndFunc();
... ... @@ -109,32 +116,15 @@
109 116 }
110 117 if (unref(isUpdate)) {
111 118 current.value = 0;
  119 + proxy.$refs.DeviceProfileStep3Ref.clearProfileDataFunc();
  120 + proxy.$refs.DeviceProfileStep3Ref.addAlarmRule();
112 121 postEditId.value = data.record.id;
113 122 const getBackendData = await deviceConfigGetDetail(postEditId.value);
114 123 editEchoData.value = { ...getBackendData };
115   - console.log(editEchoData.value);
116 124 switch (current.value) {
117 125 case 0:
118 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 128 break;
139 129 }
140 130 }
... ... @@ -142,18 +132,132 @@
142 132 function handleStepPrev() {
143 133 current.value--;
144 134 }
145   - function handleStepNext1(v) {
  135 + function handleStepNext1(v, v1) {
  136 + console.log(v, v1);
146 137 current.value++;
147 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 149 function handleStep2Next(v) {
150 150 current.value++;
  151 +
151 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 241 function handleStep3Next(v) {
155 242 current.value++;
156 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 262 function handleRedo() {
159 263 current.value = 0;
... ... @@ -197,6 +301,7 @@
197 301 return;
198 302 };
199 303 return {
  304 + handleChange,
200 305 DeviceProfileStep2Ref,
201 306 DeviceProfileStep3Ref,
202 307 DeviceProfileStep4Ref,
... ...
... ... @@ -2,8 +2,9 @@ import { BasicColumn } from '/@/components/Table';
2 2 import { FormSchema } from '/@/components/Table';
3 3 import { findDictItemByCode } from '/@/api/system/dict';
4 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 9 export const columns: BasicColumn[] = [
9 10 {
... ... @@ -30,23 +31,27 @@ export const columns: BasicColumn[] = [
30 31
31 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 34 field: 'name',
47 35 label: '配置名称',
48 36 component: 'Input',
49 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 68 label: '配置名称',
64 69 required: true,
65 70 component: 'Input',
  71 + componentProps: {
  72 + maxLength: 255,
  73 + placeholder: '请输入配置名称',
  74 + },
66 75 },
67 76 {
68 77 field: 'messageType',
... ... @@ -98,6 +107,11 @@ export const formSchema: FormSchema[] = [
98 107 label: 'accessKeyId',
99 108 required: true,
100 109 component: 'Input',
  110 + componentProps: {
  111 + maxLength: 36,
  112 + placeholder: '请输入accessKeyId',
  113 + },
  114 +
101 115 ifShow: ({ values }) => isMessage(Reflect.get(values, 'messageType')),
102 116 },
103 117 {
... ... @@ -105,6 +119,11 @@ export const formSchema: FormSchema[] = [
105 119 label: 'accessKeySecret',
106 120 required: true,
107 121 component: 'Input',
  122 + componentProps: {
  123 + maxLength: 36,
  124 + placeholder: '请输入accessKeySecret',
  125 + },
  126 +
108 127 ifShow: ({ values }) => isMessage(Reflect.get(values, 'messageType')),
109 128 },
110 129 {
... ... @@ -113,6 +132,11 @@ export const formSchema: FormSchema[] = [
113 132 defaultValue: 'smtp.163.com',
114 133 required: true,
115 134 component: 'Input',
  135 + componentProps: {
  136 + maxLength: 36,
  137 + placeholder: '请输入accessKeySecret',
  138 + },
  139 +
116 140 ifShow: ({ values }) => isEmail(Reflect.get(values, 'messageType')),
117 141 },
118 142 {
... ... @@ -121,6 +145,12 @@ export const formSchema: FormSchema[] = [
121 145 defaultValue: 25,
122 146 required: true,
123 147 component: 'InputNumber',
  148 + rules: numberRule,
  149 + componentProps: {
  150 + maxLength: 36,
  151 + placeholder: '请输入端口',
  152 + },
  153 +
124 154 ifShow: ({ values }) => isEmail(Reflect.get(values, 'messageType')),
125 155 },
126 156 {
... ... @@ -128,6 +158,11 @@ export const formSchema: FormSchema[] = [
128 158 label: '用户名',
129 159 required: true,
130 160 component: 'Input',
  161 + componentProps: {
  162 + maxLength: 255,
  163 + placeholder: '请输入用户名',
  164 + },
  165 +
131 166 ifShow: ({ values }) => isEmail(Reflect.get(values, 'messageType')),
132 167 },
133 168 {
... ... @@ -142,12 +177,46 @@ export const formSchema: FormSchema[] = [
142 177 label: '消息配置',
143 178 component: 'Input',
144 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 199 field: 'id',
148 200 label: '主键',
149 201 component: 'Input',
150 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 222 field: 'status',
... ... @@ -165,5 +234,22 @@ export const formSchema: FormSchema[] = [
165 234 label: '备注',
166 235 field: 'remark',
167 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 21 /></TabPane>
22 22 <TabPane key="3" tab="报警规则">
23 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 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 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 87 </div>
84 88 </div>
85 89 </TabPane>
... ... @@ -93,7 +97,7 @@
93 97 <script lang="ts">
94 98 import { defineComponent, ref, computed, watch } from 'vue';
95 99 import { BasicModal, useModalInner } from '/@/components/Modal';
96   - import { Tabs, TabPane } from 'ant-design-vue';
  100 + import { Tabs } from 'ant-design-vue';
97 101 import { deviceConfigGetDetail } from '/@/api/device/deviceConfigApi';
98 102 import { BasicForm, useForm } from '/@/components/Form/index';
99 103 import {
... ... @@ -116,14 +120,14 @@
116 120
117 121 export default defineComponent({
118 122 name: 'ConfigDrawer',
119   - components: { Tabs, TabPane, BasicModal, BasicForm },
  123 + components: { Tabs, TabPane: Tabs.TabPane, BasicModal, BasicForm },
120 124 emits: ['success', 'register'],
121 125 setup() {
122 126 const activeKey = ref('1');
123 127 const isUpdate = ref(true);
124 128 const descInfo: any = ref(null);
125 129 const dataInfo: any = ref('');
126   - const [registerDetail, { setFieldsValue: setRegisterDetail }] = useForm({
  130 + const [registerDetail, { resetFields, setFieldsValue: setRegisterDetail }] = useForm({
127 131 schemas: step1Schemas,
128 132 actionColOptions: {
129 133 span: 24,
... ... @@ -219,8 +223,10 @@
219 223 const [register] = useModalInner(async (data) => {
220 224 activeKey.value = '1';
221 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 228 try {
  229 + resetFields();
224 230 await setRegisterDetail({ ...descInfo.value });
225 231 } catch (e) {
226 232 return e;
... ... @@ -229,84 +235,90 @@
229 235 const handleChange = (v) => {
230 236 try {
231 237 switch (v) {
232   - case '1':
233   - setRegisterDetail({ ...descInfo.value });
234   - break;
  238 + // case '1':
  239 + // setRegisterDetail({ ...descInfo.value });
  240 + // break;
235 241 case '2':
236 242 setRegisterTrans({
237 243 transportType: descInfo.value.profileData?.transportConfiguration.type,
238 244 });
239 245 break;
240 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 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 322 break;
311 323 }
312 324 } catch (e) {
... ...
... ... @@ -45,12 +45,12 @@
45 45 </BasicTable>
46 46 <DeviceProfileModal v-if="isJudgeStatus" @register="registerModal" @success="handleSuccess" />
47 47 <DeviceConfigDetail @register="registerModalDetail" @success="handleSuccess" />
48   - <ExpExcelModal @register="register1" @success="defaultHeader" />
  48 + <!-- <ExpExcelModal @register="register1" @success="defaultHeader" /> -->
49 49 </div>
50 50 </template>
51 51 <script lang="ts">
52 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 54 import { columns, searchFormSchema } from './device.profile.data';
55 55 import { useMessage } from '/@/hooks/web/useMessage';
56 56 import { deviceConfigGetQuery, deviceConfigDelete } from '/@/api/device/deviceConfigApi';
... ... @@ -58,7 +58,7 @@
58 58 import DeviceProfileModal from '/@/views/device/profile/DeviceProfileModal.vue';
59 59 import DeviceConfigDetail from '/@/views/device/profile/deviceConfigDetail.vue';
60 60 import { ImpExcel, ExcelData } from '/@/components/Excel';
61   - import { jsonToSheetXlsx, ExportModalResult } from '/@/components/Excel';
  61 + // import { jsonToSheetXlsx, ExportModalResult } from '/@/components/Excel';
62 62
63 63 export default defineComponent({
64 64 name: 'DeviceProfileManagement',
... ... @@ -156,23 +156,23 @@
156 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 171 const handleExport = (record: Recordable) => {
172 172 console.log(record);
173   - setTimeout(() => {
174   - openModalExcel();
175   - }, 50);
  173 + // setTimeout(() => {
  174 + // openModalExcel();
  175 + // }, 50);
176 176 };
177 177 function handleImport() {
178 178 console.log('record');
... ... @@ -182,8 +182,8 @@
182 182 }
183 183 return {
184 184 registerModalDetail,
185   - register1,
186   - defaultHeader,
  185 + // register1,
  186 + // defaultHeader,
187 187 useSelectionChange,
188 188 handleTableDel,
189 189 isJudgeStatus,
... ...
1 1 <template>
2 2 <div class="step1">
3 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 45 <BasicForm @register="register" />
5 46 </div>
6 47 </div>
7 48 </template>
8 49 <script lang="ts">
9   - import { defineComponent } from 'vue';
  50 + import { defineComponent, ref } from 'vue';
10 51 import { BasicForm, useForm } from '/@/components/Form';
11 52 import { step1Schemas } from './data';
12 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 60 export default defineComponent({
15 61 components: {
... ... @@ -18,9 +64,13 @@
18 64 [Input.name]: Input,
19 65 [Input.Group.name]: Input.Group,
20 66 [Divider.name]: Divider,
  67 + Upload,
  68 + PlusOutlined,
21 69 },
22 70 emits: ['next', 'resetFunc'],
23 71 setup(_, { emit }) {
  72 + const { createMessage } = useMessage();
  73 +
24 74 const [register, { validate, setFieldsValue, resetFields }] = useForm({
25 75 labelWidth: 100,
26 76 schemas: step1Schemas,
... ... @@ -36,16 +86,59 @@
36 86 const resetFieldsFunc = (v) => {
37 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 122 async function customSubmitFunc() {
40 123 try {
41 124 const values = await validate();
42   - emit('next', values);
  125 + emit('next', values, peresonalPic.value);
43 126 } catch (error) {}
44 127 }
45 128 const customResetFunc = async () => {
46 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 144 </script>
... ...
... ... @@ -31,7 +31,7 @@
31 31 <template v-for="(childItem, createIndex) in item.alarms" :key="childItem.id">
32 32 <div class="aic" style="border: 1px solid #bfbfbf">
33 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 35 ><BasicForm @register="registerFormCreateAlarm" />
36 36 </div>
37 37 <div style="margin-left: 5px; margin-top: -50px">
... ... @@ -78,7 +78,7 @@
78 78 <div style="height: 20px"></div>
79 79 <p>清除报警规则</p>
80 80 <template
81   - v-for="(childClearItem, clearIndexItem) in item.alarms[clearIndex].clearRule"
  81 + v-for="(childClearItem, clearIndexItem) in item.clearRule"
82 82 :key="childClearItem.id"
83 83 >
84 84 <div class="aic mb-1" style="border: 1px solid #bfbfbf">
... ... @@ -222,12 +222,20 @@
222 222 const ruleClearTemplateData: any = ref(null);
223 223 const enableClearTemplateData: any = ref(null);
224 224 const detailClearTemplateData: any = ref(null);
  225 + const scheduleCustomValue: any = ref({});
  226 + const scheduleCustomClearValue: any = ref({});
225 227 const clearIndex = ref(-1);
  228 + const getSchduleCustomValue: any = ref([]);
  229 + const getSchduleClearCustomValue: any = ref([]);
226 230 //告警列表
227 231 let profileData = ref<IProfileData[]>([]);
228 232 const log = (e) => {
229 233 console.log(e);
230 234 };
  235 + //编辑清空操作
  236 + const clearProfileDataFunc = () => {
  237 + unref(profileData).splice(0, 1);
  238 + };
231 239 //删除告警配置
232 240 const deleteAlarmRule = (index: number) => {
233 241 unref(profileData).splice(index, 1);
... ... @@ -254,26 +262,27 @@
254 262 id: Date.now() + Math.random() + '',
255 263 alarmType: '',
256 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 266 propagate: false,
274 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 288 //TODO Mobile dashboard:
... ... @@ -342,6 +351,25 @@
342 351 const resetRegisterFormCreateAlarmFunc = () => {
343 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 374 const retryRegisterFormFunc = (v) => {
347 375 setRegisterForm(v);
... ... @@ -352,6 +380,25 @@
352 380 const retryRegisterFormCreateAlarmFunc = (v) => {
353 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 402 const tempValue1: string = ref<string>('');
356 403 // 添加‘创建条件’
357 404 const addCreateRole = (index: number) => {
... ... @@ -400,27 +447,26 @@
400 447 };
401 448 },
402 449 });
403   -
404 450 unref(profileData)[index].alarms.push({
405 451 id: Date.now() + Math.random() + '',
406 452 alarmType: '',
407 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 470 propagate: false,
425 471 propagateRelationTypes: [''],
426 472 });
... ... @@ -486,12 +532,23 @@
486 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 544 enableTemplateData.value =
490   - v.startsOn == undefined
  545 + v.schedule == 'ANY_TIME'
491 546 ? `始终启用`
492   - : `
  547 + : v.schedule == 'SPECIFIC_TIME'
  548 + ? `
493 549 开始时间:${v.startsOn},结束时间:${v.endsOn},天数:${findDayByValue}
494   - `;
  550 + `
  551 + : `天数:${findDayCustomByValue},开始时间: ${v.startsOn1},结束时间:${v.endsOn1}`;
495 552 };
496 553 //规则条件
497 554 const getAllFieldsRuleFunc = (v, v1) => {
... ... @@ -516,7 +573,7 @@
516 573 }
517 574 });
518 575 ruleTemplateData.value = `
519   - 键名:${v.key1}...操作:${findRuleByValue?.label}...值:${v.value1}
  576 + 键名:${v.key1} 操作:${findRuleByValue?.label} 值:${v.value1}
520 577 `;
521 578
522 579 ruleLastObj.value = v1;
... ... @@ -607,11 +664,23 @@
607 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 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 686 const getAllClearFieldsRuleFunc = (v, v1) => {
... ... @@ -636,7 +705,7 @@
636 705 }
637 706 });
638 707 ruleClearTemplateData.value = `
639   - 键名:${v.key1}...操作:${findRuleByValue?.label}...值:${v.value1}
  708 + 键名:${v.key1} 操作:${findRuleByValue?.label} 值:${v.value1}
640 709 `;
641 710
642 711 ruleLastObj.value = v1;
... ... @@ -677,7 +746,7 @@
677 746 };
678 747 Object.assign(addClearitionalObj.value, getValueConditon);
679 748 };
680   - //用于生成uuid
  749 + //生成uuid
681 750 function generateUUID() {
682 751 let d = new Date().getTime();
683 752 if (window.performance && typeof window.performance.now === 'function') {
... ... @@ -691,28 +760,111 @@
691 760 return uuid;
692 761 }
693 762 const handleFormStep3toStep4Next = async () => {
  763 + console.log(enableObj.value);
694 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 842 const scheduleClearValue = {
696 843 type: enableClearObj.value.schedule,
697 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 847 timezone: enableClearObj.value.timezone,
701 848 };
702 849 const getClearSchedule = {
703   - schedule: scheduleClearValue,
  850 + schedule:
  851 + enableClearObj.value.schedule == 'CUSTOM'
  852 + ? scheduleCustomClearValue.value
  853 + : scheduleClearValue,
704 854 };
705 855 const getClearAdditionalProp = Object.assign({}, detailClearObj.value, getClearSchedule);
706 856 const scheduleValue = {
707 857 type: enableObj.value.schedule,
708 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 861 timezone: enableObj.value.timezone,
712 862 };
713 863 const getSchedule = {
714   - schedule: scheduleValue,
  864 + schedule:
  865 + enableObj.value.schedule == 'CUSTOM' ? scheduleCustomValue.value : scheduleValue,
715 866 };
  867 +
716 868 const getAdditionalProp = Object.assign({}, detailObj.value, getSchedule);
717 869 const getScheduleAndAlarmDetails = Object.assign(
718 870 {},
... ... @@ -746,7 +898,7 @@
746 898 console.log(valueRegisterFormCreateAlarm);
747 899 const getValueRegisterFormHighSetting = {
748 900 propagate: valueRegisterFormHighSetting?.propagate,
749   - propagateRelationTypes: [valueRegisterFormHighSetting?.propagateRelationTypes],
  901 + propagateRelationTypes: [valueRegisterFormHighSetting?.propagateRelationTypes].flat(1),
750 902 };
751 903 Object.assign(
752 904 emptyObj.value,
... ... @@ -756,7 +908,9 @@
756 908 getClearRulesAllObj,
757 909 objectId
758 910 );
759   - alarmss.value.push(emptyObj.value);
  911 + if (alarmss.value.length == 0) {
  912 + alarmss.value.push(emptyObj.value);
  913 + }
760 914 const getAlarms = {
761 915 alarms: alarmss.value,
762 916 };
... ... @@ -795,7 +949,11 @@
795 949 isRuleAlarmRuleConditions.value = 4;
796 950 setTimeout(() => {
797 951 openModal4(true);
798   - proxy.$refs.getChildData1.resetDataFunc();
  952 + try {
  953 + proxy.$refs.getChildData1.resetDataFunc();
  954 + } catch (e) {
  955 + return e;
  956 + }
799 957 }, 50);
800 958 };
801 959 const handleOpenClearEnableRule = () => {
... ... @@ -814,6 +972,19 @@
814 972 };
815 973
816 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 988 clearIndex,
818 989 retryRegisterFormFunc,
819 990 retryRegisterFormHighSettingmFunc,
... ...
... ... @@ -99,7 +99,7 @@ export const formSchema: FormSchema[] = [
99 99 {
100 100 field: 'conditionType',
101 101 label: '条件类型',
102   - colProps: { span: 24 },
  102 + colProps: { span: 13 },
103 103 component: 'Select',
104 104 componentProps: {
105 105 placeholder: '请选择报警日程表',
... ... @@ -177,11 +177,28 @@ export const formSchema: FormSchema[] = [
177 177 {
178 178 field: 'defaultValue',
179 179 label: '持续时间值',
180   - colProps: { span: 24 },
  180 + colProps: { span: 13 },
181 181 component: 'Input',
182 182 componentProps: {
  183 + maxLength: 16,
183 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 202 ifShow: ({ values }) => isWenDu(Reflect.get(values, 'conditionType')),
186 203 show: ({ values }) => {
187 204 return !values.field5;
... ... @@ -210,7 +227,7 @@ export const formSchema: FormSchema[] = [
210 227 {
211 228 field: 'unit',
212 229 label: '时间单位',
213   - colProps: { span: 24 },
  230 + colProps: { span: 13 },
214 231 component: 'Select',
215 232 componentProps: {
216 233 placeholder: '请选择时间单位',
... ... @@ -226,12 +243,28 @@ export const formSchema: FormSchema[] = [
226 243 {
227 244 field: 'defaultValue',
228 245 label: '事件计数值必填',
229   - colProps: { span: 24 },
  246 + colProps: { span: 13 },
230 247 component: 'Input',
231 248 componentProps: {
  249 + maxLength: 2147483637,
232 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 268 ifShow: ({ values }) => isTimeAll(Reflect.get(values, 'conditionType')),
236 269 show: ({ values }) => {
237 270 return !values.field6;
... ... @@ -240,6 +273,7 @@ export const formSchema: FormSchema[] = [
240 273 {
241 274 field: 'inherit',
242 275 label: '',
  276 + colProps: { span: 13 },
243 277 component: 'Checkbox',
244 278 renderComponentContent: 'Inherit from owner',
245 279 ifShow: ({ values }) =>
... ...
... ... @@ -48,7 +48,7 @@ export const formSchema: FormSchema[] = [
48 48 {
49 49 field: 'type',
50 50 label: '键类型',
51   - colProps: { span: 24 },
  51 + colProps: { span: 13 },
52 52 component: 'Select',
53 53 componentProps: {
54 54 placeholder: '请选择键类型',
... ... @@ -62,49 +62,80 @@ export const formSchema: FormSchema[] = [
62 62 {
63 63 field: 'key1',
64 64 label: '键名',
65   - colProps: { span: 24 },
  65 + colProps: { span: 13 },
66 66 component: 'Input',
67 67 componentProps: {
  68 + maxLength: 255,
68 69 placeholder: '请输入键名',
69   - // options: [
70   - // { label: 'active', value: 'active' },
71   - // { label: 'inactivityAlarmTime', value: 'inactivityAlarmTime' },
72   - // { label: 'lastActivityTime', value: 'lastActivityTime' },
73   - // { label: 'lastConnectTime', value: 'lastConnectTime' },
74   - // { label: 'lastDisconnectTime', value: 'lastDisconnectTime' },
75   - // ],
76 70 },
  71 + dynamicRules: () => {
  72 + return [
  73 + {
  74 + required: false,
  75 + validator: (_, value) => {
  76 + if (String(value).length > 255) {
  77 + return Promise.reject('字数不超过255个字');
  78 + }
  79 + return Promise.resolve();
  80 + },
  81 + },
  82 + ];
  83 + },
  84 +
77 85 ifShow: ({ values }) => isShiDu(Reflect.get(values, 'type')),
78 86 },
79 87 {
80 88 field: 'key1',
81 89 label: '键名',
82   - colProps: { span: 24 },
  90 + colProps: { span: 13 },
83 91 component: 'Input',
84 92 componentProps: {
  93 + maxLength: 255,
85 94 placeholder: '请输入键名',
86   - // options: [
87   - // { label: 'CO2', value: 'CO2' },
88   - // { label: 'temp', value: 'temp' },
89   - // { label: 'wet', value: 'wet' },
90   - // ],
  95 + },
  96 + dynamicRules: () => {
  97 + return [
  98 + {
  99 + required: false,
  100 + validator: (_, value) => {
  101 + if (String(value).length > 255) {
  102 + return Promise.reject('字数不超过255个字');
  103 + }
  104 + return Promise.resolve();
  105 + },
  106 + },
  107 + ];
91 108 },
92 109 ifShow: ({ values }) => isWenDu(Reflect.get(values, 'type')),
93 110 },
94 111 {
95 112 field: 'key1',
96 113 label: '键名',
97   - colProps: { span: 24 },
  114 + colProps: { span: 13 },
98 115 component: 'Input',
99 116 componentProps: {
  117 + maxLength: 255,
100 118 placeholder: '请输入键名',
101 119 },
  120 + dynamicRules: () => {
  121 + return [
  122 + {
  123 + required: false,
  124 + validator: (_, value) => {
  125 + if (String(value).length > 255) {
  126 + return Promise.reject('字数不超过255个字');
  127 + }
  128 + return Promise.resolve();
  129 + },
  130 + },
  131 + ];
  132 + },
102 133 ifShow: ({ values }) => isTimeAll(Reflect.get(values, 'type')),
103 134 },
104 135 {
105 136 field: 'type1',
106 137 label: '值类型',
107   - colProps: { span: 24 },
  138 + colProps: { span: 13 },
108 139 component: 'Select',
109 140 componentProps: {
110 141 placeholder: '请选择值类型',
... ... @@ -122,7 +153,7 @@ export const formSchema: FormSchema[] = [
122 153 {
123 154 field: 'operation',
124 155 label: '操作',
125   - colProps: { span: 24 },
  156 + colProps: { span: 13 },
126 157 component: 'Select',
127 158 componentProps: {
128 159 placeholder: '请选择操作',
... ... @@ -141,7 +172,7 @@ export const formSchema: FormSchema[] = [
141 172 field: '',
142 173 label: '大小写',
143 174 component: 'Checkbox',
144   - colProps: { span: 24 },
  175 + colProps: { span: 13 },
145 176 renderComponentContent: '忽略大小写',
146 177 ifShow: ({ values }) => isString(Reflect.get(values, 'type1')),
147 178 },
... ... @@ -180,11 +211,28 @@ export const formSchema: FormSchema[] = [
180 211 {
181 212 field: 'value1',
182 213 label: '默认值',
183   - colProps: { span: 24 },
  214 + colProps: { span: 13 },
184 215 component: 'Input',
185 216 componentProps: {
  217 + maxLength: 16,
186 218 placeholder: '请输入默认值(数字)',
187 219 },
  220 + dynamicRules: () => {
  221 + return [
  222 + {
  223 + validator: (_, value) => {
  224 + if (!value) {
  225 + return Promise.reject('默认值不能为空');
  226 + }
  227 + const pwdRegex = new RegExp(/-?\d+/);
  228 + if (!pwdRegex.test(value)) {
  229 + return Promise.reject('只能为数字,且最长不超过16位');
  230 + }
  231 + return Promise.resolve();
  232 + },
  233 + },
  234 + ];
  235 + },
188 236 ifShow: ({ values }) => isString(Reflect.get(values, 'type1')),
189 237 show: ({ values }) => {
190 238 return !values.field5;
... ... @@ -203,7 +251,7 @@ export const formSchema: FormSchema[] = [
203 251 {
204 252 field: 'operation',
205 253 label: '操作',
206   - colProps: { span: 24 },
  254 + colProps: { span: 13 },
207 255 component: 'Select',
208 256 componentProps: {
209 257 placeholder: '请选择操作',
... ... @@ -254,11 +302,27 @@ export const formSchema: FormSchema[] = [
254 302 {
255 303 field: 'value1',
256 304 label: '值',
257   - colProps: { span: 24 },
  305 + colProps: { span: 13 },
258 306 component: 'Input',
259 307 componentProps: {
260 308 placeholder: '请输入值(数字)',
261 309 },
  310 + dynamicRules: () => {
  311 + return [
  312 + {
  313 + validator: (_, value) => {
  314 + if (!value) {
  315 + return Promise.reject('值');
  316 + }
  317 + const pwdRegex = new RegExp(/-?\d+/);
  318 + if (!pwdRegex.test(value)) {
  319 + return Promise.reject('只能为数字,且最长不超过16位');
  320 + }
  321 + return Promise.resolve();
  322 + },
  323 + },
  324 + ];
  325 + },
262 326 ifShow: ({ values }) => isNumeric(Reflect.get(values, 'type1')),
263 327 show: ({ values }) => {
264 328 return !values.field6;
... ... @@ -278,7 +342,7 @@ export const formSchema: FormSchema[] = [
278 342 {
279 343 field: 'operation',
280 344 label: '操作',
281   - colProps: { span: 24 },
  345 + colProps: { span: 13 },
282 346 component: 'Select',
283 347 componentProps: {
284 348 placeholder: '请选择操作',
... ... @@ -292,6 +356,7 @@ export const formSchema: FormSchema[] = [
292 356 {
293 357 field: '',
294 358 label: '默认值',
  359 + colProps: { span: 13 },
295 360 component: 'Checkbox',
296 361 renderComponentContent: '真',
297 362 ifShow: ({ values }) => isBoolean(Reflect.get(values, 'type1')),
... ... @@ -344,7 +409,7 @@ export const formSchema: FormSchema[] = [
344 409 {
345 410 field: 'operation',
346 411 label: '操作',
347   - colProps: { span: 24 },
  412 + colProps: { span: 13 },
348 413 component: 'Select',
349 414 componentProps: {
350 415 placeholder: '请选择操作',
... ... @@ -364,7 +429,7 @@ export const formSchema: FormSchema[] = [
364 429 component: 'DatePicker',
365 430 label: '请选择日期',
366 431 colProps: {
367   - span: 12,
  432 + span: 13,
368 433 },
369 434 ifShow: ({ values }) => isComplex(Reflect.get(values, 'type1')),
370 435 show: ({ values }) => {
... ... @@ -376,7 +441,7 @@ export const formSchema: FormSchema[] = [
376 441 component: 'TimePicker',
377 442 label: '请选择时间',
378 443 colProps: {
379   - span: 8,
  444 + span: 13,
380 445 },
381 446 ifShow: ({ values }) => isComplex(Reflect.get(values, 'type1')),
382 447 show: ({ values }) => {
... ...
... ... @@ -4,10 +4,11 @@ export const formSchema: FormSchema[] = [
4 4 {
5 5 field: 'alarmDetails',
6 6 label: '报警详细信息',
7   - colProps: { span: 12 },
  7 + colProps: { span: 13 },
8 8 required: true,
9 9 component: 'Input',
10 10 componentProps: {
  11 + maxLength: 255,
11 12 placeholder: '请输入报警详细信息',
12 13 },
13 14 },
... ...
... ... @@ -42,16 +42,16 @@ export const formSchema: FormSchema[] = [
42 42 field: 'timezone',
43 43 label: '时区',
44 44 colProps: { span: 12 },
45   -
46 45 required: true,
47 46 component: 'Select',
  47 + defaultValue: 'Asia/Shanghai (UTC+08:00)',
48 48 componentProps: {
49 49 placeholder: '请选择时区',
50 50 options: [
51   - { label: 'Africa/Abidjan (UTC+00:00)', value: 'Africa/Abidjan (UTC+00:00)' },
52   - { label: 'Africa/Accra (UTC+00:00)', value: 'Africa/Accra (UTC+00:00)' },
53   - { label: 'Africa/Addis Ababa (UTC+03:00)', value: 'Africa/Addis Ababa (UTC+03:00)' },
54   - { label: 'Africa/Asmara (UTC+03:00)', value: 'Africa/Asmara (UTC+03:00)' },
  51 + { label: 'Asia/Shanghai (UTC+08:00)', value: 'Asia/Shanghai' },
  52 + { label: 'Africa/Accra (UTC+00:00)', value: 'Africa/Accra' },
  53 + { label: 'Africa/Addis Ababa (UTC+03:00)', value: 'Africa/Addis Ababa' },
  54 + { label: 'Africa/Asmara (UTC+03:00)', value: 'Africa/Asmara' },
55 55 ],
56 56 },
57 57 ifShow: ({ values }) =>
... ... @@ -60,18 +60,28 @@ export const formSchema: FormSchema[] = [
60 60
61 61 {
62 62 field: 'daysOfWeek1',
63   - component: 'Checkbox',
64   - label: '星期一',
  63 + component: 'CheckboxGroup',
  64 + label: '天',
65 65 colProps: {
66 66 span: 8,
67 67 },
68   - renderComponentContent: '',
  68 + componentProps: {
  69 + options: [
  70 + {
  71 + label: '星期一',
  72 + value: '1',
  73 + },
  74 + ],
  75 + },
69 76 ifShow: ({ values }) => isTimeAll(Reflect.get(values, 'schedule')),
70 77 },
71 78 {
72 79 field: 'startsOn1',
73 80 component: 'TimePicker',
74 81 label: '开始时间选择',
  82 + componentProps: {
  83 + valueFormat: 'HH:mm:ss',
  84 + },
75 85 colProps: {
76 86 span: 8,
77 87 },
... ... @@ -81,6 +91,9 @@ export const formSchema: FormSchema[] = [
81 91 field: 'endsOn1',
82 92 component: 'TimePicker',
83 93 label: '结束时间选择',
  94 + componentProps: {
  95 + valueFormat: 'HH:mm:ss',
  96 + },
84 97 colProps: {
85 98 span: 8,
86 99 },
... ... @@ -89,18 +102,28 @@ export const formSchema: FormSchema[] = [
89 102
90 103 {
91 104 field: 'daysOfWeek2',
92   - component: 'Checkbox',
93   - label: '星期二',
  105 + component: 'CheckboxGroup',
  106 + label: '天',
94 107 colProps: {
95 108 span: 8,
96 109 },
97   - renderComponentContent: '',
  110 + componentProps: {
  111 + options: [
  112 + {
  113 + label: '星期二',
  114 + value: '2',
  115 + },
  116 + ],
  117 + },
98 118 ifShow: ({ values }) => isTimeAll(Reflect.get(values, 'schedule')),
99 119 },
100 120 {
101 121 field: 'startsOn2',
102 122 component: 'TimePicker',
103 123 label: '开始时间选择',
  124 + componentProps: {
  125 + valueFormat: 'HH:mm:ss',
  126 + },
104 127 colProps: {
105 128 span: 8,
106 129 },
... ... @@ -110,6 +133,9 @@ export const formSchema: FormSchema[] = [
110 133 field: 'endsOn2',
111 134 component: 'TimePicker',
112 135 label: '结束时间选择',
  136 + componentProps: {
  137 + valueFormat: 'HH:mm:ss',
  138 + },
113 139 colProps: {
114 140 span: 8,
115 141 },
... ... @@ -117,18 +143,28 @@ export const formSchema: FormSchema[] = [
117 143 },
118 144 {
119 145 field: 'daysOfWeek3',
120   - component: 'Checkbox',
121   - label: '星期三',
  146 + component: 'CheckboxGroup',
  147 + label: '天',
122 148 colProps: {
123 149 span: 8,
124 150 },
125   - renderComponentContent: '',
  151 + componentProps: {
  152 + options: [
  153 + {
  154 + label: '星期三',
  155 + value: '3',
  156 + },
  157 + ],
  158 + },
126 159 ifShow: ({ values }) => isTimeAll(Reflect.get(values, 'schedule')),
127 160 },
128 161 {
129 162 field: 'startsOn3',
130 163 component: 'TimePicker',
131 164 label: '开始时间选择',
  165 + componentProps: {
  166 + valueFormat: 'HH:mm:ss',
  167 + },
132 168 colProps: {
133 169 span: 8,
134 170 },
... ... @@ -138,6 +174,9 @@ export const formSchema: FormSchema[] = [
138 174 field: 'endsOn3',
139 175 component: 'TimePicker',
140 176 label: '结束时间选择',
  177 + componentProps: {
  178 + valueFormat: 'HH:mm:ss',
  179 + },
141 180 colProps: {
142 181 span: 8,
143 182 },
... ... @@ -145,18 +184,28 @@ export const formSchema: FormSchema[] = [
145 184 },
146 185 {
147 186 field: 'daysOfWeek4',
148   - component: 'Checkbox',
149   - label: '星期四',
  187 + component: 'CheckboxGroup',
  188 + label: '天',
150 189 colProps: {
151 190 span: 8,
152 191 },
153   - renderComponentContent: '',
  192 + componentProps: {
  193 + options: [
  194 + {
  195 + label: '星期四',
  196 + value: '4',
  197 + },
  198 + ],
  199 + },
154 200 ifShow: ({ values }) => isTimeAll(Reflect.get(values, 'schedule')),
155 201 },
156 202 {
157 203 field: 'startsOn4',
158 204 component: 'TimePicker',
159 205 label: '开始时间选择',
  206 + componentProps: {
  207 + valueFormat: 'HH:mm:ss',
  208 + },
160 209 colProps: {
161 210 span: 8,
162 211 },
... ... @@ -166,6 +215,9 @@ export const formSchema: FormSchema[] = [
166 215 field: 'endsOn4',
167 216 component: 'TimePicker',
168 217 label: '结束时间选择',
  218 + componentProps: {
  219 + valueFormat: 'HH:mm:ss',
  220 + },
169 221 colProps: {
170 222 span: 8,
171 223 },
... ... @@ -173,18 +225,28 @@ export const formSchema: FormSchema[] = [
173 225 },
174 226 {
175 227 field: 'daysOfWeek5',
176   - component: 'Checkbox',
177   - label: '星期五',
  228 + component: 'CheckboxGroup',
  229 + label: '天',
178 230 colProps: {
179 231 span: 8,
180 232 },
181   - renderComponentContent: '',
  233 + componentProps: {
  234 + options: [
  235 + {
  236 + label: '星期五',
  237 + value: '5',
  238 + },
  239 + ],
  240 + },
182 241 ifShow: ({ values }) => isTimeAll(Reflect.get(values, 'schedule')),
183 242 },
184 243 {
185 244 field: 'startsOn5',
186 245 component: 'TimePicker',
187 246 label: '开始时间选择',
  247 + componentProps: {
  248 + valueFormat: 'HH:mm:ss',
  249 + },
188 250 colProps: {
189 251 span: 8,
190 252 },
... ... @@ -194,6 +256,9 @@ export const formSchema: FormSchema[] = [
194 256 field: 'endsOn5',
195 257 component: 'TimePicker',
196 258 label: '结束时间选择',
  259 + componentProps: {
  260 + valueFormat: 'HH:mm:ss',
  261 + },
197 262 colProps: {
198 263 span: 8,
199 264 },
... ... @@ -201,18 +266,28 @@ export const formSchema: FormSchema[] = [
201 266 },
202 267 {
203 268 field: 'daysOfWeek6',
204   - component: 'Checkbox',
205   - label: '星期六',
  269 + component: 'CheckboxGroup',
  270 + label: '天',
206 271 colProps: {
207 272 span: 8,
208 273 },
209   - renderComponentContent: '',
  274 + componentProps: {
  275 + options: [
  276 + {
  277 + label: '星期六',
  278 + value: '6',
  279 + },
  280 + ],
  281 + },
210 282 ifShow: ({ values }) => isTimeAll(Reflect.get(values, 'schedule')),
211 283 },
212 284 {
213 285 field: 'startsOn6',
214 286 component: 'TimePicker',
215 287 label: '开始时间选择',
  288 + componentProps: {
  289 + valueFormat: 'HH:mm:ss',
  290 + },
216 291 colProps: {
217 292 span: 8,
218 293 },
... ... @@ -222,6 +297,9 @@ export const formSchema: FormSchema[] = [
222 297 field: 'endsOn6',
223 298 component: 'TimePicker',
224 299 label: '结束时间选择',
  300 + componentProps: {
  301 + valueFormat: 'HH:mm:ss',
  302 + },
225 303 colProps: {
226 304 span: 8,
227 305 },
... ... @@ -229,18 +307,28 @@ export const formSchema: FormSchema[] = [
229 307 },
230 308 {
231 309 field: 'daysOfWeek7',
232   - component: 'Checkbox',
233   - label: '星期七',
  310 + component: 'CheckboxGroup',
  311 + label: '天',
234 312 colProps: {
235 313 span: 8,
236 314 },
237   - renderComponentContent: '',
  315 + componentProps: {
  316 + options: [
  317 + {
  318 + label: '星期七',
  319 + value: '7',
  320 + },
  321 + ],
  322 + },
238 323 ifShow: ({ values }) => isTimeAll(Reflect.get(values, 'schedule')),
239 324 },
240 325 {
241 326 field: 'startsOn7',
242 327 component: 'TimePicker',
243 328 label: '开始时间选择',
  329 + componentProps: {
  330 + valueFormat: 'HH:mm:ss',
  331 + },
244 332 colProps: {
245 333 span: 8,
246 334 },
... ... @@ -250,6 +338,9 @@ export const formSchema: FormSchema[] = [
250 338 field: 'endsOn7',
251 339 component: 'TimePicker',
252 340 label: '结束时间选择',
  341 + componentProps: {
  342 + valueFormat: 'HH:mm:ss',
  343 + },
253 344 colProps: {
254 345 span: 8,
255 346 },
... ...
... ... @@ -13,7 +13,8 @@ export const step1Schemas: FormSchema[] = [
13 13 required: true,
14 14 component: 'Input',
15 15 componentProps: {
16   - maxLength: 30,
  16 + maxLength: 255,
  17 + placeholder: '请输入配置名称',
17 18 },
18 19 },
19 20 //规则链(string)
... ... @@ -37,17 +38,6 @@ export const step1Schemas: FormSchema[] = [
37 38 immediate: true,
38 39 },
39 40 },
40   - // {
41   - // field: 'icon',
42   - // component: 'Upload',
43   - // label: '请上传图片',
44   - // colProps: {
45   - // span: 8,
46   - // },
47   - // componentProps: {
48   - // // api: uploadApi,
49   - // },
50   - // },
51 41 {
52 42 field: 'defaultQueueName',
53 43 label: '处理队列',
... ... @@ -65,6 +55,23 @@ export const step1Schemas: FormSchema[] = [
65 55 label: '描述',
66 56 field: 'description',
67 57 component: 'InputTextArea',
  58 + componentProps: {
  59 + maxLength: 255,
  60 + placeholder: '请输入描述',
  61 + },
  62 + dynamicRules: () => {
  63 + return [
  64 + {
  65 + required: false,
  66 + validator: (_, value) => {
  67 + if (String(value).length > 255) {
  68 + return Promise.reject('字数不超过255个字');
  69 + }
  70 + return Promise.resolve();
  71 + },
  72 + },
  73 + ];
  74 + },
68 75 },
69 76 ];
70 77
... ... @@ -96,8 +103,22 @@ export const step3Schemas: FormSchema[] = [
96 103 span: 12,
97 104 },
98 105 componentProps: {
  106 + maxLength: 255,
99 107 placeholder: '请输入报警类型',
100 108 },
  109 + dynamicRules: () => {
  110 + return [
  111 + {
  112 + required: false,
  113 + validator: (_, value) => {
  114 + if (String(value).length > 255) {
  115 + return Promise.reject('字数不超过255个字');
  116 + }
  117 + return Promise.resolve();
  118 + },
  119 + },
  120 + ];
  121 + },
101 122 },
102 123 ];
103 124
... ... @@ -116,7 +137,21 @@ export const step3ViewHighSetting: FormSchema[] = [
116 137 span: 11,
117 138 },
118 139 componentProps: {
119   - placeholder: '要传递的关联类型',
  140 + maxLength: 255,
  141 + placeholder: '请输入关联类型',
  142 + },
  143 + dynamicRules: () => {
  144 + return [
  145 + {
  146 + required: false,
  147 + validator: (_, value) => {
  148 + if (String(value).length > 255) {
  149 + return Promise.reject('字数不超过255个字');
  150 + }
  151 + return Promise.resolve();
  152 + },
  153 + },
  154 + ];
120 155 },
121 156 },
122 157 ];
... ... @@ -136,7 +171,21 @@ export const step3HighSetting: FormSchema[] = [
136 171 span: 11,
137 172 },
138 173 componentProps: {
139   - placeholder: '要传递的关联类型',
  174 + maxLength: 255,
  175 + placeholder: '请输入关联类型',
  176 + },
  177 + dynamicRules: () => {
  178 + return [
  179 + {
  180 + required: false,
  181 + validator: (_, value) => {
  182 + if (String(value).length > 255) {
  183 + return Promise.reject('字数不超过255个字');
  184 + }
  185 + return Promise.resolve();
  186 + },
  187 + },
  188 + ];
140 189 },
141 190 ifShow: ({ values }) => !!values.propagate,
142 191 },
... ... @@ -152,7 +201,7 @@ export const step3CreateAlarm: FormSchema[] = [
152 201 colProps: {
153 202 span: 16,
154 203 },
155   - componentProps({ formModel }) {
  204 + componentProps() {
156 205 return {
157 206 placeholder: '请选择严重程度',
158 207 options: [
... ... @@ -216,7 +265,9 @@ export const alertContactsSchemas: FormSchema[] = [
216 265 field: 'alarmContactId',
217 266 label: '告警通知联系人',
218 267 component: 'ApiSelect',
  268 + required: true,
219 269 componentProps: {
  270 + placeholder: '请选择告警通知联系人',
220 271 api: alarmContactGetPage,
221 272 labelField: 'username',
222 273 valueField: 'id',
... ... @@ -229,6 +280,7 @@ export const alertContactsSchemas: FormSchema[] = [
229 280 required: true,
230 281 component: 'ApiSelect',
231 282 componentProps: {
  283 + placeholder: '请选择告警通知方式',
232 284 api: findDictItemByCode,
233 285 params: {
234 286 dictCode: 'message_type',
... ...
... ... @@ -26,7 +26,7 @@ interface IAlarms {
26 26 id: string;
27 27 alarmType: string;
28 28 createRules: ICreateRule;
29   - clearRule?: IClearRule[];
  29 + // clearRule?: IClearRule[];
30 30 propagate: boolean;
31 31 propagateRelationTypes: string[];
32 32 }
... ... @@ -36,4 +36,5 @@ export interface IProfileData {
36 36 transportConfiguration?: ITansportConfiguration;
37 37 provisionConfiguration?: provisionConfigurationD;
38 38 alarms?: IAlarms[];
  39 + clearRule?: IClearRule[];
39 40 }
... ...
1   -import { MessageTypeEnum } from '/@/api/tenant/tenantInfo';
2 1 import { BasicColumn } from '/@/components/Table';
3 2 import { FormSchema } from '/@/components/Table';
4 3 import { h } from 'vue';
... ... @@ -115,6 +114,10 @@ export const formSchema: FormSchema[] = [
115 114 label: '配置名称',
116 115 required: true,
117 116 component: 'Input',
  117 + componentProps: {
  118 + maxLength: 30,
  119 + placeholder: '请输入配置名称',
  120 + },
118 121 },
119 122 {
120 123 field: 'messageType',
... ... @@ -150,12 +153,22 @@ export const formSchema: FormSchema[] = [
150 153 label: 'accessKeyId',
151 154 required: true,
152 155 component: 'Input',
  156 + componentProps: {
  157 + maxLength: 36,
  158 + placeholder: '请输入accessKeyId',
  159 + },
  160 +
153 161 ifShow: ({ values }) => isMessage(Reflect.get(values, 'messageType')),
154 162 },
155 163 {
156 164 field: 'accessKeySecret',
157 165 label: 'accessKeySecret',
158 166 required: true,
  167 + componentProps: {
  168 + maxLength: 36,
  169 + placeholder: '请输入accessKeySecret',
  170 + },
  171 +
159 172 component: 'Input',
160 173 ifShow: ({ values }) => isMessage(Reflect.get(values, 'messageType')),
161 174 },
... ... @@ -165,6 +178,11 @@ export const formSchema: FormSchema[] = [
165 178 defaultValue: 'smtp.163.com',
166 179 required: true,
167 180 component: 'Input',
  181 + componentProps: {
  182 + maxLength: 36,
  183 + placeholder: '请输入服务器地址',
  184 + },
  185 +
168 186 ifShow: ({ values }) => isEmail(Reflect.get(values, 'messageType')),
169 187 },
170 188 {
... ... @@ -172,6 +190,11 @@ export const formSchema: FormSchema[] = [
172 190 label: '端口',
173 191 defaultValue: 25,
174 192 required: true,
  193 + componentProps: {
  194 + maxLength: 36,
  195 + placeholder: '请输入端口',
  196 + },
  197 +
175 198 component: 'InputNumber',
176 199 ifShow: ({ values }) => isEmail(Reflect.get(values, 'messageType')),
177 200 },
... ... @@ -179,6 +202,11 @@ export const formSchema: FormSchema[] = [
179 202 field: 'username',
180 203 label: '用户名',
181 204 required: true,
  205 + componentProps: {
  206 + maxLength: 255,
  207 + placeholder: '请输入用户名',
  208 + },
  209 +
182 210 component: 'Input',
183 211 ifShow: ({ values }) => isEmail(Reflect.get(values, 'messageType')),
184 212 },
... ... @@ -186,6 +214,7 @@ export const formSchema: FormSchema[] = [
186 214 field: 'password',
187 215 label: '密码',
188 216 required: true,
  217 +
189 218 component: 'InputPassword',
190 219 ifShow: ({ values }) => isEmail(Reflect.get(values, 'messageType')),
191 220 },
... ... @@ -194,12 +223,46 @@ export const formSchema: FormSchema[] = [
194 223 label: '消息配置',
195 224 component: 'Input',
196 225 show: false,
  226 + componentProps: {
  227 + maxLength: 255,
  228 + placeholder: '请输入消息配置',
  229 + },
  230 + dynamicRules: () => {
  231 + return [
  232 + {
  233 + required: false,
  234 + validator: (_, value) => {
  235 + if (String(value).length > 255) {
  236 + return Promise.reject('字数不超过255个字');
  237 + }
  238 + return Promise.resolve();
  239 + },
  240 + },
  241 + ];
  242 + },
197 243 },
198 244 {
199 245 field: 'id',
200 246 label: '主键',
201 247 component: 'Input',
202 248 show: false,
  249 + componentProps: {
  250 + maxLength: 36,
  251 + placeholder: '请输入主键',
  252 + },
  253 + dynamicRules: () => {
  254 + return [
  255 + {
  256 + required: false,
  257 + validator: (_, value) => {
  258 + if (String(value).length > 36) {
  259 + return Promise.reject('字数不超过255个字');
  260 + }
  261 + return Promise.resolve();
  262 + },
  263 + },
  264 + ];
  265 + },
203 266 },
204 267 {
205 268 field: 'status',
... ... @@ -216,6 +279,24 @@ export const formSchema: FormSchema[] = [
216 279 {
217 280 label: '备注',
218 281 field: 'remark',
  282 + componentProps: {
  283 + maxLength: 255,
  284 + placeholder: '请输入备注',
  285 + },
  286 + dynamicRules: () => {
  287 + return [
  288 + {
  289 + required: false,
  290 + validator: (_, value) => {
  291 + if (String(value).length > 255) {
  292 + return Promise.reject('字数不超过255个字');
  293 + }
  294 + return Promise.resolve();
  295 + },
  296 + },
  297 + ];
  298 + },
  299 +
219 300 component: 'InputTextArea',
220 301 },
221 302 {
... ... @@ -223,5 +304,22 @@ export const formSchema: FormSchema[] = [
223 304 field: 'tenantId',
224 305 component: 'Input',
225 306 show: false,
  307 + componentProps: {
  308 + maxLength: 36,
  309 + placeholder: '请输入租户ID',
  310 + },
  311 + dynamicRules: () => {
  312 + return [
  313 + {
  314 + required: false,
  315 + validator: (_, value) => {
  316 + if (String(value).length > 36) {
  317 + return Promise.reject('字数不超过255个字');
  318 + }
  319 + return Promise.resolve();
  320 + },
  321 + },
  322 + ];
  323 + },
226 324 },
227 325 ];
... ...
src/views/message/records/data.ts renamed from src/views/message/records/data.tsx
... ... @@ -15,37 +15,3 @@ export const achieveList: TabItem[] = [
15 15 component: 'EmailLog',
16 16 },
17 17 ];
18   -
19   -export const actions: any[] = [
20   - { icon: 'clarity:star-line', text: '156', color: '#018ffb' },
21   - { icon: 'bx:bxs-like', text: '156', color: '#459ae8' },
22   - { icon: 'bx:bxs-message-dots', text: '2', color: '#42d27d' },
23   -];
24   -
25   -export const articleList = (() => {
26   - const result: any[] = [];
27   - for (let i = 0; i < 4; i++) {
28   - result.push({
29   - title: 'Vben Admin',
30   - description: ['Vben', '设计语言', 'Typescript'],
31   - content: '基于Vue Next, TypeScript, Ant Design实现的一套完整的企业级后台管理系统。',
32   - time: '2020-11-14 11:20',
33   - });
34   - }
35   - return result;
36   -})();
37   -
38   -export const applicationList = (() => {
39   - const result: any[] = [];
40   - for (let i = 0; i < 8; i++) {
41   - result.push({
42   - title: 'Vben Admin',
43   - icon: 'emojione-monotone:letter-a',
44   - color: '#1890ff',
45   - active: '100',
46   - new: '1,799',
47   - download: 'bx:bx-download',
48   - });
49   - }
50   - return result;
51   -})();
... ...
... ... @@ -11,7 +11,7 @@
11 11 </template>
12 12
13 13 <script lang="ts">
14   - import { Tabs, TabPane } from 'ant-design-vue';
  14 + import { Tabs } from 'ant-design-vue';
15 15 import { defineComponent } from 'vue';
16 16 import SmsLog from './item/SmsLog.vue';
17 17 import EmailLog from './item/EmailLog.vue';
... ... @@ -20,7 +20,7 @@
20 20 export default defineComponent({
21 21 components: {
22 22 Tabs,
23   - TabPane,
  23 + TabPane: Tabs.TabPane,
24 24 SmsLog,
25 25 EmailLog,
26 26 },
... ...
... ... @@ -3,6 +3,14 @@
3 3 <BasicTable @register="registerTable">
4 4 <template #toolbar>
5 5 <a-button type="primary" @click="handleCreate"> 导出 </a-button>
  6 + <a-button
  7 + type="primary"
  8 + color="error"
  9 + @click="handleDeleteOrBatchDelete(null)"
  10 + :disabled="hasBatchDelete"
  11 + >
  12 + 批量删除
  13 + </a-button>
6 14 </template>
7 15 <template #action="{ record }">
8 16 <TableAction
... ... @@ -18,7 +26,7 @@
18 26 color: 'error',
19 27 popConfirm: {
20 28 title: '是否确认删除',
21   - confirm: handleDelete.bind(null, record),
  29 + confirm: handleDeleteOrBatchDelete.bind(null, record),
22 30 },
23 31 },
24 32 ]"
... ... @@ -33,16 +41,19 @@
33 41 import { BasicTable, useTable, TableAction } from '/@/components/Table';
34 42 import { useDrawerInner } from '/@/components/Drawer';
35 43 import { columns, searchFormSchema } from './email.data';
36   - import { useMessage } from '/@/hooks/web/useMessage';
37 44 import { mailLogPage, deleteMailLog } from '/@/api/message/records';
38 45 import { useModal } from '/@/components/Modal';
39 46 import EmailDetail from '/@/views/message/records/item/EmailDetail.vue';
  47 + import { useBatchDelete } from '/@/hooks/web/useBatchDelete';
40 48 export default defineComponent({
41 49 name: 'EmailLog',
42 50 components: { EmailDetail, BasicTable, TableAction },
43 51 setup() {
44 52 const [registerModal, { openModal }] = useModal();
45   - const { createMessage } = useMessage();
  53 + const { hasBatchDelete, selectionOptions, handleDeleteOrBatchDelete } = useBatchDelete(
  54 + deleteMailLog,
  55 + handleSuccess
  56 + );
46 57 const [register] = useDrawerInner(() => {});
47 58 const [registerTable, { reload }] = useTable({
48 59 title: '邮件发送列表',
... ... @@ -64,7 +75,7 @@
64 75 slots: { customRender: 'action' },
65 76 fixed: 'right',
66 77 },
67   - immediate: true,
  78 + ...selectionOptions,
68 79 });
69 80
70 81 function handleCreate() {}
... ... @@ -75,14 +86,6 @@
75 86 });
76 87 }
77 88
78   - function handleDelete(record: Recordable) {
79   - let ids = [record.id];
80   - deleteMailLog(ids).then((result) => {
81   - createMessage.success(result.message);
82   - handleSuccess();
83   - });
84   - }
85   -
86 89 function handleSuccess() {
87 90 reload();
88 91 }
... ... @@ -92,7 +95,8 @@
92 95 registerTable,
93 96 registerModal,
94 97 handleCreate,
95   - handleDelete,
  98 + hasBatchDelete,
  99 + handleDeleteOrBatchDelete,
96 100 handleModal,
97 101 handleSuccess,
98 102 };
... ...
... ... @@ -2,7 +2,15 @@
2 2 <div style="background-color: #f0f2f5">
3 3 <BasicTable @register="registerTable">
4 4 <template #toolbar>
5   - <a-button type="primary" @click="handleCreate"> 导出 </a-button>
  5 + <a-button type="primary" @click="handleExport"> 导出 </a-button>
  6 + <a-button
  7 + type="primary"
  8 + color="error"
  9 + @click="handleDeleteOrBatchDelete(null)"
  10 + :disabled="hasBatchDelete"
  11 + >
  12 + 批量删除
  13 + </a-button>
6 14 </template>
7 15 <template #action="{ record }">
8 16 <TableAction
... ... @@ -18,7 +26,7 @@
18 26 color: 'error',
19 27 popConfirm: {
20 28 title: '是否确认删除',
21   - confirm: handleDelete.bind(null, record),
  29 + confirm: handleDeleteOrBatchDelete.bind(null, record),
22 30 },
23 31 },
24 32 ]"
... ... @@ -29,21 +37,22 @@
29 37 </template>
30 38 <script lang="ts">
31 39 import { defineComponent, h } from 'vue';
32   -
33 40 import { BasicTable, useTable, TableAction } from '/@/components/Table';
34   - import { useDrawerInner } from '/@/components/Drawer';
35 41 import { columns, searchFormSchema } from './sms.data';
36 42 import { Modal } from 'ant-design-vue';
37   - import { useMessage } from '/@/hooks/web/useMessage';
38 43 import { smsLogPage, deleteSmsLog } from '/@/api/message/records';
39 44 import { JsonPreview } from '/@/components/CodeEditor';
  45 + import { useBatchDelete } from '/@/hooks/web/useBatchDelete';
40 46
41 47 export default defineComponent({
42 48 name: 'SmsLog',
43 49 components: { BasicTable, TableAction },
44 50 setup() {
45   - const { createMessage } = useMessage();
46   - const [register] = useDrawerInner(() => {});
  51 + // 批量删除的hooks
  52 + const { hasBatchDelete, handleDeleteOrBatchDelete, selectionOptions } = useBatchDelete(
  53 + deleteSmsLog,
  54 + handleSuccess
  55 + );
47 56 const [registerTable, { reload }] = useTable({
48 57 title: '短信发送列表',
49 58 api: smsLogPage,
... ... @@ -64,10 +73,8 @@
64 73 slots: { customRender: 'action' },
65 74 fixed: 'right',
66 75 },
  76 + ...selectionOptions,
67 77 });
68   -
69   - function handleCreate() {}
70   -
71 78 function handleQuery(record: Recordable) {
72 79 Modal.info({
73 80 title: '当前配置',
... ... @@ -75,26 +82,19 @@
75 82 content: h(JsonPreview, { data: JSON.parse(JSON.stringify(record.templateParam)) }),
76 83 });
77 84 }
78   -
79   - function handleDelete(record: Recordable) {
80   - let ids = [record.id];
81   - deleteSmsLog(ids).then((result) => {
82   - createMessage.success(result.message);
83   - handleSuccess();
84   - });
85   - }
86   -
  85 + // 导出 TODO:待做
  86 + const handleExport = () => {};
  87 + // 刷新表格
87 88 function handleSuccess() {
88 89 reload();
89 90 }
90 91
91 92 return {
92   - register,
  93 + hasBatchDelete,
93 94 registerTable,
94   - handleCreate,
95   - handleDelete,
96   - handleSuccess,
  95 + handleExport,
97 96 handleQuery,
  97 + handleDeleteOrBatchDelete,
98 98 };
99 99 },
100 100 });
... ...
... ... @@ -51,6 +51,24 @@ export const searchFormSchema: FormSchema[] = [
51 51 field: 'emailSubject',
52 52 label: '邮件主题',
53 53 component: 'Input',
  54 + componentProps: {
  55 + maxLength: 255,
  56 + placeholder: '请输入邮件主题',
  57 + },
  58 + dynamicRules: () => {
  59 + return [
  60 + {
  61 + required: false,
  62 + validator: (_, value) => {
  63 + if (String(value).length > 255) {
  64 + return Promise.reject('字数不超过255个字');
  65 + }
  66 + return Promise.resolve();
  67 + },
  68 + },
  69 + ];
  70 + },
  71 +
54 72 colProps: { span: 6 },
55 73 },
56 74 {
... ...
... ... @@ -52,6 +52,9 @@ export const searchFormSchema: FormSchema[] = [
52 52 label: '发送手机',
53 53 component: 'Input',
54 54 colProps: { span: 6 },
  55 + componentProps: {
  56 + maxLength: 36,
  57 + },
55 58 },
56 59 {
57 60 field: 'sendTime',
... ...
... ... @@ -24,12 +24,45 @@
24 24 label: '用途',
25 25 component: 'Input',
26 26 show: false,
  27 + componentProps: {
  28 + maxLength: 36,
  29 + placeholder: '请输入用途',
  30 + },
  31 + dynamicRules: () => {
  32 + return [
  33 + {
  34 + required: false,
  35 + validator: (_, value) => {
  36 + if (String(value).length > 36) {
  37 + return Promise.reject('字数不超过36个字');
  38 + }
  39 + return Promise.resolve();
  40 + },
  41 + },
  42 + ];
  43 + },
27 44 },
28 45 {
29 46 field: 'messageType',
30 47 component: 'Input',
31 48 label: 'messageType',
32 49 show: false,
  50 + componentProps: {
  51 + maxLength: 36,
  52 + },
  53 + dynamicRules: () => {
  54 + return [
  55 + {
  56 + required: false,
  57 + validator: (_, value) => {
  58 + if (String(value).length > 36) {
  59 + return Promise.reject('字数不超过36个字');
  60 + }
  61 + return Promise.resolve();
  62 + },
  63 + },
  64 + ];
  65 + },
33 66 },
34 67 {
35 68 field: 'phoneNumbers',
... ... @@ -50,6 +83,23 @@
50 83 field: 'remark',
51 84 component: 'InputTextArea',
52 85 label: '备注',
  86 + componentProps: {
  87 + maxLength: 255,
  88 + placeholder: '请输入备注',
  89 + },
  90 + dynamicRules: () => {
  91 + return [
  92 + {
  93 + required: false,
  94 + validator: (_, value) => {
  95 + if (String(value).length > 255) {
  96 + return Promise.reject('字数不超过255个字');
  97 + }
  98 + return Promise.resolve();
  99 + },
  100 + },
  101 + ];
  102 + },
53 103 },
54 104 ];
55 105 export default defineComponent({
... ...
... ... @@ -95,12 +95,46 @@ export const searchFormSchema: FormSchema[] = [
95 95 label: '模板名称',
96 96 component: 'Input',
97 97 colProps: { span: 8 },
  98 + componentProps: {
  99 + maxLength: 32,
  100 + placeholder: '请输入模板名称',
  101 + },
  102 + dynamicRules: () => {
  103 + return [
  104 + {
  105 + required: false,
  106 + validator: (_, value) => {
  107 + if (String(value).length > 32) {
  108 + return Promise.reject('字数不超过32个字');
  109 + }
  110 + return Promise.resolve();
  111 + },
  112 + },
  113 + ];
  114 + },
98 115 },
99 116 {
100 117 field: 'templateCode',
101 118 label: '模板编码',
102 119 component: 'Input',
103 120 colProps: { span: 8 },
  121 + componentProps: {
  122 + maxLength: 20,
  123 + placeholder: '请输入模板编码',
  124 + },
  125 + dynamicRules: () => {
  126 + return [
  127 + {
  128 + required: false,
  129 + validator: (_, value) => {
  130 + if (String(value).length > 20) {
  131 + return Promise.reject('字数不超过20个字');
  132 + }
  133 + return Promise.resolve();
  134 + },
  135 + },
  136 + ];
  137 + },
104 138 },
105 139 ];
106 140
... ... @@ -110,6 +144,23 @@ export const formSchema: FormSchema[] = [
110 144 label: '主键',
111 145 component: 'Input',
112 146 show: false,
  147 + componentProps: {
  148 + maxLength: 36,
  149 + placeholder: '请输入主键',
  150 + },
  151 + dynamicRules: () => {
  152 + return [
  153 + {
  154 + required: false,
  155 + validator: (_, value) => {
  156 + if (String(value).length > 36) {
  157 + return Promise.reject('字数不超过36个字');
  158 + }
  159 + return Promise.resolve();
  160 + },
  161 + },
  162 + ];
  163 + },
113 164 },
114 165 {
115 166 field: 'messageType',
... ... @@ -145,12 +196,21 @@ export const formSchema: FormSchema[] = [
145 196 label: '模板名称',
146 197 required: true,
147 198 component: 'Input',
  199 + componentProps: {
  200 + maxLength: 32,
  201 + placeholder: '请输入模板名称',
  202 + },
148 203 },
149 204 {
150 205 field: 'templateCode',
151 206 label: '模板编号',
152 207 required: true,
153 208 component: 'Input',
  209 + componentProps: {
  210 + maxLength: 20,
  211 + placeholder: '请输入模板编号',
  212 + },
  213 +
154 214 ifShow: ({ values }) => isMessage(Reflect.get(values, 'messageType')),
155 215 },
156 216 {
... ... @@ -158,6 +218,11 @@ export const formSchema: FormSchema[] = [
158 218 label: '签名',
159 219 required: true,
160 220 component: 'Input',
  221 + componentProps: {
  222 + maxLength: 32,
  223 + placeholder: '请输入签名',
  224 + },
  225 +
161 226 ifShow: ({ values }) => isMessage(Reflect.get(values, 'messageType')),
162 227 },
163 228 {
... ... @@ -180,5 +245,22 @@ export const formSchema: FormSchema[] = [
180 245 label: '租户ID',
181 246 component: 'Input',
182 247 show: false,
  248 + componentProps: {
  249 + maxLength: 36,
  250 + placeholder: '请输入租户ID',
  251 + },
  252 + dynamicRules: () => {
  253 + return [
  254 + {
  255 + required: false,
  256 + validator: (_, value) => {
  257 + if (String(value).length > 36) {
  258 + return Promise.reject('字数不超过36个字');
  259 + }
  260 + return Promise.resolve();
  261 + },
  262 + },
  263 + ];
  264 + },
183 265 },
184 266 ];
... ...
... ... @@ -54,7 +54,14 @@
54 54 const getValueData: any = ref({});
55 55 const [
56 56 registerCondition,
57   - { resetFields, updateSchema, appendSchemaByField, removeSchemaByFiled, getFieldsValue },
  57 + {
  58 + setFieldsValue,
  59 + resetFields,
  60 + updateSchema,
  61 + appendSchemaByField,
  62 + removeSchemaByFiled,
  63 + getFieldsValue,
  64 + },
58 65 ] = useForm({
59 66 labelWidth: 100,
60 67 schemas: useConditionDrawerSchema,
... ... @@ -69,7 +76,7 @@
69 76 async (newV) => {
70 77 const options = await screenLinkPageByDeptIdGetDevice({ organizationId: newV });
71 78 options.items.forEach((v) => {
72   - return (v.value = v.id);
  79 + return (v.value = v.id), (v.label = v.name);
73 80 });
74 81 updateSchema({
75 82 field: 'deviceId',
... ... @@ -79,7 +86,10 @@
79 86 });
80 87 }
81 88 );
82   -
  89 + //回显数据
  90 + const setFieldsFormValue = (v) => {
  91 + setFieldsValue(v);
  92 + };
83 93 function getAllFields(getV) {
84 94 const values = getFieldsValue();
85 95 getValueData.value = values;
... ... @@ -301,7 +311,7 @@
301 311 ]);
302 312 n.value--;
303 313 }
304   - return { registerCondition, add, del, getAllFields, funcResetFields };
  314 + return { setFieldsFormValue, registerCondition, add, del, getAllFields, funcResetFields };
305 315 },
306 316 });
307 317 </script>
... ...
... ... @@ -48,7 +48,14 @@
48 48 const getValueData: any = ref({});
49 49 const [
50 50 registerAction,
51   - { resetFields, updateSchema, appendSchemaByField, getFieldsValue, removeSchemaByFiled },
  51 + {
  52 + setFieldsValue,
  53 + resetFields,
  54 + updateSchema,
  55 + appendSchemaByField,
  56 + getFieldsValue,
  57 + removeSchemaByFiled,
  58 + },
52 59 ] = useForm({
53 60 labelWidth: 100,
54 61 schemas: useActionDrawerSchema,
... ... @@ -63,7 +70,7 @@
63 70 async (newV) => {
64 71 const options = await screenLinkPageByDeptIdGetDevice({ organizationId: newV });
65 72 options.items.forEach((v) => {
66   - return (v.value = v.id);
  73 + return (v.value = v.id), (v.label = v.name);
67 74 });
68 75 updateSchema({
69 76 field: 'deviceId',
... ... @@ -73,6 +80,10 @@
73 80 });
74 81 }
75 82 );
  83 + //回显数据
  84 + const setFieldsFormValue = (v) => {
  85 + setFieldsValue(v);
  86 + };
76 87 function getAllFields(getV) {
77 88 const values = getFieldsValue();
78 89 getValueData.value = values;
... ... @@ -225,7 +236,7 @@
225 236 n.value--;
226 237 }
227 238
228   - return { registerAction, add, del, getAllFields, funcResetFields };
  239 + return { setFieldsFormValue, registerAction, add, del, getAllFields, funcResetFields };
229 240 },
230 241 });
231 242 </script>
... ...
... ... @@ -61,9 +61,18 @@
61 61 props: ['deviceInfo'],
62 62 setup(props) {
63 63 const getValueData: any = ref({});
  64 + const getPushValueData: any = ref([]);
  65 + // const newMapGetPushValueData: any = ref([]);
64 66 const [
65 67 registerTrigger,
66   - { resetFields, appendSchemaByField, removeSchemaByFiled, getFieldsValue, updateSchema },
  68 + {
  69 + setFieldsValue,
  70 + resetFields,
  71 + appendSchemaByField,
  72 + removeSchemaByFiled,
  73 + getFieldsValue,
  74 + updateSchema,
  75 + },
67 76 ] = useForm({
68 77 labelWidth: 100,
69 78 schemas: useTriggerDrawerSchema,
... ... @@ -78,7 +87,7 @@
78 87 async (newV) => {
79 88 const options = await screenLinkPageByDeptIdGetDevice({ organizationId: newV });
80 89 options.items.forEach((v) => {
81   - return (v.value = v.id);
  90 + return (v.value = v.id), (v.label = v.name);
82 91 });
83 92 updateSchema({
84 93 field: 'deviceId',
... ... @@ -88,19 +97,42 @@
88 97 });
89 98 }
90 99 );
  100 + //回显数据
  101 + const setFieldsFormValue = (v) => {
  102 + setFieldsValue(v);
  103 + };
  104 + // //去除字符串的数字
  105 + // function trimNumber(str) {
  106 + // return str.replace(/\d+/g, '');
  107 + // }
  108 + // function unique(arr) {
  109 + // return Array.from(new Set(arr));
  110 + // }
91 111 function getAllFields(getV) {
92 112 const values = getFieldsValue();
93 113 getValueData.value = values;
94   - console.log(getValueData.value);
95 114 getV = getValueData.value;
  115 + getPushValueData.value.push(getV);
  116 + console.log(getPushValueData.value);
96 117 return getV;
97 118 }
98 119 function funcResetFields() {
99 120 resetFields();
100 121 }
  122 + const addString: any = ref('tiggerEvent1') || ref('tiggerEvent2') || ref('tiggerEvent3');
101 123
102 124 const n = ref(1);
103 125 function add() {
  126 + const values = getFieldsValue();
  127 + getPushValueData.value.push(values);
  128 + console.log(getPushValueData.value);
  129 + // newMapGetPushValueData.value = getPushValueData.value.map((m) => {
  130 + // const getKeys = Object.keys(m);
  131 + // getKeys.map((f) => {
  132 + // return unique(trimNumber(f));
  133 + // });
  134 + // });
  135 + // console.log(newMapGetPushValueData.value);
104 136 appendSchemaByField(
105 137 {
106 138 field: `kong${n.value}`,
... ... @@ -137,9 +169,9 @@
137 169 placeholder: '请选择设备',
138 170 },
139 171 ifShow: ({ values }) =>
140   - !isTime(Reflect.get(values, `tiggerEvent${n.value}`)) &&
141   - !isScene(Reflect.get(values, `tiggerEvent${n.value}`)) &&
142   - !isHand(Reflect.get(values, `tiggerEvent${n.value}`)),
  172 + !isTime(Reflect.get(values, addString.value)) &&
  173 + !isScene(Reflect.get(values, addString.value)) &&
  174 + !isHand(Reflect.get(values, addString.value)),
143 175 colProps: {
144 176 span: 12,
145 177 },
... ... @@ -157,7 +189,7 @@
157 189 colProps: {
158 190 span: 12,
159 191 },
160   - ifShow: ({ values }) => isTime(Reflect.get(values, `tiggerEvent${n.value}`)),
  192 + ifShow: ({ values }) => isTime(Reflect.get(values, addString.value)),
161 193 },
162 194 ''
163 195 );
... ... @@ -174,9 +206,9 @@
174 206 ],
175 207 },
176 208 ifShow: ({ values }) =>
177   - !isTime(Reflect.get(values, `tiggerEvent${n.value}`)) &&
178   - !isScene(Reflect.get(values, `tiggerEvent${n.value}`)) &&
179   - !isHand(Reflect.get(values, `tiggerEvent${n.value}`)),
  209 + !isTime(Reflect.get(values, addString.value)) &&
  210 + !isScene(Reflect.get(values, addString.value)) &&
  211 + !isHand(Reflect.get(values, addString.value)),
180 212 colProps: { span: 12 },
181 213 },
182 214 ''
... ... @@ -197,9 +229,9 @@
197 229 colProps: { span: 12 },
198 230 ifShow: ({ values }) =>
199 231 isUpAndDown(Reflect.get(values, `touchWay${n.value}`)) &&
200   - !isTime(Reflect.get(values, `tiggerEvent${n.value}`)) &&
201   - !isScene(Reflect.get(values, `tiggerEvent${n.value}`)) &&
202   - !isHand(Reflect.get(values, `tiggerEvent${n.value}`)),
  232 + !isTime(Reflect.get(values, addString.value)) &&
  233 + !isScene(Reflect.get(values, addString.value)) &&
  234 + !isHand(Reflect.get(values, addString.value)),
203 235 },
204 236 ''
205 237 );
... ... @@ -217,9 +249,9 @@
217 249 },
218 250 colProps: { span: 12 },
219 251 ifShow: ({ values }) =>
220   - !isTime(Reflect.get(values, `tiggerEvent${n.value}`)) &&
221   - !isScene(Reflect.get(values, `tiggerEvent${n.value}`)) &&
222   - !isHand(Reflect.get(values, `tiggerEvent${n.value}`)) &&
  252 + !isTime(Reflect.get(values, addString.value)) &&
  253 + !isScene(Reflect.get(values, addString.value)) &&
  254 + !isHand(Reflect.get(values, addString.value)) &&
223 255 !isUpAndDown(Reflect.get(values, `touchWay${n.value}`)),
224 256 },
225 257 ''
... ... @@ -242,9 +274,9 @@
242 274 ifShow: ({ values }) =>
243 275 isWenDu(Reflect.get(values, 'attributeChoose')) &&
244 276 !isUpAndDown(Reflect.get(values, `touchWay${n.value}`)) &&
245   - !isTime(Reflect.get(values, `tiggerEvent${n.value}`)) &&
246   - !isScene(Reflect.get(values, `tiggerEvent${n.value}`)) &&
247   - !isHand(Reflect.get(values, `tiggerEvent${n.value}`)),
  277 + !isTime(Reflect.get(values, addString.value)) &&
  278 + !isScene(Reflect.get(values, addString.value)) &&
  279 + !isHand(Reflect.get(values, addString.value)),
248 280 colProps: { span: 12 },
249 281 },
250 282 ''
... ... @@ -260,9 +292,9 @@
260 292 ifShow: ({ values }) =>
261 293 isWenDu(Reflect.get(values, 'attributeChoose')) &&
262 294 !isUpAndDown(Reflect.get(values, `touchWay${n.value}`)) &&
263   - !isTime(Reflect.get(values, `tiggerEvent${n.value}`)) &&
264   - !isScene(Reflect.get(values, `tiggerEvent${n.value}`)) &&
265   - !isHand(Reflect.get(values, `tiggerEvent${n.value}`)),
  295 + !isTime(Reflect.get(values, addString.value)) &&
  296 + !isScene(Reflect.get(values, addString.value)) &&
  297 + !isHand(Reflect.get(values, addString.value)),
266 298 colProps: {
267 299 span: 12,
268 300 },
... ... @@ -277,7 +309,7 @@
277 309 colProps: {
278 310 span: 12,
279 311 },
280   - ifShow: ({ values }) => isScene(Reflect.get(values, `tiggerEvent${n.value}`)),
  312 + ifShow: ({ values }) => isScene(Reflect.get(values, addString.value)),
281 313 componentProps: {
282 314 placeholder: '请输入场景触发器',
283 315 options: [
... ... @@ -300,7 +332,7 @@
300 332 componentProps: {
301 333 placeholder: '暂不实现',
302 334 },
303   - ifShow: ({ values }) => isHand(Reflect.get(values, `tiggerEvent${n.value}`)),
  335 + ifShow: ({ values }) => isHand(Reflect.get(values, addString.value)),
304 336 },
305 337 ''
306 338 );
... ... @@ -336,7 +368,7 @@
336 368 ]);
337 369 n.value--;
338 370 }
339   - return { registerTrigger, add, del, getAllFields, funcResetFields };
  371 + return { setFieldsFormValue, registerTrigger, add, del, getAllFields, funcResetFields };
340 372 },
341 373 });
342 374 </script>
... ...
... ... @@ -147,6 +147,7 @@ export const formSchema: FormSchema[] = [
147 147 required: true,
148 148 component: 'Input',
149 149 componentProps: {
  150 + maxLength: 36,
150 151 placeholder: '请输入场景联动名称',
151 152 },
152 153 },
... ... @@ -200,8 +201,22 @@ export const formSchema: FormSchema[] = [
200 201 colProps: { span: 24 },
201 202 component: 'InputTextArea',
202 203 componentProps: {
  204 + maxLength: 255,
203 205 placeholder: '请输入描述',
204 206 },
  207 + dynamicRules: () => {
  208 + return [
  209 + {
  210 + required: false,
  211 + validator: (_, value) => {
  212 + if (String(value).length > 255) {
  213 + return Promise.reject('字数不超过255个字');
  214 + }
  215 + return Promise.resolve();
  216 + },
  217 + },
  218 + ];
  219 + },
205 220 },
206 221 ];
207 222
... ... @@ -225,7 +240,21 @@ export const searchFormSchema: FormSchema[] = [
225 240 component: 'Input',
226 241 colProps: { span: 8 },
227 242 componentProps: {
228   - placeholder: '请输入场景联动状态',
  243 + maxLength: 36,
  244 + placeholder: '请输入名称',
  245 + },
  246 + dynamicRules: () => {
  247 + return [
  248 + {
  249 + required: false,
  250 + validator: (_, value) => {
  251 + if (String(value).length > 36) {
  252 + return Promise.reject('字数不超过36个字');
  253 + }
  254 + return Promise.resolve();
  255 + },
  256 + },
  257 + ];
229 258 },
230 259 },
231 260 {
... ... @@ -263,9 +292,14 @@ export const useTriggerDrawerSchema: FormSchema[] = [
263 292 field: 'deviceId',
264 293 label: '',
265 294 component: 'Select',
266   - componentProps: {
267   - placeholder: '请选择设备',
  295 + componentProps() {
  296 + return {
  297 + placeholder: '请选择设备',
  298 + };
268 299 },
  300 + // componentProps: {
  301 + // placeholder: '请选择设备',
  302 + // },
269 303 ifShow: ({ values }) =>
270 304 !isTime(Reflect.get(values, 'triggerEvent')) &&
271 305 !isScene(Reflect.get(values, 'triggerEvent')) &&
... ... @@ -279,8 +313,23 @@ export const useTriggerDrawerSchema: FormSchema[] = [
279 313 component: 'Input',
280 314 label: '',
281 315 componentProps: {
  316 + maxLength: 255,
282 317 placeholder: '请输入Cron表达式',
283 318 },
  319 + dynamicRules: () => {
  320 + return [
  321 + {
  322 + required: false,
  323 + validator: (_, value) => {
  324 + if (String(value).length > 255) {
  325 + return Promise.reject('字数不超过255个字');
  326 + }
  327 + return Promise.resolve();
  328 + },
  329 + },
  330 + ];
  331 + },
  332 +
284 333 colProps: {
285 334 span: 12,
286 335 },
... ... @@ -367,8 +416,23 @@ export const useTriggerDrawerSchema: FormSchema[] = [
367 416 component: 'Input',
368 417 label: '',
369 418 componentProps: {
  419 + maxLength: 16,
370 420 placeholder: '请输入比较值',
371 421 },
  422 + dynamicRules: () => {
  423 + return [
  424 + {
  425 + required: false,
  426 + validator: (_, value) => {
  427 + if (String(value).length > 16) {
  428 + return Promise.reject('字数不超过16个字');
  429 + }
  430 + return Promise.resolve();
  431 + },
  432 + },
  433 + ];
  434 + },
  435 +
372 436 ifShow: ({ values }) =>
373 437 isWenDu(Reflect.get(values, 'attributeChoose')) &&
374 438 !isUpAndDown(Reflect.get(values, 'touchWay')) &&
... ... @@ -399,7 +463,7 @@ export const useTriggerDrawerSchema: FormSchema[] = [
399 463 },
400 464
401 465 {
402   - field: '',
  466 + field: 'no3',
403 467 label: '',
404 468 component: 'ApiSelect',
405 469 colProps: {
... ... @@ -518,8 +582,23 @@ export const useConditionDrawerSchema: FormSchema[] = [
518 582 component: 'Input',
519 583 label: '',
520 584 componentProps: {
  585 + maxLength: 16,
521 586 placeholder: '请输入比较值',
522 587 },
  588 + dynamicRules: () => {
  589 + return [
  590 + {
  591 + required: false,
  592 + validator: (_, value) => {
  593 + if (String(value).length > 16) {
  594 + return Promise.reject('字数不超过16个字');
  595 + }
  596 + return Promise.resolve();
  597 + },
  598 + },
  599 + ];
  600 + },
  601 +
523 602 ifShow: ({ values }) =>
524 603 isShiDu(Reflect.get(values, 'property')) && !isTimeAll(Reflect.get(values, 'status')),
525 604 colProps: {
... ... @@ -550,8 +629,22 @@ export const useConditionDrawerSchema: FormSchema[] = [
550 629 component: 'Input',
551 630 label: '',
552 631 componentProps: {
  632 + maxLength: 16,
553 633 placeholder: '请输入比较值',
554 634 },
  635 + dynamicRules: () => {
  636 + return [
  637 + {
  638 + required: false,
  639 + validator: (_, value) => {
  640 + if (String(value).length > 16) {
  641 + return Promise.reject('字数不超过16个字');
  642 + }
  643 + return Promise.resolve();
  644 + },
  645 + },
  646 + ];
  647 + },
555 648 ifShow: ({ values }) =>
556 649 isWenDu(Reflect.get(values, 'property')) && !isTimeAll(Reflect.get(values, 'status')),
557 650 colProps: {
... ... @@ -602,8 +695,22 @@ export const useActionDrawerSchema: FormSchema[] = [
602 695 component: 'Input',
603 696 label: '',
604 697 componentProps: {
  698 + maxLength: 255,
605 699 placeholder: '请输入下发指定',
606 700 },
  701 + dynamicRules: () => {
  702 + return [
  703 + {
  704 + required: false,
  705 + validator: (_, value) => {
  706 + if (String(value).length > 255) {
  707 + return Promise.reject('字数不超过255个字');
  708 + }
  709 + return Promise.resolve();
  710 + },
  711 + },
  712 + ];
  713 + },
607 714 ifShow: ({ values }) =>
608 715 !isScene(Reflect.get(values, 'outTarget')) && !isMsg(Reflect.get(values, 'outTarget')),
609 716 colProps: {
... ...
... ... @@ -71,6 +71,34 @@
71 71 await setFieldsValue({
72 72 ...data.record,
73 73 });
  74 + try {
  75 + proxy.$refs.getTriggerChildData.setFieldsFormValue({
  76 + triggerEvent: data.record.triggers[0].triggerEvent,
  77 + attributeChoose: data.record?.triggers[0].attributeChoose,
  78 + touchWay: data.record?.triggers[0].touchWay,
  79 + deviceId: data.record?.triggers[0].deviceId,
  80 + compare: data.record?.triggers[0].compare,
  81 + value: data.record?.triggers[0].value,
  82 + sceneLinkageId: data.record?.triggers[0].sceneLinkageId,
  83 + });
  84 + proxy.$refs.getConditionChildData.setFieldsFormValue({
  85 + status: data.record?.doConditions[0].status,
  86 + deviceId: data.record?.doConditions[0].deviceId,
  87 + createTime: data.record?.doConditions[0].createTime,
  88 + updateTime: data.record?.doConditions[0].updateTime,
  89 + property: data.record?.doConditions[0].property,
  90 + compare: data.record?.doConditions[0].compare,
  91 + value: data.record?.doConditions[0].value,
  92 + });
  93 + proxy.$refs.getChildData.setFieldsFormValue({
  94 + outTarget: data.record?.doActions[0].outTarget,
  95 + deviceId: data.record?.doActions[0].deviceId,
  96 + command: data.record?.doActions[0].command,
  97 + sceneLinkageId: data.record?.doActions[0].sceneLinkageId,
  98 + });
  99 + } catch (e) {
  100 + return e;
  101 + }
74 102 } else {
75 103 await resetFields();
76 104 }
... ... @@ -88,7 +116,6 @@
88 116 triggersArray.push(getTriggerChildValues);
89 117 doConditionsArray.push(getconditionChildValues);
90 118 getValuesFormData = getFieldsValue();
91   - console.log('触发器',triggersArray)
92 119 Object.assign(getAllFormData, getValuesFormData);
93 120 getAllFormData.triggers = triggersArray;
94 121 getAllFormData.doConditions = doConditionsArray;
... ...
... ... @@ -95,6 +95,7 @@ export const formSchema: FormSchema[] = [
95 95 component: 'Input',
96 96 componentProps: {
97 97 placeholder: '请输入标题',
  98 + maxLength: 200,
98 99 },
99 100 },
100 101 {
... ... @@ -158,9 +159,10 @@ export const searchFormSchema: FormSchema[] = [
158 159 {
159 160 field: 'type',
160 161 label: '',
161   - colProps: { span: 8 },
  162 + colProps: { span: 4 },
162 163 component: 'Select',
163 164 componentProps: {
  165 + placeholder: '请选择类型',
164 166 options: [
165 167 {
166 168 label: '公告',
... ...
... ... @@ -11,9 +11,9 @@
11 11 <a-button @click="fireResourceError" type="primary">
12 12 {{ t('sys.errorLog.fireResourceError') }}
13 13 </a-button>
14   - <a-button @click="fireAjaxError" type="primary">
  14 + <!-- <a-button @click="fireAjaxError" type="primary">
15 15 {{ t('sys.errorLog.fireAjaxError') }}
16   - </a-button>
  16 + </a-button> -->
17 17 </template>
18 18 <template #action="{ record }">
19 19 <TableAction
... ... @@ -36,7 +36,7 @@
36 36 import { useMessage } from '/@/hooks/web/useMessage';
37 37 import { useI18n } from '/@/hooks/web/useI18n';
38 38 import { useErrorLogStore } from '/@/store/modules/errorLog';
39   - import { fireErrorApi } from '/@/api/demo/error';
  39 + // import { fireErrorApi } from '/@/api/demo/error';
40 40 import { getColumns } from './data';
41 41 import { cloneDeep } from 'lodash-es';
42 42
... ... @@ -86,7 +86,7 @@
86 86 imgList.value.push(`${new Date().getTime()}.png`);
87 87 }
88 88
89   - async function fireAjaxError() {
90   - await fireErrorApi();
91   - }
  89 + // async function fireAjaxError() {
  90 + // await fireErrorApi();
  91 + // }
92 92 </script>
... ...
... ... @@ -12,10 +12,10 @@
12 12 import { PageWrapper } from '/@/components/Page';
13 13 import { useGo } from '/@/hooks/web/usePage';
14 14 import { Description } from '../../../components/Description';
15   - import { useTabs } from '/@/hooks/web/useTabs';
16 15 import { getAccountInfo } from '../../../api/system/system';
17 16 import { accountSchema } from './account.detail.data';
18 17 import { useDescription } from '../../../components/Description';
  18 + import { useTabs } from '/@/hooks/web/useTabs';
19 19 const accountData = {};
20 20 export default defineComponent({
21 21 name: 'AccountDetail',
... ... @@ -23,11 +23,10 @@
23 23 setup() {
24 24 const route = useRoute();
25 25 const go = useGo();
26   - const { setTitle } = useTabs();
  26 + const { setTitle, close } = useTabs();
27 27 const [register, methods] = useDescription({
28 28 title: '账号基础信息',
29 29 data: accountData,
30   - bordered: false,
31 30 schema: accountSchema,
32 31 column: 3,
33 32 });
... ... @@ -52,11 +51,10 @@
52 51 // 页面左侧点击返回链接时的操作
53 52 function goBack() {
54 53 // 本例的效果时点击返回始终跳转到账号列表页,实际应用时可返回上一页
  54 + close();
55 55 go('/system/account');
56 56 }
57 57 return { goBack, accountSchema, accountData, register };
58 58 },
59 59 });
60 60 </script>
61   -
62   -<style></style>
... ...
... ... @@ -43,12 +43,44 @@ export const searchFormSchema: FormSchema[] = [
43 43 label: '用户名',
44 44 component: 'Input',
45 45 colProps: { span: 8 },
  46 + componentProps: {
  47 + maxLength: 255,
  48 + },
  49 + dynamicRules: () => {
  50 + return [
  51 + {
  52 + required: false,
  53 + validator: (_, value) => {
  54 + if (String(value).length > 255) {
  55 + return Promise.reject('字数不超过255个字');
  56 + }
  57 + return Promise.resolve();
  58 + },
  59 + },
  60 + ];
  61 + },
46 62 },
47 63 {
48 64 field: 'realName',
49 65 label: '姓名',
50 66 component: 'Input',
51 67 colProps: { span: 8 },
  68 + componentProps: {
  69 + maxLength: 255,
  70 + },
  71 + dynamicRules: () => {
  72 + return [
  73 + {
  74 + required: false,
  75 + validator: (_, value) => {
  76 + if (String(value).length > 255) {
  77 + return Promise.reject('字数不超过255个字');
  78 + }
  79 + return Promise.resolve();
  80 + },
  81 + },
  82 + ];
  83 + },
52 84 },
53 85 ];
54 86
... ... @@ -58,6 +90,22 @@ export const accountFormSchema: FormSchema[] = [
58 90 label: 'id',
59 91 component: 'Input',
60 92 show: false,
  93 + componentProps: {
  94 + maxLength: 36,
  95 + },
  96 + dynamicRules: () => {
  97 + return [
  98 + {
  99 + required: false,
  100 + validator: (_, value) => {
  101 + if (String(value).length > 36) {
  102 + return Promise.reject('字数不超过36个字');
  103 + }
  104 + return Promise.resolve();
  105 + },
  106 + },
  107 + ];
  108 + },
61 109 },
62 110 {
63 111 field: 'username',
... ... @@ -108,6 +156,9 @@ export const accountFormSchema: FormSchema[] = [
108 156 component: 'Input',
109 157 colProps: { span: 12 },
110 158 required: true,
  159 + componentProps: {
  160 + maxLength: 255,
  161 + },
111 162 },
112 163 {
113 164 label: '角色',
... ... @@ -170,5 +221,21 @@ export const accountFormSchema: FormSchema[] = [
170 221 label: ' ',
171 222 component: 'Input',
172 223 slot: 'organizationId',
  224 + componentProps: {
  225 + maxLength: 36,
  226 + },
  227 + dynamicRules: () => {
  228 + return [
  229 + {
  230 + required: false,
  231 + validator: (_, value) => {
  232 + if (String(value).length > 36) {
  233 + return Promise.reject('字数不超过36个字');
  234 + }
  235 + return Promise.resolve();
  236 + },
  237 + },
  238 + ];
  239 + },
173 240 },
174 241 ];
... ...
... ... @@ -35,12 +35,44 @@ export const searchFormSchema: FormSchema[] = [
35 35 label: '字典名称',
36 36 component: 'Input',
37 37 colProps: { span: 6 },
  38 + componentProps: {
  39 + maxLength: 32,
  40 + },
  41 + dynamicRules: () => {
  42 + return [
  43 + {
  44 + required: false,
  45 + validator: (_, value) => {
  46 + if (String(value).length > 32) {
  47 + return Promise.reject('字数不超过32个字');
  48 + }
  49 + return Promise.resolve();
  50 + },
  51 + },
  52 + ];
  53 + },
38 54 },
39 55 {
40 56 field: 'dictCode',
41 57 label: '字典编码',
42 58 component: 'Input',
43 59 colProps: { span: 6 },
  60 + componentProps: {
  61 + maxLength: 32,
  62 + },
  63 + dynamicRules: () => {
  64 + return [
  65 + {
  66 + required: false,
  67 + validator: (_, value) => {
  68 + if (String(value).length > 32) {
  69 + return Promise.reject('字数不超过32个字');
  70 + }
  71 + return Promise.resolve();
  72 + },
  73 + },
  74 + ];
  75 + },
44 76 },
45 77 ];
46 78
... ... @@ -50,16 +82,38 @@ export const formSchema: FormSchema[] = [
50 82 label: '字典名称',
51 83 required: true,
52 84 component: 'Input',
  85 + componentProps: {
  86 + maxLength: 32,
  87 + },
53 88 },
54 89 {
55 90 field: 'dictCode',
56 91 label: '字典编码',
57 92 required: true,
58 93 component: 'Input',
  94 + componentProps: {
  95 + maxLength: 32,
  96 + },
59 97 },
60 98 {
61 99 label: '备注',
62 100 field: 'description',
63 101 component: 'InputTextArea',
  102 + componentProps: {
  103 + maxLength: 255,
  104 + },
  105 + dynamicRules: () => {
  106 + return [
  107 + {
  108 + required: false,
  109 + validator: (_, value) => {
  110 + if (String(value).length > 255) {
  111 + return Promise.reject('字数不超过255个字');
  112 + }
  113 + return Promise.resolve();
  114 + },
  115 + },
  116 + ];
  117 + },
64 118 },
65 119 ];
... ...
... ... @@ -67,12 +67,44 @@ export const searchFormSchema: FormSchema[] = [
67 67 label: '文本值',
68 68 component: 'Input',
69 69 colProps: { span: 6 },
  70 + componentProps: {
  71 + maxLength: 32,
  72 + },
  73 + dynamicRules: () => {
  74 + return [
  75 + {
  76 + required: false,
  77 + validator: (_, value) => {
  78 + if (String(value).length > 32) {
  79 + return Promise.reject('字数不超过32个字');
  80 + }
  81 + return Promise.resolve();
  82 + },
  83 + },
  84 + ];
  85 + },
70 86 },
71 87 {
72 88 field: 'dictId',
73 89 label: '文本值',
74 90 component: 'Input',
75 91 show: false,
  92 + componentProps: {
  93 + maxLength: 36,
  94 + },
  95 + dynamicRules: () => {
  96 + return [
  97 + {
  98 + required: false,
  99 + validator: (_, value) => {
  100 + if (String(value).length > 36) {
  101 + return Promise.reject('字数不超过36个字');
  102 + }
  103 + return Promise.resolve();
  104 + },
  105 + },
  106 + ];
  107 + },
76 108 },
77 109 ];
78 110
... ... @@ -82,18 +114,53 @@ export const formSchema: FormSchema[] = [
82 114 label: '文本值',
83 115 required: true,
84 116 component: 'Input',
  117 + componentProps: {
  118 + maxLength: 32,
  119 + },
  120 + dynamicRules: () => {
  121 + return [
  122 + {
  123 + required: true,
  124 + validator: (_, value) => {
  125 + if (String(value).length > 32) {
  126 + return Promise.reject('字数不超过32个字');
  127 + }
  128 + return Promise.resolve();
  129 + },
  130 + },
  131 + ];
  132 + },
85 133 },
86 134 {
87 135 field: 'itemValue',
88 136 label: '字典值',
89 137 required: true,
90 138 component: 'Input',
  139 + componentProps: {
  140 + maxLength: 32,
  141 + },
  142 + dynamicRules: () => {
  143 + return [
  144 + {
  145 + required: true,
  146 + validator: (_, value) => {
  147 + if (String(value).length > 32) {
  148 + return Promise.reject('字数不超过32个字');
  149 + }
  150 + return Promise.resolve();
  151 + },
  152 + },
  153 + ];
  154 + },
91 155 },
92 156 {
93 157 field: 'sort',
94 158 label: '排序',
95 159 component: 'InputNumber',
96 160 defaultValue: 1,
  161 + componentProps: {
  162 + maxLength: 32,
  163 + },
97 164 },
98 165 {
99 166 field: 'status',
... ... @@ -111,5 +178,21 @@ export const formSchema: FormSchema[] = [
111 178 label: '备注',
112 179 field: 'description',
113 180 component: 'InputTextArea',
  181 + componentProps: {
  182 + maxLength: 255,
  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 + },
114 197 },
115 198 ];
... ...
... ... @@ -80,6 +80,22 @@ export const searchFormSchema: FormSchema[] = [
80 80 // label: '菜单名称',
81 81 component: 'Input',
82 82 colProps: { span: 8 },
  83 + componentProps: {
  84 + maxLength: 255,
  85 + },
  86 + dynamicRules: () => {
  87 + return [
  88 + {
  89 + required: false,
  90 + validator: (_, value) => {
  91 + if (String(value).length > 255) {
  92 + return Promise.reject('字数不超过255个字');
  93 + }
  94 + return Promise.resolve();
  95 + },
  96 + },
  97 + ];
  98 + },
83 99 },
84 100 {
85 101 field: 'status',
... ... @@ -123,6 +139,10 @@ export const formSchema: FormSchema[] = [
123 139 label: t('routes.common.system.tableTitleSystemMenuName'), //菜单名称
124 140 component: 'Input',
125 141 required: true,
  142 + componentProps: {
  143 + maxLength: 255,
  144 + placeholder: '请输入title',
  145 + },
126 146 },
127 147
128 148 {
... ... @@ -144,6 +164,9 @@ export const formSchema: FormSchema[] = [
144 164 label: t('routes.common.system.tableTitleSystemSort'), //排序
145 165 component: 'InputNumber',
146 166 required: true,
  167 + componentProps: {
  168 + maxLength: 32,
  169 + },
147 170 },
148 171 {
149 172 field: 'icon',
... ... @@ -159,18 +182,54 @@ export const formSchema: FormSchema[] = [
159 182 component: 'Input',
160 183 required: true,
161 184 ifShow: ({ values }) => !isButton(Reflect.get(values, 'menuType')),
  185 + componentProps: {
  186 + maxLength: 255,
  187 + palceholder: '请输入path',
  188 + },
162 189 },
163 190 {
164 191 field: 'component',
165 192 label: t('routes.common.system.menuEditPagesComponentsPath'), //组件路径
166 193 component: 'Input',
167 194 ifShow: ({ values }) => isMenu(Reflect.get(values, 'menuType')),
  195 + componentProps: {
  196 + maxLength: 100,
  197 + },
  198 + dynamicRules: () => {
  199 + return [
  200 + {
  201 + required: false,
  202 + validator: (_, value) => {
  203 + if (String(value).length > 100) {
  204 + return Promise.reject('字数不超过100个字');
  205 + }
  206 + return Promise.resolve();
  207 + },
  208 + },
  209 + ];
  210 + },
168 211 },
169 212 {
170 213 field: 'permission',
171 214 label: t('routes.common.system.tableTitleSystemPermissionTag'), //权限标识
172 215 component: 'Input',
173 216 ifShow: ({ values }) => !isDir(Reflect.get(values, 'menuType')),
  217 + componentProps: {
  218 + maxLength: 100,
  219 + },
  220 + dynamicRules: () => {
  221 + return [
  222 + {
  223 + required: false,
  224 + validator: (_, value) => {
  225 + if (String(value).length > 100) {
  226 + return Promise.reject('字数不超过100个字');
  227 + }
  228 + return Promise.resolve();
  229 + },
  230 + },
  231 + ];
  232 + },
174 233 },
175 234 {
176 235 field: 'status',
... ...
... ... @@ -45,22 +45,61 @@ export const formSchema: FormSchema[] = [
45 45 label: t('routes.common.organization.queryOrganizationName'),
46 46 component: 'Input',
47 47 required: true,
  48 + componentProps: {
  49 + maxLength: 255,
  50 + placeholder: '请输入name',
  51 + },
48 52 },
49 53 {
50 54 field: 'sort',
51 55 label: t('routes.common.common.sort'), //排序
52 56 component: 'InputNumber',
53 57 required: true,
  58 + componentProps: {
  59 + maxLength: 32,
  60 + },
54 61 },
55 62 {
56 63 label: t('routes.common.common.remark'), //备注
57 64 field: 'remark',
58 65 component: 'InputTextArea',
  66 + componentProps: {
  67 + maxLength: 255,
  68 + },
  69 + dynamicRules: () => {
  70 + return [
  71 + {
  72 + required: false,
  73 + validator: (_, value) => {
  74 + if (String(value).length > 255) {
  75 + return Promise.reject('字数不超过255个字');
  76 + }
  77 + return Promise.resolve();
  78 + },
  79 + },
  80 + ];
  81 + },
59 82 },
60 83 {
61 84 label: '租户ID',
62 85 field: 'tenantId',
63 86 component: 'Input',
64 87 show: false,
  88 + componentProps: {
  89 + maxLength: 36,
  90 + },
  91 + dynamicRules: () => {
  92 + return [
  93 + {
  94 + required: false,
  95 + validator: (_, value) => {
  96 + if (String(value).length > 36) {
  97 + return Promise.reject('字数不超过36个字');
  98 + }
  99 + return Promise.resolve();
  100 + },
  101 + },
  102 + ];
  103 + },
65 104 },
66 105 ];
... ...
... ... @@ -16,7 +16,7 @@
16 16 label: '删除',
17 17 icon: 'ant-design:delete-outlined',
18 18 color: 'error',
19   - ifShow: record.roleType != RoleEnum.ROLE_SYS_ADMIN,
  19 + ifShow: record.roleType != RoleEnum.SYS_ADMIN,
20 20 popConfirm: {
21 21 title: '是否确认删除',
22 22 confirm: handleDelete.bind(null, record),
... ...
... ... @@ -67,6 +67,22 @@ export const searchFormSchema: FormSchema[] = [
67 67 label: '角色名称',
68 68 component: 'Input',
69 69 colProps: { span: 8 },
  70 + componentProps: {
  71 + maxLength: 255,
  72 + },
  73 + dynamicRules: () => {
  74 + return [
  75 + {
  76 + required: false,
  77 + validator: (_, value) => {
  78 + if (String(value).length > 255) {
  79 + return Promise.reject('字数不超过255个字');
  80 + }
  81 + return Promise.resolve();
  82 + },
  83 + },
  84 + ];
  85 + },
70 86 },
71 87 {
72 88 field: 'status',
... ... @@ -88,6 +104,9 @@ export const formSchema: FormSchema[] = [
88 104 label: '角色名称',
89 105 required: true,
90 106 component: 'Input',
  107 + componentProps: {
  108 + maxLength: 255,
  109 + },
91 110 },
92 111 {
93 112 field: 'status',
... ... @@ -105,11 +124,43 @@ export const formSchema: FormSchema[] = [
105 124 label: '备注',
106 125 field: 'remark',
107 126 component: 'InputTextArea',
  127 + componentProps: {
  128 + maxLength: 255,
  129 + },
  130 + dynamicRules: () => {
  131 + return [
  132 + {
  133 + required: false,
  134 + validator: (_, value) => {
  135 + if (String(value).length > 255) {
  136 + return Promise.reject('字数不超过255个字');
  137 + }
  138 + return Promise.resolve();
  139 + },
  140 + },
  141 + ];
  142 + },
108 143 },
109 144 {
110 145 label: ' ',
111 146 field: 'menu',
112 147 slot: 'menu',
113 148 component: 'Input',
  149 + componentProps: {
  150 + maxLength: 255,
  151 + },
  152 + dynamicRules: () => {
  153 + return [
  154 + {
  155 + required: false,
  156 + validator: (_, value) => {
  157 + if (String(value).length > 255) {
  158 + return Promise.reject('字数不超过255个字');
  159 + }
  160 + return Promise.resolve();
  161 + },
  162 + },
  163 + ];
  164 + },
114 165 },
115 166 ];
... ...
... ... @@ -171,7 +171,7 @@
171 171 showIndexColumn: false,
172 172 searchInfo: {
173 173 tenantId,
174   - roleType: RoleEnum.ROLE_TENANT_ADMIN,
  174 + roleType: RoleEnum.TENANT_ADMIN,
175 175 },
176 176 actionColumn: {
177 177 width: 100,
... ...
... ... @@ -35,6 +35,9 @@
35 35 label: 'id:',
36 36 show: false,
37 37 component: 'Input',
  38 + componentProps: {
  39 + maxLength: 36,
  40 + },
38 41 },
39 42 {
40 43 field: 'username',
... ... @@ -76,6 +79,9 @@
76 79 label: '真实名字',
77 80 required: true,
78 81 component: 'Input',
  82 + componentProps: {
  83 + maxLength: 255,
  84 + },
79 85 },
80 86 {
81 87 field: 'phoneNumber',
... ...
... ... @@ -94,7 +94,7 @@
94 94 await updateSchema({ field: 'title', componentProps: { disabled: false } });
95 95 //如果是编辑操作,设置页面数据
96 96 if (unref(isUpdate)) {
97   - console.log(data.record);
  97 + // console.log(data.record);
98 98 getTenantRoles(data.record.tenantId).then((result) => {
99 99 Reflect.set(data.record, 'roleIds', result);
100 100 //为表单赋值
... ...
... ... @@ -46,12 +46,44 @@ export const tenantFormSchema: FormSchema[] = [
46 46 label: 'id',
47 47 slot: 'iconSelect',
48 48 component: 'Input',
  49 + componentProps: {
  50 + maxLength: 36,
  51 + },
  52 + dynamicRules: () => {
  53 + return [
  54 + {
  55 + required: false,
  56 + validator: (_, value) => {
  57 + if (String(value).length > 36) {
  58 + return Promise.reject('字数不超过36个字');
  59 + }
  60 + return Promise.resolve();
  61 + },
  62 + },
  63 + ];
  64 + },
49 65 show: false,
50 66 },
51 67 {
52 68 field: 'tenantId',
53 69 label: 'tenantId',
54 70 component: 'Input',
  71 + componentProps: {
  72 + maxLength: 36,
  73 + },
  74 + dynamicRules: () => {
  75 + return [
  76 + {
  77 + required: false,
  78 + validator: (_, value) => {
  79 + if (String(value).length > 36) {
  80 + return Promise.reject('字数不超过36个字');
  81 + }
  82 + return Promise.resolve();
  83 + },
  84 + },
  85 + ];
  86 + },
55 87 show: false,
56 88 },
57 89 {
... ... @@ -59,12 +91,32 @@ export const tenantFormSchema: FormSchema[] = [
59 91 label: '租户图标: ',
60 92 slot: 'iconSelect',
61 93 component: 'Input',
  94 + componentProps: {
  95 + maxLength: 255,
  96 + },
  97 + dynamicRules: () => {
  98 + return [
  99 + {
  100 + required: false,
  101 + validator: (_, value) => {
  102 + if (String(value).length > 255) {
  103 + return Promise.reject('字数不超过255个字');
  104 + }
  105 + return Promise.resolve();
  106 + },
  107 + },
  108 + ];
  109 + },
62 110 },
63 111 {
64 112 field: 'name',
65 113 label: '租户名称:',
66 114 required: true,
67 115 component: 'Input',
  116 + componentProps: {
  117 + maxLength: 255,
  118 + placeholder: '请输入租户名称',
  119 + },
68 120 },
69 121 {
70 122 field: 'roleIds',
... ... @@ -75,7 +127,7 @@ export const tenantFormSchema: FormSchema[] = [
75 127 mode: 'multiple',
76 128 api: getAllRoleList,
77 129 params: {
78   - roleType: RoleEnum.ROLE_TENANT_ADMIN,
  130 + roleType: RoleEnum.TENANT_ADMIN,
79 131 },
80 132 labelField: 'name',
81 133 valueField: 'id',
... ... @@ -106,5 +158,21 @@ export const tenantFormSchema: FormSchema[] = [
106 158 label: '备注: ',
107 159 field: 'description',
108 160 component: 'InputTextArea',
  161 + componentProps: {
  162 + maxLength: 500,
  163 + },
  164 + dynamicRules: () => {
  165 + return [
  166 + {
  167 + required: false,
  168 + validator: (_, value) => {
  169 + if (String(value).length > 500) {
  170 + return Promise.reject('字数不超过500个字');
  171 + }
  172 + return Promise.resolve();
  173 + },
  174 + },
  175 + ];
  176 + },
109 177 },
110 178 ];
... ...
... ... @@ -8,8 +8,22 @@ export const schemas: FormSchema[] = [
8 8 span: 24,
9 9 },
10 10 componentProps: {
  11 + maxLength: 255,
11 12 placeholder: '请输入平台名称',
12 13 },
  14 + dynamicRules: () => {
  15 + return [
  16 + {
  17 + required: false,
  18 + validator: (_, value) => {
  19 + if (String(value).length > 255) {
  20 + return Promise.reject('字数不超过255个字');
  21 + }
  22 + return Promise.resolve();
  23 + },
  24 + },
  25 + ];
  26 + },
13 27 },
14 28 {
15 29 field: 'logo',
... ...
... ... @@ -9,8 +9,22 @@ export const schemas: FormSchema[] = [
9 9 span: 24,
10 10 },
11 11 componentProps: {
  12 + maxLength: 255,
12 13 placeholder: '请输入平台名称',
13 14 },
  15 + dynamicRules: () => {
  16 + return [
  17 + {
  18 + required: false,
  19 + validator: (_, value) => {
  20 + if (String(value).length > 255) {
  21 + return Promise.reject('字数不超过255个字');
  22 + }
  23 + return Promise.resolve();
  24 + },
  25 + },
  26 + ];
  27 + },
14 28 },
15 29 {
16 30 field: 'logo',
... ... @@ -55,6 +69,23 @@ export const schemas: FormSchema[] = [
55 69 colProps: {
56 70 span: 24,
57 71 },
  72 + componentProps: {
  73 + maxLength: 100,
  74 + placeholder: '请输入页面底部版权信息',
  75 + },
  76 + dynamicRules: () => {
  77 + return [
  78 + {
  79 + required: false,
  80 + validator: (_, value) => {
  81 + if (String(value).length > 100) {
  82 + return Promise.reject('字数不超过100个字');
  83 + }
  84 + return Promise.resolve();
  85 + },
  86 + },
  87 + ];
  88 + },
58 89 },
59 90 {
60 91 field: 'presentedOurselves',
... ... @@ -63,6 +94,23 @@ export const schemas: FormSchema[] = [
63 94 colProps: {
64 95 span: 24,
65 96 },
  97 + componentProps: {
  98 + maxLength: 50,
  99 + placeholder: '请输入备案信息',
  100 + },
  101 + dynamicRules: () => {
  102 + return [
  103 + {
  104 + required: false,
  105 + validator: (_, value) => {
  106 + if (String(value).length > 50) {
  107 + return Promise.reject('字数不超过50个字');
  108 + }
  109 + return Promise.resolve();
  110 + },
  111 + },
  112 + ];
  113 + },
66 114 },
67 115 {
68 116 field: 'domain',
... ... @@ -71,5 +119,22 @@ export const schemas: FormSchema[] = [
71 119 colProps: {
72 120 span: 24,
73 121 },
  122 + componentProps: {
  123 + maxLength: 100,
  124 + placeholder: '请输入绑定域名',
  125 + },
  126 + dynamicRules: () => {
  127 + return [
  128 + {
  129 + required: false,
  130 + validator: (_, value) => {
  131 + if (String(value).length > 100) {
  132 + return Promise.reject('字数不超过100个字');
  133 + }
  134 + return Promise.resolve();
  135 + },
  136 + },
  137 + ];
  138 + },
74 139 },
75 140 ];
... ...
... ... @@ -11,8 +11,22 @@ export const schemas: FormSchema[] = [
11 11 span: 24,
12 12 },
13 13 componentProps: {
  14 + maxLength: 100,
14 15 placeholder: '请输入公司名称',
15 16 },
  17 + dynamicRules: () => {
  18 + return [
  19 + {
  20 + required: false,
  21 + validator: (_, value) => {
  22 + if (String(value).length > 100) {
  23 + return Promise.reject('字数不超过100个字');
  24 + }
  25 + return Promise.resolve();
  26 + },
  27 + },
  28 + ];
  29 + },
16 30 },
17 31 {
18 32 field: 'abbreviation',
... ... @@ -22,8 +36,22 @@ export const schemas: FormSchema[] = [
22 36 span: 24,
23 37 },
24 38 componentProps: {
  39 + maxLength: 100,
25 40 placeholder: '请输入公司简称',
26 41 },
  42 + dynamicRules: () => {
  43 + return [
  44 + {
  45 + required: false,
  46 + validator: (_, value) => {
  47 + if (String(value).length > 100) {
  48 + return Promise.reject('字数不超过100个字');
  49 + }
  50 + return Promise.resolve();
  51 + },
  52 + },
  53 + ];
  54 + },
27 55 },
28 56 {
29 57 field: 'officialWebsite',
... ... @@ -33,8 +61,22 @@ export const schemas: FormSchema[] = [
33 61 span: 24,
34 62 },
35 63 componentProps: {
  64 + maxLength: 255,
36 65 placeholder: '请输入公司官网',
37 66 },
  67 + dynamicRules: () => {
  68 + return [
  69 + {
  70 + required: false,
  71 + validator: (_, value) => {
  72 + if (String(value).length > 255) {
  73 + return Promise.reject('字数不超过255个字');
  74 + }
  75 + return Promise.resolve();
  76 + },
  77 + },
  78 + ];
  79 + },
38 80 },
39 81 {
40 82 field: 'email',
... ... @@ -57,10 +99,24 @@ export const schemas: FormSchema[] = [
57 99 span: 24,
58 100 },
59 101 componentProps: {
  102 + maxLength: 500,
60 103 placeholder: '请输入公司简介',
61 104 autoSize: { minRows: 8, maxRows: 12 },
62 105 showCount: true,
63 106 },
  107 + dynamicRules: () => {
  108 + return [
  109 + {
  110 + required: false,
  111 + validator: (_, value) => {
  112 + if (String(value).length > 500) {
  113 + return Promise.reject('字数不超过500个字');
  114 + }
  115 + return Promise.resolve();
  116 + },
  117 + },
  118 + ];
  119 + },
64 120 },
65 121 {
66 122 field: 'nameCountry',
... ... @@ -244,8 +300,22 @@ export const schemas: FormSchema[] = [
244 300 span: 24,
245 301 },
246 302 componentProps: {
  303 + maxLength: 100,
247 304 placeholder: '请输入详细地址',
248 305 },
  306 + dynamicRules: () => {
  307 + return [
  308 + {
  309 + required: false,
  310 + validator: (_, value) => {
  311 + if (String(value).length > 100) {
  312 + return Promise.reject('字数不超过100个字');
  313 + }
  314 + return Promise.resolve();
  315 + },
  316 + },
  317 + ];
  318 + },
249 319 },
250 320
251 321 {
... ... @@ -256,8 +326,22 @@ export const schemas: FormSchema[] = [
256 326 span: 24,
257 327 },
258 328 componentProps: {
  329 + maxLength: 25,
259 330 placeholder: '请输入联系人',
260 331 },
  332 + dynamicRules: () => {
  333 + return [
  334 + {
  335 + required: false,
  336 + validator: (_, value) => {
  337 + if (String(value).length > 25) {
  338 + return Promise.reject('字数不超过25个字');
  339 + }
  340 + return Promise.resolve();
  341 + },
  342 + },
  343 + ];
  344 + },
261 345 },
262 346 {
263 347 field: 'tel',
... ... @@ -275,6 +359,24 @@ export const schemas: FormSchema[] = [
275 359 field: 'qrcode',
276 360 label: '二维码',
277 361 component: 'Input',
  362 + componentProps: {
  363 + maxLength: 255,
  364 + placeholder: '请输入二维码',
  365 + },
  366 + dynamicRules: () => {
  367 + return [
  368 + {
  369 + required: false,
  370 + validator: (_, value) => {
  371 + if (String(value).length > 255) {
  372 + return Promise.reject('字数不超过255个字');
  373 + }
  374 + return Promise.resolve();
  375 + },
  376 + },
  377 + ];
  378 + },
  379 +
278 380 colProps: {
279 381 span: 24,
280 382 },
... ... @@ -285,5 +387,22 @@ export const schemas: FormSchema[] = [
285 387 label: '唯一id',
286 388 component: 'Input',
287 389 show: false,
  390 + componentProps: {
  391 + maxLength: 36,
  392 + placeholder: '请输入平台名称',
  393 + },
  394 + dynamicRules: () => {
  395 + return [
  396 + {
  397 + required: false,
  398 + validator: (_, value) => {
  399 + if (String(value).length > 36) {
  400 + return Promise.reject('字数不超过36个字');
  401 + }
  402 + return Promise.resolve();
  403 + },
  404 + },
  405 + ];
  406 + },
288 407 },
289 408 ];
... ...
... ... @@ -2,9 +2,9 @@
2 2 <div class="platform flex">
3 3 <Card class="tab-card" :bordered="false">
4 4 <Tabs v-model:activeKey="activeKey" tab-position="left">
5   - <TabPane key="企业信息" tab="企业信息" />
6   - <TabPane key="平台定制" tab="平台定制" />
7   - <TabPane key="APP定制" tab="APP定制" />
  5 + <Tabs.TabPane key="企业信息" tab="企业信息" />
  6 + <Tabs.TabPane key="平台定制" tab="平台定制" />
  7 + <Tabs.TabPane key="APP定制" tab="APP定制" />
8 8 </Tabs>
9 9 </Card>
10 10
... ... @@ -18,7 +18,7 @@
18 18 </template>
19 19
20 20 <script lang="ts" setup>
21   - import { Tabs, TabPane, Card } from 'ant-design-vue';
  21 + import { Tabs, Card } from 'ant-design-vue';
22 22 import { ref } from 'vue';
23 23 import EnterpriseInfo from './cpns/EnterpriseInfo.vue';
24 24 import CVIDraw from './cpns/CVIDraw.vue';
... ...
... ... @@ -156,7 +156,7 @@
156 156 name: values.name,
157 157 remark: values.remark,
158 158 status: values.status,
159   - roleType: RoleEnum.ROLE_TENANT_ADMIN,
  159 + roleType: RoleEnum.TENANT_ADMIN,
160 160 menu: allCheckedKeys.value as string[],
161 161 };
162 162 console.log(req, '请求参数');
... ...
... ... @@ -67,14 +67,47 @@ export const searchFormSchema: FormSchema[] = [
67 67 label: '角色名称',
68 68 component: 'Input',
69 69 colProps: { span: 8 },
  70 + componentProps: {
  71 + maxLength: 255,
  72 + placeholder: '请输入角色名称',
  73 + },
  74 + dynamicRules: () => {
  75 + return [
  76 + {
  77 + required: false,
  78 + validator: (_, value) => {
  79 + if (String(value).length > 255) {
  80 + return Promise.reject('字数不超过255个字');
  81 + }
  82 + return Promise.resolve();
  83 + },
  84 + },
  85 + ];
  86 + },
70 87 },
71 88 {
72 89 field: 'roleType',
73 90 label: '',
74 91 component: 'Input',
75 92 colProps: { span: 8 },
76   - defaultValue: RoleEnum.ROLE_TENANT_ADMIN,
  93 + defaultValue: RoleEnum.TENANT_ADMIN,
77 94 ifShow: false,
  95 + componentProps: {
  96 + maxLength: 20,
  97 + },
  98 + dynamicRules: () => {
  99 + return [
  100 + {
  101 + required: false,
  102 + validator: (_, value) => {
  103 + if (String(value).length > 20) {
  104 + return Promise.reject('字数不超过20个字');
  105 + }
  106 + return Promise.resolve();
  107 + },
  108 + },
  109 + ];
  110 + },
78 111 },
79 112 {
80 113 field: 'status',
... ... @@ -96,6 +129,10 @@ export const formSchema: FormSchema[] = [
96 129 label: '角色名称',
97 130 required: true,
98 131 component: 'Input',
  132 + componentProps: {
  133 + maxLength: 255,
  134 + placeholder: '请输入角色名称',
  135 + },
99 136 },
100 137 {
101 138 field: 'status',
... ... @@ -113,11 +150,44 @@ export const formSchema: FormSchema[] = [
113 150 label: '备注',
114 151 field: 'remark',
115 152 component: 'InputTextArea',
  153 + componentProps: {
  154 + maxLength: 255,
  155 + placeholder: '请输入备注',
  156 + },
  157 + dynamicRules: () => {
  158 + return [
  159 + {
  160 + required: false,
  161 + validator: (_, value) => {
  162 + if (String(value).length > 255) {
  163 + return Promise.reject('字数不超过255个字');
  164 + }
  165 + return Promise.resolve();
  166 + },
  167 + },
  168 + ];
  169 + },
116 170 },
117 171 {
118 172 label: ' ',
119 173 field: 'menu',
120 174 slot: 'menu',
121 175 component: 'Input',
  176 + componentProps: {
  177 + maxLength: 255,
  178 + },
  179 + dynamicRules: () => {
  180 + return [
  181 + {
  182 + required: false,
  183 + validator: (_, value) => {
  184 + if (String(value).length > 255) {
  185 + return Promise.reject('字数不超过255个字');
  186 + }
  187 + return Promise.resolve();
  188 + },
  189 + },
  190 + ];
  191 + },
122 192 },
123 193 ];
... ...
... ... @@ -37,8 +37,22 @@ export const searchFormSchema: FormSchema[] = [
37 37 colProps: { span: 8 },
38 38 component: 'Input',
39 39 componentProps: {
  40 + maxLength: 255,
40 41 placeholder: '请输入租户配置名称',
41 42 },
  43 + dynamicRules: () => {
  44 + return [
  45 + {
  46 + required: false,
  47 + validator: (_, value) => {
  48 + if (String(value).length > 255) {
  49 + return Promise.reject('字数不超过255个字');
  50 + }
  51 + return Promise.resolve();
  52 + },
  53 + },
  54 + ];
  55 + },
42 56 },
43 57 ];
44 58 export const formSchema: FormSchema[] = [
... ... @@ -49,7 +63,8 @@ export const formSchema: FormSchema[] = [
49 63 required: true,
50 64 component: 'Input',
51 65 componentProps: {
52   - placeholder: '名称',
  66 + maxLength: 255,
  67 + placeholder: '请输入名称',
53 68 },
54 69 },
55 70 {
... ... @@ -70,7 +85,21 @@ export const formSchema: FormSchema[] = [
70 85 colProps: { span: 24 },
71 86 component: 'InputTextArea',
72 87 componentProps: {
  88 + maxLength: 255,
73 89 placeholder: '请输入说明',
74 90 },
  91 + dynamicRules: () => {
  92 + return [
  93 + {
  94 + required: false,
  95 + validator: (_, value) => {
  96 + if (String(value).length > 255) {
  97 + return Promise.reject('字数不超过255个字');
  98 + }
  99 + return Promise.resolve();
  100 + },
  101 + },
  102 + ];
  103 + },
75 104 },
76 105 ];
... ...
1 1 import { FormSchema } from '/@/components/Table';
2   -// import { numberRule } from '/@/utils/rules';
  2 +import { numberRule } from '/@/utils/rules';
3 3
4 4 export const formSchema: FormSchema[] = [
5 5 {
... ... @@ -23,6 +23,7 @@ export const formSchema: FormSchema[] = [
23 23 componentProps: {
24 24 placeholder: '请输入最大设备数(请输入数字)',
25 25 },
  26 + rules: numberRule,
26 27 },
27 28 {
28 29 field: 'maxAssets',
... ... @@ -34,6 +35,7 @@ export const formSchema: FormSchema[] = [
34 35 componentProps: {
35 36 placeholder: '请输入最大资产(请输入数字)',
36 37 },
  38 + rules: numberRule,
37 39 },
38 40 {
39 41 field: 'maxCustomers',
... ... @@ -45,6 +47,7 @@ export const formSchema: FormSchema[] = [
45 47 componentProps: {
46 48 placeholder: '请输入最大客户数(请输入数字)',
47 49 },
  50 + rules: numberRule,
48 51 },
49 52 {
50 53 field: 'maxUsers',
... ... @@ -56,6 +59,7 @@ export const formSchema: FormSchema[] = [
56 59 componentProps: {
57 60 placeholder: '请输入最大用户数(请输入数字)',
58 61 },
  62 + rules: numberRule,
59 63 },
60 64 {
61 65 field: 'maxDashboards',
... ... @@ -67,6 +71,7 @@ export const formSchema: FormSchema[] = [
67 71 componentProps: {
68 72 placeholder: '请输入仪表板的最大数量(请输入数字)',
69 73 },
  74 + rules: numberRule,
70 75 },
71 76 {
72 77 field: 'maxRuleChains',
... ... @@ -78,6 +83,7 @@ export const formSchema: FormSchema[] = [
78 83 componentProps: {
79 84 placeholder: '请输入最大规则链数(请输入数字)',
80 85 },
  86 + rules: numberRule,
81 87 },
82 88 {
83 89 field: 'maxResourcesInBytes',
... ... @@ -89,6 +95,7 @@ export const formSchema: FormSchema[] = [
89 95 componentProps: {
90 96 placeholder: '请输入(请输入数字)',
91 97 },
  98 + rules: numberRule,
92 99 },
93 100 {
94 101 field: 'maxOtaPackagesInBytes',
... ... @@ -100,6 +107,7 @@ export const formSchema: FormSchema[] = [
100 107 componentProps: {
101 108 placeholder: '请输入(请输入数字)',
102 109 },
  110 + rules: numberRule,
103 111 },
104 112 {
105 113 field: 'maxTransportMessages',
... ... @@ -111,6 +119,7 @@ export const formSchema: FormSchema[] = [
111 119 componentProps: {
112 120 placeholder: '请输入最大传输消息数(请输入数字)',
113 121 },
  122 + rules: numberRule,
114 123 },
115 124 {
116 125 field: 'maxTransportDataPoints',
... ... @@ -122,6 +131,7 @@ export const formSchema: FormSchema[] = [
122 131 componentProps: {
123 132 placeholder: '请输入传输数据点的最大数量(请输入数字)',
124 133 },
  134 + rules: numberRule,
125 135 },
126 136 {
127 137 field: 'maxREExecutions',
... ... @@ -133,6 +143,7 @@ export const formSchema: FormSchema[] = [
133 143 componentProps: {
134 144 placeholder: '请输入最大规则引擎数(请输入数字)',
135 145 },
  146 + rules: numberRule,
136 147 },
137 148
138 149 {
... ... @@ -145,6 +156,7 @@ export const formSchema: FormSchema[] = [
145 156 componentProps: {
146 157 placeholder: '请输入最大JavaScript执行数(请输入数字)',
147 158 },
  159 + rules: numberRule,
148 160 },
149 161 {
150 162 field: 'maxDPStorageDays',
... ... @@ -156,6 +168,7 @@ export const formSchema: FormSchema[] = [
156 168 componentProps: {
157 169 placeholder: '请输入最大日存储数据点数(请输入数字)',
158 170 },
  171 + rules: numberRule,
159 172 },
160 173 {
161 174 field: 'defaultStorageTtlDays',
... ... @@ -167,6 +180,7 @@ export const formSchema: FormSchema[] = [
167 180 componentProps: {
168 181 placeholder: '请输入默认存储 TTL 天数(请输入数字)',
169 182 },
  183 + rules: numberRule,
170 184 },
171 185 {
172 186 field: 'alarmsTtlDays',
... ... @@ -178,6 +192,7 @@ export const formSchema: FormSchema[] = [
178 192 componentProps: {
179 193 placeholder: '请输入Alams TTL days(请输入数字)',
180 194 },
  195 + rules: numberRule,
181 196 },
182 197 {
183 198 field: 'rpcTtlDays',
... ... @@ -189,6 +204,7 @@ export const formSchema: FormSchema[] = [
189 204 componentProps: {
190 205 placeholder: '请输入RPC TTL days(请输入数字)',
191 206 },
  207 + rules: numberRule,
192 208 },
193 209 {
194 210 field: 'maxRuleNodeExecutionsPerMessage',
... ... @@ -200,6 +216,7 @@ export const formSchema: FormSchema[] = [
200 216 componentProps: {
201 217 placeholder: '请输入每条消息的最大规则节点执行数(请输入数字)',
202 218 },
  219 + rules: numberRule,
203 220 },
204 221 {
205 222 field: 'maxEmails',
... ... @@ -210,6 +227,7 @@ export const formSchema: FormSchema[] = [
210 227 componentProps: {
211 228 placeholder: '请输入发送的最大电子邮件数(请输入数字)',
212 229 },
  230 + rules: numberRule,
213 231 },
214 232 {
215 233 field: 'maxSms',
... ... @@ -221,6 +239,7 @@ export const formSchema: FormSchema[] = [
221 239 componentProps: {
222 240 placeholder: '请输入发送的最大短信数(请输入数字)',
223 241 },
  242 + rules: numberRule,
224 243 },
225 244 {
226 245 field: 'maxCreatedAlarms',
... ... @@ -232,6 +251,7 @@ export const formSchema: FormSchema[] = [
232 251 componentProps: {
233 252 placeholder: '请输入maxCreatedAlarms(请输入数字)',
234 253 },
  254 + rules: numberRule,
235 255 },
236 256 {
237 257 field: 'transportTenantMsgRateLimit',
... ...