修改部分样式

This commit is contained in:
rain
2026-07-27 17:29:58 +08:00
parent 04287e6777
commit 1e9e25fe67
53 changed files with 11562 additions and 2617 deletions
+229 -18
View File
@@ -5,16 +5,57 @@
<view class="page-layer"><PageHeader title="帮助中心" /></view>
<view class="page-content page-layer">
<text class="help-source-note">{{ sourceNote }}</text>
<view class="search-box"><input v-model.trim="keyword" aria-label="搜索帮助" placeholder="搜索问题关键词" /><text>{{ filteredQuestions.length }} </text></view>
<scroll-view scroll-x class="category-scroll" :show-scrollbar="false"><view class="category-row"><view v-for="category in helpCategories" :key="category.value" class="category-chip" :class="{ active: activeCategory === category.value }" role="button" @click="activeCategory = category.value">{{ category.label }}</view></view></scroll-view>
<view class="search-box"
><input
v-model.trim="keyword"
aria-label="搜索帮助"
placeholder="搜索问题关键词"
/><text>{{ filteredQuestions.length }} </text></view
>
<scroll-view scroll-x class="category-scroll" :show-scrollbar="false"
><view class="category-row"
><view
v-for="category in helpCategories"
:key="category.value"
class="category-chip"
:class="{ active: activeCategory === category.value }"
role="button"
@click="activeCategory = category.value"
>{{ category.label }}</view
></view
></scroll-view
>
<view v-if="filteredQuestions.length" class="question-list">
<view v-for="item in filteredQuestions" :key="item.id" class="question-card">
<view class="question-heading" role="button" :aria-label="item.question" @click="toggleQuestion(item.id)"><text>{{ item.question }}</text><text>{{ expandedIds.includes(item.id) ? "收起" : "查看" }}</text></view>
<text v-if="expandedIds.includes(item.id)" class="answer">{{ item.answer }}</text>
<view
v-for="item in filteredQuestions"
:key="item.id"
class="question-card"
>
<view
class="question-heading"
role="button"
:aria-label="item.question"
@click="toggleQuestion(item.id)"
><text>{{ item.question }}</text
><text>{{
expandedIds.includes(item.id) ? "收起" : "查看"
}}</text></view
>
<text v-if="expandedIds.includes(item.id)" class="answer">{{
item.answer
}}</text>
</view>
</view>
<view v-else class="empty-card"><text>没有找到相关问题</text><text>换个关键词试试或直接提交意见反馈</text></view>
<AppButton block type="secondary" label="联系家谱助手" @click="contactSupport" />
<view v-else class="empty-card"
><text>没有找到相关问题</text
><text>换个关键词试试或直接提交意见反馈</text></view
>
<AppButton
block
type="secondary"
label="联系家谱助手"
@click="contactSupport"
/>
</view>
</view>
</template>
@@ -25,39 +66,71 @@ import { onLoad, onShow, onUnload } from "@dcloudio/uni-app";
import AppButton from "@/components/AppButton.vue";
import ModulePageBackground from "@/components/ModulePageBackground.vue";
import PageHeader from "@/components/PageHeader.vue";
import { appApi, createRequestController, isRequestCancelled } from "@/utils/api.js";
import {
appApi,
createRequestController,
isRequestCancelled,
} from "@/utils/api.js";
import { openPage } from "@/utils/navigation.js";
const questions = ref([]);
const helpState = ref("loading");
const controller = createRequestController();
let active = true;
const categoryLabels = Object.freeze({ common: "常见问题", member: "成员管理", lineage: "世系关系" });
const categoryLabels = Object.freeze({
common: "常见问题",
member: "成员管理",
lineage: "世系关系",
});
const helpCategories = computed(() => [
{ value: "", label: "全部" },
...[...new Set(questions.value.map((item) => item.category).filter(Boolean))].map((value) => ({ value, label: categoryLabels[value.toLowerCase()] || value })),
...[
...new Set(questions.value.map((item) => item.category).filter(Boolean)),
].map((value) => ({
value,
label: categoryLabels[value.toLowerCase()] || value,
})),
]);
const activeCategory = ref("");
const keyword = ref("");
const expandedIds = ref([]);
const sourceNote = computed(() => ({ loading: "正在读取帮助文章…", error: "帮助文章暂时无法读取,请稍后重试。", empty: "暂未收到可展示的帮助文章。", ready: "帮助内容来自服务端,可按分类或关键词查找。" })[helpState.value]);
const sourceNote = computed(
() =>
({
loading: "正在读取帮助文章…",
error: "帮助文章暂时无法读取,请稍后重试。",
empty: "暂未收到可展示的帮助文章。",
ready: "帮助内容来自服务端,可按分类或关键词查找。",
})[helpState.value],
);
const filteredQuestions = computed(() => {
const query = keyword.value.toLowerCase();
return questions.value.filter((item) => (!activeCategory.value || item.category === activeCategory.value) && (!query || `${item.question}${item.answer}`.toLowerCase().includes(query)));
return questions.value.filter(
(item) =>
(!activeCategory.value || item.category === activeCategory.value) &&
(!query ||
`${item.question}${item.answer}`.toLowerCase().includes(query)),
);
});
const toggleQuestion = (id) => { expandedIds.value = expandedIds.value.includes(id) ? expandedIds.value.filter((item) => item !== id) : [...expandedIds.value, id]; };
const toggleQuestion = (id) => {
expandedIds.value = expandedIds.value.includes(id)
? expandedIds.value.filter((item) => item !== id)
: [...expandedIds.value, id];
};
const contactSupport = () => openPage("M07", {}, "M06");
const loadHelpArticles = async () => {
controller.abort();
helpState.value = "loading";
try {
const rows = await appApi.getHelpArticles({ requestController: controller });
const rows = await appApi.getHelpArticles({
requestController: controller,
});
if (!active) return;
questions.value = rows.map((item) => ({
id: String(item.helpId),
category: String(item.helpCategory || "其他"),
question: String(item.helpTitle || "未命名帮助文章"),
answer: String(item.helpContent || "暂无正文")
answer: String(item.helpContent || "暂无正文"),
}));
helpState.value = questions.value.length ? "ready" : "empty";
} catch (error) {
@@ -66,11 +139,149 @@ const loadHelpArticles = async () => {
}
};
onLoad(loadHelpArticles);
onShow(() => { if (helpState.value !== "loading") loadHelpArticles(); });
onUnload(() => { active = false; controller.abort(); });
onShow(() => {
if (helpState.value !== "loading") loadHelpArticles();
});
onUnload(() => {
active = false;
controller.abort();
});
</script>
<style scoped lang="scss">
@use "../../styles/adaptive-frame-profiles.scss" as adaptive;
.help-page{display:flex;min-height:100vh;flex-direction:column;background:$paper}.page-layer{z-index:1}.page-content{flex:1;padding:24rpx 28rpx 72rpx}.help-source-note{display:block;margin:0 4rpx 16rpx;color:$ink-muted;font-size:21rpx;line-height:1.55}.search-box{@include adaptive.adaptive-profile-field;display:grid;grid-template-columns:minmax(0,1fr) auto;min-height:86rpx;align-items:center;gap:16rpx;padding:0 30rpx}.search-box input{width:auto;min-width:0;min-height:68rpx;color:$ink;font-size:23rpx}.search-box text{color:$ink-muted;font-size:20rpx}.category-scroll{width:100%;margin-top:18rpx}.category-row{display:flex;width:max-content;gap:12rpx;padding:2rpx}.category-chip{display:flex;min-width:100rpx;min-height:64rpx;align-items:center;justify-content:center;padding:0 22rpx;box-sizing:border-box;color:$ink-muted;font-size:22rpx}.category-chip.active{@include adaptive.adaptive-scroll-button(secondary);color:$brand-red;font-weight:700}.question-list{display:flex;flex-direction:column;gap:14rpx;margin-top:18rpx}.question-card,.empty-card{@include adaptive.adaptive-profile-content}.question-card{min-height:104rpx;padding:24rpx 34rpx}.question-heading{display:grid;grid-template-columns:minmax(0,1fr) auto;min-height:58rpx;align-items:center;gap:18rpx}.question-heading text:first-child{color:$ink;font-size:24rpx;font-weight:700;overflow-wrap:anywhere}.question-heading text:last-child{color:$brand-red;font-size:20rpx}.answer{display:block;padding:14rpx 4rpx 6rpx;border-top:1px solid rgba(181,137,63,.32);color:$ink-muted;font-size:22rpx;line-height:1.65;overflow-wrap:anywhere}.empty-card{min-height:220rpx;padding:58rpx 44rpx;text-align:center}.empty-card text{display:block}.empty-card text:first-child{color:$ink;font-size:29rpx;font-weight:700}.empty-card text:last-child{margin-top:12rpx;color:$ink-muted;font-size:22rpx;line-height:1.5}.page-content>.app-button{margin-top:28rpx}@media(max-width:340px){.page-content{padding-right:20rpx;padding-left:20rpx}}
.help-page {
display: flex;
min-height: 100vh;
flex-direction: column;
background: $paper;
}
.page-layer {
z-index: 1;
}
.page-content {
flex: 1;
padding: 24rpx 28rpx 72rpx;
}
.help-source-note {
display: block;
margin: 0 4rpx 16rpx;
color: $ink-muted;
font-size: 21rpx;
line-height: 1.55;
}
.search-box {
@include adaptive.adaptive-profile-field;
display: grid;
grid-template-columns: minmax(0, 1fr) auto;
min-height: 86rpx;
align-items: center;
gap: 16rpx;
padding: 0 30rpx;
}
.search-box input {
width: auto;
min-width: 0;
min-height: 68rpx;
color: $ink;
font-size: 23rpx;
}
.search-box text {
color: $ink-muted;
font-size: 20rpx;
}
.category-scroll {
width: 100%;
margin-top: 18rpx;
}
.category-row {
display: flex;
width: max-content;
gap: 12rpx;
padding: 2rpx;
}
.category-chip {
display: flex;
min-width: 100rpx;
min-height: 64rpx;
align-items: center;
justify-content: center;
padding: 0 22rpx;
box-sizing: border-box;
color: $ink-muted;
font-size: 22rpx;
}
.category-chip.active {
@include adaptive.adaptive-scroll-button(secondary);
color: $brand-red;
font-weight: 700;
}
.question-list {
display: flex;
flex-direction: column;
gap: 14rpx;
margin-top: 18rpx;
}
.question-card,
.empty-card {
@include adaptive.adaptive-profile-content;
}
.question-card {
min-height: 104rpx;
padding: 24rpx 34rpx;
}
.question-heading {
display: grid;
grid-template-columns: minmax(0, 1fr) auto;
min-height: 58rpx;
align-items: center;
gap: 18rpx;
}
.question-heading text:first-child {
color: $ink;
font-size: 24rpx;
font-weight: 700;
overflow-wrap: anywhere;
}
.question-heading text:last-child {
color: $brand-red;
font-size: 20rpx;
}
.answer {
display: block;
padding: 14rpx 4rpx 6rpx;
border-top: 1px solid rgba(181, 137, 63, 0.32);
color: $ink-muted;
font-size: 22rpx;
line-height: 1.65;
overflow-wrap: anywhere;
}
.empty-card {
min-height: 220rpx;
padding: 58rpx 44rpx;
text-align: center;
}
.empty-card text {
display: block;
}
.empty-card text:first-child {
color: $ink;
font-size: 29rpx;
font-weight: 700;
}
.empty-card text:last-child {
margin-top: 12rpx;
color: $ink-muted;
font-size: 22rpx;
line-height: 1.5;
}
.page-content > .app-button {
margin-top: 28rpx;
}
@media (max-width: 340px) {
.page-content {
padding-right: 20rpx;
padding-left: 20rpx;
}
}
</style>