|
@@ -1,213 +1,124 @@
|
|
|
<template>
|
|
|
<div class="auxiliary-area-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)" v-waves 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-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" v-trim />
|
|
|
+ </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" :loading="state.loading">
|
|
|
+ <SvgIcon name="ele-Refresh" class="mr5" />重置
|
|
|
+ </el-button>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ <vxe-toolbar
|
|
|
+ ref="toolbarRef"
|
|
|
+ :loading="state.tableLoading"
|
|
|
+ custom
|
|
|
+ :refresh="{
|
|
|
+ queryMethod: handleQuery,
|
|
|
+ }"
|
|
|
+ >
|
|
|
+ <template #buttons>
|
|
|
<el-button type="primary" @click="onAddArea" v-auth="'auxiliary:area: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.orgTableData"
|
|
|
- expand-column-key="areaName"
|
|
|
- fixed
|
|
|
- :width="width"
|
|
|
- :height="height"
|
|
|
- ref="virtuallyTableRef"
|
|
|
- :scrollbar-always-on="true"
|
|
|
- :row-height="40"
|
|
|
- :header-height="40"
|
|
|
- >
|
|
|
- </el-table-v2>
|
|
|
</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="auxiliaryArea"
|
|
|
+ :custom-config="{ storage: true }"
|
|
|
+ showHeaderOverflow
|
|
|
+ :tree-config="{
|
|
|
+ childrenField: 'children',
|
|
|
+ transform: true,
|
|
|
+ rowField: 'id',
|
|
|
+ parentField: 'parentId',
|
|
|
+ }"
|
|
|
+ >
|
|
|
+ <vxe-column field="areaName" title="区域名称" min-width="400" treeNode>
|
|
|
+ <template #default="{ row }">
|
|
|
+ <p style="display: flex; align-items: center">
|
|
|
+ <span class="pl5" v-html="row.areaName"></span>
|
|
|
+ </p>
|
|
|
+ </template>
|
|
|
+ </vxe-column>
|
|
|
+ <vxe-column field="id" title="区域代码" min-width="350">
|
|
|
+ <template #default="{ row }">
|
|
|
+ <p style="display: flex; align-items: center">
|
|
|
+ <span class="pl5" v-html="row.id"></span>
|
|
|
+ </p>
|
|
|
+ </template>
|
|
|
+ </vxe-column>
|
|
|
+ <vxe-column field="creationTime" title="创建时间" width="160" align="center">
|
|
|
+ <template #default="{ row }">
|
|
|
+ <span>{{ formatDate(row.creationTime, 'YYYY-mm-dd HH:MM:SS') }}</span>
|
|
|
+ </template>
|
|
|
+ </vxe-column>
|
|
|
+ <vxe-column title="操作" fixed="right" width="150" align="center">
|
|
|
+ <template #default="{ row }">
|
|
|
+ <el-button link type="primary" @click="onEditArea(row)" title="修改" v-auth="'auxiliary:area:edit'" v-if="row.isCanModify">
|
|
|
+ 修改
|
|
|
+ </el-button>
|
|
|
+ <el-button link type="danger" @click="onDelArea(row)" title="删除" v-auth="'auxiliary:area:delete'" v-if="row.isCanModify">
|
|
|
+ 删除
|
|
|
+ </el-button>
|
|
|
+ </template>
|
|
|
+ </vxe-column>
|
|
|
+ </vxe-table>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
<area-add ref="areaAddRef" @updateList="queryList" />
|
|
|
<area-edit ref="areaEditRef" @updateList="queryList" />
|
|
|
</div>
|
|
|
</template>
|
|
|
<script lang="tsx" setup name="auxiliaryArea">
|
|
|
-import { defineAsyncComponent, onActivated, onMounted, reactive, ref, watch } from 'vue';
|
|
|
+import { defineAsyncComponent, nextTick, onMounted, reactive, ref, watch } from 'vue';
|
|
|
import type { FormInstance } from 'element-plus';
|
|
|
import { ElMessage, ElMessageBox } from 'element-plus';
|
|
|
import { formatDate } from '@/utils/formatTime';
|
|
|
-import { auth } from '@/utils/authFunction';
|
|
|
-import { throttle } from '@/utils/tools';
|
|
|
-import other from '@/utils/other';
|
|
|
import { treeArea, treeAreaDelete } from '@/api/auxiliary/area';
|
|
|
+import XEUtils from 'xe-utils';
|
|
|
// 引入组件
|
|
|
const AreaAdd = defineAsyncComponent(() => import('@/views/auxiliary/area/components/Area-add.vue')); // 新增区域
|
|
|
const AreaEdit = defineAsyncComponent(() => import('@/views/auxiliary/area/components/Area-edit.vue')); // 编辑区域
|
|
|
|
|
|
// 定义变量内容
|
|
|
const state = reactive<any>({
|
|
|
- orgTableData: [], // 获取所有菜单
|
|
|
- staticArr: [], // 静态数据
|
|
|
loading: false, // 加载状态
|
|
|
queryParams: {
|
|
|
keyword: null, // 关键字
|
|
|
},
|
|
|
- expandedRowKeys: [], // 展开行
|
|
|
- columns: [
|
|
|
- {
|
|
|
- key: 'areaName',
|
|
|
- dataKey: 'areaName',
|
|
|
- title: '区域名称',
|
|
|
- width: 600,
|
|
|
- },
|
|
|
- {
|
|
|
- key: 'id',
|
|
|
- dataKey: 'id',
|
|
|
- title: '区域代码',
|
|
|
- width: 400,
|
|
|
- },
|
|
|
- {
|
|
|
- key: 'creationTime',
|
|
|
- dataKey: 'creationTime',
|
|
|
- title: '创建时间',
|
|
|
- width: 200,
|
|
|
- cellRenderer: (data: any) => {
|
|
|
- return <span>{formatDate(new Date(data.rowData.creationTime), 'YYYY-mm-dd HH:MM:SS')}</span>;
|
|
|
- },
|
|
|
- },
|
|
|
- {
|
|
|
- key: 'handle',
|
|
|
- title: '操作',
|
|
|
- width: 100,
|
|
|
- fixed: 'right',
|
|
|
- align: 'center',
|
|
|
- cellRenderer: ({ rowData }: any) => {
|
|
|
- return (
|
|
|
- <span class="flex">
|
|
|
- {auth('auxiliary:area:edit') && rowData.isCanModify ? (
|
|
|
- <ElButton onClick={() => onEditArea(rowData)} type="primary" title="修改" link>
|
|
|
- 修改
|
|
|
- </ElButton>
|
|
|
- ) : (
|
|
|
- ''
|
|
|
- )}
|
|
|
- {auth('auxiliary:area:delete') && rowData.isCanModify ? (
|
|
|
- <ElButton onClick={() => onDelArea(rowData)} type="danger" title="删除" link>
|
|
|
- 删除
|
|
|
- </ElButton>
|
|
|
- ) : (
|
|
|
- ''
|
|
|
- )}
|
|
|
- </span>
|
|
|
- );
|
|
|
- },
|
|
|
- },
|
|
|
- ],
|
|
|
- isExpand: false, // 是否展开
|
|
|
});
|
|
|
const ruleFormRef = ref<RefType>(); // 搜索表单ref
|
|
|
-// 搜索
|
|
|
-const formatTable = (list: any[], keyword: string) => {
|
|
|
- if (!list.length || !Array.isArray(list)) return [];
|
|
|
- let emptyArr: any[] = [];
|
|
|
- list.map((item) => {
|
|
|
- if (item.areaName.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 = () => {
|
|
|
- if (state.queryParams.keyword) {
|
|
|
- state.loading = true;
|
|
|
- state.expandedRowKeys = [];
|
|
|
- emptyArr = [];
|
|
|
- state.orgTableData = formatTable(other.deepClone(state.staticArr), state.queryParams.keyword);
|
|
|
- state.expandedRowKeys = getExpand(state.orgTableData);
|
|
|
- state.isExpand = true;
|
|
|
- state.loading = false;
|
|
|
- } else {
|
|
|
- queryList();
|
|
|
- }
|
|
|
-}
|
|
|
+ queryList();
|
|
|
+};
|
|
|
/** 重置按钮操作 */
|
|
|
const resetQuery = (formEl: FormInstance | undefined) => {
|
|
|
if (!formEl) return;
|
|
|
formEl.resetFields();
|
|
|
queryList();
|
|
|
- state.expandedRowKeys = [];
|
|
|
- emptyArr = [];
|
|
|
- state.isExpand = false;
|
|
|
-}
|
|
|
+};
|
|
|
// 打开新增弹窗
|
|
|
const areaAddRef = ref<RefType>(); // 新增组织机构ref
|
|
|
const onAddArea = (row?: any) => {
|
|
|
- areaAddRef.value.openDialog(state.orgTableData, row);
|
|
|
+ areaAddRef.value.openDialog(tableData.value, row);
|
|
|
};
|
|
|
// 打开编辑弹窗
|
|
|
const areaEditRef = ref<RefType>(); // 编辑组织机构ref
|
|
|
const onEditArea = (row: any) => {
|
|
|
- areaEditRef.value.openDialog(row, state.orgTableData);
|
|
|
-};
|
|
|
-const expand = () => {
|
|
|
- state.isExpand = !state.isExpand;
|
|
|
-};
|
|
|
-watch(
|
|
|
- () => state.isExpand,
|
|
|
- (old: Boolean) => {
|
|
|
- if (old) getAllIds(state.orgTableData);
|
|
|
- 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);
|
|
|
- }
|
|
|
- });
|
|
|
+ areaEditRef.value.openDialog(row, tableData.value);
|
|
|
};
|
|
|
// 删除当前行
|
|
|
const onDelArea = (row: any) => {
|
|
@@ -225,12 +136,46 @@ const onDelArea = (row: any) => {
|
|
|
.catch(() => {});
|
|
|
};
|
|
|
// 获取所有部门结构
|
|
|
+const tableData = ref<EmptyArrayType>([]);
|
|
|
+const list = ref<any[]>([]);
|
|
|
const queryList = async () => {
|
|
|
state.loading = true;
|
|
|
try {
|
|
|
- const res: any = await Promise.all([treeArea()]);
|
|
|
- state.orgTableData = res[0].result ?? [];
|
|
|
- state.staticArr = res[0].result ?? [];
|
|
|
+ const res: any = await treeArea();
|
|
|
+ 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 = ['areaName', 'id'];
|
|
|
+ // 搜索为克隆数据,不会污染源数据
|
|
|
+ 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);
|
|
|
+ await nextTick(() => {
|
|
|
+ // 搜索之后默认展开所有子节点
|
|
|
+ if (tableRef.value) {
|
|
|
+ tableRef.value.setAllTreeExpand(true);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ list.value = tableData.value;
|
|
|
+ list.value = XEUtils.toTreeArray(list.value);
|
|
|
+ }
|
|
|
state.loading = false;
|
|
|
} catch (error) {
|
|
|
console.log(error);
|
|
@@ -238,18 +183,12 @@ const queryList = async () => {
|
|
|
}
|
|
|
};
|
|
|
// 页面加载时
|
|
|
+const toolbarRef = ref<RefType>();
|
|
|
+const tableRef = 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>
|
|
|
-.auxiliary-area-container {
|
|
|
- .table {
|
|
|
- flex: 1;
|
|
|
- }
|
|
|
-}
|
|
|
-</style>
|