czh-20260701-优化未收藏的计划的显示

This commit is contained in:
zhihao
2026-07-01 10:44:33 +08:00
parent b8d7e31de8
commit 20bf8acf5a
4 changed files with 1123 additions and 16 deletions
File diff suppressed because it is too large Load Diff
+10 -1
View File
@@ -274,7 +274,7 @@
<div class="list-group-col list-group-col-secret">密级</div>
<div class="list-group-col list-group-col-time">创建时间</div>
</div>
<div v-for="list in allTaskLists" :key="list.id" class="list-group-row" @click="emit('list-select', list.id)">
<div v-for="list in allTaskLists" :key="list.id" class="list-group-row" @click="onListRowClick(list)">
<div class="list-group-col list-group-col-name">
<Icon icon="ant-design:file-text-outlined" class="list-icon" size="16" />
<span class="list-name-text">{{ list.name }}</span>
@@ -915,6 +915,7 @@
'create-list': [];
'load-more': [];
'search-keyword': [keyword: string];
'preview-list': [list: TaskList];
}>();
const userStore = useUserStore();
@@ -1255,6 +1256,14 @@
}
}
function onListRowClick(list: TaskList) {
if (isFavorited(list.id)) {
emit('list-select', list.id);
} else {
emit('preview-list', list);
}
}
const _isOwner = computed(() => props.currentList?.myPermission === '1');
const canEdit = computed(() => props.currentList?.myPermission === '1' || props.currentList?.myPermission === '2');
const isReadOnly = computed(() => props.currentList?.myPermission === '3');
@@ -205,7 +205,7 @@
<Icon icon="tasklist-desc|svg" />
</span>
<div class="detail-row-content">
<a-textarea v-if="showDescEditor && !isFullReadOnly" v-model:value="taskData.taskDesc" :rows="3" placeholder="添加描述..." autofocus @blur="onDescBlur" />
<a-textarea ref="descTextareaRef" v-if="showDescEditor && !isFullReadOnly" v-model:value="taskData.taskDesc" :rows="3" placeholder="添加描述..." @blur="onDescBlur" />
<span v-else class="desc-trigger" :class="{ 'readonly-field': isFullReadOnly }" @click="!isFullReadOnly && (showDescEditor = true)">
{{ taskData.taskDesc || '添加描述' }}
</span>
@@ -218,11 +218,11 @@
</span>
<div class="detail-row-content">
<a-textarea
ref="remarkTextareaRef"
v-if="showRemarkEditor && !isFullReadOnly"
v-model:value="taskData.remark"
:rows="3"
placeholder="添加其他事项说明..."
autofocus
@blur="onRemarkBlur"
/>
<span v-else class="desc-trigger" :class="{ 'readonly-field': isFullReadOnly }" @click="!isFullReadOnly && (showRemarkEditor = true)">
@@ -309,10 +309,10 @@
<span class="feishu-subtask-drag-placeholder"></span>
<span class="feishu-subtask-check feishu-subtask-check-empty"></span>
<a-input
ref="subTaskInputRef"
v-model:value="newSubTaskName"
size="small"
placeholder="输入子事项标题按回车确认..."
autofocus
class="feishu-subtask-input"
@press-enter="handleSubmitSubTask"
@blur="showNewSubTaskInput = false"
@@ -330,16 +330,10 @@
<span class="detail-row-icon">
<Icon icon="tasklist-followers|svg" />
</span>
<div v-if="!isFullReadOnly" class="follower-clickable" @click="openDrawerUserSelect('followers')">
<div class="follower-clickable" @click="isFullReadOnly ? toggleFollow() : openDrawerUserSelect('followers')">
<span class="follower-label">添加关注人</span>
<AvatarDisplay v-if="followers.length > 0" :names="taskData.followersName" :size="24" :show-name="false" />
<AvatarDisplay v-if="followers.length > 0" :names="taskData.followersName" :size="24" :show-name="followers.length === 1" />
</div>
<template v-else>
<span v-if="followers.length === 0" class="follower-empty">无关注人</span>
<a-tooltip v-else :title="taskData.followersName" placement="top">
<AvatarDisplay :names="taskData.followersName" :size="24" :show-name="false" />
</a-tooltip>
</template>
</div>
</template>
@@ -408,11 +402,14 @@
const isFullReadOnly = computed(() => isReadOnly.value && !isAssigneeEdit.value);
const showNewSubTaskInput = ref(false);
const newSubTaskName = ref('');
const subTaskInputRef = ref();
const startTimeDayjs = ref<string | null>(null);
const endTimeDayjs = ref<string | null>(null);
const editingTitle = ref(false);
const showDescEditor = ref(false);
const showRemarkEditor = ref(false);
const descTextareaRef = ref();
const remarkTextareaRef = ref();
const subtaskExpanded = ref(true);
const subTaskUserSelectId = ref<string>('');
@@ -526,6 +523,27 @@
endTimeDayjs.value = data?.task?.endTime || null;
});
watch(showNewSubTaskInput, async (val) => {
if (val) {
await nextTick();
subTaskInputRef.value?.focus();
}
});
watch(showDescEditor, async (val) => {
if (val) {
await nextTick();
descTextareaRef.value?.focus();
}
});
watch(showRemarkEditor, async (val) => {
if (val) {
await nextTick();
remarkTextareaRef.value?.focus();
}
});
function autoSave() {
if (taskData.value) {
const updated = {
@@ -589,7 +607,7 @@
}
taskData.value.followersId = idList.join(',');
taskData.value.followersName = nameList.join(',');
autoSave();
emit('unfollow-task', taskData.value.id);
} else {
const idList = (taskData.value.followersId || '').split(',').filter(Boolean);
const nameList = (taskData.value.followersName || '').split(/[,,、]/).map((s) => s.trim()).filter(Boolean);
@@ -599,7 +617,7 @@
}
taskData.value.followersId = idList.join(',');
taskData.value.followersName = nameList.join(',');
autoSave();
emit('follow-task', taskData.value.id);
}
}
+44 -2
View File
@@ -59,6 +59,7 @@
@create-list="onCreateListModal('')"
@load-more="onLoadMoreListViews"
@search-keyword="onSearchKeywordChange"
@preview-list="onPreviewList"
/>
<TaskFlatView
v-else
@@ -103,6 +104,19 @@
@move-task="onMoveTask"
/>
<CollaboratorModal ref="collaboratorModalRef" :task-list-id="collaboratorTargetListId || currentListId" :secret-level="collaboratorTargetList ? collaboratorTargetList.secretLevel || 1 : currentList?.secretLevel || 1" @changed="onCollaboratorsChanged" />
<PlanPreviewModal
:visible="previewModalVisible"
:list-id="previewListId"
:list-name="previewListName"
:secret-level="previewSecretLevel"
:secret-text="previewSecretText"
:collaborator-names="previewCollaboratorNames"
:is-favorited="previewIsFavorited"
@update:visible="(v) => (previewModalVisible = v)"
@add-to-favorites="onAddToFavorites"
@remove-from-favorites="onRemoveFavorite"
@task-click="onPreviewTaskClick"
/>
</div>
</template>
@@ -119,6 +133,7 @@
import CreateListModal from './components/CreateListModal.vue';
import TaskDetailDrawer from './components/TaskDetailDrawer.vue';
import CollaboratorModal from './components/CollaboratorModal.vue';
import PlanPreviewModal from './components/PlanPreviewModal.vue';
import {
getMyFavorites,
addTaskListGroup,
@@ -198,6 +213,14 @@
const collaboratorTargetListId = ref('');
const defaultGroupRealIdMap = ref<Record<string, string>>({});
const previewModalVisible = ref(false);
const previewListId = ref('');
const previewListName = ref('');
const previewSecretLevel = ref(1);
const previewSecretText = ref('非密');
const previewCollaboratorNames = ref('');
const previewIsFavorited = computed(() => favoriteIdMap.value.has(previewListId.value));
const userStore = useUserStore();
const currentUserSecurityLevel = ref<number>(3);
@@ -531,6 +554,21 @@
}
}
function onPreviewList(list: TaskList) {
previewListId.value = list.id;
previewListName.value = list.name;
previewSecretLevel.value = (list as any).secretLevel || 1;
previewSecretText.value = (list as any).secretText || '非密';
previewCollaboratorNames.value = list.collaboratorNames || '';
previewModalVisible.value = true;
}
function onPreviewTaskClick(task: TaskItem, allPreviewTasks: TaskItem[]) {
currentDrawerTaskId.value = task.id;
const readOnly = false;
openDetailDrawer(true, { task, allTasks: allPreviewTasks, readOnly, secretLevel: previewSecretLevel.value || 1 });
}
function onOpenCollaborator() {
collaboratorTargetListId.value = '';
collaboratorModalRef.value?.open(currentListId.value);
@@ -600,6 +638,11 @@
try {
await addToFavorites({ taskListId, pid: pid || undefined });
await loadFavorites();
if (previewModalVisible.value) {
previewModalVisible.value = false;
onListSelect(taskListId);
}
message.success('已添加收藏');
} catch (e) {
console.error('[TaskList] 添加收藏失败', e);
}
@@ -1386,8 +1429,7 @@
await deleteTaskListApi({ id: listId });
}
if (currentListId.value === listId) {
const firstAvailable = findFirstAvailableList();
currentListId.value = firstAvailable?.id || '';
onQuickAccessTabClick('all');
}
await loadFavorites();
} catch (e) {