feat: 完成前端业务闭环与后端联调

This commit is contained in:
2026-08-24 23:37:56 +08:00
parent c59e36f933
commit 9ad572907b
175 changed files with 10711 additions and 1740 deletions
+46 -10
View File
@@ -67,12 +67,25 @@
</view>
</view>
</view>
<AppDialog
:visible="discardVisible"
eyebrow="未保存修改"
title="放弃排行修改?"
message="当前排序值还没有保存。"
confirm-text="确认放弃"
cancel-text="继续编辑"
show-cancel
:close-on-mask="false"
@confirm="confirmDiscard"
@cancel="cancelDiscard"
/>
</view>
</template>
<script setup>
import { ref } from "vue";
import { computed, ref } from "vue";
import { onBackPress, onLoad, onUnload } from "@dcloudio/uni-app";
import AppDialog from "@/components/AppDialog.vue";
import AppLoading from "@/components/AppLoading.vue";
import ModulePageBackground from "@/components/ModulePageBackground.vue";
import PageHeader from "@/components/PageHeader.vue";
@@ -82,7 +95,8 @@ import {
} from "@/services/api/request-controller.js";
import { lineageApi } from "@/services/api/lineage-service.js";
import { getRequestErrorMessage } from "@/services/api/request-error-message.js";
import { goBack, handleBackPress, returnTo } from "@/utils/navigation/gateway.js";
import { createDiscardConfirmation } from "@/utils/discard-confirmation.js";
import { goBack, handleBackPress, returnTo, runBackGuard } from "@/utils/navigation/gateway.js";
const rankState = ref("loading");
const genealogyId = ref("");
@@ -93,10 +107,21 @@ const sortOrder = ref("");
const savingRank = ref(false);
const rankError = ref("");
const committedSortOrder = ref("");
const sortOrderBaseline = ref("");
const discardVisible = ref(false);
const memberRankReadRequestController = createRequestController();
const memberRankSaveRequestController = createRequestController();
let pageActive = true;
let loadSequence = 0;
const discardConfirmation = createDiscardConfirmation((visible) => {
discardVisible.value = visible;
});
const requestDiscardConfirmation = discardConfirmation.request;
const confirmDiscard = discardConfirmation.confirm;
const cancelDiscard = discardConfirmation.cancel;
const isDirty = computed(() =>
rankState.value === "form" && sortOrder.value !== sortOrderBaseline.value,
);
const loadMember = async () => {
const activeLoad = ++loadSequence;
@@ -110,6 +135,7 @@ const loadMember = async () => {
sortOrder.value = personDetail.sortOrder === null || personDetail.sortOrder === undefined
? ""
: String(personDetail.sortOrder);
sortOrderBaseline.value = sortOrder.value;
committedSortOrder.value = "";
errorMessage.value = "";
rankState.value = "form";
@@ -146,6 +172,7 @@ const saveRank = async () => {
);
if (!pageActive) return;
committedSortOrder.value = normalizedSortOrder;
sortOrderBaseline.value = normalizedSortOrder;
}
await returnTo("T01", {
genealogyId: genealogyId.value,
@@ -162,15 +189,23 @@ const saveRank = async () => {
}
};
const requestBack = () => {
if (savingRank.value) return;
return goBack();
};
const requestBack = () => runBackGuard({
transientOpen: discardVisible.value,
dirty: isDirty.value,
submitting: savingRank.value,
"close-transient": cancelDiscard,
"block-submitting": () => true,
"confirm-discard": requestDiscardConfirmation,
});
onLoad((query) => {
genealogyId.value = String(query.genealogyId || "");
personId.value = String(query.personId || "");
if (!genealogyId.value || !personId.value || query.mode !== "rank") {
if (
!/^[1-9]\d*$/.test(genealogyId.value) ||
!/^[1-9]\d*$/.test(personId.value) ||
query.mode !== "rank"
) {
rankState.value = "error";
errorMessage.value = "请从成员资料页重新进入排行调整。";
return;
@@ -183,6 +218,7 @@ onUnload(() => {
loadSequence += 1;
memberRankReadRequestController.abort();
memberRankSaveRequestController.abort();
discardConfirmation.dispose();
});
onBackPress((event) => handleBackPress(event, requestBack));
@@ -204,7 +240,7 @@ onBackPress((event) => handleBackPress(event, requestBack));
@include adaptive-tree-panel;
z-index: 2;
width: calc(100% - 32rpx);
margin: 18rpx auto 28rpx;
margin: 18rpx auto calc(28rpx + env(safe-area-inset-bottom));
padding: 7.5% 8%;
}
.form-eyebrow {
@@ -255,7 +291,7 @@ onBackPress((event) => handleBackPress(event, requestBack));
}
.rank-field input {
min-width: 0;
min-height: 56rpx;
min-height: var(--app-touch-min);
padding: 0 14rpx;
border: 1rpx solid rgba(143, 108, 63, 0.34);
border-radius: 8rpx;
@@ -269,7 +305,7 @@ onBackPress((event) => handleBackPress(event, requestBack));
.form-action {
display: grid;
width: 100%;
min-height: 76rpx;
min-height: var(--app-touch-min);
margin-top: 22rpx;
}
.form-action--disabled { opacity: 0.58; pointer-events: none; }