Showing
20 changed files
with
473 additions
and
169 deletions
src/api/alarm/position/index.ts
0 → 100644
src/assets/images/bg-dark.png
0 → 100644
141 KB
src/assets/images/bg.png
0 → 100644
571 KB
... | ... | @@ -6,9 +6,14 @@ |
6 | 6 | <template> |
7 | 7 | <div class="anticon" :class="getAppLogoClass" @click="goHome"> |
8 | 8 | <img :src="getLogo" /> |
9 | - <div class="ml-2 md:opacity-100" :class="getTitleClass" v-show="showTitle"> | |
9 | + <span | |
10 | + class="ml-2 md:opacity-100" | |
11 | + :class="getTitleClass" | |
12 | + v-show="showTitle" | |
13 | + style="white-space: nowrap" | |
14 | + > | |
10 | 15 | {{ getTitle }} |
11 | - </div> | |
16 | + </span> | |
12 | 17 | </div> |
13 | 18 | </template> |
14 | 19 | <script lang="ts" setup> |
... | ... | @@ -56,15 +61,21 @@ |
56 | 61 | go(userStore.getUserInfo.homePath || PageEnum.BASE_HOME); |
57 | 62 | } |
58 | 63 | const getLogo = computed(() => { |
59 | - return userStore.platInfo.logo ?? '/src/assets/images/logo.png'; | |
64 | + return userStore.platInfo?.logo ?? '/src/assets/images/logo.png'; | |
60 | 65 | }); |
61 | 66 | const getTitle = computed(() => { |
62 | - return userStore.platInfo.name ?? title; | |
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; | |
63 | 75 | }); |
64 | 76 | </script> |
65 | 77 | <style lang="less" scoped> |
66 | 78 | @prefix-cls: ~'@{namespace}-app-logo'; |
67 | - | |
68 | 79 | .@{prefix-cls} { |
69 | 80 | display: flex; |
70 | 81 | align-items: center; | ... | ... |
... | ... | @@ -28,6 +28,7 @@ import { PAGE_NOT_FOUND_ROUTE } from '/@/router/routes/basic'; |
28 | 28 | import { createLocalStorage } from '/@/utils/cache/index'; |
29 | 29 | interface UserState { |
30 | 30 | platInfo: any; |
31 | + enterPriseInfo: any; | |
31 | 32 | userInfo: Nullable<UserInfo>; |
32 | 33 | token?: string; |
33 | 34 | roleList: RoleEnum[]; |
... | ... | @@ -37,11 +38,13 @@ interface UserState { |
37 | 38 | refreshToken?: string; |
38 | 39 | } |
39 | 40 | |
41 | +const storage = createLocalStorage(); | |
40 | 42 | export const useUserStore = defineStore({ |
41 | 43 | id: 'app-user', |
42 | 44 | state: (): UserState => ({ |
43 | 45 | //平台信息 |
44 | - platInfo: createLocalStorage().get('platformInfo') || null, | |
46 | + platInfo: storage.get('platInfo') || null, | |
47 | + enterPriseInfo: storage.get('enterPriseInfo') || null, | |
45 | 48 | // user info |
46 | 49 | userInfo: null, |
47 | 50 | // token |
... | ... | @@ -58,7 +61,7 @@ export const useUserStore = defineStore({ |
58 | 61 | |
59 | 62 | getters: { |
60 | 63 | getPlatInfo(): any { |
61 | - return this.platInfo || getAuthCache('platInfo'); | |
64 | + return this.platInfo; | |
62 | 65 | }, |
63 | 66 | getUserInfo(): UserInfo { |
64 | 67 | return this.userInfo || getAuthCache<UserInfo>(USER_INFO_KEY) || {}; |
... | ... | @@ -83,6 +86,9 @@ export const useUserStore = defineStore({ |
83 | 86 | setPlatInfo(platInfo: any) { |
84 | 87 | this.platInfo = platInfo; |
85 | 88 | }, |
89 | + setEnterPriseInfo(enterPriseInfo: any) { | |
90 | + this.enterPriseInfo = enterPriseInfo; | |
91 | + }, | |
86 | 92 | storeToken(jwtToken: string, refreshToken: string) { |
87 | 93 | this.jwtToken = jwtToken; |
88 | 94 | this.refreshToken = refreshToken; | ... | ... |
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 | 6 | export const formSchema: FormSchema[] = [ |
5 | 7 | { |
6 | - field: 'organization', | |
8 | + field: 'organizationId', | |
7 | 9 | label: '', |
8 | - component: 'TreeSelect', | |
10 | + component: 'ApiTreeSelect', | |
9 | 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 | 21 | label: '', |
16 | - component: 'Select', | |
22 | + component: 'ApiSelect', | |
17 | 23 | componentProps: { |
24 | + api: getDeviceProfile, | |
18 | 25 | placeholder: '请选择设备配置', |
26 | + labelField: 'name', | |
27 | + valueField: 'id', | |
19 | 28 | }, |
20 | 29 | }, |
21 | 30 | { |
22 | - field: 'device', | |
31 | + field: 'name', | |
23 | 32 | label: '', |
24 | 33 | component: 'Input', |
25 | 34 | componentProps: { |
... | ... | @@ -27,19 +36,28 @@ export const formSchema: FormSchema[] = [ |
27 | 36 | }, |
28 | 37 | }, |
29 | 38 | { |
30 | - field: 'status', | |
39 | + field: 'deviceState', | |
31 | 40 | label: '', |
32 | 41 | component: 'RadioGroup', |
33 | 42 | componentProps: { |
34 | 43 | size: 'small', |
35 | 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 | 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 | 63 | export const columns: BasicColumn[] = [ |
... | ... | @@ -57,5 +75,6 @@ export const columns: BasicColumn[] = [ |
57 | 75 | title: '状态', |
58 | 76 | dataIndex: 'deviceState', |
59 | 77 | width: 100, |
78 | + slots: { customRender: 'deviceState' }, | |
60 | 79 | }, |
61 | 80 | ]; | ... | ... |
... | ... | @@ -2,7 +2,28 @@ |
2 | 2 | <div class="wrapper"> |
3 | 3 | <div ref="wrapRef" :style="{ height, width }"> </div> |
4 | 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 | 27 | </div> |
7 | 28 | </div> |
8 | 29 | </template> |
... | ... | @@ -12,11 +33,13 @@ |
12 | 33 | import { formSchema, columns } from './config.data'; |
13 | 34 | import { BasicTable, useTable } from '/@/components/Table'; |
14 | 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 | 38 | export default defineComponent({ |
17 | 39 | name: 'BaiduMap', |
18 | 40 | components: { |
19 | 41 | BasicTable, |
42 | + Tag, | |
20 | 43 | }, |
21 | 44 | props: { |
22 | 45 | width: { |
... | ... | @@ -55,8 +78,6 @@ |
55 | 78 | formConfig: { |
56 | 79 | labelWidth: 120, |
57 | 80 | schemas: formSchema, |
58 | - showAdvancedButton: false, | |
59 | - showActionButtonGroup: false, | |
60 | 81 | }, |
61 | 82 | showIndexColumn: false, |
62 | 83 | useSearchForm: true, |
... | ... | @@ -68,6 +89,7 @@ |
68 | 89 | wrapRef, |
69 | 90 | registerTable, |
70 | 91 | handleSuccess, |
92 | + DeviceState, | |
71 | 93 | }; |
72 | 94 | }, |
73 | 95 | }); |
... | ... | @@ -83,12 +105,10 @@ |
83 | 105 | .right-wrap { |
84 | 106 | padding-top: 10px; |
85 | 107 | width: 22%; |
86 | - height: 80%; | |
108 | + height: 95%; | |
87 | 109 | position: absolute; |
88 | 110 | right: 5%; |
89 | - top: 10%; | |
90 | - } | |
91 | - .scroll-wrap { | |
92 | - height: 450px; | |
111 | + top: 3%; | |
112 | + background-color: #fff; | |
93 | 113 | } |
94 | 114 | </style> | ... | ... |
... | ... | @@ -34,13 +34,13 @@ |
34 | 34 | </Card> |
35 | 35 | <Card hoverable title="联系我们" :bordered="false"> |
36 | 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 | 38 | </template> |
39 | 39 | <CardMeta> |
40 | 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 | 44 | </template> |
45 | 45 | </CardMeta> |
46 | 46 | </Card> |
... | ... | @@ -48,9 +48,10 @@ |
48 | 48 | </template> |
49 | 49 | |
50 | 50 | <script lang="ts"> |
51 | - import { defineComponent, ref } from 'vue'; | |
51 | + import { defineComponent, ref, computed, onMounted } from 'vue'; | |
52 | 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 | 55 | export default defineComponent({ |
55 | 56 | components: { |
56 | 57 | Card, |
... | ... | @@ -60,9 +61,12 @@ |
60 | 61 | ListItemMeta, |
61 | 62 | Avatar, |
62 | 63 | CardMeta, |
63 | - QrCode, | |
64 | 64 | }, |
65 | 65 | setup() { |
66 | + onMounted(async () => { | |
67 | + const res = await getEnterPriseDetail(); | |
68 | + userStore.setEnterPriseInfo(res); | |
69 | + }); | |
66 | 70 | const helpDoc = ref([ |
67 | 71 | { |
68 | 72 | title: '如何接入设备?', |
... | ... | @@ -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 | 158 | return { |
143 | 159 | activeKey, |
... | ... | @@ -145,7 +161,10 @@ |
145 | 161 | onTabChange, |
146 | 162 | data, |
147 | 163 | helpDoc, |
148 | - qrCodeUrl, | |
164 | + getQrCode, | |
165 | + getContacts, | |
166 | + getAddress, | |
167 | + getTel, | |
149 | 168 | }; |
150 | 169 | }, |
151 | 170 | }); | ... | ... |
... | ... | @@ -51,7 +51,7 @@ |
51 | 51 | props: { |
52 | 52 | userData: { type: Object }, |
53 | 53 | }, |
54 | - emits: ['reload'], | |
54 | + emits: ['reload', 'register'], | |
55 | 55 | setup(_, { emit }) { |
56 | 56 | const DeviceStep1Ref = ref<InstanceType<typeof DeviceStep1>>(); |
57 | 57 | const DeviceStep2Ref = ref<InstanceType<typeof DeviceStep2>>(); | ... | ... |
1 | 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 | 3 | <AppLocalePicker |
4 | 4 | class="absolute text-white top-4 right-4 enter-x xl:text-gray-600" |
5 | 5 | :showText="false" |
... | ... | @@ -9,14 +9,14 @@ |
9 | 9 | |
10 | 10 | <span class="-enter-x xl:hidden"> |
11 | 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 | 15 | <div class="flex h-full"> |
16 | 16 | <div class="hidden min-h-full pl-4 mr-4 xl:flex xl:flex-col xl:w-6/12"> |
17 | 17 | <AppLogo class="-enter-x" /> |
18 | 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 | 20 | <div class="mt-10 font-medium text-white -enter-x"> |
21 | 21 | <span class="inline-block mt-4 text-3xl"> {{ t('sys.login.signInTitle') }}</span> |
22 | 22 | </div> |
... | ... | @@ -54,11 +54,65 @@ |
54 | 54 | </div> |
55 | 55 | </div> |
56 | 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 | 111 | </div> |
58 | 112 | </div> |
59 | 113 | </template> |
60 | 114 | <script lang="ts" setup> |
61 | - import { computed } from 'vue'; | |
115 | + import { computed, ref } from 'vue'; | |
62 | 116 | import { AppLogo } from '/@/components/Application'; |
63 | 117 | import { AppLocalePicker, AppDarkModeToggle } from '/@/components/Application'; |
64 | 118 | import LoginForm from './LoginForm.vue'; |
... | ... | @@ -70,6 +124,7 @@ |
70 | 124 | import { useI18n } from '/@/hooks/web/useI18n'; |
71 | 125 | import { useDesign } from '/@/hooks/web/useDesign'; |
72 | 126 | import { useLocaleStore } from '/@/store/modules/locale'; |
127 | + import { useUserStore } from '/@/store/modules/user'; | |
73 | 128 | |
74 | 129 | defineProps({ |
75 | 130 | sessionTimeout: { |
... | ... | @@ -83,6 +138,14 @@ |
83 | 138 | const localeStore = useLocaleStore(); |
84 | 139 | const showLocale = localeStore.getShowPicker; |
85 | 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 | 149 | </script> |
87 | 150 | <style lang="less"> |
88 | 151 | @prefix-cls: ~'@{namespace}-login'; |
... | ... | @@ -90,138 +153,190 @@ |
90 | 153 | @countdown-prefix-cls: ~'@{namespace}-countdown-input'; |
91 | 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 | 342 | </style> | ... | ... |
... | ... | @@ -4,7 +4,7 @@ |
4 | 4 | <div class="enter-x min-w-64 min-h-64"> |
5 | 5 | <QrCode |
6 | 6 | :value="qrCodeUrl" |
7 | - class="enter-x flex justify-center xl:justify-start" | |
7 | + class="enter-x flex justify-center xl:justify-center" | |
8 | 8 | :width="280" |
9 | 9 | /> |
10 | 10 | <Divider class="enter-x">{{ t('sys.login.scanSign') }}</Divider> | ... | ... |
... | ... | @@ -52,7 +52,7 @@ |
52 | 52 | import MenuDrawer from './MenuDrawer.vue'; |
53 | 53 | |
54 | 54 | // 导入列 属性,和搜索栏内容 |
55 | - import { columns, searchFormSchema } from './menu.data'; | |
55 | + import { columns } from './menu.data'; | |
56 | 56 | import { useI18n } from '/@/hooks/web/useI18n'; |
57 | 57 | import { notification } from 'ant-design-vue'; |
58 | 58 | |
... | ... | @@ -65,7 +65,6 @@ |
65 | 65 | const { t } = useI18n(); //加载国际化 |
66 | 66 | // 新增菜单 |
67 | 67 | const getI18nCreateMenu = computed(() => t('routes.common.system.pageSystemTitleCreateMenu')); |
68 | - console.log(111); | |
69 | 68 | const [registerTable, { reload, expandAll }] = useTable({ |
70 | 69 | title: t('routes.common.system.pageSystemTitleMenuList'), //'菜单列表' |
71 | 70 | api: getMenuList, //加载数据 | ... | ... |
... | ... | @@ -96,6 +96,7 @@ |
96 | 96 | import { logoUpload, iconUpload, bgUpload, getPlatForm, updatePlatForm } from '/@/api/oem/index'; |
97 | 97 | import { PlusOutlined } from '@ant-design/icons-vue'; |
98 | 98 | import { useUserStore } from '/@/store/modules/user'; |
99 | + import { createLocalStorage } from '/@/utils/cache/index'; | |
99 | 100 | export default defineComponent({ |
100 | 101 | components: { |
101 | 102 | BasicForm, |
... | ... | @@ -113,6 +114,7 @@ |
113 | 114 | }); |
114 | 115 | const { createMessage } = useMessage(); |
115 | 116 | const userStore = useUserStore(); |
117 | + const storage = createLocalStorage(); | |
116 | 118 | const [registerForm, { getFieldsValue, setFieldsValue }] = useForm({ |
117 | 119 | schemas, |
118 | 120 | showSubmitButton: false, |
... | ... | @@ -208,12 +210,18 @@ |
208 | 210 | compState.value.loading = false; |
209 | 211 | createMessage.success('保存信息成功'); |
210 | 212 | |
211 | - userStore.platInfo = newFieldValue; | |
212 | - // console.log() | |
213 | + setPlatFormInfo(newFieldValue); | |
213 | 214 | } catch (e) { |
214 | 215 | createMessage.error('保存信息失败'); |
215 | 216 | } |
216 | 217 | }; |
218 | + // 设置平台信息 | |
219 | + function setPlatFormInfo(newFieldValue) { | |
220 | + // 保存store | |
221 | + userStore.setPlatInfo(newFieldValue); | |
222 | + // 保存本地缓存 | |
223 | + storage.set('platInfo', newFieldValue); | |
224 | + } | |
217 | 225 | |
218 | 226 | onMounted(async () => { |
219 | 227 | const res = await getPlatForm(); | ... | ... |
1 | 1 | <template> |
2 | 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 | 30 | <Loading v-bind="compState" /> |
5 | 31 | <a-button |
6 | 32 | @click="handleUpdateInfo" |
... | ... | @@ -14,18 +40,25 @@ |
14 | 40 | |
15 | 41 | <script lang="ts"> |
16 | 42 | import { defineComponent, onMounted, ref } from 'vue'; |
17 | - import { Card } from 'ant-design-vue'; | |
43 | + import { Card, Upload } from 'ant-design-vue'; | |
18 | 44 | import { BasicForm, useForm } from '/@/components/Form/index'; |
19 | 45 | import { schemas } from '../config/enterPriseInfo.config'; |
20 | 46 | import { getEnterPriseDetail, updateEnterPriseDetail } from '/@/api/oem/index'; |
21 | 47 | import { Loading } from '/@/components/Loading'; |
22 | 48 | import { useMessage } from '/@/hooks/web/useMessage'; |
23 | 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 | 55 | export default defineComponent({ |
25 | 56 | components: { |
26 | 57 | Card, |
27 | 58 | BasicForm, |
28 | 59 | Loading, |
60 | + Upload, | |
61 | + PlusOutlined, | |
29 | 62 | }, |
30 | 63 | setup() { |
31 | 64 | const compState = ref({ |
... | ... | @@ -43,26 +76,71 @@ |
43 | 76 | }, |
44 | 77 | }); |
45 | 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 | 103 | const handleUpdateInfo = async () => { |
47 | 104 | try { |
48 | 105 | compState.value.loading = true; |
49 | 106 | const fieldsValue = getFieldsValue(); |
50 | - await updateEnterPriseDetail({ | |
107 | + const newFieldValue = { | |
51 | 108 | ...fieldsValue, |
52 | 109 | codeProv: fieldsValue.nameProv, |
53 | 110 | codeCity: fieldsValue.nameCity, |
54 | 111 | codeCoun: fieldsValue.nameCoun, |
55 | 112 | codeTown: fieldsValue.nameTown, |
56 | - }); | |
113 | + qrCode: qrcodePic.value, | |
114 | + }; | |
115 | + console.log(fieldsValue); | |
116 | + console.log(newFieldValue); | |
117 | + await updateEnterPriseDetail(newFieldValue); | |
57 | 118 | compState.value.loading = false; |
58 | 119 | createMessage.success('更新信息成功'); |
120 | + setEnterPriseInfo(newFieldValue); | |
59 | 121 | } catch (e) { |
60 | 122 | createMessage.error('更新信息失败'); |
61 | 123 | } |
62 | 124 | }; |
63 | 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 | + | |
64 | 137 | // 地区显示回显和数据联动 |
65 | - async function updateCityData(codeProv: string, codeCity: string, codeCoun: string) { | |
138 | + async function updateCityData( | |
139 | + codeProv: string, | |
140 | + codeCity: string, | |
141 | + codeCoun: string, | |
142 | + codeTown: string | |
143 | + ) { | |
66 | 144 | const nameCity = await getTownChild('codeProv', codeProv); |
67 | 145 | const nameCoun = await getTownChild('codeCity', codeCity); |
68 | 146 | const nameTown = await getTownChild('codeCoun', codeCoun); |
... | ... | @@ -78,6 +156,12 @@ |
78 | 156 | item.label = item.nameTown; |
79 | 157 | item.value = item.codeTown; |
80 | 158 | }); |
159 | + setFieldsValue({ | |
160 | + nameProv: codeProv, | |
161 | + nameCity: codeCity, | |
162 | + nameCoun: codeCoun, | |
163 | + nameTown: codeTown, | |
164 | + }); | |
81 | 165 | updateSchema({ |
82 | 166 | field: 'nameTown', |
83 | 167 | componentProps: { |
... | ... | @@ -177,14 +261,19 @@ |
177 | 261 | |
178 | 262 | onMounted(async () => { |
179 | 263 | const res = await getEnterPriseDetail(); |
180 | - updateCityData(res.codeProv, res.codeCity, res.codeCoun); | |
264 | + updateCityData(res.codeProv, res.codeCity, res.codeCoun, res.codeTown); | |
181 | 265 | setFieldsValue(res); |
266 | + qrcodePic.value = res.qrCode; | |
267 | + console.log(res); | |
182 | 268 | }); |
183 | 269 | |
184 | 270 | return { |
185 | 271 | registerForm, |
186 | 272 | compState, |
273 | + qrcodePic, | |
187 | 274 | handleUpdateInfo, |
275 | + customUploadqrcodePic, | |
276 | + beforeUploadqrcodePic, | |
188 | 277 | }; |
189 | 278 | }, |
190 | 279 | }); | ... | ... |