|
|
@@ -5,17 +5,17 @@
|
|
|
<view class="sandbox-header">
|
|
|
<image class="sandbox-logo" src="/static/logo.png" mode="aspectFit"></image>
|
|
|
<text class="sandbox-title">浠艾福能量沙盘</text>
|
|
|
- <!-- 右上角:live 模式显示个人/全家切换,preview 模式显示徽章文案 -->
|
|
|
- <view class="sandbox-switch" v-if="mode !== 'preview'" @click="onToggle">
|
|
|
- <text class="sandbox-switch-icon">{{ activeMemberIcon }}</text>
|
|
|
+ <!-- 右上角:live 模式显示个人/全家切换(preview 为轻量引导条,徽章移入引导条) -->
|
|
|
+ <view class="sandbox-switch" v-if="!isPreview" @click="onToggle">
|
|
|
+ <image class="sandbox-switch-icon" :src="activeMemberIcon" mode="aspectFit"></image>
|
|
|
<text class="sandbox-switch-label">{{ activeMemberLabel }}</text>
|
|
|
- <text class="sandbox-switch-arrow">⇄</text>
|
|
|
+ <image class="sandbox-switch-arrow" :src="uiIcons.swap" mode="aspectFit"></image>
|
|
|
</view>
|
|
|
- <text class="sandbox-badge" v-else>{{ displayBadgeText }}</text>
|
|
|
</view>
|
|
|
</slot>
|
|
|
|
|
|
- <view class="sandbox-star" :style="{height: starHeight}">
|
|
|
+ <!-- live:完整星图(双 Canvas + 点击感应层) -->
|
|
|
+ <view class="sandbox-star" v-if="!isPreview" :style="{height: starHeight}">
|
|
|
<view class="star-glow-bg"></view>
|
|
|
|
|
|
<!-- Canvas 2D 五行星图 -->
|
|
|
@@ -27,71 +27,63 @@
|
|
|
<!-- Canvas 点击感应层 -->
|
|
|
<view class="canvas-tap-area" @click="onCanvasTap"></view>
|
|
|
|
|
|
- <!-- 顶点:从 sortedDimensions 顺时针排 [心, 身, 智, 富, 行] -->
|
|
|
- <view class="star-point star-point--top star-point--row" @click="onPointClick(sortedDimensions[0].code)">
|
|
|
- <view class="point-dot" :class="'point-dot--' + dimElementColor(sortedDimensions[0].code)">
|
|
|
- <text class="point-icon">{{ sortedDimensions[0].icon }}</text>
|
|
|
+ <!-- 顶点:sortedDimensions 顺时针 [心, 身, 智, 富, 行](图标形状承载五行语义) -->
|
|
|
+ <view
|
|
|
+ v-for="pt in sortedDimensions"
|
|
|
+ :key="pt.code"
|
|
|
+ class="star-point"
|
|
|
+ :class="pt.pointClass"
|
|
|
+ @click="onPointClick(pt.code)"
|
|
|
+ >
|
|
|
+ <view class="point-dot" :class="pt.dotClass">
|
|
|
+ <image class="point-icon" :src="pt.iconUri" mode="aspectFit"></image>
|
|
|
</view>
|
|
|
- <text class="point-label">{{ sortedDimensions[0].name }}</text>
|
|
|
- <text class="point-energy">{{ sortedDimensions[0].energy }}</text>
|
|
|
- </view>
|
|
|
- <view class="star-point star-point--right" @click="onPointClick(sortedDimensions[1].code)">
|
|
|
- <view class="point-dot" :class="'point-dot--' + dimElementColor(sortedDimensions[1].code)">
|
|
|
- <text class="point-icon">{{ sortedDimensions[1].icon }}</text>
|
|
|
- </view>
|
|
|
- <text class="point-label">{{ sortedDimensions[1].name }}</text>
|
|
|
- <text class="point-energy">{{ sortedDimensions[1].energy }}</text>
|
|
|
- </view>
|
|
|
- <view class="star-point star-point--lr star-point--row" @click="onPointClick(sortedDimensions[2].code)">
|
|
|
- <view class="point-dot" :class="'point-dot--' + dimElementColor(sortedDimensions[2].code)">
|
|
|
- <text class="point-icon">{{ sortedDimensions[2].icon }}</text>
|
|
|
- </view>
|
|
|
- <text class="point-label">{{ sortedDimensions[2].name }}</text>
|
|
|
- <text class="point-energy">{{ sortedDimensions[2].energy }}</text>
|
|
|
- </view>
|
|
|
- <view class="star-point star-point--ll star-point--rev" @click="onPointClick(sortedDimensions[3].code)">
|
|
|
- <view class="point-dot" :class="'point-dot--' + dimElementColor(sortedDimensions[3].code)">
|
|
|
- <text class="point-icon">{{ sortedDimensions[3].icon }}</text>
|
|
|
- </view>
|
|
|
- <text class="point-label">{{ sortedDimensions[3].name }}</text>
|
|
|
- <text class="point-energy">{{ sortedDimensions[3].energy }}</text>
|
|
|
- </view>
|
|
|
- <view class="star-point star-point--left" @click="onPointClick(sortedDimensions[4].code)">
|
|
|
- <view class="point-dot" :class="'point-dot--' + dimElementColor(sortedDimensions[4].code)">
|
|
|
- <text class="point-icon">{{ sortedDimensions[4].icon }}</text>
|
|
|
- </view>
|
|
|
- <text class="point-label">{{ sortedDimensions[4].name }}</text>
|
|
|
- <text class="point-energy">{{ sortedDimensions[4].energy }}</text>
|
|
|
+ <text class="point-label">{{ pt.name }}</text>
|
|
|
+ <text class="point-energy" :class="pt.energyClass">{{ pt.energy }}</text>
|
|
|
</view>
|
|
|
|
|
|
<!-- 中心点击区域(太极由 Canvas 绘制) -->
|
|
|
<view class="star-center" @click="onCenterClick"></view>
|
|
|
</view>
|
|
|
|
|
|
+ <!-- preview:轻量引导条(标题 + 徽章 + 弱化五边形轮廓,不画完整星图) -->
|
|
|
+ <view class="sandbox-preview" v-else @click="onPreviewTap">
|
|
|
+ <image class="preview-pentagon" :src="uiIcons.pentagon" mode="aspectFit"></image>
|
|
|
+ <view class="preview-copy">
|
|
|
+ <text class="preview-title">五维能量沙盘</text>
|
|
|
+ <text class="preview-sub">亲子共同成长的能量地图</text>
|
|
|
+ </view>
|
|
|
+ <text class="preview-badge">{{ displayBadgeText }}</text>
|
|
|
+ </view>
|
|
|
+
|
|
|
<!-- dimension-bar slot -->
|
|
|
- <slot name="dimension-bar" v-if="showDimensionBar && mode !== 'preview'">
|
|
|
+ <slot name="dimension-bar" v-if="showDimensionBar && !isPreview">
|
|
|
<view class="dimension-bar">
|
|
|
- <view class="dim-item dim-item--earth">🌏身 {{ activeScores[0] }}%</view>
|
|
|
- <view class="dim-item dim-item--fire">🔥心 {{ activeScores[1] }}%</view>
|
|
|
- <view class="dim-item dim-item--metal">⚡智 {{ activeScores[2] }}%</view>
|
|
|
- <view class="dim-item dim-item--wood">🌿行 {{ activeScores[3] }}%</view>
|
|
|
- <view class="dim-item dim-item--water">💧富 {{ activeScores[4] }}%</view>
|
|
|
+ <view
|
|
|
+ v-for="item in linearDimensions"
|
|
|
+ :key="item.code"
|
|
|
+ class="dim-item"
|
|
|
+ :class="item.itemClass"
|
|
|
+ >
|
|
|
+ <image class="dim-item-icon" :src="item.iconUri" mode="aspectFit"></image>
|
|
|
+ <text class="dim-item-text">{{ item.name }} {{ item.energy }}%</text>
|
|
|
+ </view>
|
|
|
</view>
|
|
|
</slot>
|
|
|
|
|
|
- <!-- 右上角成员选择面板 -->
|
|
|
+ <!-- 成员选择面板 -->
|
|
|
<view v-if="memberPickerVisible" class="member-picker-mask" @click="memberPickerVisible = false">
|
|
|
<view class="member-picker-panel" @click.stop>
|
|
|
<view class="member-picker-title">切换视角</view>
|
|
|
<view
|
|
|
- v-for="option in memberOptions"
|
|
|
+ v-for="option in memberOptionsActive"
|
|
|
:key="option.key"
|
|
|
class="member-picker-item"
|
|
|
- :class="{ 'member-picker-item--active': isOptionActive(option) }"
|
|
|
+ :class="{ 'member-picker-item--active': option.active }"
|
|
|
@click="selectOption(option)"
|
|
|
>
|
|
|
<text class="member-picker-label">{{ option.label }}</text>
|
|
|
- <text class="member-picker-check" v-if="isOptionActive(option)">✓</text>
|
|
|
+ <image class="member-picker-check" v-if="option.active" :src="uiIcons.check" mode="aspectFit"></image>
|
|
|
</view>
|
|
|
</view>
|
|
|
</view>
|
|
|
@@ -112,20 +104,116 @@ import {
|
|
|
resolveSandboxScores
|
|
|
} from '@/utils/wuxing-sandbox.js'
|
|
|
|
|
|
-var DIM_KEYS = ['body', 'mind', 'wisdom', 'action', 'wealth']
|
|
|
-
|
|
|
-/** 维度 → 五行映射(API 缺字段时的兜底) */
|
|
|
+/**
|
|
|
+ * 五行图标(内联 SVG,24×24 viewBox / stroke-width 1.8 / 无填充)
|
|
|
+ *
|
|
|
+ * mp-weixin WXML 不支持模板内联 <svg>,故用 data:image/svg+xml 作为 <image> src
|
|
|
+ * (仓库既有模式:pages/shop/order-list/order-list.vue)。SVG 文档是独立渲染上下文,
|
|
|
+ * currentColor 无法继承宿主 CSS,故 stroke 颜色在此处按 $dim-data-* / $brand-primary-deep
|
|
|
+ * 词表取色(与 uni.scss 令牌一一对应,注释映射;Canvas/JS 侧无法使用 SCSS 变量)。
|
|
|
+ *
|
|
|
+ * 五行语义由形状承载:心=火焰 身=山 智=闪电 富=水滴 行=叶。
|
|
|
+ */
|
|
|
+function svgUri(paths, color) {
|
|
|
+ var inner = ''
|
|
|
+ for (var i = 0; i < paths.length; i++) {
|
|
|
+ inner += '<path d="' + paths[i] + '"/>'
|
|
|
+ }
|
|
|
+ var svg = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="' +
|
|
|
+ color + '" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">' + inner + '</svg>'
|
|
|
+ return 'data:image/svg+xml,' + encodeURIComponent(svg)
|
|
|
+}
|
|
|
+
|
|
|
+var ICON_PATHS = {
|
|
|
+ flame: [
|
|
|
+ 'M12 2.8c1.9 2.7 3.5 4.9 3.5 7.7a3.5 3.5 0 0 1-7 0c0-1.4.6-2.6 1.7-3.7.2 1.2.9 2 1.9 2.4-.6-2.3 0-4.6-.1-6.4z',
|
|
|
+ 'M12 7.6c1 1.4 1.7 2.4 1.7 3.7a1.7 1.7 0 0 1-3.4 0c0-1.3.7-2.3 1.7-3.7z'
|
|
|
+ ],
|
|
|
+ mountain: [
|
|
|
+ 'M2.8 19.2 8.8 8.6l3.4 5.6 2.2-3.6 6.8 8.6z'
|
|
|
+ ],
|
|
|
+ lightning: [
|
|
|
+ 'M13.4 2.6 5.8 13.4h4.9l-1 8 7.6-10.8h-4.9z'
|
|
|
+ ],
|
|
|
+ droplet: [
|
|
|
+ 'M12 2.8c3.2 3.8 5.2 6.5 5.2 9.2a5.2 5.2 0 0 1-10.4 0c0-2.7 2-5.4 5.2-9.2z'
|
|
|
+ ],
|
|
|
+ leaf: [
|
|
|
+ 'M5.6 18.6C6 11.4 11.6 5.2 19.6 4.6c.4 8.2-5.6 14.2-14 14z',
|
|
|
+ 'M7 17c2.6-4.3 6-7.4 10-9.6'
|
|
|
+ ],
|
|
|
+ person: [
|
|
|
+ 'M12 11.6a3.4 3.4 0 1 0 0-6.8 3.4 3.4 0 0 0 0 6.8z',
|
|
|
+ 'M5.8 20.2c.5-3.5 3-5.2 6.2-5.2s5.7 1.7 6.2 5.2'
|
|
|
+ ],
|
|
|
+ family: [
|
|
|
+ 'M8.6 12.2a3 3 0 1 0 0-6 3 3 0 0 0 0 6z',
|
|
|
+ 'M3.4 19.6c.4-3.1 2.6-4.6 5.2-4.6s4.8 1.5 5.2 4.6',
|
|
|
+ 'M17.4 8.6a2.2 2.2 0 1 0 0-4.4 2.2 2.2 0 0 0 0 4.4z',
|
|
|
+ 'M17.8 15.2c1.4.3 2.8 1.6 2.8 3.6'
|
|
|
+ ],
|
|
|
+ swap: [
|
|
|
+ 'M4.4 9.4h14.2',
|
|
|
+ 'M15.6 6.6l3 2.8-3 2.8',
|
|
|
+ 'M19.6 14.6H5.4',
|
|
|
+ 'M8.4 11.8l-3 2.8 3 2.8'
|
|
|
+ ],
|
|
|
+ check: [
|
|
|
+ 'M5 12.8 9.6 17.4 19 7.6'
|
|
|
+ ],
|
|
|
+ pentagon: [
|
|
|
+ 'M12 3.4 20.8 9.2l-3.4 10.2H6.6L3.2 9.2z'
|
|
|
+ ]
|
|
|
+}
|
|
|
+
|
|
|
+// 数据笔触深档(与 uni.scss $dim-data-* 一致)—— 图标颜色 = 数据笔触色,保证对填充 #FCE7CE ≥3:1
|
|
|
+var DIM_ICON_URIS = {
|
|
|
+ mind: svgUri(ICON_PATHS.flame, '#9D174D'), // $dim-data-mind #9D174D
|
|
|
+ body: svgUri(ICON_PATHS.mountain, '#9C4A1A'), // $dim-data-body #9C4A1A
|
|
|
+ wisdom: svgUri(ICON_PATHS.lightning,'#4338CA'), // $dim-data-wisdom #4338CA
|
|
|
+ wealth: svgUri(ICON_PATHS.droplet, '#92400E'), // $dim-data-wealth #92400E
|
|
|
+ action: svgUri(ICON_PATHS.leaf, '#047857') // $dim-data-action #047857
|
|
|
+}
|
|
|
+
|
|
|
+// UI 图标(品牌深橙,对白底 / 品牌浅底均 ≥3:1;$brand-primary-deep #C2410C)
|
|
|
+var UI_ICON_URIS = {
|
|
|
+ person: svgUri(ICON_PATHS.person, '#C2410C'),
|
|
|
+ family: svgUri(ICON_PATHS.family, '#C2410C'),
|
|
|
+ swap: svgUri(ICON_PATHS.swap, '#C2410C'),
|
|
|
+ check: svgUri(ICON_PATHS.check, '#C2410C'),
|
|
|
+ pentagon: svgUri(ICON_PATHS.pentagon, '#C2410C')
|
|
|
+}
|
|
|
+
|
|
|
+/** 环形顶点定位类(与 sortedDimensions 序一一对应:上/右/右下/左下/左) */
|
|
|
+var RING_POS = [
|
|
|
+ 'star-point--top star-point--row',
|
|
|
+ 'star-point--right',
|
|
|
+ 'star-point--lr star-point--row',
|
|
|
+ 'star-point--ll star-point--rev',
|
|
|
+ 'star-point--left'
|
|
|
+]
|
|
|
+
|
|
|
+/** 线性维度条顺序(规格 §4.2):身 -> 智 -> 富 -> 行 -> 心;idx = activeScores 下标 */
|
|
|
+var LINEAR_ORDER = [
|
|
|
+ { code: 'body', idx: 0 },
|
|
|
+ { code: 'wisdom', idx: 2 },
|
|
|
+ { code: 'wealth', idx: 4 },
|
|
|
+ { code: 'action', idx: 3 },
|
|
|
+ { code: 'mind', idx: 1 }
|
|
|
+]
|
|
|
+
|
|
|
+/** 维度 -> 五行映射(API 缺字段时的兜底;图标一律用内置 SVG,忽略接口返回的 emoji) */
|
|
|
var DIM_META = {
|
|
|
- mind: { name: '心', icon: '🔥', element: '火', color: 'fire' },
|
|
|
- action: { name: '行', icon: '🌿', element: '木', color: 'wood' },
|
|
|
- wealth: { name: '富', icon: '💧', element: '水', color: 'water' },
|
|
|
- wisdom: { name: '智', icon: '⚡', element: '金', color: 'metal' },
|
|
|
- body: { name: '身', icon: '🌏', element: '土', color: 'earth' }
|
|
|
+ mind: { name: '心', element: '火' },
|
|
|
+ body: { name: '身', element: '土' },
|
|
|
+ wisdom: { name: '智', element: '金' },
|
|
|
+ wealth: { name: '富', element: '水' },
|
|
|
+ action: { name: '行', element: '木' }
|
|
|
}
|
|
|
|
|
|
export default {
|
|
|
props: {
|
|
|
- /** 模式:'preview' 随机数据 / 'live' 真实数据 */
|
|
|
+ /** 模式:'preview' 引导条 / 'live' 真实数据 */
|
|
|
mode: {
|
|
|
type: String,
|
|
|
default: 'preview',
|
|
|
@@ -216,7 +304,8 @@ export default {
|
|
|
animWealth: 0,
|
|
|
_animator: null,
|
|
|
_flowAnim: null,
|
|
|
- _flowCanvasReady: false
|
|
|
+ _flowCanvasReady: false,
|
|
|
+ uiIcons: UI_ICON_URIS
|
|
|
}
|
|
|
},
|
|
|
computed: {
|
|
|
@@ -229,6 +318,20 @@ export default {
|
|
|
memberOptions: function() {
|
|
|
return buildMemberOptions(this.members, this.personalData)
|
|
|
},
|
|
|
+ /** 成员选择选项(预计算 active 标志,避免模板 :class 中调用方法) */
|
|
|
+ memberOptionsActive: function() {
|
|
|
+ return this.memberOptions.map(function(option) {
|
|
|
+ var active = option.viewMode === this.viewMode &&
|
|
|
+ (option.viewMode !== 'member' || String(option.memberId) === String(this.selectedMemberId))
|
|
|
+ return {
|
|
|
+ key: option.key,
|
|
|
+ label: option.label,
|
|
|
+ viewMode: option.viewMode,
|
|
|
+ memberId: option.memberId,
|
|
|
+ active: active
|
|
|
+ }
|
|
|
+ }, this)
|
|
|
+ },
|
|
|
totalMemberCount: function() {
|
|
|
if (this.memberCount > 0) return this.memberCount
|
|
|
return this.members ? this.members.length : 0
|
|
|
@@ -254,7 +357,7 @@ export default {
|
|
|
return '本人'
|
|
|
},
|
|
|
activeMemberIcon: function() {
|
|
|
- return this.viewMode === 'family' ? '👨👩👧👦' : '👤'
|
|
|
+ return this.viewMode === 'family' ? this.uiIcons.family : this.uiIcons.person
|
|
|
},
|
|
|
/** 当前活跃的五维值数组 [body, mind, wisdom, action, wealth] */
|
|
|
activeScores: function() {
|
|
|
@@ -262,23 +365,20 @@ export default {
|
|
|
return resolveSandboxScores(this.viewMode, this.scores, this.personalData, this.currentMember)
|
|
|
},
|
|
|
activeOverall: function() {
|
|
|
- if (this.isPreview) {
|
|
|
- var s = this.previewScores
|
|
|
- return Math.round((s[0] + s[1] + s[2] + s[3] + s[4]) / 5)
|
|
|
- }
|
|
|
+ if (this.isPreview) return 0
|
|
|
return resolveSandboxOverall(this.viewMode, this.scores, this.personalData, this.currentMember)
|
|
|
},
|
|
|
+ /**
|
|
|
+ * 动画目标值 ts,按环形顶点序 [mind, body, wisdom, wealth, action] 排列
|
|
|
+ * (与 render.js DIM_RING / sortedDimensions 顺序一致,不可改)
|
|
|
+ */
|
|
|
activeTs: function() {
|
|
|
- return [
|
|
|
- this.activeScores[0] / 100,
|
|
|
- this.activeScores[1] / 100,
|
|
|
- this.activeScores[2] / 100,
|
|
|
- this.activeScores[3] / 100,
|
|
|
- this.activeScores[4] / 100
|
|
|
- ]
|
|
|
+ var s = this.activeScores
|
|
|
+ return [s[1] / 100, s[0] / 100, s[2] / 100, s[4] / 100, s[3] / 100]
|
|
|
},
|
|
|
displayBadgeText: function() {
|
|
|
if (this.badgeText) return this.badgeText
|
|
|
+ if (this.isPreview) return '登录查看完整报告'
|
|
|
var label = this.viewMode === 'family' ? '家庭能量' : (this.activeMemberLabel + '能量')
|
|
|
return label + ' ' + (this.activeOverall || 0) + '%'
|
|
|
},
|
|
|
@@ -288,18 +388,9 @@ export default {
|
|
|
hasMultipleMembers: function() {
|
|
|
return this.totalMemberCount > 1
|
|
|
},
|
|
|
- activeClassName: function() {
|
|
|
- return this.currentView === 'personal' ? 'toggle-item--active' : ''
|
|
|
- },
|
|
|
- activeFamilyClassName: function() {
|
|
|
- return this.currentView === 'family' ? 'toggle-item--active' : ''
|
|
|
- },
|
|
|
/** 家庭能量值(用于太极阳面) */
|
|
|
familyEnergy: function() {
|
|
|
- if (this.isPreview) {
|
|
|
- var s = this.previewScores
|
|
|
- return Math.round((s[0] + s[1] + s[2] + s[3] + s[4]) / 5)
|
|
|
- }
|
|
|
+ if (this.isPreview) return 0
|
|
|
return this.overallScore || 0
|
|
|
},
|
|
|
/** 当前选中视角的能量值(用于太极阴面) */
|
|
|
@@ -307,9 +398,9 @@ export default {
|
|
|
if (this.isPreview) return 0
|
|
|
return this.activeOverall || 0
|
|
|
},
|
|
|
- /** 按五行顺序绕圈排列
|
|
|
- * 固定序:心(火)→身(土)→智(金)→富(水)→行(木),心始终在顶部
|
|
|
- * 其余按五行相生序顺时针依次排:左边→右边→左下→右下
|
|
|
+ /**
|
|
|
+ * 环形顶点序(= sortedDimensions,不可改):心(火)->身(土)->智(金)->富(水)->行(木)
|
|
|
+ * 心始终在顶部,其余按五行相生序顺时针:左->右->左下->右下
|
|
|
*/
|
|
|
sortedDimensions: function() {
|
|
|
var order = ['mind', 'body', 'wisdom', 'wealth', 'action']
|
|
|
@@ -334,14 +425,33 @@ export default {
|
|
|
all.push({
|
|
|
code: code,
|
|
|
name: d.name || meta.name || '',
|
|
|
- icon: d.icon || meta.icon || '',
|
|
|
element: d.element || meta.element || '',
|
|
|
energy: score,
|
|
|
- healthIndex: score
|
|
|
+ healthIndex: score,
|
|
|
+ pointClass: RING_POS[j],
|
|
|
+ dotClass: 'point-dot--' + code,
|
|
|
+ energyClass: 'point-energy--' + code,
|
|
|
+ iconUri: DIM_ICON_URIS[code] || ''
|
|
|
})
|
|
|
}
|
|
|
return all
|
|
|
- // all = [心→顶, 身→右, 智→右下, 富→左下, 行→左]
|
|
|
+ // all = [心->顶, 身->右, 智->右下, 富->左下, 行->左]
|
|
|
+ },
|
|
|
+ /** 底部线性维度条(规格 §4.2):身 -> 智 -> 富 -> 行 -> 心 */
|
|
|
+ linearDimensions: function() {
|
|
|
+ var out = []
|
|
|
+ for (var i = 0; i < LINEAR_ORDER.length; i++) {
|
|
|
+ var def = LINEAR_ORDER[i]
|
|
|
+ var meta = DIM_META[def.code] || {}
|
|
|
+ out.push({
|
|
|
+ code: def.code,
|
|
|
+ name: meta.name || '',
|
|
|
+ energy: this.activeScores[def.idx] || 0,
|
|
|
+ itemClass: 'dim-item--' + def.code,
|
|
|
+ iconUri: DIM_ICON_URIS[def.code] || ''
|
|
|
+ })
|
|
|
+ }
|
|
|
+ return out
|
|
|
}
|
|
|
},
|
|
|
watch: {
|
|
|
@@ -389,21 +499,8 @@ export default {
|
|
|
mounted: function() {
|
|
|
var self = this
|
|
|
|
|
|
- // 预览模式:生成随机五维值(缓存以避免每次 mount 重算)
|
|
|
- if (this.isPreview) {
|
|
|
- var cacheKey = '_wuxing_preview_scores'
|
|
|
- var cached = uni.getStorageSync(cacheKey)
|
|
|
- if (cached && Array.isArray(cached) && cached.length === 5) {
|
|
|
- this.previewScores = cached
|
|
|
- } else {
|
|
|
- var scores = []
|
|
|
- for (var i = 0; i < 5; i++) {
|
|
|
- scores.push(Math.floor(Math.random() * 51) + 35)
|
|
|
- }
|
|
|
- this.previewScores = scores
|
|
|
- uni.setStorageSync(cacheKey, scores)
|
|
|
- }
|
|
|
- }
|
|
|
+ // preview:轻量引导条,不初始化 Canvas、不画完整星图
|
|
|
+ if (this.isPreview) return
|
|
|
|
|
|
// 等待 DOM 就绪后初始化 Canvas
|
|
|
setTimeout(function() {
|
|
|
@@ -459,15 +556,6 @@ export default {
|
|
|
})
|
|
|
},
|
|
|
|
|
|
- isOptionActive: function(option) {
|
|
|
- if (!option) return false
|
|
|
- if (option.viewMode !== this.viewMode) return false
|
|
|
- if (option.viewMode === 'member') {
|
|
|
- return String(option.memberId) === String(this.selectedMemberId)
|
|
|
- }
|
|
|
- return true
|
|
|
- },
|
|
|
-
|
|
|
selectOption: function(option) {
|
|
|
if (!option) return
|
|
|
if (option.viewMode === 'family' && this.totalMemberCount < 2) {
|
|
|
@@ -501,18 +589,17 @@ export default {
|
|
|
})
|
|
|
},
|
|
|
|
|
|
+ /** preview 引导条点击:仍触发 point-click,由父级驱动登录 */
|
|
|
+ onPreviewTap: function() {
|
|
|
+ this.$emit('point-click', { code: '', viewMode: this.viewMode, member: null })
|
|
|
+ },
|
|
|
+
|
|
|
/** 右上角:打开成员选择面板(本人 / 各成员 / 全家) */
|
|
|
onToggle: function() {
|
|
|
if (this.isPreview) return
|
|
|
this.memberPickerVisible = true
|
|
|
},
|
|
|
|
|
|
- /** 维度 code → CSS 颜色类名(不依赖 API 的 element 字段) */
|
|
|
- dimElementColor: function(code) {
|
|
|
- var meta = DIM_META[code]
|
|
|
- return meta ? meta.color : 'fire'
|
|
|
- },
|
|
|
-
|
|
|
/* ===========================
|
|
|
Canvas 初始化 & 渲染
|
|
|
=========================== */
|
|
|
@@ -552,7 +639,8 @@ export default {
|
|
|
|
|
|
_doRender: function() {
|
|
|
if (!this.ctx) return
|
|
|
- var ts = [this.animBody, this.animMind, this.animWisdom, this.animAction, this.animWealth]
|
|
|
+ // ts 环形序 [mind, body, wisdom, wealth, action](与 render.js DIM_RING / sortedDimensions 一致)
|
|
|
+ var ts = [this.animMind, this.animBody, this.animWisdom, this.animWealth, this.animAction]
|
|
|
renderStar(this.ctx, this.canvasWidth, this.canvasHeight, ts, {
|
|
|
familyEnergy: this.familyEnergy,
|
|
|
personalEnergy: this.personalEnergy
|
|
|
@@ -563,19 +651,41 @@ export default {
|
|
|
动画控制
|
|
|
=========================== */
|
|
|
|
|
|
+ _prefersReducedMotion: function() {
|
|
|
+ try {
|
|
|
+ if (typeof window !== 'undefined' && window.matchMedia) {
|
|
|
+ return window.matchMedia('(prefers-reduced-motion: reduce)').matches
|
|
|
+ }
|
|
|
+ } catch (e) {}
|
|
|
+ return false
|
|
|
+ },
|
|
|
+
|
|
|
_startAnimation: function() {
|
|
|
var self = this
|
|
|
+
|
|
|
+ // 降低动效偏好:直接落值,不做填充动画(Canvas 无 CSS 降级,只能 JS 侧判断)
|
|
|
+ if (this._prefersReducedMotion()) {
|
|
|
+ var target = this.activeTs
|
|
|
+ this.animMind = target[0]
|
|
|
+ this.animBody = target[1]
|
|
|
+ this.animWisdom = target[2]
|
|
|
+ this.animWealth = target[3]
|
|
|
+ this.animAction = target[4]
|
|
|
+ this._doRender()
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
if (!this._animator) {
|
|
|
this._animator = new FillAnimator(
|
|
|
function() {
|
|
|
- return [self.animBody, self.animMind, self.animWisdom, self.animAction, self.animWealth]
|
|
|
+ return [self.animMind, self.animBody, self.animWisdom, self.animWealth, self.animAction]
|
|
|
},
|
|
|
function(interpolated) {
|
|
|
- self.animBody = interpolated[0]
|
|
|
- self.animMind = interpolated[1]
|
|
|
+ self.animMind = interpolated[0]
|
|
|
+ self.animBody = interpolated[1]
|
|
|
self.animWisdom = interpolated[2]
|
|
|
- self.animAction = interpolated[3]
|
|
|
- self.animWealth = interpolated[4]
|
|
|
+ self.animWealth = interpolated[3]
|
|
|
+ self.animAction = interpolated[4]
|
|
|
self._doRender()
|
|
|
}
|
|
|
)
|
|
|
@@ -608,7 +718,8 @@ export default {
|
|
|
var ctx = canvas.getContext('2d')
|
|
|
ctx.scale(pixelRatio, pixelRatio)
|
|
|
|
|
|
- var outerR = Math.min(width, height) * 0.50
|
|
|
+ // 与 render.js / hitdetect.js 保持一致的外接半径系数
|
|
|
+ var outerR = Math.min(width, height) * 0.46
|
|
|
var vertices = calcStarVertices(width / 2, height / 2, outerR)
|
|
|
|
|
|
self._flowAnim = new FlowAnimation(ctx, width, height, {
|
|
|
@@ -616,6 +727,10 @@ export default {
|
|
|
inner: vertices.inner,
|
|
|
dimOrder: dimOrder
|
|
|
})
|
|
|
+
|
|
|
+ // 降低动效偏好:不启动粒子动画
|
|
|
+ if (self._prefersReducedMotion()) return
|
|
|
+
|
|
|
self._flowAnim.start()
|
|
|
self._flowCanvasReady = true
|
|
|
})
|
|
|
@@ -664,27 +779,18 @@ export default {
|
|
|
|
|
|
<style scoped lang="scss">
|
|
|
/* ============================================================
|
|
|
-容器
|
|
|
+容器:浅色暖调卡片(与 B1 .dim-band 视觉语言一致)
|
|
|
============================================================ */
|
|
|
.wuxing-sandbox {
|
|
|
margin: 20rpx $uni-space-lg;
|
|
|
padding: 20rpx 24rpx 24rpx;
|
|
|
- background: linear-gradient(135deg, $facade-ink-navy, $accent-navy, $app-ink-night-2);
|
|
|
- border-radius: 24rpx;
|
|
|
+ background: $app-surface;
|
|
|
+ border: 1rpx solid rgba($brand-primary, 0.12);
|
|
|
+ border-radius: $radius-lg;
|
|
|
+ box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.03);
|
|
|
position: relative;
|
|
|
overflow: hidden;
|
|
|
}
|
|
|
-.wuxing-sandbox::before {
|
|
|
- content: '';
|
|
|
- position: absolute;
|
|
|
- top: -50%;
|
|
|
- left: -50%;
|
|
|
- width: 200%;
|
|
|
- height: 200%;
|
|
|
- background: radial-gradient(ellipse at 30% 20%, rgba(249,115,22,0.04), transparent 60%),
|
|
|
- radial-gradient(ellipse at 70% 80%, rgba(251,146,60,0.03), transparent 60%);
|
|
|
- pointer-events: none;
|
|
|
-}
|
|
|
|
|
|
/* ---- 标题 ---- */
|
|
|
.sandbox-header {
|
|
|
@@ -695,37 +801,28 @@ export default {
|
|
|
position: relative;
|
|
|
z-index: 5;
|
|
|
}
|
|
|
-.sandbox-title { font-size: calc(26rpx * var(--font-scale, 1)); font-weight: bold; color: #8FC5E8; margin-left: 8rpx; }
|
|
|
+.sandbox-title { font-size: calc(26rpx * var(--font-scale, 1)); font-weight: bold; color: $app-text; margin-left: 8rpx; }
|
|
|
.sandbox-logo { width: 32rpx; height: 32rpx; flex-shrink: 0; }
|
|
|
-.sandbox-badge {
|
|
|
- font-size: calc(20rpx * var(--font-scale, 1));
|
|
|
- color: rgba(143,197,232,0.7);
|
|
|
- background: rgba(143,197,232,0.1);
|
|
|
- padding: 4rpx 14rpx;
|
|
|
- border-radius: 24rpx;
|
|
|
- margin-left: auto;
|
|
|
-}
|
|
|
+
|
|
|
+/* ---- 右上角切换(触控 ≥44px = 88rpx) ---- */
|
|
|
.sandbox-switch {
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
gap: 6rpx;
|
|
|
- font-size: calc(22rpx * var(--font-scale, 1));
|
|
|
- color: $app-surface;
|
|
|
- background: linear-gradient(135deg, $accent-indigo, $accent-indigo-deep);
|
|
|
- padding: 10rpx 20rpx;
|
|
|
- border-radius: 24rpx;
|
|
|
+ min-height: 88rpx;
|
|
|
+ padding: 0 20rpx;
|
|
|
margin-left: auto;
|
|
|
flex-shrink: 0;
|
|
|
- box-shadow: 0 4rpx 12rpx rgba(102,126,234,0.45);
|
|
|
- border: 1rpx solid rgba(255,255,255,0.25);
|
|
|
-}
|
|
|
-.sandbox-switch:active {
|
|
|
- opacity: 0.85;
|
|
|
- box-shadow: none;
|
|
|
-}
|
|
|
-.sandbox-switch-icon { font-size: calc(24rpx * var(--font-scale, 1)); line-height: 1; }
|
|
|
+ border-radius: 44rpx;
|
|
|
+ color: $brand-primary-deep;
|
|
|
+ background: $brand-primary-soft;
|
|
|
+ border: 1rpx solid rgba($brand-primary, 0.18);
|
|
|
+ transition: opacity $duration-fast;
|
|
|
+}
|
|
|
+.sandbox-switch:active { opacity: 0.8; }
|
|
|
+.sandbox-switch-icon { width: 32rpx; height: 32rpx; flex-shrink: 0; }
|
|
|
.sandbox-switch-label { font-size: calc(22rpx * var(--font-scale, 1)); font-weight: 700; max-width: 140rpx; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
|
|
|
-.sandbox-switch-arrow { font-size: calc(20rpx * var(--font-scale, 1)); opacity: 0.8; }
|
|
|
+.sandbox-switch-arrow { width: 26rpx; height: 26rpx; flex-shrink: 0; opacity: 0.7; }
|
|
|
|
|
|
/* ---- 成员选择面板 ---- */
|
|
|
.member-picker-mask {
|
|
|
@@ -745,7 +842,7 @@ export default {
|
|
|
overflow-y: auto;
|
|
|
box-sizing: border-box;
|
|
|
padding: 28rpx 28rpx calc(24rpx + env(safe-area-inset-bottom));
|
|
|
- background: #ffffff;
|
|
|
+ background: $app-surface;
|
|
|
border-radius: 24rpx 24rpx 0 0;
|
|
|
box-shadow: 0 -8rpx 32rpx rgba(0, 0, 0, 0.12);
|
|
|
}
|
|
|
@@ -753,7 +850,7 @@ export default {
|
|
|
padding-bottom: 16rpx;
|
|
|
font-size: calc(26rpx * var(--font-scale, 1));
|
|
|
font-weight: 700;
|
|
|
- color: #333333;
|
|
|
+ color: $app-text;
|
|
|
text-align: center;
|
|
|
}
|
|
|
.member-picker-item {
|
|
|
@@ -764,39 +861,35 @@ export default {
|
|
|
padding: 0 24rpx;
|
|
|
margin-top: 8rpx;
|
|
|
border-radius: 16rpx;
|
|
|
- background: #f7f8fc;
|
|
|
-}
|
|
|
-.member-picker-item--active {
|
|
|
- background: rgba(102, 126, 234, 0.12);
|
|
|
-}
|
|
|
-.member-picker-label {
|
|
|
- font-size: calc(28rpx * var(--font-scale, 1));
|
|
|
- color: #333333;
|
|
|
-}
|
|
|
-.member-picker-item--active .member-picker-label {
|
|
|
- color: #667eea;
|
|
|
- font-weight: 700;
|
|
|
-}
|
|
|
-.member-picker-check {
|
|
|
- font-size: calc(30rpx * var(--font-scale, 1));
|
|
|
- font-weight: 700;
|
|
|
- color: #667eea;
|
|
|
+ background: $app-bg;
|
|
|
+ transition: background $duration-fast;
|
|
|
}
|
|
|
+.member-picker-item--active { background: $brand-primary-soft; }
|
|
|
+.member-picker-label { font-size: calc(28rpx * var(--font-scale, 1)); color: $app-text; }
|
|
|
+.member-picker-item--active .member-picker-label { color: $brand-primary-deep; font-weight: 700; }
|
|
|
+.member-picker-check { width: 34rpx; height: 34rpx; flex-shrink: 0; }
|
|
|
|
|
|
-/* ---- 五角星区域 ---- */
|
|
|
+/* ============================================================
|
|
|
+五角星区域(C3:明确高度,避免 flex 下塌陷)
|
|
|
+============================================================ */
|
|
|
.sandbox-star {
|
|
|
position: relative;
|
|
|
width: 100%;
|
|
|
+ height: 540rpx; /* 兜底(父级 starHeight 内联覆盖) */
|
|
|
+ min-height: 400rpx;
|
|
|
+ flex-shrink: 0;
|
|
|
display: flex;
|
|
|
justify-content: center;
|
|
|
align-items: center;
|
|
|
+ background: $dim-sandbox-fill;
|
|
|
+ border-radius: $radius-md;
|
|
|
}
|
|
|
|
|
|
-/* 背景光晕 */
|
|
|
+/* 背景光晕(主色仅装饰) */
|
|
|
.star-glow-bg {
|
|
|
position: absolute; width: 500rpx; height: 500rpx;
|
|
|
top: 50%; left: 50%; transform: translate(-50%, -50%);
|
|
|
- background: radial-gradient(circle, rgba(249,115,22,0.10), transparent 70%);
|
|
|
+ background: radial-gradient(circle, rgba($brand-primary, 0.08), transparent 70%);
|
|
|
border-radius: 50%; pointer-events: none;
|
|
|
}
|
|
|
|
|
|
@@ -808,72 +901,76 @@ export default {
|
|
|
}
|
|
|
|
|
|
/* ============================================================
|
|
|
-顶点:图标 + 中文标签
|
|
|
+顶点:图标 + 中文标签(图标形状承载五行语义,深档色承载数据)
|
|
|
============================================================ */
|
|
|
.star-point {
|
|
|
- position: absolute; transform: translate(-50%, -50%); z-index: 3; cursor: pointer;
|
|
|
+ position: absolute; transform: translate(-50%, -50%); z-index: 3;
|
|
|
display: flex; flex-direction: column; align-items: center;
|
|
|
+ min-width: 88rpx; min-height: 88rpx; /* 触控 ≥44px */
|
|
|
+ padding: 8rpx 12rpx;
|
|
|
+ box-sizing: border-box;
|
|
|
}
|
|
|
-/* 横排 */
|
|
|
-.star-point--row {
|
|
|
- flex-direction: row;
|
|
|
- gap: 6rpx;
|
|
|
-}
|
|
|
-.star-point--rev {
|
|
|
- flex-direction: row-reverse;
|
|
|
- gap: 6rpx;
|
|
|
-}
|
|
|
-.star-point--top { top: 1%; left: 50%; }
|
|
|
-.star-point--left { top: 38%; left: 5%; }
|
|
|
-.star-point--right { top: 38%; left: 95%; }
|
|
|
-.star-point--lr { top: 89%; left: 85%; }
|
|
|
-.star-point--ll { top: 89%; left: 15%; }
|
|
|
+.star-point--row { flex-direction: row; gap: 6rpx; }
|
|
|
+.star-point--rev { flex-direction: row-reverse; gap: 6rpx; }
|
|
|
+/* 顺时针:上=心 右=身 右下=智 左下=富 左=行 */
|
|
|
+.star-point--top { top: 6%; left: 50%; }
|
|
|
+.star-point--left { top: 40%; left: 5%; }
|
|
|
+.star-point--right { top: 40%; left: 95%; }
|
|
|
+.star-point--lr { top: 88%; left: 84%; }
|
|
|
+.star-point--ll { top: 88%; left: 16%; }
|
|
|
|
|
|
.point-dot {
|
|
|
- width: 52rpx; height: 52rpx; border-radius: 50%;
|
|
|
+ width: 60rpx; height: 60rpx; border-radius: 50%;
|
|
|
display: flex; align-items: center; justify-content: center;
|
|
|
- box-shadow: 0 0 24rpx rgba(255,255,255,0.25);
|
|
|
-}
|
|
|
-.point-dot--fire { background: linear-gradient(135deg, $mind-accent, $mat-orange-strong); }
|
|
|
-.point-dot--water { background: linear-gradient(135deg, $mat-blue-400, $mat-blue-strong); }
|
|
|
-.point-dot--earth { background: linear-gradient(135deg, $brown-warm, #5D4037); }
|
|
|
-.point-dot--metal { background: linear-gradient(135deg, $accent-gold, #FF8F00); }
|
|
|
-.point-dot--wood { background: linear-gradient(135deg, $mat-green, $mat-green-strong); }
|
|
|
-
|
|
|
-.point-icon { font-size: calc(26rpx * var(--font-scale, 1)); line-height: 1; }
|
|
|
-
|
|
|
-.point-label {
|
|
|
- font-size: calc(22rpx * var(--font-scale, 1)); font-weight: bold; color: rgba(255,255,255,0.9);
|
|
|
- margin-top: 6rpx; text-shadow: 0 1rpx 4rpx rgba(0,0,0,0.5);
|
|
|
- letter-spacing: 2rpx;
|
|
|
+ flex-shrink: 0;
|
|
|
+ border: 1rpx solid transparent;
|
|
|
}
|
|
|
+.point-dot--mind { background: $dim-mind-tint; border-color: rgba($dim-mind, 0.35); box-shadow: 0 0 12rpx rgba($dim-mind, 0.22); }
|
|
|
+.point-dot--body { background: $dim-body-tint; border-color: rgba($dim-body, 0.35); box-shadow: 0 0 12rpx rgba($dim-body, 0.22); }
|
|
|
+.point-dot--wisdom { background: $dim-wisdom-tint; border-color: rgba($dim-wisdom, 0.35); box-shadow: 0 0 12rpx rgba($dim-wisdom, 0.22); }
|
|
|
+.point-dot--wealth { background: $dim-wealth-tint; border-color: rgba($dim-wealth, 0.35); box-shadow: 0 0 12rpx rgba($dim-wealth, 0.22); }
|
|
|
+.point-dot--action { background: $dim-action-tint; border-color: rgba($dim-action, 0.35); box-shadow: 0 0 12rpx rgba($dim-action, 0.22); }
|
|
|
+
|
|
|
+.point-icon { width: 40rpx; height: 40rpx; } /* 20px 下可辨识 */
|
|
|
+.point-label { font-size: calc(22rpx * var(--font-scale, 1)); font-weight: bold; color: $app-text; margin-top: 6rpx; letter-spacing: 2rpx; }
|
|
|
.star-point--row .point-label,
|
|
|
-.star-point--rev .point-label {
|
|
|
- margin-top: 0;
|
|
|
-}
|
|
|
-.point-energy {
|
|
|
- font-size: calc(18rpx * var(--font-scale, 1)); color: rgba(143,197,232,0.8);
|
|
|
- background: rgba(143,197,232,0.12);
|
|
|
- padding: 1rpx 10rpx; border-radius: 16rpx;
|
|
|
- margin-top: 2rpx;
|
|
|
-}
|
|
|
+.star-point--rev .point-label { margin-top: 0; }
|
|
|
+.point-energy { font-size: calc(18rpx * var(--font-scale, 1)); font-weight: 600; padding: 1rpx 10rpx; border-radius: 16rpx; margin-top: 2rpx; }
|
|
|
.star-point--row .point-energy,
|
|
|
-.star-point--rev .point-energy {
|
|
|
- margin-top: 0;
|
|
|
-}
|
|
|
+.star-point--rev .point-energy { margin-top: 0; }
|
|
|
+.point-energy--mind { color: $dim-data-mind; background: $dim-mind-tint; }
|
|
|
+.point-energy--body { color: $dim-data-body; background: $dim-body-tint; }
|
|
|
+.point-energy--wisdom { color: $dim-data-wisdom; background: $dim-wisdom-tint; }
|
|
|
+.point-energy--wealth { color: $dim-data-wealth; background: $dim-wealth-tint; }
|
|
|
+.point-energy--action { color: $dim-data-action; background: $dim-action-tint; }
|
|
|
+
|
|
|
+.star-center { position: absolute; top: 50%; left: 50%; transform: translate(-50%,-50%); z-index: 4; width: 180rpx; height: 180rpx; border-radius: 50%; }
|
|
|
|
|
|
/* ============================================================
|
|
|
-中心点击区域
|
|
|
+preview 轻量引导条(标题 + 徽章 + 弱化五边形轮廓)
|
|
|
============================================================ */
|
|
|
-.star-center {
|
|
|
- position: absolute; top: 50%; left: 50%;
|
|
|
- transform: translate(-50%, -50%); z-index: 4;
|
|
|
- width: 180rpx; height: 180rpx; border-radius: 50%;
|
|
|
- cursor: pointer;
|
|
|
+.sandbox-preview {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ min-height: 88rpx;
|
|
|
+ padding: 16rpx 20rpx;
|
|
|
+ border-radius: $radius-md;
|
|
|
+ background: $brand-primary-soft;
|
|
|
+ border: 1rpx solid rgba($brand-primary, 0.15);
|
|
|
+}
|
|
|
+.preview-pentagon { width: 56rpx; height: 56rpx; flex-shrink: 0; opacity: 0.45; }
|
|
|
+.preview-copy { display: flex; flex-direction: column; margin-left: 16rpx; flex: 1; min-width: 0; }
|
|
|
+.preview-title { font-size: calc(26rpx * var(--font-scale, 1)); font-weight: bold; color: $app-text; }
|
|
|
+.preview-sub { font-size: calc(20rpx * var(--font-scale, 1)); color: $app-text-secondary; margin-top: 4rpx; }
|
|
|
+.preview-badge {
|
|
|
+ font-size: calc(20rpx * var(--font-scale, 1)); font-weight: 700;
|
|
|
+ color: $app-surface; background: $brand-primary-deep;
|
|
|
+ padding: 6rpx 14rpx; border-radius: 24rpx;
|
|
|
+ margin-left: 12rpx; flex-shrink: 0;
|
|
|
}
|
|
|
|
|
|
/* ============================================================
|
|
|
-维度详情条
|
|
|
+维度条(线性顺序:身 -> 智 -> 富 -> 行 -> 心)
|
|
|
============================================================ */
|
|
|
.dimension-bar {
|
|
|
display: flex; align-items: center; justify-content: center;
|
|
|
@@ -881,52 +978,23 @@ export default {
|
|
|
position: relative; z-index: 5; flex-wrap: wrap;
|
|
|
}
|
|
|
.dim-item {
|
|
|
- font-size: calc(20rpx * var(--font-scale, 1)); padding: 4rpx 12rpx; border-radius: 8rpx; white-space: nowrap;
|
|
|
-}
|
|
|
-.dim-item--wood { color: $mat-green; background: rgba(76,175,80,0.12); }
|
|
|
-.dim-item--fire { color: $mind-accent; background: rgba(255,107,53,0.12); }
|
|
|
-.dim-item--earth { color: $brown-warm; background: rgba(141,110,99,0.12); }
|
|
|
-.dim-item--metal { color: $accent-gold; background: rgba(255,215,0,0.12); }
|
|
|
-.dim-item--water { color: $mat-blue-400; background: rgba(66,165,245,0.12); }
|
|
|
-
|
|
|
-/* ============================================================
|
|
|
-个人/全家切换开关
|
|
|
-============================================================ */
|
|
|
-.sandbox-toggle {
|
|
|
- display: flex;
|
|
|
- justify-content: center;
|
|
|
- align-items: center;
|
|
|
- margin-bottom: 12rpx;
|
|
|
- position: relative;
|
|
|
- z-index: 5;
|
|
|
- gap: 0;
|
|
|
-}
|
|
|
-.toggle-item {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- justify-content: center;
|
|
|
- padding: 8rpx 28rpx;
|
|
|
- font-size: calc(24rpx * var(--font-scale, 1));
|
|
|
- color: rgba(143,197,232,0.6);
|
|
|
- background: rgba(143,197,232,0.08);
|
|
|
- border: 1rpx solid rgba(143,197,232,0.15);
|
|
|
- border-radius: 24rpx 0 0 24rpx;
|
|
|
- transition: color 0.2s, background-color 0.2s, border-color 0.2s;
|
|
|
-}
|
|
|
-.toggle-item--family {
|
|
|
- border-radius: 0 24rpx 24rpx 0;
|
|
|
- border-left: none;
|
|
|
-}
|
|
|
-.toggle-item--active {
|
|
|
- color: $app-surface;
|
|
|
- background: linear-gradient(135deg, $brand-primary, $brand-primary-dark);
|
|
|
- border-color: $brand-primary;
|
|
|
-}
|
|
|
-.toggle-icon {
|
|
|
- font-size: calc(26rpx * var(--font-scale, 1));
|
|
|
- margin-right: 8rpx;
|
|
|
-}
|
|
|
-.toggle-text {
|
|
|
- font-weight: bold;
|
|
|
+ display: flex; align-items: center;
|
|
|
+ font-size: calc(20rpx * var(--font-scale, 1));
|
|
|
+ padding: 6rpx 12rpx; border-radius: 8rpx; white-space: nowrap;
|
|
|
+}
|
|
|
+.dim-item--body { color: $dim-data-body; background: $dim-body-tint; }
|
|
|
+.dim-item--wisdom { color: $dim-data-wisdom; background: $dim-wisdom-tint; }
|
|
|
+.dim-item--wealth { color: $dim-data-wealth; background: $dim-wealth-tint; }
|
|
|
+.dim-item--action { color: $dim-data-action; background: $dim-action-tint; }
|
|
|
+.dim-item--mind { color: $dim-data-mind; background: $dim-mind-tint; }
|
|
|
+.dim-item-icon { width: 24rpx; height: 24rpx; margin-right: 4rpx; flex-shrink: 0; }
|
|
|
+
|
|
|
+/* 降低动效偏好:CSS 侧关闭过渡 */
|
|
|
+@media (prefers-reduced-motion: reduce) {
|
|
|
+ .sandbox-switch,
|
|
|
+ .member-picker-item,
|
|
|
+ .dim-item {
|
|
|
+ transition-duration: 0.01ms !important;
|
|
|
+ }
|
|
|
}
|
|
|
-</style>
|
|
|
+</style>
|