From ef7293704bd81bbb677aac4efd7615c4e00d0d1a Mon Sep 17 00:00:00 2001 From: kuaifan Date: Thu, 21 May 2026 06:06:39 +0000 Subject: [PATCH] =?UTF-8?q?refactor(manage):=20=E6=94=B6=E5=8F=A3=E9=83=A8?= =?UTF-8?q?=E9=97=A8=E8=B4=9F=E8=B4=A3=E4=BA=BAID=E8=A7=84=E8=8C=83?= =?UTF-8?q?=E5=8C=96=E9=80=BB=E8=BE=91=E5=B9=B6=E7=AE=80=E5=8C=96=E5=90=8E?= =?UTF-8?q?=E7=AB=AF=E5=AF=B9=E8=AF=9D=E5=8F=AF=E8=A7=81=E6=80=A7=E6=A0=A1?= =?UTF-8?q?=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 后端:任务群/项目群统一按项目级共享判断,不再区分任务可见性 - 前端:新增 department/owner/ids/save mutation 及 normalizeIntArray 工具函数 - 前端:departmentOwnerReadonlyUrls 从 action 局部变量提升至 state - 前端:修复 TaskDetail 提示文本多余空格 Co-Authored-By: Claude Opus 4.7 (1M context) --- app/Models/WebSocketDialog.php | 9 ++-- resources/assets/js/functions/common.js | 14 ++++++ resources/assets/js/pages/manage.vue | 2 +- .../manage/components/DepartmentOwnerView.vue | 2 +- .../pages/manage/components/ProjectList.vue | 2 +- .../js/pages/manage/components/TaskDetail.vue | 2 +- resources/assets/js/store/actions.js | 49 ++++++------------- resources/assets/js/store/mutations.js | 6 +++ resources/assets/js/store/state.js | 16 ++++++ 9 files changed, 59 insertions(+), 43 deletions(-) diff --git a/app/Models/WebSocketDialog.php b/app/Models/WebSocketDialog.php index 554fd68e4..65714c733 100644 --- a/app/Models/WebSocketDialog.php +++ b/app/Models/WebSocketDialog.php @@ -904,19 +904,16 @@ class WebSocketDialog extends AbstractModel case 'project': case 'task': // 项目群、任务群对话校验是否在项目内 - $taskVisibility = 1; // 项目群不涉及任务可见性,按可见处理 if ($dialog->group_type === 'project') { $projectId = intval(Project::whereDialogId($dialog->id)->value('id')); } else { - $taskRow = ProjectTask::select(['project_id', 'visibility'])->whereDialogId($dialog->id)->first(); - $projectId = intval($taskRow?->project_id); - $taskVisibility = intval($taskRow?->visibility); + $projectId = intval(ProjectTask::whereDialogId($dialog->id)->value('project_id')); } if ($projectId > 0 && ProjectUser::whereProjectId($projectId)->whereUserid($userid)->exists()) { return $dialog; } - // 部门负责人只读视角:项目群放行;任务群仅"全员可见"任务放行,指定成员可见任务不放行 - if ($projectId > 0 && $checkOwner === false && ($dialog->group_type === 'project' || $taskVisibility === 1)) { + // 部门负责人只读视角:项目/任务群按项目级共享放行(任务数据另按可见性校验,与普通成员一致) + if ($projectId > 0 && $checkOwner === false) { $departmentView = UserDepartment::ownerViewContext(User::auth(), true); if (UserDepartment::isDepartmentReadonlyProject($departmentView, $projectId)) { return $dialog; diff --git a/resources/assets/js/functions/common.js b/resources/assets/js/functions/common.js index 134f789c9..64d4f8b1c 100755 --- a/resources/assets/js/functions/common.js +++ b/resources/assets/js/functions/common.js @@ -26,6 +26,20 @@ const timezone = require("dayjs/plugin/timezone"); return typeof (obj) == "object" && Object.prototype.toString.call(obj).toLowerCase() == '[object array]' && typeof obj.length == "number"; }, + /** + * 规范化为整型数组 + * @param data + * @returns {number[]} + */ + normalizeIntArray(data) { + if (!this.isArray(data)) { + return []; + } + return [...new Set(data + .map(id => parseInt(id)) + .filter(id => id > 0))] + }, + /** * 是否数组对象 * @param obj diff --git a/resources/assets/js/pages/manage.vue b/resources/assets/js/pages/manage.vue index 924706123..e8d3df97b 100644 --- a/resources/assets/js/pages/manage.vue +++ b/resources/assets/js/pages/manage.vue @@ -678,7 +678,7 @@ export default { }, cacheDepartmentOwnerIds() { - return (this.$store.state.cacheDepartmentOwnerIds || []).map(id => parseInt(id)); + return this.$store.state.cacheDepartmentOwnerIds || []; }, /** diff --git a/resources/assets/js/pages/manage/components/DepartmentOwnerView.vue b/resources/assets/js/pages/manage/components/DepartmentOwnerView.vue index fa553eef0..f4453871a 100644 --- a/resources/assets/js/pages/manage/components/DepartmentOwnerView.vue +++ b/resources/assets/js/pages/manage/components/DepartmentOwnerView.vue @@ -63,7 +63,7 @@ export default { immediate: true, handler(show) { if (show) { - this.draftIds = (this.cacheDepartmentOwnerIds || []).map(id => parseInt(id)); + this.draftIds = (this.cacheDepartmentOwnerIds || []).slice(); } else { this.applyLoading = false; } diff --git a/resources/assets/js/pages/manage/components/ProjectList.vue b/resources/assets/js/pages/manage/components/ProjectList.vue index d8b5e9e1b..2a0459258 100644 --- a/resources/assets/js/pages/manage/components/ProjectList.vue +++ b/resources/assets/js/pages/manage/components/ProjectList.vue @@ -169,7 +169,7 @@ export default { }, ownerDepartmentIds() { - return (this.cacheDepartmentOwnerIds || []).map(id => parseInt(id)); + return this.cacheDepartmentOwnerIds || []; }, projectBaseLists() { diff --git a/resources/assets/js/pages/manage/components/TaskDetail.vue b/resources/assets/js/pages/manage/components/TaskDetail.vue index d840d7f3d..c2504310e 100755 --- a/resources/assets/js/pages/manage/components/TaskDetail.vue +++ b/resources/assets/js/pages/manage/components/TaskDetail.vue @@ -113,7 +113,7 @@ - {{$L('当前为负责人 ,并参与讨论,但不能编辑任务。')}} + {{$L('当前为负责人,并参与讨论,但不能编辑任务。')}} {{$L('该任务尚未被领取,点击这里')}} diff --git a/resources/assets/js/store/actions.js b/resources/assets/js/store/actions.js index acd313414..9eac59b08 100644 --- a/resources/assets/js/store/actions.js +++ b/resources/assets/js/store/actions.js @@ -232,25 +232,9 @@ export default { ], true)) { params.encrypt = true } - const departmentOwnerReadonlyUrls = [ - 'project/lists', - 'project/one', - 'project/column/lists', - 'project/task/lists', - 'project/task/one', - 'project/task/content', - 'project/task/content_history', - 'project/task/files', - 'project/task/fileinfo', - 'project/task/subdata', - 'project/task/related', - 'project/flow/list', - 'project/log/lists', - 'project/tag/list', - ] if (params.departmentOwner !== false && state.systemConfig.department_owner_project_view === 'open' - && departmentOwnerReadonlyUrls.includes(params.url) + && state.departmentOwnerReadonlyUrls.includes(params.url) && (state.cacheDepartmentOwnerIds || []).length > 0) { if (!$A.isJson(params.data)) params.data = {} if (params.data.department_owner_ids === undefined) { @@ -1193,7 +1177,7 @@ export default { * @param dispatch * @returns {Promise} */ - handleReadCache({state}) { + handleReadCache({state, commit}) { return new Promise(async resolve => { // 定义需要获取的数据映射 const dataMap = { @@ -1238,7 +1222,11 @@ export default { // 更新 state [...dataMap.string, ...dataMap.array, ...dataMap.json].forEach((key, index) => { - state[key] = data[index]; + if (key === 'cacheDepartmentOwnerIds') { + commit('department/owner/ids/save', data[index]); + } else { + state[key] = data[index]; + } }); // 特殊处理 cacheDialogs @@ -1597,11 +1585,10 @@ export default { * @param dispatch * @returns {Promise} */ - async getProjectsForDepartmentOwnerView({state, dispatch}) { + async getProjectsForDepartmentOwnerView({state, dispatch, commit}) { await dispatch("systemSetting").catch(() => {}); if (state.systemConfig.department_owner_project_view !== 'open') { - state.cacheDepartmentOwnerIds = []; - await $A.IDBSet("cacheDepartmentOwnerIds", []).catch(() => {}); + commit('department/owner/ids/save', []); dispatch("getProjectByQueue"); return; } @@ -1611,8 +1598,7 @@ export default { __replace: true, department_owner_ids: restoredDepartmentOwnerIds.join(',') }); - state.cacheDepartmentOwnerIds = restoredDepartmentOwnerIds; - await $A.IDBSet("cacheDepartmentOwnerIds", restoredDepartmentOwnerIds).catch(() => {}); + commit('department/owner/ids/save', restoredDepartmentOwnerIds); return; } dispatch("getProjectByQueue"); @@ -1624,13 +1610,12 @@ export default { * @param dispatch * @returns {Promise} */ - async restoreDepartmentOwnerView({state, dispatch}) { + async restoreDepartmentOwnerView({state, dispatch, commit}) { if (state.departmentOwnerViewRestored) { return []; } if (state.systemConfig.department_owner_project_view !== 'open') { - state.cacheDepartmentOwnerIds = []; - await $A.IDBSet("cacheDepartmentOwnerIds", []).catch(() => {}); + commit('department/owner/ids/save', []); return []; } state.departmentOwnerViewRestored = true; @@ -1642,8 +1627,7 @@ export default { if (restored.length > 0) { state.departmentOwnerProjectsRefreshing = true; } - state.cacheDepartmentOwnerIds = restored; - await $A.IDBSet("cacheDepartmentOwnerIds", restored).catch(() => {}); + commit('department/owner/ids/save', restored); return restored; }, @@ -1654,20 +1638,19 @@ export default { * @param ids * @returns {Promise} */ - async setDepartmentOwnerIds({state, dispatch}, ids) { + async setDepartmentOwnerIds({state, dispatch, commit}, ids) { if (state.systemConfig.department_owner_project_view !== 'open') { ids = []; } const normalized = await dispatch("normalizeDepartmentOwnerIds", ids); - const oldValue = (state.cacheDepartmentOwnerIds || []).map(id => parseInt(id)).sort().join(','); + const oldValue = (state.cacheDepartmentOwnerIds || []).slice().sort().join(','); const newValue = normalized.slice().sort().join(','); if (oldValue === newValue) { return; } state.departmentOwnerProjectsRefreshing = true; await dispatch("refreshDepartmentOwnerProjects", normalized); - state.cacheDepartmentOwnerIds = normalized; - await $A.IDBSet("cacheDepartmentOwnerIds", normalized).catch(() => {}); + commit('department/owner/ids/save', normalized); }, /** diff --git a/resources/assets/js/store/mutations.js b/resources/assets/js/store/mutations.js index f04c149dc..78b55d97b 100644 --- a/resources/assets/js/store/mutations.js +++ b/resources/assets/js/store/mutations.js @@ -248,6 +248,12 @@ export default { $A.IDBSave("cacheProjectParameter", state.cacheProjectParameter); }, + // 部门负责人视角 + 'department/owner/ids/save': function(state, data) { + state.cacheDepartmentOwnerIds = $A.normalizeIntArray(data) + $A.IDBSet("cacheDepartmentOwnerIds", state.cacheDepartmentOwnerIds).catch(() => {}); + }, + // 文件管理 'file/push': function(state, data) { state.fileLists.push(data) diff --git a/resources/assets/js/store/state.js b/resources/assets/js/store/state.js index dc8a7fb06..a52d600c3 100644 --- a/resources/assets/js/store/state.js +++ b/resources/assets/js/store/state.js @@ -106,6 +106,22 @@ export default { cacheDepartmentOwnerIds: [], departmentOwnerViewRestored: false, departmentOwnerProjectsRefreshing: false, + departmentOwnerReadonlyUrls: [ + 'project/lists', + 'project/one', + 'project/column/lists', + 'project/task/lists', + 'project/task/one', + 'project/task/content', + 'project/task/content_history', + 'project/task/files', + 'project/task/fileinfo', + 'project/task/subdata', + 'project/task/related', + 'project/flow/list', + 'project/log/lists', + 'project/tag/list', + ], // Emoji cacheEmojis: [],