upload project source code

This commit is contained in:
2026-04-30 18:49:43 +08:00
commit 9b394ba682
2277 changed files with 660945 additions and 0 deletions

View File

@@ -0,0 +1,391 @@
<template>
<view class="solutions-screen">
<view class="solutions-bg"></view>
<view class="status-bar-placeholder"></view>
<view class="solutions-header">
<view class="solutions-back-btn" @click="$emit('back')">
<text class="solutions-back-icon"></text>
</view>
<view class="solutions-header-center">
<text class="solutions-title">起名方案列表</text>
</view>
<view class="solutions-header-placeholder"></view>
</view>
<scroll-view scroll-y class="solutions-scroll">
<view class="solutions-content">
<view v-if="!solutions.length" class="solutions-empty">
<text class="solutions-empty-icon"></text>
<text class="solutions-empty-text">暂无方案</text>
</view>
<view
v-for="(it, idx) in solutions"
:key="String(it?.id || it?.solution_id || idx)"
class="solutions-item"
:style="{ animationDelay: (idx * 0.04) + 's' }"
@click="open(it)"
>
<view class="solutions-item-main">
<view class="solutions-item-header">
<view>
<text class="solutions-item-name">{{ titleOf(it) }}</text>
<text class="solutions-item-pinyin">{{ pinyinOf(it) }}</text>
</view>
<view class="solutions-item-actions">
<view class="solutions-item-view-btn" @click.stop="open(it)">
<text class="solutions-item-view-icon"></text>
<text class="solutions-item-view-text">查看</text>
</view>
<view class="solutions-item-badge">
<text class="solutions-item-badge-text">{{ idx + 1 }}</text>
</view>
</view>
</view>
<view class="solutions-item-meta">
<text class="solutions-tag">{{ tagAOf(it) }}</text>
<text class="solutions-tag">{{ tagBOf(it) }}</text>
</view>
<view class="solutions-item-meta-sub">
<text v-if="scoreOf(it)" class="solutions-chip">评分 {{ scoreOf(it) }}</text>
</view>
<view v-if="poetryOf(it)" class="solutions-item-poetry">
<text class="solutions-item-poetry-label">出处</text>
<text class="solutions-item-poetry-text">{{ poetryOf(it) }}</text>
</view>
</view>
</view>
</view>
</scroll-view>
</view>
</template>
<script setup lang="ts">
import { computed } from "vue";
import { namingApi } from "@/api/naming";
import { parseMaybeJson } from "@/utils/poll-test-solution-detail";
declare const uni: any;
const props = defineProps<{
reportId: number;
solutions: any[];
category?: string;
serviceType?: string;
}>();
const emit = defineEmits<{
back: [];
showDetail: [data: any, category?: string, serviceType?: string];
}>();
const solutions = computed(() => (Array.isArray(props.solutions) ? props.solutions : []));
const titleOf = (it: any) => {
const name = String(it?.name || it?.solution_name || it?.title || it?.label || "").trim();
if (name) return name;
const fallback = String(it?.given_name || it?.full_name || it?.company_name || "").trim();
return fallback || "方案";
};
const pinyinOf = (it: any) => String(it?.pinyin || it?.name_pinyin || "").trim() || "Pīn Yīn";
const tagAOf = (it: any) => String(it?.wuxing || it?.wuxing_tag || it?.element_tag || "五行均衡");
const tagBOf = (it: any) => String(it?.style || it?.style_tag || it?.feature_tag || "温文尔雅");
const poetryOf = (it: any) => String(it?.poetry_source || it?.poetry || it?.source || "").trim();
const scoreOf = (it: any) => {
const v = it?.total_score ?? it?.score;
if (v === null || v === undefined || v === "") return "";
return String(v);
};
const open = async (it: any) => {
const id = it?.id || it?.solution_id;
if (!id) {
uni.showToast({ title: "方案ID不存在", icon: "none" });
return;
}
try {
uni.showLoading({ title: "加载中..." });
const detailRaw: any = await namingApi.getSolutionDetail(id);
uni.hideLoading();
const parsed = parseMaybeJson(detailRaw);
if (!parsed || typeof parsed !== "object") {
uni.showToast({ title: "详情数据格式异常", icon: "none" });
return;
}
emit("showDetail", parsed, props.category, String(props.serviceType || ""));
} catch (e: any) {
uni.hideLoading();
uni.showToast({ title: e?.msg || e?.message || "加载失败", icon: "none" });
}
};
</script>
<style scoped>
.solutions-screen{
min-height: 100%;
position: relative;
overflow: hidden;
}
.solutions-bg{
position: fixed;
inset: 0;
background:
/* 纸张底色 */
radial-gradient(1200px 900px at 30% 20%, rgba(255,255,255,.92), rgba(245,241,232,.88) 45%, rgba(235,229,214,.92) 100%),
/* 纸纹颗粒 */
radial-gradient(2px 2px at 12% 18%, rgba(0,0,0,.06), transparent 55%),
radial-gradient(2px 2px at 48% 62%, rgba(0,0,0,.05), transparent 55%),
radial-gradient(2px 2px at 78% 34%, rgba(0,0,0,.04), transparent 55%),
radial-gradient(2px 2px at 32% 84%, rgba(0,0,0,.04), transparent 55%),
/* 墨韵晕染 */
radial-gradient(900px 520px at 12% 8%, rgba(25,28,33,.10), transparent 60%),
radial-gradient(760px 520px at 92% 22%, rgba(120,75,40,.08), transparent 62%),
radial-gradient(900px 640px at 40% 92%, rgba(90,35,35,.08), transparent 62%),
linear-gradient(180deg, #f6f2e8 0%, #efe7d6 60%, #f6f2e8 100%);
z-index: -1;
}
.status-bar-placeholder{
height: 24px;
}
.solutions-header{
display:flex;
align-items:center;
justify-content:space-between;
padding: 10px 14px 12px;
}
.solutions-back-btn{
width: 36px;
height: 36px;
border-radius: 12px;
border: 1px solid rgba(120,90,40,.26);
background: linear-gradient(180deg, rgba(255,255,255,.70), rgba(244,236,220,.65));
box-shadow: 0 6px 16px rgba(40,30,20,.10);
display:flex;
align-items:center;
justify-content:center;
}
.solutions-back-icon{
font-size: 22px;
color: rgba(82,60,28,.92);
line-height: 1;
}
.solutions-header-center{
display:flex;
flex-direction:column;
align-items:center;
gap: 3px;
}
.solutions-title{
font-size: 17px;
font-weight: 900;
color: rgba(28,24,20,.92);
letter-spacing: .08em;
font-family: "STSong","Songti SC","SimSun","STSong","Noto Serif SC",serif;
}
.solutions-subtitle{
font-size: 11px;
color: rgba(70,58,44,.72);
font-family: "STSong","Songti SC","SimSun","STSong","Noto Serif SC",serif;
}
.solutions-header-placeholder{
width: 36px;
height: 36px;
}
.solutions-scroll{
height: calc(100vh - 24px - 58px);
}
.solutions-content{
padding: 2px 14px 24px;
box-sizing:border-box;
}
.solutions-empty{
padding: 26px 10px;
border-radius: 18px;
border: 1px solid rgba(120,90,40,.18);
background: linear-gradient(180deg, rgba(255,255,255,.76), rgba(247,239,224,.66));
box-shadow: 0 10px 26px rgba(40,30,20,.10);
text-align:center;
}
.solutions-empty-icon{
display:block;
font-size: 18px;
color: rgba(132,98,52,.85);
margin-bottom: 6px;
}
.solutions-empty-text{
font-size: 13px;
color: rgba(50,40,28,.78);
font-family: "STSong","Songti SC","SimSun","STSong","Noto Serif SC",serif;
}
.solutions-item{
position: relative;
display:flex;
align-items:stretch;
justify-content:space-between;
border-radius: 18px;
border: 1px solid rgba(178,120,120,.45);
background:
linear-gradient(180deg, rgba(255,255,255,.84), rgba(249,243,232,.78));
overflow:hidden;
padding: 14px 14px 13px 14px;
margin-bottom: 14px;
animation: solFadeUp .22s ease both;
box-shadow:
0 14px 30px rgba(40,30,20,.14),
inset 0 1px 0 rgba(255,255,255,.55);
}
.solutions-item-main{
flex: 1;
}
.solutions-item-header{
display:flex;
align-items:flex-start;
justify-content:space-between;
gap: 10px;
}
.solutions-item-name{
font-size: 18px;
font-weight: 900;
color: #20252e;
letter-spacing: .04em;
font-family: "STSong","Songti SC","SimSun","STSong","Noto Serif SC",serif;
display: block;
}
.solutions-item-pinyin{
display: block;
margin-top: 4px;
font-size: 12px;
color: rgba(32,37,46,.72);
letter-spacing: .08em;
}
.solutions-item-badge{
width: 24px;
height: 24px;
border-radius: 999px;
border: 1px solid rgba(202,166,96,.62);
background:
linear-gradient(180deg, rgba(255,245,220,.90), rgba(248,229,184,.82));
display:flex;
align-items:center;
justify-content:center;
flex: 0 0 24px;
}
.solutions-item-badge-text{
font-size: 11px;
font-weight: 900;
color: rgba(128,96,42,.92);
}
.solutions-item-actions{
display: flex;
align-items: center;
gap: 8px;
}
.solutions-item-view-btn{
height: 26px;
padding: 0 10px;
border-radius: 999px;
border: 1px solid rgba(188,170,136,.78);
background: rgba(255,255,255,.70);
display:flex;
align-items:center;
gap: 4px;
box-shadow: 0 2px 6px rgba(40,30,20,.08);
}
.solutions-item-view-icon{
font-size: 12px;
color: rgba(55,60,68,.75);
}
.solutions-item-view-text{
font-size: 12px;
font-weight: 700;
color: rgba(55,60,68,.85);
}
.solutions-item-meta{
display:flex;
gap: 8px;
margin-top: 8px;
flex-wrap: wrap;
}
.solutions-tag{
font-size: 11px;
padding: 3px 8px;
border-radius: 7px;
border: 1px solid rgba(188,114,114,.52);
color: rgba(130,58,58,.90);
background: rgba(255,250,248,.78);
font-family: "STSong","Songti SC","SimSun","STSong","Noto Serif SC",serif;
}
.solutions-item-meta-sub{
display:flex;
gap: 8px;
margin-top: 9px;
flex-wrap: wrap;
}
.solutions-chip{
font-size: 10px;
padding: 3px 8px;
border-radius: 999px;
border: 1px solid rgba(196,168,106,.42);
color: rgba(128,96,42,.88);
background: rgba(250,239,211,.65);
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
}
.solutions-item-poetry{
margin-top: 8px;
display:flex;
align-items:flex-start;
gap: 8px;
}
.solutions-item-poetry-label{
flex: 0 0 auto;
font-size: 11px;
line-height: 1.5;
color: rgba(130,58,58,.90);
border: 1px solid rgba(188,114,114,.50);
border-radius: 6px;
padding: 1px 6px;
background: rgba(255,250,248,.78);
}
.solutions-item-poetry-text{
flex: 1;
font-size: 12px;
line-height: 1.6;
color: rgba(40,34,26,.82);
font-family: "STSong","Songti SC","SimSun","STSong","Noto Serif SC",serif;
}
@keyframes solFadeUp{
from{opacity:0;transform:translateY(6px)}
to{opacity:1;transform:translateY(0)}
}
/* 细节:内侧金线与“卷轴边” */
.solutions-item::before{
content:"";
position:absolute;
inset: 9px 9px 9px 9px;
border-radius: 12px;
border: 1px solid rgba(188,170,136,.28);
pointer-events:none;
}
.solutions-item::after{
content:"";
position:absolute;
top:-40px;
right:-60px;
width: 160px;
height: 160px;
background: radial-gradient(closest-side, rgba(188,114,114,.08), transparent 70%);
transform: rotate(18deg);
pointer-events:none;
}
/* 轻微按压反馈 */
.solutions-item:active{
transform: translateY(1px);
box-shadow:
0 10px 22px rgba(40,30,20,.12),
inset 0 1px 0 rgba(255,255,255,.55);
}
</style>