diff --git a/resources/assets/js/pages/manage/components/ProjectColumn.vue b/resources/assets/js/pages/manage/components/ProjectColumn.vue new file mode 100644 index 000000000..ddf32cd80 --- /dev/null +++ b/resources/assets/js/pages/manage/components/ProjectColumn.vue @@ -0,0 +1,260 @@ + + + diff --git a/resources/assets/js/pages/manage/components/ProjectPanel.vue b/resources/assets/js/pages/manage/components/ProjectPanel.vue index e7c0035fb..b7ff8cbb1 100644 --- a/resources/assets/js/pages/manage/components/ProjectPanel.vue +++ b/resources/assets/js/pages/manage/components/ProjectPanel.vue @@ -148,140 +148,20 @@ tag="ul" draggable=".column-item" @sort="sortUpdate(true)"> -
  • -
    -
    - - ({{panelTask(column.tasks).length}}) -
    -
    -
    - - - -
  • - -
  • - - - - - - -
    - -
    - -
    - -
    -
    - -
    -
    -
    - + :column="column" + :project-id="projectId" + :readonly="isDepartmentReadonly" + :drag-disabled="sortDisabled || isDepartmentReadonly || $isEEUIApp || windowTouch" + :loading="columnLoad[column.id] === true" + :top-show="!!columnTopShow[column.id]" + @on-command="dropColumn(column, $event)" + @on-top-show="addTopShow(column.id, $event)" + @on-priority="addTaskOpen" + @on-sort="sortUpdate"/>
  • {{$L('添加列表')}} @@ -691,8 +571,8 @@ import {debounce} from "lodash"; import Draggable from 'vuedraggable' import TaskPriority from "./TaskPriority"; import {mapGetters, mapState} from "vuex"; -import TaskAddSimple from "./TaskAddSimple"; import TaskRow from "./TaskRow"; +import ProjectColumn from "./ProjectColumn.vue"; import TaskArchived from "./TaskArchived"; import ProjectLog from "./ProjectLog"; import DrawerOverlay from "../../../components/DrawerOverlay"; @@ -700,9 +580,7 @@ import ProjectTaskTag from "./ProjectTaskTag"; import ProjectTaskTemplate from "./ProjectTaskTemplate"; import ProjectWorkflow from "./ProjectWorkflow"; import ProjectPermission from "./ProjectPermission"; -import TaskMenu from "./TaskMenu"; import TaskDeleted from "./TaskDeleted"; -import TaskTag from "./ProjectTaskTag/tags.vue"; import ProjectGantt from "./ProjectGantt"; import ProjectTableGroupDropdown from "./ProjectTableGroupDropdown.vue"; import ProjectFlowFilterDropdown from "./ProjectFlowFilterDropdown.vue"; @@ -713,6 +591,7 @@ import emitter from "../../../store/events"; import transformEmojiToHtml from "../../../utils/emoji"; import {projectTableGroups, normalizeProjectTableGroups, projectWeekRanges, taskMatchesProjectGroup} from "../../../utils/projectTableGroups"; import {scrollToStableTarget} from "../../../utils/scrollToStableTarget"; +import {updateTaskVisibilitys} from "../../../utils/taskVisibility"; import {emptyProjectFlowFilter, projectFlowFilterCount, taskMatchesProjectFlowFilter} from "../../../utils/projectFlowFilter"; export default { @@ -721,7 +600,6 @@ export default { VMPreviewNostyle, UserAvatarTip, UserSelect, - TaskMenu, ProjectTaskTag, ProjectTaskTemplate, ProjectWorkflow, @@ -730,11 +608,10 @@ export default { ProjectLog, TaskArchived, TaskRow, + ProjectColumn, Draggable, - TaskAddSimple, TaskPriority, TaskDeleted, - TaskTag, ProjectGantt, ProjectTableGroupDropdown, ProjectFlowFilterDropdown, @@ -743,8 +620,6 @@ export default { return { loading: false, - columnMenuIds: [], - nowTime: $A.dayjs().unix(), nowInterval: null, tableToday: $A.daytz().format('YYYY-MM-DD'), @@ -797,12 +672,16 @@ export default { flowFilterOpen: false, flowList: [], - columnVisibilitys: {}, - taskVisibilitys: {}, taskRowVisibilitys: {}, } }, + provide() { + return { + projectPanel: this, + } + }, + mounted() { this.nowInterval = setInterval(() => { this.nowTime = $A.dayjs().unix(); @@ -1517,12 +1396,6 @@ export default { }); }, - onColumnMenuVisible(columnId, visible) { - if (visible && !this.columnMenuIds.includes(columnId)) { - this.columnMenuIds.push(columnId) - } - }, - dropColumn(column, command) { if (this.isDepartmentReadonly) { return; @@ -1895,13 +1768,6 @@ export default { } }, - openMenu(event, task) { - const el = this.$refs[`taskMenu_${task.id}`]; - if (el) { - el[0].handleClick(event) - } - }, - taskIsHidden(task) { const {id, name, desc, complete_at} = task; const {searchText} = this; @@ -1921,12 +1787,6 @@ export default { return false; }, - ownerUser(list) { - return list.filter(({owner}) => owner == 1).sort((a, b) => { - return a.id - b.id; - }); - }, - inviteGet(refresh) { this.inviteLoad++; this.$store.dispatch("call", { @@ -2060,10 +1920,6 @@ export default { return !taskMatchesProjectFlowFilter(task, this.flowFilter); }, - expiresFormat(date) { - return $A.countDownFormat(this.nowTime, date) - }, - setTableGroupVisible(group, visible) { const selected = this.visibleTableGroups; if (!visible && selected.length === 1 && selected.includes(group.key)) return; @@ -2156,21 +2012,6 @@ export default { this.settingData = { ...this.settingData, archive_method: value }; }, - taskItemVisible({id, column_id}) { - return this.columnVisibilitys[column_id] && this.taskVisibilitys[id]?.visible - }, - - taskItemStyle({id, column_id, complete_at, color}) { - const style = {} - if (color) { - style.backgroundColor = color; - } - if (!this.taskItemVisible({id, column_id})) { - style.height = (this.taskVisibilitys[id]?.height || (complete_at ? 46 :146)) + 'px'; - } - return style; - }, - handleColumnDebounce(wait = 10, needView = false) { if (typeof wait === "boolean") { needView = wait @@ -2210,85 +2051,22 @@ export default { }, handleColumnScroll() { + const mainContainer = this.$refs.projectColumn; + if (!mainContainer) { + return + } + const mainRect = mainContainer.getBoundingClientRect(); this.columnList.forEach(({id}) => { const ref = this.$refs[`column_${id}`]; - ref && this.checkColumnVisibility(ref[0]) + ref && ref[0] && ref[0].checkVisibility(mainRect) }) }, - checkColumnVisibility(columnContainer = null) { - if (!columnContainer) { + handleTaskScroll({target}) { + if (this.tabTypeActive !== 'table') { return } - const dataId = columnContainer.getAttribute('data-id') - if (!dataId) { - return - } - const mainContainer = this.$refs.projectColumn; - if (!mainContainer) { - return false; - } - - // 获取容器的边界信息 - const mainRect = mainContainer.getBoundingClientRect(); - const columnRect = columnContainer.getBoundingClientRect(); - - // 检查元素是否在容器的可视区域内 - const visible = ( - columnRect.left < mainRect.right && - columnRect.right > mainRect.left && - columnRect.top < mainRect.bottom && - columnRect.bottom > mainRect.top - ) - if (visible) { - this.handleTaskScroll({target: columnContainer.querySelector('.task-scrollbar')}) - } - this.$set(this.columnVisibilitys, dataId, visible) - }, - - async handleTaskScroll({target}) { - if (!target) { - return - } - const targetItem = target.querySelectorAll('.task-item'); - if (!targetItem.length) { - return - } - let visibleType = null; - switch (this.tabTypeActive) { - case 'column': - visibleType = 'taskVisibilitys' - break; - case 'table': - visibleType = 'taskRowVisibilitys' - break; - default: - return - } - const targetRect = target.getBoundingClientRect(); - for (const item of targetItem) { - const dataId = item.getAttribute('data-id'); - if (!dataId) { - continue; - } - const taskRect = item.getBoundingClientRect(); - const originalVisible = this[visibleType][dataId]?.visible || false; - const currentVisible = ( - taskRect.top >= targetRect.top - taskRect.height && - taskRect.bottom <= targetRect.bottom + taskRect.height - ); - if (currentVisible === originalVisible) { - continue; - } - const firstVisible = this[visibleType][dataId] === undefined && currentVisible; - this.$set(this[visibleType], dataId, { - visible: currentVisible, - height: taskRect.height - }); - if (firstVisible) { - await this.$nextTick(); - } - } + return updateTaskVisibilitys(this, target, this.taskRowVisibilitys) }, /** diff --git a/resources/assets/js/utils/taskVisibility.js b/resources/assets/js/utils/taskVisibility.js new file mode 100644 index 000000000..adad31fa7 --- /dev/null +++ b/resources/assets/js/utils/taskVisibility.js @@ -0,0 +1,35 @@ +// 按滚动容器可视区(上下各多算一个任务高度)更新任务的可见状态,未可见的任务只渲染占位 +// 首次可见的任务逐个等待渲染,让后续任务按真实高度判断 +export async function updateTaskVisibilitys(vm, target, visibilitys) { + if (!target) { + return + } + const targetItem = target.querySelectorAll('.task-item'); + if (!targetItem.length) { + return + } + const targetRect = target.getBoundingClientRect(); + for (const item of targetItem) { + const dataId = item.getAttribute('data-id'); + if (!dataId) { + continue; + } + const taskRect = item.getBoundingClientRect(); + const originalVisible = visibilitys[dataId]?.visible || false; + const currentVisible = ( + taskRect.top >= targetRect.top - taskRect.height && + taskRect.bottom <= targetRect.bottom + taskRect.height + ); + if (currentVisible === originalVisible) { + continue; + } + const firstVisible = visibilitys[dataId] === undefined && currentVisible; + vm.$set(visibilitys, dataId, { + visible: currentVisible, + height: taskRect.height + }); + if (firstVisible) { + await vm.$nextTick(); + } + } +}