123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665 |
- <template>
- <hc-drawer
- v-model="isShow"
- to-id="hc-main-box"
- is-close
- @close="drawerClose"
- >
- <hc-body split :options="splitOptions">
- <template #left>
- <hc-tab-card :tabs="tabsData1" :tab-key="tabsKey1">
- <hc-card scrollbar>
- <template #header>
- <hc-search-input
- v-model="searchTreeName"
- placeholder="请输入关键字"
- @search="searchTreeNameClick"
- />
- </template>
- <template v-if="isTreeMode === 1">
- <hc-lazy-tree
- v-if="isShow"
- ref="treeRef1"
- is-load-menu
- :h-props="treeProps"
- tree-key="id"
- @load-menu="treeMenu"
- @load="treeLoadNode"
- @node-tap="treeNodeTap"
- @menu-tap="treeMenuClick"
- >
- <template #name="{ data }">
- <span class="text-16px font-400">{{
- data.title
- }}</span>
- </template>
- </hc-lazy-tree>
- </template>
- <template v-if="isTreeMode === 2">
- <hc-data-tree
- ref="treeRef2"
- is-load-menu
- :h-props="treeProps"
- tree-key="id"
- :datas="treeData"
- @load-menu="treeMenu"
- @node-tap="treeNodeTap"
- @menu-tap="treeMenuClick"
- >
- <template #name="{ data }">
- <span class="text-16px font-400">{{
- data.title
- }}</span>
- </template>
- </hc-data-tree>
- </template>
- </hc-card>
- </hc-tab-card>
- </template>
- <hc-tab-card
- :tabs="tabsData"
- :tab-key="tabsKey"
- @change="tabsChange"
- >
- <template v-if="tabsKey === 'second'">
- <div class="hc-flex mb-10px">
- <el-button type="primary" plain @click="setClick(1)">
- 设置为最高并卷层级
- </el-button>
- <el-button type="primary" plain @click="setClick(2)">
- 设置为分类卷并卷
- </el-button>
- <el-button type="primary" plain @click="setClick(3)">
- 设置为独立组卷
- </el-button>
- </div>
- <div class="hc-tab-scroll-class-second">
- <el-scrollbar v-loading="secondTreeLoad">
- <hc-data-tree
- ref="secondTree"
- is-load-menu
- :h-props="secondTreeProps"
- tree-key="id"
- :datas="secondTreeData"
- show-checkbox
- check-strictly
- @load-menu="secondTreeMenu"
- @menu-tap="secondTreeMenuClick"
- >
- <template #name="{ data }">
- <!-- <div class="config_type">最</div> -->
- <template
- v-if="
- Number(
- data.archiveAutoGroupSelect,
- ) === 1
- "
- >
- <div
- v-if="
- Number(data.archiveAutoType)
- === 1
- "
- class="config_type"
- >
- 最
- </div>
- <div
- v-if="
- Number(data.archiveAutoType)
- === 2
- "
- class="config_type"
- >
- 分
- </div>
- <div
- v-if="
- Number(data.archiveAutoType)
- === 3
- "
- class="config_type"
- >
- 独
- </div>
- </template>
- <span class="text-16px font-400">{{
- data.title
- }}</span>
- </template>
- </hc-data-tree>
- </el-scrollbar>
- </div>
- </template>
- <template v-if="tabsKey === 'first'">
- <entryConfig
- :right-data="secondTreeData"
- :project-id="dataInfo.id"
- :tab-key="tabsKey"
- />
- </template>
- </hc-tab-card>
- </hc-body>
- <!-- 树节点新增 -->
- <HcTreeNodeForm
- v-model="isTreeFormShow"
- :info="dataInfo"
- :data="treeFormData"
- :node="treeFormNode"
- :type="treeFormType"
- @finish="pseudoRefresh"
- />
- <!-- 树节点排序 -->
- <HcTreeNodeSort
- v-model="isTreeSortShow"
- :data="treeSortData"
- @finish="pseudoRefresh"
- />
- <!-- 查看配置 -->
- <hc-dialog v-model="configVisible" title="查看配置">
- <div v-if="configInfo && configInfo.type">
- <div class="mb-2" style="font-size: 18px">
- <span>配置类别:</span>
- <span v-if="configInfo.type == 1">最高并卷层级</span>
- <span v-if="configInfo.type == 2">分类并卷</span>
- <span v-if="configInfo.type == 3">独立组卷</span>
- </div>
- <template v-if="configInfo.type !== 2">
- <div class="config-allname">
- {{ configInfo.data.allName }}
- </div>
- </template>
- <template v-else>
- <hc-data-tree
- ref="configtree"
- :datas="configInfo.data"
- tree-key="id"
- :h-props="configTreeProps"
- show-checkbox
- :check-strictly="true"
- :default-checked-keys="checkedKeys"
- :auto-expand-keys="checkedKeys"
- @check="configCheckChange"
- />
- </template>
- </div>
- <div v-else style="text-align: center; font-size: 22px">
- 该节点尚未配置
- </div>
- <template #footer>
- <el-button @click="configVisible = false">取消查看</el-button>
- <el-button
- v-if="configInfo && configInfo.type == 2"
- type="primary"
- @click="changeConfig"
- >
- 确认修改配置
- </el-button>
- </template>
- </hc-dialog>
- <!-- 设置最高层级 -->
- <hc-dialog
- v-model="highVisible"
- :title="titleName"
- @save="setRecordsHandle"
- @close="highVisible = false"
- >
- <el-checkbox-group v-model="checkList" class="wraplabel">
- <div v-for="node in nodesList" :key="node.id">
- <el-checkbox
- :label="node.pathName"
- :value="node.id"
- style="margin-bottom: 10px"
- />
- </div>
- </el-checkbox-group>
- </hc-dialog>
- </hc-drawer>
- </template>
- <script setup>
- import { ref, watch } from 'vue'
- import { HcDelMsg, HcFirmMsg } from 'hc-vue3-ui'
- import { getArrValue, isNullES } from 'js-fast-way'
- import HcTreeNodeForm from './tree-form.vue'
- import HcTreeNodeSort from './tree-sort.vue'
- import mainApi from '~api/project/tree'
- import archiveApi from '~api/desk/archive-tree'
- import entryConfig from '../../desk/wbs/entry-config.vue'
- const props = defineProps({
- data: {
- type: Object,
- default: () => ({}),
- },
- })
- //事件
- const emit = defineEmits(['close'])
- //双向绑定
- const isShow = defineModel('modelValue', {
- default: false,
- })
- //监听数据
- const dataInfo = ref(props.data)
- watch(
- () => props.data,
- (data) => {
- dataInfo.value = data
- },
- { immediate: true, deep: true },
- )
- //监听显示
- watch(isShow, (val) => {
- if (val) getDataApi()
- })
- //处理相关数据
- const getDataApi = () => {
- getTreeAllData()
- getSecondTreeData()
- }
- //树搜索
- const isTreeMode = ref(1) //1懒加载,2全加载
- const searchTreeName = ref('')
- const searchTreeNameClick = async () => {
- if (isNullES(searchTreeName.value)) {
- isTreeMode.value = 1
- } else {
- isTreeMode.value = 2
- await getTreeAllData()
- treeRef2.value?.treeRef?.filter(searchTreeName.value)
- }
- }
- //树配置
- const treeRef1 = ref(null)
- const treeRef2 = ref(null)
- const treeProps = {
- label: 'title',
- children: 'children',
- isLeaf: 'hasChildren',
- }
- //懒加载树的菜单
- const treeMenu = ({ level }, resolve) => {
- let newMenu = []
- if (level !== 1) {
- newMenu.push({ icon: 'add-circle', label: '新增', key: 'add' })
- newMenu.push({ icon: 'draft', label: '编辑', key: 'edit' })
- newMenu.push({ icon: 'arrow-up-down', label: '排序', key: 'rank' })
- newMenu.push({ icon: 'delete-bin', label: '删除', key: 'del' })
- }
- newMenu.push({ icon: 'refresh', label: '同步', key: 'sync' })
- resolve(newMenu)
- }
- //菜单被点击
- const treeMenuClick = ({ key, data, node }) => {
- if (key === 'add') {
- if (Number(data.isStorageNode) !== 1) {
- treeFormType.value = '新增'
- treeFormData.value = data
- treeFormNode.value = node
- isTreeFormShow.value = true
- } else {
- window.$message.warning('该节点下不允许新增节点')
- }
- } else if (key === 'edit') {
- treeFormType.value = '编辑'
- treeFormData.value = data
- treeFormNode.value = node
- isTreeFormShow.value = true
- } else if (key === 'rank') {
- treeSortData.value = data
- isTreeSortShow.value = true
- } else if (key === 'del') {
- delTreeNode(data.id)
- } else if (key === 'sync') {
- syncTreeNode(data.id)
- }
- }
- //树节点新增/编辑
- const isTreeFormShow = ref(false)
- const treeFormData = ref({})
- const treeFormNode = ref({})
- const treeFormType = ref('新增')
- //树节点排序
- const isTreeSortShow = ref(false)
- const treeSortData = ref({})
- //删除树节点
- const delTreeNode = (id) => {
- HcDelMsg(async (resolve) => {
- const { isRes } = await mainApi.removeTree(id)
- if (!isRes) return
- window.$message.success('删除成功')
- resolve() //关闭弹窗的回调
- pseudoRefresh()
- })
- }
- //同步树节点
- const syncTreeNode = (id) => {
- HcFirmMsg({ text: '是否同步该节点?' }, async (resolve) => {
- const { isRes } = await mainApi.syncProjectTree({ id })
- resolve() //关闭弹窗的回调
- if (!isRes) return
- window.$message.success('操作成功')
- pseudoRefresh()
- })
- }
- //伪刷新
- const pseudoRefresh = () => {
- const val = isTreeMode.value
- isTreeMode.value = 4
- treeFormData.value = {}
- treeFormNode.value = {}
- treeFormType.value = ''
- treeSortData.value = {}
- setTimeout(() => {
- isTreeMode.value = val
- }, 300)
- }
- //全加载树
- const treeData = ref([])
- const getTreeAllData = async () => {
- const { data } = await mainApi.allTree({
- projectId: dataInfo.value.id,
- })
- treeData.value = getArrValue(data)
- }
- //立卷规则树
- const getSecondTreeData = async () => {
- secondTreeLoad.value = true
- const { data } = await mainApi.allTree({
- projectId: dataInfo.value.id,
- })
- secondTreeLoad.value = false
- secondTreeData.value = getArrValue(data)
- }
- //懒加载树
- const treeLoadNode = async ({ item, level }, resolve) => {
- const parentId = level === 0 ? 0 : item.id
- if (level === 0) {
- const arr = await lazyNodeTree(parentId)
- if (arr.length) {
- resolve(arr)
- } else {
- resolve(await archiveTreeInit())
- }
- } else {
- resolve(await lazyNodeTree(parentId))
- }
- }
- //懒加载树接口
- const lazyNodeTree = async (id) => {
- const { data } = await mainApi.lazyTree({
- parentId: id,
- projectId: dataInfo.value.id,
- })
- const res = getArrValue(data)
- for (let i = 0; i < res.length; i++) {
- res[i].hasChildren = !res[i].hasChildren
- }
- return res
- }
- //初始化根节点
- const archiveTreeInit = async () => {
- const { data } = await mainApi.treeInit({
- projectId: dataInfo.value.id,
- })
- const res = getArrValue(data)
- for (let i = 0; i < res.length; i++) {
- res[i].hasChildren = !res[i].hasChildren
- }
- return res
- }
- //树节点被点击
- const nodeInfo = ref({})
- const treeNodeTap = ({ data }) => {
- nodeInfo.value = data
- }
- //页面分割
- const splitOptions = { sizes: [50, 50], snapOffset: 0, minSize: [300, 300] }
- //左边选项卡
- const tabsKey1 = ref('1')
- const tabsData1 = ref([
- { key: '1', name: '竣工档案目录' },
- { key: '2', name: '文书档案目录' },
- ])
- //右边选项卡
- const tabsKey = ref('second')
- const tabsData = ref([
- { key: 'second', name: '立卷规则' },
- { key: 'first', name: '工程文件入口配置' },
- ])
- const tabsChange = ({ key }) => {
- tabsKey.value = key
- getSecondTreeData()
- }
- //立卷规则树
- const secondTreeLoad = ref(false)
- const secondTree = ref(null)
- const secondTreeData = ref([])
- const secondTreeProps = {
- label: 'title',
- }
- //立卷规则树右键菜单
- const secondTreeMenu = (_, resolve) => {
- resolve([
- { icon: 'eye', label: '查看配置', key: 'rank' },
- { icon: 'delete-bin', label: '删除', key: 'del' },
- ])
- }
- const secondTreeMenuClick = async ({ key, data, node }) => {
- if (key === 'rank') {
- configInfo.value = null
- const {
- data: res,
- code,
- msg,
- } = await archiveApi.getArchiveAutoRule({
- nodeId: data.id, //归档树节点的id 或者 挂载wbs节点的ID(具体哪个ID待定)
- iswbsNode: data.iswbsNode, //是否是wbs节点
- projectId: dataInfo.value.id, // 系统级为0 项目级为项目id
- wbsNode2ArchiveTreeNodeId: data.wbsNode2ArchiveTreeNodeId, // 这个树节点里面有(iswbsNode为true需传)
- })
- console.log(res, 'res')
- if (code == 200 && msg == '操作成功') {
- if (res.type) {
- configInfo.value = res
- } else if (res.archiveAutoType) {
- configInfo.value = {
- type: 2,
- data: res.tree,
- }
- checkedKeys.value = res?.selectNodeIds.split(',')
- } else {
- configInfo.value = {}
- }
- console.log(configInfo.value, 'configInfo.value ')
- configVisible.value = true
- }
- } else if (key === 'del') {
- HcDelMsg(async (resolve) => {
- const { code } = await archiveApi.removeArchiveAutoRule({
- nodeId: data.id,
- iswbsNode: data.iswbsNode, //是否是wbs节点 flase 不是 true 是 (先false,具体怎么区分后面再看)
- projectId: dataInfo.value.id, // 系统级为0 项目级为项目id
- })
- resolve() //关闭弹窗的回调
- if (code !== 200) return
- window.$message.success('删除成功')
- getSecondTreeData()
- }).then()
- }
- }
- //设置为最高并卷层级
- //获取树节点名字路径
- const getTreeNodePath = (node, refName) => {
- let nodeInfo = secondTree.value.treeRef.getNode(node.id)
- let pathArr = []
- while (nodeInfo.parent) {
- pathArr.push(nodeInfo.data.title)
- nodeInfo = nodeInfo.parent
- }
- return pathArr.reverse().join('/')
- }
- const setRecordsHandle = async () => {
- const { code, msg } = await archiveApi.saveArchiveAutoRule({
- archiveAutoType: archiveAutoType.value, //最高1 分类2 独立3
- selectNodeIds: checkList.value.join(','), //鼠标选择的节点ID(只要鼠标选择的节点,选择节点的下级子节点那种不要),逗号拼接
- iswbsNode: nodesList.value[0]?.iswbsNode, //是否是wbs节点
- projectId: dataInfo.value.id, // 系统级为0 项目级为项目id
- })
- if (code == 200 && msg == '操作成功') {
- window.$message({
- type: 'success',
- message: '设置成功',
- })
- highVisible.value = false
- getSecondTreeData()
- }
- }
- const setClick = (type) => {
- const treeRef = secondTree.value?.getRef() //树的原始ref
- const nodes = treeRef.getCheckedNodes() //获取选中的节点
- console.log(nodes, 'nodes')
- if (nodes.length < 1) {
- window.$message({
- message: '请先勾选节点,再进行设置',
- type: 'warning',
- })
- return false
- }
- let ids = []
- nodes.forEach((element) => {
- element.pathName = getTreeNodePath(element, 'secondTree')
- ids.push(element.id)
- })
- console.log(nodes, 'nodes')
- checkList.value = ids
- nodesList.value = nodes
- setName(type)
- highVisible.value = true
- }
- const titleName = ref('')
- const archiveAutoType = ref(1)
- const highVisible = ref(false)
- const checkList = ref([])
- const nodesList = ref([])
- const setName = (type) => {
- switch (type) {
- case 1:
- archiveAutoType.value = 1
- titleName.value = '设置最高并卷层级'
- break
- case 2:
- archiveAutoType.value = 2
- titleName.value = '设置分类并卷层级'
- break
- case 3:
- archiveAutoType.value = 3
- titleName.value = '设置单独并卷层级'
- break
- }
- }
- //查看配置
- const configtree = ref(null)
- const configVisible = ref(false)
- const configInfo = ref({})
- const checkedKeys = ref([])
- const configTreeProps = {
- label: 'nodeName',
- children: 'children',
- isLeaf: 'hasChildren',
- }
- const configCheckChange = (_, { checkedNodes }) => {
- let array = checkedNodes
- for (let index = 1; index < array.length; index++) {
- const element = array[index]
- if (element.iswbsNode !== array[0].iswbsNode) {
- //取消勾选
- configtree.value.treeRef.setChecked(data.id, false, false)
- window.$message({
- message: '非wbs节点不能和wbs节点一起设置规则',
- type: 'warning',
- })
- return
- }
- }
- }
- const changeConfig = async () => {
- let keys = configtree.value.treeRef.getCheckedKeys()
- let nodes = configtree.value.treeRef.getCheckedNodes()
- console.log(nodes)
- const { code, msg } = await archiveApi.updateArchiveAutoRules({
- archiveAutoType: 2, //最高1 分类2 独立3
- archiveAutoGroupId: configInfo.value.data.archiveAutoGroupId,
- selectNodeIds: keys.join(','), //鼠标选择的节点ID(只要鼠标选择的节点,选择节点的下级子节点那种不要),逗号拼接
- iswbsNode: nodes[0]?.iswbsNode, //是否是wbs节点
- projectId: dataInfo.value.id, // 系统级为0 项目级为项目id
- })
- if (code == 200) {
- window.$message({
- type: 'success',
- message: msg,
- })
- configVisible.value = false
- }
- }
- //关闭抽屉
- const drawerClose = () => {
- isShow.value = false
- emit('close')
- }
- </script>
- <style scoped lang="scss">
- .hc-tab-scroll-class-second {
- position: relative;
- height: calc(100% - 42px);
- }
- .hc-tab-scroll-class-second :deep(.hc-tree-node .data-custom-tree-node .label) {
- display: flex;
- }
- .hc-tab-scroll-class-second :deep(.config_type) {
- position: relative;
- height: 18px;
- width: 18px;
- font-size: 14px;
- display: flex;
- align-items: center;
- justify-content: center;
- background: #fb5c5c;
- color: white;
- border-radius: 3px;
- margin-right: 5px;
- }
- </style>
|