完成50%
This commit is contained in:
@@ -1,8 +1,10 @@
|
||||
<!-- 页面编号:G-11;用途:家谱设置、公开范围与访问说明(页面设计阶段使用本地模拟交互)。 -->
|
||||
<!-- 页面编号:G-11;用途:家谱设置、访问预设与家谱简介(页面设计阶段使用本地模拟交互)。 -->
|
||||
<template>
|
||||
<view class="settings-page">
|
||||
<GenealogyPageBackground />
|
||||
<view class="settings-page__header"><PageHeader title="家谱设置" /></view>
|
||||
<view class="settings-page__header">
|
||||
<PageHeader title="家谱设置" custom-back @back="requestBack" />
|
||||
</view>
|
||||
|
||||
<view
|
||||
class="settings-panel"
|
||||
@@ -22,7 +24,7 @@
|
||||
<text class="settings-form__eyebrow">谱主可见 · 基础设置</text>
|
||||
<text class="settings-form__title">完善家谱访问规则</text>
|
||||
<text class="settings-form__copy"
|
||||
>这里仅安排接口支持的名称、公开范围与访问说明;管理权转让将在成员选择场景中单独处理。</text
|
||||
>这里维护名称、访问规则与家谱简介;访问规则会同时决定公开范围和加入方式,管理权转让在成员场景中单独处理。</text
|
||||
>
|
||||
|
||||
<view class="settings-field">
|
||||
@@ -40,17 +42,17 @@
|
||||
}}</text>
|
||||
|
||||
<view class="visibility-block">
|
||||
<text class="visibility-block__label">公开范围</text>
|
||||
<text class="visibility-block__label">访问规则</text>
|
||||
<view class="visibility-options">
|
||||
<view
|
||||
v-for="option in visibilityOptions"
|
||||
v-for="option in accessPresetOptions"
|
||||
:key="option.value"
|
||||
class="visibility-option"
|
||||
@click="genealogyDraft.visibility = option.value"
|
||||
@click="genealogyDraft.accessPreset = option.value"
|
||||
>
|
||||
<image
|
||||
:src="
|
||||
genealogyDraft.visibility === option.value
|
||||
genealogyDraft.accessPreset === option.value
|
||||
? '/static/assets/foundation/transparent/a01-scroll-primary-v3.png'
|
||||
: '/static/assets/foundation/transparent/a01-scroll-secondary-v3.png'
|
||||
"
|
||||
@@ -59,7 +61,7 @@
|
||||
<text
|
||||
:class="{
|
||||
'visibility-option__text--active':
|
||||
genealogyDraft.visibility === option.value,
|
||||
genealogyDraft.accessPreset === option.value,
|
||||
}"
|
||||
>{{ option.label }}</text
|
||||
>
|
||||
@@ -69,12 +71,12 @@
|
||||
</view>
|
||||
|
||||
<view class="settings-field settings-field--note">
|
||||
<text>访问说明</text>
|
||||
<text>家谱简介</text>
|
||||
<textarea
|
||||
v-model="genealogyDraft.accessNote"
|
||||
v-model="genealogyDraft.intro"
|
||||
auto-height
|
||||
maxlength="80"
|
||||
placeholder="向访问者说明家谱用途"
|
||||
placeholder="简要介绍家谱来源与支系"
|
||||
placeholder-class="settings-placeholder"
|
||||
/>
|
||||
</view>
|
||||
@@ -94,85 +96,123 @@
|
||||
}}</text>
|
||||
<text class="settings-result__title">{{
|
||||
settingsState === "success"
|
||||
? "新的访问规则已经生效"
|
||||
? "本页设置草稿已更新"
|
||||
: settingsState === "no-permission"
|
||||
? "当前账号不能修改家谱"
|
||||
: "暂时无法打开家谱设置"
|
||||
}}</text>
|
||||
<text class="settings-result__copy">{{
|
||||
settingsState === "success"
|
||||
? `${genealogyDraft.name} · ${visibilityLabel}`
|
||||
? `本地预览已更新,尚未提交服务器;当前只保留在本页,返回总览不会改变原资料 · ${genealogyDraft.name} · ${accessPresetLabel}`
|
||||
: settingsState === "no-permission"
|
||||
? "只有家谱所有者可以修改名称、公开范围和访问说明。"
|
||||
? "只有家谱所有者可以修改名称、访问规则和家谱简介。"
|
||||
: "请从家谱总览重新进入,当前修改不会被保留。"
|
||||
}}</text>
|
||||
<view class="settings-action" @click="settingsState = 'form'">
|
||||
<view class="settings-action" @click="handleResultAction">
|
||||
<text>{{
|
||||
settingsState === "success" ? "继续调整" : "重新查看"
|
||||
}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<AppDialog
|
||||
:visible="discardVisible"
|
||||
title="放弃设置修改?"
|
||||
message="当前修改尚未保存,确认返回后将清空。"
|
||||
confirm-text="放弃并返回"
|
||||
cancel-text="继续修改"
|
||||
show-cancel
|
||||
compact-actions
|
||||
:close-on-mask="false"
|
||||
@confirm="confirmDiscard"
|
||||
@cancel="cancelDiscard"
|
||||
/>
|
||||
<view v-if="feedbackVisible" class="settings-feedback">
|
||||
<text>设置已保存</text>
|
||||
<text>本页草稿已更新</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { computed, reactive, ref } from "vue";
|
||||
import { onLoad, onUnload } from "@dcloudio/uni-app";
|
||||
import { onBackPress, onLoad, onUnload } from "@dcloudio/uni-app";
|
||||
import AppDialog from "@/components/AppDialog.vue";
|
||||
import AppLoading from "@/components/AppLoading.vue";
|
||||
import GenealogyPageBackground from "@/components/GenealogyPageBackground.vue";
|
||||
import PageHeader from "@/components/PageHeader.vue";
|
||||
import {
|
||||
findGenealogyFixture,
|
||||
getGenealogyFixtureAccess,
|
||||
} from "@/data/mock.js";
|
||||
import { createDiscardConfirmation } from "@/utils/discard-confirmation.js";
|
||||
import {
|
||||
GENEALOGY_ACCESS_PRESET,
|
||||
GENEALOGY_ACCESS_PRESET_OPTIONS,
|
||||
isGenealogyAccessPreset,
|
||||
} from "@/utils/genealogy-contracts.js";
|
||||
import { goBack, handleBackPress, runBackGuard } from "@/utils/navigation.js";
|
||||
|
||||
const genealogyId = ref("");
|
||||
const settingsState = ref("loading");
|
||||
const nameError = ref("");
|
||||
const feedbackVisible = ref(false);
|
||||
const discardVisible = ref(false);
|
||||
let feedbackTimer = null;
|
||||
const settingsFixtures = {
|
||||
1001: {
|
||||
name: "汤氏家谱",
|
||||
visibility: "MEMBER_ONLY",
|
||||
accessNote: "家族资料,请妥善保存",
|
||||
},
|
||||
1002: {
|
||||
name: "汤氏宗谱",
|
||||
visibility: "PUBLIC_APPLY",
|
||||
accessNote: "公开家谱身份,成员资料需审核后查看",
|
||||
},
|
||||
};
|
||||
const genealogyDraft = reactive({
|
||||
name: "汤氏家谱",
|
||||
visibility: "MEMBER_ONLY",
|
||||
accessNote: "家族资料,请妥善保存",
|
||||
name: "",
|
||||
accessPreset: GENEALOGY_ACCESS_PRESET.MEMBER_ONLY,
|
||||
intro: "",
|
||||
});
|
||||
const originalDraft = ref("");
|
||||
const isDirty = computed(
|
||||
() => JSON.stringify(genealogyDraft) !== originalDraft.value,
|
||||
);
|
||||
const visibilityOptions = [
|
||||
{ value: "MEMBER_ONLY", label: "仅成员可见" },
|
||||
{ value: "PUBLIC_APPLY", label: "公开可申请" },
|
||||
];
|
||||
const visibilityLabel = computed(
|
||||
() =>
|
||||
visibilityOptions.find((item) => item.value === genealogyDraft.visibility)
|
||||
settingsState.value === "form" &&
|
||||
JSON.stringify(genealogyDraft) !== originalDraft.value,
|
||||
);
|
||||
const discardConfirmation = createDiscardConfirmation((visible) => {
|
||||
discardVisible.value = visible;
|
||||
});
|
||||
const requestDiscardConfirmation = discardConfirmation.request;
|
||||
const confirmDiscard = discardConfirmation.confirm;
|
||||
const cancelDiscard = discardConfirmation.cancel;
|
||||
const accessPresetOptions = GENEALOGY_ACCESS_PRESET_OPTIONS;
|
||||
const accessPresetLabel = computed(
|
||||
() =>
|
||||
accessPresetOptions.find((item) => item.value === genealogyDraft.accessPreset)
|
||||
?.label || "",
|
||||
);
|
||||
const visibilityHint = computed(() =>
|
||||
genealogyDraft.visibility === "MEMBER_ONLY"
|
||||
genealogyDraft.accessPreset === GENEALOGY_ACCESS_PRESET.MEMBER_ONLY
|
||||
? "只有已加入本家谱的成员可以查看谱系和家族资料。"
|
||||
: "访客可检索到家谱并提交入谱申请,资料仍需审核后查看。",
|
||||
);
|
||||
|
||||
onLoad((query) => {
|
||||
genealogyId.value = query.genealogyId || "";
|
||||
Object.assign(
|
||||
genealogyDraft,
|
||||
settingsFixtures[genealogyId.value] || settingsFixtures[1001],
|
||||
);
|
||||
const loadSettings = (query = {}) => {
|
||||
genealogyId.value = String(query.genealogyId || "");
|
||||
if (!genealogyId.value) {
|
||||
settingsState.value = "error";
|
||||
return;
|
||||
}
|
||||
if (
|
||||
getGenealogyFixtureAccess(genealogyId.value).accessRole !== "owner"
|
||||
) {
|
||||
settingsState.value = "no-permission";
|
||||
return;
|
||||
}
|
||||
const fixture = findGenealogyFixture(genealogyId.value);
|
||||
if (!fixture) {
|
||||
settingsState.value = "error";
|
||||
return;
|
||||
}
|
||||
if (!isGenealogyAccessPreset(fixture.accessPreset)) {
|
||||
settingsState.value = "error";
|
||||
return;
|
||||
}
|
||||
Object.assign(genealogyDraft, {
|
||||
name: fixture.name,
|
||||
accessPreset: fixture.accessPreset,
|
||||
intro: fixture.publicDescription || "家族资料,请妥善保存",
|
||||
});
|
||||
originalDraft.value = JSON.stringify(genealogyDraft);
|
||||
settingsState.value =
|
||||
query.state === "loading"
|
||||
@@ -184,27 +224,59 @@ onLoad((query) => {
|
||||
: query.state === "error" || !genealogyId.value
|
||||
? "error"
|
||||
: "form";
|
||||
});
|
||||
};
|
||||
|
||||
onLoad(loadSettings);
|
||||
onUnload(() => {
|
||||
if (feedbackTimer) clearTimeout(feedbackTimer);
|
||||
const timer = feedbackTimer;
|
||||
feedbackTimer = null;
|
||||
if (timer) clearTimeout(timer);
|
||||
discardConfirmation.dispose();
|
||||
});
|
||||
|
||||
const requestBack = () =>
|
||||
runBackGuard({
|
||||
transientOpen: discardVisible.value,
|
||||
dirty: isDirty.value,
|
||||
"close-transient": cancelDiscard,
|
||||
"confirm-discard": requestDiscardConfirmation,
|
||||
});
|
||||
|
||||
onBackPress((event) => handleBackPress(event, requestBack));
|
||||
|
||||
const continueEditing = () => {
|
||||
if (
|
||||
getGenealogyFixtureAccess(genealogyId.value).accessRole === "owner"
|
||||
) {
|
||||
settingsState.value = "form";
|
||||
}
|
||||
};
|
||||
const handleResultAction = () => {
|
||||
if (settingsState.value === "success") return continueEditing();
|
||||
if (settingsState.value === "error")
|
||||
return loadSettings({ genealogyId: genealogyId.value });
|
||||
return goBack();
|
||||
};
|
||||
|
||||
const saveSettings = () => {
|
||||
if (!genealogyDraft.name.trim()) {
|
||||
nameError.value = "请填写家谱名称";
|
||||
return;
|
||||
}
|
||||
if (genealogyDraft.name.trim().length > 30) {
|
||||
nameError.value = "家谱名称不能超过 30 个字";
|
||||
if (genealogyDraft.name.trim().length > 20) {
|
||||
nameError.value = "家谱名称不能超过 20 个字";
|
||||
return;
|
||||
}
|
||||
originalDraft.value = JSON.stringify(genealogyDraft);
|
||||
settingsState.value = "success";
|
||||
feedbackVisible.value = true;
|
||||
feedbackTimer = setTimeout(() => {
|
||||
if (feedbackTimer) clearTimeout(feedbackTimer);
|
||||
const timer = setTimeout(() => {
|
||||
if (feedbackTimer !== timer) return;
|
||||
feedbackVisible.value = false;
|
||||
feedbackTimer = null;
|
||||
}, 1800);
|
||||
feedbackTimer = timer;
|
||||
};
|
||||
</script>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user