字典、配置、websocket
This commit is contained in:
parent
aa8920f487
commit
05dd125357
16
src/App.vue
16
src/App.vue
@ -27,24 +27,29 @@
|
||||
:y-offset="60"
|
||||
:rotate="-15"
|
||||
/>
|
||||
<global-websocket :uri="'/api/websocket/' + userInfo.id" @rollback="rollback" />
|
||||
</NConfigProvider>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, onMounted, onUnmounted } from 'vue';
|
||||
import { computed, onMounted, onUnmounted, defineAsyncComponent, h } from 'vue';
|
||||
import { darkTheme, dateZhCN, zhCN } from 'naive-ui';
|
||||
import { LockScreen } from '@/components/Lockscreen';
|
||||
import { AppProvider } from '@/components/Application';
|
||||
import { useLockscreenStore } from '@/store/modules/lockscreen';
|
||||
import { useRoute } from 'vue-router';
|
||||
import { useUserStore } from '@/store/modules/user';
|
||||
import { useDesignSettingStore } from '@/store/modules/designSetting';
|
||||
import { useProjectSetting } from '@/hooks/setting/useProjectSetting';
|
||||
import { initWebSocket, sendWebSocket } from '@/components/Websocket/index';
|
||||
const GlobalWebsocket = defineAsyncComponent(() => import('@/components/Websocket/index.vue'));
|
||||
import { lighten } from '@/utils';
|
||||
|
||||
const route = useRoute();
|
||||
const useLockscreen = useLockscreenStore();
|
||||
const designStore = useDesignSettingStore();
|
||||
|
||||
const userStore = useUserStore();
|
||||
const userInfo: object = userStore.getUserInfo || {};
|
||||
const isLock = computed(() => useLockscreen.isLock);
|
||||
const lockTime = computed(() => useLockscreen.lockTime);
|
||||
|
||||
@ -95,6 +100,13 @@
|
||||
}
|
||||
}, 1000);
|
||||
};
|
||||
const rollback = (msg) => {
|
||||
$notification.info({
|
||||
title: '通知',
|
||||
content: () => h('div', msg),
|
||||
duration: 5000,
|
||||
});
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
// document.addEventListener('mousedown', timekeeping);
|
||||
|
||||
155
src/components/Websocket/index.vue
Normal file
155
src/components/Websocket/index.vue
Normal file
@ -0,0 +1,155 @@
|
||||
<template>
|
||||
<div></div>
|
||||
</template>
|
||||
<script setup lang="ts" name="global-websocket">
|
||||
import { reactive, ref, computed,onMounted,onUnmounted } from 'vue';
|
||||
import { useUserStore } from '@/store/modules/user';
|
||||
|
||||
const emit = defineEmits(['rollback']);
|
||||
|
||||
const props = defineProps({
|
||||
uri: {
|
||||
type: String,
|
||||
},
|
||||
});
|
||||
|
||||
const state = reactive({
|
||||
webSocket: ref(), // webSocket实例
|
||||
lockReconnect: false, // 重连锁,避免多次重连
|
||||
maxReconnect: 6, // 最大重连次数, -1 标识无限重连
|
||||
reconnectTime: 0, // 重连尝试次数
|
||||
heartbeat: {
|
||||
interval: 30 * 1000, // 心跳间隔时间
|
||||
timeout: 10 * 1000, // 响应超时时间
|
||||
pingTimeoutObj: ref(), // 延时发送心跳的定时器
|
||||
pongTimeoutObj: ref(), // 接收心跳响应的定时器
|
||||
pingMessage: JSON.stringify({ type: 'ping' }), // 心跳请求信息
|
||||
},
|
||||
});
|
||||
|
||||
const token = computed(() => {
|
||||
return useUserStore().getToken;
|
||||
});
|
||||
|
||||
const tenant = computed(() => {
|
||||
return Session.getTenant();
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
initWebSocket();
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
state.webSocket.close();
|
||||
clearTimeoutObj(state.heartbeat);
|
||||
});
|
||||
|
||||
const initWebSocket = () => {
|
||||
// ws地址
|
||||
let host = window.location.host;
|
||||
let wsUri =`${location.protocol === 'https:' ? 'wss' : 'ws'}://${host}${props.uri}`;
|
||||
|
||||
// 建立连接
|
||||
state.webSocket = new WebSocket(wsUri);
|
||||
// 连接成功
|
||||
state.webSocket.onopen = onOpen;
|
||||
// 连接错误
|
||||
state.webSocket.onerror = onError;
|
||||
// 接收信息
|
||||
state.webSocket.onmessage = onMessage;
|
||||
// 连接关闭
|
||||
state.webSocket.onclose = onClose;
|
||||
};
|
||||
|
||||
const reconnect = () => {
|
||||
if (!token) {
|
||||
return;
|
||||
}
|
||||
if (state.lockReconnect || (state.maxReconnect !== -1 && state.reconnectTime > state.maxReconnect)) {
|
||||
return;
|
||||
}
|
||||
state.lockReconnect = true;
|
||||
setTimeout(() => {
|
||||
state.reconnectTime++;
|
||||
// 建立新连接
|
||||
initWebSocket();
|
||||
state.lockReconnect = false;
|
||||
}, 5000);
|
||||
};
|
||||
/**
|
||||
* 清空定时器
|
||||
*/
|
||||
const clearTimeoutObj = (heartbeat: any) => {
|
||||
heartbeat.pingTimeoutObj && clearTimeout(heartbeat.pingTimeoutObj);
|
||||
heartbeat.pongTimeoutObj && clearTimeout(heartbeat.pongTimeoutObj);
|
||||
};
|
||||
/**
|
||||
* 开启心跳
|
||||
*/
|
||||
const startHeartbeat = () => {
|
||||
const webSocket = state.webSocket;
|
||||
const heartbeat = state.heartbeat;
|
||||
// 清空定时器
|
||||
clearTimeoutObj(heartbeat);
|
||||
// 延时发送下一次心跳
|
||||
heartbeat.pingTimeoutObj = setTimeout(() => {
|
||||
// 如果连接正常
|
||||
if (webSocket.readyState === 1) {
|
||||
//这里发送一个心跳,后端收到后,返回一个心跳消息,
|
||||
webSocket.send(heartbeat.pingMessage);
|
||||
// 心跳发送后,如果服务器超时未响应则断开,如果响应了会被重置心跳定时器
|
||||
heartbeat.pongTimeoutObj = setTimeout(() => {
|
||||
webSocket.close();
|
||||
}, heartbeat.timeout);
|
||||
} else {
|
||||
// 否则重连
|
||||
reconnect();
|
||||
}
|
||||
}, heartbeat.interval);
|
||||
};
|
||||
|
||||
/**
|
||||
* 连接成功事件
|
||||
*/
|
||||
const onOpen = () => {
|
||||
//开启心跳
|
||||
startHeartbeat();
|
||||
state.reconnectTime = 0;
|
||||
};
|
||||
/**
|
||||
* 连接失败事件
|
||||
* @param e
|
||||
*/
|
||||
const onError = () => {
|
||||
//重连
|
||||
reconnect();
|
||||
};
|
||||
|
||||
/**
|
||||
* 连接关闭事件
|
||||
* @param e
|
||||
*/
|
||||
const onClose = () => {
|
||||
//重连
|
||||
reconnect();
|
||||
};
|
||||
/**
|
||||
* 接收服务器推送的信息
|
||||
* @param msgEvent
|
||||
*/
|
||||
const onMessage = (msgEvent: any) => {
|
||||
//收到服务器信息,心跳重置并发送
|
||||
startHeartbeat();
|
||||
// if (msgEvent.data.indexOf('pong') > 0) {
|
||||
// return;
|
||||
// }
|
||||
// let text =''
|
||||
// try{
|
||||
// text = JSON.parse(msgEvent.data);
|
||||
// }catch(e){
|
||||
// return
|
||||
// }
|
||||
|
||||
emit('rollback', msgEvent.data);
|
||||
};
|
||||
</script>
|
||||
@ -6,12 +6,6 @@ export const columns = [
|
||||
width: 50,
|
||||
fixed: 'left',
|
||||
},
|
||||
{
|
||||
title: 'ID',
|
||||
key: 'id',
|
||||
fixed: 'left',
|
||||
width: 50,
|
||||
},
|
||||
{
|
||||
title: '配置名称',
|
||||
key: 'name',
|
||||
|
||||
@ -1,9 +1,8 @@
|
||||
<template>
|
||||
<PageWrapper>
|
||||
<n-grid x-gap="12" cols="1 s:1 m:1 l:24 xl:24 2xl:24" responsive="screen">
|
||||
<n-grid-item span="7">
|
||||
<n-grid-item span="8">
|
||||
<n-card shadow="hover" class="border-0">
|
||||
<template #header>
|
||||
<n-space>
|
||||
<n-input
|
||||
type="text"
|
||||
@ -11,13 +10,7 @@
|
||||
placeholder="请输入配置名称"
|
||||
clearable
|
||||
/>
|
||||
<n-button
|
||||
type="primary"
|
||||
@click="
|
||||
pager.page = 1;
|
||||
loadDataTable();
|
||||
"
|
||||
>
|
||||
<n-button type="primary" @click="reloadTable">
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<SearchOutlined />
|
||||
@ -35,14 +28,12 @@
|
||||
</template>
|
||||
新建
|
||||
</n-button>
|
||||
<n-button type="warning" @click="handleEdit" v-perm="['sys:config:edit']">
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<FormOutlined />
|
||||
</n-icon> </template
|
||||
>编辑
|
||||
</n-button>
|
||||
<n-button type="error" @click="handleDelete()" v-perm="['sys:config:delete']">
|
||||
<n-button
|
||||
type="error"
|
||||
@click="handleDelete()"
|
||||
v-perm="['sys:config:delete']"
|
||||
:disabled="!selectionData.length"
|
||||
>
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<DeleteOutlined />
|
||||
@ -51,31 +42,23 @@
|
||||
</n-button>
|
||||
</n-space>
|
||||
</div>
|
||||
</template>
|
||||
<template #default>
|
||||
<div :style="{ height: fwbHeight + 'px' }" class="dict-list-box">
|
||||
<div
|
||||
v-for="(item, index) in configDataList"
|
||||
:key="index"
|
||||
@click="onCheckedRow(item)"
|
||||
class="dict-item"
|
||||
:class="item.id == configId ? 'active' : ''"
|
||||
<BasicTable
|
||||
:columns="columns"
|
||||
:actionColumn="actionColumn"
|
||||
:request="loadDataTable"
|
||||
:row-key="(row) => row.id"
|
||||
ref="tableRef"
|
||||
:showTableSetting="false"
|
||||
@update:checked-row-keys="onSelectionChange"
|
||||
:pagination="{ showQuickJumper: false, showSizePicker: false }"
|
||||
:row-props="rowProps"
|
||||
:row-class-name="getRowClassName"
|
||||
:autoScrollX="true"
|
||||
>
|
||||
<span class="t1"
|
||||
>{{ item.name }}<span class="t2">({{ item.code }})</span></span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<pagination
|
||||
style="justify-content: flex-end"
|
||||
class="mt-10 flex"
|
||||
@change="loadDataTable"
|
||||
v-model="pager"
|
||||
/>
|
||||
</template>
|
||||
</BasicTable>
|
||||
</n-card>
|
||||
</n-grid-item>
|
||||
<n-grid-item span="17">
|
||||
<n-grid-item span="16">
|
||||
<n-card shadow="hover" class="mb-4 border-0 proCard">
|
||||
<configItem :configId="configId" v-if="configItemShow" />
|
||||
</n-card>
|
||||
@ -86,23 +69,27 @@
|
||||
:configId="configId"
|
||||
v-model:visible="editVisible"
|
||||
ref="createModalRef"
|
||||
@success="loadDataTable()"
|
||||
@success="reloadTable('noRefresh')"
|
||||
/>
|
||||
</PageWrapper>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, nextTick, defineAsyncComponent, onMounted } from 'vue';
|
||||
import { ref, nextTick, defineAsyncComponent, onMounted, reactive, h } from 'vue';
|
||||
import { getConfigList, configDelete } from '@/api/data/config';
|
||||
import { PlusOutlined, FormOutlined, DeleteOutlined, SearchOutlined } from '@vicons/antd';
|
||||
import editDialog from './edit.vue';
|
||||
import configItem from './configItem.vue';
|
||||
import { TableAction } from '@/components/Table';
|
||||
import { columns } from './columns';
|
||||
import { renderIcon } from '@/utils';
|
||||
import { useMessage, useDialog } from 'naive-ui';
|
||||
|
||||
/**
|
||||
* 定义参数变量
|
||||
*/
|
||||
const configId = ref(0);
|
||||
const tableRef = ref();
|
||||
const createModalRef = ref();
|
||||
const configItemShow = ref(false);
|
||||
const editVisible = ref(false);
|
||||
@ -115,18 +102,47 @@
|
||||
const params = ref({
|
||||
name: '',
|
||||
});
|
||||
const configDataList = ref([]);
|
||||
const selectionData = ref([]);
|
||||
|
||||
const actionColumn = reactive({
|
||||
width: 200,
|
||||
title: '操作',
|
||||
align: 'center',
|
||||
key: 'action',
|
||||
fixed: 'right',
|
||||
render(record) {
|
||||
return h(TableAction as any, {
|
||||
style: 'button',
|
||||
actions: [
|
||||
{
|
||||
label: '编辑',
|
||||
icon: renderIcon(FormOutlined),
|
||||
type: 'warning',
|
||||
auth: ['sys:config:update'],
|
||||
onClick: handleEdit.bind(null, record),
|
||||
},
|
||||
{
|
||||
label: '删除',
|
||||
icon: renderIcon(DeleteOutlined),
|
||||
type: 'error',
|
||||
auth: ['sys:config:delete'],
|
||||
onClick: handleDelete.bind(null, record),
|
||||
},
|
||||
],
|
||||
select: (key) => {
|
||||
message.info(`您点击了,${key} 按钮`);
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* 定义分页参数
|
||||
* 刷新配置项值列表
|
||||
* @param noRefresh 参数
|
||||
*/
|
||||
const pager = ref({
|
||||
page: 1,
|
||||
size: 10,
|
||||
count: configDataList.value.length,
|
||||
});
|
||||
const fwbHeight = document.body.clientHeight - 335;
|
||||
|
||||
function reloadTable(noRefresh = '') {
|
||||
tableRef.value.reload(noRefresh ? {} : { pageNo: 1 });
|
||||
}
|
||||
/**
|
||||
* 执行添加
|
||||
*/
|
||||
@ -140,52 +156,58 @@
|
||||
/**
|
||||
* 执行编辑
|
||||
*/
|
||||
const handleEdit = async () => {
|
||||
const handleEdit = async (row) => {
|
||||
configId.value = row.id;
|
||||
editVisible.value = true;
|
||||
await nextTick();
|
||||
createModalRef.value.openModal();
|
||||
};
|
||||
|
||||
/**
|
||||
* 数据行选中事件
|
||||
* @param row 参数
|
||||
* 选项发生变化
|
||||
* @param value 参数
|
||||
*/
|
||||
function onCheckedRow(row) {
|
||||
configId.value = row.id;
|
||||
function onSelectionChange(value) {
|
||||
selectionData.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载数据列表
|
||||
*/
|
||||
const loadDataTable = async () => {
|
||||
let result = await getConfigList({
|
||||
...params.value,
|
||||
pageNo: pager.value.page,
|
||||
pageSize: pager.value.size,
|
||||
});
|
||||
const loadDataTable = async (res) => {
|
||||
const result = await getConfigList({ ...params.value, ...res });
|
||||
configId.value = result?.records[0]?.id;
|
||||
configItemShow.value = true;
|
||||
configDataList.value = result.records;
|
||||
pager.value.count = result.total;
|
||||
return result;
|
||||
};
|
||||
|
||||
/**
|
||||
* 执行删除
|
||||
*/
|
||||
async function handleDelete() {
|
||||
async function handleDelete(row) {
|
||||
dialog.warning({
|
||||
title: '提示',
|
||||
content: '确定要删除?',
|
||||
positiveText: '确定',
|
||||
negativeText: '取消',
|
||||
onPositiveClick: async () => {
|
||||
configDelete(configId.value);
|
||||
row ? await configDelete(row.id) : await configBatchDelete(selectionData.value);
|
||||
message.success('删除成功');
|
||||
pager.value.page = 1;
|
||||
loadDataTable();
|
||||
reloadTable();
|
||||
},
|
||||
});
|
||||
}
|
||||
const getRowClassName = (row) => {
|
||||
return configId.value === row.id ? 'clickRowStyle' : '';
|
||||
};
|
||||
const rowProps = (row) => {
|
||||
return {
|
||||
style: 'cursor: pointer;',
|
||||
onClick: () => {
|
||||
configId.value = row.id;
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* 钩子函数
|
||||
@ -243,3 +265,18 @@
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style lang="less">
|
||||
.n-data-table-tbody {
|
||||
.n-data-table-tr.clickRowStyle,
|
||||
.n-data-table-tr.clickRowStyle {
|
||||
td {
|
||||
background-color: #e7eeff !important;
|
||||
}
|
||||
&:hover {
|
||||
td {
|
||||
background-color: #e7eeff !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -6,16 +6,14 @@ export const columns = [
|
||||
width: 50,
|
||||
fixed: 'left',
|
||||
},
|
||||
{
|
||||
title: 'ID',
|
||||
key: 'id',
|
||||
},
|
||||
{
|
||||
title: '字典名称',
|
||||
key: 'name',
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
title: '字典编码',
|
||||
key: 'code',
|
||||
width: 100,
|
||||
},
|
||||
];
|
||||
|
||||
@ -1,9 +1,8 @@
|
||||
<template>
|
||||
<PageWrapper>
|
||||
<n-grid x-gap="12" cols="1 s:1 m:1 l:24 xl:24 2xl:24" responsive="screen">
|
||||
<n-grid-item span="7">
|
||||
<n-grid-item span="8">
|
||||
<n-card shadow="hover" class="border-0" size="small">
|
||||
<template #header>
|
||||
<n-space :size="4">
|
||||
<n-input
|
||||
type="text"
|
||||
@ -11,25 +10,19 @@
|
||||
placeholder="请输入字典名称"
|
||||
clearable
|
||||
/>
|
||||
<n-button
|
||||
type="primary"
|
||||
@click="
|
||||
pager.page = 1;
|
||||
loadDataTable();
|
||||
"
|
||||
>
|
||||
<n-button type="primary" @click="reloadTable">
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<SearchOutlined />
|
||||
</n-icon> </template
|
||||
>查询
|
||||
</n-button>
|
||||
<n-button type="primary" @click="dictRefresh" v-perm="['sys:dict:cache']">
|
||||
<template #icon> <RedoOutlined /> </template>刷新缓存</n-button
|
||||
>
|
||||
</n-space>
|
||||
<div style="margin-top: 15px">
|
||||
<n-space>
|
||||
<n-button type="primary" @click="dictRefresh" v-perm="['sys:dict:cache']">
|
||||
<template #icon> <RedoOutlined /> </template>刷新缓存</n-button
|
||||
>
|
||||
<n-button type="primary" @click="handleAdd" v-perm="['sys:dict:add']">
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
@ -38,14 +31,12 @@
|
||||
</template>
|
||||
新建
|
||||
</n-button>
|
||||
<n-button type="warning" @click="handleEdit" v-perm="['sys:dict:edit']">
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<FormOutlined />
|
||||
</n-icon> </template
|
||||
>编辑
|
||||
</n-button>
|
||||
<n-button type="error" @click="handleDelete()" v-perm="['sys:dict:delete']">
|
||||
<n-button
|
||||
type="error"
|
||||
@click="handleDelete()"
|
||||
v-perm="['sys:dict:delete']"
|
||||
:disabled="!selectionData.length"
|
||||
>
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<DeleteOutlined />
|
||||
@ -54,31 +45,23 @@
|
||||
</n-button>
|
||||
</n-space>
|
||||
</div>
|
||||
</template>
|
||||
<template #default>
|
||||
<div :style="{ height: fwbHeight + 'px' }" class="dict-list-box">
|
||||
<div
|
||||
v-for="(item, index) in dictDataList"
|
||||
:key="index"
|
||||
@click="onCheckedRow(item)"
|
||||
class="dict-item"
|
||||
:class="item.id == dictId ? 'active' : ''"
|
||||
<BasicTable
|
||||
:columns="columns"
|
||||
:actionColumn="actionColumn"
|
||||
:request="loadDataTable"
|
||||
:row-key="(row) => row.id"
|
||||
ref="tableRef"
|
||||
:showTableSetting="false"
|
||||
@update:checked-row-keys="onSelectionChange"
|
||||
:pagination="{ showQuickJumper: false, showSizePicker: false }"
|
||||
:row-props="rowProps"
|
||||
:row-class-name="getRowClassName"
|
||||
:autoScrollX="true"
|
||||
>
|
||||
<span class="t1"
|
||||
>{{ item.name }}<span class="t2">({{ item.code }})</span></span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<pagination
|
||||
style="justify-content: flex-end"
|
||||
class="mt-10 flex"
|
||||
@change="loadDataTable"
|
||||
v-model="pager"
|
||||
/>
|
||||
</template>
|
||||
</BasicTable>
|
||||
</n-card>
|
||||
</n-grid-item>
|
||||
<n-grid-item span="17">
|
||||
<n-grid-item span="16">
|
||||
<n-card shadow="hover" class="border-0 proCard" size="small">
|
||||
<dictItem :dictId="dictId" v-if="dictItemShow" />
|
||||
</n-card>
|
||||
@ -89,13 +72,13 @@
|
||||
:dictId="dictId"
|
||||
v-model:visible="editVisible"
|
||||
ref="createModalRef"
|
||||
@success="loadDataTable()"
|
||||
@success="reloadTable('noRefresh')"
|
||||
/>
|
||||
</PageWrapper>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, nextTick, defineAsyncComponent, onMounted } from 'vue';
|
||||
import { ref, nextTick, defineAsyncComponent, onMounted, reactive, h } from 'vue';
|
||||
import { getDictList, refreshCache, dictDelete } from '@/api/data/dictionary';
|
||||
import {
|
||||
PlusOutlined,
|
||||
@ -104,37 +87,71 @@
|
||||
SearchOutlined,
|
||||
RedoOutlined,
|
||||
} from '@vicons/antd';
|
||||
import { TableAction } from '@/components/Table';
|
||||
import { columns } from './columns';
|
||||
import editDialog from './edit.vue';
|
||||
import dictItem from './dictItem.vue';
|
||||
import { renderIcon } from '@/utils';
|
||||
import { useMessage, useDialog } from 'naive-ui';
|
||||
|
||||
/**
|
||||
* 定义参数变量
|
||||
*/
|
||||
const dictId = ref(0);
|
||||
const tableRef = ref();
|
||||
const createModalRef = ref();
|
||||
const dictItemShow = ref(false);
|
||||
const editVisible = ref(false);
|
||||
const selectionData = ref([]);
|
||||
const message = useMessage();
|
||||
const dialog = useDialog();
|
||||
|
||||
const actionColumn = reactive({
|
||||
width: 200,
|
||||
title: '操作',
|
||||
align: 'center',
|
||||
key: 'action',
|
||||
fixed: 'right',
|
||||
render(record) {
|
||||
return h(TableAction as any, {
|
||||
style: 'button',
|
||||
actions: [
|
||||
{
|
||||
label: '编辑',
|
||||
icon: renderIcon(FormOutlined),
|
||||
type: 'warning',
|
||||
auth: ['sys:dict:update'],
|
||||
onClick: handleEdit.bind(null, record),
|
||||
},
|
||||
{
|
||||
label: '删除',
|
||||
icon: renderIcon(DeleteOutlined),
|
||||
type: 'error',
|
||||
auth: ['sys:dict:delete'],
|
||||
onClick: handleDelete.bind(null, record),
|
||||
},
|
||||
],
|
||||
select: (key) => {
|
||||
message.info(`您点击了,${key} 按钮`);
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* 定义查询参数
|
||||
*/
|
||||
const params = ref({
|
||||
name: '',
|
||||
});
|
||||
const dictDataList = ref([]);
|
||||
|
||||
/**
|
||||
* 定义分页参数
|
||||
* 刷新配置项值列表
|
||||
* @param noRefresh 参数
|
||||
*/
|
||||
const pager = ref({
|
||||
page: 1,
|
||||
size: 10,
|
||||
count: dictDataList.value.length,
|
||||
});
|
||||
const fwbHeight = document.body.clientHeight - 335;
|
||||
function reloadTable(noRefresh = '') {
|
||||
tableRef.value.reload(noRefresh ? {} : { pageNo: 1 });
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行添加
|
||||
@ -149,7 +166,8 @@
|
||||
/**
|
||||
* 执行编辑
|
||||
*/
|
||||
const handleEdit = async () => {
|
||||
const handleEdit = async (row) => {
|
||||
dictId.value = row.id;
|
||||
editVisible.value = true;
|
||||
await nextTick();
|
||||
createModalRef.value.openModal();
|
||||
@ -163,46 +181,50 @@
|
||||
}
|
||||
|
||||
/**
|
||||
* 数据行选中事件
|
||||
* @param row 参数
|
||||
* 选项发生变化
|
||||
* @param value 参数
|
||||
*/
|
||||
function onCheckedRow(row) {
|
||||
dictId.value = row.id;
|
||||
function onSelectionChange(value) {
|
||||
selectionData.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载数据列表
|
||||
*/
|
||||
const loadDataTable = async () => {
|
||||
let result = await getDictList({
|
||||
...params.value,
|
||||
pageNo: pager.value.page,
|
||||
pageSize: pager.value.size,
|
||||
});
|
||||
const loadDataTable = async (res) => {
|
||||
const result = await getDictList({ ...params.value, ...res });
|
||||
dictId.value = result?.records[0]?.id;
|
||||
dictItemShow.value = true;
|
||||
dictDataList.value = result.records;
|
||||
pager.value.count = result.total;
|
||||
return result;
|
||||
};
|
||||
|
||||
/**
|
||||
* 执行删除
|
||||
*/
|
||||
async function handleDelete() {
|
||||
async function handleDelete(row) {
|
||||
dialog.warning({
|
||||
title: '提示',
|
||||
content: '确定要删除?',
|
||||
positiveText: '确定',
|
||||
negativeText: '取消',
|
||||
onPositiveClick: async () => {
|
||||
dictDelete(dictId.value);
|
||||
row ? await dictDelete(row.id) : await dictBatchDelete(selectionData.value);
|
||||
message.success('删除成功');
|
||||
pager.value.page = 1;
|
||||
loadDataTable();
|
||||
reloadTable();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
const getRowClassName = (row) => {
|
||||
return dictId.value === row.id ? 'clickRowStyle' : '';
|
||||
};
|
||||
const rowProps = (row) => {
|
||||
return {
|
||||
style: 'cursor: pointer;',
|
||||
onClick: () => {
|
||||
dictId.value = row.id;
|
||||
},
|
||||
};
|
||||
};
|
||||
/**
|
||||
* 钩子函数
|
||||
*/
|
||||
@ -259,3 +281,18 @@
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style lang="less">
|
||||
.n-data-table-tbody {
|
||||
.n-data-table-tr.clickRowStyle,
|
||||
.n-data-table-tr.clickRowStyle {
|
||||
td {
|
||||
background-color: #e7eeff !important;
|
||||
}
|
||||
&:hover {
|
||||
td {
|
||||
background-color: #e7eeff !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user