Commit 0306c83ee059059433ee5bb1e621688fccaa3092

Authored by sqy
1 parent 0e686625

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

... ... @@ -5,4 +5,4 @@ VITE_PORT = 8083
5 5 VITE_GLOB_APP_TITLE = Yunteng IOT
6 6
7 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 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 32 },
33 33 {
34 34 errorMessageMode: mode,
35   - joinPrefix: false,
36 35 }
37 36 );
38 37 }
... ...
... ... @@ -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>
... ...
... ... @@ -132,10 +132,6 @@ export const formSchema: FormSchema[] = [
132 132 field: 'id',
133 133 label: '',
134 134 component: 'Input',
135   - componentProps: {
136   - style: {
137   - display: 'none',
138   - },
139   - },
  135 + show: false,
140 136 },
141 137 ];
... ...
... ... @@ -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>
... ...
1 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 5 {{ getFormTitle }}
4 6 </h2>
5 7 </template>
... ...
... ... @@ -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 });
... ...
... ... @@ -256,4 +256,13 @@ export const schemas: FormSchema[] = [
256 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 ];
... ...