730 lines
21 KiB
Vue
730 lines
21 KiB
Vue
<template>
|
||
<view class="poem-page">
|
||
<GenealogyPageBackground />
|
||
<view class="poem-page__header">
|
||
<PageHeader
|
||
:title="pageTitle"
|
||
:action="poemState === 'list' || poemState === 'empty' ? '维护' : ''"
|
||
custom-back
|
||
@action="enterManagement"
|
||
@back="requestBack"
|
||
/>
|
||
</view>
|
||
|
||
<view class="poem-panel" :class="`poem-state--${poemState}`">
|
||
<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">按已记录的世代和字辈展示传承字序。</text>
|
||
<view class="poem-rows">
|
||
<view
|
||
v-for="item in visiblePoemRows"
|
||
:key="item.poemId"
|
||
class="poem-row"
|
||
:class="{
|
||
'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.status === GENERATION_POEM_STATUS.DISABLED
|
||
? "已停用·记录保留"
|
||
: "传承字序"
|
||
}}</text>
|
||
</view>
|
||
</view>
|
||
<view
|
||
v-if="remainingPoemCount > 0"
|
||
class="poem-load-more"
|
||
role="button"
|
||
:aria-label="'继续加载后续字辈,剩余 ' + remainingPoemCount + ' 代'"
|
||
@click="loadMorePoems"
|
||
>
|
||
<text>继续加载后续字辈(剩余 {{ remainingPoemCount }} 代)</text>
|
||
</view>
|
||
<view
|
||
class="poem-action"
|
||
role="button"
|
||
:aria-label="canManage ? '继续维护字辈诗' : '查看字辈列表'"
|
||
@click="enterManagement"
|
||
>
|
||
<image
|
||
src="/static/assets/foundation/transparent/scroll-primary.png"
|
||
mode="aspectFit"
|
||
/><text>{{ canManage ? "继续维护字辈诗" : "查看字辈列表" }}</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"
|
||
>保存前可先查看调整结果。没有分隔符时,每个字对应一代;多个字可用空格、逗号、分号、顿号、斜杠或竖线分开。</text
|
||
>
|
||
<view class="poem-field">
|
||
<text>字辈内容</text>
|
||
<textarea
|
||
v-model="poemDraft"
|
||
auto-height
|
||
:disabled="saving"
|
||
:maxlength="MAX_GENERATION_POEM_INPUT_LENGTH"
|
||
placeholder="例如:启宗敦本,或 克勤 克俭 承先 启后"
|
||
placeholder-class="poem-placeholder"
|
||
@input="invalidatePreview"
|
||
/>
|
||
</view>
|
||
<text v-if="poemError" class="poem-field-error">{{ poemError }}</text>
|
||
<view class="poem-policy">
|
||
<text>这次未填写到的后续字辈</text>
|
||
<view
|
||
class="poem-policy__option"
|
||
:class="{ 'poem-policy__option--disabled': saving }"
|
||
role="checkbox"
|
||
:aria-checked="disableMissing"
|
||
:aria-disabled="saving"
|
||
aria-label="停用未填写到的后续字辈"
|
||
@click="toggleDisableMissing"
|
||
>
|
||
<image
|
||
:src="
|
||
disableMissing
|
||
? '/static/assets/foundation/transparent/scroll-primary.png'
|
||
: '/static/assets/foundation/transparent/scroll-secondary.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"
|
||
:class="{ 'poem-action--disabled': previewing || saving }"
|
||
role="button"
|
||
:aria-disabled="previewing || saving"
|
||
aria-label="取消"
|
||
@click="requestLeaveEditor"
|
||
>
|
||
<image
|
||
src="/static/assets/foundation/transparent/scroll-secondary.png"
|
||
mode="aspectFit"
|
||
/><text class="poem-action__secondary">取消</text>
|
||
</view>
|
||
<view
|
||
class="poem-action"
|
||
:class="{ 'poem-action--disabled': previewing || saving }"
|
||
role="button"
|
||
:aria-disabled="previewing || saving"
|
||
aria-label="查看调整结果"
|
||
@click="previewPoems"
|
||
>
|
||
<image
|
||
src="/static/assets/foundation/transparent/scroll-secondary.png"
|
||
mode="aspectFit"
|
||
/><text class="poem-action__secondary">{{
|
||
previewing ? "正在查看" : "查看调整结果"
|
||
}}</text>
|
||
</view>
|
||
<view
|
||
class="poem-action"
|
||
:class="{ 'poem-action--disabled': !canSave || saving }"
|
||
role="button"
|
||
:aria-disabled="!canSave || saving"
|
||
aria-label="保存字辈"
|
||
@click="savePoems"
|
||
>
|
||
<image
|
||
src="/static/assets/foundation/transparent/scroll-primary.png"
|
||
mode="aspectFit"
|
||
/><text>{{ saving ? "正在保存" : "保存字辈" }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<view v-else class="poem-state-card">
|
||
<text class="poem-list__eyebrow">{{
|
||
poemState === "empty" ? "尚未建立字辈" : "字辈暂不可用"
|
||
}}</text>
|
||
<text class="poem-list__title">{{
|
||
poemState === "empty"
|
||
? "暂时没有可显示的字辈"
|
||
: "暂时无法读取字辈诗"
|
||
}}</text>
|
||
<text class="poem-list__copy">{{ stateCopy }}</text>
|
||
<view
|
||
class="poem-action"
|
||
role="button"
|
||
:aria-label="poemState === 'empty' ? '查看字辈列表' : '重新读取'"
|
||
@click="handleStateAction"
|
||
>
|
||
<image
|
||
src="/static/assets/foundation/transparent/scroll-primary.png"
|
||
mode="aspectFit"
|
||
/><text>{{
|
||
poemState === "empty" ? "查看字辈列表" : "重新读取"
|
||
}}</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="feedbackMessage" class="poem-feedback"
|
||
><text>{{ feedbackMessage }}</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/genealogy/PageBackground.vue";
|
||
import PageHeader from "@/components/PageHeader.vue";
|
||
import { createDiscardConfirmation } from "@/utils/discard-confirmation.js";
|
||
import {
|
||
createRequestController,
|
||
isRequestCancelled
|
||
} from "@/services/api/request-controller.js";
|
||
import { generationPoemApi } from "@/services/api/generation-poem-service.js";
|
||
import { getRequestErrorMessage } from "@/services/api/request-error-message.js";
|
||
import {
|
||
MAX_GENERATION_POEM_INPUT_LENGTH,
|
||
GENERATION_POEM_STATUS,
|
||
validateGenerationPoemText,
|
||
} from "@/utils/genealogy/generation-poem.js";
|
||
import { handleBackPress, runBackGuard } from "@/utils/navigation/gateway.js";
|
||
|
||
const POEM_RENDER_BATCH_SIZE = 50;
|
||
const genealogyId = ref("");
|
||
const genealogyName = ref("当前家谱");
|
||
const poemState = ref("loading");
|
||
const poemError = ref("");
|
||
const feedbackMessage = ref("");
|
||
const discardVisible = ref(false);
|
||
const canManage = ref(false);
|
||
const previewing = ref(false);
|
||
const saving = ref(false);
|
||
const poemDraft = ref("");
|
||
const disableMissing = ref(false);
|
||
const editorSnapshot = ref(null);
|
||
const poemRows = ref([]);
|
||
const visiblePoemCount = ref(POEM_RENDER_BATCH_SIZE);
|
||
const preview = ref(null);
|
||
const previewSignature = ref("");
|
||
const poemListController = createRequestController();
|
||
const poemPreviewController = createRequestController();
|
||
const poemSaveController = createRequestController();
|
||
let requestSequence = 0;
|
||
let pageActive = true;
|
||
|
||
const visiblePoemRows = computed(() =>
|
||
poemRows.value.slice(0, visiblePoemCount.value),
|
||
);
|
||
const remainingPoemCount = computed(() =>
|
||
Math.max(0, poemRows.value.length - visiblePoemCount.value),
|
||
);
|
||
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 draftSignature = computed(
|
||
() => `${poemDraft.value}\u0000${disableMissing.value}`,
|
||
);
|
||
const canSave = computed(
|
||
() =>
|
||
Boolean(preview.value) && previewSignature.value === draftSignature.value,
|
||
);
|
||
const previewSummary = computed(() => {
|
||
if (previewing.value) return "正在查看调整结果。";
|
||
if (!preview.value) return "请先查看调整结果,再保存。";
|
||
return `调整结果:新增 ${preview.value.createCount} 条,更新 ${preview.value.updateCount} 条,保留 ${preview.value.keepCount} 条,停用 ${preview.value.disableCount} 条。`;
|
||
});
|
||
const stateCopy = computed(() =>
|
||
poemState.value === "empty"
|
||
? "当前尚未添加可用的字辈,可进入维护页面查看。"
|
||
: "暂未读取到可展示的字辈,请稍后重试。",
|
||
);
|
||
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 applyRows = (rows) => {
|
||
poemRows.value = rows;
|
||
visiblePoemCount.value = POEM_RENDER_BATCH_SIZE;
|
||
const named = rows.find((item) => item.genealogyName);
|
||
genealogyName.value = named?.genealogyName || "当前家谱";
|
||
};
|
||
const loadPoems = async ({ management = false } = {}) => {
|
||
if (!genealogyId.value) {
|
||
poemState.value = "error";
|
||
return false;
|
||
}
|
||
const sequence = ++requestSequence;
|
||
poemState.value = "loading";
|
||
poemError.value = "";
|
||
try {
|
||
const rows = management
|
||
? await generationPoemApi.getGenerationPoemManagement(genealogyId.value, {
|
||
requestController: poemListController,
|
||
})
|
||
: await generationPoemApi.getGenerationPoems(genealogyId.value, {
|
||
requestController: poemListController,
|
||
});
|
||
if (!pageActive || sequence !== requestSequence) return false;
|
||
applyRows(rows);
|
||
canManage.value = management;
|
||
poemState.value = rows.length ? "list" : "empty";
|
||
return true;
|
||
} catch (error) {
|
||
if (!pageActive || isRequestCancelled(error) || sequence !== requestSequence) return false;
|
||
poemState.value = "error";
|
||
return false;
|
||
}
|
||
};
|
||
const loadMorePoems = () => {
|
||
visiblePoemCount.value = Math.min(
|
||
poemRows.value.length,
|
||
visiblePoemCount.value + POEM_RENDER_BATCH_SIZE,
|
||
);
|
||
};
|
||
const invalidatePreview = () => {
|
||
poemError.value = "";
|
||
preview.value = null;
|
||
previewSignature.value = "";
|
||
};
|
||
const toggleDisableMissing = () => {
|
||
if (saving.value) return;
|
||
disableMissing.value = !disableMissing.value;
|
||
invalidatePreview();
|
||
};
|
||
const openEditor = () => {
|
||
if (!canManage.value) return false;
|
||
poemDraft.value = poemRows.value
|
||
.filter((item) => item.status === GENERATION_POEM_STATUS.ACTIVE)
|
||
.map((item) => item.generationText)
|
||
.join(" ");
|
||
disableMissing.value = false;
|
||
preview.value = null;
|
||
previewSignature.value = "";
|
||
editorSnapshot.value = Object.freeze({
|
||
poemDraft: poemDraft.value,
|
||
disableMissing: disableMissing.value,
|
||
});
|
||
poemState.value = "edit";
|
||
return true;
|
||
};
|
||
const enterManagement = async () => {
|
||
if (previewing.value || saving.value) return;
|
||
const loaded = await loadPoems({ management: true });
|
||
if (pageActive && loaded) openEditor();
|
||
};
|
||
const requestLeaveEditor = async () => {
|
||
if (previewing.value || saving.value) return false;
|
||
if (isDirty.value) {
|
||
const confirmed = await requestDiscardConfirmation();
|
||
if (!confirmed) return false;
|
||
}
|
||
poemState.value = poemRows.value.length ? "list" : "empty";
|
||
editorSnapshot.value = null;
|
||
poemError.value = "";
|
||
return true;
|
||
};
|
||
const validateDraft = () => {
|
||
const validation = validateGenerationPoemText(poemDraft.value);
|
||
if (!validation.valid) {
|
||
poemError.value = validation.message;
|
||
return false;
|
||
}
|
||
return true;
|
||
};
|
||
const previewPoems = async () => {
|
||
if (previewing.value || saving.value || !validateDraft()) return;
|
||
const submittedDraft = {
|
||
poemText: poemDraft.value,
|
||
disableMissing: disableMissing.value,
|
||
};
|
||
const submittedSignature = draftSignature.value;
|
||
previewing.value = true;
|
||
poemError.value = "";
|
||
try {
|
||
const previewResult = await generationPoemApi.previewGenerationPoemBatch(
|
||
genealogyId.value,
|
||
submittedDraft,
|
||
{ requestController: poemPreviewController },
|
||
);
|
||
if (!pageActive || submittedSignature !== draftSignature.value) return;
|
||
preview.value = previewResult;
|
||
previewSignature.value = submittedSignature;
|
||
} catch (error) {
|
||
if (pageActive && !isRequestCancelled(error))
|
||
poemError.value = getRequestErrorMessage(error, "暂时无法查看调整结果,请稍后重试。");
|
||
} finally {
|
||
if (pageActive) previewing.value = false;
|
||
}
|
||
};
|
||
const savePoems = async () => {
|
||
if (!canSave.value || saving.value || !validateDraft()) return;
|
||
saving.value = true;
|
||
poemError.value = "";
|
||
try {
|
||
await generationPoemApi.saveGenerationPoemBatch(
|
||
genealogyId.value,
|
||
{
|
||
poemText: poemDraft.value,
|
||
disableMissing: disableMissing.value,
|
||
},
|
||
{ requestController: poemSaveController },
|
||
);
|
||
if (!pageActive) return;
|
||
feedbackMessage.value = "字辈已保存,正在刷新列表。";
|
||
const loaded = await loadPoems({ management: true });
|
||
if (!pageActive) return;
|
||
if (!loaded) {
|
||
poemError.value = "字辈已保存,但页面暂时未更新,请稍后重新查看。";
|
||
return;
|
||
}
|
||
editorSnapshot.value = null;
|
||
feedbackMessage.value = "字辈已保存。";
|
||
} catch (error) {
|
||
if (pageActive && !isRequestCancelled(error))
|
||
poemError.value = getRequestErrorMessage(error, "字辈保存失败,请稍后重试。");
|
||
} finally {
|
||
if (pageActive) saving.value = false;
|
||
}
|
||
};
|
||
const requestBack = () =>
|
||
runBackGuard({
|
||
transientOpen: discardVisible.value,
|
||
internalTrail: poemState.value === "edit",
|
||
submitting: previewing.value || saving.value,
|
||
"close-transient": cancelDiscard,
|
||
"pop-internal-trail": requestLeaveEditor,
|
||
"block-submitting": () => true,
|
||
});
|
||
const handleStateAction = () =>
|
||
poemState.value === "empty" ? enterManagement() : loadPoems();
|
||
|
||
onLoad((query) => {
|
||
genealogyId.value = String(query?.genealogyId || "");
|
||
loadPoems();
|
||
});
|
||
onBackPress((event) => handleBackPress(event, requestBack));
|
||
onUnload(() => {
|
||
pageActive = false;
|
||
++requestSequence;
|
||
poemListController.abort();
|
||
poemPreviewController.abort();
|
||
poemSaveController.abort();
|
||
discardConfirmation.dispose();
|
||
});
|
||
</script>
|
||
|
||
<style scoped lang="scss">
|
||
@import "../../styles/adaptive-frame-profiles.scss";
|
||
.poem-page {
|
||
display: flex;
|
||
min-height: 100vh;
|
||
flex-direction: column;
|
||
background: $paper;
|
||
}
|
||
.poem-page__header {
|
||
z-index: 3;
|
||
}
|
||
.poem-panel {
|
||
@include 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: clamp(14px, 23rpx, 17px);
|
||
letter-spacing: 3rpx;
|
||
}
|
||
.poem-list__title {
|
||
display: block;
|
||
margin-top: 11rpx;
|
||
color: $ink;
|
||
font-family: "STKaiti", "KaiTi", serif;
|
||
font-size: clamp(19px, 35rpx, 24px);
|
||
font-weight: 700;
|
||
}
|
||
.poem-list__copy {
|
||
display: block;
|
||
margin-top: 10rpx;
|
||
color: $ink-muted;
|
||
font-size: clamp(15px, 24rpx, 18px);
|
||
line-height: 1.55;
|
||
}
|
||
.poem-rows {
|
||
margin-top: 18rpx;
|
||
}
|
||
.poem-load-more {
|
||
display: flex;
|
||
min-height: 88rpx;
|
||
align-items: center;
|
||
justify-content: center;
|
||
margin-top: 14rpx;
|
||
background: url("/static/assets/foundation/transparent/scroll-secondary.png")
|
||
center / contain no-repeat;
|
||
}
|
||
.poem-load-more text {
|
||
color: $ink;
|
||
font-size: clamp(14px, 23rpx, 17px);
|
||
font-weight: 700;
|
||
}
|
||
.poem-row {
|
||
@include 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: clamp(14px, 23rpx, 17px);
|
||
}
|
||
.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: clamp(17px, 32rpx, 22px);
|
||
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: clamp(14px, 22rpx, 17px);
|
||
}
|
||
.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: 88rpx;
|
||
margin-top: 20rpx;
|
||
}
|
||
.poem-action--disabled {
|
||
opacity: 0.55;
|
||
}
|
||
.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: clamp(15px, 25rpx, 18px);
|
||
font-weight: 700;
|
||
letter-spacing: 2rpx;
|
||
}
|
||
.poem-field {
|
||
@include 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: clamp(14px, 22rpx, 17px);
|
||
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: clamp(14px, 22rpx, 17px);
|
||
line-height: 1.5;
|
||
}
|
||
.poem-placeholder {
|
||
color: #a79884;
|
||
}
|
||
.poem-field-error {
|
||
display: block;
|
||
margin-top: 4rpx;
|
||
color: $brand-red;
|
||
font-size: clamp(15px, 24rpx, 18px);
|
||
line-height: max(1.35em, clamp(19px, 34rpx, 24px));
|
||
text-align: right;
|
||
}
|
||
.poem-policy {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
margin-top: 22rpx;
|
||
}
|
||
.poem-policy > text {
|
||
color: $ink;
|
||
font-size: clamp(15px, 24rpx, 18px);
|
||
font-weight: 700;
|
||
}
|
||
.poem-policy__option {
|
||
display: grid;
|
||
width: 248rpx;
|
||
min-height: 88rpx;
|
||
}
|
||
.poem-policy__option--disabled {
|
||
opacity: 0.55;
|
||
}
|
||
.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: clamp(14px, 23rpx, 17px);
|
||
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: clamp(14px, 23rpx, 17px);
|
||
line-height: 1.6;
|
||
}
|
||
.poem-editor__actions {
|
||
display: flex;
|
||
gap: 14rpx;
|
||
margin-top: 18rpx;
|
||
}
|
||
.poem-editor__actions .poem-action {
|
||
width: calc((100% - 28rpx) / 3);
|
||
margin-top: 0;
|
||
}
|
||
.poem-action .poem-action__secondary {
|
||
color: $ink;
|
||
}
|
||
.poem-state-card {
|
||
padding: 180rpx 4% 70rpx;
|
||
text-align: center;
|
||
}
|
||
.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/scroll-secondary.png")
|
||
center / contain no-repeat;
|
||
}
|
||
.poem-feedback text {
|
||
z-index: 1;
|
||
color: $ink;
|
||
font-size: clamp(14px, 22rpx, 17px);
|
||
}
|
||
@media (min-width: 400px) {
|
||
.poem-panel {
|
||
width: calc(100% - 48rpx);
|
||
}
|
||
}
|
||
</style>
|