Browse Source

feat: 拖拽改变层级关系

text-draggable
xuesinan 3 years ago
parent
commit
e376206137
  1. 2
      src/apis/index.js
  2. 2
      src/components/tall/left/Index.vue
  3. 508
      src/components/tall/left/Projects copy.vue
  4. 299
      src/components/tall/left/Projects.vue

2
src/apis/index.js

@ -128,7 +128,7 @@ export const getFinanceByTask = (params, url) => http.post(`${url}/finance/getBy
* 导入wbs
* @param {object} e
*/
export const importWbs = (url, formData, config, parentId) => http.post(`${url}/tall/project/wbs?parentId=${parentId}`, formData, config);
export const importWbs = (url, formData, parentId) => http.post(`${url}/tall/project/wbs?parentId=${parentId}`, formData);
// 导出
export const exportWbs = (params, url) => http.post(`${url}/tall/project/exportWbs`, params);

2
src/components/tall/left/Index.vue

@ -72,7 +72,7 @@ async function toUpload(e) {
param.append('file', file);
const config = { headers: { 'Content-Type': 'multipart/form-data' } };
const res = await importWbs(currUrl.value, param, config, '');
const res = await importWbs(currUrl.value, param, '');
store.commit('layout/setRefreshProjects', !refreshProjects.value);
} catch (error) {
message.info(error || '导入失败');

508
src/components/tall/left/Projects copy.vue

@ -0,0 +1,508 @@
<template>
<a-divider />
<div class="list-flex">
<div class="item-box" v-for="(item, index) in projects" :key="index">
<div class="one-level h-70 cursor-pointer flex items-center">
<!-- <div class="icon" @click.stop="showActionCard(item)"><img src="https://www.tall.wiki/staticrec/drag.svg" /></div> -->
<div class="flex-none">
<a-popover placement="bottomLeft">
<template #content>
<p class="cursor-pointer" @click="showImportCard(item)">导入</p>
<p class="cursor-pointer" @click="exportProject(item.id)">导出</p>
<p class="m-0 cursor-pointer" @click="showDelCard(item)">删除</p>
</template>
<div class="icon"><img src="https://www.tall.wiki/staticrec/drag.svg" /></div>
</a-popover>
</div>
<div class="w-full flex items-center justify-between" @click="toDetail(item)">
<div class="detail">
<div class="name-box flex items-center" :class="{ 'mb-2': item.businessCode !== 'ZERO' }">
<div class="name truncate">{{ item.name }}</div>
<div class="precent-num">
{{ item.status === 1 ? '进行中' : item.status === 2 ? '已结束' : item.status === 0 ? '未开始' : '暂停' }}
</div>
</div>
<div class="time" v-if="item.businessCode !== 'ZERO'">
{{ dayjs(Number(item.startTime)).format('MM-DD HH:mm') }}
{{ dayjs(Number(item.endTime)).format('MM-DD HH:mm') }}
</div>
</div>
<div class="right flex justify-end items-center" @click.stop="openMenu">
<a-button v-if="item.businessCode === 'ZERO'" class="mr-2" shape="round" type="primary" @click="toWorkbench(item)">
工作台
</a-button>
<RightOutlined v-if="!item.show" @click="changeShow(item)" />
<DownOutlined v-else @click="changeShow(item)" />
</div>
</div>
</div>
<div class="two-box" v-if="item.show">
<div class="two-flex" v-for="(sonItem, sonIndex) in item.sonProjectList" :key="sonIndex">
<div class="two-level h-70 cursor-pointer flex items-center">
<!-- <div class="icon" @click.stop="showActionCard(sonItem)"><img src="https://www.tall.wiki/staticrec/drag.svg" /></div> -->
<div class="flex-none">
<a-popover placement="bottomLeft">
<template #content>
<!-- <p class="cursor-pointer" @click="showImportCard(sonItem)">导入</p> -->
<p class="cursor-pointer" @click="exportProject(sonItem.id)">导出</p>
<p class="m-0 cursor-pointer" @click="showDelCard(sonItem)">删除</p>
</template>
<div class="icon"><img src="https://www.tall.wiki/staticrec/drag.svg" /></div>
</a-popover>
</div>
<div class="flex items-center justify-between" style="width: calc(100% - 32px)" @click="toDetail(sonItem)">
<div class="detail">
<div class="name-box mb-2 flex items-center">
<div class="name truncate">{{ sonItem.name }}</div>
<div class="precent-num">
{{ item.status === 1 ? '进行中' : item.status === 2 ? '已结束' : item.status === 0 ? '未开始' : '暂停' }}
</div>
</div>
<div class="time">
{{ dayjs(Number(sonItem.startTime)).format('MM-DD HH:mm') }}
{{ dayjs(Number(sonItem.endTime)).format('MM-DD HH:mm') }}
</div>
</div>
<div class="right" @click.stop="openMenu">
<RightOutlined v-if="!sonItem.show" @click="changeShow(sonItem)" />
<DownOutlined v-else @click="changeShow(sonItem)" />
</div>
</div>
</div>
</div>
</div>
</div>
<input class="import-wbs hidden" type="file" @change="toImport" />
<a-modal v-model:visible="importVisible" title="导入" @ok="handleImport">
<p>确定要导入到{{ importParent }}</p>
</a-modal>
<a-modal v-model:visible="visible" title="删除" @ok="handleOk">
<p>确定要删除吗</p>
</a-modal>
<draggable
class="dragArea p-0 list-none"
tag="ul"
:list="projects"
:group="{ name: 'g1' }"
item-key="name"
:move="checkMove"
@end="onEnd"
>
<template #item="{ element }">
<li class="item-box">
<!-- <p>{{ element.name }}</p> -->
<div
class="one-level cursor-pointer h-60 flex items-center"
:class="{ 'h-70': element.sonProjectList && element.sonProjectList.length > 0 }"
:style="{ 'padding-top': element.sonProjectList && element.sonProjectList.length > 0 ? 0 : '5px' }"
>
<!-- <div class="icon" @click.stop="showActionCard(item)"><img src="https://www.tall.wiki/staticrec/drag.svg" /></div> -->
<div class="flex-none">
<a-popover placement="bottomLeft">
<template #content>
<p class="cursor-pointer" @click="showImportCard(element)">导入</p>
<p class="cursor-pointer" @click="exportProject(element.id)">导出</p>
<p class="m-0 cursor-pointer" @click="showDelCard(element)">删除</p>
</template>
<div class="icon"><img src="https://www.tall.wiki/staticrec/drag.svg" /></div>
</a-popover>
</div>
<div class="w-full flex items-center justify-between" @click="toDetail(element)">
<div class="detail">
<div class="name-box flex items-center" :class="{ 'mb-2': element.businessCode !== 'ZERO' }">
<div class="name truncate">{{ element.name }}</div>
<div class="precent-num">
{{ element.status === 1 ? '进行中' : element.status === 2 ? '已结束' : element.status === 0 ? '未开始' : '暂停' }}
</div>
</div>
<div class="time" v-if="element.businessCode !== 'ZERO'">
{{ dayjs(Number(element.startTime)).format('MM-DD HH:mm') }}
{{ dayjs(Number(element.endTime)).format('MM-DD HH:mm') }}
</div>
</div>
<div class="right flex justify-end items-center" @click.stop="openMenu">
<a-button v-if="element.businessCode === 'ZERO'" class="mr-2" shape="round" type="primary" @click="toWorkbench(element)">
工作台
</a-button>
<RightOutlined v-if="!element.show" @click="changeShow(element)" />
<DownOutlined v-else @click="changeShow(element)" />
</div>
</div>
</div>
<draggable
class="dragArea p-0 list-none two-box"
tag="ul"
:list="element.sonProjectList"
:group="{ name: 'g1' }"
item-key="name"
:move="checkMove"
@end="onEnd"
>
<template #item="{ element }">
<li class="two-flex">
<!-- <p>{{ element.name }}</p> -->
<div class="two-level h-70 cursor-pointer flex items-center">
<!-- <div class="icon" @click.stop="showActionCard(sonItem)">
<img src="https://www.tall.wiki/staticrec/drag.svg" />
</div> -->
<div class="flex-none">
<a-popover placement="bottomLeft">
<template #content>
<!-- <p class="cursor-pointer" @click="showImportCard(sonItem)">导入</p> -->
<p class="cursor-pointer" @click="exportProject(element.id)">导出</p>
<p class="m-0 cursor-pointer" @click="showDelCard(element)">删除</p>
</template>
<div class="icon"><img src="https://www.tall.wiki/staticrec/drag.svg" /></div>
</a-popover>
</div>
<div class="flex items-center justify-between" style="width: calc(100% - 32px)" @click="toDetail(element)">
<div class="detail">
<div class="name-box mb-2 flex items-center">
<div class="name truncate">{{ element.name }}</div>
<div class="precent-num">
{{ element.status === 1 ? '进行中' : element.status === 2 ? '已结束' : element.status === 0 ? '未开始' : '暂停' }}
</div>
</div>
<div class="time">
{{ dayjs(Number(element.startTime)).format('MM-DD HH:mm') }}
{{ dayjs(Number(element.endTime)).format('MM-DD HH:mm') }}
</div>
</div>
<div class="right" @click.stop="openMenu">
<RightOutlined v-if="!element.show" @click="changeShow(element)" />
<DownOutlined v-else @click="changeShow(element)" />
</div>
</div>
</div>
</li>
</template>
</draggable>
</li>
</template>
</draggable>
</div>
</template>
<script setup>
import { ref, reactive, watch, computed } from 'vue';
import { useStore } from 'vuex';
import { useRouter } from 'vue-router';
import dayjs from 'dayjs';
import { getProjects, delProject, setProjectSort, exportWbs, importWbs } from 'apis';
import { RightOutlined, DownOutlined } from '@ant-design/icons-vue';
import { message } from 'ant-design-vue';
import draggable from 'vuedraggable';
const store = useStore();
const router = useRouter();
const visible = ref(false); //
const importVisible = ref(false); //
const importParent = ref(null); //
const importParentId = ref(null); // ID
const currUrl = ref(null); // url
const deleteId = ref(null); // id
const sessionProject = sessionStorage.getItem('project'); //
const projectInfo = computed(() => store.state.projects.project); //
const projects = computed(() => store.state.projects.projects); //
const startTime = computed(() => store.state.layout.startTime); //
const endTime = computed(() => store.state.layout.endTime); //
const refreshProjects = computed(() => store.state.layout.refreshProjects); //
const moveProjectId = ref(''); // id
const moveBusinessCode = ref(''); //
const targetProjectId = ref(''); // id
if (sessionProject && !projectInfo.value.id) {
// storestorestore
const info = JSON.parse(sessionProject);
store.commit('projects/setProject', info);
}
//
if (!startTime.value) {
const data = {
startTime: dayjs().startOf('day').format('x'),
endTime: dayjs().endOf('day').format('x'),
};
store.commit('layout/setSelectTime', data);
}
getProjectsList();
watch([startTime, endTime, refreshProjects], () => {
getProjectsList();
});
//
async function getProjectsList() {
try {
const data = await getProjects(startTime.value, endTime.value);
data.forEach(item => {
item.show = false;
if (item.sonProjectList.length > 0) {
item.show = true;
}
});
store.commit('projects/setProjects', data);
} catch (error) {
message.info(error);
throw new Error(error);
}
}
//
function toDetail(item) {
clearRolesData();
clearTasksData();
store.commit('projects/setProject', item);
store.commit('task/setTaskDetailParams', ''); //
store.commit('task/setTaskDetailUrl', ''); //
store.commit('task/setTaskDetailShow', '');
router.push({ path: '/tall/pc/home/test' });
}
//
function changeShow(item) {
item.show = !item.show;
}
//
const showImportCard = item => {
importVisible.value = true;
importParent.value = item.name;
importParentId.value = item.id;
currUrl.value = item.url;
};
//
async function handleImport() {
importVisible.value = false;
await importProject();
getProjectsList();
}
//
async function importProject() {
document.querySelector('.import-wbs').click();
}
async function toImport(e) {
try {
const file = e.target.files[0];
const param = new FormData();
param.append('file', file);
const config = { headers: { 'Content-Type': 'multipart/form-data' } };
const res = await importWbs(currUrl.value, param, importParentId.value);
} catch (error) {
message.info(error || '导入失败');
}
}
//
const showDelCard = item => {
visible.value = true;
deleteId.value = item.id;
};
//
async function handleOk() {
visible.value = false;
await deleteProject(deleteId.value);
getProjectsList();
}
//
async function deleteProject(param) {
try {
await delProject(param);
} catch (error) {
message.info(error);
throw new Error(error);
}
}
//
async function exportProject(id) {
try {
const params = { param: { projectId: id } };
const { url } = store.state.projects.project;
const data = await exportWbs(params, url);
window.open(data.url, '_blank');
} catch (error) {
message.info(error);
throw new Error(error);
}
}
//
function clearRolesData() {
store.commit('role/setInvisibleRoles', []);
store.commit('role/setVisibleRoles', []);
store.commit('role/setRoleId', '');
}
//
function clearTasksData() {
//
store.commit('task/setPermanents', []);
store.commit('task/setDailyTasks', []);
//
store.commit('task/clearTasks');
//
store.commit('task/clearRealTasks');
store.commit('task/setUpNextPage', 1);
store.commit('task/setDownNextPage', 1);
}
//
function toWorkbench(item) {
toDetail(item);
store.commit('task/setTaskDetailShow', 'workbench'); //
}
function checkMove(e) {
moveProjectId.value = e.draggedContext.element.id;
moveBusinessCode.value = e.draggedContext.element.businessCode;
targetProjectId.value = '';
}
function onEnd(e) {
projects.value.forEach(item => {
if (item.sonProjectList) {
const index = item.sonProjectList.findIndex(sec => sec.id === moveProjectId.value);
if (index > -1) targetProjectId.value = item.id;
}
});
const params = {
moveProjectId: moveProjectId.value,
targetProjectId: targetProjectId.value,
businessCode: moveBusinessCode.value,
};
handleSort(params);
}
//
async function handleSort(param) {
try {
const params = { param };
await setProjectSort(params);
message.info('层级关系修改成功');
} catch (error) {
message.info(error.msg || '层级关系修改失败');
throw new Error(error);
}
getProjectsList();
}
</script>
<style scoped>
.list-flex {
height: calc(100vh - 48px - 272px - 56px - 16px - 2px);
overflow-y: auto;
}
.list-flex::-webkit-scrollbar {
width: 0 !important;
}
.ant-divider-horizontal {
height: 16px;
background: #eeeeee;
margin: 0;
}
.project-list {
padding: 16px 0;
}
.h-60 {
height: 60px;
}
.h-70 {
height: 70px;
}
.one-level {
padding: 0 16px;
}
.two-level {
padding: 0 16px 0 32px;
}
.three-level {
padding: 0 16px 0 48px;
}
.icon {
margin-right: 8px;
width: 24px;
height: 24px;
}
.detail {
width: calc(100% - 46px);
}
.name {
margin-right: 8px;
font-size: 14px;
line-height: 1;
font-weight: 600;
max-width: calc(100% - 56px);
color: #333333;
}
.precent-num {
width: 48px;
height: 18px;
line-height: 18px;
text-align: center;
border-radius: 18px;
background-color: rgba(24, 144, 255, 0.2);
color: #1890ff;
font-size: 12px;
}
.time {
font-size: 12px;
color: #999999;
}
.right {
width: 14px;
margin-left: 30px;
}
.dragArea {
min-height: 5px;
/* outline: 1px dashed; */
}
</style>

299
src/components/tall/left/Projects.vue

@ -1,85 +1,200 @@
<template>
<a-divider />
<div class="list-flex">
<div class="item-box" v-for="(item, index) in projects" :key="index">
<div class="one-level h-70 cursor-pointer flex items-center">
<!-- <div class="icon" @click.stop="showActionCard(item)"><img src="https://www.tall.wiki/staticrec/drag.svg" /></div> -->
<div class="flex-none">
<a-popover placement="bottomLeft">
<template #content>
<p class="cursor-pointer" @click="showImportCard(item)">导入</p>
<p class="cursor-pointer" @click="exportProject(item.id)">导出</p>
<p class="m-0 cursor-pointer" @click="showDelCard(item)">删除</p>
</template>
<div class="icon"><img src="https://www.tall.wiki/staticrec/drag.svg" /></div>
</a-popover>
</div>
<template v-for="(item, index) in projects">
<div class="item-box" v-if="item.businessCode === 'ZERO'" :key="index">
<div class="one-level h-70 cursor-pointer flex items-center">
<!-- <div class="icon" @click.stop="showActionCard(item)"><img src="https://www.tall.wiki/staticrec/drag.svg" /></div> -->
<div class="flex-none">
<a-popover placement="bottomLeft">
<template #content>
<p class="cursor-pointer" @click="showImportCard(item)">导入</p>
<p class="m-0 cursor-pointer" @click="exportProject(item.id)">导出</p>
<!-- <p class="m-0 cursor-pointer" @click="showDelCard(item)">删除</p> -->
</template>
<div class="icon"><img src="https://www.tall.wiki/staticrec/drag.svg" /></div>
</a-popover>
</div>
<div class="w-full flex items-center justify-between" @click="toDetail(item)">
<div class="detail">
<div class="name-box flex items-center" :class="{ 'mb-2': item.businessCode !== 'ZERO' }">
<div class="name truncate">{{ item.name }}</div>
<div class="precent-num">
{{ item.status === 1 ? '进行中' : item.status === 2 ? '已结束' : item.status === 0 ? '未开始' : '暂停' }}
</div>
</div>
<div class="w-full flex items-center justify-between" @click="toDetail(item)">
<div class="detail">
<div class="name-box flex items-center" :class="{ 'mb-2': item.businessCode !== 'ZERO' }">
<div class="name truncate">{{ item.name }}</div>
<div class="precent-num">
{{ item.status === 1 ? '进行中' : item.status === 2 ? '已结束' : item.status === 0 ? '未开始' : '暂停' }}
<div class="time" v-if="item.businessCode !== 'ZERO'">
{{ dayjs(Number(item.startTime)).format('MM-DD HH:mm') }}
{{ dayjs(Number(item.endTime)).format('MM-DD HH:mm') }}
</div>
</div>
<div class="time" v-if="item.businessCode !== 'ZERO'">
{{ dayjs(Number(item.startTime)).format('MM-DD HH:mm') }}
{{ dayjs(Number(item.endTime)).format('MM-DD HH:mm') }}
<div class="right flex justify-end items-center" @click.stop="openMenu">
<a-button v-if="item.businessCode === 'ZERO'" class="mr-2" shape="round" type="primary" @click="toWorkbench(item)">
工作台
</a-button>
<RightOutlined v-if="!item.show" @click="changeShow(item)" />
<DownOutlined v-else @click="changeShow(item)" />
</div>
</div>
</div>
<div class="right flex justify-end items-center" @click.stop="openMenu">
<a-button v-if="item.businessCode === 'ZERO'" class="mr-2" shape="round" type="primary" @click="toWorkbench(item)">
工作台
</a-button>
<div class="two-box" v-if="item.show">
<div class="two-flex" v-for="(sonItem, sonIndex) in item.sonProjectList" :key="sonIndex">
<div class="two-level h-70 cursor-pointer flex items-center">
<!-- <div class="icon" @click.stop="showActionCard(sonItem)"><img src="https://www.tall.wiki/staticrec/drag.svg" /></div> -->
<div class="flex-none">
<a-popover placement="bottomLeft">
<template #content>
<!-- <p class="cursor-pointer" @click="showImportCard(sonItem)">导入</p> -->
<p class="cursor-pointer" @click="exportProject(sonItem.id)">导出</p>
<p class="m-0 cursor-pointer" @click="showDelCard(sonItem)">删除</p>
</template>
<div class="icon"><img src="https://www.tall.wiki/staticrec/drag.svg" /></div>
</a-popover>
</div>
<RightOutlined v-if="!item.show" @click="changeShow(item)" />
<DownOutlined v-else @click="changeShow(item)" />
<div class="flex items-center justify-between" style="width: calc(100% - 32px)" @click="toDetail(sonItem)">
<div class="detail">
<div class="name-box mb-2 flex items-center">
<div class="name truncate">{{ sonItem.name }}</div>
<div class="precent-num">
{{ item.status === 1 ? '进行中' : item.status === 2 ? '已结束' : item.status === 0 ? '未开始' : '暂停' }}
</div>
</div>
<div class="time">
{{ dayjs(Number(sonItem.startTime)).format('MM-DD HH:mm') }}
{{ dayjs(Number(sonItem.endTime)).format('MM-DD HH:mm') }}
</div>
</div>
<div class="right" @click.stop="openMenu">
<RightOutlined v-if="!sonItem.show" @click="changeShow(sonItem)" />
<DownOutlined v-else @click="changeShow(sonItem)" />
</div>
</div>
</div>
</div>
</div>
</div>
<div class="two-box" v-if="item.show">
<div class="two-flex" v-for="(sonItem, sonIndex) in item.sonProjectList" :key="sonIndex">
<div class="two-level h-70 cursor-pointer flex items-center">
<!-- <div class="icon" @click.stop="showActionCard(sonItem)"><img src="https://www.tall.wiki/staticrec/drag.svg" /></div> -->
</template>
<draggable
class="dragArea p-0 list-none"
tag="ul"
:list="projects"
:group="{ name: 'g1' }"
item-key="name"
:move="checkMove"
@end="onEnd"
>
<template #item="{ element }">
<li class="item-box" v-if="element.businessCode !== 'ZERO'">
<!-- <p>{{ element.name }}</p> -->
<div
class="one-level cursor-pointer h-60 flex items-center"
:class="{ 'h-70': element.sonProjectList && element.sonProjectList.length > 0 }"
:style="{ 'padding-top': element.sonProjectList && element.sonProjectList.length > 0 ? 0 : '5px' }"
>
<!-- <div class="icon" @click.stop="showActionCard(item)"><img src="https://www.tall.wiki/staticrec/drag.svg" /></div> -->
<div class="flex-none">
<a-popover placement="bottomLeft">
<template #content>
<p class="cursor-pointer" @click="showImportCard(sonItem)">导入</p>
<p class="cursor-pointer" @click="exportProject(sonItem.id)">导出</p>
<p class="m-0 cursor-pointer" @click="showDelCard(sonItem)">删除</p>
<p class="cursor-pointer" @click="showImportCard(element)">导入</p>
<p class="cursor-pointer" @click="exportProject(element.id)">导出</p>
<p class="m-0 cursor-pointer" @click="showDelCard(element)">删除</p>
</template>
<div class="icon"><img src="https://www.tall.wiki/staticrec/drag.svg" /></div>
</a-popover>
</div>
<div class="flex items-center justify-between" style="width: calc(100% - 32px)" @click="toDetail(sonItem)">
<div class="w-full flex items-center justify-between" @click="toDetail(element)">
<div class="detail">
<div class="name-box mb-2 flex items-center">
<div class="name truncate">{{ sonItem.name }}</div>
<div class="name-box flex items-center" :class="{ 'mb-2': element.businessCode !== 'ZERO' }">
<div class="name truncate">{{ element.name }}</div>
<div class="precent-num">
{{ item.status === 1 ? '进行中' : item.status === 2 ? '已结束' : item.status === 0 ? '未开始' : '暂停' }}
{{ element.status === 1 ? '进行中' : element.status === 2 ? '已结束' : element.status === 0 ? '未开始' : '暂停' }}
</div>
</div>
<div class="time">
{{ dayjs(Number(sonItem.startTime)).format('MM-DD HH:mm') }} {{ dayjs(Number(sonItem.endTime)).format('MM-DD HH:mm') }}
<div class="time" v-if="element.businessCode !== 'ZERO'">
{{ dayjs(Number(element.startTime)).format('MM-DD HH:mm') }}
{{ dayjs(Number(element.endTime)).format('MM-DD HH:mm') }}
</div>
</div>
<div class="right" @click.stop="openMenu">
<RightOutlined v-if="!sonItem.show" @click="changeShow(sonItem)" />
<DownOutlined v-else @click="changeShow(sonItem)" />
<div class="right flex justify-end items-center" @click.stop="openMenu">
<a-button v-if="element.businessCode === 'ZERO'" class="mr-2" shape="round" type="primary" @click="toWorkbench(element)">
工作台
</a-button>
<RightOutlined v-if="!element.show" @click="changeShow(element)" />
<DownOutlined v-else @click="changeShow(element)" />
</div>
</div>
</div>
</div>
</div>
</div>
<draggable
class="dragArea p-0 list-none two-box"
tag="ul"
:list="element.sonProjectList"
:group="{ name: 'g1' }"
item-key="name"
:move="checkMove"
@end="onEnd"
>
<template #item="{ element }">
<li class="two-flex">
<!-- <p>{{ element.name }}</p> -->
<div class="two-level h-70 cursor-pointer flex items-center">
<!-- <div class="icon" @click.stop="showActionCard(sonItem)">
<img src="https://www.tall.wiki/staticrec/drag.svg" />
</div> -->
<div class="flex-none">
<a-popover placement="bottomLeft">
<template #content>
<!-- <p class="cursor-pointer" @click="showImportCard(sonItem)">导入</p> -->
<p class="cursor-pointer" @click="exportProject(element.id)">导出</p>
<p class="m-0 cursor-pointer" @click="showDelCard(element)">删除</p>
</template>
<div class="icon"><img src="https://www.tall.wiki/staticrec/drag.svg" /></div>
</a-popover>
</div>
<div class="flex items-center justify-between" style="width: calc(100% - 32px)" @click="toDetail(element)">
<div class="detail">
<div class="name-box mb-2 flex items-center">
<div class="name truncate">{{ element.name }}</div>
<div class="precent-num">
{{ element.status === 1 ? '进行中' : element.status === 2 ? '已结束' : element.status === 0 ? '未开始' : '暂停' }}
</div>
</div>
<div class="time">
{{ dayjs(Number(element.startTime)).format('MM-DD HH:mm') }}
{{ dayjs(Number(element.endTime)).format('MM-DD HH:mm') }}
</div>
</div>
<div class="right" @click.stop="openMenu">
<RightOutlined v-if="!element.show" @click="changeShow(element)" />
<DownOutlined v-else @click="changeShow(element)" />
</div>
</div>
</div>
</li>
</template>
</draggable>
</li>
</template>
</draggable>
<input class="import-wbs hidden" type="file" @change="toImport" />
<a-modal v-model:visible="importVisible" title="导入" @ok="handleImport">
@ -89,13 +204,11 @@
<a-modal v-model:visible="visible" title="删除" @ok="handleOk">
<p>确定要删除吗</p>
</a-modal>
<nested v-if="projects.length > 0" :lists="projects" @changeData="handleChangeData"></nested>
</div>
</template>
<script setup>
import { ref, watch, computed } from 'vue';
import { ref, reactive, watch, computed } from 'vue';
import { useStore } from 'vuex';
import { useRouter } from 'vue-router';
import dayjs from 'dayjs';
@ -103,7 +216,6 @@ import { getProjects, delProject, setProjectSort, exportWbs, importWbs } from 'a
import { RightOutlined, DownOutlined } from '@ant-design/icons-vue';
import { message } from 'ant-design-vue';
import draggable from 'vuedraggable';
import nested from 'components/tall/Center/nested.vue';
const store = useStore();
const router = useRouter();
@ -120,6 +232,10 @@ const startTime = computed(() => store.state.layout.startTime); // 当前选择
const endTime = computed(() => store.state.layout.endTime); //
const refreshProjects = computed(() => store.state.layout.refreshProjects); //
const moveProjectId = ref(''); // id
const moveBusinessCode = ref(''); //
const targetProjectId = ref(''); // id
if (sessionProject && !projectInfo.value.id) {
// storestorestore
const info = JSON.parse(sessionProject);
@ -175,6 +291,7 @@ function changeShow(item) {
item.show = !item.show;
}
//
const showImportCard = item => {
importVisible.value = true;
importParent.value = item.name;
@ -201,7 +318,7 @@ async function toImport(e) {
param.append('file', file);
const config = { headers: { 'Content-Type': 'multipart/form-data' } };
const res = await importWbs(currUrl.value, param, config, importParentId.value);
const res = await importWbs(currUrl.value, param, importParentId.value);
} catch (error) {
message.info(error || '导入失败');
}
@ -270,60 +387,27 @@ function toWorkbench(item) {
store.commit('task/setTaskDetailShow', 'workbench'); //
}
//
//
//
// function checkMove(e) {
// console.log('', e, projects.value);
// moveProjectId.value = e.draggedContext.element.id;
// moveBusinessCode.value = e.draggedContext.element.businessCode;
// }
//
// function onEnd() {
// console.log('onEnd', projects.value);
// targetProjectId.value = '';
// projects.value.forEach(item => {
// if (item.sonProjectList) {
// item.sonProjectList.forEach(pro => {
// if (pro.id === moveProjectId.value) {
// targetProjectId.value = item.id;
// }
// });
// }
// });
// const param = {
// moveProjectId: moveProjectId.value,
// targetProjectId: targetProjectId.value,
// businessCode: moveBusinessCode.value,
// };
// handleSort(param);
// }
//
function handleChangeData(data) {
console.log('子组件传参', projects.value);
let targetProjectId = '';
function checkMove(e) {
moveProjectId.value = e.draggedContext.element.id;
moveBusinessCode.value = e.draggedContext.element.businessCode;
targetProjectId.value = '';
}
function onEnd(e) {
projects.value.forEach(item => {
if (item.sonProjectList) {
item.sonProjectList.forEach(pro => {
if (pro.id === data.moveProjectId) {
targetProjectId = item.id;
}
});
const index = item.sonProjectList.findIndex(sec => sec.id === moveProjectId.value);
if (index > -1) targetProjectId.value = item.id;
}
});
const param = {
moveProjectId: data.moveProjectId,
targetProjectId,
businessCode: data.businessCode,
const params = {
moveProjectId: moveProjectId.value,
targetProjectId: targetProjectId.value,
businessCode: moveBusinessCode.value,
};
console.log('param', param);
handleSort(param);
handleSort(params);
}
//
@ -360,6 +444,10 @@ async function handleSort(param) {
padding: 16px 0;
}
.h-60 {
height: 60px;
}
.h-70 {
height: 70px;
}
@ -376,7 +464,7 @@ async function handleSort(param) {
padding: 0 16px 0 48px;
}
.item-box .icon {
.icon {
margin-right: 8px;
width: 24px;
height: 24px;
@ -415,4 +503,9 @@ async function handleSort(param) {
width: 14px;
margin-left: 30px;
}
.dragArea {
min-height: 5px;
/* outline: 1px dashed; */
}
</style>

Loading…
Cancel
Save