Commit 1380ef69ef5a621e3e8fd016b7c8914c426ff7ce

Authored by fengtao
2 parents e2ec225f d4825a8a

Merge branch 'main' into ft-dev

Showing 51 changed files with 724 additions and 608 deletions
1 <template> 1 <template>
2 - <ConfigProvider :locale="getAntdLocale"> 2 + <ConfigProvider :locale="getAntdLocale" :autoInsertSpaceInButton="false">
3 <AppProvider> 3 <AppProvider>
4 <RouterView /> 4 <RouterView />
5 </AppProvider> 5 </AppProvider>
@@ -34,7 +34,7 @@ export const useBatchDelete = ( @@ -34,7 +34,7 @@ export const useBatchDelete = (
34 if (record) { 34 if (record) {
35 try { 35 try {
36 await deleteFn([record.id]); 36 await deleteFn([record.id]);
37 - createMessage.success('删除联系人成功'); 37 + createMessage.success('删除成功');
38 handleSuccess(); 38 handleSuccess();
39 } catch (e) { 39 } catch (e) {
40 createMessage.error('删除失败'); 40 createMessage.error('删除失败');
@@ -42,11 +42,12 @@ export const useBatchDelete = ( @@ -42,11 +42,12 @@ export const useBatchDelete = (
42 } else { 42 } else {
43 try { 43 try {
44 await deleteFn(selectedRowIds.value); 44 await deleteFn(selectedRowIds.value);
45 - createMessage.success('批量删除联系人成功'); 45 + createMessage.success('批量删除成功');
46 selectedRowIds.value = []; 46 selectedRowIds.value = [];
47 handleSuccess(); 47 handleSuccess();
48 } catch (e) { 48 } catch (e) {
49 - createMessage.info('删除失败'); 49 + createMessage.error('删除失败');
  50 + selectedRowIds.value = [];
50 } 51 }
51 } 52 }
52 }; 53 };
@@ -23,6 +23,7 @@ @@ -23,6 +23,7 @@
23 import { getDeviceAlarm } from '/@/api/device/deviceManager'; 23 import { getDeviceAlarm } from '/@/api/device/deviceManager';
24 import { useDrawer } from '/@/components/Drawer'; 24 import { useDrawer } from '/@/components/Drawer';
25 import AlarmDetailDrawer from './cpns/AlarmDetailDrawer.vue'; 25 import AlarmDetailDrawer from './cpns/AlarmDetailDrawer.vue';
  26 +
26 export default defineComponent({ 27 export default defineComponent({
27 name: 'AlarmCenter', 28 name: 'AlarmCenter',
28 components: { 29 components: {
@@ -42,6 +43,7 @@ @@ -42,6 +43,7 @@
42 useSearchForm: true, 43 useSearchForm: true,
43 bordered: true, 44 bordered: true,
44 showIndexColumn: false, 45 showIndexColumn: false,
  46 + showTableSetting: true,
45 actionColumn: { 47 actionColumn: {
46 width: 200, 48 width: 200,
47 title: '操作', 49 title: '操作',
@@ -8,7 +8,7 @@ @@ -8,7 +8,7 @@
8 /> 8 />
9 <BasicTable @register="registerTable" :searchInfo="searchInfo" class="w-3/4 xl:w-4/5"> 9 <BasicTable @register="registerTable" :searchInfo="searchInfo" class="w-3/4 xl:w-4/5">
10 <template #toolbar> 10 <template #toolbar>
11 - <a-button type="primary" @click="handleCreateOrEdit(null)"> 新增联系人 </a-button> 11 + <a-button type="primary" @click="handleCreateOrEdit(null)"> 新增告警联系人 </a-button>
12 <a-button 12 <a-button
13 type="primary" 13 type="primary"
14 color="error" 14 color="error"
@@ -91,7 +91,7 @@ @@ -91,7 +91,7 @@
91 }, 91 },
92 rowKey: 'id', 92 rowKey: 'id',
93 actionColumn: { 93 actionColumn: {
94 - width: 180, 94 + width: 200,
95 title: '操作', 95 title: '操作',
96 dataIndex: 'action', 96 dataIndex: 'action',
97 slots: { customRender: 'action' }, 97 slots: { customRender: 'action' },
@@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@
13 } 13 }
14 const props = withDefaults(defineProps<Props>(), { 14 const props = withDefaults(defineProps<Props>(), {
15 width: '100%', 15 width: '100%',
16 - height: '300px', 16 + height: '320px',
17 customerTrendList: () => [], 17 customerTrendList: () => [],
18 }); 18 });
19 watch( 19 watch(
@@ -17,32 +17,29 @@ @@ -17,32 +17,29 @@
17 <img src="/src/assets/images/tip.png" style="width: 1.125rem; height: 1.125rem" /> 17 <img src="/src/assets/images/tip.png" style="width: 1.125rem; height: 1.125rem" />
18 </div> 18 </div>
19 <div> 设备数(个) </div> 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 </div> 20 </div>
43 </div> 21 </div>
44 <div class="ml-2 pt-4" style="border-top: 2px solid #f0f2f5"> 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 </Card> 44 </Card>
48 <Card size="small" class="md:w-1/3 w-full !md:mt-0 !mt-4 !md:mr-4" style="color: #666"> 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,9 +100,19 @@
100 >{{ index + 1 }}</span 100 >{{ index + 1 }}</span
101 > 101 >
102 <div class="flex justify-between" style="width: 100%"> 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 <div class="flex w-7/10"> 116 <div class="flex w-7/10">
107 <Progress 117 <Progress
108 :showInfo="false" 118 :showInfo="false"
@@ -142,7 +152,16 @@ @@ -142,7 +152,16 @@
142 152
143 <script lang="ts"> 153 <script lang="ts">
144 import { defineComponent, ref, computed, onMounted } from 'vue'; 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 import { useUserStore } from '/@/store/modules/user'; 165 import { useUserStore } from '/@/store/modules/user';
147 import { getEnterPriseDetail } from '/@/api/oem'; 166 import { getEnterPriseDetail } from '/@/api/oem';
148 import { notifyMyGetrPageApi } from '/@/api/stationnotification/stationnotifyApi'; 167 import { notifyMyGetrPageApi } from '/@/api/stationnotification/stationnotifyApi';
@@ -166,6 +185,7 @@ @@ -166,6 +185,7 @@
166 BasicTable, 185 BasicTable,
167 Progress, 186 Progress,
168 Skeleton, 187 Skeleton,
  188 + Tooltip,
169 }, 189 },
170 props: { 190 props: {
171 role: { 191 role: {
@@ -28,7 +28,12 @@ @@ -28,7 +28,12 @@
28 </div> 28 </div>
29 </Card> 29 </Card>
30 <div v-if="isAdmin(role)"> 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 <template #extra> 37 <template #extra>
33 <div class="extra-date"> 38 <div class="extra-date">
34 <template v-for="(item, index) in TenantOrCustomerDateList" :key="item.value"> 39 <template v-for="(item, index) in TenantOrCustomerDateList" :key="item.value">
@@ -47,7 +52,12 @@ @@ -47,7 +52,12 @@
47 </template> 52 </template>
48 <TenantTrend :tenantTrendList="tenantTrendList" /> 53 <TenantTrend :tenantTrendList="tenantTrendList" />
49 </Card> 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 <template #extra> 61 <template #extra>
52 <div class="extra-date"> 62 <div class="extra-date">
53 <template v-for="(item, index) in TenantOrCustomerDateList" :key="item.value"> 63 <template v-for="(item, index) in TenantOrCustomerDateList" :key="item.value">
@@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@
13 } 13 }
14 const props = withDefaults(defineProps<Props>(), { 14 const props = withDefaults(defineProps<Props>(), {
15 width: '100%', 15 width: '100%',
16 - height: '300px', 16 + height: '320px',
17 tenantTrendList: () => [], 17 tenantTrendList: () => [],
18 }); 18 });
19 19
@@ -3,27 +3,30 @@ import { FormSchema } from '/@/components/Form'; @@ -3,27 +3,30 @@ import { FormSchema } from '/@/components/Form';
3 import { BasicColumn } from '/@/components/Table'; 3 import { BasicColumn } from '/@/components/Table';
4 import { DeviceTypeEnum } from '/@/api/device/model/deviceModel'; 4 import { DeviceTypeEnum } from '/@/api/device/model/deviceModel';
5 import { getCustomerList } from '/@/api/device/deviceManager'; 5 import { getCustomerList } from '/@/api/device/deviceManager';
6 -import dayjs from 'moment';  
7 -export const columns: BasicColumn[] = [ 6 +import { DescItem } from '/@/components/Description/index';
  7 +import moment from 'moment';
  8 +// 设备详情的描述
  9 +export const descSchema: DescItem[] = [
8 { 10 {
9 - title: '设备名称',  
10 - dataIndex: 'name',  
11 - width: 120, 11 + field: 'createTime',
  12 + label: '创建时间',
12 }, 13 },
13 { 14 {
14 - title: '设备标签',  
15 - dataIndex: 'label',  
16 - width: 100, 15 + field: 'name',
  16 + label: '设备名称',
17 }, 17 },
18 { 18 {
19 - title: '设备配置',  
20 - dataIndex: 'deviceProfile.name',  
21 - width: 160, 19 + field: 'label',
  20 + label: '设备标签',
  21 + },
  22 + {
  23 + field: 'deviceProfile.name',
  24 + label: '设备配置',
22 }, 25 },
23 { 26 {
24 - title: '设备类型',  
25 - dataIndex: 'deviceType',  
26 - customRender({ text }) { 27 + field: 'deviceType',
  28 + label: '设备类型',
  29 + render: (text) => {
27 return text === DeviceTypeEnum.GATEWAY 30 return text === DeviceTypeEnum.GATEWAY
28 ? '网关设备' 31 ? '网关设备'
29 : text == DeviceTypeEnum.DIRECT_CONNECTION 32 : text == DeviceTypeEnum.DIRECT_CONNECTION
@@ -32,11 +35,11 @@ export const columns: BasicColumn[] = [ @@ -32,11 +35,11 @@ export const columns: BasicColumn[] = [
32 }, 35 },
33 }, 36 },
34 { 37 {
35 - title: '描述',  
36 - dataIndex: 'description',  
37 - width: 180, 38 + field: 'description',
  39 + label: '描述',
38 }, 40 },
39 ]; 41 ];
  42 +
40 // 实时数据表格 43 // 实时数据表格
41 export const realTimeDataColumns: BasicColumn[] = [ 44 export const realTimeDataColumns: BasicColumn[] = [
42 { 45 {
@@ -100,7 +103,7 @@ export const alarmSearchSchemas: FormSchema[] = [ @@ -100,7 +103,7 @@ export const alarmSearchSchemas: FormSchema[] = [
100 component: 'DatePicker', 103 component: 'DatePicker',
101 componentProps: { 104 componentProps: {
102 valueFormat: 'x', 105 valueFormat: 'x',
103 - showTime: { defaultValue: dayjs('23:59:59', 'HH:mm:ss') }, 106 + showTime: { defaultValue: moment('23:59:59', 'HH:mm:ss') },
104 }, 107 },
105 colProps: { span: 6 }, 108 colProps: { span: 6 },
106 }, 109 },
@@ -212,20 +215,25 @@ export const alarmSchemasForm: FormSchema[] = [ @@ -212,20 +215,25 @@ export const alarmSchemasForm: FormSchema[] = [
212 }, 215 },
213 }, 216 },
214 ]; 217 ];
215 -  
216 // 子设备 218 // 子设备
217 export const childDeviceSchemas: FormSchema[] = [ 219 export const childDeviceSchemas: FormSchema[] = [
218 { 220 {
219 - field: 'icon',  
220 - label: '设备配置',  
221 - component: 'Select', 221 + field: 'deviceState',
  222 + label: '设备状态',
222 colProps: { span: 6 }, 223 colProps: { span: 6 },
  224 + component: 'Select',
223 componentProps: { 225 componentProps: {
  226 + size: 'small',
224 maxLength: 255, 227 maxLength: 255,
  228 + options: [
  229 + { label: '待激活', value: 'INACTIVE' },
  230 + { label: '在线', value: 'ONLINE' },
  231 + { label: '离线', value: 'OFFLINE' },
  232 + ],
225 }, 233 },
226 }, 234 },
227 { 235 {
228 - field: 'icon', 236 + field: 'name',
229 label: '设备名称', 237 label: '设备名称',
230 component: 'Input', 238 component: 'Input',
231 colProps: { span: 6 }, 239 colProps: { span: 6 },
@@ -238,32 +246,30 @@ export const childDeviceSchemas: FormSchema[] = [ @@ -238,32 +246,30 @@ export const childDeviceSchemas: FormSchema[] = [
238 export const childDeviceColumns: BasicColumn[] = [ 246 export const childDeviceColumns: BasicColumn[] = [
239 { 247 {
240 title: '名称', 248 title: '名称',
241 - dataIndex: 'name', 249 + dataIndex: 'tbDeviceName',
242 width: 120, 250 width: 120,
243 }, 251 },
244 { 252 {
245 - title: '设备配置',  
246 - dataIndex: 'label',  
247 - width: 100,  
248 - },  
249 - {  
250 title: '标签', 253 title: '标签',
251 - dataIndex: 'aaa', 254 + dataIndex: 'label',
252 width: 160, 255 width: 160,
253 }, 256 },
254 { 257 {
255 title: '状态', 258 title: '状态',
256 - dataIndex: 'bbb', 259 + dataIndex: 'deviceState',
  260 + slots: { customRender: 'deviceState' },
257 width: 160, 261 width: 160,
258 }, 262 },
259 { 263 {
260 title: '最后连接时间', 264 title: '最后连接时间',
261 - dataIndex: 'ccc', 265 + dataIndex: 'lastOnlineTime',
  266 + format: (text) => formatToDateTime(text, 'YYYY-MM-DD HH:mm:ss'),
262 width: 160, 267 width: 160,
263 }, 268 },
264 { 269 {
265 - title: '创建时间',  
266 - dataIndex: 'ddd', 270 + title: '更新时间',
  271 + dataIndex: 'createdTime',
  272 + format: (text) => formatToDateTime(text, 'YYYY-MM-DD HH:mm:ss'),
267 width: 160, 273 width: 160,
268 }, 274 },
269 ]; 275 ];
@@ -7,7 +7,7 @@ @@ -7,7 +7,7 @@
7 centered 7 centered
8 @ok="dispatchCustomer" 8 @ok="dispatchCustomer"
9 @cancel="resetFields" 9 @cancel="resetFields"
10 - :minHeight="150" 10 + :minHeight="100"
11 okText="分配" 11 okText="分配"
12 > 12 >
13 <BasicForm @register="registerForm" /> 13 <BasicForm @register="registerForm" />
@@ -3,22 +3,22 @@ @@ -3,22 +3,22 @@
3 v-bind="$attrs" 3 v-bind="$attrs"
4 isDetail 4 isDetail
5 @register="register" 5 @register="register"
6 - :destroyOnClose="true" 6 + destroyOnClose
7 @close="closeDrawer" 7 @close="closeDrawer"
8 :title="deviceDetail.name" 8 :title="deviceDetail.name"
9 - width="70%" 9 + width="80%"
10 > 10 >
11 - <Tabs v-model:activeKey="activeKey" :size="size" type="card">  
12 - <TabPane key="1" tab="详情"  
13 - ><Detail ref="deviceDetailRef" :deviceDetail="deviceDetail"  
14 - /></TabPane>  
15 - <TabPane key="2" tab="实时数据" v-if="deviceDetail?.deviceType !== 'GATEWAY'"  
16 - ><RealTimeData :deviceDetail="deviceDetail"  
17 - /></TabPane> 11 + <Tabs v-model:activeKey="activeKey" :size="size">
  12 + <TabPane key="1" tab="详情">
  13 + <Detail ref="deviceDetailRef" :deviceDetail="deviceDetail" />
  14 + </TabPane>
  15 + <TabPane key="2" tab="实时数据" v-if="deviceDetail?.deviceType !== 'GATEWAY'">
  16 + <RealTimeData :deviceDetail="deviceDetail" />
  17 + </TabPane>
18 <TabPane key="3" tab="告警"><Alarm :id="deviceDetail.id" /></TabPane> 18 <TabPane key="3" tab="告警"><Alarm :id="deviceDetail.id" /></TabPane>
19 - <TabPane key="4" tab="子设备" v-if="deviceDetail?.deviceType === 'GATEWAY'"  
20 - ><ChildDevice  
21 - /></TabPane> 19 + <TabPane key="4" tab="子设备" v-if="deviceDetail?.deviceType === 'GATEWAY'">
  20 + <ChildDevice :fromId="deviceDetail?.tbDeviceId" />
  21 + </TabPane>
22 </Tabs> 22 </Tabs>
23 </BasicDrawer> 23 </BasicDrawer>
24 </template> 24 </template>
@@ -10,9 +10,9 @@ @@ -10,9 +10,9 @@
10 centered 10 centered
11 > 11 >
12 <div class="step-form-form"> 12 <div class="step-form-form">
13 - <Steps :current="current">  
14 - <Step title="填写设备信息" v-if="!isUpdate" />  
15 - <Step title="添加设备凭证" v-if="!isUpdate" /> 13 + <Steps :current="current" v-if="!isUpdate">
  14 + <Step title="填写设备信息" />
  15 + <Step title="添加设备凭证" />
16 </Steps> 16 </Steps>
17 </div> 17 </div>
18 <div class="mt-5"> 18 <div class="mt-5">
@@ -6,6 +6,7 @@ @@ -6,6 +6,7 @@
6 @cancel="handleCancel" 6 @cancel="handleCancel"
7 @ok="handleOk" 7 @ok="handleOk"
8 centered 8 centered
  9 + :canFullscreen="false"
9 > 10 >
10 <BasicForm @register="registerForm" /> 11 <BasicForm @register="registerForm" />
11 </BasicModal> 12 </BasicModal>
1 <template> 1 <template>
2 - <div> 2 + <div style="background-color: #f0f2f5">
3 <BasicTable @register="registerTable"> 3 <BasicTable @register="registerTable">
4 <template #action="{ record }"> 4 <template #action="{ record }">
5 <TableAction 5 <TableAction
@@ -40,18 +40,12 @@ @@ -40,18 +40,12 @@
40 const [registerTable, { reload }] = useTable({ 40 const [registerTable, { reload }] = useTable({
41 api: getDeviceAlarm, 41 api: getDeviceAlarm,
42 columns: alarmColumns, 42 columns: alarmColumns,
  43 + useSearchForm: true,
43 formConfig: { 44 formConfig: {
44 labelWidth: 120, 45 labelWidth: 120,
45 schemas: alarmSearchSchemas, 46 schemas: alarmSearchSchemas,
46 }, 47 },
47 showTableSetting: true, 48 showTableSetting: true,
48 - tableSetting: {  
49 - redo: true,  
50 - size: false,  
51 - setting: false,  
52 - fullScreen: false,  
53 - },  
54 - useSearchForm: true,  
55 bordered: true, 49 bordered: true,
56 showIndexColumn: false, 50 showIndexColumn: false,
57 beforeFetch: (data) => { 51 beforeFetch: (data) => {
1 <template> 1 <template>
2 - <BasicTable @register="registerTable" /> 2 + <div style="background-color: #f0f2f5">
  3 + <BasicTable @register="registerTable">
  4 + <template #deviceState="{ record }">
  5 + <Tag
  6 + :color="
  7 + record.deviceState == DeviceState.INACTIVE
  8 + ? 'warning'
  9 + : record.deviceState == DeviceState.ONLINE
  10 + ? 'success'
  11 + : 'error'
  12 + "
  13 + class="ml-2"
  14 + >
  15 + {{
  16 + record.deviceState == DeviceState.INACTIVE
  17 + ? '待激活'
  18 + : record.deviceState == DeviceState.ONLINE
  19 + ? '在线'
  20 + : '离线'
  21 + }}
  22 + </Tag>
  23 + </template>
  24 + </BasicTable>
  25 + </div>
3 </template> 26 </template>
4 <script lang="ts"> 27 <script lang="ts">
5 - import { defineComponent } from 'vue'; 28 + import { defineComponent, onMounted } from 'vue';
  29 + import { Tag } from 'ant-design-vue';
  30 + import { DeviceState } from '/@/api/device/model/deviceModel';
6 import { BasicTable, useTable } from '/@/components/Table'; 31 import { BasicTable, useTable } from '/@/components/Table';
7 import { childDeviceColumns, childDeviceSchemas } from '../../config/detail.config'; 32 import { childDeviceColumns, childDeviceSchemas } from '../../config/detail.config';
8 - 33 + import { getChildDevicePage } from '/@/api/device/deviceManager.ts';
9 export default defineComponent({ 34 export default defineComponent({
10 name: 'DeviceManagement', 35 name: 'DeviceManagement',
11 components: { 36 components: {
12 BasicTable, 37 BasicTable,
  38 + Tag,
  39 + },
  40 + props: {
  41 + fromId: {
  42 + type: String,
  43 + required: true,
  44 + },
13 }, 45 },
14 - setup(_) { 46 + setup(props) {
  47 + console.log(123);
  48 + onMounted(() => {
  49 + console.log(props.fromId);
  50 + });
15 const [registerTable] = useTable({ 51 const [registerTable] = useTable({
  52 + api: getChildDevicePage,
16 columns: childDeviceColumns, 53 columns: childDeviceColumns,
17 formConfig: { 54 formConfig: {
18 labelWidth: 120, 55 labelWidth: 120,
19 schemas: childDeviceSchemas, 56 schemas: childDeviceSchemas,
20 }, 57 },
  58 + beforeFetch: (data) => {
  59 + console.log(props.fromId);
  60 + Reflect.set(data, 'fromId', props.fromId);
  61 + },
21 useSearchForm: true, 62 useSearchForm: true,
22 showTableSetting: true, 63 showTableSetting: true,
23 bordered: true, 64 bordered: true,
@@ -26,6 +67,7 @@ @@ -26,6 +67,7 @@
26 67
27 return { 68 return {
28 registerTable, 69 registerTable,
  70 + DeviceState,
29 }; 71 };
30 }, 72 },
31 }); 73 });
@@ -6,14 +6,7 @@ @@ -6,14 +6,7 @@
6 </div> 6 </div>
7 <div> 7 <div>
8 <p>设备信息</p> 8 <p>设备信息</p>
9 - <Table  
10 - bordered  
11 - :columns="columns"  
12 - :data-source="[deviceDetail]"  
13 - :rowKey="(_, index) => index"  
14 - :pagination="false"  
15 - style="width: 800px"  
16 - /> 9 + <Description @register="register" class="mt-4" :data="deviceDetail" />
17 </div> 10 </div>
18 <div class="mt-4"> 11 <div class="mt-4">
19 <a-button type="primary" class="mr-4" @click="copyTbDeviceId">复制设备ID</a-button> 12 <a-button type="primary" class="mr-4" @click="copyTbDeviceId">复制设备ID</a-button>
@@ -23,14 +16,14 @@ @@ -23,14 +16,14 @@
23 </div> 16 </div>
24 <div v-if="deviceDetail?.deviceInfo?.address" class="mt-4"> 17 <div v-if="deviceDetail?.deviceInfo?.address" class="mt-4">
25 <p>设备位置</p> 18 <p>设备位置</p>
26 - <div ref="wrapRef" style="height: 400px; width: 100%"></div> 19 + <div ref="wrapRef" style="height: 550px; width: 100%"></div>
27 </div> 20 </div>
28 </div> 21 </div>
29 </template> 22 </template>
30 <script lang="ts"> 23 <script lang="ts">
31 import { defineComponent, ref, unref, nextTick } from 'vue'; 24 import { defineComponent, ref, unref, nextTick } from 'vue';
32 - import { Image, Table } from 'ant-design-vue';  
33 - import { columns } from '../../config/detail.config'; 25 + import { Image } from 'ant-design-vue';
  26 + import { descSchema } from '../../config/detail.config';
34 import { useScript } from '/@/hooks/web/useScript'; 27 import { useScript } from '/@/hooks/web/useScript';
35 import { useCopyToClipboard } from '/@/hooks/web/useCopyToClipboard'; 28 import { useCopyToClipboard } from '/@/hooks/web/useCopyToClipboard';
36 import { useMessage } from '/@/hooks/web/useMessage'; 29 import { useMessage } from '/@/hooks/web/useMessage';
@@ -38,10 +31,13 @@ @@ -38,10 +31,13 @@
38 import { useModal } from '/@/components/Modal'; 31 import { useModal } from '/@/components/Modal';
39 import ManageDeviceTokenModal from '../modal/ManageDeviceTokenModal.vue'; 32 import ManageDeviceTokenModal from '../modal/ManageDeviceTokenModal.vue';
40 import { getDeviceToken } from '/@/api/device/deviceManager'; 33 import { getDeviceToken } from '/@/api/device/deviceManager';
  34 + import { Description, useDescription } from '/@/components/Description';
  35 + import wz from '/@/assets/images/wz.png';
  36 +
41 export default defineComponent({ 37 export default defineComponent({
42 components: { 38 components: {
43 Image, 39 Image,
44 - Table, 40 + Description,
45 ManageDeviceTokenModal, 41 ManageDeviceTokenModal,
46 }, 42 },
47 props: { 43 props: {
@@ -51,6 +47,13 @@ @@ -51,6 +47,13 @@
51 }, 47 },
52 }, 48 },
53 setup(props) { 49 setup(props) {
  50 + console.log(props.deviceDetail);
  51 + const [register] = useDescription({
  52 + layout: 'vertical',
  53 + schema: descSchema,
  54 + column: 2,
  55 + });
  56 +
54 // 地图 57 // 地图
55 const wrapRef = ref<HTMLDivElement | null>(null); 58 const wrapRef = ref<HTMLDivElement | null>(null);
56 const { toPromise } = useScript({ src: BAI_DU_MAP_URL }); 59 const { toPromise } = useScript({ src: BAI_DU_MAP_URL });
@@ -62,7 +65,7 @@ @@ -62,7 +65,7 @@
62 const BMap = (window as any).BMap; 65 const BMap = (window as any).BMap;
63 if (!wrapEl) return; 66 if (!wrapEl) return;
64 const map = new BMap.Map(wrapEl); 67 const map = new BMap.Map(wrapEl);
65 - let myIcon = new BMap.Icon('/src/assets/images/wz.png', new BMap.Size(20, 30)); 68 + let myIcon = new BMap.Icon(wz, new BMap.Size(20, 30));
66 69
67 const point = new BMap.Point(Number(longitude), Number(latitude)); 70 const point = new BMap.Point(Number(longitude), Number(latitude));
68 var content = `我在 ${address}`; 71 var content = `我在 ${address}`;
@@ -107,13 +110,13 @@ @@ -107,13 +110,13 @@
107 }; 110 };
108 111
109 return { 112 return {
110 - columns,  
111 wrapRef, 113 wrapRef,
112 copyTbDeviceId, 114 copyTbDeviceId,
113 copyDeviceToken, 115 copyDeviceToken,
114 initMap, 116 initMap,
115 manageDeviceToken, 117 manageDeviceToken,
116 registerModal, 118 registerModal,
  119 + register,
117 }; 120 };
118 }, 121 },
119 }); 122 });
1 <template> 1 <template>
2 - <BasicTable @register="registerTable" /> 2 + <div style="background-color: #f0f2f5">
  3 + <BasicTable @register="registerTable" />
  4 + </div>
3 </template> 5 </template>
4 <script lang="ts"> 6 <script lang="ts">
5 import { defineComponent, reactive } from 'vue'; 7 import { defineComponent, reactive } from 'vue';
@@ -48,10 +50,25 @@ @@ -48,10 +50,25 @@
48 const { createMessage } = useMessage(); 50 const { createMessage } = useMessage();
49 const [registerTable] = useTable({ 51 const [registerTable] = useTable({
50 columns: realTimeDataColumns, 52 columns: realTimeDataColumns,
51 - showTableSetting: false, 53 + showTableSetting: true,
52 bordered: true, 54 bordered: true,
53 showIndexColumn: false, 55 showIndexColumn: false,
54 dataSource: state.recordList, 56 dataSource: state.recordList,
  57 + useSearchForm: true,
  58 + formConfig: {
  59 + labelWidth: 120,
  60 + schemas: [
  61 + {
  62 + field: 'icon',
  63 + label: '设备配置',
  64 + component: 'Select',
  65 + colProps: { span: 6 },
  66 + componentProps: {
  67 + maxLength: 255,
  68 + },
  69 + },
  70 + ],
  71 + },
55 }); 72 });
56 73
57 const { send, close } = useWebSocket(state.server, { 74 const { send, close } = useWebSocket(state.server, {
@@ -9,6 +9,14 @@ @@ -9,6 +9,14 @@
9 <BasicTable @register="registerTable" class="w-5/6 xl:w-4/5"> 9 <BasicTable @register="registerTable" class="w-5/6 xl:w-4/5">
10 <template #toolbar> 10 <template #toolbar>
11 <a-button type="primary" @click="handleCreate" v-if="authBtn(role)"> 新增设备 </a-button> 11 <a-button type="primary" @click="handleCreate" v-if="authBtn(role)"> 新增设备 </a-button>
  12 + <a-button
  13 + color="error"
  14 + v-if="authBtn(role)"
  15 + @click="handleDeleteOrBatchDelete(null)"
  16 + :disabled="hasBatchDelete"
  17 + >
  18 + 批量删除
  19 + </a-button>
12 </template> 20 </template>
13 <template #deviceProfile="{ record }"> 21 <template #deviceProfile="{ record }">
14 <a-button type="link" class="ml-2" @click="goDeviceProfile(record.deviceProfile.name)"> 22 <a-button type="link" class="ml-2" @click="goDeviceProfile(record.deviceProfile.name)">
@@ -85,7 +93,7 @@ @@ -85,7 +93,7 @@
85 color: 'error', 93 color: 'error',
86 popConfirm: { 94 popConfirm: {
87 title: '是否确认删除', 95 title: '是否确认删除',
88 - confirm: handleDelete.bind(null, record), 96 + confirm: handleDeleteOrBatchDelete.bind(null, record),
89 }, 97 },
90 }, 98 },
91 ]" 99 ]"
@@ -104,7 +112,6 @@ @@ -104,7 +112,6 @@
104 import { BasicTable, useTable, TableAction } from '/@/components/Table'; 112 import { BasicTable, useTable, TableAction } from '/@/components/Table';
105 import { columns, searchFormSchema } from './config/device.data'; 113 import { columns, searchFormSchema } from './config/device.data';
106 import { Tag } from 'ant-design-vue'; 114 import { Tag } from 'ant-design-vue';
107 - import { useMessage } from '/@/hooks/web/useMessage';  
108 import { 115 import {
109 deleteDevice, 116 deleteDevice,
110 devicePage, 117 devicePage,
@@ -125,6 +132,8 @@ @@ -125,6 +132,8 @@
125 import { USER_INFO_KEY } from '/@/enums/cacheEnum'; 132 import { USER_INFO_KEY } from '/@/enums/cacheEnum';
126 import { getAuthCache } from '/@/utils/auth'; 133 import { getAuthCache } from '/@/utils/auth';
127 import { authBtn } from '/@/enums/roleEnum'; 134 import { authBtn } from '/@/enums/roleEnum';
  135 + import { useBatchDelete } from '/@/hooks/web/useBatchDelete';
  136 +
128 export default defineComponent({ 137 export default defineComponent({
129 name: 'DeviceManagement', 138 name: 'DeviceManagement',
130 components: { 139 components: {
@@ -138,9 +147,11 @@ @@ -138,9 +147,11 @@
138 CustomerModal, 147 CustomerModal,
139 }, 148 },
140 setup(_) { 149 setup(_) {
141 - const { createMessage } = useMessage();  
142 const go = useGo(); 150 const go = useGo();
143 - 151 + const { hasBatchDelete, handleDeleteOrBatchDelete, selectionOptions } = useBatchDelete(
  152 + deleteDevice,
  153 + handleSuccess
  154 + );
144 const searchInfo = reactive<Recordable>({}); 155 const searchInfo = reactive<Recordable>({});
145 const { organizationIdTreeRef, resetFn } = useResetOrganizationTree(searchInfo); 156 const { organizationIdTreeRef, resetFn } = useResetOrganizationTree(searchInfo);
146 const [registerModal, { openModal }] = useModal(); 157 const [registerModal, { openModal }] = useModal();
@@ -166,6 +177,7 @@ @@ -166,6 +177,7 @@
166 slots: { customRender: 'action' }, 177 slots: { customRender: 'action' },
167 fixed: 'right', 178 fixed: 'right',
168 }, 179 },
  180 + ...selectionOptions,
169 }); 181 });
170 182
171 const userInfo: any = getAuthCache(USER_INFO_KEY); 183 const userInfo: any = getAuthCache(USER_INFO_KEY);
@@ -206,14 +218,6 @@ @@ -206,14 +218,6 @@
206 }); 218 });
207 } 219 }
208 220
209 - function handleDelete(record: Recordable) {  
210 - let ids = [record.id];  
211 - deleteDevice(ids).then(() => {  
212 - createMessage.success('删除设备成功');  
213 - handleSuccess();  
214 - });  
215 - }  
216 -  
217 function handleSuccess() { 221 function handleSuccess() {
218 reload(); 222 reload();
219 } 223 }
@@ -230,7 +234,6 @@ @@ -230,7 +234,6 @@
230 handleCreate, 234 handleCreate,
231 handleDetail, 235 handleDetail,
232 handleEdit, 236 handleEdit,
233 - handleDelete,  
234 handleSuccess, 237 handleSuccess,
235 goDeviceProfile, 238 goDeviceProfile,
236 handleSelect, 239 handleSelect,
@@ -245,6 +248,8 @@ @@ -245,6 +248,8 @@
245 registerCustomerModal, 248 registerCustomerModal,
246 authBtn, 249 authBtn,
247 role, 250 role,
  251 + handleDeleteOrBatchDelete,
  252 + hasBatchDelete,
248 }; 253 };
249 }, 254 },
250 }); 255 });
@@ -143,7 +143,7 @@ @@ -143,7 +143,7 @@
143 pagination: false, 143 pagination: false,
144 autoCreateKey: true, 144 autoCreateKey: true,
145 actionColumn: { 145 actionColumn: {
146 - width: 180, 146 + width: 200,
147 title: '操作', 147 title: '操作',
148 dataIndex: 'action', 148 dataIndex: 'action',
149 slots: { customRender: 'action' }, 149 slots: { customRender: 'action' },
@@ -2,7 +2,10 @@ @@ -2,7 +2,10 @@
2 <div> 2 <div>
3 <BasicTable @register="registerTable"> 3 <BasicTable @register="registerTable">
4 <template #toolbar> 4 <template #toolbar>
5 - <a-button type="primary" @click="handleCreate"> 新增配置 </a-button> 5 + <a-button type="primary" @click="handleCreate"> 新增消息配置 </a-button>
  6 + <a-button color="error" @click="handleDeleteOrBatchDelete(null)" :disabled="hasBatchDelete">
  7 + 批量删除
  8 + </a-button>
6 </template> 9 </template>
7 <template #config="{ record }"> 10 <template #config="{ record }">
8 <a-button type="link" class="ml-2" @click="showData(record)"> 查看配置 </a-button> 11 <a-button type="link" class="ml-2" @click="showData(record)"> 查看配置 </a-button>
@@ -21,7 +24,7 @@ @@ -21,7 +24,7 @@
21 color: 'error', 24 color: 'error',
22 popConfirm: { 25 popConfirm: {
23 title: '是否确认删除', 26 title: '是否确认删除',
24 - confirm: handleDelete.bind(null, record), 27 + confirm: handleDeleteOrBatchDelete.bind(null, record),
25 }, 28 },
26 ifShow: record.status == 0, 29 ifShow: record.status == 0,
27 }, 30 },
@@ -42,13 +45,16 @@ @@ -42,13 +45,16 @@
42 import { columns, searchFormSchema } from './config.data'; 45 import { columns, searchFormSchema } from './config.data';
43 import { Modal } from 'ant-design-vue'; 46 import { Modal } from 'ant-design-vue';
44 import { JsonPreview } from '/@/components/CodeEditor'; 47 import { JsonPreview } from '/@/components/CodeEditor';
45 - import { useMessage } from '/@/hooks/web/useMessage'; 48 + import { useBatchDelete } from '/@/hooks/web/useBatchDelete';
46 export default defineComponent({ 49 export default defineComponent({
47 name: 'MessageConfigManagement', 50 name: 'MessageConfigManagement',
48 components: { BasicTable, ConfigDrawer, TableAction }, 51 components: { BasicTable, ConfigDrawer, TableAction },
49 setup() { 52 setup() {
50 const [registerDrawer, { openDrawer }] = useDrawer(); 53 const [registerDrawer, { openDrawer }] = useDrawer();
51 - const { createMessage } = useMessage(); 54 + const { hasBatchDelete, handleDeleteOrBatchDelete, selectionOptions } = useBatchDelete(
  55 + deleteMessageConfig,
  56 + handleSuccess
  57 + );
52 const [registerTable, { reload }] = useTable({ 58 const [registerTable, { reload }] = useTable({
53 title: '消息配置列表', 59 title: '消息配置列表',
54 api: messageConfigPage, 60 api: messageConfigPage,
@@ -62,12 +68,13 @@ @@ -62,12 +68,13 @@
62 bordered: true, 68 bordered: true,
63 showIndexColumn: false, 69 showIndexColumn: false,
64 actionColumn: { 70 actionColumn: {
65 - width: 180, 71 + width: 200,
66 title: '操作', 72 title: '操作',
67 dataIndex: 'action', 73 dataIndex: 'action',
68 slots: { customRender: 'action' }, 74 slots: { customRender: 'action' },
69 fixed: 'right', 75 fixed: 'right',
70 }, 76 },
  77 + ...selectionOptions,
71 }); 78 });
72 79
73 function handleCreate() { 80 function handleCreate() {
@@ -83,14 +90,6 @@ @@ -83,14 +90,6 @@
83 }); 90 });
84 } 91 }
85 92
86 - function handleDelete(record: Recordable) {  
87 - let ids = [record.id];  
88 - deleteMessageConfig(ids).then((result) => {  
89 - createMessage.success(result.message);  
90 - handleSuccess();  
91 - });  
92 - }  
93 -  
94 function handleSuccess() { 93 function handleSuccess() {
95 reload(); 94 reload();
96 } 95 }
@@ -107,8 +106,9 @@ @@ -107,8 +106,9 @@
107 showData, 106 showData,
108 handleCreate, 107 handleCreate,
109 handleEdit, 108 handleEdit,
110 - handleDelete,  
111 handleSuccess, 109 handleSuccess,
  110 + hasBatchDelete,
  111 + handleDeleteOrBatchDelete,
112 }; 112 };
113 }, 113 },
114 }); 114 });
@@ -69,7 +69,7 @@ @@ -69,7 +69,7 @@
69 bordered: true, 69 bordered: true,
70 showIndexColumn: false, 70 showIndexColumn: false,
71 actionColumn: { 71 actionColumn: {
72 - width: 140, 72 + width: 200,
73 title: '操作', 73 title: '操作',
74 dataIndex: 'action', 74 dataIndex: 'action',
75 slots: { customRender: 'action' }, 75 slots: { customRender: 'action' },
@@ -67,7 +67,7 @@ @@ -67,7 +67,7 @@
67 bordered: true, 67 bordered: true,
68 showIndexColumn: false, 68 showIndexColumn: false,
69 actionColumn: { 69 actionColumn: {
70 - width: 140, 70 + width: 200,
71 title: '操作', 71 title: '操作',
72 dataIndex: 'action', 72 dataIndex: 'action',
73 slots: { customRender: 'action' }, 73 slots: { customRender: 'action' },
@@ -2,7 +2,10 @@ @@ -2,7 +2,10 @@
2 <div> 2 <div>
3 <BasicTable @register="registerTable"> 3 <BasicTable @register="registerTable">
4 <template #toolbar> 4 <template #toolbar>
5 - <a-button type="primary" @click="handleCreate"> 新增模板 </a-button> 5 + <a-button type="primary" @click="handleCreate"> 新增消息模板 </a-button>
  6 + <a-button color="error" @click="handleDeleteOrBatchDelete(null)" :disabled="hasBatchDelete">
  7 + 批量删除
  8 + </a-button>
6 </template> 9 </template>
7 <template #config="{ record }"> 10 <template #config="{ record }">
8 <a-button type="link" class="ml-2" @click="goConfig"> 11 <a-button type="link" class="ml-2" @click="goConfig">
@@ -28,7 +31,7 @@ @@ -28,7 +31,7 @@
28 color: 'error', 31 color: 'error',
29 popConfirm: { 32 popConfirm: {
30 title: '是否确认删除', 33 title: '是否确认删除',
31 - confirm: handleDelete.bind(null, record), 34 + confirm: handleDeleteOrBatchDelete.bind(null, record),
32 }, 35 },
33 }, 36 },
34 ]" 37 ]"
@@ -47,7 +50,6 @@ @@ -47,7 +50,6 @@
47 import { useDrawer } from '/@/components/Drawer'; 50 import { useDrawer } from '/@/components/Drawer';
48 import TemplateDrawer from './TemplateDrawer.vue'; 51 import TemplateDrawer from './TemplateDrawer.vue';
49 import { columns, searchFormSchema } from './template.data'; 52 import { columns, searchFormSchema } from './template.data';
50 - import { useMessage } from '/@/hooks/web/useMessage';  
51 import { deleteMessageTemplate, messageTemplatePage } from '/@/api/message/template'; 53 import { deleteMessageTemplate, messageTemplatePage } from '/@/api/message/template';
52 import { useGo } from '/@/hooks/web/usePage'; 54 import { useGo } from '/@/hooks/web/usePage';
53 import { PageEnum } from '/@/enums/pageEnum'; 55 import { PageEnum } from '/@/enums/pageEnum';
@@ -55,6 +57,7 @@ @@ -55,6 +57,7 @@
55 import SendSms from '/@/views/message/template/SendSms.vue'; 57 import SendSms from '/@/views/message/template/SendSms.vue';
56 import { MessageEnum } from '/@/enums/messageEnum'; 58 import { MessageEnum } from '/@/enums/messageEnum';
57 import SendEmail from '/@/views/message/template/SendEmail.vue'; 59 import SendEmail from '/@/views/message/template/SendEmail.vue';
  60 + import { useBatchDelete } from '/@/hooks/web/useBatchDelete';
58 61
59 export default defineComponent({ 62 export default defineComponent({
60 name: 'MessageTemplateManagement', 63 name: 'MessageTemplateManagement',
@@ -64,7 +67,10 @@ @@ -64,7 +67,10 @@
64 const [registerMailModal, { openModal: openMailModal }] = useModal(); 67 const [registerMailModal, { openModal: openMailModal }] = useModal();
65 const go = useGo(); 68 const go = useGo();
66 const [registerDrawer, { openDrawer }] = useDrawer(); 69 const [registerDrawer, { openDrawer }] = useDrawer();
67 - const { createMessage } = useMessage(); 70 + const { hasBatchDelete, handleDeleteOrBatchDelete, selectionOptions } = useBatchDelete(
  71 + deleteMessageTemplate,
  72 + handleSuccess
  73 + );
68 const [registerTable, { reload }] = useTable({ 74 const [registerTable, { reload }] = useTable({
69 title: '消息模板列表', 75 title: '消息模板列表',
70 api: messageTemplatePage, 76 api: messageTemplatePage,
@@ -78,12 +84,13 @@ @@ -78,12 +84,13 @@
78 bordered: true, 84 bordered: true,
79 showIndexColumn: false, 85 showIndexColumn: false,
80 actionColumn: { 86 actionColumn: {
81 - width: 180, 87 + width: 200,
82 title: '操作', 88 title: '操作',
83 dataIndex: 'action', 89 dataIndex: 'action',
84 slots: { customRender: 'action' }, 90 slots: { customRender: 'action' },
85 fixed: 'right', 91 fixed: 'right',
86 }, 92 },
  93 + ...selectionOptions,
87 }); 94 });
88 95
89 function handleCreate() { 96 function handleCreate() {
@@ -119,15 +126,6 @@ @@ -119,15 +126,6 @@
119 }); 126 });
120 } 127 }
121 } 128 }
122 -  
123 - function handleDelete(record: Recordable) {  
124 - let ids = [record.id];  
125 - deleteMessageTemplate(ids).then((result) => {  
126 - createMessage.success(result.message);  
127 - handleSuccess();  
128 - });  
129 - }  
130 -  
131 function handleSuccess() { 129 function handleSuccess() {
132 reload(); 130 reload();
133 } 131 }
@@ -141,10 +139,11 @@ @@ -141,10 +139,11 @@
141 registerMailModal, 139 registerMailModal,
142 handleCreate, 140 handleCreate,
143 handleEdit, 141 handleEdit,
144 - handleDelete,  
145 handleSuccess, 142 handleSuccess,
146 handleModal, 143 handleModal,
147 goConfig, 144 goConfig,
  145 + hasBatchDelete,
  146 + handleDeleteOrBatchDelete,
148 }; 147 };
149 }, 148 },
150 }); 149 });
@@ -96,7 +96,7 @@ @@ -96,7 +96,7 @@
96 bordered: true, 96 bordered: true,
97 showIndexColumn: false, 97 showIndexColumn: false,
98 actionColumn: { 98 actionColumn: {
99 - width: 180, 99 + width: 200,
100 title: '操作', 100 title: '操作',
101 dataIndex: 'action', 101 dataIndex: 'action',
102 slots: { customRender: 'action' }, 102 slots: { customRender: 'action' },
@@ -7,12 +7,8 @@ @@ -7,12 +7,8 @@
7 > 7 >
8 <template #toolbar> 8 <template #toolbar>
9 <a-button type="primary" @click="handleAdd"> 新增场景联动 </a-button> 9 <a-button type="primary" @click="handleAdd"> 新增场景联动 </a-button>
10 - <a-button  
11 - style="background-color: rgba(237, 111, 111, 1)"  
12 - type="default"  
13 - @click="handleToolbarDel"  
14 - >  
15 - <span style="color: white">删除</span> 10 + <a-button color="error" @click="handleDeleteOrBatchDelete(null)" :disabled="hasBatchDelete">
  11 + 批量删除
16 </a-button> 12 </a-button>
17 </template> 13 </template>
18 <template #action="{ record }"> 14 <template #action="{ record }">
@@ -29,7 +25,7 @@ @@ -29,7 +25,7 @@
29 color: 'error', 25 color: 'error',
30 popConfirm: { 26 popConfirm: {
31 title: '是否确认删除', 27 title: '是否确认删除',
32 - confirm: handleDelete.bind(null, record), 28 + confirm: handleDeleteOrBatchDelete.bind(null, record),
33 }, 29 },
34 }, 30 },
35 ]" 31 ]"
@@ -52,6 +48,7 @@ @@ -52,6 +48,7 @@
52 import { columns, searchFormSchema } from './config'; 48 import { columns, searchFormSchema } from './config';
53 import { useMessage } from '/@/hooks/web/useMessage'; 49 import { useMessage } from '/@/hooks/web/useMessage';
54 import { screenLinkPageGetApi, screenLinkPageDeleteApi } from '/@/api/ruleengine/ruleengineApi'; 50 import { screenLinkPageGetApi, screenLinkPageDeleteApi } from '/@/api/ruleengine/ruleengineApi';
  51 + import { useBatchDelete } from '/@/hooks/web/useBatchDelete';
55 52
56 export default defineComponent({ 53 export default defineComponent({
57 name: 'Index', 54 name: 'Index',
@@ -60,31 +57,34 @@ @@ -60,31 +57,34 @@
60 setup() { 57 setup() {
61 const { proxy } = getCurrentInstance(); 58 const { proxy } = getCurrentInstance();
62 const sceneLinkAgeDrawerRef: any = ref(null); 59 const sceneLinkAgeDrawerRef: any = ref(null);
  60 + const { hasBatchDelete, handleDeleteOrBatchDelete, selectionOptions } = useBatchDelete(
  61 + screenLinkPageDeleteApi,
  62 + handleSuccess
  63 + );
63 let selectedRowKeys: Array<string> = []; 64 let selectedRowKeys: Array<string> = [];
64 let echoEditData = reactive({}); 65 let echoEditData = reactive({});
65 const [registerDrawer, { openDrawer }] = useDrawer(); 66 const [registerDrawer, { openDrawer }] = useDrawer();
66 const { createMessage } = useMessage(); 67 const { createMessage } = useMessage();
67 const [registerTable, { reload, getSelectRowKeys }] = useTable({ 68 const [registerTable, { reload, getSelectRowKeys }] = useTable({
68 title: '场景联动列表', 69 title: '场景联动列表',
69 - clickToRowSelect: false,  
70 api: screenLinkPageGetApi, 70 api: screenLinkPageGetApi,
71 columns, 71 columns,
72 formConfig: { 72 formConfig: {
73 labelWidth: 120, 73 labelWidth: 120,
74 schemas: searchFormSchema, 74 schemas: searchFormSchema,
75 }, 75 },
76 - rowKey: 'id',  
77 useSearchForm: true, 76 useSearchForm: true,
78 showTableSetting: true, 77 showTableSetting: true,
79 bordered: true, 78 bordered: true,
80 showIndexColumn: false, 79 showIndexColumn: false,
81 actionColumn: { 80 actionColumn: {
82 - width: 180, 81 + width: 200,
83 title: '操作', 82 title: '操作',
84 dataIndex: 'action', 83 dataIndex: 'action',
85 slots: { customRender: 'action' }, 84 slots: { customRender: 'action' },
86 fixed: 'right', 85 fixed: 'right',
87 }, 86 },
  87 + ...selectionOptions,
88 }); 88 });
89 89
90 function handleAdd() { 90 function handleAdd() {
@@ -146,6 +146,8 @@ @@ -146,6 +146,8 @@
146 handleEdit, 146 handleEdit,
147 handleDelete, 147 handleDelete,
148 handleSuccess, 148 handleSuccess,
  149 + hasBatchDelete,
  150 + handleDeleteOrBatchDelete,
149 }; 151 };
150 }, 152 },
151 }); 153 });
@@ -41,7 +41,7 @@ @@ -41,7 +41,7 @@
41 bordered: true, 41 bordered: true,
42 showIndexColumn: false, 42 showIndexColumn: false,
43 actionColumn: { 43 actionColumn: {
44 - width: 180, 44 + width: 200,
45 title: '操作', 45 title: '操作',
46 dataIndex: 'action', 46 dataIndex: 'action',
47 slots: { customRender: 'action' }, 47 slots: { customRender: 'action' },
@@ -2,8 +2,8 @@ @@ -2,8 +2,8 @@
2 <div> 2 <div>
3 <BasicTable @register="registerTable"> 3 <BasicTable @register="registerTable">
4 <template #toolbar> 4 <template #toolbar>
5 - <a-button type="primary" @click="handleAdd"> 新增 </a-button>  
6 - <a-button color="error" @click="handleToolbarDel" :disabled="hasBatchDelete"> 5 + <a-button type="primary" @click="handleAdd">新增通知</a-button>
  6 + <a-button color="error" @click="handleDeleteOrBatchDelete(null)" :disabled="hasBatchDelete">
7 批量删除 7 批量删除
8 </a-button> 8 </a-button>
9 </template> 9 </template>
@@ -32,7 +32,7 @@ @@ -32,7 +32,7 @@
32 color: 'error', 32 color: 'error',
33 popConfirm: { 33 popConfirm: {
34 title: '是否确认删除', 34 title: '是否确认删除',
35 - confirm: handleDelete.bind(null, record), 35 + confirm: handleDeleteOrBatchDelete.bind(null, record),
36 }, 36 },
37 }, 37 },
38 ]" 38 ]"
@@ -44,14 +44,14 @@ @@ -44,14 +44,14 @@
44 </div> 44 </div>
45 </template> 45 </template>
46 <script lang="ts"> 46 <script lang="ts">
47 - import { defineComponent, computed, unref, ref } from 'vue'; 47 + import { defineComponent } from 'vue';
48 import { BasicTable, useTable, TableAction } from '/@/components/Table'; 48 import { BasicTable, useTable, TableAction } from '/@/components/Table';
49 import { useDrawer } from '/@/components/Drawer'; 49 import { useDrawer } from '/@/components/Drawer';
50 import NotifyManagerDrawer from './useDrawer.vue'; 50 import NotifyManagerDrawer from './useDrawer.vue';
51 import tableViewChild from './viewDetailDrawer.vue'; 51 import tableViewChild from './viewDetailDrawer.vue';
52 import { columns, searchFormSchema } from './config.d'; 52 import { columns, searchFormSchema } from './config.d';
53 - import { useMessage } from '/@/hooks/web/useMessage';  
54 import { notifyGetTableApi, notifyDeleteApi } from '/@/api/stationnotification/stationnotifyApi'; 53 import { notifyGetTableApi, notifyDeleteApi } from '/@/api/stationnotification/stationnotifyApi';
  54 + import { useBatchDelete } from '/@/hooks/web/useBatchDelete';
55 55
56 export default defineComponent({ 56 export default defineComponent({
57 name: 'Notificationmannager', 57 name: 'Notificationmannager',
@@ -59,45 +59,31 @@ @@ -59,45 +59,31 @@
59 setup() { 59 setup() {
60 const [registerDrawer, { openDrawer }] = useDrawer(); 60 const [registerDrawer, { openDrawer }] = useDrawer();
61 const [registerAdd, { openDrawer: openDrawerAdd }] = useDrawer(); 61 const [registerAdd, { openDrawer: openDrawerAdd }] = useDrawer();
62 - const { createMessage } = useMessage();  
63 - // 批量删除  
64 - const selectedRowIds = ref<string[]>([]);  
65 - const hasBatchDelete = computed(() => unref(selectedRowIds).length <= 0);  
66 - const onSelectRowChange = (selectedRowKeys: string[]) => {  
67 - selectedRowIds.value = selectedRowKeys;  
68 - console.log(selectedRowKeys);  
69 - };  
70 - async function handleToolbarDel() {  
71 - await notifyDeleteApi(selectedRowIds.value);  
72 - createMessage.success('批量删除成功');  
73 - selectedRowIds.value = [];  
74 - reload();  
75 - }  
76 62
  63 + // 批量删除
  64 + const { hasBatchDelete, handleDeleteOrBatchDelete, selectionOptions } = useBatchDelete(
  65 + notifyDeleteApi,
  66 + handleSuccess
  67 + );
77 const [registerTable, { reload }] = useTable({ 68 const [registerTable, { reload }] = useTable({
78 - clickToRowSelect: false,  
79 api: notifyGetTableApi, 69 api: notifyGetTableApi,
80 columns, 70 columns,
81 formConfig: { 71 formConfig: {
82 labelWidth: 120, 72 labelWidth: 120,
83 schemas: searchFormSchema, 73 schemas: searchFormSchema,
84 }, 74 },
85 - rowSelection: {  
86 - onChange: onSelectRowChange,  
87 - type: 'checkbox',  
88 - },  
89 - rowKey: 'id',  
90 useSearchForm: true, 75 useSearchForm: true,
91 showTableSetting: true, 76 showTableSetting: true,
92 bordered: true, 77 bordered: true,
93 showIndexColumn: false, 78 showIndexColumn: false,
94 actionColumn: { 79 actionColumn: {
95 - width: 180, 80 + width: 200,
96 title: '操作', 81 title: '操作',
97 dataIndex: 'action', 82 dataIndex: 'action',
98 slots: { customRender: 'action' }, 83 slots: { customRender: 'action' },
99 fixed: 'right', 84 fixed: 'right',
100 }, 85 },
  86 + ...selectionOptions,
101 }); 87 });
102 88
103 function handleAdd() { 89 function handleAdd() {
@@ -117,12 +103,6 @@ @@ -117,12 +103,6 @@
117 isUpdate: true, 103 isUpdate: true,
118 }); 104 });
119 } 105 }
120 - async function handleDelete(record: Recordable) {  
121 - let ids = [record.id];  
122 - await notifyDeleteApi(ids);  
123 - createMessage.success('删除成功');  
124 - reload();  
125 - }  
126 function handleSuccess() { 106 function handleSuccess() {
127 reload(); 107 reload();
128 } 108 }
@@ -133,11 +113,9 @@ @@ -133,11 +113,9 @@
133 registerTable, 113 registerTable,
134 registerDrawer, 114 registerDrawer,
135 handleAdd, 115 handleAdd,
136 - handleToolbarDel,  
137 handleEdit, 116 handleEdit,
138 - handleDelete,  
139 handleSuccess, 117 handleSuccess,
140 - onSelectRowChange, 118 + handleDeleteOrBatchDelete,
141 }; 119 };
142 }, 120 },
143 }); 121 });
@@ -3,27 +3,21 @@ @@ -3,27 +3,21 @@
3 <BasicDrawer 3 <BasicDrawer
4 v-bind="$attrs" 4 v-bind="$attrs"
5 @register="registerDrawer" 5 @register="registerDrawer"
6 - :showFooter="false"  
7 :title="getTitle" 6 :title="getTitle"
8 width="800px" 7 width="800px"
  8 + showFooter
9 > 9 >
10 - <BasicForm :showResetButton="false" :showSubmitButton="false" @register="registerForm">  
11 - <template #add>  
12 - <Button style="margin-left: 30px; margin-top: 80px" type="primary" @click="handleCancel"  
13 - >取消</Button  
14 - >  
15 - <Button style="margin-left: 30px" type="primary" @click="handleSaveDraft"  
16 - >保存草稿</Button  
17 - >  
18 - <Button style="margin-left: 30px" type="primary" @click="handleSend">发布通知</Button>  
19 - </template>  
20 - </BasicForm> 10 + <BasicForm @register="registerForm" />
  11 + <template #footer>
  12 + <a-button @click="handleCancel">取消</a-button>
  13 + <a-button @click="handleSaveDraft">保存草稿</a-button>
  14 + <a-button type="primary" @click="handleSend">发布通知</a-button>
  15 + </template>
21 </BasicDrawer> 16 </BasicDrawer>
22 </div> 17 </div>
23 </template> 18 </template>
24 <script lang="ts"> 19 <script lang="ts">
25 import { defineComponent, computed, unref, ref } from 'vue'; 20 import { defineComponent, computed, unref, ref } from 'vue';
26 - import { Button } from '/@/components/Button';  
27 import { BasicForm, useForm } from '/@/components/Form'; 21 import { BasicForm, useForm } from '/@/components/Form';
28 import { formSchema } from './config.d'; 22 import { formSchema } from './config.d';
29 import { BasicDrawer, useDrawerInner } from '/@/components/Drawer'; 23 import { BasicDrawer, useDrawerInner } from '/@/components/Drawer';
@@ -34,7 +28,7 @@ @@ -34,7 +28,7 @@
34 import { useMessage } from '/@/hooks/web/useMessage'; 28 import { useMessage } from '/@/hooks/web/useMessage';
35 export default defineComponent({ 29 export default defineComponent({
36 name: 'ConfigDrawer', 30 name: 'ConfigDrawer',
37 - components: { BasicDrawer, BasicForm, Button }, 31 + components: { BasicDrawer, BasicForm },
38 emits: ['success', 'register'], 32 emits: ['success', 'register'],
39 setup(_, { emit }) { 33 setup(_, { emit }) {
40 const { createMessage } = useMessage(); 34 const { createMessage } = useMessage();
@@ -54,6 +48,7 @@ @@ -54,6 +48,7 @@
54 noticeId.value = data.record.id; 48 noticeId.value = data.record.id;
55 Reflect.set(data.record, 'receiverType', data.record.receiverType === '全部' ? '0' : '1'); 49 Reflect.set(data.record, 'receiverType', data.record.receiverType === '全部' ? '0' : '1');
56 if (data.record.receiverType === '1') { 50 if (data.record.receiverType === '1') {
  51 + if (!data.record.pointId.length) return;
57 const organizationId = data.record.pointId.split(','); 52 const organizationId = data.record.pointId.split(',');
58 Reflect.set(data.record, 'organizationId', organizationId); 53 Reflect.set(data.record, 'organizationId', organizationId);
59 } 54 }
@@ -108,7 +103,7 @@ @@ -108,7 +103,7 @@
108 createMessage.success('保存草稿成功'); 103 createMessage.success('保存草稿成功');
109 }; 104 };
110 const handleCancel = () => { 105 const handleCancel = () => {
111 - resetFields(); 106 + // resetFields();
112 closeDrawer(); 107 closeDrawer();
113 }; 108 };
114 return { 109 return {
@@ -71,7 +71,7 @@ @@ -71,7 +71,7 @@
71 api: getNotifyDetailPage, 71 api: getNotifyDetailPage,
72 columns: detailColumns, 72 columns: detailColumns,
73 bordered: true, 73 bordered: true,
74 - showTableSetting: false, 74 + showTableSetting: true,
75 showIndexColumn: false, 75 showIndexColumn: false,
76 immediate: false, 76 immediate: false,
77 beforeFetch: getNoticeId, 77 beforeFetch: getNoticeId,
@@ -49,7 +49,7 @@ @@ -49,7 +49,7 @@
49 title: t('sys.errorLog.tableTitle'), 49 title: t('sys.errorLog.tableTitle'),
50 columns: getColumns(), 50 columns: getColumns(),
51 actionColumn: { 51 actionColumn: {
52 - width: 80, 52 + width: 200,
53 title: 'Action', 53 title: 'Action',
54 dataIndex: 'action', 54 dataIndex: 'action',
55 slots: { customRender: 'action' }, 55 slots: { customRender: 'action' },
1 <template> 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 </div> 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 </div> 43 </div>
38 </div> 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 </div> 45 </div>
51 </div> 46 </div>
52 </template> 47 </template>
@@ -59,76 +54,162 @@ @@ -59,76 +54,162 @@
59 import RegisterForm from './RegisterForm.vue'; 54 import RegisterForm from './RegisterForm.vue';
60 import MobileForm from './MobileForm.vue'; 55 import MobileForm from './MobileForm.vue';
61 import QrCodeForm from './QrCodeForm.vue'; 56 import QrCodeForm from './QrCodeForm.vue';
  57 + import { useGlobSetting } from '/@/hooks/setting';
  58 + import { useI18n } from '/@/hooks/web/useI18n';
62 import { useDesign } from '/@/hooks/web/useDesign'; 59 import { useDesign } from '/@/hooks/web/useDesign';
63 import { useLocaleStore } from '/@/store/modules/locale'; 60 import { useLocaleStore } from '/@/store/modules/locale';
64 import { useUserStore } from '/@/store/modules/user'; 61 import { useUserStore } from '/@/store/modules/user';
65 -  
66 defineProps({ 62 defineProps({
67 sessionTimeout: { 63 sessionTimeout: {
68 type: Boolean, 64 type: Boolean,
69 }, 65 },
70 }); 66 });
71 67
  68 + const globSetting = useGlobSetting();
72 const { prefixCls } = useDesign('login'); 69 const { prefixCls } = useDesign('login');
  70 + const { t } = useI18n();
73 const localeStore = useLocaleStore(); 71 const localeStore = useLocaleStore();
74 const showLocale = localeStore.getShowPicker; 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 </script> 74 </script>
87 <style lang="less"> 75 <style lang="less">
88 @prefix-cls: ~'@{namespace}-login'; 76 @prefix-cls: ~'@{namespace}-login';
89 @logo-prefix-cls: ~'@{namespace}-app-logo'; 77 @logo-prefix-cls: ~'@{namespace}-app-logo';
90 @countdown-prefix-cls: ~'@{namespace}-countdown-input'; 78 @countdown-prefix-cls: ~'@{namespace}-countdown-input';
91 @dark-bg: #293146; 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 width: 100%; 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 position: absolute; 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 </style> 215 </style>
1 <template> 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 </Button> 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 </template> 63 </template>
79 <script lang="ts" setup> 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 import LoginFormTitle from './LoginFormTitle.vue'; 67 import LoginFormTitle from './LoginFormTitle.vue';
84 68
85 import { useI18n } from '/@/hooks/web/useI18n'; 69 import { useI18n } from '/@/hooks/web/useI18n';
@@ -98,12 +82,14 @@ @@ -98,12 +82,14 @@
98 const { t } = useI18n(); 82 const { t } = useI18n();
99 const { notification, createErrorModal } = useMessage(); 83 const { notification, createErrorModal } = useMessage();
100 const { prefixCls } = useDesign('login'); 84 const { prefixCls } = useDesign('login');
  85 + const userStore = useUserStore();
101 86
102 const { setLoginState, getLoginState } = useLoginState(); 87 const { setLoginState, getLoginState } = useLoginState();
103 const { getFormRules } = useFormRules(); 88 const { getFormRules } = useFormRules();
104 - const userStore = useUserStore(); 89 +
105 const formRef = ref(); 90 const formRef = ref();
106 const loading = ref(false); 91 const loading = ref(false);
  92 + const rememberMe = ref(false);
107 93
108 const formData = reactive({ 94 const formData = reactive({
109 account: 'sysadmin', 95 account: 'sysadmin',
@@ -112,8 +98,6 @@ @@ -112,8 +98,6 @@
112 98
113 const { validForm } = useFormValid(formRef); 99 const { validForm } = useFormValid(formRef);
114 100
115 - //onKeyStroke('Enter', handleLogin);  
116 -  
117 const getShow = computed(() => unref(getLoginState) === LoginStateEnum.LOGIN); 101 const getShow = computed(() => unref(getLoginState) === LoginStateEnum.LOGIN);
118 const storage = createLocalStorage(); 102 const storage = createLocalStorage();
119 async function handleLogin() { 103 async function handleLogin() {
@@ -121,13 +105,11 @@ @@ -121,13 +105,11 @@
121 if (!data) return; 105 if (!data) return;
122 try { 106 try {
123 loading.value = true; 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 if (userInfo) { 113 if (userInfo) {
132 notification.success({ 114 notification.success({
133 message: t('sys.login.loginSuccessTitle'), 115 message: t('sys.login.loginSuccessTitle'),
@@ -145,15 +127,10 @@ @@ -145,15 +127,10 @@
145 link.href = res.icon ?? '/favicon.ico'; 127 link.href = res.icon ?? '/favicon.ico';
146 document.getElementsByTagName('head')[0].appendChild(link); 128 document.getElementsByTagName('head')[0].appendChild(link);
147 } 129 }
148 - } catch (error: any) { 130 + } catch (error) {
149 createErrorModal({ 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 getContainer: () => document.body.querySelector(`.${prefixCls}`) || document.body, 134 getContainer: () => document.body.querySelector(`.${prefixCls}`) || document.body,
158 }); 135 });
159 } finally { 136 } finally {
1 <template> 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 {{ getFormTitle }} 3 {{ getFormTitle }}
6 </h2> 4 </h2>
7 </template> 5 </template>
@@ -21,14 +21,7 @@ @@ -21,14 +21,7 @@
21 </FormItem> 21 </FormItem>
22 22
23 <FormItem class="enter-x"> 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 {{ t('sys.login.loginButton') }} 25 {{ t('sys.login.loginButton') }}
33 </Button> 26 </Button>
34 <Button size="large" block class="mt-4" @click="handleBackLogin"> 27 <Button size="large" block class="mt-4" @click="handleBackLogin">
@@ -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-center" 7 + class="enter-x flex justify-center xl:justify-start"
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>
@@ -9,6 +9,13 @@ @@ -9,6 +9,13 @@
9 <BasicTable @register="registerTable" class="w-3/4 xl:w-4/5"> 9 <BasicTable @register="registerTable" class="w-3/4 xl:w-4/5">
10 <template #toolbar> 10 <template #toolbar>
11 <a-button type="primary" @click="handleCreate">新增账号</a-button> 11 <a-button type="primary" @click="handleCreate">新增账号</a-button>
  12 + <a-button
  13 + color="error"
  14 + @click="handleDeleteOrBatchDelete(null)"
  15 + :disabled="hasBatchDelete"
  16 + >
  17 + 批量删除
  18 + </a-button>
12 </template> 19 </template>
13 <template #status="{ record }"> 20 <template #status="{ record }">
14 <Tag 21 <Tag
@@ -54,7 +61,7 @@ @@ -54,7 +61,7 @@
54 ifShow: record.level != 0, 61 ifShow: record.level != 0,
55 popConfirm: { 62 popConfirm: {
56 title: '是否确认删除', 63 title: '是否确认删除',
57 - confirm: handleDelete.bind(null, record), 64 + confirm: handleDeleteOrBatchDelete.bind(null, record),
58 }, 65 },
59 }, 66 },
60 ]" 67 ]"
@@ -74,18 +81,19 @@ @@ -74,18 +81,19 @@
74 import { Tag } from 'ant-design-vue'; 81 import { Tag } from 'ant-design-vue';
75 import { useModal } from '/@/components/Modal'; 82 import { useModal } from '/@/components/Modal';
76 import AccountModal from './AccountModal.vue'; 83 import AccountModal from './AccountModal.vue';
77 -  
78 import { columns, searchFormSchema } from './account.data'; 84 import { columns, searchFormSchema } from './account.data';
79 import { useGo } from '/@/hooks/web/usePage'; 85 import { useGo } from '/@/hooks/web/usePage';
80 - import { useMessage } from '/@/hooks/web/useMessage';  
81 - 86 + import { useBatchDelete } from '/@/hooks/web/useBatchDelete';
82 export default defineComponent({ 87 export default defineComponent({
83 name: 'AccountManagement', 88 name: 'AccountManagement',
84 components: { BasicTable, PageWrapper, OrganizationIdTree, AccountModal, TableAction, Tag }, 89 components: { BasicTable, PageWrapper, OrganizationIdTree, AccountModal, TableAction, Tag },
85 setup() { 90 setup() {
86 const go = useGo(); 91 const go = useGo();
  92 + const { hasBatchDelete, handleDeleteOrBatchDelete, selectionOptions } = useBatchDelete(
  93 + deleteUser,
  94 + handleSuccess
  95 + );
87 const [registerModal, { openModal }] = useModal(); 96 const [registerModal, { openModal }] = useModal();
88 - const { createMessage } = useMessage();  
89 let searchInfo = reactive<Recordable>({}); 97 let searchInfo = reactive<Recordable>({});
90 const { organizationIdTreeRef, resetFn } = useResetOrganizationTree(searchInfo); 98 const { organizationIdTreeRef, resetFn } = useResetOrganizationTree(searchInfo);
91 const [registerTable, { reload }] = useTable({ 99 const [registerTable, { reload }] = useTable({
@@ -103,13 +111,13 @@ @@ -103,13 +111,13 @@
103 useSearchForm: true, 111 useSearchForm: true,
104 showTableSetting: true, 112 showTableSetting: true,
105 bordered: true, 113 bordered: true,
106 -  
107 actionColumn: { 114 actionColumn: {
108 - width: 220, 115 + width: 200,
109 title: '操作', 116 title: '操作',
110 dataIndex: 'action', 117 dataIndex: 'action',
111 slots: { customRender: 'action' }, 118 slots: { customRender: 'action' },
112 }, 119 },
  120 + ...selectionOptions,
113 }); 121 });
114 122
115 function handleCreate() { 123 function handleCreate() {
@@ -123,15 +131,6 @@ @@ -123,15 +131,6 @@
123 isUpdate: true, 131 isUpdate: true,
124 }); 132 });
125 } 133 }
126 -  
127 - function handleDelete(record: Recordable) {  
128 - let ids = [record.id];  
129 - deleteUser(ids).then(() => {  
130 - createMessage.success('删除成功');  
131 - reload();  
132 - });  
133 - }  
134 -  
135 function handleSuccess() { 134 function handleSuccess() {
136 reload(); 135 reload();
137 } 136 }
@@ -150,11 +149,12 @@ @@ -150,11 +149,12 @@
150 registerModal, 149 registerModal,
151 handleCreate, 150 handleCreate,
152 handleEdit, 151 handleEdit,
153 - handleDelete,  
154 handleSuccess, 152 handleSuccess,
155 handleSelect, 153 handleSelect,
156 handleView, 154 handleView,
157 organizationIdTreeRef, 155 organizationIdTreeRef,
  156 + hasBatchDelete,
  157 + handleDeleteOrBatchDelete,
158 }; 158 };
159 }, 159 },
160 }); 160 });
@@ -3,6 +3,9 @@ @@ -3,6 +3,9 @@
3 <BasicTable @register="registerTable"> 3 <BasicTable @register="registerTable">
4 <template #toolbar> 4 <template #toolbar>
5 <a-button type="primary" @click="handleCreate"> 新增字典 </a-button> 5 <a-button type="primary" @click="handleCreate"> 新增字典 </a-button>
  6 + <a-button color="error" @click="handleDeleteOrBatchDelete(null)" :disabled="hasBatchDelete">
  7 + 批量删除
  8 + </a-button>
6 </template> 9 </template>
7 <template #action="{ record }"> 10 <template #action="{ record }">
8 <TableAction 11 <TableAction
@@ -23,7 +26,7 @@ @@ -23,7 +26,7 @@
23 color: 'error', 26 color: 'error',
24 popConfirm: { 27 popConfirm: {
25 title: '是否确认删除', 28 title: '是否确认删除',
26 - confirm: handleDelete.bind(null, record), 29 + confirm: handleDeleteOrBatchDelete.bind(null, record),
27 }, 30 },
28 }, 31 },
29 ]" 32 ]"
@@ -51,15 +54,19 @@ @@ -51,15 +54,19 @@
51 54
52 import { columns, searchFormSchema } from './dict.data'; 55 import { columns, searchFormSchema } from './dict.data';
53 import { Tag } from 'ant-design-vue'; 56 import { Tag } from 'ant-design-vue';
54 - import { useMessage } from '/@/hooks/web/useMessage'; 57 +
  58 + import { useBatchDelete } from '/@/hooks/web/useBatchDelete';
55 59
56 export default defineComponent({ 60 export default defineComponent({
57 name: 'DictManagement', 61 name: 'DictManagement',
58 components: { BasicTable, DictDrawer, ItemIndex, TableAction, Tag }, 62 components: { BasicTable, DictDrawer, ItemIndex, TableAction, Tag },
59 setup() { 63 setup() {
60 - const { createMessage } = useMessage();  
61 const [registerDrawer, { openDrawer: openDrawer }] = useDrawer(); 64 const [registerDrawer, { openDrawer: openDrawer }] = useDrawer();
62 const [registerItemDrawer, { openDrawer: openItemDrawer }] = useDrawer(); 65 const [registerItemDrawer, { openDrawer: openItemDrawer }] = useDrawer();
  66 + const { hasBatchDelete, handleDeleteOrBatchDelete, selectionOptions } = useBatchDelete(
  67 + deleteDict,
  68 + handleSuccess
  69 + );
63 const [registerTable, { reload }] = useTable({ 70 const [registerTable, { reload }] = useTable({
64 title: '字典配置列表', 71 title: '字典配置列表',
65 api: sysDictPage, 72 api: sysDictPage,
@@ -73,12 +80,13 @@ @@ -73,12 +80,13 @@
73 bordered: true, 80 bordered: true,
74 showIndexColumn: false, 81 showIndexColumn: false,
75 actionColumn: { 82 actionColumn: {
76 - width: 240, 83 + width: 300,
77 title: '操作', 84 title: '操作',
78 dataIndex: 'action', 85 dataIndex: 'action',
79 slots: { customRender: 'action' }, 86 slots: { customRender: 'action' },
80 fixed: 'right', 87 fixed: 'right',
81 }, 88 },
  89 + ...selectionOptions,
82 }); 90 });
83 91
84 function handleCreate() { 92 function handleCreate() {
@@ -100,14 +108,6 @@ @@ -100,14 +108,6 @@
100 }); 108 });
101 } 109 }
102 110
103 - function handleDelete(record: Recordable) {  
104 - let ids = [record.id];  
105 - deleteDict(ids).then((result) => {  
106 - createMessage.success(result.message);  
107 - handleSuccess();  
108 - });  
109 - }  
110 -  
111 function handleSuccess() { 111 function handleSuccess() {
112 reload(); 112 reload();
113 } 113 }
@@ -119,8 +119,10 @@ @@ -119,8 +119,10 @@
119 handleCreate, 119 handleCreate,
120 handleEdit, 120 handleEdit,
121 handleItem, 121 handleItem,
122 - handleDelete, 122 +
123 handleSuccess, 123 handleSuccess,
  124 + hasBatchDelete,
  125 + handleDeleteOrBatchDelete,
124 }; 126 };
125 }, 127 },
126 }); 128 });
@@ -5,6 +5,9 @@ @@ -5,6 +5,9 @@
5 <a-button type="primary" @click="handleCreate"> 5 <a-button type="primary" @click="handleCreate">
6 {{ getI18nCreateMenu }} 6 {{ getI18nCreateMenu }}
7 </a-button> 7 </a-button>
  8 + <a-button color="error" @click="handleDeleteOrBatchDelete(null)" :disabled="hasBatchDelete">
  9 + 批量删除
  10 + </a-button>
8 </template> 11 </template>
9 <template #action="{ record }"> 12 <template #action="{ record }">
10 <TableAction 13 <TableAction
@@ -53,6 +56,7 @@ @@ -53,6 +56,7 @@
53 import { columns } from './menu.data'; 56 import { columns } from './menu.data';
54 import { useI18n } from '/@/hooks/web/useI18n'; 57 import { useI18n } from '/@/hooks/web/useI18n';
55 import { notification } from 'ant-design-vue'; 58 import { notification } from 'ant-design-vue';
  59 + import { useBatchDelete } from '/@/hooks/web/useBatchDelete';
56 60
57 // 自定义表格组件和属性 61 // 自定义表格组件和属性
58 export default defineComponent({ 62 export default defineComponent({
@@ -63,29 +67,29 @@ @@ -63,29 +67,29 @@
63 const { t } = useI18n(); //加载国际化 67 const { t } = useI18n(); //加载国际化
64 // 新增菜单 68 // 新增菜单
65 const getI18nCreateMenu = computed(() => t('routes.common.system.pageSystemTitleCreateMenu')); 69 const getI18nCreateMenu = computed(() => t('routes.common.system.pageSystemTitleCreateMenu'));
  70 + const { hasBatchDelete, handleDeleteOrBatchDelete, selectionOptions } = useBatchDelete(
  71 + delMenu,
  72 + handleSuccess
  73 + );
66 const [registerTable, { reload, expandAll }] = useTable({ 74 const [registerTable, { reload, expandAll }] = useTable({
67 title: t('routes.common.system.pageSystemTitleMenuList'), //'菜单列表' 75 title: t('routes.common.system.pageSystemTitleMenuList'), //'菜单列表'
68 api: getMenuList, //加载数据 76 api: getMenuList, //加载数据
69 columns, //加载列 77 columns, //加载列
70 - // formConfig: {  
71 - // labelWidth: 120,  
72 - // schemas: searchFormSchema,  
73 - // },  
74 isTreeTable: true, 78 isTreeTable: true,
75 pagination: false, 79 pagination: false,
76 striped: false, 80 striped: false,
77 - // useSearchForm: true,  
78 showTableSetting: true, 81 showTableSetting: true,
79 bordered: true, 82 bordered: true,
80 showIndexColumn: false, 83 showIndexColumn: false,
81 canResize: false, 84 canResize: false,
82 actionColumn: { 85 actionColumn: {
83 - width: 120, 86 + width: 200,
84 title: t('routes.common.system.pageSystemTitleOperation'), //操作 87 title: t('routes.common.system.pageSystemTitleOperation'), //操作
85 dataIndex: 'action', 88 dataIndex: 'action',
86 slots: { customRender: 'action' }, 89 slots: { customRender: 'action' },
87 fixed: 'right', 90 fixed: 'right',
88 }, 91 },
  92 + ...selectionOptions,
89 }); 93 });
90 94
91 /** 95 /**
@@ -157,6 +161,8 @@ @@ -157,6 +161,8 @@
157 handleDelete, 161 handleDelete,
158 handleSuccess, 162 handleSuccess,
159 onFetchSuccess, 163 onFetchSuccess,
  164 + hasBatchDelete,
  165 + handleDeleteOrBatchDelete,
160 }; 166 };
161 }, 167 },
162 }); 168 });
@@ -5,6 +5,9 @@ @@ -5,6 +5,9 @@
5 <a-button type="primary" @click="handleCreate"> 5 <a-button type="primary" @click="handleCreate">
6 {{ getI18n }} 6 {{ getI18n }}
7 </a-button> 7 </a-button>
  8 + <a-button color="error" @click="handleDeleteOrBatchDelete(null)" :disabled="hasBatchDelete">
  9 + 批量删除
  10 + </a-button>
8 </template> 11 </template>
9 <template #action="{ record }"> 12 <template #action="{ record }">
10 <TableAction 13 <TableAction
@@ -20,7 +23,7 @@ @@ -20,7 +23,7 @@
20 color: 'error', 23 color: 'error',
21 popConfirm: { 24 popConfirm: {
22 title: getDeleteTitle(), //是否确认删除//getDeleteTitle() 25 title: getDeleteTitle(), //是否确认删除//getDeleteTitle()
23 - confirm: handleDelete.bind(null, record), 26 + confirm: handleDeleteOrBatchDelete.bind(null, record),
24 }, 27 },
25 }, 28 },
26 ]" 29 ]"
@@ -32,18 +35,14 @@ @@ -32,18 +35,14 @@
32 </template> 35 </template>
33 <script lang="ts"> 36 <script lang="ts">
34 import { computed, defineComponent, nextTick } from 'vue'; 37 import { computed, defineComponent, nextTick } from 'vue';
35 -  
36 import { BasicTable, useTable, TableAction } from '/@/components/Table'; 38 import { BasicTable, useTable, TableAction } from '/@/components/Table';
37 -  
38 // 加载自定义侧边弹出框 组件 39 // 加载自定义侧边弹出框 组件
39 -  
40 import { useDrawer } from '/@/components/Drawer'; 40 import { useDrawer } from '/@/components/Drawer';
41 import DeptDrawer from './OrganizationDrawer.vue'; 41 import DeptDrawer from './OrganizationDrawer.vue';
42 import { columns } from './organization.data'; 42 import { columns } from './organization.data';
43 import { useI18n } from '/@/hooks/web/useI18n'; 43 import { useI18n } from '/@/hooks/web/useI18n';
44 import { delOrganization, getOrganizationList } from '/@/api/system/system'; 44 import { delOrganization, getOrganizationList } from '/@/api/system/system';
45 - import { useMessage } from '/@/hooks/web/useMessage';  
46 - 45 + import { useBatchDelete } from '/@/hooks/web/useBatchDelete';
47 export default defineComponent({ 46 export default defineComponent({
48 name: 'DeptManagement', 47 name: 'DeptManagement',
49 components: { BasicTable, DeptDrawer, TableAction }, 48 components: { BasicTable, DeptDrawer, TableAction },
@@ -51,7 +50,10 @@ @@ -51,7 +50,10 @@
51 const [registerModal, { openDrawer }] = useDrawer(); 50 const [registerModal, { openDrawer }] = useDrawer();
52 const { t } = useI18n(); //加载国际化 51 const { t } = useI18n(); //加载国际化
53 const getI18n = computed(() => t('routes.common.organization.toolCreateOrganization')); 52 const getI18n = computed(() => t('routes.common.organization.toolCreateOrganization'));
54 - const { createMessage } = useMessage(); 53 + const { hasBatchDelete, handleDeleteOrBatchDelete, selectionOptions } = useBatchDelete(
  54 + delOrganization,
  55 + handleSuccess
  56 + );
55 const [registerTable, { reload, expandAll }] = useTable({ 57 const [registerTable, { reload, expandAll }] = useTable({
56 title: t('routes.common.organization.toolOrganizationList'), 58 title: t('routes.common.organization.toolOrganizationList'),
57 api: getOrganizationList, 59 api: getOrganizationList,
@@ -65,12 +67,13 @@ @@ -65,12 +67,13 @@
65 showIndexColumn: false, 67 showIndexColumn: false,
66 canResize: false, 68 canResize: false,
67 actionColumn: { 69 actionColumn: {
68 - width: 80, 70 + width: 200,
69 title: t('routes.common.common.operation'), //操作 71 title: t('routes.common.common.operation'), //操作
70 dataIndex: 'action', 72 dataIndex: 'action',
71 slots: { customRender: 'action' }, 73 slots: { customRender: 'action' },
72 fixed: 'right', 74 fixed: 'right',
73 }, 75 },
  76 + ...selectionOptions,
74 }); 77 });
75 /** 78 /**
76 * 获得删除提示框的文字 79 * 获得删除提示框的文字
@@ -93,17 +96,6 @@ @@ -93,17 +96,6 @@
93 }); 96 });
94 } 97 }
95 98
96 - async function handleDelete(record: Recordable) {  
97 - try {  
98 - let ids = [record.id];  
99 - await delOrganization(ids);  
100 - createMessage.success('删除组织成功');  
101 - handleSuccess();  
102 - } catch (e) {  
103 - return e;  
104 - }  
105 - }  
106 -  
107 function handleSuccess() { 99 function handleSuccess() {
108 reload(); 100 reload();
109 } 101 }
@@ -120,9 +112,10 @@ @@ -120,9 +112,10 @@
120 getDeleteTitle, 112 getDeleteTitle,
121 handleCreate, 113 handleCreate,
122 handleEdit, 114 handleEdit,
123 - handleDelete,  
124 handleSuccess, 115 handleSuccess,
125 onFetchSuccess, 116 onFetchSuccess,
  117 + hasBatchDelete,
  118 + handleDeleteOrBatchDelete,
126 }; 119 };
127 }, 120 },
128 }); 121 });
@@ -2,7 +2,10 @@ @@ -2,7 +2,10 @@
2 <div> 2 <div>
3 <BasicTable @register="registerTable"> 3 <BasicTable @register="registerTable">
4 <template #toolbar> 4 <template #toolbar>
5 - <a-button type="primary" @click="handleCreate"> 新增角色 </a-button> 5 + <a-button type="primary" @click="handleCreate">新增角色</a-button>
  6 + <a-button color="error" @click="handleDeleteOrBatchDelete(null)" :disabled="hasBatchDelete">
  7 + 批量删除
  8 + </a-button>
6 </template> 9 </template>
7 <template #action="{ record }"> 10 <template #action="{ record }">
8 <TableAction 11 <TableAction
@@ -19,7 +22,7 @@ @@ -19,7 +22,7 @@
19 ifShow: record.roleType != RoleEnum.SYS_ADMIN, 22 ifShow: record.roleType != RoleEnum.SYS_ADMIN,
20 popConfirm: { 23 popConfirm: {
21 title: '是否确认删除', 24 title: '是否确认删除',
22 - confirm: handleDelete.bind(null, record), 25 + confirm: handleDeleteOrBatchDelete.bind(null, record),
23 }, 26 },
24 }, 27 },
25 ]" 28 ]"
@@ -39,21 +42,20 @@ @@ -39,21 +42,20 @@
39 import RoleDrawer from './RoleDrawer.vue'; 42 import RoleDrawer from './RoleDrawer.vue';
40 import { columns, searchFormSchema } from './role.data'; 43 import { columns, searchFormSchema } from './role.data';
41 import { RoleEnum } from '/@/enums/roleEnum'; 44 import { RoleEnum } from '/@/enums/roleEnum';
42 - 45 + import { useBatchDelete } from '/@/hooks/web/useBatchDelete';
43 export default defineComponent({ 46 export default defineComponent({
44 name: 'RoleManagement', 47 name: 'RoleManagement',
45 components: { BasicTable, RoleDrawer, TableAction }, 48 components: { BasicTable, RoleDrawer, TableAction },
46 setup() { 49 setup() {
47 const [registerDrawer, { openDrawer }] = useDrawer(); 50 const [registerDrawer, { openDrawer }] = useDrawer();
  51 + const { hasBatchDelete, handleDeleteOrBatchDelete, selectionOptions } = useBatchDelete(
  52 + delRole,
  53 + handleSuccess
  54 + );
48 const [registerTable, { reload }] = useTable({ 55 const [registerTable, { reload }] = useTable({
49 title: '角色列表', 56 title: '角色列表',
50 api: getRoleListByPage, 57 api: getRoleListByPage,
51 columns, 58 columns,
52 - tableSetting: {  
53 - redo: true,  
54 - size: false,  
55 - setting: false,  
56 - },  
57 formConfig: { 59 formConfig: {
58 labelWidth: 120, 60 labelWidth: 120,
59 schemas: searchFormSchema, 61 schemas: searchFormSchema,
@@ -63,12 +65,13 @@ @@ -63,12 +65,13 @@
63 bordered: true, 65 bordered: true,
64 showIndexColumn: false, 66 showIndexColumn: false,
65 actionColumn: { 67 actionColumn: {
66 - width: 80, 68 + width: 200,
67 title: '操作', 69 title: '操作',
68 dataIndex: 'action', 70 dataIndex: 'action',
69 slots: { customRender: 'action' }, 71 slots: { customRender: 'action' },
70 fixed: 'right', 72 fixed: 'right',
71 }, 73 },
  74 + ...selectionOptions,
72 }); 75 });
73 76
74 function handleCreate() { 77 function handleCreate() {
@@ -83,13 +86,6 @@ @@ -83,13 +86,6 @@
83 isUpdate: true, 86 isUpdate: true,
84 }); 87 });
85 } 88 }
86 -  
87 - async function handleDelete(record: Recordable) {  
88 - const roleIds = [record.id];  
89 - delRole(roleIds).then(() => {  
90 - reload();  
91 - });  
92 - }  
93 function handleSuccess() { 89 function handleSuccess() {
94 reload(); 90 reload();
95 } 91 }
@@ -99,9 +95,10 @@ @@ -99,9 +95,10 @@
99 registerDrawer, 95 registerDrawer,
100 handleCreate, 96 handleCreate,
101 handleEdit, 97 handleEdit,
102 - handleDelete,  
103 handleSuccess, 98 handleSuccess,
104 RoleEnum, 99 RoleEnum,
  100 + hasBatchDelete,
  101 + handleDeleteOrBatchDelete,
105 }; 102 };
106 }, 103 },
107 }); 104 });
@@ -188,11 +188,6 @@ @@ -188,11 +188,6 @@
188 slots: { customRender: 'action' }, 188 slots: { customRender: 'action' },
189 fixed: 'right', 189 fixed: 'right',
190 }, 190 },
191 - tableSetting: {  
192 - redo: true,  
193 - size: false,  
194 - setting: false,  
195 - },  
196 }); 191 });
197 //默认传递页面数据 192 //默认传递页面数据
198 const [tenantAdminDrawer, { closeDrawer }] = useDrawerInner(async (data) => { 193 const [tenantAdminDrawer, { closeDrawer }] = useDrawerInner(async (data) => {
@@ -98,7 +98,6 @@ @@ -98,7 +98,6 @@
98 { 98 {
99 field: 'email', 99 field: 'email',
100 label: '邮件', 100 label: '邮件',
101 - required: true,  
102 component: 'Input', 101 component: 'Input',
103 rules: emailRule, 102 rules: emailRule,
104 }, 103 },
@@ -39,7 +39,7 @@ @@ -39,7 +39,7 @@
39 import { FileItem } from '/@/components/Upload/src/typing'; 39 import { FileItem } from '/@/components/Upload/src/typing';
40 import { upload } from '/@/api/oss/ossFileUploader'; 40 import { upload } from '/@/api/oss/ossFileUploader';
41 import { getTenantRoles, updateOrCreateTenant } from '/@/api/tenant/tenantApi'; 41 import { getTenantRoles, updateOrCreateTenant } from '/@/api/tenant/tenantApi';
42 - 42 + import { useMessage } from '/@/hooks/web/useMessage';
43 export default defineComponent({ 43 export default defineComponent({
44 name: 'TenantDrawer', 44 name: 'TenantDrawer',
45 components: { 45 components: {
@@ -133,12 +133,16 @@ @@ -133,12 +133,16 @@
133 entityType: 'TENANT_PROFILE', 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 } finally { 142 } finally {
141 - setDrawerProps({ confirmLoading: false }); 143 + setDrawerProps({
  144 + confirmLoading: false,
  145 + });
142 } 146 }
143 } 147 }
144 148
@@ -74,16 +74,54 @@ @@ -74,16 +74,54 @@
74 import { useDrawer } from '/@/components/Drawer'; 74 import { useDrawer } from '/@/components/Drawer';
75 import TenantDrawer from './TenantDrawer.vue'; 75 import TenantDrawer from './TenantDrawer.vue';
76 import TenantAdminDrawer from './TenantAdminDrawer.vue'; 76 import TenantAdminDrawer from './TenantAdminDrawer.vue';
  77 + import { useMessage } from '/@/hooks/web/useMessage';
77 export default defineComponent({ 78 export default defineComponent({
78 components: { BasicTable, TableImg, Tag, TableAction, TenantDrawer, TenantAdminDrawer }, 79 components: { BasicTable, TableImg, Tag, TableAction, TenantDrawer, TenantAdminDrawer },
79 setup() { 80 setup() {
80 const [tenantDrawer, { openDrawer }] = useDrawer(); 81 const [tenantDrawer, { openDrawer }] = useDrawer();
81 const [tenantAdminDrawer, { openDrawer: openTenantAdminDrawer }] = useDrawer(); 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 reload(); 119 reload();
86 - }); 120 + const { createMessage } = useMessage();
  121 + createMessage.success('删除成功');
  122 + } finally {
  123 + setLoading(false);
  124 + }
87 } 125 }
88 126
89 function handleCreate() { 127 function handleCreate() {
@@ -105,44 +143,10 @@ @@ -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 function handleSuccess() { 146 function handleSuccess() {
118 reload(); 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 return { 150 return {
147 tenantTable, 151 tenantTable,
148 handleEdit, 152 handleEdit,
@@ -152,6 +156,7 @@ @@ -152,6 +156,7 @@
152 tenantAdminDrawer, 156 tenantAdminDrawer,
153 handleSuccess, 157 handleSuccess,
154 handleTenantAdminDrawer, 158 handleTenantAdminDrawer,
  159 + setLoading,
155 }; 160 };
156 }, 161 },
157 }); 162 });
@@ -38,7 +38,7 @@ export const schemas: FormSchema[] = [ @@ -38,7 +38,7 @@ export const schemas: FormSchema[] = [
38 { 38 {
39 field: 'icon', 39 field: 'icon',
40 component: 'Upload', 40 component: 'Upload',
41 - label: 'Favicon浏览器Icon图标', 41 + label: '浏览器Icon图标',
42 colProps: { 42 colProps: {
43 span: 24, 43 span: 24,
44 }, 44 },
@@ -130,7 +130,7 @@ export const schemas: FormSchema[] = [ @@ -130,7 +130,7 @@ export const schemas: FormSchema[] = [
130 params: { parentId: 0 }, 130 params: { parentId: 0 },
131 labelField: 'name', 131 labelField: 'name',
132 valueField: 'code', 132 valueField: 'code',
133 - placeholder: '请选择国家/地区', 133 + placeholder: '国家/地区',
134 }, 134 },
135 }, 135 },
136 { 136 {
@@ -146,7 +146,7 @@ export const schemas: FormSchema[] = [ @@ -146,7 +146,7 @@ export const schemas: FormSchema[] = [
146 api: getAreaList, 146 api: getAreaList,
147 labelField: 'name', 147 labelField: 'name',
148 valueField: 'code', 148 valueField: 'code',
149 - placeholder: '请选择省份', 149 + placeholder: '省份',
150 params: { parentId: 1 }, 150 params: { parentId: 1 },
151 async onChange(value) { 151 async onChange(value) {
152 if (value === undefined) { 152 if (value === undefined) {
@@ -158,18 +158,21 @@ export const schemas: FormSchema[] = [ @@ -158,18 +158,21 @@ export const schemas: FormSchema[] = [
158 field: 'nameCity', 158 field: 'nameCity',
159 componentProps: { 159 componentProps: {
160 options: [], 160 options: [],
  161 + placeholder: '城市',
161 }, 162 },
162 }, 163 },
163 { 164 {
164 field: 'nameCoun', 165 field: 'nameCoun',
165 componentProps: { 166 componentProps: {
166 options: [], 167 options: [],
  168 + placeholder: '区/县',
167 }, 169 },
168 }, 170 },
169 { 171 {
170 field: 'nameTown', 172 field: 'nameTown',
171 componentProps: { 173 componentProps: {
172 options: [], 174 options: [],
  175 + placeholder: '城镇/街道',
173 }, 176 },
174 }, 177 },
175 ]); 178 ]);
@@ -186,7 +189,7 @@ export const schemas: FormSchema[] = [ @@ -186,7 +189,7 @@ export const schemas: FormSchema[] = [
186 field: 'nameCity', 189 field: 'nameCity',
187 componentProps: { 190 componentProps: {
188 options: nameCity, 191 options: nameCity,
189 - placeholder: '请选择城市', 192 + placeholder: '城市',
190 async onChange(value) { 193 async onChange(value) {
191 if (value === undefined) { 194 if (value === undefined) {
192 formModel.nameCoun = undefined; // reset city value 195 formModel.nameCoun = undefined; // reset city value
@@ -223,7 +226,7 @@ export const schemas: FormSchema[] = [ @@ -223,7 +226,7 @@ export const schemas: FormSchema[] = [
223 updateSchema({ 226 updateSchema({
224 field: 'nameTown', 227 field: 'nameTown',
225 componentProps: { 228 componentProps: {
226 - placeholder: '请选择街道/城镇', 229 + placeholder: '城镇/街道',
227 options: [], 230 options: [],
228 }, 231 },
229 }); 232 });
@@ -236,7 +239,7 @@ export const schemas: FormSchema[] = [ @@ -236,7 +239,7 @@ export const schemas: FormSchema[] = [
236 updateSchema({ 239 updateSchema({
237 field: 'nameTown', 240 field: 'nameTown',
238 componentProps: { 241 componentProps: {
239 - placeholder: '请选择街道/城镇', 242 + placeholder: '城镇/街道',
240 options: nameTown, 243 options: nameTown,
241 }, 244 },
242 }); 245 });
@@ -257,6 +260,7 @@ export const schemas: FormSchema[] = [ @@ -257,6 +260,7 @@ export const schemas: FormSchema[] = [
257 field: 'nameCity', 260 field: 'nameCity',
258 component: 'Select', 261 component: 'Select',
259 label: '', 262 label: '',
  263 + labelWidth: 0,
260 colProps: { 264 colProps: {
261 span: 5, 265 span: 5,
262 style: { 266 style: {
@@ -271,11 +275,11 @@ export const schemas: FormSchema[] = [ @@ -271,11 +275,11 @@ export const schemas: FormSchema[] = [
271 colProps: { 275 colProps: {
272 span: 5, 276 span: 5,
273 style: { 277 style: {
274 - marginLeft: '-160px', 278 + marginLeft: '-10rem',
275 }, 279 },
276 }, 280 },
277 componentProps: { 281 componentProps: {
278 - placeholder: '请选择区/县', 282 + placeholder: '区/县',
279 }, 283 },
280 }, 284 },
281 { 285 {
@@ -285,11 +289,11 @@ export const schemas: FormSchema[] = [ @@ -285,11 +289,11 @@ export const schemas: FormSchema[] = [
285 colProps: { 289 colProps: {
286 span: 6, 290 span: 6,
287 style: { 291 style: {
288 - marginLeft: '-160px', 292 + marginLeft: '-10rem',
289 }, 293 },
290 }, 294 },
291 componentProps: { 295 componentProps: {
292 - placeholder: '请选择街道/城镇', 296 + placeholder: '城镇/街道',
293 }, 297 },
294 }, 298 },
295 { 299 {
@@ -137,21 +137,18 @@ @@ -137,21 +137,18 @@
137 137
138 // 地区显示回显和数据联动 138 // 地区显示回显和数据联动
139 async function updateCityData( 139 async function updateCityData(
140 - provs: CityItem[],  
141 cities: CityItem[], 140 cities: CityItem[],
142 couns: CityItem[], 141 couns: CityItem[],
143 towns: CityItem[], 142 towns: CityItem[],
144 code: Code 143 code: Code
145 ) { 144 ) {
146 // 加工后端返回字段 145 // 加工后端返回字段
147 - provs.forEach((item) => {  
148 - item.label = item.name;  
149 - item.value = item.code;  
150 - }); 146 +
151 cities.forEach((item) => { 147 cities.forEach((item) => {
152 item.label = item.name; 148 item.label = item.name;
153 item.value = item.code; 149 item.value = item.code;
154 }); 150 });
  151 +
155 couns.forEach((item) => { 152 couns.forEach((item) => {
156 item.label = item.name; 153 item.label = item.name;
157 item.value = item.code; 154 item.value = item.code;
@@ -161,13 +158,6 @@ @@ -161,13 +158,6 @@
161 item.value = item.code; 158 item.value = item.code;
162 }); 159 });
163 const { codeCountry, codeProv, codeCity, codeCoun, codeTown } = code; 160 const { codeCountry, codeProv, codeCity, codeCoun, codeTown } = code;
164 - setFieldsValue({  
165 - nameCountry: codeCountry,  
166 - nameProv: codeProv,  
167 - nameCity: codeCity,  
168 - nameCoun: codeCoun,  
169 - nameTown: codeTown,  
170 - });  
171 updateSchema([ 161 updateSchema([
172 { 162 {
173 field: 'nameCity', 163 field: 'nameCity',
@@ -175,17 +165,25 @@ @@ -175,17 +165,25 @@
175 return { 165 return {
176 options: cities, 166 options: cities,
177 async onChange(value) { 167 async onChange(value) {
178 - let couns: CityItem[] = await getAreaList({ parentId: value });  
179 if (value === undefined) { 168 if (value === undefined) {
180 formModel.nameCoun = undefined; // reset city value 169 formModel.nameCoun = undefined; // reset city value
181 formModel.nameTown = undefined; 170 formModel.nameTown = undefined;
182 - updateSchema({  
183 - field: 'nameTown',  
184 - componentProps: {  
185 - options: [], 171 + updateSchema([
  172 + {
  173 + field: 'nameCoun',
  174 + componentProps: {
  175 + options: [],
  176 + },
186 }, 177 },
187 - }); 178 + {
  179 + field: 'nameTown',
  180 + componentProps: {
  181 + options: [],
  182 + },
  183 + },
  184 + ]);
188 } else { 185 } else {
  186 + let couns: CityItem[] = await getAreaList({ parentId: value });
189 couns.forEach((item) => { 187 couns.forEach((item) => {
190 item.label = item.name; 188 item.label = item.name;
191 item.value = item.code; 189 item.value = item.code;
@@ -198,23 +196,23 @@ @@ -198,23 +196,23 @@
198 // 请选择区 196 // 请选择区
199 options: couns, 197 options: couns,
200 async onChange(value) { 198 async onChange(value) {
201 - let towns: CityItem[] = await getAreaList({ parentId: value });  
202 if (value === undefined) { 199 if (value === undefined) {
203 formModel.nameTown = undefined; 200 formModel.nameTown = undefined;
  201 + } else {
  202 + let towns: CityItem[] = await getAreaList({ parentId: value });
  203 + towns.forEach((item) => {
  204 + item.label = item.name;
  205 + item.value = item.code;
  206 + });
  207 + formModel.nameTown = undefined;
  208 + updateSchema({
  209 + field: 'nameTown',
  210 + componentProps: {
  211 + placeholder: '城镇/街道',
  212 + options: towns,
  213 + },
  214 + });
204 } 215 }
205 - towns.forEach((item) => {  
206 - item.label = item.name;  
207 - item.value = item.code;  
208 - });  
209 -  
210 - formModel.nameTown = undefined;  
211 - updateSchema({  
212 - field: 'nameTown',  
213 - componentProps: {  
214 - placeholder: '请选择街道/城镇',  
215 - options: towns,  
216 - },  
217 - });  
218 }, 216 },
219 }, 217 },
220 }); 218 });
@@ -235,6 +233,7 @@ @@ -235,6 +233,7 @@
235 updateSchema({ 233 updateSchema({
236 field: 'nameTown', 234 field: 'nameTown',
237 componentProps: { 235 componentProps: {
  236 + placeholder: '城镇/街道',
238 options: [], 237 options: [],
239 }, 238 },
240 }); 239 });
@@ -250,7 +249,7 @@ @@ -250,7 +249,7 @@
250 updateSchema({ 249 updateSchema({
251 field: 'nameTown', 250 field: 'nameTown',
252 componentProps: { 251 componentProps: {
253 - placeholder: '请选择街道/城镇', 252 + placeholder: '城镇/街道',
254 options: towns, 253 options: towns,
255 }, 254 },
256 }); 255 });
@@ -265,22 +264,20 @@ @@ -265,22 +264,20 @@
265 }, 264 },
266 }, 265 },
267 ]); 266 ]);
  267 + setFieldsValue({
  268 + nameCountry: codeCountry,
  269 + nameProv: codeProv,
  270 + nameCity: codeCity,
  271 + nameCoun: codeCoun,
  272 + nameTown: codeTown,
  273 + });
268 } 274 }
269 275
270 onMounted(async () => { 276 onMounted(async () => {
271 const res = await getEnterPriseDetail(); 277 const res = await getEnterPriseDetail();
272 if (res.sysTown) { 278 if (res.sysTown) {
273 - const {  
274 - provs,  
275 - cities,  
276 - couns,  
277 - towns,  
278 - codeCountry,  
279 - codeProv,  
280 - codeCity,  
281 - codeCoun,  
282 - codeTown,  
283 - } = res.sysTown; 279 + const { cities, couns, towns, codeCountry, codeProv, codeCity, codeCoun, codeTown } =
  280 + res.sysTown;
284 const code = { 281 const code = {
285 codeCountry, 282 codeCountry,
286 codeProv, 283 codeProv,
@@ -288,7 +285,7 @@ @@ -288,7 +285,7 @@
288 codeCoun, 285 codeCoun,
289 codeTown, 286 codeTown,
290 }; 287 };
291 - updateCityData(provs, cities, couns, towns, code); 288 + updateCityData(cities, couns, towns, code);
292 setFieldsValue(res); 289 setFieldsValue(res);
293 qrcodePic.value = res.qrCode; 290 qrcodePic.value = res.qrCode;
294 } else { 291 } else {
@@ -308,5 +305,3 @@ @@ -308,5 +305,3 @@
308 }, 305 },
309 }); 306 });
310 </script> 307 </script>
311 -  
312 -<style lang="less" scoped></style>  
@@ -33,13 +33,12 @@ @@ -33,13 +33,12 @@
33 margin: 20px; 33 margin: 20px;
34 line-height: 50px; 34 line-height: 50px;
35 font-size: 18px; 35 font-size: 18px;
36 - border-radius: 8px; 36 +
37 background-color: #fff; 37 background-color: #fff;
38 padding-left: 10px; 38 padding-left: 10px;
39 } 39 }
40 .tab-card { 40 .tab-card {
41 margin: 20px 0 20px 20px; 41 margin: 20px 0 20px 20px;
42 - border-radius: 5px;  
43 } 42 }
44 .card { 43 .card {
45 margin: 20px; 44 margin: 20px;
@@ -48,11 +48,7 @@ @@ -48,11 +48,7 @@
48 title: '租户角色列表', 48 title: '租户角色列表',
49 api: getRoleListByPage, 49 api: getRoleListByPage,
50 columns, 50 columns,
51 - tableSetting: {  
52 - redo: true,  
53 - size: false,  
54 - setting: false,  
55 - }, 51 +
56 formConfig: { 52 formConfig: {
57 labelWidth: 120, 53 labelWidth: 120,
58 schemas: searchFormSchema, 54 schemas: searchFormSchema,
@@ -62,7 +58,7 @@ @@ -62,7 +58,7 @@
62 bordered: true, 58 bordered: true,
63 showIndexColumn: false, 59 showIndexColumn: false,
64 actionColumn: { 60 actionColumn: {
65 - width: 80, 61 + width: 200,
66 title: '操作', 62 title: '操作',
67 dataIndex: 'action', 63 dataIndex: 'action',
68 slots: { customRender: 'action' }, 64 slots: { customRender: 'action' },
@@ -62,7 +62,7 @@ @@ -62,7 +62,7 @@
62 bordered: true, 62 bordered: true,
63 showIndexColumn: false, 63 showIndexColumn: false,
64 actionColumn: { 64 actionColumn: {
65 - width: 180, 65 + width: 200,
66 title: '操作', 66 title: '操作',
67 dataIndex: 'action', 67 dataIndex: 'action',
68 slots: { customRender: 'action' }, 68 slots: { customRender: 'action' },