Files
snowy/snowy-admin-web/src/views/biz/org/index.vue

292 lines
7.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<XnResizablePanel direction="row" :initial-size="300" :min-size="200" :max-size="500" :md="0">
<template #left>
<div ref="treeContainerRef" style="height: 100%">
<xn-tree-skeleton v-if="treeLoading && treeData.length === 0" />
<a-tree
v-else-if="treeData.length > 0"
v-model:expandedKeys="defaultExpandedKeys"
:tree-data="treeData"
:field-names="treeFieldNames"
:load-data="onLoadData"
:height="treeHeight"
@select="treeSelect"
/>
<a-empty v-else :image="Empty.PRESENTED_IMAGE_SIMPLE" />
</div>
</template>
<template #right>
<a-form ref="searchFormRef" :model="searchFormState">
<a-row :gutter="10">
<a-col :xs="24" :sm="8" :md="8" :lg="0" :xl="0">
<a-form-item label="上级机构:" name="parentId">
<a-tree-select
v-model:value="searchFormState.parentId"
class="xn-wd"
:dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"
placeholder="请选择上级机构"
allow-clear
:tree-data="treeData"
:field-names="{
children: 'children',
label: 'name',
value: 'id'
}"
tree-line
:load-data="onLoadData"
/>
</a-form-item>
</a-col>
<a-col :xs="24" :sm="8" :md="8" :lg="8" :xl="8">
<a-form-item name="searchKey" label="名称">
<a-input v-model:value="searchFormState.searchKey" placeholder="请输入名称关键词" />
</a-form-item>
</a-col>
<a-col :xs="24" :sm="16" :md="16" :lg="16" :xl="16">
<a-form-item>
<a-space>
<a-button type="primary" @click="tableRef.refresh(true)">
<template #icon><SearchOutlined /></template>
查询
</a-button>
<a-button @click="reset">
<template #icon><redo-outlined /></template>
重置
</a-button>
</a-space>
</a-form-item>
</a-col>
</a-row>
</a-form>
<s-table
ref="tableRef"
:columns="columns"
:data="loadData"
:expand-row-by-click="true"
:alert="options.alert.show"
bordered
:row-key="(record) => record.id"
:tool-config="toolConfig"
:row-selection="options.rowSelection"
:scroll="{ x: 'max-content' }"
>
<template #operator>
<a-space>
<a-button
type="primary"
@click="formRef.onOpen(undefined, searchFormState.parentId)"
v-if="hasPerm('bizOrgAdd')"
>
<template #icon><plus-outlined /></template>
新增
</a-button>
<xn-batch-button
v-if="hasPerm('bizOrgCopy')"
buttonName="批量复制"
icon="CopyOutlined"
:isPopconFirm="false"
:selectedRowKeys="selectedRowKeys"
@batchCallBack="copyBatchOrg"
/>
<xn-batch-button
v-if="hasPerm('bizOrgBatchDelete')"
buttonName="批量删除"
icon="DeleteOutlined"
buttonDanger
:selectedRowKeys="selectedRowKeys"
@batchCallBack="deleteBatchOrg"
/>
</a-space>
</template>
<template #bodyCell="{ column, record }">
<template v-if="column.dataIndex === 'category'">
{{ $TOOL.dictTypeData('ORG_CATEGORY', record.category) }}
</template>
<template v-if="column.dataIndex === 'action'">
<a @click="formRef.onOpen(record)" v-if="hasPerm('bizOrgEdit')">编辑</a>
<a-divider type="vertical" v-if="hasPerm(['bizOrgEdit', 'bizOrgDelete'], 'and')" />
<a-popconfirm title="删除此机构与下级机构吗" @confirm="removeOrg(record)">
<a-button type="link" danger size="small" v-if="hasPerm('bizOrgDelete')">删除</a-button>
</a-popconfirm>
</template>
</template>
</s-table>
</template>
</XnResizablePanel>
<Form ref="formRef" @successful="tableRef.refresh()" />
<CopyForm ref="copyFormRef" @successful="tableRef.clearRefreshSelected()" />
</template>
<script setup name="bizOrg">
import { Empty } from 'ant-design-vue'
import { isEmpty } from 'lodash-es'
import { triggerRef, onMounted, onActivated, onUnmounted } from 'vue'
import bizOrgApi from '@/api/biz/bizOrgApi'
import Form from './form.vue'
import CopyForm from './copyForm.vue'
const columns = [
{
title: '机构名称',
dataIndex: 'name'
},
{
title: '分类',
dataIndex: 'category'
},
{
title: '排序',
dataIndex: 'sortCode'
}
]
if (hasPerm(['bizOrgEdit', 'bizOrgDelete'])) {
columns.push({
title: '操作',
dataIndex: 'action',
align: 'center',
fixed: 'right'
})
}
const selectedRowKeys = ref([])
// 列表选择配置
const options = {
alert: {
show: false,
clear: () => {
selectedRowKeys.value = ref([])
}
},
rowSelection: {
onChange: (selectedRowKey, selectedRows) => {
selectedRowKeys.value = selectedRowKey
}
}
}
const toolConfig = { refresh: true, height: true, columnSetting: true }
// 定义tableDOM
const tableRef = ref(null)
const formRef = ref()
const searchFormRef = ref()
const searchFormState = ref({})
// 默认展开的节点
const defaultExpandedKeys = ref([])
const treeData = ref([])
// 替换treeNode 中 title,key,children
const treeFieldNames = { children: 'children', title: 'name', key: 'id' }
// 树容器高度自适应
const treeContainerRef = ref(null)
const treeHeight = ref(0)
let resizeObserver = null
const calcTreeHeight = () => {
if (treeContainerRef.value) {
treeHeight.value = treeContainerRef.value.clientHeight
}
}
onMounted(() => {
calcTreeHeight()
if (treeContainerRef.value) {
resizeObserver = new ResizeObserver(calcTreeHeight)
resizeObserver.observe(treeContainerRef.value)
}
})
onActivated(calcTreeHeight)
onUnmounted(() => {
if (resizeObserver) {
resizeObserver.disconnect()
}
})
// 表格查询 返回 Promise 对象
const loadData = (parameter) => {
return bizOrgApi.orgPage(Object.assign(parameter, searchFormState.value)).then((res) => {
return res
})
}
// 重置
const reset = () => {
searchFormRef.value.resetFields()
tableRef.value.refresh(true)
}
const treeLoading = ref(true)
// 加载左侧的树
const loadTreeData = () => {
treeLoading.value = true
bizOrgApi
.orgTreeLazy()
.then((res) => {
if (res !== null) {
treeData.value = res.map((item) => {
return {
...item,
isLeaf: item.isLeaf === undefined ? false : item.isLeaf
}
})
if (isEmpty(defaultExpandedKeys.value)) {
// 默认展开第一级
if (treeData.value.length > 0) {
defaultExpandedKeys.value.push(treeData.value[0].id)
}
}
}
})
.finally(() => {
treeLoading.value = false
})
}
loadTreeData()
// 懒加载子节点
const onLoadData = (treeNode) => {
return new Promise((resolve) => {
if (treeNode.dataRef.children || treeNode.dataRef.isLeaf) {
resolve()
return
}
bizOrgApi
.orgTreeLazy({
parentId: treeNode.dataRef.id
})
.then((res) => {
treeNode.dataRef.children = res.map((item) => {
return {
...item,
isLeaf: item.isLeaf === undefined ? false : item.isLeaf
}
})
triggerRef(treeData)
resolve()
})
})
}
// 点击树查询
const treeSelect = (selectedKeys) => {
if (selectedKeys.length > 0) {
searchFormState.value.parentId = selectedKeys.toString()
} else {
delete searchFormState.value.parentId
}
tableRef.value.refresh(true)
}
// 删除
const removeOrg = (record) => {
let params = [
{
id: record.id
}
]
bizOrgApi.orgDelete(params).then(() => {
tableRef.value.refresh(true)
})
}
// 批量删除
const deleteBatchOrg = (params) => {
bizOrgApi.orgDelete(params).then(() => {
tableRef.value.clearRefreshSelected()
})
}
// 批量复制
const copyFormRef = ref()
const copyBatchOrg = (params) => {
copyFormRef.value.onOpen(params)
}
</script>