|
@@ -0,0 +1,279 @@
|
|
|
+<template>
|
|
|
+ <hc-new-dialog v-model="moveModal" is-table title="跨节点移动" widths="72rem" @close="closeModal">
|
|
|
+ <hc-page-split>
|
|
|
+ <template #left>
|
|
|
+ <hc-card scrollbar>
|
|
|
+ <div class="checkbox-container">
|
|
|
+ <el-checkbox
|
|
|
+ v-model="checkAll"
|
|
|
+ :indeterminate="isIndeterminate"
|
|
|
+ @change="handleCheckAllChange"
|
|
|
+ >
|
|
|
+ <span class="font-800">全选</span>
|
|
|
+ </el-checkbox>
|
|
|
+ <el-checkbox-group
|
|
|
+ v-model="checkedCities"
|
|
|
+ class="checkbox-group"
|
|
|
+ @change="handleCheckedCitiesChange"
|
|
|
+ >
|
|
|
+ <el-checkbox
|
|
|
+ v-for="city in cities"
|
|
|
+ :key="city"
|
|
|
+ :label="city"
|
|
|
+ :value="city"
|
|
|
+ class="checkbox-item"
|
|
|
+ >
|
|
|
+ {{ city }}
|
|
|
+ </el-checkbox>
|
|
|
+ </el-checkbox-group>
|
|
|
+ </div>
|
|
|
+ </hc-card>
|
|
|
+ </template>
|
|
|
+ <hc-card class="tree-card">
|
|
|
+ <template #search>
|
|
|
+ <div class="flex-1">
|
|
|
+ <el-input v-model="searchInput" placeholder="请输入" />
|
|
|
+ </div>
|
|
|
+ <div class="ml-2">
|
|
|
+ <el-button
|
|
|
+ hc-btn
|
|
|
+ type="primary"
|
|
|
+ @click="searchClick"
|
|
|
+ >
|
|
|
+ 搜索
|
|
|
+ </el-button>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <!-- 添加懒加载树 -->
|
|
|
+ <el-scrollbar class="tree-scrollbar mt-3" style="height: 100%;">
|
|
|
+ <el-tree
|
|
|
+ ref="treeRef"
|
|
|
+ node-key="id"
|
|
|
+ :data="treeData"
|
|
|
+ :props="treeProps"
|
|
|
+ :load="treeLoadNode"
|
|
|
+ lazy
|
|
|
+ :show-checkbox="true"
|
|
|
+ :check-strictly="true"
|
|
|
+ :check-on-click-node="true"
|
|
|
+
|
|
|
+ highlight-current
|
|
|
+ @check="handleCheckChange"
|
|
|
+ >
|
|
|
+ <template #default="{ node, data }">
|
|
|
+ <span class="custom-tree-node">
|
|
|
+ <span>{{ node.label }}</span>
|
|
|
+ <span v-if="data.code" class="ml-2 text-gray-400">({{ data.code }})</span>
|
|
|
+ </span>
|
|
|
+ </template>
|
|
|
+ </el-tree>
|
|
|
+ </el-scrollbar>
|
|
|
+ </hc-card>
|
|
|
+ </hc-page-split>
|
|
|
+ </hc-new-dialog>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup>
|
|
|
+import { nextTick, ref, watch } from 'vue'
|
|
|
+import { getArrValue, getObjValue } from 'js-fast-way'
|
|
|
+import queryApi from '~api/data-fill/query'
|
|
|
+// 接收父组件传入的属性
|
|
|
+const props = defineProps({
|
|
|
+ contractId: {
|
|
|
+ type: String,
|
|
|
+ default: '',
|
|
|
+ },
|
|
|
+ classType: {
|
|
|
+ type: String,
|
|
|
+ default: '',
|
|
|
+ },
|
|
|
+ authBtnTabKey: {
|
|
|
+ type: String,
|
|
|
+ default: '',
|
|
|
+ },
|
|
|
+})
|
|
|
+//事件
|
|
|
+const emit = defineEmits(['close', 'save'])
|
|
|
+const contractId = ref(props.contractId)
|
|
|
+const classType = ref(props.classType)
|
|
|
+const authBtnTabKey = ref(props.authBtnTabKey)
|
|
|
+//监听
|
|
|
+watch(() => [
|
|
|
+
|
|
|
+ props.contractId,
|
|
|
+ props.classType,
|
|
|
+ props.authBtnTabKey,
|
|
|
+], ([cid, clas, tab]) => {
|
|
|
+ contractId.value = cid
|
|
|
+ classType.value = clas
|
|
|
+ authBtnTabKey.value = tab
|
|
|
+})
|
|
|
+const moveModal = defineModel('modelValue', {
|
|
|
+ default: false,
|
|
|
+})
|
|
|
+const closeModal = ()=>{
|
|
|
+ moveModal.value = false
|
|
|
+
|
|
|
+ emit('close')
|
|
|
+}
|
|
|
+
|
|
|
+const checkAll = ref(false)
|
|
|
+const isIndeterminate = ref(true)
|
|
|
+const checkedCities = ref([])
|
|
|
+const cities = ['Shanghai', 'Beijing']
|
|
|
+
|
|
|
+const handleCheckAllChange = (val) => {
|
|
|
+ checkedCities.value = val ? cities : []
|
|
|
+ isIndeterminate.value = false
|
|
|
+}
|
|
|
+const handleCheckedCitiesChange = (value) => {
|
|
|
+ const checkedCount = value.length
|
|
|
+ checkAll.value = checkedCount === cities.length
|
|
|
+ isIndeterminate.value = checkedCount > 0 && checkedCount < cities.length
|
|
|
+}
|
|
|
+const searchInput = ref('')
|
|
|
+
|
|
|
+// 树相关
|
|
|
+const treeRef = ref(null)
|
|
|
+const treeData = ref([])
|
|
|
+const currentNode = ref(null)
|
|
|
+
|
|
|
+// 树配置
|
|
|
+const treeProps = {
|
|
|
+ label: 'title',
|
|
|
+ children: 'children',
|
|
|
+ isLeaf: 'notExsitChild',
|
|
|
+}
|
|
|
+
|
|
|
+// 加载节点数据
|
|
|
+
|
|
|
+const treeLoadNode = async (node, resolve) => {
|
|
|
+
|
|
|
+ const { level, data: item } = node
|
|
|
+
|
|
|
+ let contractIdRelation = '',
|
|
|
+ parentId = '',
|
|
|
+ primaryKeyId = ''
|
|
|
+ if (level !== 0) {
|
|
|
+ const nodeData = getObjValue(item)
|
|
|
+ contractIdRelation = nodeData?.contractIdRelation || ''
|
|
|
+ parentId = contractIdRelation ? nodeData?.primaryKeyId : nodeData?.id
|
|
|
+ primaryKeyId = nodeData?.id || ''
|
|
|
+ }
|
|
|
+ //获取数据
|
|
|
+ const { data } = await queryApi.queryWbsTreeData({
|
|
|
+ contractId: contractId.value || '',
|
|
|
+ contractIdRelation,
|
|
|
+ primaryKeyId,
|
|
|
+ parentId,
|
|
|
+ // classifyType: authBtnTabKey.value,
|
|
|
+ classifyType: classType.value,
|
|
|
+ tableOwner: authBtnTabKey.value,
|
|
|
+ dataTime:new Date(),
|
|
|
+ })
|
|
|
+
|
|
|
+
|
|
|
+ resolve(getArrValue(data))
|
|
|
+}
|
|
|
+// 节点点击事件
|
|
|
+const handleCheckChange = (data, checked) => {
|
|
|
+ // 确保只能选中一个节点
|
|
|
+ const checkedNodes = treeRef.value.getCheckedNodes()
|
|
|
+ if (checkedNodes.length > 1) {
|
|
|
+ // 取消之前选中的节点
|
|
|
+ checkedNodes.forEach(node => {
|
|
|
+ if (node.id !== data.id) {
|
|
|
+ treeRef.value.setChecked(node, false)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ currentNode.value = checked ? data : null
|
|
|
+ console.log('当前选中节点:', currentNode.value)
|
|
|
+}
|
|
|
+
|
|
|
+// 搜索功能
|
|
|
+const searchClick = () => {
|
|
|
+ if (!searchInput.value) {
|
|
|
+ window.$message.warning('请输入搜索关键词')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ // TODO: 实现搜索逻辑
|
|
|
+ console.log('搜索关键词:', searchInput.value)
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+.checkbox-container {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 10px;
|
|
|
+
|
|
|
+ .checkbox-group {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 10px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .checkbox-item {
|
|
|
+ height: 32px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.custom-tree-node {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ font-size: 14px;
|
|
|
+
|
|
|
+ .el-icon {
|
|
|
+ margin-right: 4px;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+:deep(.el-tree-node__content) {
|
|
|
+ height: 32px;
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ background-color: var(--el-tree-node-hover-bg-color);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+:deep(.el-tree) {
|
|
|
+ // 自定义复选框样式使其看起来像单选框
|
|
|
+ .el-checkbox {
|
|
|
+ .el-checkbox__inner {
|
|
|
+ border-radius: 50%;
|
|
|
+ &::after {
|
|
|
+ transform: rotate(45deg) scaleY(1);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+// 添加树卡片样式
|
|
|
+.tree-card {
|
|
|
+ height: 100%;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+
|
|
|
+ :deep(.hc-card-body) {
|
|
|
+ flex: 1;
|
|
|
+ height: 0;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ padding: 0;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 修改滚动容器样式
|
|
|
+.tree-scrollbar {
|
|
|
+ flex: 1;
|
|
|
+ height: 0;
|
|
|
+ margin-top: 12px;
|
|
|
+
|
|
|
+ :deep(.el-scrollbar__view) {
|
|
|
+ height: 100%;
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|