123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387 |
- <template>
- <hc-new-dialog v-model="moveModal" is-table title="跨节点移动" widths="72rem" @close="closeModal">
- <hc-page-split class="m-4" :options="{ sizes: [50, 50] }">
- <template #left>
- <hc-card scrollbar>
- <div v-loading="cityLoading" 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.pkeyId"
- :label="city.fullName "
- :value="city.pkeyId "
- class="checkbox-item"
- >
- {{ city.fullName }}
- </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="请输入" clearable />
- </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
- v-if="!isShowSearch"
- ref="treeRef"
- node-key="id"
-
- :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>
- </template>
- </el-tree>
- <el-tree
- v-else
- v-loading="treeLoading"
- node-key="id"
- default-expand-all
- :props="treeProps"
- :data="treeData"
-
- :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>
- </template>
- </el-tree>
- </el-scrollbar>
- </hc-card>
- </hc-page-split>
- <template #footer>
- <el-button :loading="moveLoading" @click="submitMove(1)">保存并退出</el-button>
- <el-button type="primary" :loading="moveLoading" @click="submitMove(2)">保存并继续</el-button>
- </template>
- </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: '',
- },
- primaryKeyId: {
- type: String,
- default: '',
- },
- })
- //事件
- const emit = defineEmits(['close', 'save'])
- const contractId = ref(props.contractId)
- const classType = ref(props.classType)
- const authBtnTabKey = ref(props.authBtnTabKey)
- const primaryKeyId = ref(props.primaryKeyId)
- //监听
- watch(() => [
- props.contractId,
- props.classType,
- props.authBtnTabKey,
- props.primaryKeyId,
- ], ([cid, clas, tab, pkid]) => {
- contractId.value = cid
- classType.value = clas
- authBtnTabKey.value = tab
- primaryKeyId.value = pkid
- getSameLevelsTreeData()
- })
- const moveModal = defineModel('modelValue', {
- default: false,
- })
- const closeModal = ()=>{
- moveModal.value = false
- checkAll.value = false
- checkedCities.value = []
- cities.value = []
- treeRef.value.setCheckedKeys([])
- emit('close')
- }
- const checkAll = ref(false)
- const isIndeterminate = ref(false)
- const checkedCities = ref([])
- const cities = ref([])
- const handleCheckAllChange = (val) => {
- checkedCities.value = val ? cities.value.map(city => city.pkeyId) : []
- isIndeterminate.value = false
- }
- const handleCheckedCitiesChange = (value) => {
- const checkedCount = value.length
- checkAll.value = checkedCount === cities.value.length
- isIndeterminate.value = checkedCount > 0 && checkedCount < cities.value.length
- }
- const searchInput = ref('')
- // 树相关
- const treeRef = ref(null)
- const treeData = ref([])
- const isShowSearch = ref(false)
- 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) {
- isShowSearch.value = false
-
- } else {
- isShowSearch.value = true
- getSearchTreeData()
- }
- // TODO: 实现搜索逻辑
- console.log('搜索关键词:', searchInput.value)
- }
- const treeLoading = ref(false)
- const getSearchTreeData = async () => {
- treeLoading.value = true
- const { error, code, data }
- = await queryApi.getTreeNodeByQueryValueAndContractId({
- contractId: contractId.value,
- queryValue: searchInput.value,
- tableOwner: authBtnTabKey.value,
- })
- //判断状态
- if (!error && code === 200) {
-
- treeData.value = getArrValue(data)
- treeLoading.value = false
- } else {
- treeLoading.value = false
- treeData.value = []
- }
- }
- const cityLoading = ref(false)
- const getSameLevelsTreeData = async () => {
- cityLoading.value = true
- const { error, code, data }
- = await queryApi.getSiblingWbsContract({
- pKeyId: primaryKeyId.value,
-
- })
- //判断状态
- if (!error && code === 200) {
-
- cities.value = getArrValue(data)
- cityLoading.value = false
- } else {
- cityLoading.value = false
- cities.value = []
- }
- }
- const moveLoading = ref(false)
- const submitMove = async (type)=>{
- moveLoading.value = true
- const { error, code, data, msg } = await queryApi.moveNode({
- leftPkeyIds: checkedCities.value,
- rightPkeyId:currentNode.value.pKeyId,
- })
- moveLoading.value = false
- if (!error && code === 200) {
- window.$message?.success(msg ?? '操作成功')
- }
- if (type === 1) {
- emit('save')
- } else {
- checkAll.value = false
- checkedCities.value = []
- cities.value = []
- treeRef.value.setCheckedKeys([])
- getSameLevelsTreeData()
- searchClick()
- }
-
- }
- </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>
|