Sfoglia il codice sorgente

reactor:知识库管理表格重构完成;

zhangchong 5 mesi fa
parent
commit
e6764eedd1

+ 85 - 81
src/views/knowledge/browse/index.vue

@@ -3,7 +3,8 @@
 		<div class="layout-padding-auto layout-padding-view pd20">
 			<splitpanes class="h100" Vertical>
 				<pane min-size="16" max-size="25" size="16">
-					<el-input v-model="filterText" placeholder="请填写知识分类名称" class="input-with-select mb10" clearable @input="onQueryChanged"> </el-input>
+					<el-input v-model="filterText" placeholder="请填写知识分类名称" class="input-with-select mb10" clearable @input="onQueryChanged">
+					</el-input>
 					<el-scrollbar style="height: calc(100% - 40px);'" ref="scrollBarRef">
 						<el-skeleton :loading="state.typeLoading" animated :rows="10">
 							<template #default>
@@ -32,53 +33,78 @@
 						</el-skeleton>
 					</el-scrollbar>
 				</pane>
-				<pane class="h100">
-					<ProTable
-						ref="proTableRef"
-						:columns="columns"
-						:data="state.tableData"
-						@updateTable="queryList"
+				<pane class="h100" style="display: flex; flex-direction: column; flex: 1">
+					<el-form :model="state.queryParams" ref="ruleFormRef" inline @submit.native.prevent>
+						<el-form-item prop="Title">
+							<el-input v-model="state.queryParams.Title" placeholder="标题" clearable @keyup.enter="handleQuery" class="keyword-input" />
+						</el-form-item>
+						<el-form-item prop="CreatorName">
+							<el-input v-model="state.queryParams.CreatorName" placeholder="浏览人" clearable @keyup.enter="handleQuery" class="keyword-input" />
+						</el-form-item>
+						<el-form-item label="浏览时间" prop="crTime">
+							<el-date-picker
+								v-model="state.queryParams.crTime"
+								type="datetimerange"
+								unlink-panels
+								range-separator="至"
+								start-placeholder="开始时间"
+								end-placeholder="结束时间"
+								:shortcuts="shortcuts"
+								@change="handleQuery"
+								value-format="YYYY-MM-DD[T]HH:mm:ss"
+								:default-time="defaultTimeStartEnd"
+							/>
+						</el-form-item>
+						<el-form-item>
+							<el-button type="primary" @click="handleQuery" :loading="state.tableLoading"> <SvgIcon name="ele-Search" class="mr5" />查询 </el-button>
+							<el-button @click="resetQuery(ruleFormRef)" class="default-button" :loading="state.tableLoading">
+								<SvgIcon name="ele-Refresh" class="mr5" />重置
+							</el-button>
+						</el-form-item>
+					</el-form>
+					<vxe-toolbar
+						ref="toolbarRef"
 						:loading="state.tableLoading"
+						custom
+						:refresh="{
+							queryMethod: handleQuery,
+						}"
+						:tools="[{ toolRender: { name: 'exportCurrent' } }, { toolRender: { name: 'exportAll' } }]"
+					>
+					</vxe-toolbar>
+					<div style="overflow: hidden; width: 100%; height: 100%; flex: 1">
+						<vxe-table
+							border
+							:loading="state.tableLoading"
+							:data="state.tableData"
+							:column-config="{ resizable: true }"
+							:row-config="{ isCurrent: true, isHover: true, height: 30 }"
+							ref="tableRef"
+							height="auto"
+							auto-resize
+							show-overflow
+							:scrollY="{ enabled: true, gt: 0 }"
+							id="knowledgeBrowse"
+							:custom-config="{ storage: true }"
+							showHeaderOverflow
+							:params="{ exportMethod: KnowledgePageViewExport, exportParams: requestParams }"
+						>
+							<vxe-column field="knowledgeTitle" title="标题" min-width="200"></vxe-column>
+							<vxe-column field="creatorName" title="浏览人" min-width="120"></vxe-column>
+							<vxe-column field="creationTime" title="浏览时间" width="160">
+								<template #default="{ row }">
+									{{ formatDate(row.creationTime, 'YYYY-mm-dd HH:MM:SS') }}
+								</template>
+							</vxe-column>
+						</vxe-table>
+					</div>
+					<pagination
+						@pagination="queryList"
 						:total="state.total"
-						v-model:page-index="state.queryParams.PageIndex"
+						v-model:current-page="state.queryParams.PageIndex"
 						v-model:page-size="state.queryParams.PageSize"
-						:toolButton="['refresh', 'setting', 'exportCurrent', 'exportAll']"
-						:exportMethod="KnowledgePageViewExport"
-						:exportParams="requestParams"
-					>
-						<template #table-search>
-							<el-form :model="state.queryParams" ref="ruleFormRef" inline @submit.native.prevent>
-								<el-form-item prop="Title">
-									<el-input v-model="state.queryParams.Title" placeholder="标题" clearable @keyup.enter="handleQuery" class="keyword-input" />
-								</el-form-item>
-								<el-form-item prop="CreatorName">
-									<el-input v-model="state.queryParams.CreatorName" placeholder="浏览人" clearable @keyup.enter="handleQuery" class="keyword-input" />
-								</el-form-item>
-								<el-form-item label="浏览时间" prop="crTime">
-									<el-date-picker
-										v-model="state.queryParams.crTime"
-										type="datetimerange"
-										unlink-panels
-										range-separator="至"
-										start-placeholder="开始时间"
-										end-placeholder="结束时间"
-										:shortcuts="shortcuts"
-										@change="handleQuery"
-										value-format="YYYY-MM-DD[T]HH:mm:ss"
-										:default-time="defaultTimeStartEnd"
-									/>
-								</el-form-item>
-								<el-form-item>
-									<el-button type="primary" @click="handleQuery" :loading="state.tableLoading">
-										<SvgIcon name="ele-Search" class="mr5" />查询
-									</el-button>
-									<el-button @click="resetQuery(ruleFormRef)" class="default-button" :loading="state.tableLoading">
-										<SvgIcon name="ele-Refresh" class="mr5" />重置
-									</el-button>
-								</el-form-item>
-							</el-form>
-						</template>
-					</ProTable>
+						:disabled="state.tableLoading"
+					/>
 				</pane>
 			</splitpanes>
 		</div>
@@ -88,7 +114,6 @@
 <script lang="tsx" setup name="knowledgeBrowse">
 import { defineAsyncComponent, onMounted, reactive, ref } from 'vue';
 import type { FormInstance } from 'element-plus';
-import { getCanUseOrgByUser } from '@/api/system/user';
 import { Splitpanes, Pane } from 'splitpanes';
 import 'splitpanes/dist/splitpanes.css';
 import Other from '@/utils/other';
@@ -98,20 +123,7 @@ import { defaultTimeStartEnd, shortcuts } from '@/utils/constants';
 import { KnowledgePageViewExport, KnowledgePageViewPaged } from '@/api/knowledge/browse';
 
 const TextTooltip = defineAsyncComponent(() => import('@/components/TextTooltip/index.vue'));
-const proTableRef = ref<RefType>(); // 表格ref
-// 表格配置项
-const columns = ref<any[]>([
-	{ prop: 'knowledgeTitle', label: '标题', minWidth: 200 },
-	{ prop: 'creatorName', label: '浏览人', minWidth: 120 },
-	{
-		prop: 'creationTime',
-		label: '浏览时间',
-		minWidth: 160,
-		render: (scope: any) => {
-			return <span>{formatDate(scope.row.creationTime, 'YYYY-mm-dd HH:MM:SS')}</span>;
-		},
-	},
-]);
+const pagination = defineAsyncComponent(() => import('@/components/ProTable/components/Pagination.vue')); // 分页
 // 定义变量内容
 const state = reactive<any>({
 	queryParams: {
@@ -119,21 +131,15 @@ const state = reactive<any>({
 		PageSize: 20, // 每页条数
 		Title: null, // 标题
 		CreatorName: null, // 浏览人
-		crTime:[], // 创建时间
-		StartTime:null,
-		EndTime:null,
-		KnowledgeTypeId:null, // 知识分类Id
+		crTime: [], // 创建时间
+		StartTime: null,
+		EndTime: null,
+		KnowledgeTypeId: null, // 知识分类Id
 	},
 	tableData: [], // 表格数据
 	total: 0, // 总条数
 	loading: false, // 加载状态
 	tableLoading: false, // 表格加载状态
-	orgData: [], // 组织结构数据
-	roleOptions: [], // 角色数据
-	baseData: [], // 基础数据
-	telsList: [], // 分机数据
-	telsListGroup: [], //分机组
-
 	knowledgeOptions: [], //知识库类型数据
 });
 const ruleFormRef = ref<FormInstance>(); //表单ref
@@ -163,9 +169,9 @@ const requestParams = ref<EmptyObjectType>({});
 const queryList = () => {
 	state.tableLoading = true;
 	requestParams.value = Other.deepClone(state.queryParams);
-	requestParams.value .StartTime = state.queryParams.crTime === null ? null : state.queryParams.crTime[0];
-	requestParams.value .EndTime = state.queryParams.crTime === null ? null : state.queryParams.crTime[1];
-	Reflect.deleteProperty(requestParams.value , 'crTime');
+	requestParams.value.StartTime = state.queryParams.crTime === null ? null : state.queryParams.crTime[0];
+	requestParams.value.EndTime = state.queryParams.crTime === null ? null : state.queryParams.crTime[1];
+	Reflect.deleteProperty(requestParams.value, 'crTime');
 	KnowledgePageViewPaged(requestParams.value)
 		.then((response: any) => {
 			state.tableData = response?.result.items ?? [];
@@ -200,15 +206,13 @@ const getKnowledgeType = async () => {
 		state.typeLoading = false;
 	}
 };
+const toolbarRef = ref<RefType>();
+const tableRef = ref<RefType>();
 onMounted(() => {
-	getKnowledgeType();
 	queryList();
+	if (tableRef.value && toolbarRef.value) {
+		tableRef.value.connect(toolbarRef.value);
+	}
+	getKnowledgeType();
 });
 </script>
-<style lang="scss" scoped>
-.knowledge-browse-container {
-	:deep(.pro-table-main) {
-		height: 100%;
-	}
-}
-</style>

+ 73 - 59
src/views/knowledge/collect/index.vue

@@ -32,38 +32,69 @@
 						</el-skeleton>
 					</el-scrollbar>
 				</pane>
-				<pane class="h100">
-					<ProTable
-						ref="proTableRef"
-						:columns="columns"
-						:data="state.tableData"
-						@updateTable="queryList"
-						:loading="state.loading"
+				<pane class="h100" style="display: flex; flex-direction: column; flex: 1">
+					<el-form :model="state.queryParams" ref="ruleFormRef" inline @submit.native.prevent>
+						<el-form-item label="关键词" prop="Keyword">
+							<el-input v-model="state.queryParams.Keyword" placeholder="关键词" clearable @keyup.enter="handleQuery" class="keyword-input" />
+						</el-form-item>
+						<el-form-item>
+							<el-button type="primary" @click="handleQuery" :loading="state.loading"> <SvgIcon name="ele-Search" class="mr5" />查询 </el-button>
+							<el-button @click="resetQuery(ruleFormRef)" class="default-button"> <SvgIcon name="ele-Refresh" class="mr5" />重置 </el-button>
+						</el-form-item>
+					</el-form>
+					<vxe-toolbar
+						ref="toolbarRef"
+						:loading="state.tableLoading"
+						custom
+						:refresh="{
+							queryMethod: handleQuery,
+						}"
+					>
+					</vxe-toolbar>
+					<div style="overflow: hidden; width: 100%; height: 100%; flex: 1">
+						<vxe-table
+							border
+							:loading="state.tableLoading"
+							:data="state.tableData"
+							:column-config="{ resizable: true }"
+							:row-config="{ isCurrent: true, isHover: true, height: 30 }"
+							ref="tableRef"
+							height="auto"
+							auto-resize
+							show-overflow
+							:scrollY="{ enabled: true, gt: 0 }"
+							id="knowledgeCollect"
+							:custom-config="{ storage: true }"
+							showHeaderOverflow
+						>
+							<vxe-column field="knowledge.title" title="标题" min-width="200">
+								<template #default="{ row }">
+									<el-button link type="primary" @click="onPreview(row)">{{ row.knowledge?.title }}</el-button>
+								</template>
+							</vxe-column>
+							<vxe-column field="knowledgeType" title="知识分类" width="150"></vxe-column>
+							<vxe-column field="knowledge.statusText" title="知识状态" width="100"></vxe-column>
+							<vxe-column field="score" title="知识评分" width="120"></vxe-column>
+							<vxe-column field="creatorName" title="收藏人" width="120"></vxe-column>
+							<vxe-column field="creationTime" title="收藏时间" width="160">
+								<template #default="{ row }">
+									{{ formatDate(row.creationTime, 'YYYY-mm-dd HH:MM:SS') }}
+								</template>
+							</vxe-column>
+							<vxe-column title="操作" fixed="right" width="100" align="center" :show-overflow="false">
+								<template #default="{ row }">
+									<el-button link type="primary" @click="onPreview(row)" title="知识详情"> 知识详情 </el-button>
+								</template>
+							</vxe-column>
+						</vxe-table>
+					</div>
+					<pagination
+						@pagination="queryList"
 						:total="state.total"
-						v-model:page-index="state.queryParams.PageIndex"
+						v-model:current-page="state.queryParams.PageIndex"
 						v-model:page-size="state.queryParams.PageSize"
-					>
-						<template #table-search>
-							<el-form :model="state.queryParams" ref="ruleFormRef" inline @submit.native.prevent>
-								<el-form-item label="关键词" prop="Keyword">
-									<el-input v-model="state.queryParams.Keyword" placeholder="关键词" clearable @keyup.enter="handleQuery" class="keyword-input" />
-								</el-form-item>
-								<el-form-item>
-									<el-button type="primary" @click="handleQuery" :loading="state.loading"> <SvgIcon name="ele-Search" class="mr5" />查询 </el-button>
-									<el-button @click="resetQuery(ruleFormRef)" class="default-button"> <SvgIcon name="ele-Refresh" class="mr5" />重置 </el-button>
-								</el-form-item>
-							</el-form>
-						</template>
-						<template #title="{ row }">
-							<el-button link type="primary" @click="onPreview(row)">{{ row.knowledge?.title }}</el-button>
-						</template>
-						<template #knowledgeType="{ row }">
-							<span>{{ row.knowledge?.knowledgeType?.map((item) => item.value).join(',') }}</span>
-						</template>
-						<template #operation="{ row }">
-							<el-button link type="primary" @click="onPreview(row)" title="知识详情"> 知识详情 </el-button>
-						</template>
-					</ProTable>
+						:disabled="state.tableLoading"
+					/>
 				</pane>
 			</splitpanes>
 		</div>
@@ -79,29 +110,10 @@ import { useRouter } from 'vue-router';
 import { collectList, delCollectGroup, getCollectList } from '@/api/knowledge/collect';
 import { Splitpanes, Pane } from 'splitpanes';
 import 'splitpanes/dist/splitpanes.css';
-import { knowledgeCollect } from '@/api/knowledge';
-import mittBus from '@/utils/mitt';
 
 const TextTooltip = defineAsyncComponent(() => import('@/components/TextTooltip/index.vue'));
 const CollectGroupAdd = defineAsyncComponent(() => import('@/views/knowledge/collect/components/Collect-group-add.vue')); // 收藏分组新增
-const proTableRef = ref<RefType>(); // 表格ref
-// 表格配置项
-const columns = ref<any[]>([
-	{ prop: 'knowledge.title', label: '知识标题', minWidth: 200 },
-	{ prop: 'knowledgeType', label: '知识分类', minWidth: 150 },
-	{ prop: 'knowledge.statusText', label: '知识状态', minWidth: 100 },
-	{ prop: 'score', label: '知识评分' },
-	{ prop: 'creatorName', label: '收藏人', minWidth: 120 },
-	{
-		prop: 'creationTime',
-		label: '收藏时间',
-		minWidth: 160,
-		render: (scope) => {
-			return <span>{formatDate(scope.row.creationTime, 'YYYY-mm-dd HH:MM:SS')}</span>;
-		},
-	},
-	{ prop: 'operation', label: '操作', fixed: 'right', width: 90, align: 'center' },
-]);
+const pagination = defineAsyncComponent(() => import('@/components/ProTable/components/Pagination.vue')); // 分页
 // 定义变量内容
 const state = reactive<any>({
 	loading: false, // 加载状态
@@ -191,12 +203,12 @@ const renderContent = (h, { node, data }) => {
 			<TextTooltip content={node.label} effect="dark" placement="top"></TextTooltip>
 			{node.label === '全部' ? (
 				<span>
-					<el-button link type="primary" onClick={(event:MouseEvent) => appendGroup(event)}>
+					<el-button link type="primary" onClick={(event: MouseEvent) => appendGroup(event)}>
 						新增
 					</el-button>
 				</span>
 			) : (
-				<el-button link type="danger" onClick={(event:MouseEvent) => deleteGroup(event,node)}>
+				<el-button link type="danger" onClick={(event: MouseEvent) => deleteGroup(event, node)}>
 					删除
 				</el-button>
 			)}
@@ -205,13 +217,13 @@ const renderContent = (h, { node, data }) => {
 };
 // 新增节点
 const collectGroupAddRef = ref<RefType>();
-const appendGroup= (event:MouseEvent) => {
+const appendGroup = (event: MouseEvent) => {
 	// 阻止事件冒泡
 	event.stopPropagation();
 	collectGroupAddRef.value.openDialog();
 };
 // 删除节点
-const deleteGroup = (event:MouseEvent,node: any)=>{
+const deleteGroup = (event: MouseEvent, node: any) => {
 	// 阻止事件冒泡
 	event.stopPropagation();
 	ElMessageBox.confirm(`删除分组将同步取消该分组下已收藏的知识,是否确认删除?`, '提示', {
@@ -236,23 +248,25 @@ const deleteGroup = (event:MouseEvent,node: any)=>{
 				});
 		})
 		.catch(() => {});
-}
+};
 // 点击节点
 const handleNodeClick = (data: any) => {
 	state.queryParams.KnowledgeCollectGroupId = data.id;
 	queryList();
 };
 // 页面加载时
+const toolbarRef = ref<RefType>();
+const tableRef = ref<RefType>();
 onMounted(() => {
-	getCollectGroupOptions();
 	queryList();
+	if (tableRef.value && toolbarRef.value) {
+		tableRef.value.connect(toolbarRef.value);
+	}
+	getCollectGroupOptions();
 });
 </script>
 <style lang="scss" scoped>
 .knowledge-collect-container {
-	:deep(.pro-table-main) {
-		height: 100%;
-	}
 	:deep(.el-tree-node__content) {
 		height: 36px;
 	}

+ 119 - 208
src/views/knowledge/config/type/index.vue

@@ -1,67 +1,91 @@
 <template>
 	<div class="knowledge-type-container layout-padding">
 		<div class="layout-padding-auto layout-padding-view pd20">
-			<el-row class="mb20" :gutter="10">
-				<el-col :xs="24" :sm="12" :md="18" :lg="18" :xl="18">
-					<el-form :model="state.queryParams" ref="ruleFormRef" inline @submit.native.prevent>
-						<el-form-item label="关键字" prop="keyword" class="mb0">
-							<el-input v-model="state.queryParams.keyword" placeholder="类型名称" clearable @keyup.enter="handleQuery" class="keyword-input" />
-						</el-form-item>
-						<el-form-item class="mb0">
-							<el-button type="primary" @click="handleQuery" :loading="state.loading"> <SvgIcon name="ele-Search" class="mr5" />查询 </el-button>
-							<el-button @click="resetQuery(ruleFormRef)" class="default-button" :loading="state.loading">
-								<SvgIcon name="ele-Refresh" class="mr5" />重置
-							</el-button>
-						</el-form-item>
-					</el-form>
-				</el-col>
-				<el-col :xs="24" :sm="12" :md="6" :lg="6" :xl="6" style="text-align: right">
-					<el-button type="primary" @click="expand">
-						<SvgIcon
-							name="ele-ArrowDownBold"
-							style="transition: transform var(--el-transition-duration)"
-							:style="state.isExpand ? 'transform: none' : 'transform: rotateZ(180deg)'"
-							class="mr5"
-						/>
-						{{ state.isExpand ? '收起' : '展开' }}</el-button
-					>
-					<el-button type="primary" @click="onOpenAdd" v-auth="'knowledge:type:add'"> <SvgIcon name="ele-Plus" class="mr5" /> 新增 </el-button>
-				</el-col>
-			</el-row>
-			<el-auto-resizer class="table" v-loading="state.loading">
-				<template #default="{ height, width }">
-					<el-table-v2
-						v-model:expanded-row-keys="state.expandedRowKeys"
-						:columns="state.columns"
-						:data="state.tableData"
-						expand-column-key="name"
-						fixed
-						:width="width"
-						:height="height"
-						ref="virtuallyTableRef"
-            :scrollbar-always-on="true"
-            :row-height="40"
-            :header-height="40"
-					>
-					</el-table-v2>
+			<el-form :model="state.queryParams" ref="ruleFormRef" inline @submit.native.prevent>
+				<el-form-item label="关键字" prop="keyword" class="mb0">
+					<el-input v-model="state.queryParams.keyword" placeholder="类型名称" clearable @keyup.enter="handleQuery" class="keyword-input" />
+				</el-form-item>
+				<el-form-item class="mb0">
+					<el-button type="primary" @click="handleQuery" :loading="state.loading"> <SvgIcon name="ele-Search" class="mr5" />查询 </el-button>
+					<el-button @click="resetQuery(ruleFormRef)" class="default-button" :loading="state.loading">
+						<SvgIcon name="ele-Refresh" class="mr5" />重置
+					</el-button>
+				</el-form-item>
+			</el-form>
+			<vxe-toolbar
+				ref="toolbarRef"
+				:loading="state.loading"
+				custom
+				:refresh="{
+					queryMethod: handleQuery,
+				}"
+			>
+				<template #buttons>
+					<el-button type="primary" @click="onOpenAdd" v-auth="'knowledge:type:add'"> <SvgIcon name="ele-Plus" class="mr5" /> 新增类型 </el-button>
 				</template>
-			</el-auto-resizer>
+			</vxe-toolbar>
+			<div style="overflow: hidden; width: 100%; height: 100%; flex: 1">
+				<vxe-table
+					:loading="state.loading"
+					:data="list"
+					:column-config="{ resizable: true, useKey: true }"
+					:row-config="{ isCurrent: true, isHover: true, useKey: true, height: 36 }"
+					ref="tableRef"
+					height="auto"
+					auto-resize
+					show-overflow
+					:scrollY="{ enabled: true, gt: 0 }"
+					id="knowledgeType"
+					:custom-config="{ storage: true }"
+					showHeaderOverflow
+					:tree-config="{
+						childrenField: 'children',
+						transform: true,
+						rowField: 'id',
+						parentField: 'parentId',
+					}"
+				>
+					<vxe-column field="name" title="类型名称" min-width="400" treeNode>
+						<template #default="{ row }">
+							<p style="display: flex; align-items: center">
+								<span class="pl5" v-html="row.name"></span>
+							</p>
+						</template>
+					</vxe-column>
+					<vxe-column field="sort" title="排序" width="80"></vxe-column>
+					<vxe-column field="lastModificationTime" title="更新时间" width="160">
+						<template #default="{ row }">
+							{{ formatDate(row.lastModificationTime, 'YYYY-mm-dd HH:MM:SS') }}
+						</template>
+					</vxe-column>
+					<vxe-column field="isEnable" title="状态" width="120" align="center">
+						<template #default="{ row }">
+							<el-tag :type="row.isEnable ? 'success' : 'info'">{{ row.isEnable ? '启用' : '禁用' }}</el-tag>
+						</template>
+					</vxe-column>
+					<vxe-column title="操作" fixed="right" width="180" align="center" :show-overflow="false">
+						<template #default="{ row }">
+							<el-button link type="primary" @click="onConnect(row)" title="关联组织" v-auth="'knowledge:type:connect'"> 关联组织 </el-button>
+							<el-button link type="primary" @click="onOpenEdit(row)" title="修改" v-auth="'knowledge:type:edit'"> 修改 </el-button>
+							<el-button link type="danger" @click="onDelete(row)" title="删除" v-auth="'knowledge:type:delete'"> 删除 </el-button>
+						</template>
+					</vxe-column>
+				</vxe-table>
+			</div>
 		</div>
 		<knowledge-type-add ref="knowledgeTypeAddRef" @updateList="queryList" />
 		<knowledge-type-edit ref="knowledgeTypeEditRef" @updateList="queryList" />
-    <knowledge-type-connect ref="knowledgeTypeConnectRef" @updateList="queryList" />
+		<knowledge-type-connect ref="knowledgeTypeConnectRef" @updateList="queryList" />
 	</div>
 </template>
 <script lang="tsx" setup name="knowledgeType">
-import { defineAsyncComponent, onActivated, onMounted, reactive, ref, watch } from 'vue';
+import { defineAsyncComponent, nextTick, onMounted, reactive, ref } from 'vue';
 import type { FormInstance } from 'element-plus';
 import { ElMessage, ElMessageBox } from 'element-plus';
-import { auth } from '@/utils/authFunction';
 import { formatDate } from '@/utils/formatTime';
 import { delType, treeList } from '@/api/knowledge/type';
 import { throttle } from '@/utils/tools';
-import other from '@/utils/other';
-import { getCanUseOrg } from "@/api/system/user";
+import XEUtils from 'xe-utils';
 // 引入组件
 const KnowledgeTypeAdd = defineAsyncComponent(() => import('@/views/knowledge/config/type/components/Knowledge-type-add.vue')); // 新增组件
 const KnowledgeTypeEdit = defineAsyncComponent(() => import('@/views/knowledge/config/type/components/Knowledge-type-edit.vue')); // 修改组件
@@ -71,158 +95,22 @@ const TextTooltip = defineAsyncComponent(() => import('@/components/TextTooltip/
 // 定义变量内容
 const ruleFormRef = ref<RefType>(); // 表单ref
 const state = reactive<any>({
-	tableData: [], // 获取所有菜单
-	staticArr: [], // 获取所有菜单
 	loading: false, // 加载状态
-	isExpand: false, // 是否展开
 	queryParams: {
 		// 查询参数
 		keyword: null,
 	},
-	expandedRowKeys: [], // 展开的行
-	columns: [
-		{
-			key: 'name',
-			dataKey: 'name',
-			title: '类型名称',
-			width: 600,
-      cellRenderer: (data: any) => {
-        return <TextTooltip content={data.rowData.name} effect="dark" placement="top"></TextTooltip>;
-      },
-		},
-		{
-			key: 'sort',
-			dataKey: 'sort',
-			title: '排序',
-			width: 150,
-		},
-		{
-			key: 'lastModificationTime',
-			dataKey: 'lastModificationTime',
-			title: '更新时间',
-			width: 200,
-			cellRenderer: (data: any) => {
-				return <span>{formatDate(new Date(data.rowData.lastModificationTime), 'YYYY-mm-dd HH:MM:SS')}</span>;
-			},
-		},
-		{
-			key: 'isEnable',
-			dataKey: 'isEnable',
-			title: '状态',
-			width: 100,
-			cellRenderer: (data: any) => {
-				return <el-tag type={data.rowData.isEnable ? 'success' : 'info'}>{data.rowData.isEnable ? '启用' : '禁用'}</el-tag>;
-			},
-		},
-		{
-			key: 'handle',
-			title: '操作',
-			width: 170,
-			fixed: 'right',
-			align: 'center',
-			cellRenderer: (data: any) => {
-				return (
-					<span>
-            {auth('knowledge:type:connect') ? (
-              <ElButton onClick={() => onConnect(data.rowData)} type="primary" title="关联组织" link>
-                关联组织
-              </ElButton>
-            ) : (
-              ''
-            )}
-						{auth('knowledge:type:edit') ? (
-							<ElButton onClick={() => onOpenEdit(data.rowData)} type="primary" title="修改菜单" link>
-								修改
-							</ElButton>
-						) : (
-							''
-						)}
-						{auth('knowledge:type:delete') ? (
-							<ElButton onClick={() => onDelete(data.rowData)} type="danger" title="删除分类" link>
-								删除
-							</ElButton>
-						) : (
-							''
-						)}
-					</span>
-				);
-			},
-		},
-	],
 });
-// 表格过滤
-const formatTable = (list: any[], keyword: string) => {
-	if (!list.length || !Array.isArray(list)) return [];
-	let emptyArr: any[] = [];
-	list.map((item) => {
-		if (item.name.includes(keyword)) {
-			if (item.children && Array.isArray(item.children) && item.children.length > 0) {
-				item.children = formatTable(item.children, keyword);
-			}
-			emptyArr.push(item);
-		} else if (item.children && Array.isArray(item.children) && item.children.length > 0) {
-			item.children = formatTable(item.children, keyword);
-			if (item.children.length) {
-				emptyArr.push(item);
-			}
-		}
-	});
-	return emptyArr;
-};
-let emptyArr: any[] = [];
-const getExpand = (list: any[]) => {
-	if (!list.length || !Array.isArray(list)) return [];
-	list.map((item) => {
-		if (item.children && Array.isArray(item.children) && item.children.length > 0) {
-			getExpand(item.children);
-		}
-		emptyArr.push(item.id);
-	});
-	return emptyArr;
-};
 /** 搜索按钮操作 节流操作 */
-const handleQuery = throttle(() => {
-	if (state.queryParams.keyword) {
-		state.loading = true;
-		state.expandedRowKeys = [];
-		emptyArr = [];
-		state.tableData = formatTable(other.deepClone(state.staticArr), state.queryParams.keyword);
-		state.expandedRowKeys = getExpand(state.tableData);
-		state.isExpand = true;
-		state.loading = false;
-	} else {
-		queryList();
-	}
-}, 500);
+const handleQuery = () => {
+	queryList();
+};
 /** 重置按钮操作 */
 const resetQuery = throttle((formEl: FormInstance | undefined) => {
 	if (!formEl) return;
 	formEl.resetFields();
 	queryList();
-	state.expandedRowKeys = [];
-	emptyArr = [];
-	state.isExpand = false;
-}, 500);
-// 展开收起
-const expand = () => {
-	state.isExpand = !state.isExpand;
-};
-watch(
-	() => state.isExpand,
-	(old: Boolean) => {
-		if (old) getAllIds(state.tableData);
-		else state.expandedRowKeys = [];
-	}
-);
-const getAllIds = (arr: any) => {
-	if (!arr) return [];
-	arr.forEach((v: any) => {
-		if (v.children?.length) {
-			getAllIds(v.children);
-			state.expandedRowKeys.push(v.id);
-		}
-	});
-};
+}, 300);
 // 打开新增分类弹窗
 const knowledgeTypeAddRef = ref<RefType>(); // 新增ref
 const onOpenAdd = () => {
@@ -255,37 +143,60 @@ const onConnect = (row: any) => {
 	knowledgeTypeConnectRef.value.openDialog(row);
 };
 // 获取知识库类型
+const tableRef = ref<RefType>();
+const tableData = ref<EmptyArrayType>([]);
+const list = ref<any[]>([]);
 const queryList = () => {
 	state.loading = true;
 	treeList()
 		.then((res: any) => {
-			state.tableData = res?.result ?? [];
-			state.staticArr = res?.result ?? [];
-			state.expandedRowKeys = state.tableData.map((v: any) => {
-				return v.children.map((i: any) => {
-					return i.id;
+			tableData.value = res?.result ?? [];
+			const filterVal = XEUtils.toValueString(state.queryParams.keyword)?.trim().toLowerCase();
+			if (filterVal) {
+				const filterRE = new RegExp(filterVal, 'gi');
+				const options = { children: 'children' };
+				const searchProps = ['name'];
+				// 搜索为克隆数据,不会污染源数据
+				const rest = XEUtils.searchTree(
+					tableData.value,
+					(item) => searchProps.some((key) => String(item[key]).toLowerCase().indexOf(filterVal) > -1),
+					options
+				);
+				XEUtils.eachTree(
+					rest,
+					(item) => {
+						searchProps.forEach((key) => {
+							item[key] = String(item[key]).replace(filterRE, (match) => `<span class="keyword-highlight">${match}</span>`);
+						});
+					},
+					options
+				);
+				list.value = rest;
+				list.value = XEUtils.toTreeArray(list.value);
+				nextTick(() => {
+					// 搜索之后默认展开所有子节点
+					if (tableRef.value) {
+						tableRef.value.setAllTreeExpand(true);
+					}
 				});
-			});
-			state.expandedRowKeys.push(state.tableData[0].id); //默认展开一级
+			} else {
+				list.value = tableData.value;
+				list.value = XEUtils.toTreeArray(list.value);
+			}
+
 			state.loading = false;
 		})
-		.catch(() => {
+		.catch((err) => {
+			console.log(err);
 			state.loading = false;
 		});
 };
 // 页面加载时
+const toolbarRef = ref<RefType>();
 onMounted(() => {
 	queryList();
-});
-const virtuallyTableRef = ref<RefType>();
-onActivated(() => {
-	virtuallyTableRef.value.scrollToTop(0); // 回到顶部
+	if (tableRef.value && toolbarRef.value) {
+		tableRef.value.connect(toolbarRef.value);
+	}
 });
 </script>
-<style lang="scss" scoped>
-.knowledge-type-container {
-	.table {
-		flex: 1;
-	}
-}
-</style>

+ 99 - 83
src/views/knowledge/error/index.vue

@@ -1,62 +1,100 @@
 <template>
 	<div class="knowledge-error-container layout-padding">
 		<div class="layout-padding-auto layout-padding-view pd20">
-			<ProTable
-				ref="proTableRef"
-				:columns="columns"
-				:data="state.tableData"
-				@updateTable="queryList"
-				:loading="state.loading"
+			<el-form :model="state.queryParams" ref="ruleFormRef" inline @submit.native.prevent>
+				<el-form-item label="纠错人" prop="CreatorName">
+					<el-input v-model="state.queryParams.CreatorName" placeholder="请填写纠错人" clearable @keyup.enter="handleQuery" class="keyword-input" />
+				</el-form-item>
+				<el-form-item label="知识分类" prop="KnowledgeTypeId">
+					<el-cascader
+						:options="state.typeData"
+						filterable
+						:props="{ checkStrictly: true, value: 'id', label: 'name', emitPath: false, children: 'children' }"
+						placeholder="请选择知识分类"
+						v-model="state.queryParams.KnowledgeTypeId"
+						ref="cascadeRef"
+						@change="handleQuery"
+					>
+					</el-cascader>
+				</el-form-item>
+				<el-form-item>
+					<el-button type="primary" @click="handleQuery" :loading="state.loading"> <SvgIcon name="ele-Search" class="mr5" />查询 </el-button>
+					<el-button @click="resetQuery(ruleFormRef)" v-waves class="default-button"> <SvgIcon name="ele-Refresh" class="mr5" />重置 </el-button>
+				</el-form-item>
+			</el-form>
+			<vxe-toolbar
+				ref="toolbarRef"
+				:loading="state.tableLoading"
+				custom
+				:refresh="{
+					queryMethod: handleQuery,
+				}"
+			>
+			</vxe-toolbar>
+			<div style="overflow: hidden; width: 100%; height: 100%; flex: 1">
+				<vxe-table
+					border
+					:loading="state.tableLoading"
+					:data="state.tableData"
+					:column-config="{ resizable: true }"
+					:row-config="{ isCurrent: true, isHover: true, height: 30 }"
+					ref="tableRef"
+					height="auto"
+					auto-resize
+					show-overflow
+					:scrollY="{ enabled: true, gt: 0 }"
+					id="knowledgeError"
+					:custom-config="{ storage: true }"
+					showHeaderOverflow
+				>
+					<vxe-column field="knowledge.title" title="标题" min-width="200">
+						<template #default="{row}">
+							<el-button link type="primary" @click="onPreview(row)">{{ row.knowledge?.title }}</el-button>
+						</template>
+					</vxe-column>
+					<vxe-column field="knowledgeType" title="知识分类" width="150"></vxe-column>
+					<vxe-column field="knowledge.statusText" title="知识状态" width="100"></vxe-column>
+					<vxe-column field="stateText" title="答复状态" width="120"></vxe-column>
+					<vxe-column field="creatorName" title="纠错人" width="120"></vxe-column>
+					<vxe-column field="creationTime" title="纠错时间" width="160">
+						<template #default="{ row }">
+							{{ formatDate(row.creationTime, 'YYYY-mm-dd HH:MM:SS') }}
+						</template>
+					</vxe-column>
+					<vxe-column field="content" title="纠错内容" width="150"></vxe-column>
+					<vxe-column field="replyContent" title="答复内容" width="150"></vxe-column>
+					<vxe-column field="replyTime" title="答复时间" width="160">
+						<template #default="{ row }">
+							{{ formatDate(row.replyTime, 'YYYY-mm-dd HH:MM:SS') }}
+						</template>
+					</vxe-column>
+					<vxe-column title="操作" fixed="right" width="140" align="center">
+						<template #default="{ row }">
+							<el-button link type="primary" @click="onPreview(row)" title="知识详情"> 知识详情 </el-button>
+							<el-button link type="primary" @click="onReply(row)" v-auth="'knowledge:error:reply'" title="答复" v-if="[0].includes(row.state)">
+								答复
+							</el-button>
+							<el-button
+								link
+								type="primary"
+								@click="onEdit(row)"
+								title="编辑"
+								v-if="[0, 4].includes(row.knowledge?.status)"
+								v-auth="'knowledge:error:edit'"
+							>
+								编辑
+							</el-button>
+						</template>
+					</vxe-column>
+				</vxe-table>
+			</div>
+			<pagination
+				@pagination="queryList"
 				:total="state.total"
-				v-model:page-index="state.queryParams.PageIndex"
+				v-model:current-page="state.queryParams.PageIndex"
 				v-model:page-size="state.queryParams.PageSize"
-			>
-        <template #table-search>
-          <el-form :model="state.queryParams" ref="ruleFormRef" inline @submit.native.prevent>
-            <el-form-item label="纠错人" prop="CreatorName">
-              <el-input v-model="state.queryParams.CreatorName" placeholder="请填写纠错人" clearable @keyup.enter="handleQuery" class="keyword-input" />
-            </el-form-item>
-            <el-form-item label="知识分类" prop="KnowledgeTypeId">
-              <el-cascader
-                  :options="state.typeData"
-                  filterable
-                  :props="{ checkStrictly: true, value: 'id', label: 'name', emitPath: false, children: 'children' }"
-                  placeholder="请选择知识分类"
-                  v-model="state.queryParams.KnowledgeTypeId"
-                  ref="cascadeRef"
-                  @change="handleQuery"
-              >
-              </el-cascader>
-            </el-form-item>
-            <el-form-item>
-              <el-button type="primary" @click="handleQuery" :loading="state.loading"> <SvgIcon name="ele-Search" class="mr5" />查询 </el-button>
-              <el-button @click="resetQuery(ruleFormRef)" v-waves class="default-button"> <SvgIcon name="ele-Refresh" class="mr5" />重置 </el-button>
-            </el-form-item>
-          </el-form>
-        </template>
-				<template #title="{ row }">
-					<el-button link type="primary" @click="onPreview(row)">{{ row.knowledge?.title }}</el-button>
-				</template>
-				<template #knowledgeType="{ row }">
-					<span>{{ row.knowledge?.knowledgeType?.map((item) => item.value).join(',') }}</span>
-				</template>
-				<template #operation="{ row }">
-					<el-button link type="primary" @click="onPreview(row)" title="知识详情"> 知识详情 </el-button>
-					<el-button link type="primary" @click="onReply(row)" v-auth="'knowledge:error:reply'" title="答复" v-if="[0].includes(row.state)">
-						答复
-					</el-button>
-					<el-button
-						link
-						type="primary"
-						@click="onEdit(row)"
-						title="编辑"
-						v-if="[0, 4].includes(row.knowledge?.status)"
-						v-auth="'knowledge:error:edit'"
-					>
-						编辑
-					</el-button>
-				</template>
-			</ProTable>
+				:disabled="state.tableLoading"
+			/>
 		</div>
 		<!-- 知识纠错 -->
 		<error-add ref="errorAddRef" @submitSuccess="queryList" />
@@ -73,35 +111,8 @@ import { treeList } from '@/api/knowledge/type';
 
 // 引入组件
 const ErrorAdd = defineAsyncComponent(() => import('@/views/knowledge/error/components/Error-add.vue')); // 知识纠错
+const pagination = defineAsyncComponent(() => import('@/components/ProTable/components/Pagination.vue')); // 分页
 
-const proTableRef = ref<RefType>(); // 表格ref
-// 表格配置项
-const columns = ref<any[]>([
-	{ prop: 'knowledge.title', label: '知识标题', minWidth: 200 },
-	{ prop: 'knowledgeType', label: '知识分类', minWidth: 150 },
-	{ prop: 'knowledge.statusText', label: '知识状态' },
-	{ prop: 'stateText', label: '答复状态' },
-	{ prop: 'creatorName', label: '纠错人', minWidth: 120 },
-	{
-		prop: 'creationTime',
-		label: '纠错时间',
-		minWidth: 160,
-		render: (scope) => {
-			return <span>{formatDate(scope.row.creationTime, 'YYYY-mm-dd HH:MM:SS')}</span>;
-		},
-	},
-	{ prop: 'content', label: '纠错内容' },
-	{ prop: 'replyContent', label: '答复内容', minWidth: 150 },
-	{
-		prop: 'replyTime',
-		label: '答复时间',
-		minWidth: 160,
-		render: (scope) => {
-			return <span>{formatDate(scope.row.replyTime, 'YYYY-mm-dd HH:MM:SS')}</span>;
-		},
-	},
-	{ prop: 'operation', label: '操作', fixed: 'right', width: 140, align: 'center' },
-]);
 // 定义变量内容
 const state = reactive<any>({
 	loading: false, // 加载状态
@@ -176,9 +187,14 @@ const onEdit = (row: any) => {
 		},
 	});
 };
+const toolbarRef = ref<RefType>();
+const tableRef = ref<RefType>();
 // 页面加载时
 onMounted(() => {
-	getBaseData();
 	queryList();
+	if (tableRef.value && toolbarRef.value) {
+		tableRef.value.connect(toolbarRef.value);
+	}
+	getBaseData();
 });
 </script>

+ 91 - 87
src/views/knowledge/hotWords/index.vue

@@ -1,50 +1,89 @@
 <template>
 	<div class="knowledge-hot-words-container layout-padding">
 		<div class="layout-padding-auto layout-padding-view pd20">
-			<ProTable
-				ref="proTableRef"
-				:columns="columns"
-				:data="state.tableData"
-				@updateTable="queryList"
+			<el-form :model="state.queryParams" ref="ruleFormRef" inline @submit.native.prevent>
+				<el-form-item label="热词名称" prop="Name">
+					<el-input v-model="state.queryParams.Name" placeholder="请填写热词名称" clearable @keyup.enter="handleQuery" class="keyword-input" />
+				</el-form-item>
+				<el-form-item label="类型" prop="Type">
+					<el-select v-model="state.queryParams.Type" placeholder="请选择类型" clearable>
+						<el-option v-for="items in typeOptions" :key="items.key" :label="items.value" :value="items.key" />
+					</el-select>
+				</el-form-item>
+				<el-form-item>
+					<el-button type="primary" @click="handleQuery" :loading="state.loading"> <SvgIcon name="ele-Search" class="mr5" />查询 </el-button>
+					<el-button @click="resetQuery(ruleFormRef)" class="default-button"> <SvgIcon name="ele-Refresh" class="mr5" />重置 </el-button>
+				</el-form-item>
+			</el-form>
+			<vxe-toolbar
+				ref="toolbarRef"
 				:loading="state.loading"
-				:total="state.total"
-				v-model:page-index="state.queryParams.PageIndex"
-				v-model:page-size="state.queryParams.PageSize"
-				@sort-change="sortChange"
+				custom
+				:refresh="{
+					queryMethod: handleQuery,
+				}"
 			>
-				<template #table-search>
-					<el-form :model="state.queryParams" ref="ruleFormRef" inline @submit.native.prevent>
-						<el-form-item label="热词名称" prop="Name">
-							<el-input v-model="state.queryParams.Name" placeholder="请填写热词名称" clearable @keyup.enter="handleQuery" class="keyword-input" />
-						</el-form-item>
-						<el-form-item label="类型" prop="Type">
-							<el-select v-model="state.queryParams.Type" placeholder="请选择类型" clearable>
-								<el-option v-for="items in typeOptions" :key="items.key" :label="items.value" :value="items.key" />
-							</el-select>
-						</el-form-item>
-						<el-form-item>
-							<el-button type="primary" @click="handleQuery" :loading="state.loading"> <SvgIcon name="ele-Search" class="mr5" />查询 </el-button>
-							<el-button @click="resetQuery(ruleFormRef)" class="default-button"> <SvgIcon name="ele-Refresh" class="mr5" />重置 </el-button>
-						</el-form-item>
-					</el-form>
-				</template>
-				<template #tableHeader>
-					<el-button type="primary" @click="onProjectAdd" v-auth="'knowledge:hotWords:add'"> <SvgIcon name="ele-Plus" class="mr5" />新增 </el-button>
-				</template>
-				<template #type="{ row }">
-					{{ row.isIntelligent === 1 ? '是' : '否' }}
+				<template #buttons>
+					<el-button type="primary" @click="onProjectAdd" v-auth="'knowledge:hotWords:add'">
+						<SvgIcon name="ele-Plus" class="mr5" />新增热词</el-button
+					>
 				</template>
-				<!-- 表格操作 -->
-				<template #operation="{ row }">
-					<el-button link type="primary" @click="onProjectEdit(row)" v-auth="'knowledge:hotWords:edit'" title="修改热词"> 修改 </el-button>
-					<el-button link type="danger" @click="onProjectDelete(row)" v-auth="'knowledge:hotWords:delete'" title="删除热词"> 删除 </el-button>
-				</template>
-			</ProTable>
+			</vxe-toolbar>
+			<div style="overflow: hidden; width: 100%; height: 100%; flex: 1">
+				<vxe-table
+					border
+					:loading="state.loading"
+					:data="state.tableData"
+					:column-config="{ resizable: true }"
+					:row-config="{ isCurrent: true, isHover: true, height: 30 }"
+					ref="tableRef"
+					height="auto"
+					auto-resize
+					show-overflow
+					@sort-change="sortChange"
+					:sort-config="{ remote: true }"
+					:scrollY="{ enabled: true, gt: 0 }"
+					id="knowledgeHotWords"
+					:custom-config="{ storage: true }"
+					showHeaderOverflow
+				>
+					<vxe-column field="keyWord" title="热词名称" min-width="150"></vxe-column>
+					<vxe-column field="typeTxt" title="类型" width="100"></vxe-column>
+					<vxe-column field="sort" title="排序" width="100" sortable></vxe-column>
+					<vxe-column field="searchCount" title="搜索次数" width="100" sortable></vxe-column>
+					<vxe-column field="isEnable" title="是否启用" width="100">
+						<template #default="{ row }">
+							<template v-if="auth('knowledge:hotWords:edit')">
+								<el-switch v-model="row.isEnable" active-text="启用" inactive-text="禁用"  @change="changeIsEnable(row)" inline-prompt size="small" />
+							</template>
+							<span v-else>{{ row.isEnable ? '已启用' : '已禁用' }}</span>
+						</template>
+					</vxe-column>
+					<vxe-column field="creationTime" title="创建时间" width="160" sortable>
+						<template #default="{ row }">
+							{{ formatDate(row.creationTime, 'YYYY-mm-dd HH:MM:SS') }}
+						</template>
+					</vxe-column>
+					<vxe-column title="操作" fixed="right" width="120" align="center">
+						<template #default="{ row }">
+							<el-button link type="primary" @click="onProjectEdit(row)" v-auth="'knowledge:hotWords:edit'" title="修改热词"> 修改 </el-button>
+							<el-button link type="danger" @click="onProjectDelete(row)" v-auth="'knowledge:hotWords:delete'" title="删除热词"> 删除 </el-button>
+						</template>
+					</vxe-column>
+				</vxe-table>
+			</div>
+			<pagination
+				@pagination="queryList"
+				:total="state.total"
+				v-model:current-page="state.queryParams.PageIndex"
+				v-model:page-size="state.queryParams.PageSize"
+				:disabled="state.loading"
+			/>
 		</div>
 		<!--  热词新增  -->
-		<hot-words-add ref="hotWordsAddRef" @updateList="queryList" :typeOptions="typeOptions"/>
+		<hot-words-add ref="hotWordsAddRef" @updateList="queryList" :typeOptions="typeOptions" />
 		<!--  热词修改  -->
-		<hot-word-edit ref="hotWordEditRef" @updateList="queryList" :typeOptions="typeOptions"/>
+		<hot-word-edit ref="hotWordEditRef" @updateList="queryList" :typeOptions="typeOptions" />
 	</div>
 </template>
 
@@ -54,51 +93,10 @@ import { ElMessage, ElMessageBox, FormInstance } from 'element-plus';
 import { formatDate } from '@/utils/formatTime';
 import { auth } from '@/utils/authFunction';
 import { delKnowledgeHotWords, getKnowledgeHotWordsBaseData, getKnowledgeHotWordsList, updateKnowledgeHotWords } from '@/api/knowledge/hotWords';
-
 // 引入组件
 const hotWordsAdd = defineAsyncComponent(() => import('@/views/knowledge/hotWords/components/Hot-words-add.vue')); // 热词新增
 const HotWordEdit = defineAsyncComponent(() => import('@/views/knowledge/hotWords/components/Hot-words-edit.vue')); // 热词修改
-const proTableRef = ref<RefType>(); // 表格ref
-// 表格配置项
-const columns = ref<any>([
-	{ type: 'selection', fixed: 'left', width: 40, align: 'center' },
-	{ prop: 'keyWord', label: '热词名称', minWidth: 150 },
-	{ prop: 'typeTxt', label: '类型', minWidth: 100 },
-	{ prop: 'sort', label: '排序', minWidth: 100,sortable: 'custom', },
-	{ prop: 'searchCount', label: '搜索次数', minWidth: 100,sortable: 'custom', },
-	{
-		prop: 'isEnable',
-		label: '是否启用',
-		render: (scope: any) => {
-			return (
-				<>
-					{auth('knowledge:hotWords:edit') ? (
-						<el-switch
-							model-value={scope.row.isEnable}
-							active-text="启用"
-							inactive-text="禁用"
-							onClick={() => changeIsEnable(scope.row)}
-							inline-prompt
-							size="small"
-						/>
-					) : (
-						<span>{scope.row.isEnable ? '已启用' : '已禁用'}</span>
-					)}
-				</>
-			);
-		},
-	},
-	{
-		prop: 'creationTime',
-		label: '创建时间',
-		minWidth: 160,
-		sortable: 'custom',
-		render: (scope: EmptyObjectType) => {
-			return <span>{formatDate(scope.row.creationTime, 'YYYY-mm-dd HH:MM:SS')}</span>;
-		},
-	},
-	{ prop: 'operation', label: '操作', fixed: 'right', width: 140, align: 'center' },
-]);
+const pagination = defineAsyncComponent(() => import('@/components/ProTable/components/Pagination.vue')); // 分页
 // 定义变量内容
 const state = reactive<any>({
 	loading: false, // 加载状态
@@ -109,8 +107,8 @@ const state = reactive<any>({
 		GroupingName: null,
 		Type: null,
 		Name: null,
-		SortField:null,
-		OrderByType:null
+		SortField: null,
+		OrderByType: null,
 	},
 	total: 0, // 总条数
 	tableData: [], // 表格数据
@@ -136,10 +134,10 @@ const queryList = () => {
 };
 // 排序
 const sortChange = (val: any) => {
-	state.queryParams.SortField = val.order ? val.prop : null;
+	state.queryParams.SortField = val.order ? val.field : null;
 	// 0 升序 1 降序
-	state.queryParams.OrderByType = val.order ? (val.order == 'descending' ? 1 : 0) : null;
-	queryList();
+	state.queryParams.SortRule = val.order ? (val.order == 'desc' ? 1 : 0) : null;
+	handleQuery();
 };
 // 重置表单
 const resetQuery = (formEl: FormInstance | undefined) => {
@@ -168,7 +166,7 @@ const onProjectDelete = (row: any) => {
 		autofocus: false,
 	})
 		.then(() => {
-			delKnowledgeHotWords(row.id ).then(() => {
+			delKnowledgeHotWords(row.id).then(() => {
 				ElMessage.success('操作成功');
 				queryList();
 			});
@@ -177,6 +175,7 @@ const onProjectDelete = (row: any) => {
 };
 //  修改是否启用
 const changeIsEnable = (row: any) => {
+	row.isEnable = !row.isEnable //保持switch点击前的状态
 	ElMessageBox.confirm(`您确定要${row.isEnable ? '禁用' : '启用'}:【${row.keyWord}】热词,是否继续?`, '提示', {
 		confirmButtonText: '确认',
 		cancelButtonText: '取消',
@@ -211,9 +210,14 @@ const getBaseData = () => {
 		typeOptions.value = res.result.knowledgeHotWordType;
 	});
 };
+const toolbarRef = ref<RefType>();
+const tableRef = ref<RefType>();
 // 页面加载时
 onMounted(() => {
-	getBaseData();
 	queryList();
+	if (tableRef.value && toolbarRef.value) {
+		tableRef.value.connect(toolbarRef.value);
+	}
+	getBaseData();
 });
 </script>

+ 225 - 348
src/views/knowledge/index/index.vue

@@ -136,65 +136,66 @@
 						</el-scrollbar>
 					</template>
 				</pane>
-				<pane class="h100">
+				<pane class="h100" style="display: flex; flex-direction: column; flex: 1;">
 					<el-tabs v-model="state.queryParams.Status" @tab-change="handleClick" v-loading="state.loading">
 						<el-tab-pane :label="v.value" :name="v.key" v-for="(v, i) in state.statusOptions" :key="i" :disabled="state.tableLoading"></el-tab-pane>
 					</el-tabs>
-					<ProTable
-						ref="proTableRef"
-						:columns="columns"
-						:data="state.tableData"
-						@updateTable="queryList"
+					<el-form :model="state.queryParams" ref="ruleFormRef" inline @submit.native.prevent>
+						<el-form-item label="审核类型" prop="ModuleCode" v-if="state.queryParams.Status === '1'">
+							<el-segmented
+								:options="state.tabAuditingNames"
+								v-model="state.queryParams.ModuleCode"
+								@change="handleQuery"
+								:disabled="state.tableLoading"
+							/>
+						</el-form-item>
+						<el-form-item label="草稿类型" prop="NewDraftsStatus" v-if="state.queryParams.Status === '8'">
+							<el-segmented
+								:options="state.tabNewDraftsNames"
+								v-model="state.queryParams.NewDraftsStatus"
+								@change="handleQuery"
+								:disabled="state.tableLoading"
+							/>
+						</el-form-item>
+						<el-form-item label="关键字" prop="Keyword">
+							<el-input
+								v-model="state.queryParams.Keyword"
+								placeholder="标题/创建人/创建部门/来源部门"
+								clearable
+								@keyup.enter="handleQuery"
+								class="keyword-input"
+							/>
+						</el-form-item>
+						<el-form-item label="是否公开" prop="IsPublic">
+							<el-select v-model="state.queryParams.IsPublic" placeholder="请选择是否公开" @change="handleQuery" clearable>
+								<el-option label="是" :value="true" />
+								<el-option label="否" :value="false" />
+							</el-select>
+						</el-form-item>
+						<el-form-item>
+							<el-button type="primary" @click="handleQuery" :loading="state.tableLoading">
+								<SvgIcon name="ele-Search" class="mr5" />查询
+							</el-button>
+							<el-button @click="resetQuery(ruleFormRef)" class="default-button" :loading="state.tableLoading">
+								<SvgIcon name="ele-Refresh" class="mr5" />重置
+							</el-button>
+						</el-form-item>
+					</el-form>
+					<vxe-toolbar
+						ref="toolbarRef"
 						:loading="state.tableLoading"
-						:total="state.total"
-						v-model:page-index="state.queryParams.PageIndex"
-						v-model:page-size="state.queryParams.PageSize"
-						v-if="['1'].includes(state.queryParams.Status)"
-						:toolButton="['refresh', 'setting', 'exportCurrent', 'exportAll']"
-						:exportMethod="knowledgeExport"
-						:exportParams="requestParams"
+						custom
+						:refresh="{
+							queryMethod: handleQuery,
+						}"
+						:tools="[{ toolRender: { name: 'exportCurrent' } }, { toolRender: { name: 'exportAll' } }]"
 					>
-						<template #table-search>
-							<el-form :model="state.queryParams" ref="ruleFormRef" inline @submit.native.prevent>
-								<el-form-item label="审核类型" prop="ModuleCode">
-									<el-segmented
-										:options="state.tabAuditingNames"
-										v-model="state.queryParams.ModuleCode"
-										@change="handleQuery"
-										:disabled="state.tableLoading"
-									/>
-								</el-form-item>
-								<el-form-item label="关键字" prop="Keyword">
-									<el-input
-										v-model="state.queryParams.Keyword"
-										placeholder="标题/创建人/创建部门/来源部门"
-										clearable
-										@keyup.enter="handleQuery"
-										class="keyword-input"
-									/>
-								</el-form-item>
-								<el-form-item label="是否公开" prop="IsPublic">
-									<el-select v-model="state.queryParams.IsPublic" placeholder="请选择是否公开" @change="handleQuery" clearable>
-										<el-option label="是" :value="true" />
-										<el-option label="否" :value="false" />
-									</el-select>
-								</el-form-item>
-								<el-form-item>
-									<el-button type="primary" @click="handleQuery" :loading="state.tableLoading">
-										<SvgIcon name="ele-Search" class="mr5" />查询
-									</el-button>
-									<el-button @click="resetQuery(ruleFormRef)" class="default-button" :loading="state.tableLoading">
-										<SvgIcon name="ele-Refresh" class="mr5" />重置
-									</el-button>
-								</el-form-item>
-							</el-form>
-						</template>
-						<template #tableHeader="scope">
+						<template #buttons>
 							<el-button type="primary" @click="onAddKnowledge" v-auth="'knowledge:index:add'" :loading="state.tableLoading">
 								<SvgIcon name="ele-Plus" class="mr5" />创建知识
 							</el-button>
-							<el-dropdown v-auth="'knowledge:index:export:detail'" @command="onExportDetail" class="ml12 mr12" :disabled="!scope.isSelected">
-								<el-button type="primary" :disabled="!scope.isSelected" :loading="state.tableLoading">
+							<el-dropdown v-auth="'knowledge:index:export:detail'" @command="onExportDetail" class="ml12 mr12" :disabled="isChecked">
+								<el-button type="primary" :disabled="isChecked" :loading="state.tableLoading">
 									导出知识详情<SvgIcon name="ele-ArrowDown" class="ml3" />
 								</el-button>
 								<template #dropdown>
@@ -209,197 +210,137 @@
 								v-if="state.queryParams.Status === '1'"
 								v-auth="'knowledge:index:audit:batch'"
 								:loading="state.loading"
-								:disabled="!scope.isSelected"
+								:disabled="isChecked"
 							>
 								<SvgIcon name="ele-Edit" class="mr5" />批量审核
 							</el-button>
 						</template>
-						<template #title="{ row }">
-							<el-button link type="primary" @click="onPreview(row)">{{ row.title }}</el-button>
-						</template>
-						<template #isPublic="{ row }">
-							<span>{{ row.isPublic ? '是' : '否' }}</span>
-						</template>
-						<template #operation="{ row }">
-							<el-button
-								link
-								type="primary"
-								@click="onEdit(row)"
-								title="编辑"
-								v-if="[0, 4, 5, 6].includes(row.newStatus) && row.status !== '1'"
-								v-auth="'knowledge:index:edit'"
-							>
-								编辑
-							</el-button>
-							<el-button
-								link
-								type="danger"
-								@click="onRowDel(row)"
-								title="删除"
-								v-if="[0, 2, 4, 5, 6].includes(row.newStatus) && row.status !== '1' && ['YiBin'].includes(themeConfig.appScope)"
-								v-auth="'knowledge:index:delete'"
-							>
-								删除
-							</el-button>
-							<el-button
-								link
-								type="primary"
-								@click="offShelfFn(row)"
-								title="下架"
-								v-if="[3].includes(row.newStatus)"
-								v-auth="'knowledge:index:undercarriage'"
-							>
-								下架
-							</el-button>
-							<el-button
-								link
-								type="primary"
-								@click="groundingFn(row)"
-								title="上架"
-								v-if="[4].includes(row.newStatus)"
-								v-auth="'knowledge:index:grounding'"
-							>
-								上架
-							</el-button>
-							<el-button link type="primary" @click="onprogress(row)" title="查看审核记录" v-if="[5].includes(row.newStatus)"> 审核记录 </el-button>
-							<!--									<el-button
-                link
-                type="primary"
-                @click="onAudit(row)"
-                title="审批"
-                v-if="[1, 2].includes(row.status) && row.isCanHandle"
-                v-auth="'business:order:handle'"
-              >
-                审批
-              </el-button>-->
-							<el-button link type="primary" @click="onPreview(row)" title="查看"> 查看 </el-button>
-						</template>
-					</ProTable>
-					<ProTable
-						ref="proTableRef"
-						:columns="staticColumns"
-						:data="state.tableData"
-						@updateTable="queryList"
-						:loading="state.tableLoading"
-						:total="state.total"
-						v-model:page-index="state.queryParams.PageIndex"
-						v-model:page-size="state.queryParams.PageSize"
-						v-else
-						:toolButton="['refresh', 'setting', 'exportCurrent', 'exportAll']"
-						:exportMethod="knowledgeExport"
-						:exportParams="requestParams"
-					>
-						<template #table-search>
-							<el-form :model="state.queryParams" ref="ruleFormRef" inline @submit.native.prevent>
-								<el-form-item label="草稿类型" prop="NewDraftsStatus" v-if="state.queryParams.Status === '8'">
-									<el-segmented
-										:options="state.tabNewDraftsNames"
-										v-model="state.queryParams.NewDraftsStatus"
-										@change="handleQuery"
-										:disabled="state.tableLoading"
-									/>
-								</el-form-item>
-								<el-form-item label="关键字" prop="Keyword">
-									<el-input
-										v-model="state.queryParams.Keyword"
-										placeholder="标题/创建人/创建部门/来源部门"
-										clearable
-										@keyup.enter="handleQuery"
-										class="keyword-input"
-									/>
-								</el-form-item>
-								<el-form-item label="是否公开" prop="IsPublic">
-									<el-select v-model="state.queryParams.IsPublic" placeholder="请选择是否公开" @change="handleQuery" clearable>
-										<el-option label="是" :value="true" />
-										<el-option label="否" :value="false" />
-									</el-select>
-								</el-form-item>
-								<el-form-item>
-									<el-button type="primary" @click="handleQuery" :loading="state.tableLoading">
-										<SvgIcon name="ele-Search" class="mr5" />查询
+					</vxe-toolbar>
+					<div style="overflow: hidden; width: 100%; height: 100%; flex: 1">
+						<vxe-table
+							border
+							:loading="state.tableLoading"
+							:data="state.tableData"
+							:column-config="{ resizable: true }"
+							:row-config="{ isCurrent: true, isHover: true, height: 30 }"
+							ref="tableRef"
+							height="auto"
+							auto-resize
+							show-overflow
+							:print-config="{}"
+							:scrollY="{ enabled: true, gt: 0 }"
+							id="knowledgeManage"
+							:custom-config="{ storage: true }"
+							showHeaderOverflow
+							:params="{ exportMethod: knowledgeExport, exportParams: requestParams }"
+							@checkbox-all="selectAllChangeEvent"
+							@checkbox-change="selectChangeEvent"
+						>
+							<vxe-column type="checkbox" width="50" align="center"></vxe-column>
+							<vxe-column field="workflow.moduleName" title="审核类型" width="120" v-if="state.queryParams.Status === '1'"></vxe-column>
+							<vxe-column field="title" title="标题" min-width="200">
+								<template #default="{row}">
+									<el-button link type="primary" @click="onPreview(row)">{{ row.title }}</el-button>
+								</template>
+							</vxe-column>
+							<vxe-column field="knowledgeTypeText" title="知识分类" width="150"></vxe-column>
+							<vxe-column field="statusName" title="知识状态" width="110"></vxe-column>
+							<vxe-column field="attribution" title="知识归属" width="140"></vxe-column>
+							<vxe-column field="sourceOrganize.name" title="来源部门" width="140"></vxe-column>
+							<vxe-column field="hotspotName" title="热点" width="150"></vxe-column>
+							<vxe-column field="isPublic" title="是否公开" width="100">
+								<template #default="{ row }">
+									{{ row.isPublic ? '是' : '否' }}
+								</template>
+							</vxe-column>
+							<vxe-column field="pageView" title="阅读次数" width="100"></vxe-column>
+							<vxe-column field="onShelfTime" title="上架时间" width="160">
+								<template #default="{ row }">
+									{{ formatDate(row.onShelfTime, 'YYYY-mm-dd HH:MM:SS') }}
+								</template>
+							</vxe-column>
+							<vxe-column field="offShelfTime" title="下架时间" width="160">
+								<template #default="{ row }">
+									{{ formatDate(row.offShelfTime, 'YYYY-mm-dd HH:MM:SS') }}
+								</template>
+							</vxe-column>
+							<vxe-column field="creatorName" title="创建人" width="120"></vxe-column>
+							<vxe-column field="creatorOrgName" title="创建部门" width="150"></vxe-column>
+							<vxe-column field="creationTime" title="创建时间" width="160">
+								<template #default="{ row }">
+									{{ formatDate(row.creationTime, 'YYYY-mm-dd HH:MM:SS') }}
+								</template>
+							</vxe-column>
+							<vxe-column field="lastModificationTime" title="更新时间" width="160">
+								<template #default="{ row }">
+									{{ formatDate(row.lastModificationTime, 'YYYY-mm-dd HH:MM:SS') }}
+								</template>
+							</vxe-column>
+							<vxe-column title="操作" fixed="right" width="250" align="center">
+								<template #default="{ row }">
+									<el-button
+										link
+										type="primary"
+										@click="onEdit(row)"
+										title="编辑"
+										v-if="[0, 4, 5, 6].includes(row.newStatus) && row.status !== '1'"
+										v-auth="'knowledge:index:edit'"
+									>
+										编辑
 									</el-button>
-									<el-button @click="resetQuery(ruleFormRef)" class="default-button" :loading="state.tableLoading">
-										<SvgIcon name="ele-Refresh" class="mr5" />重置
+									<el-button
+										link
+										type="danger"
+										@click="onRowDel(row)"
+										title="删除"
+										v-if="[0, 2, 4, 5, 6].includes(row.newStatus) && row.status !== '1' && ['YiBin'].includes(themeConfig.appScope)"
+										v-auth="'knowledge:index:delete'"
+									>
+										删除
 									</el-button>
-								</el-form-item>
-							</el-form>
-						</template>
-						<template #tableHeader="scope">
-							<el-button type="primary" @click="onAddKnowledge" v-auth="'knowledge:index:add'" :loading="state.tableLoading">
-								<SvgIcon name="ele-Plus" class="mr5" />创建知识
-							</el-button>
-							<el-dropdown v-auth="'knowledge:index:export:detail'" @command="onExportDetail" class="ml12 mr12" :disabled="!scope.isSelected">
-								<el-button type="primary" :disabled="!scope.isSelected" :loading="state.tableLoading">
-									导出知识详情<SvgIcon name="ele-ArrowDown" class="ml3" />
-								</el-button>
-								<template #dropdown>
-									<el-dropdown-menu>
-										<el-dropdown-item :command="item.key" v-for="item in exportType" :key="item.key">{{ item.value }}</el-dropdown-item>
-									</el-dropdown-menu>
+									<el-button
+										link
+										type="primary"
+										@click="offShelfFn(row)"
+										title="下架"
+										v-if="[3].includes(row.newStatus)"
+										v-auth="'knowledge:index:undercarriage'"
+									>
+										下架
+									</el-button>
+									<el-button
+										link
+										type="primary"
+										@click="groundingFn(row)"
+										title="上架"
+										v-if="[4].includes(row.newStatus)"
+										v-auth="'knowledge:index:grounding'"
+									>
+										上架
+									</el-button>
+									<el-button link type="primary" @click="onprogress(row)" title="查看审核记录" v-if="[5].includes(row.newStatus)"> 审核记录 </el-button>
+									<!--									<el-button
+										link
+										type="primary"
+										@click="onAudit(row)"
+										title="审批"
+										v-if="[1, 2].includes(row.status) && row.isCanHandle"
+										v-auth="'business:order:handle'"
+									>
+										审批
+									</el-button>-->
+									<el-button link type="primary" @click="onPreview(row)" title="查看"> 查看 </el-button>
 								</template>
-							</el-dropdown>
-						</template>
-						<template #title="{ row }">
-							<el-button link type="primary" @click="onPreview(row)">{{ row.title }}</el-button>
-						</template>
-						<template #isPublic="{ row }">
-							<span>{{ row.isPublic ? '是' : '否' }}</span>
-						</template>
-						<template #operation="{ row }">
-							<el-button
-								link
-								type="primary"
-								@click="onEdit(row)"
-								title="编辑"
-								v-if="[0, 4, 5, 6].includes(row.newStatus) && row.status !== '1'"
-								v-auth="'knowledge:index:edit'"
-							>
-								编辑
-							</el-button>
-							<el-button
-								link
-								type="danger"
-								@click="onRowDel(row)"
-								title="删除"
-								v-if="[0, 2, 4, 5, 6].includes(row.newStatus) && row.status !== '1' && ['YiBin'].includes(themeConfig.appScope)"
-								v-auth="'knowledge:index:delete'"
-							>
-								删除
-							</el-button>
-							<el-button
-								link
-								type="primary"
-								@click="offShelfFn(row)"
-								title="下架"
-								v-if="[3].includes(row.newStatus)"
-								v-auth="'knowledge:index:undercarriage'"
-							>
-								下架
-							</el-button>
-							<el-button
-								link
-								type="primary"
-								@click="groundingFn(row)"
-								title="上架"
-								v-if="[4].includes(row.newStatus)"
-								v-auth="'knowledge:index:grounding'"
-							>
-								上架
-							</el-button>
-							<el-button link type="primary" @click="onprogress(row)" title="查看审核记录" v-if="[5].includes(row.newStatus)"> 审核记录 </el-button>
-							<!--									<el-button
-                link
-                type="primary"
-                @click="onAudit(row)"
-                title="审批"
-                v-if="[1, 2].includes(row.status) && row.isCanHandle"
-                v-auth="'business:order:handle'"
-              >
-                审批
-              </el-button>-->
-							<el-button link type="primary" @click="onPreview(row)" title="查看"> 查看 </el-button>
-						</template>
-					</ProTable>
+							</vxe-column>
+						</vxe-table>
+					</div>
+					<pagination
+						@pagination="queryList"
+						:total="state.total"
+						v-model:current-page="state.queryParams.PageIndex"
+						v-model:page-size="state.queryParams.PageSize"
+						:disabled="state.tableLoading"
+					/>
 				</pane>
 			</splitpanes>
 		</div>
@@ -413,7 +354,7 @@
 </template>
 
 <script lang="tsx" setup name="knowledgeManage">
-import { ref, reactive, onMounted, watch, defineAsyncComponent } from 'vue';
+import { ref, reactive, onMounted, watch, defineAsyncComponent, computed } from 'vue';
 import { ElMessageBox, ElMessage } from 'element-plus';
 import { useRouter } from 'vue-router';
 import type { FormInstance } from 'element-plus';
@@ -437,14 +378,15 @@ import { storeToRefs } from 'pinia';
 import Other from '@/utils/other';
 import { downloadFileByStream } from '@/utils/tools';
 import { useThemeConfig } from '@/stores/themeConfig';
+import { VxeUI } from 'vxe-pc-ui';
 
 // 引入组件
 const ProcessAudit = defineAsyncComponent(() => import('@/components/ProcessAudit/index.vue')); // 流程审批
 const AuditProgress = defineAsyncComponent(() => import('@/views/knowledge/components/Audit-progress.vue')); // 编写规范
 const TextTooltip = defineAsyncComponent(() => import('@/components/TextTooltip/index.vue'));
 const ToEnd = defineAsyncComponent(() => import('@/views/knowledge/index/components/To-end.vue')); // 批量审批
+const pagination = defineAsyncComponent(() => import('@/components/ProTable/components/Pagination.vue')); // 分页
 
-const proTableRef = ref<RefType>(); // 表格ref
 // 定义变量内容
 const state = reactive<any>({
 	queryParams: {
@@ -591,100 +533,6 @@ const getKnowledgeType = async () => {
 		state.typeLoading = false;
 	}
 };
-// 表格配置项
-const columns = ref<any[]>([
-	{ type: 'selection', minWidth: 40, align: 'center' },
-	{ prop: 'workflow.moduleName', label: '审核类型', width: 120 },
-	{ prop: 'title', label: '标题', minWidth: 200 },
-	{ prop: 'knowledgeTypeText', label: '知识分类', minWidth: 150 },
-	{ prop: 'statusName', label: '知识状态', minWidth: 100 },
-	{ prop: 'attribution', label: '知识归属', minWidth: 140 },
-	{ prop: 'sourceOrganize.name', label: '来源部门', minWidth: 140 },
-	{ prop: 'hotspotName', label: '热点', minWidth: 150 },
-	{ prop: 'isPublic', label: '是否公开' },
-	{ prop: 'pageView', label: '阅读次数' },
-	{
-		prop: 'onShelfTime',
-		label: '上架时间',
-		minWidth: 160,
-		render: (scope) => {
-			return <span>{formatDate(scope.row.onShelfTime, 'YYYY-mm-dd HH:MM:SS')}</span>;
-		},
-	},
-	{
-		prop: 'offShelfTime',
-		label: '下架时间',
-		minWidth: 170,
-		render: (scope) => {
-			return <span>{formatDate(scope.row.offShelfTime, 'YYYY-mm-dd HH:MM:SS')}</span>;
-		},
-	},
-	{ prop: 'creatorName', label: '创建人', minWidth: 120 },
-	{ prop: 'creatorOrgName', label: '创建部门', minWidth: 140 },
-	{
-		prop: 'creationTime',
-		label: '创建时间',
-		minWidth: 170,
-		render: (scope) => {
-			return <span>{formatDate(scope.row.creationTime, 'YYYY-mm-dd HH:MM:SS')}</span>;
-		},
-	},
-	{
-		prop: 'lastModificationTime',
-		label: '更新时间',
-		minWidth: 170,
-		render: (scope) => {
-			return <span>{formatDate(scope.row.lastModificationTime, 'YYYY-mm-dd HH:MM:SS')}</span>;
-		},
-	},
-	{ prop: 'operation', label: '操作', fixed: 'right', width: 250, align: 'center' },
-]);
-const staticColumns = [
-	{ type: 'selection', minWidth: 40, align: 'center' },
-	{ prop: 'title', label: '标题', minWidth: 200 },
-	{ prop: 'knowledgeTypeText', label: '知识分类', minWidth: 150 },
-	{ prop: 'statusName', label: '知识状态', minWidth: 100 },
-	{ prop: 'attribution', label: '知识归属', minWidth: 140 },
-	{ prop: 'sourceOrganize.name', label: '来源部门', minWidth: 140 },
-	{ prop: 'hotspotName', label: '热点', minWidth: 150 },
-	{ prop: 'isPublic', label: '是否公开' },
-	{ prop: 'pageView', label: '阅读次数' },
-	{
-		prop: 'onShelfTime',
-		label: '上架时间',
-		minWidth: 160,
-		render: (scope) => {
-			return <span>{formatDate(scope.row.onShelfTime, 'YYYY-mm-dd HH:MM:SS')}</span>;
-		},
-	},
-	{
-		prop: 'offShelfTime',
-		label: '下架时间',
-		minWidth: 170,
-		render: (scope) => {
-			return <span>{formatDate(scope.row.offShelfTime, 'YYYY-mm-dd HH:MM:SS')}</span>;
-		},
-	},
-	{ prop: 'creatorName', label: '创建人', minWidth: 120 },
-	{ prop: 'creatorOrgName', label: '创建部门', minWidth: 140 },
-	{
-		prop: 'creationTime',
-		label: '创建时间',
-		minWidth: 170,
-		render: (scope) => {
-			return <span>{formatDate(scope.row.creationTime, 'YYYY-mm-dd HH:MM:SS')}</span>;
-		},
-	},
-	{
-		prop: 'lastModificationTime',
-		label: '更新时间',
-		minWidth: 170,
-		render: (scope) => {
-			return <span>{formatDate(scope.row.lastModificationTime, 'YYYY-mm-dd HH:MM:SS')}</span>;
-		},
-	},
-	{ prop: 'operation', label: '操作', fixed: 'right', width: 250, align: 'center' },
-];
 /** 获取知识列表 */
 const requestParams = ref<EmptyObjectType>({});
 const queryList = () => {
@@ -890,36 +738,65 @@ const onprogress = (row: any) => {
 // 导出详情
 const onExportDetail = (command: string | number | object) => {
 	state.loading = true;
-	knowledgeDetailExport({ ids: proTableRef.value.selectedListIds, fileType: command })
+	const ids = checkTable.value.map((item: any) => item.id);
+	VxeUI.modal.message({
+		content: `导出中,请稍等`,
+		status: 'loading',
+		id: 'exportDetail',
+		duration: -1,
+	});
+	knowledgeDetailExport({ ids, fileType: command })
 		.then((res) => {
 			downloadFileByStream(res);
 			state.loading = false;
+			VxeUI.modal.close('exportDetail');
+			VxeUI.modal.message({
+				content: `导出成功`,
+				status: 'success',
+			});
 		})
 		.catch(() => {
 			state.loading = false;
+			VxeUI.modal.close('exportDetail');
+			VxeUI.modal.message({
+				content: `导出失败`,
+				status: 'error',
+			});
 		});
 };
 // 批量审核
 const toEndRef = ref<RefType>();
 const onAuditBatch = () => {
-	toEndRef.value.openDialog(proTableRef.value.selectedListIds);
+	const ids = checkTable.value.map((item: any) => item.id);
+	toEndRef.value.openDialog(ids);
+};
+const tableRef = ref<RefType>();
+const checkTable = ref<EmptyArrayType>([]);
+const selectAllChangeEvent = ({ checked }) => {
+	if (tableRef.value) {
+		const records = tableRef.value.getCheckboxRecords();
+		checkTable.value = records;
+		console.log(checked ? '所有勾选事件' : '所有取消事件', records);
+	}
 };
+
+const selectChangeEvent = ({ checked }) => {
+	if (tableRef.value) {
+		const records = tableRef.value.getCheckboxRecords();
+		checkTable.value = records;
+		console.log(checked ? '勾选事件' : '取消事件', records);
+	}
+};
+const isChecked = computed(() => {
+	return !Boolean(checkTable.value.length);
+});
+const toolbarRef = ref<RefType>();
 onMounted(() => {
+	queryList();
+	if (tableRef.value && toolbarRef.value) {
+		tableRef.value.connect(toolbarRef.value);
+	}
 	getKnowledgeType();
 	getOrgListApi();
-	queryList();
 });
-</script>
-<style lang="scss" scoped>
-.knowledge-index-container {
-	:deep(.pro-table-main) {
-		height: calc(100% - 54px) !important;
-	}
-	:deep(.el-tree-node__content) {
-		height: 32px;
-	}
-	:deep(.el-card__body) {
-		height: 100%;
-	}
-}
-</style>
+</script>

+ 91 - 76
src/views/knowledge/question/index.vue

@@ -1,53 +1,91 @@
 <template>
 	<div class="knowledge-question-container layout-padding">
 		<div class="layout-padding-auto layout-padding-view pd20">
-			<ProTable
-				ref="proTableRef"
-				:columns="columns"
-				:data="state.tableData"
-				@updateTable="queryList"
-				:loading="state.loading"
+			<el-form :model="state.queryParams" ref="ruleFormRef" inline @submit.native.prevent>
+				<el-form-item label="提问人" prop="CreatorName">
+					<el-input v-model="state.queryParams.CreatorName" placeholder="请填写提问人" clearable @keyup.enter="handleQuery" class="keyword-input" />
+				</el-form-item>
+				<el-form-item label="知识分类" prop="KnowledgeTypeId">
+					<el-cascader
+						:options="state.typeData"
+						filterable
+						:props="{ checkStrictly: true, value: 'id', label: 'name', emitPath: false, children: 'children' }"
+						placeholder="请选择知识分类"
+						v-model="state.queryParams.KnowledgeTypeId"
+						ref="cascadeRef"
+						@change="handleQuery"
+					>
+					</el-cascader>
+				</el-form-item>
+				<el-form-item>
+					<el-button type="primary" @click="handleQuery" :loading="state.loading"> <SvgIcon name="ele-Search" class="mr5" />查询 </el-button>
+					<el-button @click="resetQuery(ruleFormRef)" v-waves class="default-button"> <SvgIcon name="ele-Refresh" class="mr5" />重置 </el-button>
+				</el-form-item>
+			</el-form>
+			<vxe-toolbar
+				ref="toolbarRef"
+				:loading="state.tableLoading"
+				custom
+				:refresh="{
+					queryMethod: handleQuery,
+				}"
+			>
+			</vxe-toolbar>
+			<div style="overflow: hidden; width: 100%; height: 100%; flex: 1">
+				<vxe-table
+					border
+					:loading="state.tableLoading"
+					:data="state.tableData"
+					:column-config="{ resizable: true }"
+					:row-config="{ isCurrent: true, isHover: true, height: 30 }"
+					ref="tableRef"
+					height="auto"
+					auto-resize
+					show-overflow
+					:scrollY="{ enabled: true, gt: 0 }"
+					id="knowledgeQuestion"
+					:custom-config="{ storage: true }"
+					showHeaderOverflow
+				>
+					<vxe-column field="knowledge.title" title="标题" min-width="200">
+						<template #default="{row}">
+							<el-button link type="primary" @click="onPreview(row)">{{ row.knowledge?.title }}</el-button>
+						</template>
+					</vxe-column>
+					<vxe-column field="knowledgeType" title="知识分类" width="150"></vxe-column>
+					<vxe-column field="knowledge.statusText" title="知识状态" width="100"></vxe-column>
+					<vxe-column field="stateText" title="答复状态" width="120"></vxe-column>
+					<vxe-column field="creatorName" title="提问人" width="120"></vxe-column>
+					<vxe-column field="creationTime" title="提问时间" width="160">
+						<template #default="{ row }">
+							{{ formatDate(row.creationTime, 'YYYY-mm-dd HH:MM:SS') }}
+						</template>
+					</vxe-column>
+					<vxe-column field="content" title="提问内容" width="150"></vxe-column>
+					<vxe-column field="replyContent" title="答复内容" width="150"></vxe-column>
+					<vxe-column field="replyTime" title="答复时间" width="160">
+						<template #default="{ row }">
+							{{ formatDate(row.replyTime, 'YYYY-mm-dd HH:MM:SS') }}
+						</template>
+					</vxe-column>
+					<vxe-column title="操作" fixed="right" width="160" align="center" :show-overflow="false">
+						<template #default="{ row }">
+							<el-button link type="primary" @click="onPreview(row)" title="知识详情"> 知识详情 </el-button>
+							<el-button link type="primary" @click="onReply(row)" v-auth="'knowledge:question:reply'" title="答复" v-if="[0].includes(row.state)">
+								答复
+							</el-button>
+							<el-button link type="primary" @click="onEdit(row)" title="编辑" v-if="[0, 4].includes(row.knowledge?.status)"> 编辑 </el-button>
+						</template>
+					</vxe-column>
+				</vxe-table>
+			</div>
+			<pagination
+				@pagination="queryList"
 				:total="state.total"
-				v-model:page-index="state.queryParams.PageIndex"
+				v-model:current-page="state.queryParams.PageIndex"
 				v-model:page-size="state.queryParams.PageSize"
-			>
-        <template #table-search>
-          <el-form :model="state.queryParams" ref="ruleFormRef" inline @submit.native.prevent>
-            <el-form-item label="提问人" prop="CreatorName">
-              <el-input v-model="state.queryParams.CreatorName" placeholder="请填写提问人" clearable @keyup.enter="handleQuery" class="keyword-input" />
-            </el-form-item>
-            <el-form-item label="知识分类" prop="KnowledgeTypeId">
-              <el-cascader
-                  :options="state.typeData"
-                  filterable
-                  :props="{ checkStrictly: true, value: 'id', label: 'name', emitPath: false, children: 'children' }"
-                  placeholder="请选择知识分类"
-                  v-model="state.queryParams.KnowledgeTypeId"
-                  ref="cascadeRef"
-                  @change="handleQuery"
-              >
-              </el-cascader>
-            </el-form-item>
-            <el-form-item>
-              <el-button type="primary" @click="handleQuery" :loading="state.loading"> <SvgIcon name="ele-Search" class="mr5" />查询 </el-button>
-              <el-button @click="resetQuery(ruleFormRef)" v-waves class="default-button"> <SvgIcon name="ele-Refresh" class="mr5" />重置 </el-button>
-            </el-form-item>
-          </el-form>
-        </template>
-				<template #title="{ row }">
-					<el-button link type="primary" @click="onPreview(row)">{{ row.knowledge?.title }}</el-button>
-				</template>
-				<template #knowledgeType="{ row }">
-					<span>{{ row.knowledge?.knowledgeType?.map((item) => item.value).join(',') }}</span>
-				</template>
-				<template #operation="{ row }">
-					<el-button link type="primary" @click="onPreview(row)" title="知识详情"> 知识详情 </el-button>
-					<el-button link type="primary" @click="onReply(row)" v-auth="'knowledge:question:reply'" title="答复" v-if="[0].includes(row.state)">
-						答复
-					</el-button>
-					<el-button link type="primary" @click="onEdit(row)" title="编辑" v-if="[0, 4].includes(row.knowledge?.status)"> 编辑 </el-button>
-				</template>
-			</ProTable>
+				:disabled="state.tableLoading"
+			/>
 		</div>
 		<!-- 知识提问 -->
 		<question-add ref="questionRef" @submitSuccess="queryList" />
@@ -65,42 +103,14 @@ import { treeList } from '@/api/knowledge/type';
 
 // 引入组件
 const QuestionAdd = defineAsyncComponent(() => import('@/views/knowledge/question/components/Question-add.vue')); // 知识提问
-
-const proTableRef = ref<RefType>(); // 表格ref
-// 表格配置项
-const columns = ref<any[]>([
-	{ prop: 'knowledge.title', label: '知识标题', minWidth: 200 },
-	{ prop: 'knowledgeType', label: '知识分类', minWidth: 150 },
-	{ prop: 'knowledge.statusText', label: '知识状态', minWidth: 100 },
-	{ prop: 'stateText', label: '答复状态' },
-	{ prop: 'creatorName', label: '纠错人', minWidth: 120 },
-	{
-		prop: 'creationTime',
-		label: '提问时间',
-		minWidth: 160,
-		render: (scope) => {
-			return <span>{formatDate(scope.row.creationTime, 'YYYY-mm-dd HH:MM:SS')}</span>;
-		},
-	},
-	{ prop: 'content', label: '提问内容' },
-	{ prop: 'replyContent', label: '答复内容' },
-	{
-		prop: 'replyTime',
-		label: '答复时间',
-		minWidth: 160,
-		render: (scope) => {
-			return <span>{formatDate(scope.row.replyTime, 'YYYY-mm-dd HH:MM:SS')}</span>;
-		},
-	},
-	{ prop: 'operation', label: '操作', fixed: 'right', minWidth: 140, align: 'center' },
-]);
+const pagination = defineAsyncComponent(() => import('@/components/ProTable/components/Pagination.vue')); // 分页
 // 定义变量内容
 const state = reactive<any>({
 	loading: false, // 加载状态
 	queryParams: {
 		// 查询参数
 		PageIndex: 1,
-		PageSize: 20,
+		PageSize: 2,
 		KnowledgeTypeId: null, // 知识分类
 		CreatorName: null, // 提问人
 	},
@@ -168,8 +178,13 @@ const onEdit = (row: any) => {
 	});
 };
 // 页面加载时
+const toolbarRef = ref<RefType>();
+const tableRef = ref<RefType>();
 onMounted(() => {
-	getBaseData();
 	queryList();
+	if (tableRef.value && toolbarRef.value) {
+		tableRef.value.connect(toolbarRef.value);
+	}
+	getBaseData();
 });
 </script>

+ 1 - 1
src/views/system/menu/index.vue

@@ -45,7 +45,7 @@
 						parentField:'parentId',
 					}"
 				>
-					<vxe-column field="pageName" title="菜单名称" min-width="400" align="center" treeNode>
+					<vxe-column field="pageName" title="菜单名称" min-width="400" treeNode>
 						<template #default="{ row }">
 							<p style="display: flex; align-items: center">
 								<MenuSvgIcon :name="row.icon" />

+ 1 - 1
src/views/system/user/index.vue

@@ -31,7 +31,7 @@
 						</el-skeleton>
 					</el-scrollbar>
 				</pane>
-				<pane class="h100" style="display: flex; flex-direction: column; flex: 1">
+				<pane class="h100" style="display: flex; flex-direction: column; flex: 1;">
 					<el-form :model="state.queryParams" ref="ruleFormRef" inline @submit.native.prevent>
 						<el-form-item label="关键字" prop="Keyword">
 							<el-input