修改完成待测试

This commit is contained in:
2026-09-13 17:45:47 +08:00
parent 9ad572907b
commit bbc024f7f2
80 changed files with 3844 additions and 1672 deletions
+106 -20
View File
@@ -94,18 +94,46 @@
><AppButton block :label="`新建${recordName}`" @click="openCreate"
/></view>
<view v-else class="memo-list">
<BatchManagementBar
v-if="deletableMemos.length"
:resource-name="recordName"
:active="memoBatch.selectionMode.value"
:selected-count="memoBatch.selectedCount.value"
:all-selected="memoBatch.allSelected.value"
:busy="memoBatch.deleting.value"
@start="memoBatch.enterSelectionMode"
@finish="memoBatch.exitSelectionMode"
@toggle-all="memoBatch.toggleAll"
@delete="memoBatch.requestDelete"
/>
<text v-if="memoBatch.notice.value" class="save-notice" role="status">{{ memoBatch.notice.value }}</text>
<text v-if="memoBatch.error.value" class="delete-error" role="alert">{{ memoBatch.error.value }}</text>
<text v-if="saveNotice" class="save-notice"
>{{ recordName }}已保存</text
>
<text v-if="deleteError" class="delete-error">{{ deleteError }}</text>
<view v-for="item in memos" :key="item.id" class="memo-card" role="button" :aria-label="`查看${item.title}详情`" @click="openMemoDetail(item)">
<view class="memo-card__copy">
<text>{{ item.title }}</text>
<text v-if="item.remindTime">{{ item.remindTime }}</text>
<text v-if="item.createTime">创建于 {{ formatMinuteTimestamp(item.createTime) }}</text>
<text v-if="item.content" class="memo-card__content">{{ item.content }}</text>
<view v-for="item in memos" :key="item.id" class="memo-card" role="button" :aria-label="memoBatch.selectionMode.value && item.canDelete ? `${memoBatch.isSelected(item) ? '取消选择' : '选择'}${item.title}` : `查看${item.title}详情`" @click="handleMemoClick(item)">
<BatchSelectionMark
v-if="memoBatch.selectionMode.value && item.canDelete"
:selected="memoBatch.isSelected(item)"
:label="`${recordName}${item.title}`"
@toggle="memoBatch.toggleSelection(item)"
/>
<view class="memo-card__main">
<image
v-if="item.mediaFiles?.[0]?.accessUrl"
class="memo-card__cover"
:src="item.mediaFiles[0].accessUrl"
mode="aspectFill"
/>
<view class="memo-card__copy">
<text>{{ item.title }}</text>
<text v-if="item.remindTime">{{ item.remindTime }}</text>
<text v-if="item.createTime">创建于 {{ formatMinuteTimestamp(item.createTime) }}</text>
<text v-if="item.content" class="memo-card__content">{{ item.content }}</text>
</view>
</view>
<view v-if="item.canEdit || item.canDelete" class="memo-card__actions">
<view v-if="!memoBatch.selectionMode.value && (item.canEdit || item.canDelete)" class="memo-card__actions">
<AppButton
v-if="item.canEdit"
compact
@@ -124,6 +152,17 @@
</view>
</view>
</view>
<AppDialog
:visible="memoBatch.confirmationVisible.value"
:title="`将选中的${recordName}移入回收站?`"
:message="memoBatch.confirmationMessage.value"
:confirm-text="memoBatch.deleting.value ? '正在删除' : '移入回收站'"
cancel-text="继续选择"
show-cancel
:close-on-mask="false"
@confirm="memoBatch.confirmDelete"
@cancel="memoBatch.cancelDelete"
/>
<AppDialog
:visible="Boolean(detailTarget)"
:eyebrow="`${recordName}详情`"
@@ -178,8 +217,11 @@ import { onBackPress, onLoad, onShow, onUnload } from "@dcloudio/uni-app";
import AppButton from "@/components/AppButton.vue";
import AppDialog from "@/components/AppDialog.vue";
import AppLoading from "@/components/AppLoading.vue";
import BatchManagementBar from "@/components/BatchManagementBar.vue";
import BatchSelectionMark from "@/components/BatchSelectionMark.vue";
import ModulePageBackground from "@/components/ModulePageBackground.vue";
import PageHeader from "@/components/PageHeader.vue";
import { useBatchDeletion } from "@/composables/use-batch-deletion.js";
import {
createRequestController,
isRequestCancelled
@@ -233,6 +275,19 @@ const memoDetailRequestController = createRequestController();
const memoCreateGuard = createNonIdempotentWriteGuard();
let pageActive = true;
const valid = computed(() => /^[1-9]\d*$/.test(genealogyId.value));
const memoBatch = useBatchDeletion({
items: memos,
deleteOne: (memo) =>
lifeRecordApi.deleteMemo(genealogyId.value, memo.id, {
requestController: memoDeletionRequestController,
}),
resourceName: "记录",
isActive: () => pageActive,
onEmpty: () => {
listState.value = "empty";
},
});
const deletableMemos = memoBatch.deletableItems;
const isBenefactorMode = computed(() => memoType.value === MEMO_TYPE.BENEFACTOR);
const recordName = computed(() => isBenefactorMode.value ? "家族恩人" : "家族备忘");
const pageTitle = computed(() => recordName.value);
@@ -285,6 +340,7 @@ const loadMemos = async () => {
});
if (!pageActive) return;
memos.value = rows.filter((memo) => memo.memoType === memoType.value);
memoBatch.exitSelectionMode();
listState.value = memos.value.length ? "ready" : "empty";
if (pendingMemoId.value) {
const target = memos.value.find((item) => item.id === pendingMemoId.value);
@@ -372,6 +428,13 @@ const openMemoDetail = async (memo) => {
detailError.value = getRequestErrorMessage(cause, "完整备忘读取失败,请稍后重试。");
}
};
const handleMemoClick = (memo) => {
if (memoBatch.selectionMode.value && memo?.canDelete) {
memoBatch.toggleSelection(memo);
return;
}
openMemoDetail(memo);
};
const closeMemoDetail = () => {
if (detailState.value === "loading") return;
detailTarget.value = null;
@@ -503,19 +566,30 @@ const deleteMemo = async () => {
if (pageActive) deleting.value = false;
}
};
const requestBack = () =>
detailTarget.value
? (closeMemoDetail(), true)
: view.value !== "form"
? goBack()
: runBackGuard({
transientOpen: discardVisible.value,
dirty: dirty.value,
submitting: submitting.value || uploading.value,
"close-transient": cancelDiscard,
"block-submitting": () => true,
"confirm-discard": confirmation.request,
});
const requestBack = () => {
if (memoBatch.deleting.value) return true;
if (memoBatch.confirmationVisible.value) {
memoBatch.cancelDelete();
return true;
}
if (memoBatch.selectionMode.value) {
memoBatch.exitSelectionMode();
return true;
}
if (detailTarget.value) {
closeMemoDetail();
return true;
}
if (view.value !== "form") return goBack();
return runBackGuard({
transientOpen: discardVisible.value,
dirty: dirty.value,
submitting: submitting.value || uploading.value,
"close-transient": cancelDiscard,
"block-submitting": () => true,
"confirm-discard": confirmation.request,
});
};
onLoad((query) => {
genealogyId.value = String(query?.genealogyId || "");
@@ -708,10 +782,22 @@ onUnload(() => {
min-height: 128rpx;
padding: 28rpx 32rpx;
}
.memo-card__main {
display: flex;
align-items: flex-start;
gap: 18rpx;
}
.memo-card__copy {
min-width: 0;
flex: 1;
}
.memo-card__cover {
width: 148rpx;
height: 148rpx;
flex: 0 0 148rpx;
border-radius: 8rpx;
background: rgba(128, 89, 49, .12);
}
.memo-card__actions {
display: flex;
width: 100%;