717 lines
20 KiB
Vue
717 lines
20 KiB
Vue
<!-- 页面编号:G-12;用途:字辈诗列表、空状态与批量维护(页面设计阶段使用本地模拟交互)。 -->
|
||
<template>
|
||
<view class="poem-page">
|
||
<GenealogyPageBackground />
|
||
<view class="poem-page__header"
|
||
><PageHeader
|
||
:title="pageTitle"
|
||
:action="canManage && poemState === 'list' ? '维护' : ''"
|
||
custom-back
|
||
@action="openEditor"
|
||
@back="requestBack"
|
||
/></view>
|
||
|
||
<view
|
||
class="poem-panel"
|
||
:class="{
|
||
'poem-state--list': poemState === 'list',
|
||
'poem-state--empty': poemState === 'empty',
|
||
'poem-state--edit': poemState === 'edit',
|
||
'poem-state--error': poemState === 'error',
|
||
'poem-state--no-permission': poemState === 'no-permission',
|
||
}"
|
||
>
|
||
<AppLoading
|
||
v-if="poemState === 'loading'"
|
||
text="正在整理字辈诗"
|
||
description="请稍候,正在读取家谱字序。"
|
||
/>
|
||
<view v-else-if="poemState === 'list'" class="poem-list">
|
||
<text class="poem-list__eyebrow">{{ genealogyName }} · 传承字序</text>
|
||
<text class="poem-list__title">{{ generationRangeTitle }}</text>
|
||
<text class="poem-list__copy">{{ currentGenerationCopy }}</text>
|
||
<view class="poem-rows">
|
||
<view
|
||
v-for="item in visiblePoemRows"
|
||
:key="item.generationNo"
|
||
class="poem-row"
|
||
:class="{
|
||
'poem-row--current': item.current,
|
||
'poem-row--disabled': item.status === GENERATION_POEM_STATUS.DISABLED,
|
||
}"
|
||
>
|
||
<text class="poem-row__number">第 {{ item.generationNo }} 世</text>
|
||
<text class="poem-row__character">{{ item.generationText }}</text>
|
||
<text class="poem-row__status">{{
|
||
item.current
|
||
? "当前字辈"
|
||
: item.status === GENERATION_POEM_STATUS.DISABLED
|
||
? "已停用·记录保留"
|
||
: "传承字序"
|
||
}}</text>
|
||
</view>
|
||
</view>
|
||
<view
|
||
v-if="remainingPoemCount > 0"
|
||
class="poem-load-more"
|
||
@click="loadMorePoems"
|
||
>
|
||
<text>继续加载后续字辈(剩余 {{ remainingPoemCount }} 代)</text>
|
||
</view>
|
||
<view v-if="canManage" class="poem-action" @click="openEditor">
|
||
<image
|
||
src="/static/assets/foundation/transparent/a01-scroll-primary-v3.png"
|
||
mode="aspectFit"
|
||
/><text>维护字辈诗</text>
|
||
</view>
|
||
</view>
|
||
|
||
<view v-else-if="poemState === 'edit'" class="poem-editor">
|
||
<text class="poem-list__eyebrow">批量维护</text>
|
||
<text class="poem-list__title">录入完整字辈序列</text>
|
||
<text class="poem-list__copy"
|
||
>无分隔符时每个字符对应一代;也可用空格、逗号、分号、顿号、斜杠或竖线分隔多字字辈。一次最多
|
||
{{ MAX_GENERATION_COUNT }} 代,每代最多
|
||
{{ MAX_GENERATION_TEXT_LENGTH }} 个字符。本页只更新本地预览,尚未提交服务器。</text
|
||
>
|
||
<view class="poem-field">
|
||
<text>字辈内容</text>
|
||
<textarea
|
||
v-model="poemDraft"
|
||
auto-height
|
||
:maxlength="MAX_GENERATION_POEM_INPUT_LENGTH * 2"
|
||
placeholder="例如:启宗敦本,或 克勤 克俭 承先 启后"
|
||
placeholder-class="poem-placeholder"
|
||
@input="poemError = ''"
|
||
/>
|
||
</view>
|
||
<text v-if="poemError" class="poem-field-error">{{ poemError }}</text>
|
||
<view class="poem-policy">
|
||
<text>未被新文本覆盖的后续世代</text>
|
||
<view
|
||
class="poem-policy__option"
|
||
@click="disableMissing = !disableMissing"
|
||
>
|
||
<image
|
||
:src="
|
||
disableMissing
|
||
? '/static/assets/foundation/transparent/a01-scroll-primary-v3.png'
|
||
: '/static/assets/foundation/transparent/a01-scroll-secondary-v3.png'
|
||
"
|
||
mode="aspectFit"
|
||
/>
|
||
<text
|
||
:class="{
|
||
'poem-policy__option-text--active': disableMissing,
|
||
}"
|
||
>{{ disableMissing ? "停用并保留记录" : "保持原状态" }}</text
|
||
>
|
||
</view>
|
||
</view>
|
||
<text class="poem-preview"
|
||
>预览:{{ previewSummary }}</text
|
||
>
|
||
<view class="poem-editor__actions">
|
||
<view class="poem-action" @click="requestLeaveEditor">
|
||
<image
|
||
src="/static/assets/foundation/transparent/a01-scroll-secondary-v3.png"
|
||
mode="aspectFit"
|
||
/><text class="poem-action__secondary">取消</text>
|
||
</view>
|
||
<view class="poem-action" @click="savePoems">
|
||
<image
|
||
src="/static/assets/foundation/transparent/a01-scroll-primary-v3.png"
|
||
mode="aspectFit"
|
||
/><text>保存字辈</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view v-else class="poem-state-card">
|
||
<text class="poem-list__eyebrow">{{
|
||
poemState === "empty"
|
||
? "尚未建立字辈"
|
||
: poemState === "no-permission"
|
||
? "权限不足"
|
||
: "字辈暂不可用"
|
||
}}</text>
|
||
<text class="poem-list__title">{{
|
||
poemState === "empty"
|
||
? "从第一段传承字序开始"
|
||
: poemState === "no-permission"
|
||
? "当前账号不能维护字辈"
|
||
: "暂时无法读取字辈诗"
|
||
}}</text>
|
||
<text class="poem-list__copy">{{
|
||
poemState === "empty"
|
||
? "管理员可以一次录入连续字辈,系统会按世代拆分展示。"
|
||
: poemState === "no-permission"
|
||
? "普通成员可以查看字辈,但只有具备管理权限的成员可以维护。"
|
||
: "请从家谱总览重新进入,或稍后再试。"
|
||
}}</text>
|
||
<view
|
||
v-if="poemState !== 'empty' || canManage"
|
||
class="poem-action"
|
||
@click="handleStateAction"
|
||
>
|
||
<image
|
||
src="/static/assets/foundation/transparent/a01-scroll-primary-v3.png"
|
||
mode="aspectFit"
|
||
/><text>{{
|
||
poemState === "empty"
|
||
? "开始录入"
|
||
: poemState === "no-permission"
|
||
? "返回家谱总览"
|
||
: "重新查看"
|
||
}}</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="poem-feedback">
|
||
<text>本地字辈预览已更新</text>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script setup>
|
||
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 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 {
|
||
MAX_GENERATION_COUNT,
|
||
MAX_GENERATION_POEM_INPUT_LENGTH,
|
||
MAX_GENERATION_TEXT_LENGTH,
|
||
GENERATION_POEM_STATUS,
|
||
findFirstGenerationGap,
|
||
mergeGenerationPoemRows,
|
||
validateGenerationPoemText,
|
||
} from "@/utils/generation-poem.js";
|
||
import { handleBackPress, runBackGuard } from "@/utils/navigation.js";
|
||
|
||
const INITIAL_POEM_TEXT = "启宗敦本";
|
||
const POEM_RENDER_BATCH_SIZE = 50;
|
||
const PREVIEW_GENERATION_LIMIT = 12;
|
||
const LOCAL_PREVIEW_START_GENERATION = 1;
|
||
const LOCAL_CURRENT_GENERATION = 3;
|
||
const genealogyId = ref("");
|
||
const genealogyName = ref("家谱");
|
||
const poemState = ref("loading");
|
||
const poemError = ref("");
|
||
const feedbackVisible = ref(false);
|
||
const discardVisible = ref(false);
|
||
const canManage = ref(false);
|
||
let feedbackTimer = null;
|
||
const poemDraft = ref(INITIAL_POEM_TEXT);
|
||
// OpenAPI 的 disableMissing 示例为 false;本地同样采用安全默认 false。停用后续世代是高影响动作,
|
||
// 必须由谱主主动选择,不能把缩短一次本地草稿解释为默认停用历史记录。
|
||
const disableMissing = ref(false);
|
||
const editorOrigin = ref("list");
|
||
const editorSnapshot = ref(null);
|
||
const poemRows = ref([]);
|
||
const visiblePoemCount = ref(POEM_RENDER_BATCH_SIZE);
|
||
const visiblePoemRows = computed(() =>
|
||
poemRows.value.slice(0, visiblePoemCount.value),
|
||
);
|
||
const remainingPoemCount = computed(() =>
|
||
poemRows.value.length > visiblePoemCount.value
|
||
? poemRows.value.length - visiblePoemCount.value
|
||
: 0,
|
||
);
|
||
const pageTitle = computed(() =>
|
||
poemState.value === "edit" ? "维护字辈诗" : "字辈诗",
|
||
);
|
||
const generationRangeTitle = computed(() => {
|
||
if (!poemRows.value.length) return "尚未建立字辈";
|
||
const first = poemRows.value[0].generationNo;
|
||
const last = poemRows.value[poemRows.value.length - 1].generationNo;
|
||
return first === last ? `第 ${first} 世字辈` : `第 ${first}—${last} 世字辈`;
|
||
});
|
||
const currentGenerationCopy = computed(() => {
|
||
const current = poemRows.value.find((item) => item.current);
|
||
return current
|
||
? `当前为第 ${current.generationNo} 世“${current.generationText}”字辈。`
|
||
: `当前第 ${LOCAL_CURRENT_GENERATION} 世尚未被有效字辈覆盖。`;
|
||
});
|
||
const previewSummary = computed(() => {
|
||
const validation = validateGenerationPoemText(poemDraft.value);
|
||
if (!validation.valid) {
|
||
return poemDraft.value.trim() ? validation.message : "尚未录入字辈";
|
||
}
|
||
const visible = validation.generations
|
||
.slice(0, PREVIEW_GENERATION_LIMIT)
|
||
.join(" · ");
|
||
const remaining = validation.generations.length - PREVIEW_GENERATION_LIMIT;
|
||
return remaining > 0 ? `${visible} · …另 ${remaining} 代` : visible;
|
||
});
|
||
const isDirty = computed(() =>
|
||
Boolean(
|
||
poemState.value === "edit" &&
|
||
editorSnapshot.value &&
|
||
(poemDraft.value !== editorSnapshot.value.poemDraft ||
|
||
disableMissing.value !== editorSnapshot.value.disableMissing),
|
||
),
|
||
);
|
||
const discardConfirmation = createDiscardConfirmation((visible) => {
|
||
discardVisible.value = visible;
|
||
});
|
||
const requestDiscardConfirmation = discardConfirmation.request;
|
||
const confirmDiscard = discardConfirmation.confirm;
|
||
const cancelDiscard = discardConfirmation.cancel;
|
||
|
||
const resetPoemRows = () => {
|
||
const seed = validateGenerationPoemText(INITIAL_POEM_TEXT).generations;
|
||
poemDraft.value = INITIAL_POEM_TEXT;
|
||
poemRows.value = mergeGenerationPoemRows({
|
||
existingRows: [],
|
||
generationTexts: seed,
|
||
startGeneration: LOCAL_PREVIEW_START_GENERATION,
|
||
currentGeneration: LOCAL_CURRENT_GENERATION,
|
||
disableMissing: false,
|
||
});
|
||
visiblePoemCount.value = POEM_RENDER_BATCH_SIZE;
|
||
};
|
||
|
||
const loadMorePoems = () => {
|
||
visiblePoemCount.value = Math.min(
|
||
poemRows.value.length,
|
||
visiblePoemCount.value + POEM_RENDER_BATCH_SIZE,
|
||
);
|
||
};
|
||
|
||
const loadPoems = (query = {}) => {
|
||
genealogyId.value = String(query.genealogyId || "");
|
||
const fixture = findGenealogyFixture(genealogyId.value);
|
||
if (!fixture) {
|
||
canManage.value = false;
|
||
poemState.value = "error";
|
||
return;
|
||
}
|
||
genealogyName.value = fixture.name || "家谱";
|
||
const accessRole = getGenealogyFixtureAccess(genealogyId.value).accessRole;
|
||
canManage.value = accessRole === "owner";
|
||
if (accessRole === "guest") {
|
||
poemState.value = "no-permission";
|
||
return;
|
||
}
|
||
resetPoemRows();
|
||
const requestedState =
|
||
query.state === "loading"
|
||
? "loading"
|
||
: query.state === "empty"
|
||
? "empty"
|
||
: query.state === "edit"
|
||
? "edit"
|
||
: query.state === "no-permission"
|
||
? "no-permission"
|
||
: query.state === "error"
|
||
? "error"
|
||
: "list";
|
||
if (requestedState === "empty") {
|
||
poemDraft.value = "";
|
||
poemRows.value = [];
|
||
}
|
||
if (requestedState === "edit") {
|
||
if (!canManage.value) {
|
||
poemState.value = "no-permission";
|
||
return;
|
||
}
|
||
poemState.value = "list";
|
||
openEditor("list");
|
||
return;
|
||
}
|
||
poemState.value = requestedState;
|
||
};
|
||
|
||
onLoad(loadPoems);
|
||
onUnload(() => {
|
||
const timer = feedbackTimer;
|
||
feedbackTimer = null;
|
||
if (timer) clearTimeout(timer);
|
||
discardConfirmation.dispose();
|
||
});
|
||
|
||
const openEditor = (origin = poemState.value) => {
|
||
if (!canManage.value) return false;
|
||
editorOrigin.value = origin === "empty" ? "empty" : "list";
|
||
editorSnapshot.value = Object.freeze({
|
||
poemDraft: poemDraft.value,
|
||
disableMissing: disableMissing.value,
|
||
});
|
||
poemState.value = "edit";
|
||
return true;
|
||
};
|
||
const restoreEditorSnapshot = () => {
|
||
if (!editorSnapshot.value) return;
|
||
poemDraft.value = editorSnapshot.value.poemDraft;
|
||
disableMissing.value = editorSnapshot.value.disableMissing;
|
||
};
|
||
const requestLeaveEditor = async () => {
|
||
if (isDirty.value) {
|
||
const confirmed = await requestDiscardConfirmation();
|
||
if (!confirmed) return false;
|
||
}
|
||
restoreEditorSnapshot();
|
||
poemState.value = editorOrigin.value;
|
||
editorSnapshot.value = null;
|
||
poemError.value = "";
|
||
return true;
|
||
};
|
||
const requestBack = () =>
|
||
runBackGuard({
|
||
transientOpen: discardVisible.value,
|
||
internalTrail: poemState.value === "edit",
|
||
"close-transient": cancelDiscard,
|
||
"pop-internal-trail": requestLeaveEditor,
|
||
});
|
||
|
||
onBackPress((event) => handleBackPress(event, requestBack));
|
||
|
||
const handleStateAction = () => {
|
||
if (poemState.value === "empty") return openEditor("empty");
|
||
if (poemState.value === "error")
|
||
return loadPoems({ genealogyId: genealogyId.value });
|
||
return requestBack();
|
||
};
|
||
const savePoems = () => {
|
||
const validation = validateGenerationPoemText(poemDraft.value);
|
||
if (!validation.valid) {
|
||
poemError.value = validation.message;
|
||
return;
|
||
}
|
||
const lastGeneration =
|
||
LOCAL_PREVIEW_START_GENERATION + validation.generations.length - 1;
|
||
if (LOCAL_CURRENT_GENERATION > lastGeneration) {
|
||
poemError.value = `请至少录入到当前第 ${LOCAL_CURRENT_GENERATION} 世`;
|
||
return;
|
||
}
|
||
const nextRows = mergeGenerationPoemRows({
|
||
existingRows: poemRows.value,
|
||
generationTexts: validation.generations,
|
||
startGeneration: LOCAL_PREVIEW_START_GENERATION,
|
||
currentGeneration: LOCAL_CURRENT_GENERATION,
|
||
disableMissing: disableMissing.value,
|
||
});
|
||
const activeRows = nextRows.filter(
|
||
(item) => item.status === GENERATION_POEM_STATUS.ACTIVE,
|
||
);
|
||
const lastActiveGeneration = activeRows.length
|
||
? activeRows[activeRows.length - 1].generationNo
|
||
: null;
|
||
const firstGap = lastActiveGeneration === null
|
||
? null
|
||
: findFirstGenerationGap(
|
||
nextRows,
|
||
lastActiveGeneration + 1,
|
||
LOCAL_PREVIEW_START_GENERATION,
|
||
);
|
||
if (firstGap !== null) {
|
||
poemError.value = `第 ${firstGap} 世字辈缺失;请补齐完整序列,或选择停用未覆盖的后续记录`;
|
||
return;
|
||
}
|
||
poemRows.value = nextRows;
|
||
visiblePoemCount.value = POEM_RENDER_BATCH_SIZE;
|
||
editorSnapshot.value = null;
|
||
poemState.value = "list";
|
||
feedbackVisible.value = true;
|
||
if (feedbackTimer) clearTimeout(feedbackTimer);
|
||
const timer = setTimeout(() => {
|
||
if (feedbackTimer !== timer) return;
|
||
feedbackVisible.value = false;
|
||
feedbackTimer = null;
|
||
}, 1800);
|
||
feedbackTimer = timer;
|
||
};
|
||
</script>
|
||
|
||
<style scoped lang="scss">
|
||
@use "../../styles/adaptive-frame-profiles.scss" as adaptive;
|
||
.poem-page {
|
||
display: flex;
|
||
min-height: 100vh;
|
||
flex-direction: column;
|
||
background: $paper;
|
||
}
|
||
.poem-page__header {
|
||
z-index: 3;
|
||
}
|
||
.poem-panel {
|
||
@include adaptive.adaptive-genealogy-state-panel;
|
||
z-index: 2;
|
||
width: calc(100% - 32rpx);
|
||
margin: 18rpx auto 0;
|
||
padding: 76rpx 8%;
|
||
box-sizing: border-box;
|
||
}
|
||
.poem-panel > .app-loading {
|
||
grid-area: 1 / 1 / -1 / -1;
|
||
}
|
||
.poem-list,
|
||
.poem-editor,
|
||
.poem-state-card {
|
||
min-width: 0;
|
||
}
|
||
.poem-list__eyebrow {
|
||
display: block;
|
||
color: $brand-red;
|
||
font-size: 23rpx;
|
||
letter-spacing: 3rpx;
|
||
}
|
||
.poem-list__title {
|
||
display: block;
|
||
margin-top: 11rpx;
|
||
color: $ink;
|
||
font-family: "STKaiti", "KaiTi", serif;
|
||
font-size: 35rpx;
|
||
font-weight: 700;
|
||
}
|
||
.poem-list__copy {
|
||
display: block;
|
||
margin-top: 10rpx;
|
||
color: $ink-muted;
|
||
font-size: 24rpx;
|
||
line-height: 1.55;
|
||
}
|
||
.poem-rows {
|
||
margin-top: 18rpx;
|
||
}
|
||
.poem-load-more {
|
||
display: flex;
|
||
min-height: 64rpx;
|
||
align-items: center;
|
||
justify-content: center;
|
||
margin-top: 14rpx;
|
||
background: url("/static/assets/foundation/transparent/a01-scroll-secondary-v3.png")
|
||
center / contain no-repeat;
|
||
}
|
||
.poem-load-more text {
|
||
color: $ink;
|
||
font-size: 23rpx;
|
||
font-weight: 700;
|
||
}
|
||
.poem-row {
|
||
@include adaptive.adaptive-genealogy-form-field;
|
||
display: grid;
|
||
min-height: 72rpx;
|
||
margin-top: 10rpx;
|
||
grid-template-columns: minmax(116rpx, 38%) minmax(0, 1fr) auto;
|
||
align-items: center;
|
||
}
|
||
.poem-row__number {
|
||
z-index: 1;
|
||
grid-column: 1;
|
||
margin-left: 24rpx;
|
||
color: $ink-muted;
|
||
font-size: 23rpx;
|
||
}
|
||
.poem-row__character {
|
||
z-index: 1;
|
||
grid-column: 2;
|
||
min-width: 0;
|
||
padding: 12rpx 16rpx 12rpx 0;
|
||
color: $ink;
|
||
font-family: "STKaiti", "KaiTi", serif;
|
||
font-size: 32rpx;
|
||
font-weight: 700;
|
||
line-height: 1.4;
|
||
overflow-wrap: anywhere;
|
||
word-break: break-word;
|
||
}
|
||
.poem-row__status {
|
||
z-index: 1;
|
||
grid-column: 3;
|
||
margin-right: 22rpx;
|
||
color: $ink-muted;
|
||
font-size: 22rpx;
|
||
}
|
||
.poem-row--current .poem-row__character,
|
||
.poem-row--current .poem-row__status {
|
||
color: $brand-red;
|
||
}
|
||
.poem-row--disabled .poem-row__character,
|
||
.poem-row--disabled .poem-row__status {
|
||
color: $ink-muted;
|
||
opacity: 0.62;
|
||
}
|
||
.poem-action {
|
||
display: grid;
|
||
width: 100%;
|
||
min-height: 76rpx;
|
||
margin-top: 20rpx;
|
||
}
|
||
.poem-action image {
|
||
grid-area: 1 / 1;
|
||
width: 100%;
|
||
height: 100%;
|
||
}
|
||
.poem-action text {
|
||
z-index: 1;
|
||
display: flex;
|
||
grid-area: 1 / 1;
|
||
align-items: center;
|
||
justify-content: center;
|
||
height: 100%;
|
||
color: #fff9ed;
|
||
font-size: 25rpx;
|
||
font-weight: 700;
|
||
letter-spacing: 2rpx;
|
||
}
|
||
.poem-field {
|
||
@include adaptive.adaptive-genealogy-form-field;
|
||
display: grid;
|
||
min-height: 118rpx;
|
||
margin-top: 22rpx;
|
||
}
|
||
.poem-field > text {
|
||
z-index: 1;
|
||
grid-area: 1 / 1;
|
||
align-self: center;
|
||
margin-left: 24rpx;
|
||
color: $ink;
|
||
font-size: 22rpx;
|
||
font-weight: 700;
|
||
}
|
||
.poem-field textarea {
|
||
z-index: 1;
|
||
grid-area: 1 / 1;
|
||
box-sizing: border-box;
|
||
width: auto;
|
||
min-width: 0;
|
||
min-height: 118rpx;
|
||
margin-right: 20rpx;
|
||
margin-left: 164rpx;
|
||
padding-top: 34rpx;
|
||
color: $ink;
|
||
font-size: 22rpx;
|
||
line-height: 1.5;
|
||
}
|
||
.poem-placeholder {
|
||
color: #a79884;
|
||
}
|
||
.poem-field-error {
|
||
display: block;
|
||
margin-top: 4rpx;
|
||
color: $brand-red;
|
||
font-size: 24rpx;
|
||
line-height: 34rpx;
|
||
text-align: right;
|
||
}
|
||
.poem-policy {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
margin-top: 22rpx;
|
||
}
|
||
.poem-policy > text {
|
||
color: $ink;
|
||
font-size: 24rpx;
|
||
font-weight: 700;
|
||
}
|
||
.poem-policy__option {
|
||
display: grid;
|
||
width: 248rpx;
|
||
min-height: 62rpx;
|
||
}
|
||
.poem-policy__option image {
|
||
grid-area: 1 / 1;
|
||
width: 100%;
|
||
height: 100%;
|
||
}
|
||
.poem-policy__option text {
|
||
z-index: 1;
|
||
display: flex;
|
||
grid-area: 1 / 1;
|
||
align-items: center;
|
||
justify-content: center;
|
||
height: 100%;
|
||
color: $ink;
|
||
font-size: 23rpx;
|
||
font-weight: 700;
|
||
}
|
||
.poem-policy__option .poem-policy__option-text--active {
|
||
color: #fff9ed;
|
||
}
|
||
.poem-preview {
|
||
display: block;
|
||
margin-top: 22rpx;
|
||
color: $ink-muted;
|
||
font-size: 23rpx;
|
||
line-height: 1.6;
|
||
}
|
||
.poem-editor__actions {
|
||
display: flex;
|
||
gap: 14rpx;
|
||
margin-top: 18rpx;
|
||
}
|
||
.poem-editor__actions .poem-action {
|
||
width: calc(50% - 7rpx);
|
||
margin-top: 0;
|
||
}
|
||
.poem-action .poem-action__secondary {
|
||
color: $ink;
|
||
}
|
||
.poem-state-card {
|
||
text-align: center;
|
||
}
|
||
.poem-state--empty,
|
||
.poem-state--error,
|
||
.poem-state--no-permission {
|
||
padding: 180rpx 4% 70rpx;
|
||
}
|
||
.poem-state-card .poem-list__eyebrow {
|
||
text-align: center;
|
||
}
|
||
.poem-state-card .poem-list__copy {
|
||
margin-top: 22rpx;
|
||
}
|
||
.poem-state-card .poem-action {
|
||
width: 420rpx;
|
||
max-width: 100%;
|
||
margin: 34rpx auto 0;
|
||
}
|
||
.poem-feedback {
|
||
position: fixed;
|
||
z-index: 30;
|
||
top: 138rpx;
|
||
left: 50%;
|
||
display: flex;
|
||
min-width: 260rpx;
|
||
min-height: 74rpx;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 0 34rpx;
|
||
transform: translateX(-50%);
|
||
background: url("/static/assets/foundation/transparent/a01-scroll-secondary-v3.png")
|
||
center / contain no-repeat;
|
||
}
|
||
.poem-feedback text {
|
||
z-index: 1;
|
||
color: $ink;
|
||
font-size: 22rpx;
|
||
}
|
||
@media (min-width: 400px) {
|
||
.poem-panel {
|
||
width: calc(100% - 48rpx);
|
||
}
|
||
}
|
||
</style>
|