Commit 4fe7d1e94c7257c011d2d8e0195bdc916ff9be4f
Merge branch 'sqy_dev' into 'main'
oem,首页,登录页逻辑界面修改 See merge request huang/yun-teng-iot-front!22
Showing
22 changed files
with
516 additions
and
189 deletions
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,13 +2,18 @@ | @@ -2,13 +2,18 @@ | ||
| 2 | * @Author: Vben | 2 | * @Author: Vben |
| 3 | * @Description: logo component | 3 | * @Description: logo component |
| 4 | --> | 4 | --> |
| 5 | -<!-- TODO: appLogo --> | 5 | + |
| 6 | <template> | 6 | <template> |
| 7 | <div class="anticon" :class="getAppLogoClass" @click="goHome"> | 7 | <div class="anticon" :class="getAppLogoClass" @click="goHome"> |
| 8 | - <img :src="getLogoUrl" /> | ||
| 9 | - <div class="ml-2 md:opacity-100" :class="getTitleClass" v-show="showTitle"> | ||
| 10 | - {{ title }} | ||
| 11 | - </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> | ||
| 12 | </div> | 17 | </div> |
| 13 | </template> | 18 | </template> |
| 14 | <script lang="ts" setup> | 19 | <script lang="ts" setup> |
| @@ -19,7 +24,6 @@ | @@ -19,7 +24,6 @@ | ||
| 19 | import { useDesign } from '/@/hooks/web/useDesign'; | 24 | import { useDesign } from '/@/hooks/web/useDesign'; |
| 20 | import { PageEnum } from '/@/enums/pageEnum'; | 25 | import { PageEnum } from '/@/enums/pageEnum'; |
| 21 | import { useUserStore } from '/@/store/modules/user'; | 26 | import { useUserStore } from '/@/store/modules/user'; |
| 22 | - import { createLocalStorage } from '/@/utils/cache/index'; | ||
| 23 | const props = defineProps({ | 27 | const props = defineProps({ |
| 24 | /** | 28 | /** |
| 25 | * The theme of the current parent component | 29 | * The theme of the current parent component |
| @@ -46,15 +50,6 @@ | @@ -46,15 +50,6 @@ | ||
| 46 | props.theme, | 50 | props.theme, |
| 47 | { 'collapsed-show-title': unref(getCollapsedShowTitle) }, | 51 | { 'collapsed-show-title': unref(getCollapsedShowTitle) }, |
| 48 | ]); | 52 | ]); |
| 49 | - | ||
| 50 | - const storage = createLocalStorage(); | ||
| 51 | - // 获取AppLogo | ||
| 52 | - const getLogoUrl = computed(() => { | ||
| 53 | - return storage.get('platformInfo') | ||
| 54 | - ? storage.get('platformInfo').logo | ||
| 55 | - : '/src/assets/images/logo.png'; | ||
| 56 | - }); | ||
| 57 | - | ||
| 58 | const getTitleClass = computed(() => [ | 53 | const getTitleClass = computed(() => [ |
| 59 | `${prefixCls}__title`, | 54 | `${prefixCls}__title`, |
| 60 | { | 55 | { |
| @@ -65,10 +60,22 @@ | @@ -65,10 +60,22 @@ | ||
| 65 | function goHome() { | 60 | function goHome() { |
| 66 | go(userStore.getUserInfo.homePath || PageEnum.BASE_HOME); | 61 | go(userStore.getUserInfo.homePath || PageEnum.BASE_HOME); |
| 67 | } | 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 | + }); | ||
| 68 | </script> | 76 | </script> |
| 69 | <style lang="less" scoped> | 77 | <style lang="less" scoped> |
| 70 | @prefix-cls: ~'@{namespace}-app-logo'; | 78 | @prefix-cls: ~'@{namespace}-app-logo'; |
| 71 | - | ||
| 72 | .@{prefix-cls} { | 79 | .@{prefix-cls} { |
| 73 | display: flex; | 80 | display: flex; |
| 74 | 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, |
| @@ -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 | ]; |
| @@ -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 | }); |
| @@ -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"> | 2 | + <!-- <div :class="prefixCls" class="relative w-full h-full px-4"> |
| 3 | <AppLocalePicker | 3 | <AppLocalePicker |
| 4 | class="absolute text-white top-4 right-4 enter-x xl:text-gray-600" | 4 | class="absolute text-white top-4 right-4 enter-x xl:text-gray-600" |
| 5 | :showText="false" | 5 | :showText="false" |
| @@ -9,14 +9,14 @@ | @@ -9,14 +9,14 @@ | ||
| 9 | 9 | ||
| 10 | <span class="-enter-x xl:hidden"> | 10 | <span class="-enter-x xl:hidden"> |
| 11 | <AppLogo :alwaysShowTitle="true" /> | 11 | <AppLogo :alwaysShowTitle="true" /> |
| 12 | - </span> | 12 | + </span> --> |
| 13 | 13 | ||
| 14 | - <div class="container relative h-full py-2 mx-auto sm:px-10"> | 14 | + <!-- <div class="container relative h-full py-2 mx-auto sm:px-10"> |
| 15 | <div class="flex h-full"> | 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"> | 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" /> | 17 | <AppLogo class="-enter-x" /> |
| 18 | <div class="my-auto"> | 18 | <div class="my-auto"> |
| 19 | - <img :alt="title" src="../../../assets/images/iot.png" class="w-4/5 -mt-16 -enter-x" /> | 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"> | 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> | 21 | <span class="inline-block mt-4 text-3xl"> {{ t('sys.login.signInTitle') }}</span> |
| 22 | </div> | 22 | </div> |
| @@ -54,11 +54,65 @@ | @@ -54,11 +54,65 @@ | ||
| 54 | </div> | 54 | </div> |
| 55 | </div> | 55 | </div> |
| 56 | </div> | 56 | </div> |
| 57 | + </div> --> | ||
| 58 | + <!-- </div> --> | ||
| 59 | + <div class="login-page"> | ||
| 60 | + <div class="login-header" :style="{ backgroundColor: isDark ? '#1d3794' : '#22283a' }"> | ||
| 61 | + <AppLogo | ||
| 62 | + :alwaysShowTitle="true" | ||
| 63 | + style="z-index: 99; position: absolute; width: 40px; height: 100px; left: 10%; top: -20px" | ||
| 64 | + /> | ||
| 65 | + <AppLocalePicker | ||
| 66 | + class="absolute text-white top-4 right-4 enter-x xl:text-gray-600" | ||
| 67 | + :showText="false" | ||
| 68 | + v-if="!sessionTimeout && showLocale" | ||
| 69 | + /> | ||
| 70 | + <AppDarkModeToggle | ||
| 71 | + class="absolute top-3 right-7 enter-x" | ||
| 72 | + v-if="!sessionTimeout" | ||
| 73 | + @click="toggleDark" | ||
| 74 | + /> | ||
| 75 | + </div> | ||
| 76 | + <div class="login-container" :class="{ light1: isDark, dark: !isDark }"> | ||
| 77 | + <div class="login-description"> | ||
| 78 | + <h1>物联网平台</h1> | ||
| 79 | + <h2>输入您的个人详细信息开始使用!</h2> | ||
| 80 | + </div> | ||
| 81 | + <div class="flex w-full h-full py-5 xl:h-auto xl:py-0 xl:my-0 xl:w-6/12"> | ||
| 82 | + <div | ||
| 83 | + :class="`${prefixCls}-form`" | ||
| 84 | + class=" | ||
| 85 | + relative | ||
| 86 | + w-full | ||
| 87 | + px-5 | ||
| 88 | + py-8 | ||
| 89 | + mx-auto | ||
| 90 | + my-auto | ||
| 91 | + rounded-md | ||
| 92 | + shadow-md | ||
| 93 | + xl:ml-16 xl:bg-transparent | ||
| 94 | + sm:px-8 | ||
| 95 | + xl:p-4 xl:shadow-none | ||
| 96 | + sm:w-3/4 | ||
| 97 | + lg:w-2/4 | ||
| 98 | + xl:w-auto | ||
| 99 | + enter-x | ||
| 100 | + " | ||
| 101 | + :style="{ backgroundColor: isDark ? '#fff' : '#1a2030' }" | ||
| 102 | + > | ||
| 103 | + <LoginForm /> | ||
| 104 | + <ForgetPasswordForm /> | ||
| 105 | + <RegisterForm /> | ||
| 106 | + <MobileForm /> | ||
| 107 | + <QrCodeForm /> | ||
| 108 | + </div> | ||
| 109 | + </div> | ||
| 110 | + <div style="position: absolute; bottom: 20px; left: 45%">{{ getCopyRight }}</div> | ||
| 57 | </div> | 111 | </div> |
| 58 | </div> | 112 | </div> |
| 59 | </template> | 113 | </template> |
| 60 | <script lang="ts" setup> | 114 | <script lang="ts" setup> |
| 61 | - import { computed } from 'vue'; | 115 | + import { computed, ref } from 'vue'; |
| 62 | import { AppLogo } from '/@/components/Application'; | 116 | import { AppLogo } from '/@/components/Application'; |
| 63 | import { AppLocalePicker, AppDarkModeToggle } from '/@/components/Application'; | 117 | import { AppLocalePicker, AppDarkModeToggle } from '/@/components/Application'; |
| 64 | import LoginForm from './LoginForm.vue'; | 118 | import LoginForm from './LoginForm.vue'; |
| @@ -70,6 +124,7 @@ | @@ -70,6 +124,7 @@ | ||
| 70 | import { useI18n } from '/@/hooks/web/useI18n'; | 124 | import { useI18n } from '/@/hooks/web/useI18n'; |
| 71 | import { useDesign } from '/@/hooks/web/useDesign'; | 125 | import { useDesign } from '/@/hooks/web/useDesign'; |
| 72 | import { useLocaleStore } from '/@/store/modules/locale'; | 126 | import { useLocaleStore } from '/@/store/modules/locale'; |
| 127 | + import { useUserStore } from '/@/store/modules/user'; | ||
| 73 | 128 | ||
| 74 | defineProps({ | 129 | defineProps({ |
| 75 | sessionTimeout: { | 130 | sessionTimeout: { |
| @@ -83,6 +138,14 @@ | @@ -83,6 +138,14 @@ | ||
| 83 | const localeStore = useLocaleStore(); | 138 | const localeStore = useLocaleStore(); |
| 84 | const showLocale = localeStore.getShowPicker; | 139 | const showLocale = localeStore.getShowPicker; |
| 85 | const title = computed(() => globSetting?.title ?? ''); | 140 | const title = computed(() => globSetting?.title ?? ''); |
| 141 | + const isDark = ref(true); | ||
| 142 | + const toggleDark = () => { | ||
| 143 | + isDark.value = !isDark.value; | ||
| 144 | + }; | ||
| 145 | + const userStore = useUserStore(); | ||
| 146 | + const getCopyRight = computed(() => { | ||
| 147 | + return (userStore.platInfo?.copyright ?? '') + (userStore.platInfo?.presentedOurselves ?? ''); | ||
| 148 | + }); | ||
| 86 | </script> | 149 | </script> |
| 87 | <style lang="less"> | 150 | <style lang="less"> |
| 88 | @prefix-cls: ~'@{namespace}-login'; | 151 | @prefix-cls: ~'@{namespace}-login'; |
| @@ -90,138 +153,190 @@ | @@ -90,138 +153,190 @@ | ||
| 90 | @countdown-prefix-cls: ~'@{namespace}-countdown-input'; | 153 | @countdown-prefix-cls: ~'@{namespace}-countdown-input'; |
| 91 | @dark-bg: #293146; | 154 | @dark-bg: #293146; |
| 92 | 155 | ||
| 93 | - html[data-theme='dark'] { | ||
| 94 | - .@{prefix-cls} { | ||
| 95 | - background-color: @dark-bg; | 156 | + // html[data-theme='dark'] { |
| 157 | + // .@{prefix-cls} { | ||
| 158 | + // background-color: @dark-bg; | ||
| 96 | 159 | ||
| 97 | - &::before { | ||
| 98 | - background-image: url(/@/assets/svg/login-bg-dark.svg); | ||
| 99 | - } | 160 | + // &::before { |
| 161 | + // background-image: url(/@/assets/svg/login-bg-dark.svg); | ||
| 162 | + // } | ||
| 100 | 163 | ||
| 101 | - .ant-input, | ||
| 102 | - .ant-input-password { | ||
| 103 | - background-color: #232a3b; | ||
| 104 | - } | 164 | + // .ant-input, |
| 165 | + // .ant-input-password { | ||
| 166 | + // background-color: #232a3b; | ||
| 167 | + // } | ||
| 105 | 168 | ||
| 106 | - .ant-btn:not(.ant-btn-link):not(.ant-btn-primary) { | ||
| 107 | - border: 1px solid #4a5569; | ||
| 108 | - } | 169 | + // .ant-btn:not(.ant-btn-link):not(.ant-btn-primary) { |
| 170 | + // border: 1px solid #4a5569; | ||
| 171 | + // } | ||
| 109 | 172 | ||
| 110 | - &-form { | ||
| 111 | - background: transparent !important; | ||
| 112 | - } | 173 | + // &-form { |
| 174 | + // background: transparent !important; | ||
| 175 | + // } | ||
| 113 | 176 | ||
| 114 | - .app-iconify { | ||
| 115 | - color: #fff; | ||
| 116 | - } | ||
| 117 | - } | 177 | + // .app-iconify { |
| 178 | + // color: #fff; | ||
| 179 | + // } | ||
| 180 | + // } | ||
| 118 | 181 | ||
| 119 | - input.fix-auto-fill, | ||
| 120 | - .fix-auto-fill input { | ||
| 121 | - -webkit-text-fill-color: #c9d1d9 !important; | ||
| 122 | - box-shadow: inherit !important; | ||
| 123 | - } | ||
| 124 | - } | 182 | + // input.fix-auto-fill, |
| 183 | + // .fix-auto-fill input { | ||
| 184 | + // -webkit-text-fill-color: #c9d1d9 !important; | ||
| 185 | + // box-shadow: inherit !important; | ||
| 186 | + // } | ||
| 187 | + // } | ||
| 125 | 188 | ||
| 126 | - .@{prefix-cls} { | ||
| 127 | - min-height: 100%; | ||
| 128 | - overflow: hidden; | ||
| 129 | - @media (max-width: @screen-xl) { | ||
| 130 | - background-color: #293146; | 189 | + // .@{prefix-cls} { |
| 190 | + // min-height: 100%; | ||
| 191 | + // overflow: hidden; | ||
| 192 | + // @media (max-width: @screen-xl) { | ||
| 193 | + // background-color: #293146; | ||
| 131 | 194 | ||
| 132 | - .@{prefix-cls}-form { | ||
| 133 | - background-color: #fff; | ||
| 134 | - } | ||
| 135 | - } | 195 | + // .@{prefix-cls}-form { |
| 196 | + // background-color: #fff; | ||
| 197 | + // } | ||
| 198 | + // } | ||
| 136 | 199 | ||
| 137 | - &::before { | ||
| 138 | - position: absolute; | ||
| 139 | - top: 0; | ||
| 140 | - left: 0; | ||
| 141 | - 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; | ||
| 151 | - } | ||
| 152 | - } | 200 | + // &::before { |
| 201 | + // position: absolute; | ||
| 202 | + // top: 0; | ||
| 203 | + // left: 0; | ||
| 204 | + // width: 100%; | ||
| 205 | + // height: 100%; | ||
| 206 | + // margin-left: -48%; | ||
| 207 | + // background-image: url(/@/assets/images/bg.png); | ||
| 208 | + // background-position: 100%; | ||
| 209 | + // background-repeat: no-repeat; | ||
| 210 | + // background-size: auto 100%; | ||
| 211 | + // content: ''; | ||
| 212 | + // @media (max-width: @screen-xl) { | ||
| 213 | + // display: none; | ||
| 214 | + // } | ||
| 215 | + // } | ||
| 153 | 216 | ||
| 154 | - .@{logo-prefix-cls} { | ||
| 155 | - position: absolute; | ||
| 156 | - top: 12px; | ||
| 157 | - height: 30px; | 217 | + // .@{logo-prefix-cls} { |
| 218 | + // position: absolute; | ||
| 219 | + // top: 12px; | ||
| 220 | + // height: 30px; | ||
| 158 | 221 | ||
| 159 | - &__title { | ||
| 160 | - font-size: 16px; | ||
| 161 | - color: #fff; | ||
| 162 | - } | 222 | + // &__title { |
| 223 | + // font-size: 16px; | ||
| 224 | + // color: #fff; | ||
| 225 | + // } | ||
| 163 | 226 | ||
| 164 | - img { | ||
| 165 | - width: 32px; | ||
| 166 | - } | ||
| 167 | - } | 227 | + // img { |
| 228 | + // width: 32px; | ||
| 229 | + // } | ||
| 230 | + // } | ||
| 168 | 231 | ||
| 169 | - .container { | ||
| 170 | - .@{logo-prefix-cls} { | ||
| 171 | - display: flex; | ||
| 172 | - width: 60%; | ||
| 173 | - height: 80px; | 232 | + // .container { |
| 233 | + // .@{logo-prefix-cls} { | ||
| 234 | + // display: flex; | ||
| 235 | + // width: 60%; | ||
| 236 | + // height: 80px; | ||
| 174 | 237 | ||
| 175 | - &__title { | ||
| 176 | - font-size: 24px; | ||
| 177 | - color: #fff; | ||
| 178 | - } | 238 | + // &__title { |
| 239 | + // font-size: 24px; | ||
| 240 | + // color: #fff; | ||
| 241 | + // } | ||
| 179 | 242 | ||
| 180 | - img { | ||
| 181 | - width: 48px; | ||
| 182 | - } | ||
| 183 | - } | ||
| 184 | - } | 243 | + // img { |
| 244 | + // width: 48px; | ||
| 245 | + // } | ||
| 246 | + // } | ||
| 247 | + // } | ||
| 185 | 248 | ||
| 186 | - &-sign-in-way { | ||
| 187 | - .anticon { | ||
| 188 | - font-size: 22px; | ||
| 189 | - color: #888; | ||
| 190 | - cursor: pointer; | 249 | + // &-sign-in-way { |
| 250 | + // .anticon { | ||
| 251 | + // font-size: 22px; | ||
| 252 | + // color: #888; | ||
| 253 | + // cursor: pointer; | ||
| 191 | 254 | ||
| 192 | - &:hover { | ||
| 193 | - color: @primary-color; | ||
| 194 | - } | ||
| 195 | - } | ||
| 196 | - } | 255 | + // &:hover { |
| 256 | + // color: @primary-color; | ||
| 257 | + // } | ||
| 258 | + // } | ||
| 259 | + // } | ||
| 197 | 260 | ||
| 198 | - input:not([type='checkbox']) { | ||
| 199 | - min-width: 360px; | 261 | + // input:not([type='checkbox']) { |
| 262 | + // min-width: 360px; | ||
| 200 | 263 | ||
| 201 | - @media (max-width: @screen-xl) { | ||
| 202 | - min-width: 320px; | ||
| 203 | - } | 264 | + // @media (max-width: @screen-xl) { |
| 265 | + // min-width: 320px; | ||
| 266 | + // } | ||
| 204 | 267 | ||
| 205 | - @media (max-width: @screen-lg) { | ||
| 206 | - min-width: 260px; | ||
| 207 | - } | 268 | + // @media (max-width: @screen-lg) { |
| 269 | + // min-width: 260px; | ||
| 270 | + // } | ||
| 208 | 271 | ||
| 209 | - @media (max-width: @screen-md) { | ||
| 210 | - min-width: 240px; | ||
| 211 | - } | 272 | + // @media (max-width: @screen-md) { |
| 273 | + // min-width: 240px; | ||
| 274 | + // } | ||
| 275 | + | ||
| 276 | + // @media (max-width: @screen-sm) { | ||
| 277 | + // min-width: 160px; | ||
| 278 | + // } | ||
| 279 | + // } | ||
| 212 | 280 | ||
| 213 | - @media (max-width: @screen-sm) { | ||
| 214 | - min-width: 160px; | 281 | + // .@{countdown-prefix-cls} input { |
| 282 | + // min-width: unset; | ||
| 283 | + // } | ||
| 284 | + | ||
| 285 | + // .ant-divider-inner-text { | ||
| 286 | + // font-size: 12px; | ||
| 287 | + // color: @text-color-secondary; | ||
| 288 | + // } | ||
| 289 | + // } | ||
| 290 | + | ||
| 291 | + .light1 { | ||
| 292 | + background-image: url('/src/assets/images/bg.png'); | ||
| 293 | + } | ||
| 294 | + .dark { | ||
| 295 | + background-image: url('/src/assets/images/bg-dark.png'); | ||
| 296 | + } | ||
| 297 | + .login-page { | ||
| 298 | + width: 100%; | ||
| 299 | + height: 100%; | ||
| 300 | + position: relative; | ||
| 301 | + .login-header { | ||
| 302 | + height: 60px; | ||
| 303 | + width: 100%; | ||
| 304 | + background-color: #1d3794; | ||
| 305 | + .vben-dark-switch { | ||
| 306 | + margin-left: 1840px; | ||
| 215 | } | 307 | } |
| 216 | } | 308 | } |
| 217 | 309 | ||
| 218 | - .@{countdown-prefix-cls} input { | ||
| 219 | - min-width: unset; | ||
| 220 | - } | 310 | + .login-container { |
| 311 | + position: relative; | ||
| 312 | + left: -6px; | ||
| 313 | + right: 20px; | ||
| 314 | + width: 101vw; | ||
| 315 | + height: calc(100% - 60px); | ||
| 316 | + background-size: 100% 100%; | ||
| 317 | + background-repeat: no-repeat; | ||
| 318 | + .vben-login-form { | ||
| 319 | + position: absolute; | ||
| 221 | 320 | ||
| 222 | - .ant-divider-inner-text { | ||
| 223 | - font-size: 12px; | ||
| 224 | - color: @text-color-secondary; | 321 | + width: 410px; |
| 322 | + right: 200px; | ||
| 323 | + top: 50%; | ||
| 324 | + margin-top: -180px; | ||
| 325 | + } | ||
| 326 | + .login-description { | ||
| 327 | + position: absolute; | ||
| 328 | + right: 13%; | ||
| 329 | + top: 15%; | ||
| 330 | + h1 { | ||
| 331 | + font-size: 26px; | ||
| 332 | + color: #5aeeed; | ||
| 333 | + text-align: center; | ||
| 334 | + } | ||
| 335 | + h2 { | ||
| 336 | + font-size: 20px; | ||
| 337 | + color: #5aeeed; | ||
| 338 | + } | ||
| 339 | + } | ||
| 225 | } | 340 | } |
| 226 | } | 341 | } |
| 227 | </style> | 342 | </style> |
| @@ -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, //加载数据 |
| @@ -95,6 +95,7 @@ | @@ -95,6 +95,7 @@ | ||
| 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'; | ||
| 98 | import { createLocalStorage } from '/@/utils/cache/index'; | 99 | import { createLocalStorage } from '/@/utils/cache/index'; |
| 99 | export default defineComponent({ | 100 | export default defineComponent({ |
| 100 | components: { | 101 | components: { |
| @@ -112,6 +113,8 @@ | @@ -112,6 +113,8 @@ | ||
| 112 | tip: '拼命加载中...', | 113 | tip: '拼命加载中...', |
| 113 | }); | 114 | }); |
| 114 | const { createMessage } = useMessage(); | 115 | const { createMessage } = useMessage(); |
| 116 | + const userStore = useUserStore(); | ||
| 117 | + const storage = createLocalStorage(); | ||
| 115 | const [registerForm, { getFieldsValue, setFieldsValue }] = useForm({ | 118 | const [registerForm, { getFieldsValue, setFieldsValue }] = useForm({ |
| 116 | schemas, | 119 | schemas, |
| 117 | showSubmitButton: false, | 120 | showSubmitButton: false, |
| @@ -197,22 +200,28 @@ | @@ -197,22 +200,28 @@ | ||
| 197 | try { | 200 | try { |
| 198 | const fieldValue = getFieldsValue(); | 201 | const fieldValue = getFieldsValue(); |
| 199 | compState.value.loading = true; | 202 | compState.value.loading = true; |
| 200 | - await updatePlatForm({ | 203 | + const newFieldValue = { |
| 201 | ...fieldValue, | 204 | ...fieldValue, |
| 202 | logo: unref(logoPic), | 205 | logo: unref(logoPic), |
| 203 | icon: unref(iconPic), | 206 | icon: unref(iconPic), |
| 204 | background: unref(bgPic), | 207 | background: unref(bgPic), |
| 205 | - }); | 208 | + }; |
| 209 | + await updatePlatForm(newFieldValue); | ||
| 206 | compState.value.loading = false; | 210 | compState.value.loading = false; |
| 207 | createMessage.success('保存信息成功'); | 211 | createMessage.success('保存信息成功'); |
| 208 | 212 | ||
| 209 | - // 保存一份数据到本地缓存中. | ||
| 210 | - const storage = createLocalStorage(); | ||
| 211 | - storage.set('PlatformInfo', fieldValue); | 213 | + setPlatFormInfo(newFieldValue); |
| 212 | } catch (e) { | 214 | } catch (e) { |
| 213 | createMessage.error('保存信息失败'); | 215 | createMessage.error('保存信息失败'); |
| 214 | } | 216 | } |
| 215 | }; | 217 | }; |
| 218 | + // 设置平台信息 | ||
| 219 | + function setPlatFormInfo(newFieldValue) { | ||
| 220 | + // 保存store | ||
| 221 | + userStore.setPlatInfo(newFieldValue); | ||
| 222 | + // 保存本地缓存 | ||
| 223 | + storage.set('platInfo', newFieldValue); | ||
| 224 | + } | ||
| 216 | 225 | ||
| 217 | onMounted(async () => { | 226 | onMounted(async () => { |
| 218 | 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,18 +40,25 @@ | @@ -14,18 +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'; |
| 23 | import { getTownChild } from '/@/api/oem/index'; | 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'; | ||
| 24 | export default defineComponent({ | 55 | export default defineComponent({ |
| 25 | components: { | 56 | components: { |
| 26 | Card, | 57 | Card, |
| 27 | BasicForm, | 58 | BasicForm, |
| 28 | Loading, | 59 | Loading, |
| 60 | + Upload, | ||
| 61 | + PlusOutlined, | ||
| 29 | }, | 62 | }, |
| 30 | setup() { | 63 | setup() { |
| 31 | const compState = ref({ | 64 | const compState = ref({ |
| @@ -43,25 +76,71 @@ | @@ -43,25 +76,71 @@ | ||
| 43 | }, | 76 | }, |
| 44 | }); | 77 | }); |
| 45 | 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 | + // 更新 | ||
| 46 | const handleUpdateInfo = async () => { | 103 | const handleUpdateInfo = async () => { |
| 47 | try { | 104 | try { |
| 48 | compState.value.loading = true; | 105 | compState.value.loading = true; |
| 49 | const fieldsValue = getFieldsValue(); | 106 | const fieldsValue = getFieldsValue(); |
| 50 | - await updateEnterPriseDetail({ | 107 | + const newFieldValue = { |
| 51 | ...fieldsValue, | 108 | ...fieldsValue, |
| 52 | codeProv: fieldsValue.nameProv, | 109 | codeProv: fieldsValue.nameProv, |
| 53 | codeCity: fieldsValue.nameCity, | 110 | codeCity: fieldsValue.nameCity, |
| 54 | codeCoun: fieldsValue.nameCoun, | 111 | codeCoun: fieldsValue.nameCoun, |
| 55 | codeTown: fieldsValue.nameTown, | 112 | codeTown: fieldsValue.nameTown, |
| 56 | - }); | 113 | + qrCode: qrcodePic.value, |
| 114 | + }; | ||
| 115 | + console.log(fieldsValue); | ||
| 116 | + console.log(newFieldValue); | ||
| 117 | + await updateEnterPriseDetail(newFieldValue); | ||
| 57 | compState.value.loading = false; | 118 | compState.value.loading = false; |
| 58 | createMessage.success('更新信息成功'); | 119 | createMessage.success('更新信息成功'); |
| 120 | + setEnterPriseInfo(newFieldValue); | ||
| 59 | } catch (e) { | 121 | } catch (e) { |
| 60 | createMessage.error('更新信息失败'); | 122 | createMessage.error('更新信息失败'); |
| 61 | } | 123 | } |
| 62 | }; | 124 | }; |
| 63 | 125 | ||
| 64 | - async function updateCityData(codeProv: string, codeCity: string, codeCoun: string) { | 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 | + ) { | ||
| 65 | const nameCity = await getTownChild('codeProv', codeProv); | 144 | const nameCity = await getTownChild('codeProv', codeProv); |
| 66 | const nameCoun = await getTownChild('codeCity', codeCity); | 145 | const nameCoun = await getTownChild('codeCity', codeCity); |
| 67 | const nameTown = await getTownChild('codeCoun', codeCoun); | 146 | const nameTown = await getTownChild('codeCoun', codeCoun); |
| @@ -77,6 +156,12 @@ | @@ -77,6 +156,12 @@ | ||
| 77 | item.label = item.nameTown; | 156 | item.label = item.nameTown; |
| 78 | item.value = item.codeTown; | 157 | item.value = item.codeTown; |
| 79 | }); | 158 | }); |
| 159 | + setFieldsValue({ | ||
| 160 | + nameProv: codeProv, | ||
| 161 | + nameCity: codeCity, | ||
| 162 | + nameCoun: codeCoun, | ||
| 163 | + nameTown: codeTown, | ||
| 164 | + }); | ||
| 80 | updateSchema({ | 165 | updateSchema({ |
| 81 | field: 'nameTown', | 166 | field: 'nameTown', |
| 82 | componentProps: { | 167 | componentProps: { |
| @@ -100,7 +185,6 @@ | @@ -100,7 +185,6 @@ | ||
| 100 | }); | 185 | }); |
| 101 | } | 186 | } |
| 102 | let nameTown = await getTownChild('codeCoun', value); | 187 | let nameTown = await getTownChild('codeCoun', value); |
| 103 | - console.log(111); | ||
| 104 | nameTown.forEach((item) => { | 188 | nameTown.forEach((item) => { |
| 105 | item.label = item.nameTown; | 189 | item.label = item.nameTown; |
| 106 | item.value = item.codeTown; | 190 | item.value = item.codeTown; |
| @@ -177,14 +261,19 @@ | @@ -177,14 +261,19 @@ | ||
| 177 | 261 | ||
| 178 | onMounted(async () => { | 262 | onMounted(async () => { |
| 179 | const res = await getEnterPriseDetail(); | 263 | const res = await getEnterPriseDetail(); |
| 180 | - updateCityData(res.codeProv, res.codeCity, res.codeCoun); | 264 | + updateCityData(res.codeProv, res.codeCity, res.codeCoun, res.codeTown); |
| 181 | setFieldsValue(res); | 265 | setFieldsValue(res); |
| 266 | + qrcodePic.value = res.qrCode; | ||
| 267 | + console.log(res); | ||
| 182 | }); | 268 | }); |
| 183 | 269 | ||
| 184 | return { | 270 | return { |
| 185 | registerForm, | 271 | registerForm, |
| 186 | compState, | 272 | compState, |
| 273 | + qrcodePic, | ||
| 187 | handleUpdateInfo, | 274 | handleUpdateInfo, |
| 275 | + customUploadqrcodePic, | ||
| 276 | + beforeUploadqrcodePic, | ||
| 188 | }; | 277 | }; |
| 189 | }, | 278 | }, |
| 190 | }); | 279 | }); |
| @@ -190,7 +190,7 @@ export const schemas: FormSchema[] = [ | @@ -190,7 +190,7 @@ export const schemas: FormSchema[] = [ | ||
| 190 | colProps: { | 190 | colProps: { |
| 191 | span: 5, | 191 | span: 5, |
| 192 | style: { | 192 | style: { |
| 193 | - marginLeft: '-80px', | 193 | + marginLeft: '-5rem', |
| 194 | }, | 194 | }, |
| 195 | }, | 195 | }, |
| 196 | }, | 196 | }, |
| @@ -256,4 +256,13 @@ export const schemas: FormSchema[] = [ | @@ -256,4 +256,13 @@ export const schemas: FormSchema[] = [ | ||
| 256 | placeholder: '请输入联系电话', | 256 | placeholder: '请输入联系电话', |
| 257 | }, | 257 | }, |
| 258 | }, | 258 | }, |
| 259 | + { | ||
| 260 | + field: 'qrcode', | ||
| 261 | + label: '二维码', | ||
| 262 | + component: 'Input', | ||
| 263 | + colProps: { | ||
| 264 | + span: 24, | ||
| 265 | + }, | ||
| 266 | + slot: 'qrcode', | ||
| 267 | + }, | ||
| 259 | ]; | 268 | ]; |