Commit 6984fb1f5bec0dbc364e9da98c777f651090ad10

Authored by sqy
1 parent 7c87f4b7

'fix:优化未查到数据界面,修复用户详情404问题,改为静态路由,首页增加过滤时间'

... ... @@ -16,11 +16,11 @@ VITE_BUILD_COMPRESS = 'gzip'
16 16 VITE_BUILD_COMPRESS_DELETE_ORIGIN_FILE = false
17 17
18 18 # Basic interface address SPA
19   -VITE_GLOB_API_URL=http://localhost:8080/api
  19 +VITE_GLOB_API_URL=http://101.133.234.90: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=http://localhost:8080/upload
  23 +VITE_GLOB_UPLOAD_URL=http://101.133.234.90:8080/upload
24 24
25 25 # Interface prefix
26 26 VITE_GLOB_API_URL_PREFIX=/yt
... ...
... ... @@ -158,10 +158,10 @@ export const dispatchCustomer = (data) => {
158 158 };
159 159 // 取消分配客户
160 160 export const cancelDispatchCustomer = (data) => {
161   - const { customerId, tbDeviceId } = data;
  161 + const { tbDeviceId } = data;
162 162 return defHttp.delete(
163 163 {
164   - url: `/customer/${customerId}/device/${tbDeviceId}`,
  164 + url: `/customer/device/${tbDeviceId}`,
165 165 },
166 166 {
167 167 joinPrefix: false,
... ...
... ... @@ -14,8 +14,9 @@ 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   -import 'ant-design-vue/dist/antd.less';
18   -
  17 +if (import.meta.env.DEV) {
  18 + import('ant-design-vue/dist/antd.less');
  19 +}
19 20 async function bootstrap() {
20 21 const app = createApp(App);
21 22
... ...
... ... @@ -76,31 +76,3 @@ export const ERROR_LOG_ROUTE: AppRouteRecordRaw = {
76 76 },
77 77 ],
78 78 };
79   -
80   -// export const UPDATE_SYSTEM_PASSWORD: AppRouteRecordRaw = {
81   -// path: '/system',
82   -// name: 'routes.common.system.system',
83   -// component: LAYOUT,
84   -// redirect: '/system/systemManagement',
85   -// meta: {
86   -// icon: 'bx:bx-home',
87   -// title: 'routes.common.system.system',
88   -// status: '0',
89   -// menuType: '0',
90   -// },
91   -// children: [
92   -// {
93   -// path: '/system/password',
94   -// name: 'routes.common.system.modifyPassword',
95   -// component: () => import('/@/views/system/password/index.vue'),
96   -// meta: {
97   -// icon: 'bx:bx-home',
98   -// title: 'routes.common.system.modifyPassword',
99   -// menuType: '1',
100   -// ignoreKeepAlive: true,
101   -// hideMenu: false,
102   -// status: '0',
103   -// },
104   -// },
105   -// ],
106   -// };
... ...
... ... @@ -5,6 +5,7 @@ import { PAGE_NOT_FOUND_ROUTE, REDIRECT_ROUTE } from '/@/router/routes/basic';
5 5 import { mainOutRoutes } from './mainOut';
6 6 import { PageEnum } from '/@/enums/pageEnum';
7 7 import { t } from '/@/hooks/web/useI18n';
  8 +import { LAYOUT } from '../constant';
8 9
9 10 const modules = import.meta.globEager('./modules/**/*.ts');
10 11
... ... @@ -39,10 +40,33 @@ export const LoginRoute: AppRouteRecordRaw = {
39 40 },
40 41 };
41 42
  43 +// 用户详情静态路由
  44 +export const AccountDetail: AppRouteRecordRaw = {
  45 + path: '/system',
  46 + name: '系统管理',
  47 + component: LAYOUT,
  48 + meta: {
  49 + title: '系统管理',
  50 + hideBreadcrumb: true,
  51 + hideChildrenInMenu: true,
  52 + },
  53 + children: [
  54 + {
  55 + path: 'account_detail/:id',
  56 + name: 'Account_Detail',
  57 + component: () => import('/@/views/system/account/AccountDetail.vue'),
  58 + meta: {
  59 + title: '用户详情',
  60 + },
  61 + },
  62 + ],
  63 +};
  64 +
42 65 // Basic routing without permission
43 66 export const basicRoutes = [
44 67 LoginRoute,
45 68 RootRoute,
  69 + AccountDetail,
46 70 ...mainOutRoutes,
47 71 REDIRECT_ROUTE,
48 72 PAGE_NOT_FOUND_ROUTE,
... ...
1   -// import type { AppRouteModule } from '/@/router/types';
2   -
3   -// import { LAYOUT } from '/@/router/constant';
4   -// import { t } from '/@/hooks/web/useI18n';
5   -
6   -// const dashboard: AppRouteModule = {
7   -// path: '/about',
8   -// name: 'About',
9   -// component: LAYOUT,
10   -// redirect: '/about/index',
11   -// meta: {
12   -// hideChildrenInMenu: true,
13   -// icon: 'simple-icons:about-dot-me',
14   -// title: t('routes.dashboard.about'),
15   -// orderNo: 100000,
16   -// },
17   -// children: [
18   -// {
19   -// path: 'index',
20   -// name: 'AboutPage',
21   -// component: () => import('/@/views/sys/about/index.vue'),
22   -// meta: {
23   -// title: t('routes.dashboard.about'),
24   -// icon: 'simple-icons:about-dot-me',
25   -// hideMenu: true,
26   -// },
27   -// },
28   -// ],
29   -// };
30   -
31   -// export default dashboard;
1   -// import type { AppRouteModule } from '/@/router/types';
2   -
3   -// import { LAYOUT } from '/@/router/constant';
4   -// import { t } from '/@/hooks/web/useI18n';
5   -
6   -// const dashboard: AppRouteModule = {
7   -// path: '/dashboard',
8   -// name: 'Dashboard',
9   -// component: LAYOUT,
10   -// redirect: '/dashboard/analysis',
11   -// meta: {
12   -// orderNo: 10,
13   -// icon: 'ion:grid-outline',
14   -// title: t('routes.dashboard.dashboard'),
15   -// },
16   -// children: [
17   -// {
18   -// path: 'analysis',
19   -// name: 'Analysis',
20   -// component: () => import('/@/views/dashboard/analysis/index.vue'),
21   -// meta: {
22   -// // affix: true,
23   -// title: t('routes.dashboard.analysis'),
24   -// },
25   -// },
26   -// {
27   -// path: 'workbench',
28   -// name: 'Workbench',
29   -// component: () => import('/@/views/dashboard/workbench/index.vue'),
30   -// meta: {
31   -// title: t('routes.dashboard.workbench'),
32   -// },
33   -// },
34   -// ],
35   -// };
36   -
37   -// export default dashboard;
... ... @@ -34,13 +34,7 @@
34 34 :canFullscreen="false"
35 35 >
36 36 <BasicForm @register="registerForm" />
37   - <Alert
38   - v-if="!isNull"
39   - message="当前时间节点暂无历史数据"
40   - description="请尝试选择其他时间段查询历史数据"
41   - type="warning"
42   - show-icon
43   - />
  37 + <Empty v-if="!isNull" />
44 38 <div v-show="isNull" ref="chartRef" :style="{ height: '600px', width }"></div>
45 39 </BasicModal>
46 40 <DeviceDetailDrawer @register="registerDetailDrawer" />
... ... @@ -52,7 +46,7 @@
52 46 import { formSchema, columns } from './config.data';
53 47 import { BasicTable, useTable } from '/@/components/Table';
54 48 import { devicePage } from '/@/api/alarm/contact/alarmContact';
55   - import { Tag, Alert } from 'ant-design-vue';
  49 + import { Tag, Empty } from 'ant-design-vue';
56 50 import { DeviceState } from '/@/api/device/model/deviceModel';
57 51 import { BAI_DU_MAP_URL } from '/@/utils/fnUtils';
58 52 import { useModal, BasicModal } from '/@/components/Modal';
... ... @@ -72,7 +66,7 @@
72 66 components: {
73 67 BasicTable,
74 68 Tag,
75   - Alert,
  69 + Empty,
76 70 BasicModal,
77 71 BasicForm,
78 72 DeviceDetailDrawer,
... ...
... ... @@ -58,7 +58,6 @@ export const searchFormSchema: FormSchema[] = [
58 58 componentProps: {
59 59 maxLength: 36,
60 60 placeholder: '请输入联系人姓名',
61   - maxLength: 36,
62 61 },
63 62 },
64 63 ];
... ...
... ... @@ -27,12 +27,46 @@
27 27 <VisitAnalysisBar :dataPointList="state.dataPointList" :messageList="state.messageList" />
28 28 </div>
29 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>
  30 + <div v-if="isAdmin(role)">
  31 + <Card v-bind="$attrs" title="租户趋势">
  32 + <template #extra>
  33 + <div class="extra-date">
  34 + <template v-for="(item, index) in TenantOrCustomerDateList" :key="item.value">
  35 + <span
  36 + @click="quickQueryTenantOrCustomerTime(index, item.value, 'tenant')"
  37 + :class="{ active: index === activeTenantIndex }"
  38 + >{{ item.label }}</span
  39 + >
  40 + </template>
  41 + <DatePicker.RangePicker
  42 + @change="onDateTenantChange"
  43 + size="small"
  44 + v-model:value="tenantDateValue"
  45 + />
  46 + </div>
  47 + </template>
  48 + <TenantTrend />
  49 + </Card>
  50 + <Card v-bind="$attrs" title="客户趋势">
  51 + <template #extra>
  52 + <div class="extra-date">
  53 + <template v-for="(item, index) in TenantOrCustomerDateList" :key="item.value">
  54 + <span
  55 + @click="quickQueryTenantOrCustomerTime(index, item.value, 'customer')"
  56 + :class="{ active: index === activeCustomerIndex }"
  57 + >{{ item.label }}</span
  58 + >
  59 + </template>
  60 + <DatePicker.RangePicker
  61 + @change="onDateCustomerChange"
  62 + size="small"
  63 + v-model:value="customerDateValue"
  64 + />
  65 + </div>
  66 + </template>
  67 + <CustomerTrend />
  68 + </Card>
  69 + </div>
36 70 </template>
37 71 <script lang="ts" setup>
38 72 import { ref, reactive } from 'vue';
... ... @@ -42,11 +76,12 @@
42 76 import { isAdmin } from '/@/enums/roleEnum';
43 77 import { useWebSocket } from '@vueuse/core';
44 78 import { getAuthCache } from '/@/utils/auth';
45   - import CustomerTrend from './CustomerTrend.vue';
46   - import TenantTrend from './TenantTrend.vue';
47 79 import { JWT_TOKEN_KEY } from '/@/enums/cacheEnum';
48 80 import { formatToDateTime } from '/@/utils/dateUtil';
49 81 import { getEntitiesId } from '/@/api/dashboard/index';
  82 + import CustomerTrend from './CustomerTrend.vue';
  83 + import TenantTrend from './TenantTrend.vue';
  84 + import { useDate } from '../hooks/useDate';
50 85 defineExpose({
51 86 isAdmin,
52 87 });
... ... @@ -75,6 +110,7 @@
75 110 { label: '7天', value: 604800000 },
76 111 { label: '30天', value: 2592000000 },
77 112 ]);
  113 +
78 114 // web Socket
79 115 const token: string = getAuthCache(JWT_TOKEN_KEY);
80 116 const state = reactive({
... ... @@ -342,6 +378,17 @@
342 378
343 379 console.log(JSON.parse(sendValue), '----interval', state.alarmList);
344 380 }
  381 +
  382 + const {
  383 + tenantDateValue,
  384 + customerDateValue,
  385 + activeTenantIndex,
  386 + activeCustomerIndex,
  387 + TenantOrCustomerDateList,
  388 + quickQueryTenantOrCustomerTime,
  389 + onDateTenantChange,
  390 + onDateCustomerChange,
  391 + } = useDate();
345 392 </script>
346 393
347 394 <style lang="less">
... ...
... ... @@ -2,13 +2,13 @@
2 2 <div>
3 3 <p class="center">告警数</p>
4 4 <div ref="chartRef" :style="{ height, width }" v-show="alarmList.length"></div>
5   - <div v-show="!alarmList.length">暂无数据</div>
  5 + <div v-show="!alarmList.length"><Empty /></div>
6 6 </div>
7 7 </template>
8 8 <script lang="ts" setup>
9 9 import { onMounted, ref, Ref, withDefaults, watch } from 'vue';
10 10 import { useECharts } from '/@/hooks/web/useECharts';
11   -
  11 + import { Empty } from 'ant-design-vue';
12 12 interface Props {
13 13 width?: string;
14 14 height?: string;
... ...
... ... @@ -2,12 +2,13 @@
2 2 <div>
3 3 <p class="center">消息量</p>
4 4 <div ref="chartRef" :style="{ height, width }" v-show="dataPointList.length"></div>
5   - <div v-show="!dataPointList.length">暂无数据</div>
  5 + <div v-show="!dataPointList.length"><Empty /></div>
6 6 </div>
7 7 </template>
8 8 <script lang="ts" setup>
9 9 import { ref, Ref, watch, withDefaults } from 'vue';
10 10 import { useECharts } from '/@/hooks/web/useECharts';
  11 + import { Empty } from 'ant-design-vue';
11 12 type DataItem = [number, string];
12 13 interface Props {
13 14 width?: string;
... ...
  1 +import { ref } from 'vue';
  2 +export function useDate() {
  3 + const tenantDateValue = ref([]);
  4 + const customerDateValue = ref([]);
  5 + const activeTenantIndex = ref(0);
  6 + const activeCustomerIndex = ref(0);
  7 + const TenantOrCustomerDateList = ref([
  8 + { label: '30天', value: 2592000000 },
  9 + { label: '最近三个月', value: 7776000000 },
  10 + { label: '最近一年', value: 31536000000 },
  11 + ]);
  12 +
  13 + // 租户趋势和客户趋势快速选择时间
  14 + function quickQueryTenantOrCustomerTime(
  15 + index: number,
  16 + value: number,
  17 + flag: 'tenant' | 'customer'
  18 + ) {
  19 + if (flag === 'tenant') {
  20 + if (activeTenantIndex.value === index) return;
  21 + activeTenantIndex.value = index;
  22 + tenantDateValue.value = [];
  23 + console.log(value);
  24 + } else {
  25 + if (activeCustomerIndex.value === index) return;
  26 + activeCustomerIndex.value = index;
  27 + customerDateValue.value = [];
  28 + console.log(value);
  29 + }
  30 + }
  31 + // 租户选择日期
  32 + function onDateTenantChange(_, dateString) {
  33 + activeTenantIndex.value = -1;
  34 + console.log(dateString);
  35 + }
  36 + // 客户趋势选择日期
  37 + function onDateCustomerChange(_, dateString) {
  38 + activeCustomerIndex.value = -1;
  39 + console.log(dateString);
  40 + }
  41 + return {
  42 + tenantDateValue,
  43 + customerDateValue,
  44 + activeTenantIndex,
  45 + activeCustomerIndex,
  46 + TenantOrCustomerDateList,
  47 + quickQueryTenantOrCustomerTime,
  48 + onDateTenantChange,
  49 + onDateCustomerChange,
  50 + };
  51 +}
... ...
... ... @@ -52,17 +52,17 @@
52 52 :actions="[
53 53 record.customerId
54 54 ? {
55   - tooltip: '取消分配给客户',
  55 + label: '取消分配',
56 56 icon: 'mdi:account-arrow-left',
57 57 ifShow: authBtn(role),
58 58 popConfirm: {
59   - title: '是否取消分配客户',
  59 + title: '是否取消分配客户',
60 60 confirm: handleCancelDispatchCustomer.bind(null, record),
61 61 },
62 62 }
63 63 : {
  64 + label: '分配客户',
64 65 icon: 'mdi:account-arrow-right',
65   - tooltip: '分配给客户',
66 66 ifShow: authBtn(role),
67 67 onClick: handleDispatchCustomer.bind(null, record),
68 68 },
... ... @@ -156,7 +156,7 @@
156 156 showIndexColumn: false,
157 157 searchInfo: searchInfo,
158 158 actionColumn: {
159   - width: 250,
  159 + width: 300,
160 160 title: '操作',
161 161 dataIndex: 'action',
162 162 slots: { customRender: 'action' },
... ... @@ -179,7 +179,7 @@
179 179 // 取消分配客户
180 180 async function handleCancelDispatchCustomer(record: Recordable) {
181 181 console.log('record', record);
182   - await cancelDispatchCustomer({ ...record, customerId: '' });
  182 + await cancelDispatchCustomer(record);
183 183 handleSuccess();
184 184 }
185 185
... ...