Commit 9e3463aee1c4a4b1e906c28153a3f4669cfede26

Authored by xp.Huang
2 parents 9efe030f 9905fa23

Merge branch 'sqy_dev' into 'main'

'feat:地图搜索完善,fix:OEM调整,实时数据支持模糊查询,动态修改标题'

See merge request huang/yun-teng-iot-front!116
... ... @@ -11,7 +11,6 @@
11 11 import { AppProvider } from '/@/components/Application';
12 12 import { useTitle } from '/@/hooks/web/useTitle';
13 13 import { useLocale } from '/@/locales/useLocale';
14   -
15 14 // support Multi-language
16 15 const { getAntdLocale } = useLocale();
17 16
... ...
1   -<!--
2   - * @Author: Vben
3   - * @Description: logo component
4   --->
5   -
6 1 <template>
7   - <div class="application" :class="getAppLogoClass">
  2 + <div class="anticon" :class="getAppLogoClass" @click="goHome">
8 3 <img v-if="getLogo" :src="getLogo" />
9 4 <img v-else src="/src/assets/images/logo.png" />
10   - <span
11   - class="ml-2 md:opacity-100"
12   - :class="getTitleClass"
13   - v-show="showTitle"
14   - style="white-space: nowrap; font-size: small; color: #f3f4fb"
15   - >
  5 + <div class="ml-2 truncate md:opacity-100" :class="getTitleClass" v-show="showTitle">
16 6 {{ getTitle }}
17   - </span>
  7 + </div>
18 8 </div>
19 9 </template>
20 10 <script lang="ts" setup>
... ... @@ -96,6 +86,7 @@
96 86 font-size: 16px;
97 87 font-weight: 700;
98 88 transition: all 0.5s;
  89 + line-height: normal;
99 90 }
100 91 }
101 92 </style>
... ...
... ... @@ -3,7 +3,7 @@ import { useI18n } from '/@/hooks/web/useI18n';
3 3 import { useTitle as usePageTitle } from '@vueuse/core';
4 4 import { useGlobSetting } from '/@/hooks/setting';
5 5 import { useRouter } from 'vue-router';
6   -
  6 +import { createLocalStorage } from '/@/utils/cache/index';
7 7 import { REDIRECT_NAME } from '/@/router/constant';
8 8
9 9 export function useTitle() {
... ... @@ -12,7 +12,7 @@ export function useTitle() {
12 12 const { currentRoute } = useRouter();
13 13
14 14 const pageTitle = usePageTitle();
15   -
  15 + const storage = createLocalStorage();
16 16 watch(
17 17 () => currentRoute.value.path,
18 18 () => {
... ... @@ -22,7 +22,9 @@ export function useTitle() {
22 22 }
23 23
24 24 const tTitle = t(route?.meta?.title as string);
25   - pageTitle.value = tTitle ? ` ${tTitle} - ${title} ` : `${title}`;
  25 + pageTitle.value = tTitle
  26 + ? ` ${tTitle} - ${storage.get('platInfo').name ?? title} `
  27 + : `${title}`;
26 28 },
27 29 { immediate: true }
28 30 );
... ...
... ... @@ -42,7 +42,7 @@ export const emailRule: Rule[] = [
42 42 {
43 43 validator: (_, value: string) => {
44 44 const reg = /^[a-zA-Z0-9_.-]+@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*\.[a-zA-Z0-9]{2,6}$/;
45   - if (value === '') {
  45 + if (!value) {
46 46 return Promise.resolve();
47 47 } else if (!reg.test(value)) {
48 48 return Promise.reject('电子邮箱格式不正确');
... ...
... ... @@ -43,7 +43,12 @@
43 43 </Card>
44 44 <Card title="联系我们" :bordered="false" v-bind="$attrs" :headStyle="{ padding: 0 }">
45 45 <template #cover>
46   - <img :src="getQrCode" alt="" style="width: 150px; height: 150px; margin: 50px auto" />
  46 + <img
  47 + :src="getQrCode"
  48 + v-if="getQrCode"
  49 + style="width: 150px; height: 150px; margin: 50px auto"
  50 + />
  51 + <Empty v-else :image="Empty.PRESENTED_IMAGE_SIMPLE" />
47 52 </template>
48 53 <CardMeta>
49 54 <template #description>
... ... @@ -161,6 +166,7 @@
161 166 Progress,
162 167 Skeleton,
163 168 Tooltip,
  169 + Empty,
164 170 } from 'ant-design-vue';
165 171 import { useUserStore } from '/@/store/modules/user';
166 172 import { getEnterPriseDetail } from '/@/api/oem';
... ... @@ -186,6 +192,7 @@
186 192 Progress,
187 193 Skeleton,
188 194 Tooltip,
  195 + Empty,
189 196 },
190 197 props: {
191 198 role: {
... ... @@ -288,6 +295,7 @@
288 295 go,
289 296 registerTable,
290 297 isAdmin,
  298 + Empty,
291 299 };
292 300 },
293 301 });
... ...
... ... @@ -5,7 +5,6 @@
5 5 import { ref, Ref, withDefaults, onMounted, watch } from 'vue';
6 6 import { useECharts } from '/@/hooks/web/useECharts';
7 7 import { getTrendData } from '/@/api/dashboard/index';
8   -
9 8 interface Props {
10 9 width?: string;
11 10 height?: string;
... ...
1 1 <template>
2 2 <div>
3 3 <div ref="chartRef" :style="{ height, width }" v-show="alarmList.length"></div>
4   - <div v-show="!alarmList.length"><Empty /></div>
  4 + <div v-show="!alarmList.length"><Empty :image="Empty.PRESENTED_IMAGE_SIMPLE" /></div>
5 5 </div>
6 6 </template>
7 7 <script lang="ts" setup>
... ...
1 1 <template>
2 2 <div>
3 3 <div ref="chartRef" :style="{ height, width }" v-show="dataPointList.length"></div>
4   - <div v-show="!dataPointList.length"><Empty /></div>
  4 + <div v-show="!dataPointList.length"><Empty :image="Empty.PRESENTED_IMAGE_SIMPLE" /></div>
5 5 </div>
6 6 </template>
7 7 <script lang="ts" setup>
... ...
... ... @@ -127,6 +127,9 @@
127 127 }
128 128 // 验证成功 --调-- 新增或者编辑接口
129 129 const msg = computed(() => (unref(stepState).id ? '更新设备成功' : '新增设备成功'));
  130 + // 此处需要删除地图的属性,否则会报堆栈溢出的错误 Uncaught RangeError: Maximum call stack size exceeded
  131 + Reflect.deleteProperty(DeviceStep1Ref.value.positionState, 'map');
  132 + Reflect.deleteProperty(DeviceStep1Ref.value.positionState, 'marker');
130 133 if (unref(stepState).id) {
131 134 const editData = {
132 135 ...unref(stepState),
... ... @@ -135,6 +138,7 @@
135 138 ...DeviceStep1Ref.value?.positionState,
136 139 },
137 140 };
  141 +
138 142 await createOrEditDevice(editData);
139 143 } else {
140 144 const createData = {
... ...
... ... @@ -44,10 +44,10 @@
44 44 centered
45 45 >
46 46 <div>
47   - <a-form :label-col="labelCol" :colon="false">
48   - <a-row :gutter="20" class="mt-4">
49   - <a-col :span="20">
50   - <a-form-item label="搜索位置">
  47 + <Form :label-col="labelCol" :colon="false">
  48 + <Row :gutter="20" class="mt-4">
  49 + <Col :span="20">
  50 + <FormItem label="搜索位置">
51 51 <AutoComplete
52 52 v-model:value="positionState.address"
53 53 :options="dataSource"
... ... @@ -57,22 +57,22 @@
57 57 @select="handleSelect"
58 58 backfill
59 59 />
60   - </a-form-item>
61   - </a-col>
62   - </a-row>
63   - <a-row :gutter="20" class="">
64   - <a-col :span="10">
65   - <a-form-item label="经度">
  60 + </FormItem>
  61 + </Col>
  62 + </Row>
  63 + <Row :gutter="20" class="">
  64 + <Col :span="10">
  65 + <FormItem label="经度">
66 66 <Input v-model:value="positionState.longitude" disabled />
67   - </a-form-item>
68   - </a-col>
69   - <a-col :span="10">
70   - <a-form-item label="纬度">
  67 + </FormItem>
  68 + </Col>
  69 + <Col :span="10">
  70 + <FormItem label="纬度">
71 71 <Input v-model:value="positionState.latitude" disabled />
72   - </a-form-item>
73   - </a-col>
74   - </a-row>
75   - </a-form>
  72 + </FormItem>
  73 + </Col>
  74 + </Row>
  75 + </Form>
76 76 <div ref="wrapRef" style="height: 300px; width: 90%" class="ml-6"></div>
77 77 </div>
78 78 </Modal>
... ... @@ -88,6 +88,7 @@
88 88 import { upload } from '/@/api/oss/ossFileUploader';
89 89 import { FileItem } from '/@/components/Upload/src/typing';
90 90 import { BAI_DU_MAP_URL } from '/@/utils/fnUtils';
  91 +
91 92 import icon from '/@/assets/images/wz.png';
92 93 import { useDebounceFn } from '@vueuse/core';
93 94 export default defineComponent({
... ... @@ -95,15 +96,14 @@
95 96 BasicForm,
96 97 Input,
97 98 AutoComplete,
98   - [Input.Group.name]: Input.Group,
99 99 Upload,
100 100 EnvironmentTwoTone,
101 101 PlusOutlined,
102 102 Modal,
103   - [Form.name]: Form,
104   - [Form.Item.name]: Form.Item,
105   - [Row.name]: Row,
106   - [Col.name]: Col,
  103 + Form,
  104 + FormItem: Form.Item,
  105 + Row,
  106 + Col,
107 107 },
108 108 props: {
109 109 deviceInfo: {
... ... @@ -209,6 +209,7 @@
209 209 const wrapRef = ref<HTMLDivElement | null>(null);
210 210 const { toPromise } = useScript({ src: BAI_DU_MAP_URL });
211 211
  212 + // 初始化地图
212 213 async function initMap(longitude, latitude) {
213 214 await toPromise();
214 215 await nextTick();
... ... @@ -243,7 +244,6 @@
243 244 });
244 245 }
245 246 const dataSource = ref<any[]>([]);
246   -
247 247 const onSearch = (searchText: string) => {
248 248 if (!searchText) {
249 249 dataSource.value = [];
... ... @@ -256,7 +256,6 @@
256 256 const searchArr = [];
257 257 for (let i = 0; i < res.getCurrentNumPois(); i++) {
258 258 const item = res.getPoi(i);
259   - console.log(item);
260 259 searchArr.push({
261 260 label: item.address + item.title,
262 261 value: item.address + item.title,
... ... @@ -268,13 +267,12 @@
268 267 },
269 268 }); //调用search方法,根据检索词searchText发起检索
270 269 local.search(searchText);
271   - console.log(dataSource);
272 270 };
273 271 // 防抖函数包装一下,防止频繁执行
274 272 const debounceSearch = useDebounceFn(onSearch, 500);
275 273 function handleSelect(value, option) {
276 274 dataSource.value = [];
277   - console.log(option);
  275 +
278 276 positionState.address = option.value; //记录详细地址,含建筑物名
279 277 const { lat, lng } = option.point;
280 278 positionState.latitude = lat; //记录当前选中地址坐标
... ... @@ -299,11 +297,9 @@
299 297 // 取消选择位置
300 298 const handleCancel = () => {
301 299 dataSource.value = [];
302   -
303 300 for (let key in positionState) {
304 301 positionState[key] = '';
305 302 }
306   - console.log(positionState);
307 303 };
308 304 // 父组件调用更新字段值的方法
309 305 function parentSetFieldsValue(data) {
... ...
... ... @@ -77,17 +77,17 @@
77 77 setTableData(state.recordList);
78 78 return;
79 79 }
80   - const newRecordList = state.recordList.find((item) => {
81   - if (item.key === key) return item;
82   - console.log('--------------------------', item);
83   - if (item.value === key) return item;
84   - });
85   - console.log(newRecordList);
86   - if (!newRecordList) {
87   - setTableData([]);
88   - } else {
89   - setTableData([newRecordList]);
  80 + let newRecordList = [];
  81 + let len = state.recordList.length;
  82 + for (let i = 0; i < len; i++) {
  83 + if (
  84 + state.recordList[i].key.indexOf(key) >= 0 ||
  85 + state.recordList[i].value.indexOf(key) >= 0
  86 + ) {
  87 + newRecordList.push(state.recordList[i]);
  88 + }
90 89 }
  90 + setTableData(newRecordList);
91 91 },
92 92 resetFunc() {
93 93 setTableData(state.recordList);
... ...
... ... @@ -28,7 +28,7 @@ export const schemas: FormSchema[] = [
28 28 {
29 29 field: 'logo',
30 30 component: 'Upload',
31   - label: '平台Logo',
  31 + label: 'APP Logo',
32 32 colProps: {
33 33 span: 24,
34 34 },
... ...
... ... @@ -102,7 +102,6 @@ export const schemas: FormSchema[] = [
102 102 maxLength: 500,
103 103 placeholder: '请输入公司简介',
104 104 autoSize: { minRows: 8, maxRows: 12 },
105   - showCount: true,
106 105 },
107 106 dynamicRules: () => {
108 107 return [
... ...
... ... @@ -15,13 +15,13 @@
15 15 <img v-if="logoPic" :src="logoPic" />
16 16 <div v-else>
17 17 <div style="margin-top: 30px">
18   - <PlusOutlined style="font-size: 30px" />
  18 + <PlusOutlined style="font-size: 50px" />
19 19 </div>
20 20 <div
21 21 class="ant-upload-text flex"
22   - style="width: 180px; height: 130px; align-items: center"
  22 + style="width: 180px; height: 100px; align-items: center; font-size: 9px"
23 23 >
24   - 支持.PNG、.JPG、.SVG格式,建议尺寸32px × 32px,大小不超过500KB。</div
  24 + 支持.PNG、.JPG格式,建议尺寸为32*32px,大小不超过500KB</div
25 25 >
26 26 </div>
27 27 </Upload>
... ... @@ -38,13 +38,13 @@
38 38 <img v-if="bgPic" :src="bgPic" alt="avatar" />
39 39 <div v-else>
40 40 <div style="margin-top: 30px">
41   - <PlusOutlined style="font-size: 30px" />
  41 + <PlusOutlined style="font-size: 50px" />
42 42 </div>
43 43 <div
44 44 class="ant-upload-text flex"
45   - style="width: 280px; height: 130px; align-items: center"
  45 + style="width: 280px; height: 100px; align-items: center; font-size: 9px"
46 46 >
47   - 支持.PNG、.JPG、.SVG格式,建议尺寸为1250px × 730px(及以上),大小不超过5M。</div
  47 + 支持.PNG、.JPG格式,建议尺寸为1080*1620px,大小不超过5M</div
48 48 >
49 49 </div>
50 50 </Upload>
... ... @@ -64,8 +64,14 @@
64 64 :before-upload="beforeUploadHomeSwiper"
65 65 >
66 66 <div v-if="fileList.length < 5">
67   - <plus-outlined />
68   - <div class="ant-upload-text">Upload</div>
  67 + <div style="margin-top: 30px">
  68 + <PlusOutlined style="font-size: 50px" />
  69 + </div>
  70 + <div
  71 + class="ant-upload-text flex"
  72 + style="width: 150px; height: 70px; align-items: center; font-size: 9px"
  73 + >支持.PNG、.JPG格式,建议尺寸为800*600px,大小不超过3M</div
  74 + >
69 75 </div>
70 76 </Upload>
71 77 <Modal :visible="previewVisible" :footer="null" @cancel="handleCancel">
... ... @@ -252,7 +258,7 @@
252 258
253 259 onMounted(async () => {
254 260 const res = await getAppDesign();
255   - const rotation = res.rotation.split(',');
  261 + const rotation = res.rotation ? res.rotation.split(',') : [];
256 262 const arr: any[] = [];
257 263 for (let item of rotation) {
258 264 arr.push({
... ... @@ -265,7 +271,7 @@
265 271 setFieldsValue(res);
266 272 logoPic.value = res.logo;
267 273 bgPic.value = res.background;
268   - if (arr[0].url === '') return;
  274 + if (arr[0]?.url === '') return;
269 275 fileList.value = arr;
270 276 });
271 277 return {
... ...
... ... @@ -14,13 +14,13 @@
14 14 <img v-if="logoPic" :src="logoPic" />
15 15 <div v-else>
16 16 <div style="margin-top: 30px">
17   - <PlusOutlined style="font-size: 30px" />
  17 + <PlusOutlined style="font-size: 50px" />
18 18 </div>
19 19 <div
20 20 class="ant-upload-text flex"
21   - style="width: 180px; height: 130px; align-items: center"
  21 + style="width: 180px; height: 100px; align-items: center; font-size: 9px"
22 22 >
23   - 支持.PNG、.JPG、.SVG格式,建议尺寸32px × 32px,大小不超过500KB。</div
  23 + 支持.PNG、.JPG格式,建议尺寸为32*32px,大小不超过500KB</div
24 24 >
25 25 </div>
26 26 </Upload>
... ... @@ -39,7 +39,15 @@
39 39 <div style="background-color: #ccc; margin-top: 20px">重新上传</div>
40 40 </div>
41 41 <div v-else>
42   - <PlusOutlined style="font-size: 30px" />
  42 + <div style="margin-top: 20px">
  43 + <PlusOutlined style="font-size: 30px" />
  44 + </div>
  45 + <div
  46 + class="ant-upload-text flex"
  47 + style="width: 130px; height: 70px; align-items: center; font-size: 9px"
  48 + >
  49 + 支持.ICON格式,建议尺寸为16*16px</div
  50 + >
43 51 </div>
44 52 </Upload>
45 53 </template>
... ... @@ -55,13 +63,13 @@
55 63 <img v-if="bgPic" :src="bgPic" alt="avatar" />
56 64 <div v-else>
57 65 <div style="margin-top: 30px">
58   - <PlusOutlined style="font-size: 30px" />
  66 + <PlusOutlined style="font-size: 50px" />
59 67 </div>
60 68 <div
61 69 class="ant-upload-text flex"
62   - style="width: 280px; height: 130px; align-items: center"
  70 + style="width: 280px; height: 130px; align-items: center; font-size: 9px"
63 71 >
64   - 支持.PNG、.JPG、.SVG格式,建议尺寸为1250px × 730px(及以上),大小不超过5M。</div
  72 + 支持.PNG、.JPG格式,建议尺寸为1920*1080px以上,大小不超过5M</div
65 73 >
66 74 </div>
67 75 </Upload>
... ... @@ -97,6 +105,8 @@
97 105 import { PlusOutlined } from '@ant-design/icons-vue';
98 106 import { useUserStore } from '/@/store/modules/user';
99 107 import { createLocalStorage } from '/@/utils/cache/index';
  108 + import { useTitle } from '@vueuse/core';
  109 + import { useGlobSetting } from '/@/hooks/setting';
100 110 export default defineComponent({
101 111 components: {
102 112 BasicForm,
... ... @@ -221,6 +231,8 @@
221 231 userStore.setPlatInfo(newFieldValue);
222 232 // 保存本地缓存
223 233 storage.set('platInfo', newFieldValue);
  234 + const { title } = useGlobSetting();
  235 + useTitle(`OEM定制 - ${newFieldValue.name === '' ? title : newFieldValue.name}`);
224 236 }
225 237
226 238 onMounted(async () => {
... ...
... ... @@ -14,13 +14,13 @@
14 14 <img v-if="qrcodePic" :src="qrcodePic" alt="avatar" />
15 15 <div v-else>
16 16 <div style="margin-top: 30px">
17   - <PlusOutlined style="font-size: 30px" />
  17 + <PlusOutlined style="font-size: 50px" />
18 18 </div>
19 19 <div
20 20 class="ant-upload-text flex"
21   - style="width: 280px; height: 130px; align-items: center"
  21 + style="width: 180px; height: 100px; align-items: center; font-size: 9px"
22 22 >
23   - 支持.PNG、.JPG、.SVG格式,建议尺寸为300px × 300px(及以上),大小不超过2M。</div
  23 + 支持.PNG、.JPG格式,建议尺寸为300*300px,大小不超过2M</div
24 24 >
25 25 </div>
26 26 </Upload>
... ...
... ... @@ -9,7 +9,7 @@
9 9 </Card>
10 10
11 11 <div style="width: 100%">
12   - <div class="title">{{ activeKey }}</div>
  12 + <Card class="card" :title="activeKey" :bordered="false" :bodyStyle="{ display: 'none' }" />
13 13 <EnterpriseInfo v-if="activeKey === '企业信息'" />
14 14 <CVIDraw v-else-if="activeKey === '平台定制'" />
15 15 <AppDraw v-else />
... ... @@ -23,6 +23,7 @@
23 23 import EnterpriseInfo from './cpns/EnterpriseInfo.vue';
24 24 import CVIDraw from './cpns/CVIDraw.vue';
25 25 import AppDraw from './cpns/AppDraw.vue';
  26 +
26 27 const activeKey = ref('企业信息');
27 28 </script>
28 29
... ... @@ -30,18 +31,16 @@
30 31 .title {
31 32 width: 97.4%;
32 33 height: 50px;
33   - margin: 20px;
  34 + margin: 1rem;
34 35 line-height: 50px;
35 36 font-size: 18px;
36   -
37   - background-color: #fff;
38 37 padding-left: 10px;
  38 + background-color: #fff;
39 39 }
40 40 .tab-card {
41   - margin: 20px 0 20px 20px;
  41 + margin: 1rem 0 1rem 1rem;
42 42 }
43 43 .card {
44   - margin: 20px;
45   - border-radius: 8px;
  44 + margin: 1rem;
46 45 }
47 46 </style>
... ...