824 lines
26 KiB
Vue
824 lines
26 KiB
Vue
<template>
|
||
<view class="company-desktop-detail">
|
||
<view class="detail-header">
|
||
<view class="detail-header-back" @click="emit('back')">
|
||
<text class="back-icon">‹</text>
|
||
<text class="back-text">返回</text>
|
||
</view>
|
||
<text class="detail-header-title">公司测名详解</text>
|
||
<view class="detail-header-placeholder" />
|
||
</view>
|
||
|
||
<scroll-view scroll-y class="detail-content">
|
||
<view class="report-body">
|
||
<!-- header -->
|
||
<view
|
||
class="section"
|
||
:class="{ 'section--click': hasNodes(header.details?.nodes) }"
|
||
@click="hasNodes(header.details?.nodes) && openDetail(header.details?.title || '总分详解', header.details?.nodes)"
|
||
>
|
||
<text class="section-label">header · 总分</text>
|
||
<view class="score-row">
|
||
<text class="name">{{ toText(header.name) || '—' }}</text>
|
||
<text class="score">{{ num(header.score, 0) }}</text>
|
||
</view>
|
||
<view class="tag-row">
|
||
<text class="pill">{{ toText(header.tagLeft) }}</text>
|
||
<text class="pill">{{ toText(header.tagRight) }}</text>
|
||
</view>
|
||
<text class="body-text">{{ toText(header.quote) }}</text>
|
||
<text v-if="hasNodes(header.details?.nodes)" class="section-hint">点击本段查看「{{ toText(header.details?.title) || '详解' }}」</text>
|
||
</view>
|
||
|
||
<!-- characterAnalysis -->
|
||
<view
|
||
class="section"
|
||
:class="{ 'section--click': hasNodes(characterAnalysis.details?.nodes) }"
|
||
@click="
|
||
hasNodes(characterAnalysis.details?.nodes) &&
|
||
openDetail(characterAnalysis.details?.title || '字义数理详解', characterAnalysis.details?.nodes)
|
||
"
|
||
>
|
||
<text class="section-label">characterAnalysis · 字义数理</text>
|
||
<view class="char-grid">
|
||
<view v-for="(it, idx) in arr(characterAnalysis.characters)" :key="idx" class="char-box">
|
||
<text class="char-single">{{ toText(it?.char) }}</text>
|
||
<text class="char-meta">{{ toText(it?.element) }} · {{ num(it?.stroke, 0) }}画</text>
|
||
<text class="body-text small">{{ toText(it?.meaning) }}</text>
|
||
</view>
|
||
</view>
|
||
<text class="body-text">{{ toText(characterAnalysis.analysis) }}</text>
|
||
<text v-if="hasNodes(characterAnalysis.details?.nodes)" class="section-hint">
|
||
点击本段查看「{{ toText(characterAnalysis.details?.title) || '详细拆解' }}」
|
||
</text>
|
||
</view>
|
||
|
||
<!-- businessPattern -->
|
||
<view class="section">
|
||
<text class="section-label">businessPattern · 商业格局</text>
|
||
<SixDimensionRadarDesktopEchart
|
||
:labels="arr(businessPattern.radar?.labels)"
|
||
:values="arr(businessPattern.radar?.values)"
|
||
:remark="summaryText"
|
||
/>
|
||
<view v-if="arr(businessPattern.summary).length" class="kv-inline">
|
||
<view v-for="(s, si) in arr(businessPattern.summary)" :key="si" class="summary-chip">
|
||
<text class="chip-k">{{ toText(s?.label) }}</text>
|
||
<text class="chip-v">{{ toText(s?.value) }}</text>
|
||
</view>
|
||
</view>
|
||
<view
|
||
v-if="hasNodes(businessPattern.details?.nodes)"
|
||
class="section-link"
|
||
:class="{ 'section--click': true }"
|
||
@click="openDetail(businessPattern.details?.title || '商业六维详解', businessPattern.details?.nodes)"
|
||
>
|
||
<text>{{ toText(businessPattern.details?.title) || '商业六维 · 解释与建议' }} ›</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- gua -->
|
||
<view
|
||
class="section"
|
||
:class="{ 'section--click': hasNodes(gua.details?.nodes) }"
|
||
@click="hasNodes(gua.details?.nodes) && openDetail(gua.details?.title || '卦象解读', gua.details?.nodes)"
|
||
>
|
||
<text class="section-label">gua · 卦象</text>
|
||
<text v-if="toText(gua.bg)" class="gua-bg">卦字:{{ toText(gua.bg) }}</text>
|
||
<text class="headline">{{ toText(gua.name) }} · {{ toText(gua.badge) }}</text>
|
||
<text class="body-text">{{ toText(gua.desc) }}</text>
|
||
<view v-if="arr(gua.tags).length" class="tag-list">
|
||
<text v-for="(t, ti) in arr(gua.tags)" :key="ti" class="pill pill--soft">{{ toText(t) }}</text>
|
||
</view>
|
||
<text class="body-text">{{ toText(gua.insight) }}</text>
|
||
<text v-if="hasNodes(gua.details?.nodes)" class="section-hint">点击本段查看卦象详解</text>
|
||
</view>
|
||
|
||
<!-- team -->
|
||
<view
|
||
class="section"
|
||
:class="{ 'section--click': hasNodes(team.details?.nodes) }"
|
||
@click="hasNodes(team.details?.nodes) && openDetail(team.details?.title || '团队契合', team.details?.nodes)"
|
||
>
|
||
<text class="section-label">team · 团队契合</text>
|
||
<view v-for="(m, mi) in arr(team.members)" :key="mi" class="member-block">
|
||
<text class="member-line">
|
||
{{ toText(m?.role) }} · {{ num(m?.score, 0) }}分 · {{ toText(m?.match) }}
|
||
</text>
|
||
<text v-if="toText(m?.desc)" class="body-text small">{{ toText(m?.desc) }}</text>
|
||
</view>
|
||
<text v-if="toText(team.note)" class="body-text note">{{ toText(team.note) }}</text>
|
||
<text v-if="hasNodes(team.details?.nodes)" class="section-hint">点击本段查看团队说明</text>
|
||
</view>
|
||
|
||
<!-- years -->
|
||
<view
|
||
class="section"
|
||
:class="{ 'section--click': hasNodes(years.details?.nodes) }"
|
||
@click="hasNodes(years.details?.nodes) && openDetail(years.details?.title || '流年运势', years.details?.nodes)"
|
||
>
|
||
<text class="section-label">years · 流年</text>
|
||
<view v-for="(y, yi) in arr(years.items)" :key="yi" class="year-row">
|
||
<text class="year-key">{{ toText(y?.year) }}</text>
|
||
<text class="year-luck">{{ toText(y?.luck) }}</text>
|
||
<text class="year-text">{{ toText(y?.text) }}</text>
|
||
</view>
|
||
<text v-if="hasNodes(years.details?.nodes)" class="section-hint">点击本段查看流年预警/建议</text>
|
||
</view>
|
||
|
||
<!-- wealthTrend -->
|
||
<view
|
||
class="section"
|
||
:class="{ 'section--click': hasNodes(wealthTrend.details?.nodes) }"
|
||
@click="hasNodes(wealthTrend.details?.nodes) && openDetail(wealthTrend.details?.title || '财运走势', wealthTrend.details?.nodes)"
|
||
>
|
||
<text class="section-label">wealthTrend · 财运走势</text>
|
||
<view class="bars">
|
||
<view v-for="(v, vi) in arr(wealthTrend.bars)" :key="vi" class="bar-wrap">
|
||
<view class="bar" :style="{ height: `${Math.max(8, Math.min(100, num(v, 0)))}%` }" />
|
||
</view>
|
||
</view>
|
||
<text class="body-text">{{ toText(wealthTrend.note) }}</text>
|
||
<text v-if="hasNodes(wealthTrend.details?.nodes)" class="section-hint">点击本段查看走势建议</text>
|
||
</view>
|
||
|
||
<!-- direction -->
|
||
<view
|
||
class="section"
|
||
:class="{ 'section--click': hasNodes(direction.details?.nodes) }"
|
||
@click="hasNodes(direction.details?.nodes) && openDetail(direction.details?.title || '吉凶方位', direction.details?.nodes)"
|
||
>
|
||
<text class="section-label">direction · 方位</text>
|
||
<text class="body-text">{{ toText(direction.note) }}</text>
|
||
<text v-if="direction.goodDot && (direction.goodDot.x != null || direction.goodDot.y != null)" class="body-text small">
|
||
吉位参考点(相对坐标):x {{ num(direction.goodDot?.x, 0) }},y {{ num(direction.goodDot?.y, 0) }}
|
||
</text>
|
||
<text v-if="hasNodes(direction.details?.nodes)" class="section-hint">点击本段查看方位说明</text>
|
||
</view>
|
||
|
||
<!-- layout -->
|
||
<view
|
||
class="section"
|
||
:class="{ 'section--click': hasNodes(layout.details?.nodes) }"
|
||
@click="hasNodes(layout.details?.nodes) && openDetail(layout.details?.title || '办公布局', layout.details?.nodes)"
|
||
>
|
||
<text class="section-label">layout · 办公布局</text>
|
||
<view v-for="(it, li) in arr(layout.items)" :key="li" class="layout-line">
|
||
<text class="layout-strong">{{ toText(it?.strong) }}</text>
|
||
<view class="layout-flow">
|
||
<text class="body-text small">{{ toText(it?.textBefore) }}</text>
|
||
<text v-for="(h, hi) in arr(it?.highlights)" :key="hi" class="highlight">「{{ toText(h) }}」</text>
|
||
<text class="body-text small">{{ toText(it?.textAfter) }}</text>
|
||
</view>
|
||
</view>
|
||
<text v-if="hasNodes(layout.details?.nodes)" class="section-hint">点击本段查看布局建议</text>
|
||
</view>
|
||
|
||
<!-- execution -->
|
||
<view
|
||
class="section section--wide"
|
||
:class="{ 'section--click': hasNodes(execution.details?.nodes) }"
|
||
@click="hasNodes(execution.details?.nodes) && openDetail(execution.details?.title || '执行建议', execution.details?.nodes)"
|
||
>
|
||
<text class="section-label">execution · 执行建议</text>
|
||
<text class="body-text">{{ toText(execution.text) }}</text>
|
||
<text v-if="hasNodes(execution.details?.nodes)" class="section-hint">点击本段查看执行条目</text>
|
||
</view>
|
||
|
||
<!-- liuyao -->
|
||
<view
|
||
v-if="hasLiuyao"
|
||
class="section"
|
||
:class="{ 'section--click': hasNodes(liuyao.details?.nodes) }"
|
||
@click="hasNodes(liuyao.details?.nodes) && openDetail('六爻', liuyao.details?.nodes)"
|
||
>
|
||
<text class="section-label">liuyao · 六爻</text>
|
||
<text class="headline">{{ toText(liuyao.hexagram_title) }}</text>
|
||
<text class="body-text">{{ toText(liuyao.changing_summary) }}</text>
|
||
<text class="body-text">{{ toText(liuyao.interpretation) }}</text>
|
||
<text v-for="(yl, yi) in arr(liuyao.yao_lines)" :key="yi" class="body-text small mono">· {{ toText(yl) }}</text>
|
||
<text v-if="hasNodes(liuyao.details?.nodes)" class="section-hint">点击本段查看六爻详解</text>
|
||
</view>
|
||
|
||
<!-- wuxing_bagua -->
|
||
<view
|
||
v-if="hasWuxingBagua"
|
||
class="section"
|
||
:class="{ 'section--click': hasNodes(wuxingBagua.details?.nodes) }"
|
||
@click="hasNodes(wuxingBagua.details?.nodes) && openDetail('五行八卦', wuxingBagua.details?.nodes)"
|
||
>
|
||
<text class="section-label">wuxing_bagua · 五行八卦</text>
|
||
<text class="body-text">{{ toText(wuxingBagua.wuxing_sketch) }}</text>
|
||
<text class="body-text">{{ toText(wuxingBagua.bagua_profile) }}</text>
|
||
<text class="body-text">{{ toText(wuxingBagua.mutual_sketch) }}</text>
|
||
<text class="body-text strong-end">{{ toText(wuxingBagua.summary) }}</text>
|
||
<text v-if="hasNodes(wuxingBagua.details?.nodes)" class="section-hint">点击本段查看详解</text>
|
||
</view>
|
||
|
||
<!-- zodiac_sign -->
|
||
<view
|
||
v-if="hasZodiac"
|
||
class="section"
|
||
:class="{ 'section--click': hasNodes(zodiacSign.details?.nodes) }"
|
||
@click="hasNodes(zodiacSign.details?.nodes) && openDetail('属相', zodiacSign.details?.nodes)"
|
||
>
|
||
<text class="section-label">zodiac_sign · 属相</text>
|
||
<text class="headline">
|
||
{{ toText(zodiacSign.animal_icon) }} {{ toText(zodiacSign.animal) }}({{ toText(zodiacSign.earthly_branch) }})
|
||
</text>
|
||
<text class="body-text">{{ toText(zodiacSign.trait_summary) }}</text>
|
||
<text class="body-text">{{ toText(zodiacSign.name_harmony) }}</text>
|
||
<text v-if="hasNodes(zodiacSign.details?.nodes)" class="section-hint">点击本段查看属相详解</text>
|
||
</view>
|
||
|
||
<!-- career_plan -->
|
||
<view
|
||
v-if="hasCareerPlan"
|
||
class="section"
|
||
:class="{ 'section--click': hasNodes(careerPlan.details?.nodes) }"
|
||
@click="hasNodes(careerPlan.details?.nodes) && openDetail('事业规划', careerPlan.details?.nodes)"
|
||
>
|
||
<text class="section-label">career_plan · 事业规划</text>
|
||
<text class="body-text">{{ toText(careerPlan.summary) }}</text>
|
||
<view v-for="(ms, msi) in arr(careerPlan.milestones)" :key="msi" class="milestone">
|
||
<text class="milestone-title">{{ toText(ms?.phase) }}{{ toText(ms?.period) ? ' · ' + toText(ms.period) : '' }}</text>
|
||
<text v-if="toText(ms?.focus)" class="body-text small">重点:{{ toText(ms.focus) }}</text>
|
||
<text v-if="toText(ms?.advice)" class="body-text small">建议:{{ toText(ms.advice) }}</text>
|
||
</view>
|
||
<text v-if="hasNodes(careerPlan.details?.nodes)" class="section-hint">点击本段查看规划详解</text>
|
||
</view>
|
||
|
||
<!-- lucky_numbers -->
|
||
<view
|
||
v-if="hasLuckyNumbers"
|
||
class="section"
|
||
:class="{ 'section--click': hasNodes(luckyNumbers.details?.nodes) }"
|
||
@click="hasNodes(luckyNumbers.details?.nodes) && openDetail('幸运数字', luckyNumbers.details?.nodes)"
|
||
>
|
||
<text class="section-label">lucky_numbers · 幸运数字</text>
|
||
<text class="headline">首推:{{ toText(luckyNumbers.primary) }}</text>
|
||
<text class="body-text">{{ arr(luckyNumbers.numbers).join('、') }}</text>
|
||
<text class="body-text">{{ toText(luckyNumbers.meaning) }}</text>
|
||
<text v-if="hasNodes(luckyNumbers.details?.nodes)" class="section-hint">点击本段查看数字详解</text>
|
||
</view>
|
||
|
||
<!-- lucky_colors -->
|
||
<view
|
||
v-if="hasLuckyColors"
|
||
class="section"
|
||
:class="{ 'section--click': hasNodes(luckyColors.details?.nodes) }"
|
||
@click="hasNodes(luckyColors.details?.nodes) && openDetail('幸运色', luckyColors.details?.nodes)"
|
||
>
|
||
<text class="section-label">lucky_colors · 幸运色</text>
|
||
<text class="headline">主推:{{ toText(luckyColors.primary) }}</text>
|
||
<view class="color-row">
|
||
<view v-for="(c, ci) in arr(luckyColors.colors)" :key="ci" class="color-item">
|
||
<view class="color-swatch" :style="{ backgroundColor: toText(c?.hex) || '#333' }" />
|
||
<text class="body-text small">{{ toText(c?.name) }}{{ toText(c?.note) ? ' · ' + toText(c.note) : '' }}</text>
|
||
</view>
|
||
</view>
|
||
<text class="body-text">{{ toText(luckyColors.meaning) }}</text>
|
||
<text v-if="hasNodes(luckyColors.details?.nodes)" class="section-hint">点击本段查看用色详解</text>
|
||
</view>
|
||
</view>
|
||
</scroll-view>
|
||
|
||
<view v-if="props.showBusinessFortune !== false" class="footer-action">
|
||
<button class="fortune-btn" type="button" @click="emit('businessFortune', detailData)">查看商业运势</button>
|
||
</view>
|
||
|
||
<view v-if="showModal" class="modal-mask" @click="closeModal">
|
||
<view class="detail-modal" @click.stop>
|
||
<view class="detail-modal-card">
|
||
<text class="modal-title">{{ modalTitle }}</text>
|
||
<text class="close" @click="closeModal">×</text>
|
||
</view>
|
||
<scroll-view scroll-y class="detail-modal-body">
|
||
<view v-for="(node, idx) in modalNodes" :key="idx" class="node">
|
||
<text v-if="node?.type === 'text'" class="line">{{ toText(node.text) }}</text>
|
||
<view v-else-if="node?.type === 'list'">
|
||
<text v-for="(item, j) in arr(node.items)" :key="j" class="line">- {{ toText(item) }}</text>
|
||
</view>
|
||
<view v-else-if="node?.type === 'kv'">
|
||
<text v-for="(item, j) in arr(node.items)" :key="j" class="line">{{ toText(item?.label) }}:{{ toText(item?.value) }}</text>
|
||
</view>
|
||
</view>
|
||
</scroll-view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { computed, ref } from "vue";
|
||
import SixDimensionRadarDesktopEchart from "../SixDimensionRadarDesktopEchart.vue";
|
||
|
||
const props = defineProps<{
|
||
data: any;
|
||
showBusinessFortune?: boolean;
|
||
}>();
|
||
|
||
const emit = defineEmits<{
|
||
back: [];
|
||
businessFortune: [any];
|
||
}>();
|
||
|
||
const parseMaybeJson = (value: any) => {
|
||
if (value && typeof value === "object") return value;
|
||
if (typeof value !== "string") return {};
|
||
try {
|
||
return JSON.parse(value);
|
||
} catch {
|
||
return {};
|
||
}
|
||
};
|
||
const toText = (v: any) => String(v ?? "").trim();
|
||
const num = (v: any, fallback = 0) => {
|
||
const n = Number(v);
|
||
return Number.isFinite(n) ? n : fallback;
|
||
};
|
||
const arr = (v: any) => (Array.isArray(v) ? v : []);
|
||
const hasNodes = (nodes: any) => arr(nodes).length > 0;
|
||
|
||
const detailData = computed(() => parseMaybeJson(props.data));
|
||
const header = computed(() => detailData.value?.header || {});
|
||
const characterAnalysis = computed(() => detailData.value?.characterAnalysis || {});
|
||
const businessPattern = computed(() => detailData.value?.businessPattern || {});
|
||
const gua = computed(() => detailData.value?.gua || {});
|
||
const team = computed(() => detailData.value?.team || {});
|
||
const years = computed(() => detailData.value?.years || {});
|
||
const wealthTrend = computed(() => detailData.value?.wealthTrend || {});
|
||
const direction = computed(() => detailData.value?.direction || {});
|
||
const layout = computed(() => detailData.value?.layout || {});
|
||
const execution = computed(() => detailData.value?.execution || {});
|
||
|
||
const liuyao = computed(() => detailData.value?.liuyao || {});
|
||
const wuxingBagua = computed(() => detailData.value?.wuxing_bagua || {});
|
||
const zodiacSign = computed(() => detailData.value?.zodiac_sign || {});
|
||
const careerPlan = computed(() => detailData.value?.career_plan || {});
|
||
const luckyNumbers = computed(() => detailData.value?.lucky_numbers || {});
|
||
const luckyColors = computed(() => detailData.value?.lucky_colors || {});
|
||
|
||
const summaryText = computed(() =>
|
||
arr(businessPattern.value?.summary)
|
||
.map((x: any) => `${toText(x?.label)} ${toText(x?.value)}`)
|
||
.filter(Boolean)
|
||
.join(" · "),
|
||
);
|
||
|
||
const hasLiuyao = computed(
|
||
() =>
|
||
!!(
|
||
toText(liuyao.value?.hexagram_title) ||
|
||
toText(liuyao.value?.changing_summary) ||
|
||
toText(liuyao.value?.interpretation) ||
|
||
arr(liuyao.value?.yao_lines).length ||
|
||
hasNodes(liuyao.value?.details?.nodes)
|
||
),
|
||
);
|
||
const hasWuxingBagua = computed(
|
||
() =>
|
||
!!(
|
||
toText(wuxingBagua.value?.wuxing_sketch) ||
|
||
toText(wuxingBagua.value?.bagua_profile) ||
|
||
toText(wuxingBagua.value?.mutual_sketch) ||
|
||
toText(wuxingBagua.value?.summary) ||
|
||
hasNodes(wuxingBagua.value?.details?.nodes)
|
||
),
|
||
);
|
||
const hasZodiac = computed(
|
||
() =>
|
||
!!(
|
||
toText(zodiacSign.value?.animal) ||
|
||
toText(zodiacSign.value?.trait_summary) ||
|
||
toText(zodiacSign.value?.name_harmony) ||
|
||
hasNodes(zodiacSign.value?.details?.nodes)
|
||
),
|
||
);
|
||
const hasCareerPlan = computed(
|
||
() =>
|
||
!!(
|
||
toText(careerPlan.value?.summary) ||
|
||
arr(careerPlan.value?.milestones).length ||
|
||
hasNodes(careerPlan.value?.details?.nodes)
|
||
),
|
||
);
|
||
const hasLuckyNumbers = computed(
|
||
() =>
|
||
!!(toText(luckyNumbers.value?.primary) || arr(luckyNumbers.value?.numbers).length || toText(luckyNumbers.value?.meaning)),
|
||
);
|
||
const hasLuckyColors = computed(
|
||
() =>
|
||
!!(
|
||
toText(luckyColors.value?.primary) ||
|
||
arr(luckyColors.value?.colors).length ||
|
||
toText(luckyColors.value?.meaning)
|
||
),
|
||
);
|
||
|
||
const showModal = ref(false);
|
||
const modalTitle = ref("");
|
||
const modalNodes = ref<any[]>([]);
|
||
const openDetail = (title: string, nodes: any[]) => {
|
||
const list = arr(nodes);
|
||
if (!list.length) return;
|
||
modalTitle.value = toText(title) || "详情";
|
||
modalNodes.value = list;
|
||
showModal.value = true;
|
||
};
|
||
const closeModal = () => {
|
||
showModal.value = false;
|
||
};
|
||
</script>
|
||
|
||
<style scoped>
|
||
.company-desktop-detail {
|
||
min-height: 100%;
|
||
height: 100%;
|
||
display: flex;
|
||
flex-direction: column;
|
||
background: linear-gradient(165deg, #070a12 0%, #12102a 42%, #0a1628 100%);
|
||
color: #e8e4dc;
|
||
}
|
||
|
||
.detail-header {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: 12px 16px;
|
||
background: rgba(15, 23, 42, 0.72);
|
||
border-bottom: 1px solid rgba(212, 175, 55, 0.2);
|
||
flex-shrink: 0;
|
||
}
|
||
.detail-header-back {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 6px;
|
||
color: #d4af37;
|
||
}
|
||
.detail-header-title {
|
||
font-size: 16px;
|
||
font-weight: 700;
|
||
color: #f2e6d8;
|
||
}
|
||
.detail-header-placeholder {
|
||
width: 48px;
|
||
}
|
||
|
||
.detail-content {
|
||
flex: 1;
|
||
min-height: 0;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.report-body {
|
||
max-width: 820px;
|
||
margin: 0 auto;
|
||
padding: 16px 18px 20px;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.section {
|
||
margin-bottom: 16px;
|
||
padding: 14px 16px;
|
||
border-radius: 12px;
|
||
background: rgba(15, 23, 42, 0.52);
|
||
border: 1px solid rgba(212, 175, 55, 0.14);
|
||
border-left: 3px solid rgba(212, 175, 55, 0.45);
|
||
backdrop-filter: blur(8px);
|
||
}
|
||
.section--wide {
|
||
max-width: 100%;
|
||
}
|
||
.section--click {
|
||
cursor: pointer;
|
||
}
|
||
.section--click:active {
|
||
opacity: 0.92;
|
||
}
|
||
|
||
.section-label {
|
||
display: block;
|
||
font-size: 11px;
|
||
letter-spacing: 0.06em;
|
||
color: rgba(212, 175, 55, 0.75);
|
||
margin-bottom: 10px;
|
||
font-weight: 600;
|
||
}
|
||
|
||
/* 商业六维内嵌 ECharts 组件自带外边距,报告式布局里收紧 */
|
||
:deep(.sixdim-section) {
|
||
margin-bottom: 0 !important;
|
||
}
|
||
|
||
.score-row {
|
||
display: flex;
|
||
align-items: baseline;
|
||
justify-content: space-between;
|
||
margin-bottom: 8px;
|
||
}
|
||
.name {
|
||
font-size: 22px;
|
||
font-weight: 800;
|
||
color: #f2e6d8;
|
||
}
|
||
.score {
|
||
font-size: 32px;
|
||
font-weight: 800;
|
||
color: #d4af37;
|
||
}
|
||
|
||
.tag-row,
|
||
.tag-list {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 8px;
|
||
margin-bottom: 10px;
|
||
}
|
||
.pill {
|
||
font-size: 11px;
|
||
padding: 4px 10px;
|
||
border-radius: 999px;
|
||
background: rgba(212, 175, 55, 0.12);
|
||
border: 1px solid rgba(212, 175, 55, 0.28);
|
||
color: #ede6d8;
|
||
}
|
||
.pill--soft {
|
||
background: rgba(255, 255, 255, 0.06);
|
||
border-color: rgba(148, 163, 184, 0.28);
|
||
color: rgba(232, 228, 220, 0.9);
|
||
}
|
||
|
||
.body-text {
|
||
display: block;
|
||
font-size: 13px;
|
||
line-height: 1.55;
|
||
color: rgba(232, 228, 220, 0.92);
|
||
margin-bottom: 8px;
|
||
}
|
||
.body-text.small {
|
||
font-size: 12px;
|
||
color: rgba(232, 228, 220, 0.82);
|
||
}
|
||
.body-text.note {
|
||
font-style: italic;
|
||
color: rgba(212, 175, 55, 0.65);
|
||
}
|
||
.mono {
|
||
font-family: ui-monospace, monospace;
|
||
}
|
||
.strong-end {
|
||
font-weight: 600;
|
||
color: #f0dba9;
|
||
}
|
||
|
||
.headline {
|
||
display: block;
|
||
font-size: 15px;
|
||
font-weight: 700;
|
||
color: #f4e5c4;
|
||
margin-bottom: 8px;
|
||
}
|
||
.gua-bg {
|
||
display: block;
|
||
font-size: 12px;
|
||
color: rgba(212, 175, 55, 0.8);
|
||
margin-bottom: 6px;
|
||
}
|
||
|
||
.section-hint {
|
||
display: block;
|
||
margin-top: 8px;
|
||
font-size: 11px;
|
||
color: rgba(148, 163, 184, 0.85);
|
||
}
|
||
.section-link {
|
||
margin-top: 10px;
|
||
padding-top: 10px;
|
||
border-top: 1px solid rgba(212, 175, 55, 0.12);
|
||
font-size: 12px;
|
||
color: #d4af37;
|
||
}
|
||
|
||
.char-grid {
|
||
display: grid;
|
||
grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
|
||
gap: 10px;
|
||
margin-bottom: 12px;
|
||
}
|
||
.char-box {
|
||
padding: 10px;
|
||
border-radius: 10px;
|
||
background: rgba(2, 6, 23, 0.4);
|
||
border: 1px solid rgba(212, 175, 55, 0.12);
|
||
}
|
||
.char-single {
|
||
font-size: 22px;
|
||
font-weight: 800;
|
||
}
|
||
.char-meta {
|
||
display: block;
|
||
font-size: 11px;
|
||
color: rgba(203, 213, 225, 0.8);
|
||
margin: 4px 0 6px;
|
||
}
|
||
|
||
.kv-inline {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 8px;
|
||
margin-top: 12px;
|
||
}
|
||
.summary-chip {
|
||
padding: 6px 10px;
|
||
border-radius: 8px;
|
||
background: rgba(2, 6, 23, 0.45);
|
||
border: 1px solid rgba(148, 163, 184, 0.22);
|
||
}
|
||
.chip-k {
|
||
font-size: 11px;
|
||
color: rgba(203, 213, 225, 0.85);
|
||
margin-right: 6px;
|
||
}
|
||
.chip-v {
|
||
font-size: 12px;
|
||
font-weight: 700;
|
||
color: #f0dba9;
|
||
}
|
||
|
||
.member-block {
|
||
margin-bottom: 10px;
|
||
padding-bottom: 10px;
|
||
border-bottom: 1px solid rgba(255, 255, 255, 0.06);
|
||
}
|
||
.member-block:last-of-type {
|
||
border-bottom: none;
|
||
}
|
||
.member-line {
|
||
font-size: 13px;
|
||
font-weight: 600;
|
||
color: #f2e6d8;
|
||
}
|
||
|
||
.year-row {
|
||
display: grid;
|
||
grid-template-columns: 56px 52px 1fr;
|
||
gap: 8px;
|
||
align-items: start;
|
||
margin-bottom: 8px;
|
||
font-size: 12px;
|
||
}
|
||
.year-key {
|
||
color: #d4af37;
|
||
font-weight: 700;
|
||
}
|
||
.year-luck {
|
||
color: #a7f3d0;
|
||
}
|
||
|
||
.layout-line {
|
||
margin-bottom: 10px;
|
||
}
|
||
.layout-strong {
|
||
display: block;
|
||
font-size: 13px;
|
||
font-weight: 700;
|
||
color: #f0dba9;
|
||
margin-bottom: 4px;
|
||
}
|
||
.highlight {
|
||
color: #fde68a;
|
||
margin: 0 2px;
|
||
font-size: 12px;
|
||
}
|
||
.layout-flow {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
align-items: baseline;
|
||
gap: 2px 6px;
|
||
}
|
||
|
||
.bars {
|
||
height: 96px;
|
||
display: flex;
|
||
align-items: flex-end;
|
||
gap: 6px;
|
||
margin: 12px 0;
|
||
}
|
||
.bar-wrap {
|
||
flex: 1;
|
||
height: 100%;
|
||
border-radius: 6px;
|
||
background: rgba(255, 255, 255, 0.06);
|
||
overflow: hidden;
|
||
display: flex;
|
||
align-items: flex-end;
|
||
}
|
||
.bar {
|
||
width: 100%;
|
||
background: linear-gradient(180deg, rgba(255, 205, 96, 0.9), rgba(230, 129, 38, 0.78));
|
||
}
|
||
|
||
.milestone {
|
||
margin-top: 10px;
|
||
padding: 10px;
|
||
border-radius: 10px;
|
||
background: rgba(2, 6, 23, 0.35);
|
||
border: 1px solid rgba(212, 175, 55, 0.1);
|
||
}
|
||
.milestone-title {
|
||
display: block;
|
||
font-size: 13px;
|
||
font-weight: 700;
|
||
color: #f4e5c4;
|
||
margin-bottom: 6px;
|
||
}
|
||
|
||
.color-row {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 12px;
|
||
margin: 10px 0;
|
||
}
|
||
.color-item {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
}
|
||
.color-swatch {
|
||
width: 28px;
|
||
height: 28px;
|
||
border-radius: 8px;
|
||
border: 1px solid rgba(255, 255, 255, 0.2);
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.footer-action {
|
||
padding: 10px 18px 14px;
|
||
flex-shrink: 0;
|
||
max-width: 820px;
|
||
width: 100%;
|
||
margin: 0 auto;
|
||
box-sizing: border-box;
|
||
}
|
||
.fortune-btn {
|
||
width: 100%;
|
||
border-radius: 10px;
|
||
padding: 10px 12px;
|
||
background: linear-gradient(135deg, rgba(139, 35, 35, 0.95), rgba(90, 20, 20, 0.98));
|
||
color: #fdfbf7;
|
||
border: 1px solid rgba(212, 175, 55, 0.35);
|
||
}
|
||
|
||
.modal-mask {
|
||
position: fixed;
|
||
inset: 0;
|
||
z-index: 3200;
|
||
background: rgba(2, 6, 23, 0.72);
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 16px;
|
||
box-sizing: border-box;
|
||
}
|
||
.detail-modal {
|
||
width: min(640px, 100%);
|
||
max-height: min(82vh, 760px);
|
||
background: rgba(10, 12, 20, 0.96);
|
||
border: 1px solid rgba(212, 175, 55, 0.2);
|
||
border-radius: 12px;
|
||
overflow: hidden;
|
||
}
|
||
.detail-modal-card {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
padding: 10px 12px;
|
||
border-bottom: 1px solid rgba(212, 175, 55, 0.16);
|
||
}
|
||
.modal-title {
|
||
color: #d4af37;
|
||
font-size: 14px;
|
||
font-weight: 700;
|
||
}
|
||
.close {
|
||
color: #d4af37;
|
||
font-size: 20px;
|
||
}
|
||
.detail-modal-body {
|
||
max-height: calc(min(82vh, 760px) - 48px);
|
||
padding: 12px;
|
||
box-sizing: border-box;
|
||
}
|
||
.node {
|
||
margin-bottom: 8px;
|
||
}
|
||
.line {
|
||
display: block;
|
||
font-size: 13px;
|
||
line-height: 1.5;
|
||
color: rgba(232, 228, 220, 0.9);
|
||
margin-bottom: 6px;
|
||
}
|
||
</style>
|