Commit 0306c83ee059059433ee5bb1e621688fccaa3092

Authored by sqy
1 parent 0e686625

'oem,首页,登录页逻辑界面修改'

@@ -5,4 +5,4 @@ VITE_PORT = 8083 @@ -5,4 +5,4 @@ VITE_PORT = 8083
5 VITE_GLOB_APP_TITLE = Yunteng IOT 5 VITE_GLOB_APP_TITLE = Yunteng IOT
6 6
7 # spa shortname 7 # spa shortname
8 -VITE_GLOB_APP_SHORT_NAME = Yunteng IOT 8 +# VITE_GLOB_APP_SHORT_NAME = Yunteng IOT
  1 +import { defHttp } from '/@/utils/http/axios';
  2 +
  3 +export const getDeviceProfile = () => {
  4 + return defHttp.get({
  5 + url: '/deviceProfile/me',
  6 + });
  7 +};
@@ -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 +};
@@ -32,7 +32,6 @@ export function loginApi(params: LoginParams, mode: ErrorMessageMode = 'modal') @@ -32,7 +32,6 @@ export function loginApi(params: LoginParams, mode: ErrorMessageMode = 'modal')
32 }, 32 },
33 { 33 {
34 errorMessageMode: mode, 34 errorMessageMode: mode,
35 - joinPrefix: false,  
36 } 35 }
37 ); 36 );
38 } 37 }
@@ -6,9 +6,14 @@ @@ -6,9 +6,14 @@
6 <template> 6 <template>
7 <div class="anticon" :class="getAppLogoClass" @click="goHome"> 7 <div class="anticon" :class="getAppLogoClass" @click="goHome">
8 <img :src="getLogo" /> 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 {{ getTitle }} 15 {{ getTitle }}
11 - </div> 16 + </span>
12 </div> 17 </div>
13 </template> 18 </template>
14 <script lang="ts" setup> 19 <script lang="ts" setup>
@@ -56,15 +61,21 @@ @@ -56,15 +61,21 @@
56 go(userStore.getUserInfo.homePath || PageEnum.BASE_HOME); 61 go(userStore.getUserInfo.homePath || PageEnum.BASE_HOME);
57 } 62 }
58 const getLogo = computed(() => { 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 const getTitle = computed(() => { 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 </script> 76 </script>
65 <style lang="less" scoped> 77 <style lang="less" scoped>
66 @prefix-cls: ~'@{namespace}-app-logo'; 78 @prefix-cls: ~'@{namespace}-app-logo';
67 -  
68 .@{prefix-cls} { 79 .@{prefix-cls} {
69 display: flex; 80 display: flex;
70 align-items: center; 81 align-items: center;
@@ -28,6 +28,7 @@ import { PAGE_NOT_FOUND_ROUTE } from '/@/router/routes/basic'; @@ -28,6 +28,7 @@ import { PAGE_NOT_FOUND_ROUTE } from '/@/router/routes/basic';
28 import { createLocalStorage } from '/@/utils/cache/index'; 28 import { createLocalStorage } from '/@/utils/cache/index';
29 interface UserState { 29 interface UserState {
30 platInfo: any; 30 platInfo: any;
  31 + enterPriseInfo: any;
31 userInfo: Nullable<UserInfo>; 32 userInfo: Nullable<UserInfo>;
32 token?: string; 33 token?: string;
33 roleList: RoleEnum[]; 34 roleList: RoleEnum[];
@@ -37,11 +38,13 @@ interface UserState { @@ -37,11 +38,13 @@ interface UserState {
37 refreshToken?: string; 38 refreshToken?: string;
38 } 39 }
39 40
  41 +const storage = createLocalStorage();
40 export const useUserStore = defineStore({ 42 export const useUserStore = defineStore({
41 id: 'app-user', 43 id: 'app-user',
42 state: (): UserState => ({ 44 state: (): UserState => ({
43 //平台信息 45 //平台信息
44 - platInfo: createLocalStorage().get('platformInfo') || null, 46 + platInfo: storage.get('platInfo') || null,
  47 + enterPriseInfo: storage.get('enterPriseInfo') || null,
45 // user info 48 // user info
46 userInfo: null, 49 userInfo: null,
47 // token 50 // token
@@ -58,7 +61,7 @@ export const useUserStore = defineStore({ @@ -58,7 +61,7 @@ export const useUserStore = defineStore({
58 61
59 getters: { 62 getters: {
60 getPlatInfo(): any { 63 getPlatInfo(): any {
61 - return this.platInfo || getAuthCache('platInfo'); 64 + return this.platInfo;
62 }, 65 },
63 getUserInfo(): UserInfo { 66 getUserInfo(): UserInfo {
64 return this.userInfo || getAuthCache<UserInfo>(USER_INFO_KEY) || {}; 67 return this.userInfo || getAuthCache<UserInfo>(USER_INFO_KEY) || {};
@@ -83,6 +86,9 @@ export const useUserStore = defineStore({ @@ -83,6 +86,9 @@ export const useUserStore = defineStore({
83 setPlatInfo(platInfo: any) { 86 setPlatInfo(platInfo: any) {
84 this.platInfo = platInfo; 87 this.platInfo = platInfo;
85 }, 88 },
  89 + setEnterPriseInfo(enterPriseInfo: any) {
  90 + this.enterPriseInfo = enterPriseInfo;
  91 + },
86 storeToken(jwtToken: string, refreshToken: string) { 92 storeToken(jwtToken: string, refreshToken: string) {
87 this.jwtToken = jwtToken; 93 this.jwtToken = jwtToken;
88 this.refreshToken = refreshToken; 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 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>
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, //加载数据
@@ -96,6 +96,7 @@ @@ -96,6 +96,7 @@
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 { useUserStore } from '/@/store/modules/user';
  99 + import { createLocalStorage } from '/@/utils/cache/index';
99 export default defineComponent({ 100 export default defineComponent({
100 components: { 101 components: {
101 BasicForm, 102 BasicForm,
@@ -113,6 +114,7 @@ @@ -113,6 +114,7 @@
113 }); 114 });
114 const { createMessage } = useMessage(); 115 const { createMessage } = useMessage();
115 const userStore = useUserStore(); 116 const userStore = useUserStore();
  117 + const storage = createLocalStorage();
116 const [registerForm, { getFieldsValue, setFieldsValue }] = useForm({ 118 const [registerForm, { getFieldsValue, setFieldsValue }] = useForm({
117 schemas, 119 schemas,
118 showSubmitButton: false, 120 showSubmitButton: false,
@@ -208,12 +210,18 @@ @@ -208,12 +210,18 @@
208 compState.value.loading = false; 210 compState.value.loading = false;
209 createMessage.success('保存信息成功'); 211 createMessage.success('保存信息成功');
210 212
211 - userStore.platInfo = newFieldValue;  
212 - // console.log() 213 + setPlatFormInfo(newFieldValue);
213 } catch (e) { 214 } catch (e) {
214 createMessage.error('保存信息失败'); 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 onMounted(async () => { 226 onMounted(async () => {
219 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,26 +76,71 @@ @@ -43,26 +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
  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 const nameCity = await getTownChild('codeProv', codeProv); 144 const nameCity = await getTownChild('codeProv', codeProv);
67 const nameCoun = await getTownChild('codeCity', codeCity); 145 const nameCoun = await getTownChild('codeCity', codeCity);
68 const nameTown = await getTownChild('codeCoun', codeCoun); 146 const nameTown = await getTownChild('codeCoun', codeCoun);
@@ -78,6 +156,12 @@ @@ -78,6 +156,12 @@
78 item.label = item.nameTown; 156 item.label = item.nameTown;
79 item.value = item.codeTown; 157 item.value = item.codeTown;
80 }); 158 });
  159 + setFieldsValue({
  160 + nameProv: codeProv,
  161 + nameCity: codeCity,
  162 + nameCoun: codeCoun,
  163 + nameTown: codeTown,
  164 + });
81 updateSchema({ 165 updateSchema({
82 field: 'nameTown', 166 field: 'nameTown',
83 componentProps: { 167 componentProps: {
@@ -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 });
@@ -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 ];