Commit 82d39fed3e6d03b50bcc8a4ca56a98668bbc6f53

Authored by sqy
1 parent 99c1ff47

'style:集中调整样式,统一table的风格,还原login为官方页面'

Showing 40 changed files with 396 additions and 391 deletions
1 1 <template>
2   - <ConfigProvider :locale="getAntdLocale">
  2 + <ConfigProvider :locale="getAntdLocale" :autoInsertSpaceInButton="false">
3 3 <AppProvider>
4 4 <RouterView />
5 5 </AppProvider>
... ...
... ... @@ -42,6 +42,7 @@
42 42 useSearchForm: true,
43 43 bordered: true,
44 44 showIndexColumn: false,
  45 + showTableSetting: true,
45 46 actionColumn: {
46 47 width: 200,
47 48 title: '操作',
... ...
... ... @@ -8,7 +8,7 @@
8 8 />
9 9 <BasicTable @register="registerTable" :searchInfo="searchInfo" class="w-3/4 xl:w-4/5">
10 10 <template #toolbar>
11   - <a-button type="primary" @click="handleCreateOrEdit(null)"> 新增联系人 </a-button>
  11 + <a-button type="primary" @click="handleCreateOrEdit(null)"> 新增告警联系人 </a-button>
12 12 <a-button
13 13 type="primary"
14 14 color="error"
... ... @@ -91,7 +91,7 @@
91 91 },
92 92 rowKey: 'id',
93 93 actionColumn: {
94   - width: 180,
  94 + width: 200,
95 95 title: '操作',
96 96 dataIndex: 'action',
97 97 slots: { customRender: 'action' },
... ...
... ... @@ -13,7 +13,7 @@
13 13 }
14 14 const props = withDefaults(defineProps<Props>(), {
15 15 width: '100%',
16   - height: '300px',
  16 + height: '320px',
17 17 customerTrendList: () => [],
18 18 });
19 19 watch(
... ...
... ... @@ -17,32 +17,29 @@
17 17 <img src="/src/assets/images/tip.png" style="width: 1.125rem; height: 1.125rem" />
18 18 </div>
19 19 <div> 设备数(个) </div>
20   - <div class="mt-2" style="font-size: 0.75rem">
21   - <div class="flex" style="align-items: center"
22   - ><img
23   - src="/src/assets/images/online.png"
24   - class="mr-1"
25   - style="width: 0.625rem; height: 0.625rem"
26   - />
27   - <span>在线{{ growCardList?.deviceInfo?.onLine }}</span>
28   - <img
29   - src="/src/assets/images/offline.png"
30   - class="mr-1 ml-1"
31   - style="width: 0.625rem; height: 0.625rem"
32   - />
33   - <span> 离线{{ growCardList?.deviceInfo?.offLine }} </span>
34   - <img
35   - src="/src/assets/images/inactive.png"
36   - class="mr-1 ml-1"
37   - style="width: 0.625rem; height: 0.625rem"
38   - />
39   - <span> 未激活{{ growCardList?.deviceInfo?.inActive }} </span>
40   - </div>
41   - </div>
42 20 </div>
43 21 </div>
44 22 <div class="ml-2 pt-4" style="border-top: 2px solid #f0f2f5">
45   - 今日新增 {{ toThousands(growCardList?.deviceInfo?.todayAdd) }}</div
  23 + <div class="flex" style="align-items: center"
  24 + ><img
  25 + src="/src/assets/images/online.png"
  26 + class="mr-1"
  27 + style="width: 0.625rem; height: 0.625rem"
  28 + />
  29 + <span>在线 {{ growCardList?.deviceInfo?.onLine }}</span>
  30 + <img
  31 + src="/src/assets/images/offline.png"
  32 + class="mr-1 ml-1"
  33 + style="width: 0.625rem; height: 0.625rem"
  34 + />
  35 + <span> 离线 {{ growCardList?.deviceInfo?.offLine }} </span>
  36 + <img
  37 + src="/src/assets/images/inactive.png"
  38 + class="mr-1 ml-1"
  39 + style="width: 0.625rem; height: 0.625rem"
  40 + />
  41 + <span> 未激活 {{ growCardList?.deviceInfo?.inActive }} </span>
  42 + </div></div
46 43 >
47 44 </Card>
48 45 <Card size="small" class="md:w-1/3 w-full !md:mt-0 !mt-4 !md:mr-4" style="color: #666">
... ...
... ... @@ -100,9 +100,19 @@
100 100 >{{ index + 1 }}</span
101 101 >
102 102 <div class="flex justify-between" style="width: 100%">
103   - <span>
104   - {{ item.name }}
105   - </span>
  103 + <div
  104 + style="
  105 + width: 10rem;
  106 + white-space: nowrap;
  107 + text-overflow: ellipsis;
  108 + overflow: hidden;
  109 + word-break: break-all;
  110 + "
  111 + >
  112 + <Tooltip :title="item.name">
  113 + {{ item.name }}
  114 + </Tooltip>
  115 + </div>
106 116 <div class="flex w-7/10">
107 117 <Progress
108 118 :showInfo="false"
... ... @@ -142,7 +152,16 @@
142 152
143 153 <script lang="ts">
144 154 import { defineComponent, ref, computed, onMounted } from 'vue';
145   - import { Card, Anchor, List, Avatar, Descriptions, Progress, Skeleton } from 'ant-design-vue';
  155 + import {
  156 + Card,
  157 + Anchor,
  158 + List,
  159 + Avatar,
  160 + Descriptions,
  161 + Progress,
  162 + Skeleton,
  163 + Tooltip,
  164 + } from 'ant-design-vue';
146 165 import { useUserStore } from '/@/store/modules/user';
147 166 import { getEnterPriseDetail } from '/@/api/oem';
148 167 import { notifyMyGetrPageApi } from '/@/api/stationnotification/stationnotifyApi';
... ... @@ -166,6 +185,7 @@
166 185 BasicTable,
167 186 Progress,
168 187 Skeleton,
  188 + Tooltip,
169 189 },
170 190 props: {
171 191 role: {
... ...
... ... @@ -28,7 +28,12 @@
28 28 </div>
29 29 </Card>
30 30 <div v-if="isAdmin(role)">
31   - <Card v-bind="$attrs" title="租户趋势" style="height: 428px">
  31 + <Card
  32 + v-bind="$attrs"
  33 + title="租户趋势"
  34 + style="height: 26.75rem"
  35 + :bodyStyle="{ padding: '0 24px' }"
  36 + >
32 37 <template #extra>
33 38 <div class="extra-date">
34 39 <template v-for="(item, index) in TenantOrCustomerDateList" :key="item.value">
... ... @@ -47,7 +52,12 @@
47 52 </template>
48 53 <TenantTrend :tenantTrendList="tenantTrendList" />
49 54 </Card>
50   - <Card v-bind="$attrs" title="客户趋势" style="height: 428px">
  55 + <Card
  56 + v-bind="$attrs"
  57 + title="客户趋势"
  58 + style="height: 26.75rem"
  59 + :bodyStyle="{ padding: '0 24px' }"
  60 + >
51 61 <template #extra>
52 62 <div class="extra-date">
53 63 <template v-for="(item, index) in TenantOrCustomerDateList" :key="item.value">
... ...
... ... @@ -13,7 +13,7 @@
13 13 }
14 14 const props = withDefaults(defineProps<Props>(), {
15 15 width: '100%',
16   - height: '300px',
  16 + height: '320px',
17 17 tenantTrendList: () => [],
18 18 });
19 19
... ...
... ... @@ -45,12 +45,7 @@
45 45 schemas: alarmSearchSchemas,
46 46 },
47 47 showTableSetting: true,
48   - tableSetting: {
49   - redo: true,
50   - size: false,
51   - setting: false,
52   - fullScreen: false,
53   - },
  48 +
54 49 useSearchForm: true,
55 50 bordered: true,
56 51 showIndexColumn: false,
... ...
... ... @@ -48,7 +48,7 @@
48 48 const { createMessage } = useMessage();
49 49 const [registerTable] = useTable({
50 50 columns: realTimeDataColumns,
51   - showTableSetting: false,
  51 + showTableSetting: true,
52 52 bordered: true,
53 53 showIndexColumn: false,
54 54 dataSource: state.recordList,
... ...
... ... @@ -142,7 +142,7 @@
142 142 pagination: false,
143 143 autoCreateKey: true,
144 144 actionColumn: {
145   - width: 180,
  145 + width: 200,
146 146 title: '操作',
147 147 dataIndex: 'action',
148 148 slots: { customRender: 'action' },
... ...
... ... @@ -2,7 +2,7 @@
2 2 <div>
3 3 <BasicTable @register="registerTable">
4 4 <template #toolbar>
5   - <a-button type="primary" @click="handleCreate"> 新增配置 </a-button>
  5 + <a-button type="primary" @click="handleCreate"> 新增消息配置 </a-button>
6 6 </template>
7 7 <template #config="{ record }">
8 8 <a-button type="link" class="ml-2" @click="showData(record)"> 查看配置 </a-button>
... ... @@ -62,7 +62,7 @@
62 62 bordered: true,
63 63 showIndexColumn: false,
64 64 actionColumn: {
65   - width: 180,
  65 + width: 200,
66 66 title: '操作',
67 67 dataIndex: 'action',
68 68 slots: { customRender: 'action' },
... ...
... ... @@ -69,7 +69,7 @@
69 69 bordered: true,
70 70 showIndexColumn: false,
71 71 actionColumn: {
72   - width: 140,
  72 + width: 200,
73 73 title: '操作',
74 74 dataIndex: 'action',
75 75 slots: { customRender: 'action' },
... ...
... ... @@ -67,7 +67,7 @@
67 67 bordered: true,
68 68 showIndexColumn: false,
69 69 actionColumn: {
70   - width: 140,
  70 + width: 200,
71 71 title: '操作',
72 72 dataIndex: 'action',
73 73 slots: { customRender: 'action' },
... ...
... ... @@ -2,7 +2,7 @@
2 2 <div>
3 3 <BasicTable @register="registerTable">
4 4 <template #toolbar>
5   - <a-button type="primary" @click="handleCreate"> 新增模板 </a-button>
  5 + <a-button type="primary" @click="handleCreate"> 新增消息模板 </a-button>
6 6 </template>
7 7 <template #config="{ record }">
8 8 <a-button type="link" class="ml-2" @click="goConfig">
... ... @@ -78,7 +78,7 @@
78 78 bordered: true,
79 79 showIndexColumn: false,
80 80 actionColumn: {
81   - width: 180,
  81 + width: 200,
82 82 title: '操作',
83 83 dataIndex: 'action',
84 84 slots: { customRender: 'action' },
... ...
... ... @@ -96,7 +96,7 @@
96 96 bordered: true,
97 97 showIndexColumn: false,
98 98 actionColumn: {
99   - width: 180,
  99 + width: 200,
100 100 title: '操作',
101 101 dataIndex: 'action',
102 102 slots: { customRender: 'action' },
... ...
... ... @@ -79,7 +79,7 @@
79 79 bordered: true,
80 80 showIndexColumn: false,
81 81 actionColumn: {
82   - width: 180,
  82 + width: 200,
83 83 title: '操作',
84 84 dataIndex: 'action',
85 85 slots: { customRender: 'action' },
... ...
... ... @@ -41,7 +41,7 @@
41 41 bordered: true,
42 42 showIndexColumn: false,
43 43 actionColumn: {
44   - width: 180,
  44 + width: 200,
45 45 title: '操作',
46 46 dataIndex: 'action',
47 47 slots: { customRender: 'action' },
... ...
... ... @@ -2,7 +2,7 @@
2 2 <div>
3 3 <BasicTable @register="registerTable">
4 4 <template #toolbar>
5   - <a-button type="primary" @click="handleAdd"> 新增 </a-button>
  5 + <a-button type="primary" @click="handleAdd">新增通知</a-button>
6 6 <a-button color="error" @click="handleToolbarDel" :disabled="hasBatchDelete">
7 7 批量删除
8 8 </a-button>
... ... @@ -92,7 +92,7 @@
92 92 bordered: true,
93 93 showIndexColumn: false,
94 94 actionColumn: {
95   - width: 180,
  95 + width: 200,
96 96 title: '操作',
97 97 dataIndex: 'action',
98 98 slots: { customRender: 'action' },
... ...
... ... @@ -71,7 +71,7 @@
71 71 api: getNotifyDetailPage,
72 72 columns: detailColumns,
73 73 bordered: true,
74   - showTableSetting: false,
  74 + showTableSetting: true,
75 75 showIndexColumn: false,
76 76 immediate: false,
77 77 beforeFetch: getNoticeId,
... ...
... ... @@ -49,7 +49,7 @@
49 49 title: t('sys.errorLog.tableTitle'),
50 50 columns: getColumns(),
51 51 actionColumn: {
52   - width: 80,
  52 + width: 200,
53 53 title: 'Action',
54 54 dataIndex: 'action',
55 55 slots: { customRender: 'action' },
... ...
1 1 <template>
2   - <div class="login-page" :class="{ light1: isDark, dark: !isDark }">
3   - <div class="login-header" :style="{ backgroundColor: isDark ? '#1d3794' : '#22283a' }">
4   - <AppLogo
5   - :alwaysShowTitle="true"
6   - style="z-index: 99; position: absolute; width: 40px; height: 100px; left: 10%; top: -20px"
7   - />
8   -
9   - <AppDarkModeToggle
10   - class="absolute top-3 right-10 enter-x"
11   - v-if="!sessionTimeout"
12   - @click="toggleDark"
13   - />
14   - <AppLocalePicker
15   - class="absolute text-white top-4 right-4 enter-x xl:text-gray-600"
16   - :showText="false"
17   - color="#ffffff"
18   - v-if="!sessionTimeout && showLocale"
19   - />
20   - </div>
21   - <div class="login-container">
22   - <div class="flex w-full h-full py-5 xl:h-auto xl:py-0 xl:my-0 xl:w-6/12">
23   - <div class="login-description">
24   - <h1>物联网平台</h1>
25   - <h2>输入您的个人详细信息开始使用!</h2>
  2 + <div :class="prefixCls" class="relative w-full h-full px-4">
  3 + <AppLocalePicker
  4 + class="absolute text-white top-4 right-4 enter-x xl:text-gray-600"
  5 + :showText="false"
  6 + v-if="!sessionTimeout && showLocale"
  7 + />
  8 + <AppDarkModeToggle class="absolute top-3 right-7 enter-x" v-if="!sessionTimeout" />
  9 +
  10 + <span class="-enter-x xl:hidden">
  11 + <AppLogo :alwaysShowTitle="true" />
  12 + </span>
  13 +
  14 + <div class="container relative h-full py-2 mx-auto sm:px-10">
  15 + <div class="flex h-full">
  16 + <div class="hidden min-h-full pl-4 mr-4 xl:flex xl:flex-col xl:w-6/12">
  17 + <AppLogo class="-enter-x" />
  18 + <div class="my-auto">
  19 + <img
  20 + :alt="title"
  21 + src="../../../assets/svg/login-box-bg.svg"
  22 + class="w-1/2 -mt-16 -enter-x"
  23 + />
  24 + <div class="mt-10 font-medium text-white -enter-x">
  25 + <span class="inline-block mt-4 text-3xl"> {{ t('sys.login.signInTitle') }}</span>
  26 + </div>
  27 + <div class="mt-5 font-normal text-white text-md dark:text-gray-500 -enter-x">
  28 + {{ t('sys.login.signInDesc') }}
  29 + </div>
  30 + </div>
26 31 </div>
27   - <div
28   - :class="`${prefixCls}-form`"
29   - class="relative w-full px-5 py-8 mx-auto my-auto rounded-md shadow-md xl:ml-16 xl:bg-transparent sm:px-8 xl:p-4 xl:shadow-none sm:w-3/4 lg:w-2/4 xl:w-auto enter-x"
30   - :style="{ backgroundColor: isDark ? '#fff' : '#1a2030' }"
31   - >
32   - <LoginForm />
33   - <ForgetPasswordForm />
34   - <RegisterForm />
35   - <MobileForm />
36   - <QrCodeForm />
  32 + <div class="flex w-full h-full py-5 xl:h-auto xl:py-0 xl:my-0 xl:w-6/12">
  33 + <div
  34 + :class="`${prefixCls}-form`"
  35 + class="relative w-full px-5 py-8 mx-auto my-auto rounded-md shadow-md xl:ml-16 xl:bg-transparent sm:px-8 xl:p-4 xl:shadow-none sm:w-3/4 lg:w-2/4 xl:w-auto enter-x"
  36 + >
  37 + <LoginForm />
  38 + <ForgetPasswordForm />
  39 + <RegisterForm />
  40 + <MobileForm />
  41 + <QrCodeForm />
  42 + </div>
37 43 </div>
38 44 </div>
39   - <div
40   - style="
41   - width: 100%;
42   - display: flex;
43   - justify-content: center;
44   - position: absolute;
45   - bottom: 1.25rem;
46   - color: #fff;
47   - "
48   - >{{ getCopyRight }}</div
49   - >
50 45 </div>
51 46 </div>
52 47 </template>
... ... @@ -59,76 +54,162 @@
59 54 import RegisterForm from './RegisterForm.vue';
60 55 import MobileForm from './MobileForm.vue';
61 56 import QrCodeForm from './QrCodeForm.vue';
  57 + import { useGlobSetting } from '/@/hooks/setting';
  58 + import { useI18n } from '/@/hooks/web/useI18n';
62 59 import { useDesign } from '/@/hooks/web/useDesign';
63 60 import { useLocaleStore } from '/@/store/modules/locale';
64 61 import { useUserStore } from '/@/store/modules/user';
65   -
66 62 defineProps({
67 63 sessionTimeout: {
68 64 type: Boolean,
69 65 },
70 66 });
71 67
  68 + const globSetting = useGlobSetting();
72 69 const { prefixCls } = useDesign('login');
  70 + const { t } = useI18n();
73 71 const localeStore = useLocaleStore();
74 72 const showLocale = localeStore.getShowPicker;
75   - const isDark = ref(true);
76   - const toggleDark = () => {
77   - isDark.value = !isDark.value;
78   - };
79   - const userStore = useUserStore();
80   - const getCopyRight = computed(() => {
81   - return (
82   - (userStore.platInfo?.copyright ?? 'Copyright@ 云腾五洲 蜀ICP') +
83   - (userStore.platInfo?.presentedOurselves ?? '')
84   - );
85   - });
  73 + const title = computed(() => globSetting?.title ?? '');
86 74 </script>
87 75 <style lang="less">
88 76 @prefix-cls: ~'@{namespace}-login';
89 77 @logo-prefix-cls: ~'@{namespace}-app-logo';
90 78 @countdown-prefix-cls: ~'@{namespace}-countdown-input';
91 79 @dark-bg: #293146;
92   - .light1 {
93   - background-image: url('/src/assets/images/bg.png');
94   - }
95   - .dark {
96   - background-image: url('/src/assets/images/bg-dark.png');
  80 +
  81 + html[data-theme='dark'] {
  82 + .@{prefix-cls} {
  83 + background-color: @dark-bg;
  84 +
  85 + &::before {
  86 + background-image: url(/@/assets/svg/login-bg-dark.svg);
  87 + }
  88 +
  89 + .ant-input,
  90 + .ant-input-password {
  91 + background-color: #232a3b;
  92 + }
  93 +
  94 + .ant-btn:not(.ant-btn-link):not(.ant-btn-primary) {
  95 + border: 1px solid #4a5569;
  96 + }
  97 +
  98 + &-form {
  99 + background: transparent !important;
  100 + }
  101 +
  102 + .app-iconify {
  103 + color: #fff;
  104 + }
  105 + }
  106 +
  107 + input.fix-auto-fill,
  108 + .fix-auto-fill input {
  109 + -webkit-text-fill-color: #c9d1d9 !important;
  110 + box-shadow: inherit !important;
  111 + }
97 112 }
98   - .login-page {
99   - width: 100%;
100   - height: 100%;
101   - position: relative;
102   - background-size: 100% 100%;
103   - background-repeat: no-repeat;
104   - .login-header {
105   - height: 60px;
  113 +
  114 + .@{prefix-cls} {
  115 + min-height: 100%;
  116 + overflow: hidden;
  117 + @media (max-width: @screen-xl) {
  118 + background-color: #293146;
  119 +
  120 + .@{prefix-cls}-form {
  121 + background-color: #fff;
  122 + }
  123 + }
  124 +
  125 + &::before {
  126 + position: absolute;
  127 + top: 0;
  128 + left: 0;
106 129 width: 100%;
  130 + height: 100%;
  131 + margin-left: -48%;
  132 + background-image: url(/@/assets/svg/login-bg.svg);
  133 + background-position: 100%;
  134 + background-repeat: no-repeat;
  135 + background-size: auto 100%;
  136 + content: '';
  137 + @media (max-width: @screen-xl) {
  138 + display: none;
  139 + }
  140 + }
  141 +
  142 + .@{logo-prefix-cls} {
107 143 position: absolute;
108   - background-color: #1d3794;
  144 + top: 12px;
  145 + height: 30px;
  146 +
  147 + &__title {
  148 + font-size: 16px;
  149 + color: #fff;
  150 + }
  151 +
  152 + img {
  153 + width: 32px;
  154 + }
109 155 }
110   - .login-container {
111   - .login-description {
112   - position: absolute;
113   - right: 16.25rem;
114   - top: 10rem;
115   - text-align: center;
116   - h1 {
117   - color: #5aeeed;
118   - font-size: 26px;
  156 +
  157 + .container {
  158 + .@{logo-prefix-cls} {
  159 + display: flex;
  160 + width: 60%;
  161 + height: 80px;
  162 +
  163 + &__title {
  164 + font-size: 24px;
  165 + color: #fff;
  166 + }
  167 +
  168 + img {
  169 + width: 48px;
119 170 }
120   - h2 {
121   - color: #5aeeed;
122   - font-size: 20px;
  171 + }
  172 + }
  173 +
  174 + &-sign-in-way {
  175 + .anticon {
  176 + font-size: 22px;
  177 + color: #888;
  178 + cursor: pointer;
  179 +
  180 + &:hover {
  181 + color: @primary-color;
123 182 }
124 183 }
125   - .vben-login-form {
126   - position: absolute;
127   - width: 25.625rem;
128   - right: 12.5rem;
129   - top: 50%;
130   - margin-top: -11.25rem;
  184 + }
  185 +
  186 + input:not([type='checkbox']) {
  187 + min-width: 360px;
  188 +
  189 + @media (max-width: @screen-xl) {
  190 + min-width: 320px;
  191 + }
  192 +
  193 + @media (max-width: @screen-lg) {
  194 + min-width: 260px;
  195 + }
  196 +
  197 + @media (max-width: @screen-md) {
  198 + min-width: 240px;
  199 + }
  200 +
  201 + @media (max-width: @screen-sm) {
  202 + min-width: 160px;
131 203 }
132 204 }
  205 +
  206 + .@{countdown-prefix-cls} input {
  207 + min-width: unset;
  208 + }
  209 +
  210 + .ant-divider-inner-text {
  211 + font-size: 12px;
  212 + color: @text-color-secondary;
  213 + }
133 214 }
134 215 </style>
... ...
1 1 <template>
2   - <div>
3   - <LoginFormTitle v-show="getShow" class="enter-x" />
4   - <Form
5   - class="p-4 enter-x"
6   - :model="formData"
7   - :rules="getFormRules"
8   - ref="formRef"
9   - v-show="getShow"
10   - @keypress.enter="handleLogin"
11   - >
12   - <FormItem name="account" class="enter-x">
13   - <Input
14   - size="large"
15   - v-model:value="formData.account"
16   - :placeholder="t('sys.login.userName')"
17   - class="fix-auto-fill"
18   - />
19   - </FormItem>
20   - <FormItem name="password" class="enter-x">
21   - <InputPassword
22   - size="large"
23   - visibilityToggle
24   - v-model:value="formData.password"
25   - :placeholder="t('sys.login.password')"
26   - />
27   - </FormItem>
  2 + <LoginFormTitle v-show="getShow" class="enter-x" />
  3 + <Form
  4 + class="p-4 enter-x"
  5 + :model="formData"
  6 + :rules="getFormRules"
  7 + ref="formRef"
  8 + v-show="getShow"
  9 + @keypress.enter="handleLogin"
  10 + >
  11 + <FormItem name="account" class="enter-x">
  12 + <Input
  13 + size="large"
  14 + v-model:value="formData.account"
  15 + :placeholder="t('sys.login.userName')"
  16 + class="fix-auto-fill"
  17 + />
  18 + </FormItem>
  19 + <FormItem name="password" class="enter-x">
  20 + <InputPassword
  21 + size="large"
  22 + visibilityToggle
  23 + v-model:value="formData.password"
  24 + :placeholder="t('sys.login.password')"
  25 + />
  26 + </FormItem>
28 27
29   - <FormItem class="enter-x">
30   - <Button
31   - size="large"
32   - block
33   - @click="handleLogin"
34   - :loading="loading"
35   - style="background-color: #2950f7; color: #fff"
36   - >
37   - {{ t('sys.login.loginButton') }}
38   - </Button>
39   - </FormItem>
40   - <ARow type="flex" justify="space-between">
41   - <ACol :md="11" :xs="24">
42   - <Button
43   - type="link"
44   - color="#2950f7"
45   - block
46   - @click="setLoginState(LoginStateEnum.MOBILE)"
47   - style="color: #2950f7"
48   - >
49   - {{ t('sys.login.mobileSignInFormTitle') }}
50   - </Button>
51   - </ACol>
52   - <ACol :md="11" :xs="24">
53   - <Button
54   - type="link"
55   - block
56   - @click="setLoginState(LoginStateEnum.QR_CODE)"
57   - style="color: #2950f7"
58   - >
59   - {{ t('sys.login.qrSignInFormTitle') }}
  28 + <ARow class="enter-x">
  29 + <ACol :span="12">
  30 + <FormItem>
  31 + <Checkbox v-model:checked="rememberMe" size="small">
  32 + {{ t('sys.login.rememberMe') }}
  33 + </Checkbox>
  34 + </FormItem>
  35 + </ACol>
  36 + <ACol :span="12">
  37 + <FormItem style="text-align: right">
  38 + <Button type="link" size="small" @click="setLoginState(LoginStateEnum.RESET_PASSWORD)">
  39 + {{ t('sys.login.forgetPassword') }}
60 40 </Button>
61   - </ACol>
62   - </ARow>
63   - <ARow class="enter-x">
64   - <ACol :span="12">
65   - <FormItem />
66   - </ACol>
67   - <ACol :span="12">
68   - <FormItem :style="{ 'text-align': 'right' }">
69   - <!-- No logic, you need to deal with it yourself -->
70   - <Button type="link" size="small" @click="setLoginState(LoginStateEnum.RESET_PASSWORD)">
71   - {{ t('sys.login.forgetPassword') }}
72   - </Button>
73   - </FormItem>
74   - </ACol>
75   - </ARow>
76   - </Form>
77   - </div>
  41 + </FormItem>
  42 + </ACol>
  43 + </ARow>
  44 +
  45 + <FormItem class="enter-x">
  46 + <Button type="primary" size="large" block @click="handleLogin" :loading="loading">
  47 + {{ t('sys.login.loginButton') }}
  48 + </Button>
  49 + </FormItem>
  50 + <ARow class="enter-x flex justify-between">
  51 + <ACol :md="11" :xs="24">
  52 + <Button block @click="setLoginState(LoginStateEnum.MOBILE)">
  53 + {{ t('sys.login.mobileSignInFormTitle') }}
  54 + </Button>
  55 + </ACol>
  56 + <ACol :md="11" :xs="24">
  57 + <Button block @click="setLoginState(LoginStateEnum.QR_CODE)">
  58 + {{ t('sys.login.qrSignInFormTitle') }}
  59 + </Button>
  60 + </ACol>
  61 + </ARow>
  62 + </Form>
78 63 </template>
79 64 <script lang="ts" setup>
80   - import { reactive, ref, toRaw, unref, computed } from 'vue';
81   -
82   - import { Form, Input, Row, Col, Button } from 'ant-design-vue';
  65 + import { reactive, ref, unref, computed } from 'vue';
  66 + import { Checkbox, Form, Input, Row, Col, Button } from 'ant-design-vue';
83 67 import LoginFormTitle from './LoginFormTitle.vue';
84 68
85 69 import { useI18n } from '/@/hooks/web/useI18n';
... ... @@ -98,12 +82,14 @@
98 82 const { t } = useI18n();
99 83 const { notification, createErrorModal } = useMessage();
100 84 const { prefixCls } = useDesign('login');
  85 + const userStore = useUserStore();
101 86
102 87 const { setLoginState, getLoginState } = useLoginState();
103 88 const { getFormRules } = useFormRules();
104   - const userStore = useUserStore();
  89 +
105 90 const formRef = ref();
106 91 const loading = ref(false);
  92 + const rememberMe = ref(false);
107 93
108 94 const formData = reactive({
109 95 account: 'sysadmin',
... ... @@ -112,8 +98,6 @@
112 98
113 99 const { validForm } = useFormValid(formRef);
114 100
115   - //onKeyStroke('Enter', handleLogin);
116   -
117 101 const getShow = computed(() => unref(getLoginState) === LoginStateEnum.LOGIN);
118 102 const storage = createLocalStorage();
119 103 async function handleLogin() {
... ... @@ -121,13 +105,11 @@
121 105 if (!data) return;
122 106 try {
123 107 loading.value = true;
124   - const userInfo = await userStore.login(
125   - toRaw({
126   - password: data.password,
127   - username: data.account,
128   - mode: 'none', //不要默认的错误提示
129   - })
130   - );
  108 + const userInfo = await userStore.login({
  109 + password: data.password,
  110 + username: data.account,
  111 + mode: 'none', //不要默认的错误提示
  112 + });
131 113 if (userInfo) {
132 114 notification.success({
133 115 message: t('sys.login.loginSuccessTitle'),
... ... @@ -145,15 +127,10 @@
145 127 link.href = res.icon ?? '/favicon.ico';
146 128 document.getElementsByTagName('head')[0].appendChild(link);
147 129 }
148   - } catch (error: any) {
  130 + } catch (error) {
149 131 createErrorModal({
150   - title: t('sys.api.loginFailed'),
151   - content:
152   - error.response && error.response.status == 401
153   - ? error.response.data.message
154   - : error.code == 'ECONNABORTED'
155   - ? t('sys.api.timeoutMessage')
156   - : t('sys.api.apiRequestFailed'),
  132 + title: t('sys.api.errorTip'),
  133 + content: (error as unknown as Error).message || t('sys.api.networkExceptionMsg'),
157 134 getContainer: () => document.body.querySelector(`.${prefixCls}`) || document.body,
158 135 });
159 136 } finally {
... ...
1 1 <template>
2   - <h2
3   - class="mb-3 text-2xl font-bold text-center xl:text-3xl enter-x xl:text-left flex justify-center"
4   - >
  2 + <h2 class="mb-3 text-2xl font-bold text-center xl:text-3xl enter-x xl:text-left">
5 3 {{ getFormTitle }}
6 4 </h2>
7 5 </template>
... ...
... ... @@ -21,14 +21,7 @@
21 21 </FormItem>
22 22
23 23 <FormItem class="enter-x">
24   - <Button
25   - type="primary"
26   - size="large"
27   - block
28   - @click="handleLogin"
29   - :loading="loading"
30   - style="background-color: #2950f7; color: #fff"
31   - >
  24 + <Button type="primary" size="large" block @click="handleLogin" :loading="loading">
32 25 {{ t('sys.login.loginButton') }}
33 26 </Button>
34 27 <Button size="large" block class="mt-4" @click="handleBackLogin">
... ...
... ... @@ -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-center"
  7 + class="enter-x flex justify-center xl:justify-start"
8 8 :width="280"
9 9 />
10 10 <Divider class="enter-x">{{ t('sys.login.scanSign') }}</Divider>
... ...
... ... @@ -103,9 +103,8 @@
103 103 useSearchForm: true,
104 104 showTableSetting: true,
105 105 bordered: true,
106   -
107 106 actionColumn: {
108   - width: 220,
  107 + width: 200,
109 108 title: '操作',
110 109 dataIndex: 'action',
111 110 slots: { customRender: 'action' },
... ...
... ... @@ -73,7 +73,7 @@
73 73 bordered: true,
74 74 showIndexColumn: false,
75 75 actionColumn: {
76   - width: 240,
  76 + width: 300,
77 77 title: '操作',
78 78 dataIndex: 'action',
79 79 slots: { customRender: 'action' },
... ...
... ... @@ -80,7 +80,7 @@
80 80 showIndexColumn: false,
81 81 canResize: false,
82 82 actionColumn: {
83   - width: 120,
  83 + width: 200,
84 84 title: t('routes.common.system.pageSystemTitleOperation'), //操作
85 85 dataIndex: 'action',
86 86 slots: { customRender: 'action' },
... ...
... ... @@ -65,7 +65,7 @@
65 65 showIndexColumn: false,
66 66 canResize: false,
67 67 actionColumn: {
68   - width: 80,
  68 + width: 200,
69 69 title: t('routes.common.common.operation'), //操作
70 70 dataIndex: 'action',
71 71 slots: { customRender: 'action' },
... ...
... ... @@ -2,7 +2,7 @@
2 2 <div>
3 3 <BasicTable @register="registerTable">
4 4 <template #toolbar>
5   - <a-button type="primary" @click="handleCreate"> 新增角色 </a-button>
  5 + <a-button type="primary" @click="handleCreate">新增角色</a-button>
6 6 </template>
7 7 <template #action="{ record }">
8 8 <TableAction
... ... @@ -49,11 +49,6 @@
49 49 title: '角色列表',
50 50 api: getRoleListByPage,
51 51 columns,
52   - tableSetting: {
53   - redo: true,
54   - size: false,
55   - setting: false,
56   - },
57 52 formConfig: {
58 53 labelWidth: 120,
59 54 schemas: searchFormSchema,
... ... @@ -63,7 +58,7 @@
63 58 bordered: true,
64 59 showIndexColumn: false,
65 60 actionColumn: {
66   - width: 80,
  61 + width: 200,
67 62 title: '操作',
68 63 dataIndex: 'action',
69 64 slots: { customRender: 'action' },
... ...
... ... @@ -188,11 +188,6 @@
188 188 slots: { customRender: 'action' },
189 189 fixed: 'right',
190 190 },
191   - tableSetting: {
192   - redo: true,
193   - size: false,
194   - setting: false,
195   - },
196 191 });
197 192 //默认传递页面数据
198 193 const [tenantAdminDrawer, { closeDrawer }] = useDrawerInner(async (data) => {
... ...
... ... @@ -98,7 +98,6 @@
98 98 {
99 99 field: 'email',
100 100 label: '邮件',
101   - required: true,
102 101 component: 'Input',
103 102 rules: emailRule,
104 103 },
... ...
... ... @@ -39,7 +39,7 @@
39 39 import { FileItem } from '/@/components/Upload/src/typing';
40 40 import { upload } from '/@/api/oss/ossFileUploader';
41 41 import { getTenantRoles, updateOrCreateTenant } from '/@/api/tenant/tenantApi';
42   -
  42 + import { useMessage } from '/@/hooks/web/useMessage';
43 43 export default defineComponent({
44 44 name: 'TenantDrawer',
45 45 components: {
... ... @@ -133,12 +133,16 @@
133 133 entityType: 'TENANT_PROFILE',
134 134 },
135 135 };
136   - updateOrCreateTenant(req).then(() => {
137   - closeDrawer(); //关闭侧框
138   - emit('success');
139   - });
  136 + await updateOrCreateTenant(req);
  137 + closeDrawer(); //关闭侧框
  138 + emit('success');
  139 + } catch (e) {
  140 + const { createMessage } = useMessage();
  141 + createMessage.error("Can't use isolated tenant profiles in monolith setup!");
140 142 } finally {
141   - setDrawerProps({ confirmLoading: false });
  143 + setDrawerProps({
  144 + confirmLoading: false,
  145 + });
142 146 }
143 147 }
144 148
... ...
... ... @@ -74,16 +74,54 @@
74 74 import { useDrawer } from '/@/components/Drawer';
75 75 import TenantDrawer from './TenantDrawer.vue';
76 76 import TenantAdminDrawer from './TenantAdminDrawer.vue';
  77 + import { useMessage } from '/@/hooks/web/useMessage';
77 78 export default defineComponent({
78 79 components: { BasicTable, TableImg, Tag, TableAction, TenantDrawer, TenantAdminDrawer },
79 80 setup() {
80 81 const [tenantDrawer, { openDrawer }] = useDrawer();
81 82 const [tenantAdminDrawer, { openDrawer: openTenantAdminDrawer }] = useDrawer();
  83 + const searchFiled: FormSchema[] = [
  84 + {
  85 + field: 'tenantName',
  86 + label: '租户名称',
  87 + component: 'Input',
  88 + componentProps: {
  89 + placeholder: '请输入租户名称',
  90 + },
  91 + colProps: { span: 8 },
  92 + },
  93 + ];
  94 + const [tenantTable, { reload, setLoading }] = useTable({
  95 + title: '租户',
  96 + api: getTenantPage,
  97 + columns: getBasicColumns(),
  98 + useSearchForm: true,
  99 + showTableSetting: true,
  100 + bordered: true,
  101 + showIndexColumn: false,
82 102
83   - function handleDelete(record: Recordable) {
84   - deleteTenant([record.id]).then(() => {
  103 + formConfig: {
  104 + labelWidth: 120,
  105 + schemas: searchFiled,
  106 + },
  107 + actionColumn: {
  108 + width: 200,
  109 + title: '操作',
  110 + dataIndex: 'action',
  111 + slots: { customRender: 'action' },
  112 + fixed: 'right',
  113 + },
  114 + });
  115 + async function handleDelete(record: Recordable) {
  116 + try {
  117 + setLoading(true);
  118 + await deleteTenant([record.id]);
85 119 reload();
86   - });
  120 + const { createMessage } = useMessage();
  121 + createMessage.success('删除成功');
  122 + } finally {
  123 + setLoading(false);
  124 + }
87 125 }
88 126
89 127 function handleCreate() {
... ... @@ -105,44 +143,10 @@
105 143 });
106 144 }
107 145
108   - const searchFiled: FormSchema[] = [
109   - {
110   - field: 'tenantName',
111   - label: '租户名称',
112   - component: 'Input',
113   - colProps: { span: 8 },
114   - },
115   - ];
116   -
117 146 function handleSuccess() {
118 147 reload();
119 148 }
120 149
121   - const [tenantTable, { reload }] = useTable({
122   - title: '租户',
123   - api: getTenantPage,
124   - columns: getBasicColumns(),
125   - useSearchForm: true,
126   - showTableSetting: true,
127   - bordered: true,
128   - showIndexColumn: false,
129   - tableSetting: {
130   - redo: true,
131   - size: false,
132   - setting: false,
133   - },
134   - formConfig: {
135   - labelWidth: 120,
136   - schemas: searchFiled,
137   - },
138   - actionColumn: {
139   - width: 150,
140   - title: '操作',
141   - dataIndex: 'action',
142   - slots: { customRender: 'action' },
143   - fixed: 'right',
144   - },
145   - });
146 150 return {
147 151 tenantTable,
148 152 handleEdit,
... ... @@ -152,6 +156,7 @@
152 156 tenantAdminDrawer,
153 157 handleSuccess,
154 158 handleTenantAdminDrawer,
  159 + setLoading,
155 160 };
156 161 },
157 162 });
... ...
... ... @@ -38,7 +38,7 @@ export const schemas: FormSchema[] = [
38 38 {
39 39 field: 'icon',
40 40 component: 'Upload',
41   - label: 'Favicon浏览器Icon图标',
  41 + label: '浏览器Icon图标',
42 42 colProps: {
43 43 span: 24,
44 44 },
... ...
... ... @@ -14,19 +14,6 @@ export const schemas: FormSchema[] = [
14 14 maxLength: 100,
15 15 placeholder: '请输入公司名称',
16 16 },
17   - dynamicRules: () => {
18   - return [
19   - {
20   - required: false,
21   - validator: (_, value) => {
22   - if (String(value).length > 100) {
23   - return Promise.reject('字数不超过100个字');
24   - }
25   - return Promise.resolve();
26   - },
27   - },
28   - ];
29   - },
30 17 },
31 18 {
32 19 field: 'abbreviation',
... ... @@ -39,19 +26,6 @@ export const schemas: FormSchema[] = [
39 26 maxLength: 100,
40 27 placeholder: '请输入公司简称',
41 28 },
42   - dynamicRules: () => {
43   - return [
44   - {
45   - required: false,
46   - validator: (_, value) => {
47   - if (String(value).length > 100) {
48   - return Promise.reject('字数不超过100个字');
49   - }
50   - return Promise.resolve();
51   - },
52   - },
53   - ];
54   - },
55 29 },
56 30 {
57 31 field: 'officialWebsite',
... ... @@ -64,19 +38,6 @@ export const schemas: FormSchema[] = [
64 38 maxLength: 255,
65 39 placeholder: '请输入公司官网',
66 40 },
67   - dynamicRules: () => {
68   - return [
69   - {
70   - required: false,
71   - validator: (_, value) => {
72   - if (String(value).length > 255) {
73   - return Promise.reject('字数不超过255个字');
74   - }
75   - return Promise.resolve();
76   - },
77   - },
78   - ];
79   - },
80 41 },
81 42 {
82 43 field: 'email',
... ... @@ -102,20 +63,6 @@ export const schemas: FormSchema[] = [
102 63 maxLength: 500,
103 64 placeholder: '请输入公司简介',
104 65 autoSize: { minRows: 8, maxRows: 12 },
105   - showCount: true,
106   - },
107   - dynamicRules: () => {
108   - return [
109   - {
110   - required: false,
111   - validator: (_, value) => {
112   - if (String(value).length > 500) {
113   - return Promise.reject('字数不超过500个字');
114   - }
115   - return Promise.resolve();
116   - },
117   - },
118   - ];
119 66 },
120 67 },
121 68 {
... ... @@ -146,7 +93,7 @@ export const schemas: FormSchema[] = [
146 93 api: getAreaList,
147 94 labelField: 'name',
148 95 valueField: 'code',
149   - placeholder: '请选择省份',
  96 + placeholder: '省份',
150 97 params: { parentId: 1 },
151 98 async onChange(value) {
152 99 if (value === undefined) {
... ... @@ -186,7 +133,7 @@ export const schemas: FormSchema[] = [
186 133 field: 'nameCity',
187 134 componentProps: {
188 135 options: nameCity,
189   - placeholder: '请选择城市',
  136 + placeholder: '城市',
190 137 async onChange(value) {
191 138 if (value === undefined) {
192 139 formModel.nameCoun = undefined; // reset city value
... ... @@ -223,7 +170,7 @@ export const schemas: FormSchema[] = [
223 170 updateSchema({
224 171 field: 'nameTown',
225 172 componentProps: {
226   - placeholder: '请选择街道/城镇',
  173 + placeholder: '城镇/街道',
227 174 options: [],
228 175 },
229 176 });
... ... @@ -236,7 +183,7 @@ export const schemas: FormSchema[] = [
236 183 updateSchema({
237 184 field: 'nameTown',
238 185 componentProps: {
239   - placeholder: '请选择街道/城镇',
  186 + placeholder: '城镇/街道',
240 187 options: nameTown,
241 188 },
242 189 });
... ... @@ -257,11 +204,11 @@ export const schemas: FormSchema[] = [
257 204 field: 'nameCity',
258 205 component: 'Select',
259 206 label: '',
  207 + componentProps: {
  208 + placeholder: '城市',
  209 + },
260 210 colProps: {
261 211 span: 5,
262   - style: {
263   - marginLeft: '-5rem',
264   - },
265 212 },
266 213 },
267 214 {
... ... @@ -269,13 +216,10 @@ export const schemas: FormSchema[] = [
269 216 component: 'Select',
270 217 label: '',
271 218 colProps: {
272   - span: 5,
273   - style: {
274   - marginLeft: '-160px',
275   - },
  219 + span: 3,
276 220 },
277 221 componentProps: {
278   - placeholder: '请选择区/县',
  222 + placeholder: '区/县',
279 223 },
280 224 },
281 225 {
... ... @@ -284,12 +228,9 @@ export const schemas: FormSchema[] = [
284 228 label: '',
285 229 colProps: {
286 230 span: 6,
287   - style: {
288   - marginLeft: '-160px',
289   - },
290 231 },
291 232 componentProps: {
292   - placeholder: '请选择街道/城镇',
  233 + placeholder: '城镇/街道',
293 234 },
294 235 },
295 236 {
... ...
... ... @@ -33,13 +33,12 @@
33 33 margin: 20px;
34 34 line-height: 50px;
35 35 font-size: 18px;
36   - border-radius: 8px;
  36 +
37 37 background-color: #fff;
38 38 padding-left: 10px;
39 39 }
40 40 .tab-card {
41 41 margin: 20px 0 20px 20px;
42   - border-radius: 5px;
43 42 }
44 43 .card {
45 44 margin: 20px;
... ...
... ... @@ -48,11 +48,7 @@
48 48 title: '租户角色列表',
49 49 api: getRoleListByPage,
50 50 columns,
51   - tableSetting: {
52   - redo: true,
53   - size: false,
54   - setting: false,
55   - },
  51 +
56 52 formConfig: {
57 53 labelWidth: 120,
58 54 schemas: searchFormSchema,
... ... @@ -62,7 +58,7 @@
62 58 bordered: true,
63 59 showIndexColumn: false,
64 60 actionColumn: {
65   - width: 80,
  61 + width: 200,
66 62 title: '操作',
67 63 dataIndex: 'action',
68 64 slots: { customRender: 'action' },
... ...
... ... @@ -62,7 +62,7 @@
62 62 bordered: true,
63 63 showIndexColumn: false,
64 64 actionColumn: {
65   - width: 180,
  65 + width: 200,
66 66 title: '操作',
67 67 dataIndex: 'action',
68 68 slots: { customRender: 'action' },
... ...