Showing
42 changed files
with
620 additions
and
354 deletions
@@ -45,7 +45,6 @@ | @@ -45,7 +45,6 @@ | ||
45 | "cropperjs": "^1.5.12", | 45 | "cropperjs": "^1.5.12", |
46 | "crypto-js": "^4.1.1", | 46 | "crypto-js": "^4.1.1", |
47 | "echarts": "^5.1.2", | 47 | "echarts": "^5.1.2", |
48 | - "emit": "^0.0.2", | ||
49 | "intro.js": "^4.1.0", | 48 | "intro.js": "^4.1.0", |
50 | "jwt-decode": "^3.1.2", | 49 | "jwt-decode": "^3.1.2", |
51 | "lodash-es": "^4.17.21", | 50 | "lodash-es": "^4.17.21", |
src/api/alarm/position/index.ts
0 → 100644
@@ -90,3 +90,8 @@ export const updateAppDesign = (data) => { | @@ -90,3 +90,8 @@ export const updateAppDesign = (data) => { | ||
90 | data, | 90 | data, |
91 | }); | 91 | }); |
92 | }; | 92 | }; |
93 | + | ||
94 | +// 二维码上传 | ||
95 | +export const qrcodeUpload = (file) => { | ||
96 | + return defHttp.post<FileUploadResponse>({ url: API.BaseUploadUrl, params: file }); | ||
97 | +}; |
src/assets/images/bg-dark.png
0 → 100644
141 KB
src/assets/images/bg.png
0 → 100644
571 KB
@@ -2,12 +2,18 @@ | @@ -2,12 +2,18 @@ | ||
2 | * @Author: Vben | 2 | * @Author: Vben |
3 | * @Description: logo component | 3 | * @Description: logo component |
4 | --> | 4 | --> |
5 | + | ||
5 | <template> | 6 | <template> |
6 | <div class="anticon" :class="getAppLogoClass" @click="goHome"> | 7 | <div class="anticon" :class="getAppLogoClass" @click="goHome"> |
7 | - <img src="../../../assets/images/logo.png" /> | ||
8 | - <div class="ml-2 md:opacity-100" :class="getTitleClass" v-show="showTitle"> | ||
9 | - {{ title }} | ||
10 | - </div> | 8 | + <img :src="getLogo" /> |
9 | + <span | ||
10 | + class="ml-2 md:opacity-100" | ||
11 | + :class="getTitleClass" | ||
12 | + v-show="showTitle" | ||
13 | + style="white-space: nowrap" | ||
14 | + > | ||
15 | + {{ getTitle }} | ||
16 | + </span> | ||
11 | </div> | 17 | </div> |
12 | </template> | 18 | </template> |
13 | <script lang="ts" setup> | 19 | <script lang="ts" setup> |
@@ -18,7 +24,6 @@ | @@ -18,7 +24,6 @@ | ||
18 | import { useDesign } from '/@/hooks/web/useDesign'; | 24 | import { useDesign } from '/@/hooks/web/useDesign'; |
19 | import { PageEnum } from '/@/enums/pageEnum'; | 25 | import { PageEnum } from '/@/enums/pageEnum'; |
20 | import { useUserStore } from '/@/store/modules/user'; | 26 | import { useUserStore } from '/@/store/modules/user'; |
21 | - | ||
22 | const props = defineProps({ | 27 | const props = defineProps({ |
23 | /** | 28 | /** |
24 | * The theme of the current parent component | 29 | * The theme of the current parent component |
@@ -45,7 +50,6 @@ | @@ -45,7 +50,6 @@ | ||
45 | props.theme, | 50 | props.theme, |
46 | { 'collapsed-show-title': unref(getCollapsedShowTitle) }, | 51 | { 'collapsed-show-title': unref(getCollapsedShowTitle) }, |
47 | ]); | 52 | ]); |
48 | - | ||
49 | const getTitleClass = computed(() => [ | 53 | const getTitleClass = computed(() => [ |
50 | `${prefixCls}__title`, | 54 | `${prefixCls}__title`, |
51 | { | 55 | { |
@@ -56,10 +60,22 @@ | @@ -56,10 +60,22 @@ | ||
56 | function goHome() { | 60 | function goHome() { |
57 | go(userStore.getUserInfo.homePath || PageEnum.BASE_HOME); | 61 | go(userStore.getUserInfo.homePath || PageEnum.BASE_HOME); |
58 | } | 62 | } |
63 | + const getLogo = computed(() => { | ||
64 | + return userStore.platInfo?.logo ?? '/src/assets/images/logo.png'; | ||
65 | + }); | ||
66 | + const getTitle = computed(() => { | ||
67 | + // 设置icon | ||
68 | + let link = (document.querySelector("link[rel*='icon']") || | ||
69 | + document.createElement('link')) as HTMLLinkElement; | ||
70 | + link.type = 'image/x-icon'; | ||
71 | + link.rel = 'shortcut icon'; | ||
72 | + link.href = userStore.platInfo?.icon ?? '/public/favicon.ico'; | ||
73 | + document.getElementsByTagName('head')[0].appendChild(link); | ||
74 | + return userStore.platInfo?.name ?? title; | ||
75 | + }); | ||
59 | </script> | 76 | </script> |
60 | <style lang="less" scoped> | 77 | <style lang="less" scoped> |
61 | @prefix-cls: ~'@{namespace}-app-logo'; | 78 | @prefix-cls: ~'@{namespace}-app-logo'; |
62 | - | ||
63 | .@{prefix-cls} { | 79 | .@{prefix-cls} { |
64 | display: flex; | 80 | display: flex; |
65 | align-items: center; | 81 | align-items: center; |
@@ -29,6 +29,7 @@ export const APP_LOCAL_CACHE_KEY = 'COMMON__LOCAL__KEY__'; | @@ -29,6 +29,7 @@ export const APP_LOCAL_CACHE_KEY = 'COMMON__LOCAL__KEY__'; | ||
29 | // base global session key | 29 | // base global session key |
30 | export const APP_SESSION_CACHE_KEY = 'COMMON__SESSION__KEY__'; | 30 | export const APP_SESSION_CACHE_KEY = 'COMMON__SESSION__KEY__'; |
31 | 31 | ||
32 | +export const PLATFORM = 'PLATFORM'; | ||
32 | export enum CacheTypeEnum { | 33 | export enum CacheTypeEnum { |
33 | SESSION, | 34 | SESSION, |
34 | LOCAL, | 35 | LOCAL, |
1 | export enum RoleEnum { | 1 | export enum RoleEnum { |
2 | - ROLE_SYS_ADMIN = 'ROLE_SYS_ADMIN', | ||
3 | - ROLE_TENANT_ADMIN = 'ROLE_TENANT_ADMIN', | ||
4 | - ROLE_NORMAL_USER = 'ROLE_NORMAL_USER', | ||
5 | - ROLE_PLATFORM_ADMIN = 'ROLE_PLATFORM_ADMIN', | 2 | + ROLE_SYS_ADMIN = 'SYS_ADMIN', |
3 | + ROLE_TENANT_ADMIN = 'TENANT_ADMIN', | ||
4 | + ROLE_NORMAL_USER = 'CUSTOMER_USER', | ||
5 | + ROLE_PLATFORM_ADMIN = 'PLATFORM_ADMIN', | ||
6 | } | 6 | } |
@@ -25,8 +25,10 @@ import { router } from '/@/router'; | @@ -25,8 +25,10 @@ import { router } from '/@/router'; | ||
25 | import { usePermissionStore } from '/@/store/modules/permission'; | 25 | import { usePermissionStore } from '/@/store/modules/permission'; |
26 | import { RouteRecordRaw } from 'vue-router'; | 26 | import { RouteRecordRaw } from 'vue-router'; |
27 | import { PAGE_NOT_FOUND_ROUTE } from '/@/router/routes/basic'; | 27 | import { PAGE_NOT_FOUND_ROUTE } from '/@/router/routes/basic'; |
28 | - | 28 | +import { createLocalStorage } from '/@/utils/cache/index'; |
29 | interface UserState { | 29 | interface UserState { |
30 | + platInfo: any; | ||
31 | + enterPriseInfo: any; | ||
30 | userInfo: Nullable<UserInfo>; | 32 | userInfo: Nullable<UserInfo>; |
31 | token?: string; | 33 | token?: string; |
32 | roleList: RoleEnum[]; | 34 | roleList: RoleEnum[]; |
@@ -36,9 +38,13 @@ interface UserState { | @@ -36,9 +38,13 @@ interface UserState { | ||
36 | refreshToken?: string; | 38 | refreshToken?: string; |
37 | } | 39 | } |
38 | 40 | ||
41 | +const storage = createLocalStorage(); | ||
39 | export const useUserStore = defineStore({ | 42 | export const useUserStore = defineStore({ |
40 | id: 'app-user', | 43 | id: 'app-user', |
41 | state: (): UserState => ({ | 44 | state: (): UserState => ({ |
45 | + //平台信息 | ||
46 | + platInfo: storage.get('platInfo') || null, | ||
47 | + enterPriseInfo: storage.get('enterPriseInfo') || null, | ||
42 | // user info | 48 | // user info |
43 | userInfo: null, | 49 | userInfo: null, |
44 | // token | 50 | // token |
@@ -52,7 +58,11 @@ export const useUserStore = defineStore({ | @@ -52,7 +58,11 @@ export const useUserStore = defineStore({ | ||
52 | // Last fetch time | 58 | // Last fetch time |
53 | lastUpdateTime: 0, | 59 | lastUpdateTime: 0, |
54 | }), | 60 | }), |
61 | + | ||
55 | getters: { | 62 | getters: { |
63 | + getPlatInfo(): any { | ||
64 | + return this.platInfo; | ||
65 | + }, | ||
56 | getUserInfo(): UserInfo { | 66 | getUserInfo(): UserInfo { |
57 | return this.userInfo || getAuthCache<UserInfo>(USER_INFO_KEY) || {}; | 67 | return this.userInfo || getAuthCache<UserInfo>(USER_INFO_KEY) || {}; |
58 | }, | 68 | }, |
@@ -73,6 +83,12 @@ export const useUserStore = defineStore({ | @@ -73,6 +83,12 @@ export const useUserStore = defineStore({ | ||
73 | }, | 83 | }, |
74 | }, | 84 | }, |
75 | actions: { | 85 | actions: { |
86 | + setPlatInfo(platInfo: any) { | ||
87 | + this.platInfo = platInfo; | ||
88 | + }, | ||
89 | + setEnterPriseInfo(enterPriseInfo: any) { | ||
90 | + this.enterPriseInfo = enterPriseInfo; | ||
91 | + }, | ||
76 | storeToken(jwtToken: string, refreshToken: string) { | 92 | storeToken(jwtToken: string, refreshToken: string) { |
77 | this.jwtToken = jwtToken; | 93 | this.jwtToken = jwtToken; |
78 | this.refreshToken = refreshToken; | 94 | this.refreshToken = refreshToken; |
@@ -5,6 +5,7 @@ import type { RouteLocationNormalized } from 'vue-router'; | @@ -5,6 +5,7 @@ import type { RouteLocationNormalized } from 'vue-router'; | ||
5 | import { createLocalStorage, createSessionStorage } from '/@/utils/cache'; | 5 | import { createLocalStorage, createSessionStorage } from '/@/utils/cache'; |
6 | import { Memory } from './memory'; | 6 | import { Memory } from './memory'; |
7 | import { | 7 | import { |
8 | + PLATFORM, | ||
8 | TOKEN_KEY, | 9 | TOKEN_KEY, |
9 | JWT_TOKEN_KEY, | 10 | JWT_TOKEN_KEY, |
10 | REFRESH_TOKEN_KEY, | 11 | REFRESH_TOKEN_KEY, |
@@ -21,6 +22,7 @@ import { toRaw } from 'vue'; | @@ -21,6 +22,7 @@ import { toRaw } from 'vue'; | ||
21 | import { pick, omit } from 'lodash-es'; | 22 | import { pick, omit } from 'lodash-es'; |
22 | 23 | ||
23 | interface BasicStore { | 24 | interface BasicStore { |
25 | + [PLATFORM]: Object; | ||
24 | [TOKEN_KEY]: string | number | null | undefined; | 26 | [TOKEN_KEY]: string | number | null | undefined; |
25 | [JWT_TOKEN_KEY]: string | number | null | undefined; | 27 | [JWT_TOKEN_KEY]: string | number | null | undefined; |
26 | [REFRESH_TOKEN_KEY]: string | number | null | undefined; | 28 | [REFRESH_TOKEN_KEY]: string | number | null | undefined; |
1 | -import { BasicColumn } from '/@/components/Table'; | ||
2 | - | ||
3 | -import { FormSchema } from '/@/components/Table'; | 1 | +import type { BasicColumn } from '/@/components/Table'; |
2 | +import type { FormSchema } from '/@/components/Table'; | ||
3 | +import { getOrganizationList } from '/@/api/system/system'; | ||
4 | +import { copyTransFun } from '/@/utils/fnUtils'; | ||
5 | +import { getDeviceProfile } from '/@/api/alarm/position'; | ||
4 | export const formSchema: FormSchema[] = [ | 6 | export const formSchema: FormSchema[] = [ |
5 | { | 7 | { |
6 | - field: 'organization', | 8 | + field: 'organizationId', |
7 | label: '', | 9 | label: '', |
8 | - component: 'TreeSelect', | 10 | + component: 'ApiTreeSelect', |
9 | componentProps: { | 11 | componentProps: { |
10 | - placeholder: '请选择组织', | 12 | + api: async () => { |
13 | + const data = await getOrganizationList(); | ||
14 | + copyTransFun(data as any as any[]); | ||
15 | + return data; | ||
16 | + }, | ||
11 | }, | 17 | }, |
12 | }, | 18 | }, |
13 | { | 19 | { |
14 | - field: 'organization', | 20 | + field: 'profileId', |
15 | label: '', | 21 | label: '', |
16 | - component: 'Select', | 22 | + component: 'ApiSelect', |
17 | componentProps: { | 23 | componentProps: { |
24 | + api: getDeviceProfile, | ||
18 | placeholder: '请选择设备配置', | 25 | placeholder: '请选择设备配置', |
26 | + labelField: 'name', | ||
27 | + valueField: 'id', | ||
19 | }, | 28 | }, |
20 | }, | 29 | }, |
21 | { | 30 | { |
22 | - field: 'device', | 31 | + field: 'name', |
23 | label: '', | 32 | label: '', |
24 | component: 'Input', | 33 | component: 'Input', |
25 | componentProps: { | 34 | componentProps: { |
@@ -27,19 +36,28 @@ export const formSchema: FormSchema[] = [ | @@ -27,19 +36,28 @@ export const formSchema: FormSchema[] = [ | ||
27 | }, | 36 | }, |
28 | }, | 37 | }, |
29 | { | 38 | { |
30 | - field: 'status', | 39 | + field: 'deviceState', |
31 | label: '', | 40 | label: '', |
32 | component: 'RadioGroup', | 41 | component: 'RadioGroup', |
33 | componentProps: { | 42 | componentProps: { |
34 | size: 'small', | 43 | size: 'small', |
35 | options: [ | 44 | options: [ |
36 | - { label: '全部', value: 'Apple' }, | ||
37 | - { label: '离线', value: 'Pear' }, | ||
38 | - { label: '在线', value: 'Orange' }, | 45 | + { label: '待激活', value: 'INACTIVE' }, |
46 | + { label: '在线', value: 'ONLINE' }, | ||
47 | + { label: '离线', value: 'OFFLINE' }, | ||
39 | { label: '报警', value: 'hhh' }, | 48 | { label: '报警', value: 'hhh' }, |
40 | ], | 49 | ], |
41 | }, | 50 | }, |
42 | }, | 51 | }, |
52 | + { | ||
53 | + field: 'alarmStatus', | ||
54 | + label: '', | ||
55 | + component: 'RadioGroup', | ||
56 | + componentProps: { | ||
57 | + size: 'small', | ||
58 | + options: [{ label: '是否报警', value: '' }], | ||
59 | + }, | ||
60 | + }, | ||
43 | ]; | 61 | ]; |
44 | 62 | ||
45 | export const columns: BasicColumn[] = [ | 63 | export const columns: BasicColumn[] = [ |
@@ -57,5 +75,6 @@ export const columns: BasicColumn[] = [ | @@ -57,5 +75,6 @@ export const columns: BasicColumn[] = [ | ||
57 | title: '状态', | 75 | title: '状态', |
58 | dataIndex: 'deviceState', | 76 | dataIndex: 'deviceState', |
59 | width: 100, | 77 | width: 100, |
78 | + slots: { customRender: 'deviceState' }, | ||
60 | }, | 79 | }, |
61 | ]; | 80 | ]; |
@@ -2,7 +2,28 @@ | @@ -2,7 +2,28 @@ | ||
2 | <div class="wrapper"> | 2 | <div class="wrapper"> |
3 | <div ref="wrapRef" :style="{ height, width }"> </div> | 3 | <div ref="wrapRef" :style="{ height, width }"> </div> |
4 | <div class="right-wrap"> | 4 | <div class="right-wrap"> |
5 | - <BasicTable @register="registerTable" /> | 5 | + <BasicTable @register="registerTable"> |
6 | + <template #deviceState="{ record }"> | ||
7 | + <Tag | ||
8 | + :color=" | ||
9 | + record.deviceState == DeviceState.INACTIVE | ||
10 | + ? 'warning' | ||
11 | + : record.deviceState == DeviceState.ONLINE | ||
12 | + ? 'success' | ||
13 | + : 'error' | ||
14 | + " | ||
15 | + class="ml-2" | ||
16 | + > | ||
17 | + {{ | ||
18 | + record.deviceState == DeviceState.INACTIVE | ||
19 | + ? '待激活' | ||
20 | + : record.deviceState == DeviceState.ONLINE | ||
21 | + ? '在线' | ||
22 | + : '离线' | ||
23 | + }} | ||
24 | + </Tag> | ||
25 | + </template></BasicTable | ||
26 | + > | ||
6 | </div> | 27 | </div> |
7 | </div> | 28 | </div> |
8 | </template> | 29 | </template> |
@@ -12,11 +33,13 @@ | @@ -12,11 +33,13 @@ | ||
12 | import { formSchema, columns } from './config.data'; | 33 | import { formSchema, columns } from './config.data'; |
13 | import { BasicTable, useTable } from '/@/components/Table'; | 34 | import { BasicTable, useTable } from '/@/components/Table'; |
14 | import { devicePage } from '/@/api/alarm/contact/alarmContact'; | 35 | import { devicePage } from '/@/api/alarm/contact/alarmContact'; |
15 | - | 36 | + import { Tag } from 'ant-design-vue'; |
37 | + import { DeviceState } from '/@/api/device/model/deviceModel'; | ||
16 | export default defineComponent({ | 38 | export default defineComponent({ |
17 | name: 'BaiduMap', | 39 | name: 'BaiduMap', |
18 | components: { | 40 | components: { |
19 | BasicTable, | 41 | BasicTable, |
42 | + Tag, | ||
20 | }, | 43 | }, |
21 | props: { | 44 | props: { |
22 | width: { | 45 | width: { |
@@ -55,8 +78,6 @@ | @@ -55,8 +78,6 @@ | ||
55 | formConfig: { | 78 | formConfig: { |
56 | labelWidth: 120, | 79 | labelWidth: 120, |
57 | schemas: formSchema, | 80 | schemas: formSchema, |
58 | - showAdvancedButton: false, | ||
59 | - showActionButtonGroup: false, | ||
60 | }, | 81 | }, |
61 | showIndexColumn: false, | 82 | showIndexColumn: false, |
62 | useSearchForm: true, | 83 | useSearchForm: true, |
@@ -68,6 +89,7 @@ | @@ -68,6 +89,7 @@ | ||
68 | wrapRef, | 89 | wrapRef, |
69 | registerTable, | 90 | registerTable, |
70 | handleSuccess, | 91 | handleSuccess, |
92 | + DeviceState, | ||
71 | }; | 93 | }; |
72 | }, | 94 | }, |
73 | }); | 95 | }); |
@@ -83,12 +105,10 @@ | @@ -83,12 +105,10 @@ | ||
83 | .right-wrap { | 105 | .right-wrap { |
84 | padding-top: 10px; | 106 | padding-top: 10px; |
85 | width: 22%; | 107 | width: 22%; |
86 | - height: 80%; | 108 | + height: 95%; |
87 | position: absolute; | 109 | position: absolute; |
88 | right: 5%; | 110 | right: 5%; |
89 | - top: 10%; | ||
90 | - } | ||
91 | - .scroll-wrap { | ||
92 | - height: 450px; | 111 | + top: 3%; |
112 | + background-color: #fff; | ||
93 | } | 113 | } |
94 | </style> | 114 | </style> |
@@ -132,10 +132,6 @@ export const formSchema: FormSchema[] = [ | @@ -132,10 +132,6 @@ export const formSchema: FormSchema[] = [ | ||
132 | field: 'id', | 132 | field: 'id', |
133 | label: '', | 133 | label: '', |
134 | component: 'Input', | 134 | component: 'Input', |
135 | - componentProps: { | ||
136 | - style: { | ||
137 | - display: 'none', | ||
138 | - }, | ||
139 | - }, | 135 | + show: false, |
140 | }, | 136 | }, |
141 | ]; | 137 | ]; |
src/views/dashboard/analysis/components/DynamicInfo.vue
renamed from
src/views/dashboard/workbench/components/DynamicInfo.vue
src/views/dashboard/analysis/components/ProjectCard.vue
renamed from
src/views/dashboard/workbench/components/ProjectCard.vue
src/views/dashboard/analysis/components/QuickNav.vue
renamed from
src/views/dashboard/workbench/components/QuickNav.vue
src/views/dashboard/analysis/components/SaleRadar.vue
renamed from
src/views/dashboard/workbench/components/SaleRadar.vue
src/views/dashboard/analysis/components/WorkbenchHeader.vue
renamed from
src/views/dashboard/workbench/components/WorkbenchHeader.vue
src/views/dashboard/analysis/components/data.ts
renamed from
src/views/dashboard/workbench/components/data.ts
1 | <template> | 1 | <template> |
2 | - <div class="p-4 md:flex"> | ||
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"> | ||
7 | - <Card title="核心流程指南" style="width: 100%"> | ||
8 | - <img alt="核心流程指南" src="../../../assets/images/flow.png" /> | 2 | + <PageWrapper> |
3 | + <template #headerContent> <WorkbenchHeader /> </template> | ||
4 | + <div class="lg:flex"> | ||
5 | + <div class="lg:w-7/10 w-full !mr-4 enter-y"> | ||
6 | + <ProjectCard :loading="loading" class="enter-y" /> | ||
7 | + <DynamicInfo :loading="loading" class="!my-4 enter-y" /> | ||
8 | + </div> | ||
9 | + <div class="lg:w-3/10 w-full enter-y"> | ||
10 | + <QuickNav :loading="loading" class="enter-y" /> | ||
11 | + | ||
12 | + <Card class="!my-4 enter-y" :loading="loading"> | ||
13 | + <img class="xl:h-50 h-30 mx-auto" src="../../../assets/svg/illustration.svg" /> | ||
9 | </Card> | 14 | </Card> |
15 | + | ||
16 | + <SaleRadar :loading="loading" class="enter-y" /> | ||
10 | </div> | 17 | </div> |
11 | </div> | 18 | </div> |
12 | - <div class="md:w-3/10 w-full enter-y"> | ||
13 | - <HelpDoc /> | ||
14 | - </div> | ||
15 | - </div> | 19 | + <BasicModal |
20 | + @register="register" | ||
21 | + v-bind="$attrs" | ||
22 | + :mask="true" | ||
23 | + :showCancelBtn="false" | ||
24 | + :showOkBtn="false" | ||
25 | + :canFullscreen="false" | ||
26 | + :closable="false" | ||
27 | + :maskStyle="maskColor" | ||
28 | + :height="600" | ||
29 | + :width="1500" | ||
30 | + :maskClosable="false" | ||
31 | + title="请修改密码" | ||
32 | + :helpMessage="['请您修改密码']" | ||
33 | + > | ||
34 | + <PasswordDialog /> | ||
35 | + </BasicModal> | ||
36 | + </PageWrapper> | ||
16 | </template> | 37 | </template> |
17 | <script lang="ts" setup> | 38 | <script lang="ts" setup> |
18 | - import { ref } from 'vue'; | ||
19 | - import GrowCard from './components/GrowCard.vue'; | ||
20 | - import SiteAnalysis from './components/SiteAnalysis.vue'; | 39 | + import PasswordDialog from '/@/views/system/password/index.vue'; |
40 | + import { BasicModal, useModal } from '/@/components/Modal'; | ||
41 | + import { getAuthCache } from '/@/utils/auth'; | ||
42 | + import { USER_INFO_KEY } from '/@/enums/cacheEnum'; | ||
43 | + import { ref, onMounted } from 'vue'; | ||
21 | import { Card } from 'ant-design-vue'; | 44 | import { Card } from 'ant-design-vue'; |
22 | - import HelpDoc from './components/HelpDoc.vue'; | ||
23 | - const loading = ref(true); | 45 | + import { PageWrapper } from '/@/components/Page'; |
46 | + import WorkbenchHeader from './components/WorkbenchHeader.vue'; | ||
47 | + import ProjectCard from './components/ProjectCard.vue'; | ||
48 | + import QuickNav from './components/QuickNav.vue'; | ||
49 | + import DynamicInfo from './components/DynamicInfo.vue'; | ||
50 | + import SaleRadar from './components/SaleRadar.vue'; | ||
51 | + | ||
52 | + const maskColor = ref({ backgroundColor: 'grey' }); | ||
53 | + const statusModel = ref(false); | ||
54 | + const [register, { openModal }] = useModal(); | ||
55 | + onMounted(() => { | ||
56 | + const userInfo: object = getAuthCache(USER_INFO_KEY); | ||
57 | + if (userInfo.needSetPwd == true) { | ||
58 | + statusModel.value = true; | ||
59 | + openModal(statusModel.value); | ||
60 | + } else if (userInfo.needSetPwd == false) { | ||
61 | + openModal(statusModel.value); | ||
62 | + } | ||
63 | + }); | ||
64 | + //Yunteng123456!!! | ||
65 | + //Password123456! | ||
66 | + //System123456! | ||
67 | + //Testrole123456! | ||
68 | + const loading = ref(false); | ||
24 | setTimeout(() => { | 69 | setTimeout(() => { |
25 | loading.value = false; | 70 | loading.value = false; |
26 | }, 1500); | 71 | }, 1500); |
src/views/dashboard/workbench/components/GrowCard.vue
renamed from
src/views/dashboard/analysis/components/GrowCard.vue
src/views/dashboard/workbench/components/HelpDoc.vue
renamed from
src/views/dashboard/analysis/components/HelpDoc.vue
@@ -34,13 +34,13 @@ | @@ -34,13 +34,13 @@ | ||
34 | </Card> | 34 | </Card> |
35 | <Card hoverable title="联系我们" :bordered="false"> | 35 | <Card hoverable title="联系我们" :bordered="false"> |
36 | <template #cover> | 36 | <template #cover> |
37 | - <QrCode :value="qrCodeUrl" class="flex justify-center" /> | 37 | + <img :src="getQrCode" alt="" style="width: 150px; height: 150px; margin: 50px auto" /> |
38 | </template> | 38 | </template> |
39 | <CardMeta> | 39 | <CardMeta> |
40 | <template #description> | 40 | <template #description> |
41 | - <p>联系人: 张三</p> | ||
42 | - <p>联系电话: 15912341234</p> | ||
43 | - <p>联系地址: 四川省成都市剑南大道北段中1533号 </p> | 41 | + <p>联系人: {{ getContacts }}</p> |
42 | + <p>联系电话: {{ getTel }}</p> | ||
43 | + <p>联系地址: {{ getAddress }} </p> | ||
44 | </template> | 44 | </template> |
45 | </CardMeta> | 45 | </CardMeta> |
46 | </Card> | 46 | </Card> |
@@ -48,9 +48,10 @@ | @@ -48,9 +48,10 @@ | ||
48 | </template> | 48 | </template> |
49 | 49 | ||
50 | <script lang="ts"> | 50 | <script lang="ts"> |
51 | - import { defineComponent, ref } from 'vue'; | 51 | + import { defineComponent, ref, computed, onMounted } from 'vue'; |
52 | import { Card, AnchorLink, List, ListItem, ListItemMeta, Avatar, CardMeta } from 'ant-design-vue'; | 52 | import { Card, AnchorLink, List, ListItem, ListItemMeta, Avatar, CardMeta } from 'ant-design-vue'; |
53 | - import { QrCode } from '/@/components/Qrcode/index'; | 53 | + import { useUserStore } from '/@/store/modules/user'; |
54 | + import { getEnterPriseDetail } from '/@/api/oem'; | ||
54 | export default defineComponent({ | 55 | export default defineComponent({ |
55 | components: { | 56 | components: { |
56 | Card, | 57 | Card, |
@@ -60,9 +61,12 @@ | @@ -60,9 +61,12 @@ | ||
60 | ListItemMeta, | 61 | ListItemMeta, |
61 | Avatar, | 62 | Avatar, |
62 | CardMeta, | 63 | CardMeta, |
63 | - QrCode, | ||
64 | }, | 64 | }, |
65 | setup() { | 65 | setup() { |
66 | + onMounted(async () => { | ||
67 | + const res = await getEnterPriseDetail(); | ||
68 | + userStore.setEnterPriseInfo(res); | ||
69 | + }); | ||
66 | const helpDoc = ref([ | 70 | const helpDoc = ref([ |
67 | { | 71 | { |
68 | title: '如何接入设备?', | 72 | title: '如何接入设备?', |
@@ -137,7 +141,19 @@ | @@ -137,7 +141,19 @@ | ||
137 | }, | 141 | }, |
138 | ]; | 142 | ]; |
139 | 143 | ||
140 | - const qrCodeUrl = 'https://www.vvbin.cn'; | 144 | + const userStore = useUserStore(); |
145 | + const getContacts = computed(() => { | ||
146 | + return userStore.enterPriseInfo?.contacts; | ||
147 | + }); | ||
148 | + const getAddress = computed(() => { | ||
149 | + return userStore.enterPriseInfo?.address; | ||
150 | + }); | ||
151 | + const getTel = computed(() => { | ||
152 | + return userStore.enterPriseInfo?.tel; | ||
153 | + }); | ||
154 | + const getQrCode = computed(() => { | ||
155 | + return userStore.enterPriseInfo?.qrCode; | ||
156 | + }); | ||
141 | 157 | ||
142 | return { | 158 | return { |
143 | activeKey, | 159 | activeKey, |
@@ -145,7 +161,10 @@ | @@ -145,7 +161,10 @@ | ||
145 | onTabChange, | 161 | onTabChange, |
146 | data, | 162 | data, |
147 | helpDoc, | 163 | helpDoc, |
148 | - qrCodeUrl, | 164 | + getQrCode, |
165 | + getContacts, | ||
166 | + getAddress, | ||
167 | + getTel, | ||
149 | }; | 168 | }; |
150 | }, | 169 | }, |
151 | }); | 170 | }); |
src/views/dashboard/workbench/components/SiteAnalysis.vue
renamed from
src/views/dashboard/analysis/components/SiteAnalysis.vue
src/views/dashboard/workbench/components/VisitAnalysis.vue
renamed from
src/views/dashboard/analysis/components/VisitAnalysis.vue
src/views/dashboard/workbench/components/VisitAnalysisBar.vue
renamed from
src/views/dashboard/analysis/components/VisitAnalysisBar.vue
src/views/dashboard/workbench/components/props.ts
renamed from
src/views/dashboard/analysis/components/props.ts
src/views/dashboard/workbench/data.ts
renamed from
src/views/dashboard/analysis/data.ts
1 | <template> | 1 | <template> |
2 | - <PageWrapper> | ||
3 | - <template #headerContent> <WorkbenchHeader /> </template> | ||
4 | - <div class="lg:flex"> | ||
5 | - <div class="lg:w-7/10 w-full !mr-4 enter-y"> | ||
6 | - <ProjectCard :loading="loading" class="enter-y" /> | ||
7 | - <DynamicInfo :loading="loading" class="!my-4 enter-y" /> | ||
8 | - </div> | ||
9 | - <div class="lg:w-3/10 w-full enter-y"> | ||
10 | - <QuickNav :loading="loading" class="enter-y" /> | ||
11 | - | ||
12 | - <Card class="!my-4 enter-y" :loading="loading"> | ||
13 | - <img class="xl:h-50 h-30 mx-auto" src="../../../assets/svg/illustration.svg" /> | 2 | + <div class="p-4 md:flex"> |
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"> | ||
7 | + <Card title="核心流程指南" style="width: 100%"> | ||
8 | + <img alt="核心流程指南" src="../../../assets/images/flow.png" /> | ||
14 | </Card> | 9 | </Card> |
15 | - | ||
16 | - <SaleRadar :loading="loading" class="enter-y" /> | ||
17 | </div> | 10 | </div> |
18 | </div> | 11 | </div> |
19 | - <BasicModal | ||
20 | - @register="register" | ||
21 | - v-bind="$attrs" | ||
22 | - :mask="true" | ||
23 | - :showCancelBtn="false" | ||
24 | - :showOkBtn="false" | ||
25 | - :canFullscreen="false" | ||
26 | - :closable="false" | ||
27 | - :maskStyle="maskColor" | ||
28 | - :height="600" | ||
29 | - :width="1500" | ||
30 | - :maskClosable="false" | ||
31 | - title="请修改密码" | ||
32 | - :helpMessage="['请您修改密码']" | ||
33 | - > | ||
34 | - <PasswordDialog /> | ||
35 | - </BasicModal> | ||
36 | - </PageWrapper> | 12 | + <div class="md:w-3/10 w-full enter-y"> |
13 | + <HelpDoc /> | ||
14 | + </div> | ||
15 | + </div> | ||
37 | </template> | 16 | </template> |
38 | <script lang="ts" setup> | 17 | <script lang="ts" setup> |
39 | - import PasswordDialog from '/@/views/system/password/index.vue'; | ||
40 | - import { BasicModal, useModal } from '/@/components/Modal'; | ||
41 | - import { getAuthCache } from '/@/utils/auth'; | ||
42 | - import { USER_INFO_KEY } from '/@/enums/cacheEnum'; | ||
43 | - import { ref, onMounted } from 'vue'; | 18 | + import { ref } from 'vue'; |
19 | + import GrowCard from './components/GrowCard.vue'; | ||
20 | + import SiteAnalysis from './components/SiteAnalysis.vue'; | ||
44 | import { Card } from 'ant-design-vue'; | 21 | import { Card } from 'ant-design-vue'; |
45 | - import { PageWrapper } from '/@/components/Page'; | ||
46 | - import WorkbenchHeader from './components/WorkbenchHeader.vue'; | ||
47 | - import ProjectCard from './components/ProjectCard.vue'; | ||
48 | - import QuickNav from './components/QuickNav.vue'; | ||
49 | - import DynamicInfo from './components/DynamicInfo.vue'; | ||
50 | - import SaleRadar from './components/SaleRadar.vue'; | ||
51 | - | ||
52 | - const maskColor = ref({ backgroundColor: 'grey' }); | ||
53 | - const statusModel = ref(false); | ||
54 | - const [register, { openModal }] = useModal(); | ||
55 | - onMounted(() => { | ||
56 | - const userInfo: object = getAuthCache(USER_INFO_KEY); | ||
57 | - if (userInfo.needSetPwd == true) { | ||
58 | - statusModel.value = true; | ||
59 | - openModal(statusModel.value); | ||
60 | - } else if (userInfo.needSetPwd == false) { | ||
61 | - openModal(statusModel.value); | ||
62 | - } | ||
63 | - }); | ||
64 | - //Yunteng123456!!! | ||
65 | - //Password123456! | ||
66 | - //System123456! | ||
67 | - //Testrole123456! | ||
68 | - const loading = ref(false); | 22 | + import HelpDoc from './components/HelpDoc.vue'; |
23 | + const loading = ref(true); | ||
69 | setTimeout(() => { | 24 | setTimeout(() => { |
70 | loading.value = false; | 25 | loading.value = false; |
71 | }, 1500); | 26 | }, 1500); |
@@ -51,7 +51,7 @@ | @@ -51,7 +51,7 @@ | ||
51 | props: { | 51 | props: { |
52 | userData: { type: Object }, | 52 | userData: { type: Object }, |
53 | }, | 53 | }, |
54 | - emits: ['reload'], | 54 | + emits: ['reload', 'register'], |
55 | setup(_, { emit }) { | 55 | setup(_, { emit }) { |
56 | const DeviceStep1Ref = ref<InstanceType<typeof DeviceStep1>>(); | 56 | const DeviceStep1Ref = ref<InstanceType<typeof DeviceStep1>>(); |
57 | const DeviceStep2Ref = ref<InstanceType<typeof DeviceStep2>>(); | 57 | const DeviceStep2Ref = ref<InstanceType<typeof DeviceStep2>>(); |
1 | <template> | 1 | <template> |
2 | - <div :class="prefixCls" class="relative w-full h-full px-4"> | ||
3 | - <AppLocalePicker | ||
4 | - class="absolute text-white top-4 right-4 enter-x xl:text-gray-600" | ||
5 | - :showText="false" | ||
6 | - v-if="!sessionTimeout && showLocale" | ||
7 | - /> | ||
8 | - <AppDarkModeToggle class="absolute top-3 right-7 enter-x" v-if="!sessionTimeout" /> | ||
9 | - | ||
10 | - <span class="-enter-x xl:hidden"> | ||
11 | - <AppLogo :alwaysShowTitle="true" /> | ||
12 | - </span> | ||
13 | - | ||
14 | - <div class="container relative h-full py-2 mx-auto sm:px-10"> | ||
15 | - <div class="flex h-full"> | ||
16 | - <div class="hidden min-h-full pl-4 mr-4 xl:flex xl:flex-col xl:w-6/12"> | ||
17 | - <AppLogo class="-enter-x" /> | ||
18 | - <div class="my-auto"> | ||
19 | - <img :alt="title" src="../../../assets/images/iot.png" class="w-4/5 -mt-16 -enter-x" /> | ||
20 | - <div class="mt-10 font-medium text-white -enter-x"> | ||
21 | - <span class="inline-block mt-4 text-3xl"> {{ t('sys.login.signInTitle') }}</span> | ||
22 | - </div> | ||
23 | - <div class="mt-5 font-normal text-white text-md dark:text-gray-500 -enter-x"> | ||
24 | - {{ t('sys.login.signInDesc') }} | ||
25 | - </div> | ||
26 | - </div> | ||
27 | - </div> | ||
28 | - <div class="flex w-full h-full py-5 xl:h-auto xl:py-0 xl:my-0 xl:w-6/12"> | ||
29 | - <div | ||
30 | - :class="`${prefixCls}-form`" | ||
31 | - class=" | ||
32 | - relative | ||
33 | - w-full | ||
34 | - px-5 | ||
35 | - py-8 | ||
36 | - mx-auto | ||
37 | - my-auto | ||
38 | - rounded-md | ||
39 | - shadow-md | ||
40 | - xl:ml-16 xl:bg-transparent | ||
41 | - sm:px-8 | ||
42 | - xl:p-4 xl:shadow-none | ||
43 | - sm:w-3/4 | ||
44 | - lg:w-2/4 | ||
45 | - xl:w-auto | ||
46 | - enter-x | ||
47 | - " | ||
48 | - > | ||
49 | - <LoginForm /> | ||
50 | - <ForgetPasswordForm /> | ||
51 | - <RegisterForm /> | ||
52 | - <MobileForm /> | ||
53 | - <QrCodeForm /> | ||
54 | - </div> | 2 | + <div class="login-page"> |
3 | + <div class="login-header" :style="{ backgroundColor: isDark ? '#1d3794' : '#22283a' }"> | ||
4 | + <AppLogo | ||
5 | + :alwaysShowTitle="true" | ||
6 | + style="z-index: 99; position: absolute; width: 40px; height: 100px; left: 10%; top: -20px" | ||
7 | + /> | ||
8 | + <AppLocalePicker | ||
9 | + class="absolute text-white top-4 right-4 enter-x xl:text-gray-600" | ||
10 | + :showText="false" | ||
11 | + v-if="!sessionTimeout && showLocale" | ||
12 | + /> | ||
13 | + <AppDarkModeToggle | ||
14 | + class="absolute top-3 right-7 enter-x" | ||
15 | + v-if="!sessionTimeout" | ||
16 | + @click="toggleDark" | ||
17 | + /> | ||
18 | + </div> | ||
19 | + <div class="login-container" :class="{ light1: isDark, dark: !isDark }"> | ||
20 | + <div class="login-description"> | ||
21 | + <h1>物联网平台</h1> | ||
22 | + <h2>输入您的个人详细信息开始使用!</h2> | ||
23 | + </div> | ||
24 | + <div class="flex w-full h-full py-5 xl:h-auto xl:py-0 xl:my-0 xl:w-6/12"> | ||
25 | + <div | ||
26 | + :class="`${prefixCls}-form`" | ||
27 | + class=" | ||
28 | + relative | ||
29 | + w-full | ||
30 | + px-5 | ||
31 | + py-8 | ||
32 | + mx-auto | ||
33 | + my-auto | ||
34 | + rounded-md | ||
35 | + shadow-md | ||
36 | + xl:ml-16 xl:bg-transparent | ||
37 | + sm:px-8 | ||
38 | + xl:p-4 xl:shadow-none | ||
39 | + sm:w-3/4 | ||
40 | + lg:w-2/4 | ||
41 | + xl:w-auto | ||
42 | + enter-x | ||
43 | + " | ||
44 | + :style="{ backgroundColor: isDark ? '#fff' : '#1a2030' }" | ||
45 | + > | ||
46 | + <LoginForm /> | ||
47 | + <ForgetPasswordForm /> | ||
48 | + <RegisterForm /> | ||
49 | + <MobileForm /> | ||
50 | + <QrCodeForm /> | ||
55 | </div> | 51 | </div> |
56 | </div> | 52 | </div> |
53 | + <div style="position: absolute; bottom: 20px; left: 45%">{{ getCopyRight }}</div> | ||
57 | </div> | 54 | </div> |
58 | </div> | 55 | </div> |
59 | </template> | 56 | </template> |
60 | <script lang="ts" setup> | 57 | <script lang="ts" setup> |
61 | - import { computed } from 'vue'; | 58 | + import { computed, ref } from 'vue'; |
62 | import { AppLogo } from '/@/components/Application'; | 59 | import { AppLogo } from '/@/components/Application'; |
63 | import { AppLocalePicker, AppDarkModeToggle } from '/@/components/Application'; | 60 | import { AppLocalePicker, AppDarkModeToggle } from '/@/components/Application'; |
64 | import LoginForm from './LoginForm.vue'; | 61 | import LoginForm from './LoginForm.vue'; |
@@ -70,6 +67,7 @@ | @@ -70,6 +67,7 @@ | ||
70 | import { useI18n } from '/@/hooks/web/useI18n'; | 67 | import { useI18n } from '/@/hooks/web/useI18n'; |
71 | import { useDesign } from '/@/hooks/web/useDesign'; | 68 | import { useDesign } from '/@/hooks/web/useDesign'; |
72 | import { useLocaleStore } from '/@/store/modules/locale'; | 69 | import { useLocaleStore } from '/@/store/modules/locale'; |
70 | + import { useUserStore } from '/@/store/modules/user'; | ||
73 | 71 | ||
74 | defineProps({ | 72 | defineProps({ |
75 | sessionTimeout: { | 73 | sessionTimeout: { |
@@ -83,145 +81,69 @@ | @@ -83,145 +81,69 @@ | ||
83 | const localeStore = useLocaleStore(); | 81 | const localeStore = useLocaleStore(); |
84 | const showLocale = localeStore.getShowPicker; | 82 | const showLocale = localeStore.getShowPicker; |
85 | const title = computed(() => globSetting?.title ?? ''); | 83 | const title = computed(() => globSetting?.title ?? ''); |
84 | + const isDark = ref(true); | ||
85 | + const toggleDark = () => { | ||
86 | + isDark.value = !isDark.value; | ||
87 | + }; | ||
88 | + const userStore = useUserStore(); | ||
89 | + const getCopyRight = computed(() => { | ||
90 | + return (userStore.platInfo?.copyright ?? '') + (userStore.platInfo?.presentedOurselves ?? ''); | ||
91 | + }); | ||
86 | </script> | 92 | </script> |
87 | <style lang="less"> | 93 | <style lang="less"> |
88 | @prefix-cls: ~'@{namespace}-login'; | 94 | @prefix-cls: ~'@{namespace}-login'; |
89 | @logo-prefix-cls: ~'@{namespace}-app-logo'; | 95 | @logo-prefix-cls: ~'@{namespace}-app-logo'; |
90 | @countdown-prefix-cls: ~'@{namespace}-countdown-input'; | 96 | @countdown-prefix-cls: ~'@{namespace}-countdown-input'; |
91 | @dark-bg: #293146; | 97 | @dark-bg: #293146; |
92 | - | ||
93 | - html[data-theme='dark'] { | ||
94 | - .@{prefix-cls} { | ||
95 | - background-color: @dark-bg; | ||
96 | - | ||
97 | - &::before { | ||
98 | - background-image: url(/@/assets/svg/login-bg-dark.svg); | ||
99 | - } | ||
100 | - | ||
101 | - .ant-input, | ||
102 | - .ant-input-password { | ||
103 | - background-color: #232a3b; | ||
104 | - } | ||
105 | - | ||
106 | - .ant-btn:not(.ant-btn-link):not(.ant-btn-primary) { | ||
107 | - border: 1px solid #4a5569; | ||
108 | - } | ||
109 | - | ||
110 | - &-form { | ||
111 | - background: transparent !important; | ||
112 | - } | ||
113 | - | ||
114 | - .app-iconify { | ||
115 | - color: #fff; | ||
116 | - } | ||
117 | - } | ||
118 | - | ||
119 | - input.fix-auto-fill, | ||
120 | - .fix-auto-fill input { | ||
121 | - -webkit-text-fill-color: #c9d1d9 !important; | ||
122 | - box-shadow: inherit !important; | ||
123 | - } | 98 | + .light1 { |
99 | + background-image: url('/src/assets/images/bg.png'); | ||
124 | } | 100 | } |
125 | - | ||
126 | - .@{prefix-cls} { | ||
127 | - min-height: 100%; | ||
128 | - overflow: hidden; | ||
129 | - @media (max-width: @screen-xl) { | ||
130 | - background-color: #293146; | ||
131 | - | ||
132 | - .@{prefix-cls}-form { | ||
133 | - background-color: #fff; | ||
134 | - } | ||
135 | - } | ||
136 | - | ||
137 | - &::before { | ||
138 | - position: absolute; | ||
139 | - top: 0; | ||
140 | - left: 0; | 101 | + .dark { |
102 | + background-image: url('/src/assets/images/bg-dark.png'); | ||
103 | + } | ||
104 | + .login-page { | ||
105 | + width: 100%; | ||
106 | + height: 100%; | ||
107 | + position: relative; | ||
108 | + .login-header { | ||
109 | + height: 60px; | ||
141 | width: 100%; | 110 | width: 100%; |
142 | - height: 100%; | ||
143 | - margin-left: -48%; | ||
144 | - background-image: url(/@/assets/svg/login-bg.svg); | ||
145 | - background-position: 100%; | ||
146 | - background-repeat: no-repeat; | ||
147 | - background-size: auto 100%; | ||
148 | - content: ''; | ||
149 | - @media (max-width: @screen-xl) { | ||
150 | - display: none; | 111 | + background-color: #1d3794; |
112 | + .vben-dark-switch { | ||
113 | + margin-left: 1840px; | ||
151 | } | 114 | } |
152 | } | 115 | } |
153 | 116 | ||
154 | - .@{logo-prefix-cls} { | ||
155 | - position: absolute; | ||
156 | - top: 12px; | ||
157 | - height: 30px; | ||
158 | - | ||
159 | - &__title { | ||
160 | - font-size: 16px; | ||
161 | - color: #fff; | ||
162 | - } | 117 | + .login-container { |
118 | + position: relative; | ||
119 | + left: -6px; | ||
120 | + right: 20px; | ||
121 | + width: 101vw; | ||
122 | + height: calc(100% - 60px); | ||
123 | + background-size: 100% 100%; | ||
124 | + background-repeat: no-repeat; | ||
125 | + .vben-login-form { | ||
126 | + position: absolute; | ||
163 | 127 | ||
164 | - img { | ||
165 | - width: 32px; | 128 | + width: 410px; |
129 | + right: 200px; | ||
130 | + top: 50%; | ||
131 | + margin-top: -180px; | ||
166 | } | 132 | } |
167 | - } | ||
168 | - | ||
169 | - .container { | ||
170 | - .@{logo-prefix-cls} { | ||
171 | - display: flex; | ||
172 | - width: 60%; | ||
173 | - height: 80px; | ||
174 | - | ||
175 | - &__title { | ||
176 | - font-size: 24px; | ||
177 | - color: #fff; | 133 | + .login-description { |
134 | + position: absolute; | ||
135 | + right: 13%; | ||
136 | + top: 15%; | ||
137 | + h1 { | ||
138 | + font-size: 26px; | ||
139 | + color: #5aeeed; | ||
140 | + text-align: center; | ||
178 | } | 141 | } |
179 | - | ||
180 | - img { | ||
181 | - width: 48px; | 142 | + h2 { |
143 | + font-size: 20px; | ||
144 | + color: #5aeeed; | ||
182 | } | 145 | } |
183 | } | 146 | } |
184 | } | 147 | } |
185 | - | ||
186 | - &-sign-in-way { | ||
187 | - .anticon { | ||
188 | - font-size: 22px; | ||
189 | - color: #888; | ||
190 | - cursor: pointer; | ||
191 | - | ||
192 | - &:hover { | ||
193 | - color: @primary-color; | ||
194 | - } | ||
195 | - } | ||
196 | - } | ||
197 | - | ||
198 | - input:not([type='checkbox']) { | ||
199 | - min-width: 360px; | ||
200 | - | ||
201 | - @media (max-width: @screen-xl) { | ||
202 | - min-width: 320px; | ||
203 | - } | ||
204 | - | ||
205 | - @media (max-width: @screen-lg) { | ||
206 | - min-width: 260px; | ||
207 | - } | ||
208 | - | ||
209 | - @media (max-width: @screen-md) { | ||
210 | - min-width: 240px; | ||
211 | - } | ||
212 | - | ||
213 | - @media (max-width: @screen-sm) { | ||
214 | - min-width: 160px; | ||
215 | - } | ||
216 | - } | ||
217 | - | ||
218 | - .@{countdown-prefix-cls} input { | ||
219 | - min-width: unset; | ||
220 | - } | ||
221 | - | ||
222 | - .ant-divider-inner-text { | ||
223 | - font-size: 12px; | ||
224 | - color: @text-color-secondary; | ||
225 | - } | ||
226 | } | 148 | } |
227 | </style> | 149 | </style> |
@@ -44,7 +44,7 @@ | @@ -44,7 +44,7 @@ | ||
44 | </ARow> | 44 | </ARow> |
45 | <ARow class="enter-x"> | 45 | <ARow class="enter-x"> |
46 | <ACol :span="12"> | 46 | <ACol :span="12"> |
47 | - <FormItem> </FormItem> | 47 | + <FormItem /> |
48 | </ACol> | 48 | </ACol> |
49 | <ACol :span="12"> | 49 | <ACol :span="12"> |
50 | <FormItem :style="{ 'text-align': 'right' }"> | 50 | <FormItem :style="{ 'text-align': 'right' }"> |
@@ -60,7 +60,7 @@ | @@ -60,7 +60,7 @@ | ||
60 | <script lang="ts" setup> | 60 | <script lang="ts" setup> |
61 | import { reactive, ref, toRaw, unref, computed } from 'vue'; | 61 | import { reactive, ref, toRaw, unref, computed } from 'vue'; |
62 | 62 | ||
63 | - import { Checkbox, Form, Input, Row, Col, Button, Divider } from 'ant-design-vue'; | 63 | + import { Form, Input, Row, Col, Button } from 'ant-design-vue'; |
64 | import LoginFormTitle from './LoginFormTitle.vue'; | 64 | import LoginFormTitle from './LoginFormTitle.vue'; |
65 | 65 | ||
66 | import { useI18n } from '/@/hooks/web/useI18n'; | 66 | import { useI18n } from '/@/hooks/web/useI18n'; |
@@ -69,7 +69,8 @@ | @@ -69,7 +69,8 @@ | ||
69 | import { useUserStore } from '/@/store/modules/user'; | 69 | import { useUserStore } from '/@/store/modules/user'; |
70 | import { LoginStateEnum, useLoginState, useFormRules, useFormValid } from './useLogin'; | 70 | import { LoginStateEnum, useLoginState, useFormRules, useFormValid } from './useLogin'; |
71 | import { useDesign } from '/@/hooks/web/useDesign'; | 71 | import { useDesign } from '/@/hooks/web/useDesign'; |
72 | - //import { onKeyStroke } from '@vueuse/core'; | 72 | + import { getPlatForm } from '/@/api/oem/index'; |
73 | + import { createLocalStorage } from '/@/utils/cache/index'; | ||
73 | 74 | ||
74 | const ACol = Col; | 75 | const ACol = Col; |
75 | const ARow = Row; | 76 | const ARow = Row; |
@@ -78,14 +79,12 @@ | @@ -78,14 +79,12 @@ | ||
78 | const { t } = useI18n(); | 79 | const { t } = useI18n(); |
79 | const { notification, createErrorModal } = useMessage(); | 80 | const { notification, createErrorModal } = useMessage(); |
80 | const { prefixCls } = useDesign('login'); | 81 | const { prefixCls } = useDesign('login'); |
81 | - const userStore = useUserStore(); | ||
82 | 82 | ||
83 | const { setLoginState, getLoginState } = useLoginState(); | 83 | const { setLoginState, getLoginState } = useLoginState(); |
84 | const { getFormRules } = useFormRules(); | 84 | const { getFormRules } = useFormRules(); |
85 | - | 85 | + const userStore = useUserStore(); |
86 | const formRef = ref(); | 86 | const formRef = ref(); |
87 | const loading = ref(false); | 87 | const loading = ref(false); |
88 | - const rememberMe = ref(false); | ||
89 | 88 | ||
90 | const formData = reactive({ | 89 | const formData = reactive({ |
91 | account: 'sysadmin', | 90 | account: 'sysadmin', |
@@ -116,8 +115,11 @@ | @@ -116,8 +115,11 @@ | ||
116 | description: `${t('sys.login.loginSuccessDesc')}: ${userInfo.realName}`, | 115 | description: `${t('sys.login.loginSuccessDesc')}: ${userInfo.realName}`, |
117 | duration: 3, | 116 | duration: 3, |
118 | }); | 117 | }); |
118 | + const res = await getPlatForm(); | ||
119 | + const storage = createLocalStorage(); | ||
120 | + storage.set('platformInfo', res); | ||
119 | } | 121 | } |
120 | - } catch (error) { | 122 | + } catch (error: any) { |
121 | createErrorModal({ | 123 | createErrorModal({ |
122 | title: t('sys.api.loginFailed'), | 124 | title: t('sys.api.loginFailed'), |
123 | content: | 125 | content: |
@@ -131,5 +133,15 @@ | @@ -131,5 +133,15 @@ | ||
131 | } finally { | 133 | } finally { |
132 | loading.value = false; | 134 | loading.value = false; |
133 | } | 135 | } |
136 | + | ||
137 | + const res = await getPlatForm(); | ||
138 | + userStore.setPlatInfo(res); | ||
139 | + // 设置icon | ||
140 | + let link = (document.querySelector("link[rel*='icon']") || | ||
141 | + document.createElement('link')) as HTMLLinkElement; | ||
142 | + link.type = 'image/x-icon'; | ||
143 | + link.rel = 'shortcut icon'; | ||
144 | + link.href = res.icon ?? '/public/favicon.ico'; | ||
145 | + document.getElementsByTagName('head')[0].appendChild(link); | ||
134 | } | 146 | } |
135 | </script> | 147 | </script> |
1 | <template> | 1 | <template> |
2 | - <h2 class="mb-3 text-2xl font-bold text-center xl:text-3xl enter-x xl:text-left"> | 2 | + <h2 |
3 | + class="mb-3 text-2xl font-bold text-center xl:text-3xl enter-x xl:text-left flex justify-center" | ||
4 | + > | ||
3 | {{ getFormTitle }} | 5 | {{ getFormTitle }} |
4 | </h2> | 6 | </h2> |
5 | </template> | 7 | </template> |
@@ -4,7 +4,7 @@ | @@ -4,7 +4,7 @@ | ||
4 | <div class="enter-x min-w-64 min-h-64"> | 4 | <div class="enter-x min-w-64 min-h-64"> |
5 | <QrCode | 5 | <QrCode |
6 | :value="qrCodeUrl" | 6 | :value="qrCodeUrl" |
7 | - class="enter-x flex justify-center xl:justify-start" | 7 | + class="enter-x flex justify-center xl:justify-center" |
8 | :width="280" | 8 | :width="280" |
9 | /> | 9 | /> |
10 | <Divider class="enter-x">{{ t('sys.login.scanSign') }}</Divider> | 10 | <Divider class="enter-x">{{ t('sys.login.scanSign') }}</Divider> |
@@ -52,7 +52,7 @@ | @@ -52,7 +52,7 @@ | ||
52 | import MenuDrawer from './MenuDrawer.vue'; | 52 | import MenuDrawer from './MenuDrawer.vue'; |
53 | 53 | ||
54 | // 导入列 属性,和搜索栏内容 | 54 | // 导入列 属性,和搜索栏内容 |
55 | - import { columns, searchFormSchema } from './menu.data'; | 55 | + import { columns } from './menu.data'; |
56 | import { useI18n } from '/@/hooks/web/useI18n'; | 56 | import { useI18n } from '/@/hooks/web/useI18n'; |
57 | import { notification } from 'ant-design-vue'; | 57 | import { notification } from 'ant-design-vue'; |
58 | 58 | ||
@@ -65,7 +65,6 @@ | @@ -65,7 +65,6 @@ | ||
65 | const { t } = useI18n(); //加载国际化 | 65 | const { t } = useI18n(); //加载国际化 |
66 | // 新增菜单 | 66 | // 新增菜单 |
67 | const getI18nCreateMenu = computed(() => t('routes.common.system.pageSystemTitleCreateMenu')); | 67 | const getI18nCreateMenu = computed(() => t('routes.common.system.pageSystemTitleCreateMenu')); |
68 | - console.log(111); | ||
69 | const [registerTable, { reload, expandAll }] = useTable({ | 68 | const [registerTable, { reload, expandAll }] = useTable({ |
70 | title: t('routes.common.system.pageSystemTitleMenuList'), //'菜单列表' | 69 | title: t('routes.common.system.pageSystemTitleMenuList'), //'菜单列表' |
71 | api: getMenuList, //加载数据 | 70 | api: getMenuList, //加载数据 |
@@ -98,10 +98,11 @@ | @@ -98,10 +98,11 @@ | ||
98 | const { createMessage } = useMessage(); | 98 | const { createMessage } = useMessage(); |
99 | const [tenantAdminFormDrawer, { openDrawer: openTenantAdminFormDrawer }] = useDrawer(); | 99 | const [tenantAdminFormDrawer, { openDrawer: openTenantAdminFormDrawer }] = useDrawer(); |
100 | 100 | ||
101 | + const tenantId = ref(''); | ||
101 | function handleCreateTenantAdmin() { | 102 | function handleCreateTenantAdmin() { |
102 | openTenantAdminFormDrawer(true, { | 103 | openTenantAdminFormDrawer(true, { |
103 | isUpdate: false, | 104 | isUpdate: false, |
104 | - tenantCode: tenantCode, | 105 | + tenantId: tenantId.value, |
105 | }); | 106 | }); |
106 | } | 107 | } |
107 | 108 | ||
@@ -109,7 +110,7 @@ | @@ -109,7 +110,7 @@ | ||
109 | openTenantAdminFormDrawer(true, { | 110 | openTenantAdminFormDrawer(true, { |
110 | isUpdate: true, | 111 | isUpdate: true, |
111 | record, | 112 | record, |
112 | - tenantCode: tenantCode, | 113 | + tenantCode: tenantId.value, |
113 | }); | 114 | }); |
114 | } | 115 | } |
115 | 116 | ||
@@ -160,7 +161,6 @@ | @@ -160,7 +161,6 @@ | ||
160 | slots: { customRender: 'status' }, | 161 | slots: { customRender: 'status' }, |
161 | }, | 162 | }, |
162 | ]; | 163 | ]; |
163 | - const tenantCode = ref(''); | ||
164 | const [tenantAdminTable, { reload }] = useTable({ | 164 | const [tenantAdminTable, { reload }] = useTable({ |
165 | api: getTenantAdminPage, | 165 | api: getTenantAdminPage, |
166 | columns: tenantAdminColumns as BasicColumn[], | 166 | columns: tenantAdminColumns as BasicColumn[], |
@@ -168,7 +168,7 @@ | @@ -168,7 +168,7 @@ | ||
168 | bordered: true, | 168 | bordered: true, |
169 | showIndexColumn: false, | 169 | showIndexColumn: false, |
170 | searchInfo: { | 170 | searchInfo: { |
171 | - tenantCode: tenantCode, | 171 | + tenantId: tenantId, |
172 | roleType: RoleEnum.ROLE_TENANT_ADMIN, | 172 | roleType: RoleEnum.ROLE_TENANT_ADMIN, |
173 | }, | 173 | }, |
174 | actionColumn: { | 174 | actionColumn: { |
@@ -186,8 +186,8 @@ | @@ -186,8 +186,8 @@ | ||
186 | }); | 186 | }); |
187 | //默认传递页面数据 | 187 | //默认传递页面数据 |
188 | const [tenantAdminDrawer, { closeDrawer }] = useDrawerInner(async (data) => { | 188 | const [tenantAdminDrawer, { closeDrawer }] = useDrawerInner(async (data) => { |
189 | - tenantCode.value = data.record.tenantCode; | ||
190 | - await reload(); | 189 | + tenantId.value = data.record.tenantId; |
190 | + reload(); | ||
191 | }); | 191 | }); |
192 | 192 | ||
193 | //提交按钮 | 193 | //提交按钮 |
@@ -204,7 +204,7 @@ | @@ -204,7 +204,7 @@ | ||
204 | handleCreateTenantAdmin, | 204 | handleCreateTenantAdmin, |
205 | handleSubmit, | 205 | handleSubmit, |
206 | tenantAdminTable, | 206 | tenantAdminTable, |
207 | - tenantCode, | 207 | + tenantId, |
208 | tenantAdminFormDrawer, | 208 | tenantAdminFormDrawer, |
209 | handleSuccess, | 209 | handleSuccess, |
210 | handleEdit, | 210 | handleEdit, |
@@ -7,7 +7,7 @@ | @@ -7,7 +7,7 @@ | ||
7 | width="60%" | 7 | width="60%" |
8 | @ok="handleSubmit" | 8 | @ok="handleSubmit" |
9 | > | 9 | > |
10 | - <BasicForm @register="tenantAdminForm"> </BasicForm> | 10 | + <BasicForm @register="tenantAdminForm" /> |
11 | </BasicDrawer> | 11 | </BasicDrawer> |
12 | </template> | 12 | </template> |
13 | <script lang="ts"> | 13 | <script lang="ts"> |
@@ -25,7 +25,7 @@ | @@ -25,7 +25,7 @@ | ||
25 | }, | 25 | }, |
26 | setup(_, { emit }) { | 26 | setup(_, { emit }) { |
27 | const isUpdate = ref(true); | 27 | const isUpdate = ref(true); |
28 | - const tenantCode = ref(''); | 28 | + const tenantId = ref(''); |
29 | const formSchema: FormSchema[] = [ | 29 | const formSchema: FormSchema[] = [ |
30 | { | 30 | { |
31 | field: 'id', | 31 | field: 'id', |
@@ -81,7 +81,7 @@ | @@ -81,7 +81,7 @@ | ||
81 | async (data) => { | 81 | async (data) => { |
82 | await resetFields(); | 82 | await resetFields(); |
83 | isUpdate.value = !!data?.isUpdate; | 83 | isUpdate.value = !!data?.isUpdate; |
84 | - tenantCode.value = data?.tenantCode; | 84 | + tenantId.value = data?.tenantId; |
85 | await updateSchema({ field: 'title', componentProps: { disabled: false } }); | 85 | await updateSchema({ field: 'title', componentProps: { disabled: false } }); |
86 | if (unref(isUpdate)) { | 86 | if (unref(isUpdate)) { |
87 | await setFieldsValue({ | 87 | await setFieldsValue({ |
@@ -106,7 +106,7 @@ | @@ -106,7 +106,7 @@ | ||
106 | typeof values.tenantExpireTime != 'undefined' && values.tenantExpireTime != null | 106 | typeof values.tenantExpireTime != 'undefined' && values.tenantExpireTime != null |
107 | ? values.tenantExpireTime.format('YYYY-MM-DD HH:mm:ss') | 107 | ? values.tenantExpireTime.format('YYYY-MM-DD HH:mm:ss') |
108 | : null, | 108 | : null, |
109 | - tenantCode: tenantCode.value, | 109 | + tenantId: tenantId.value, |
110 | }; | 110 | }; |
111 | setDrawerProps({ confirmLoading: true }); | 111 | setDrawerProps({ confirmLoading: true }); |
112 | saveTenantAdmin(requestParams as any as UserDTO).then(() => { | 112 | saveTenantAdmin(requestParams as any as UserDTO).then(() => { |
@@ -35,8 +35,8 @@ | @@ -35,8 +35,8 @@ | ||
35 | :before-upload="beforeUploadIconPic" | 35 | :before-upload="beforeUploadIconPic" |
36 | > | 36 | > |
37 | <div v-if="iconPic"> | 37 | <div v-if="iconPic"> |
38 | - <img :src="iconPic" /> | ||
39 | - <div style="background-color: #ccc">重新上传</div> | 38 | + <img :src="iconPic" class="m-auto" /> |
39 | + <div style="background-color: #ccc; margin-top: 20px">重新上传</div> | ||
40 | </div> | 40 | </div> |
41 | <div v-else> | 41 | <div v-else> |
42 | <PlusOutlined style="font-size: 30px" /> | 42 | <PlusOutlined style="font-size: 30px" /> |
@@ -95,6 +95,8 @@ | @@ -95,6 +95,8 @@ | ||
95 | import type { FileItem } from '/@/components/Upload/src/typing'; | 95 | import type { FileItem } from '/@/components/Upload/src/typing'; |
96 | import { logoUpload, iconUpload, bgUpload, getPlatForm, updatePlatForm } from '/@/api/oem/index'; | 96 | import { logoUpload, iconUpload, bgUpload, getPlatForm, updatePlatForm } from '/@/api/oem/index'; |
97 | import { PlusOutlined } from '@ant-design/icons-vue'; | 97 | import { PlusOutlined } from '@ant-design/icons-vue'; |
98 | + import { useUserStore } from '/@/store/modules/user'; | ||
99 | + import { createLocalStorage } from '/@/utils/cache/index'; | ||
98 | export default defineComponent({ | 100 | export default defineComponent({ |
99 | components: { | 101 | components: { |
100 | BasicForm, | 102 | BasicForm, |
@@ -111,6 +113,8 @@ | @@ -111,6 +113,8 @@ | ||
111 | tip: '拼命加载中...', | 113 | tip: '拼命加载中...', |
112 | }); | 114 | }); |
113 | const { createMessage } = useMessage(); | 115 | const { createMessage } = useMessage(); |
116 | + const userStore = useUserStore(); | ||
117 | + const storage = createLocalStorage(); | ||
114 | const [registerForm, { getFieldsValue, setFieldsValue }] = useForm({ | 118 | const [registerForm, { getFieldsValue, setFieldsValue }] = useForm({ |
115 | schemas, | 119 | schemas, |
116 | showSubmitButton: false, | 120 | showSubmitButton: false, |
@@ -146,7 +150,7 @@ | @@ -146,7 +150,7 @@ | ||
146 | } | 150 | } |
147 | return isJpgOrPng && isLt2M; | 151 | return isJpgOrPng && isLt2M; |
148 | }; | 152 | }; |
149 | - | 153 | + // Icon上传 |
150 | async function customUploadIconPic({ file }) { | 154 | async function customUploadIconPic({ file }) { |
151 | if (beforeUploadIconPic(file)) { | 155 | if (beforeUploadIconPic(file)) { |
152 | const formData = new FormData(); | 156 | const formData = new FormData(); |
@@ -158,9 +162,9 @@ | @@ -158,9 +162,9 @@ | ||
158 | } | 162 | } |
159 | } | 163 | } |
160 | const beforeUploadIconPic = (file: FileItem) => { | 164 | const beforeUploadIconPic = (file: FileItem) => { |
161 | - const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png'; | 165 | + const isJpgOrPng = file.type === 'image/x-icon'; |
162 | if (!isJpgOrPng) { | 166 | if (!isJpgOrPng) { |
163 | - createMessage.error('只能上传图片文件!'); | 167 | + createMessage.error('只能上传.icon图片文件!'); |
164 | } | 168 | } |
165 | const isLt2M = (file.size as number) / 1024 < 500; | 169 | const isLt2M = (file.size as number) / 1024 < 500; |
166 | if (!isLt2M) { | 170 | if (!isLt2M) { |
@@ -196,18 +200,28 @@ | @@ -196,18 +200,28 @@ | ||
196 | try { | 200 | try { |
197 | const fieldValue = getFieldsValue(); | 201 | const fieldValue = getFieldsValue(); |
198 | compState.value.loading = true; | 202 | compState.value.loading = true; |
199 | - await updatePlatForm({ | 203 | + const newFieldValue = { |
200 | ...fieldValue, | 204 | ...fieldValue, |
201 | - background: unref(bgPic), | ||
202 | - icon: unref(bgPic), | ||
203 | logo: unref(logoPic), | 205 | logo: unref(logoPic), |
204 | - }); | 206 | + icon: unref(iconPic), |
207 | + background: unref(bgPic), | ||
208 | + }; | ||
209 | + await updatePlatForm(newFieldValue); | ||
205 | compState.value.loading = false; | 210 | compState.value.loading = false; |
206 | createMessage.success('保存信息成功'); | 211 | createMessage.success('保存信息成功'); |
212 | + | ||
213 | + setPlatFormInfo(newFieldValue); | ||
207 | } catch (e) { | 214 | } catch (e) { |
208 | createMessage.error('保存信息失败'); | 215 | createMessage.error('保存信息失败'); |
209 | } | 216 | } |
210 | }; | 217 | }; |
218 | + // 设置平台信息 | ||
219 | + function setPlatFormInfo(newFieldValue) { | ||
220 | + // 保存store | ||
221 | + userStore.setPlatInfo(newFieldValue); | ||
222 | + // 保存本地缓存 | ||
223 | + storage.set('platInfo', newFieldValue); | ||
224 | + } | ||
211 | 225 | ||
212 | onMounted(async () => { | 226 | onMounted(async () => { |
213 | const res = await getPlatForm(); | 227 | const res = await getPlatForm(); |
1 | <template> | 1 | <template> |
2 | <div class="card"> | 2 | <div class="card"> |
3 | - <Card :bordered="false" class="card"> <BasicForm @register="registerForm" /></Card> | 3 | + <Card :bordered="false" class="card"> |
4 | + <BasicForm @register="registerForm"> | ||
5 | + <template #qrcode> | ||
6 | + <Upload | ||
7 | + name="avatar" | ||
8 | + list-type="picture-card" | ||
9 | + class="avatar-uploader" | ||
10 | + :show-upload-list="false" | ||
11 | + :customRequest="customUploadqrcodePic" | ||
12 | + :before-upload="beforeUploadqrcodePic" | ||
13 | + > | ||
14 | + <img v-if="qrcodePic" :src="qrcodePic" alt="avatar" /> | ||
15 | + <div v-else> | ||
16 | + <div style="margin-top: 30px"> | ||
17 | + <PlusOutlined style="font-size: 30px" /> | ||
18 | + </div> | ||
19 | + <div | ||
20 | + class="ant-upload-text flex" | ||
21 | + style="width: 280px; height: 130px; align-items: center" | ||
22 | + > | ||
23 | + 支持.PNG、.JPG、.SVG格式,建议尺寸为300px × 300px(及以上),大小不超过2M。</div | ||
24 | + > | ||
25 | + </div> | ||
26 | + </Upload> | ||
27 | + </template></BasicForm | ||
28 | + ></Card | ||
29 | + > | ||
4 | <Loading v-bind="compState" /> | 30 | <Loading v-bind="compState" /> |
5 | <a-button | 31 | <a-button |
6 | @click="handleUpdateInfo" | 32 | @click="handleUpdateInfo" |
@@ -14,17 +40,25 @@ | @@ -14,17 +40,25 @@ | ||
14 | 40 | ||
15 | <script lang="ts"> | 41 | <script lang="ts"> |
16 | import { defineComponent, onMounted, ref } from 'vue'; | 42 | import { defineComponent, onMounted, ref } from 'vue'; |
17 | - import { Card } from 'ant-design-vue'; | 43 | + import { Card, Upload } from 'ant-design-vue'; |
18 | import { BasicForm, useForm } from '/@/components/Form/index'; | 44 | import { BasicForm, useForm } from '/@/components/Form/index'; |
19 | import { schemas } from '../config/enterPriseInfo.config'; | 45 | import { schemas } from '../config/enterPriseInfo.config'; |
20 | import { getEnterPriseDetail, updateEnterPriseDetail } from '/@/api/oem/index'; | 46 | import { getEnterPriseDetail, updateEnterPriseDetail } from '/@/api/oem/index'; |
21 | import { Loading } from '/@/components/Loading'; | 47 | import { Loading } from '/@/components/Loading'; |
22 | import { useMessage } from '/@/hooks/web/useMessage'; | 48 | import { useMessage } from '/@/hooks/web/useMessage'; |
49 | + import { getTownChild } from '/@/api/oem/index'; | ||
50 | + import { useUserStore } from '/@/store/modules/user'; | ||
51 | + import { createLocalStorage } from '/@/utils/cache'; | ||
52 | + import { PlusOutlined } from '@ant-design/icons-vue'; | ||
53 | + import type { FileItem } from '/@/components/Upload/src/typing'; | ||
54 | + import { qrcodeUpload } from '/@/api/oem/index'; | ||
23 | export default defineComponent({ | 55 | export default defineComponent({ |
24 | components: { | 56 | components: { |
25 | Card, | 57 | Card, |
26 | BasicForm, | 58 | BasicForm, |
27 | Loading, | 59 | Loading, |
60 | + Upload, | ||
61 | + PlusOutlined, | ||
28 | }, | 62 | }, |
29 | setup() { | 63 | setup() { |
30 | const compState = ref({ | 64 | const compState = ref({ |
@@ -32,7 +66,7 @@ | @@ -32,7 +66,7 @@ | ||
32 | loading: false, | 66 | loading: false, |
33 | tip: '拼命加载中...', | 67 | tip: '拼命加载中...', |
34 | }); | 68 | }); |
35 | - const [registerForm, { getFieldsValue, setFieldsValue }] = useForm({ | 69 | + const [registerForm, { getFieldsValue, setFieldsValue, updateSchema }] = useForm({ |
36 | labelWidth: 80, | 70 | labelWidth: 80, |
37 | schemas, | 71 | schemas, |
38 | showResetButton: false, | 72 | showResetButton: false, |
@@ -42,32 +76,204 @@ | @@ -42,32 +76,204 @@ | ||
42 | }, | 76 | }, |
43 | }); | 77 | }); |
44 | const { createMessage } = useMessage(); | 78 | const { createMessage } = useMessage(); |
79 | + | ||
80 | + const qrcodePic = ref(); | ||
81 | + const customUploadqrcodePic = async ({ file }) => { | ||
82 | + if (beforeUploadqrcodePic(file)) { | ||
83 | + const formData = new FormData(); | ||
84 | + formData.append('file', file); | ||
85 | + const response = await qrcodeUpload(formData); | ||
86 | + if (response.fileStaticUri) { | ||
87 | + qrcodePic.value = response.fileStaticUri; | ||
88 | + } | ||
89 | + } | ||
90 | + }; | ||
91 | + const beforeUploadqrcodePic = (file: FileItem) => { | ||
92 | + const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png'; | ||
93 | + if (!isJpgOrPng) { | ||
94 | + createMessage.error('只能上传图片文件!'); | ||
95 | + } | ||
96 | + const isLt2M = (file.size as number) / 1024 / 1024 < 2; | ||
97 | + if (!isLt2M) { | ||
98 | + createMessage.error('图片大小不能超过2MB!'); | ||
99 | + } | ||
100 | + return isJpgOrPng && isLt2M; | ||
101 | + }; | ||
102 | + // 更新 | ||
45 | const handleUpdateInfo = async () => { | 103 | const handleUpdateInfo = async () => { |
46 | try { | 104 | try { |
47 | compState.value.loading = true; | 105 | compState.value.loading = true; |
48 | const fieldsValue = getFieldsValue(); | 106 | const fieldsValue = getFieldsValue(); |
49 | - await updateEnterPriseDetail({ | 107 | + const newFieldValue = { |
50 | ...fieldsValue, | 108 | ...fieldsValue, |
51 | codeProv: fieldsValue.nameProv, | 109 | codeProv: fieldsValue.nameProv, |
52 | codeCity: fieldsValue.nameCity, | 110 | codeCity: fieldsValue.nameCity, |
53 | codeCoun: fieldsValue.nameCoun, | 111 | codeCoun: fieldsValue.nameCoun, |
54 | codeTown: fieldsValue.nameTown, | 112 | codeTown: fieldsValue.nameTown, |
55 | - }); | 113 | + qrCode: qrcodePic.value, |
114 | + }; | ||
115 | + console.log(fieldsValue); | ||
116 | + console.log(newFieldValue); | ||
117 | + await updateEnterPriseDetail(newFieldValue); | ||
56 | compState.value.loading = false; | 118 | compState.value.loading = false; |
57 | createMessage.success('更新信息成功'); | 119 | createMessage.success('更新信息成功'); |
120 | + setEnterPriseInfo(newFieldValue); | ||
58 | } catch (e) { | 121 | } catch (e) { |
59 | createMessage.error('更新信息失败'); | 122 | createMessage.error('更新信息失败'); |
60 | } | 123 | } |
61 | }; | 124 | }; |
125 | + | ||
126 | + const userStore = useUserStore(); | ||
127 | + const storage = createLocalStorage(); | ||
128 | + | ||
129 | + // 设置企业信息 | ||
130 | + function setEnterPriseInfo(newFieldValue) { | ||
131 | + // 保存store | ||
132 | + userStore.setEnterPriseInfo(newFieldValue); | ||
133 | + // 保存本地缓存 | ||
134 | + storage.set('enterpriseInfo', newFieldValue); | ||
135 | + } | ||
136 | + | ||
137 | + // 地区显示回显和数据联动 | ||
138 | + async function updateCityData( | ||
139 | + codeProv: string, | ||
140 | + codeCity: string, | ||
141 | + codeCoun: string, | ||
142 | + codeTown: string | ||
143 | + ) { | ||
144 | + const nameCity = await getTownChild('codeProv', codeProv); | ||
145 | + const nameCoun = await getTownChild('codeCity', codeCity); | ||
146 | + const nameTown = await getTownChild('codeCoun', codeCoun); | ||
147 | + nameCity.forEach((item) => { | ||
148 | + item.label = item.nameCity; | ||
149 | + item.value = item.codeCity; | ||
150 | + }); | ||
151 | + nameCoun.forEach((item) => { | ||
152 | + item.label = item.nameCoun; | ||
153 | + item.value = item.codeCoun; | ||
154 | + }); | ||
155 | + nameTown.forEach((item) => { | ||
156 | + item.label = item.nameTown; | ||
157 | + item.value = item.codeTown; | ||
158 | + }); | ||
159 | + setFieldsValue({ | ||
160 | + nameProv: codeProv, | ||
161 | + nameCity: codeCity, | ||
162 | + nameCoun: codeCoun, | ||
163 | + nameTown: codeTown, | ||
164 | + }); | ||
165 | + updateSchema({ | ||
166 | + field: 'nameTown', | ||
167 | + componentProps: { | ||
168 | + options: nameTown, | ||
169 | + }, | ||
170 | + }); | ||
171 | + updateSchema({ | ||
172 | + field: 'nameCoun', | ||
173 | + componentProps: { | ||
174 | + options: nameCoun, | ||
175 | + async onChange(value) { | ||
176 | + if (value === undefined) { | ||
177 | + setFieldsValue({ | ||
178 | + nameTown: undefined, | ||
179 | + }); | ||
180 | + updateSchema({ | ||
181 | + field: 'nameTown', | ||
182 | + componentProps: { | ||
183 | + options: [], | ||
184 | + }, | ||
185 | + }); | ||
186 | + } | ||
187 | + let nameTown = await getTownChild('codeCoun', value); | ||
188 | + nameTown.forEach((item) => { | ||
189 | + item.label = item.nameTown; | ||
190 | + item.value = item.codeTown; | ||
191 | + }); | ||
192 | + setFieldsValue({ | ||
193 | + nameTown: undefined, | ||
194 | + }); | ||
195 | + updateSchema({ | ||
196 | + field: 'nameTown', | ||
197 | + componentProps: { | ||
198 | + placeholder: '请选择街道/城镇', | ||
199 | + options: nameTown, | ||
200 | + }, | ||
201 | + }); | ||
202 | + }, | ||
203 | + }, | ||
204 | + }); | ||
205 | + updateSchema({ | ||
206 | + field: 'nameCity', | ||
207 | + componentProps: ({ formModel }) => { | ||
208 | + return { | ||
209 | + options: nameCity, | ||
210 | + onChange: async (value) => { | ||
211 | + let nameCoun = await getTownChild('codeCity', value); | ||
212 | + if (value === undefined) { | ||
213 | + formModel.nameCoun = undefined; // reset city value | ||
214 | + formModel.nameTown = undefined; | ||
215 | + nameCoun = []; | ||
216 | + updateSchema({ | ||
217 | + field: 'nameTown', | ||
218 | + componentProps: { | ||
219 | + options: [], | ||
220 | + }, | ||
221 | + }); | ||
222 | + } | ||
223 | + nameCoun.forEach((item) => { | ||
224 | + item.label = item.nameCoun; | ||
225 | + item.value = item.codeCoun; | ||
226 | + }); | ||
227 | + formModel.nameCoun = undefined; // reset city value | ||
228 | + formModel.nameTown = undefined; | ||
229 | + updateSchema({ | ||
230 | + field: 'nameCoun', | ||
231 | + componentProps: { | ||
232 | + // 请选择区 | ||
233 | + options: nameCoun, | ||
234 | + async onChange(value) { | ||
235 | + let nameTown = await getTownChild('codeCoun', value); | ||
236 | + if (value === undefined) { | ||
237 | + formModel.nameTown = undefined; | ||
238 | + nameTown = []; | ||
239 | + } | ||
240 | + nameTown.forEach((item) => { | ||
241 | + item.label = item.nameTown; | ||
242 | + item.value = item.codeTown; | ||
243 | + }); | ||
244 | + | ||
245 | + formModel.nameTown = undefined; | ||
246 | + updateSchema({ | ||
247 | + field: 'nameTown', | ||
248 | + componentProps: { | ||
249 | + placeholder: '请选择街道/城镇', | ||
250 | + options: nameTown, | ||
251 | + }, | ||
252 | + }); | ||
253 | + }, | ||
254 | + }, | ||
255 | + }); | ||
256 | + }, | ||
257 | + }; | ||
258 | + }, | ||
259 | + }); | ||
260 | + } | ||
261 | + | ||
62 | onMounted(async () => { | 262 | onMounted(async () => { |
63 | const res = await getEnterPriseDetail(); | 263 | const res = await getEnterPriseDetail(); |
264 | + updateCityData(res.codeProv, res.codeCity, res.codeCoun, res.codeTown); | ||
64 | setFieldsValue(res); | 265 | setFieldsValue(res); |
266 | + qrcodePic.value = res.qrCode; | ||
267 | + console.log(res); | ||
65 | }); | 268 | }); |
66 | 269 | ||
67 | return { | 270 | return { |
68 | registerForm, | 271 | registerForm, |
69 | compState, | 272 | compState, |
273 | + qrcodePic, | ||
70 | handleUpdateInfo, | 274 | handleUpdateInfo, |
275 | + customUploadqrcodePic, | ||
276 | + beforeUploadqrcodePic, | ||
71 | }; | 277 | }; |
72 | }, | 278 | }, |
73 | }); | 279 | }); |
@@ -51,6 +51,7 @@ export const schemas: FormSchema[] = [ | @@ -51,6 +51,7 @@ export const schemas: FormSchema[] = [ | ||
51 | field: 'synopsis', | 51 | field: 'synopsis', |
52 | component: 'InputTextArea', | 52 | component: 'InputTextArea', |
53 | label: '公司简介', | 53 | label: '公司简介', |
54 | + | ||
54 | colProps: { | 55 | colProps: { |
55 | span: 24, | 56 | span: 24, |
56 | }, | 57 | }, |
@@ -116,6 +117,9 @@ export const schemas: FormSchema[] = [ | @@ -116,6 +117,9 @@ export const schemas: FormSchema[] = [ | ||
116 | }, | 117 | }, |
117 | }); | 118 | }); |
118 | } | 119 | } |
120 | + formModel.nameCity = undefined; // reset city value | ||
121 | + formModel.nameCoun = undefined; | ||
122 | + formModel.nameTown = undefined; | ||
119 | updateSchema({ | 123 | updateSchema({ |
120 | field: 'nameCity', | 124 | field: 'nameCity', |
121 | componentProps: () => { | 125 | componentProps: () => { |
@@ -146,14 +150,20 @@ export const schemas: FormSchema[] = [ | @@ -146,14 +150,20 @@ export const schemas: FormSchema[] = [ | ||
146 | // 请选择区 | 150 | // 请选择区 |
147 | options: nameCoun, | 151 | options: nameCoun, |
148 | async onChange(value) { | 152 | async onChange(value) { |
149 | - let nameTown = await getTownChild('codeCoun', value); | 153 | + const nameTown = await getTownChild('codeCoun', value); |
150 | nameTown.forEach((item) => { | 154 | nameTown.forEach((item) => { |
151 | item.label = item.nameTown; | 155 | item.label = item.nameTown; |
152 | item.value = item.codeTown; | 156 | item.value = item.codeTown; |
153 | }); | 157 | }); |
154 | if (value === undefined) { | 158 | if (value === undefined) { |
155 | formModel.nameTown = undefined; | 159 | formModel.nameTown = undefined; |
156 | - nameTown = []; | 160 | + updateSchema({ |
161 | + field: 'nameTown', | ||
162 | + componentProps: { | ||
163 | + placeholder: '请选择街道/城镇', | ||
164 | + options: [], | ||
165 | + }, | ||
166 | + }); | ||
157 | } | 167 | } |
158 | updateSchema({ | 168 | updateSchema({ |
159 | field: 'nameTown', | 169 | field: 'nameTown', |
@@ -177,11 +187,10 @@ export const schemas: FormSchema[] = [ | @@ -177,11 +187,10 @@ export const schemas: FormSchema[] = [ | ||
177 | field: 'nameCity', | 187 | field: 'nameCity', |
178 | component: 'Select', | 188 | component: 'Select', |
179 | label: '', | 189 | label: '', |
180 | - | ||
181 | colProps: { | 190 | colProps: { |
182 | span: 5, | 191 | span: 5, |
183 | style: { | 192 | style: { |
184 | - marginLeft: '-80px', | 193 | + marginLeft: '-5rem', |
185 | }, | 194 | }, |
186 | }, | 195 | }, |
187 | }, | 196 | }, |
@@ -213,13 +222,6 @@ export const schemas: FormSchema[] = [ | @@ -213,13 +222,6 @@ export const schemas: FormSchema[] = [ | ||
213 | placeholder: '请选择街道/城镇', | 222 | placeholder: '请选择街道/城镇', |
214 | }, | 223 | }, |
215 | }, | 224 | }, |
216 | - | ||
217 | - // { | ||
218 | - // field: 'nameProv', | ||
219 | - // label: '所在城市', | ||
220 | - // component: 'Cascader', | ||
221 | - // }, | ||
222 | - | ||
223 | { | 225 | { |
224 | field: 'address', | 226 | field: 'address', |
225 | component: 'Input', | 227 | component: 'Input', |
@@ -254,4 +256,13 @@ export const schemas: FormSchema[] = [ | @@ -254,4 +256,13 @@ export const schemas: FormSchema[] = [ | ||
254 | placeholder: '请输入联系电话', | 256 | placeholder: '请输入联系电话', |
255 | }, | 257 | }, |
256 | }, | 258 | }, |
259 | + { | ||
260 | + field: 'qrcode', | ||
261 | + label: '二维码', | ||
262 | + component: 'Input', | ||
263 | + colProps: { | ||
264 | + span: 24, | ||
265 | + }, | ||
266 | + slot: 'qrcode', | ||
267 | + }, | ||
257 | ]; | 268 | ]; |
@@ -23,7 +23,7 @@ | @@ -23,7 +23,7 @@ | ||
23 | import EnterpriseInfo from './components/EnterpriseInfo.vue'; | 23 | import EnterpriseInfo from './components/EnterpriseInfo.vue'; |
24 | import CVIDraw from './components/CVIDraw.vue'; | 24 | import CVIDraw from './components/CVIDraw.vue'; |
25 | import AppDraw from './components/AppDraw.vue'; | 25 | import AppDraw from './components/AppDraw.vue'; |
26 | - const activeKey = ref('APP定制'); | 26 | + const activeKey = ref('企业信息'); |
27 | </script> | 27 | </script> |
28 | 28 | ||
29 | <style lang="less" scoped> | 29 | <style lang="less" scoped> |