|
|
@@ -50,16 +50,21 @@
|
|
|
</el-col>
|
|
|
</el-row>
|
|
|
<el-row :gutter="12">
|
|
|
- <el-col :span="12">
|
|
|
+ <el-col :span="8">
|
|
|
<el-form-item label="肩宽(cm)">
|
|
|
<el-input v-model="bodyForm.shoulderWidth" disabled />
|
|
|
</el-form-item>
|
|
|
</el-col>
|
|
|
- <el-col :span="12">
|
|
|
+ <el-col :span="8">
|
|
|
<el-form-item label="身长(cm)">
|
|
|
<el-input v-model="bodyForm.bodyHeight" disabled />
|
|
|
</el-form-item>
|
|
|
</el-col>
|
|
|
+ <el-col :span="8">
|
|
|
+ <el-form-item label="脊柱长(cm)">
|
|
|
+ <el-input v-model="bodyForm.spineLength" disabled />
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
</el-row>
|
|
|
<el-row :gutter="12">
|
|
|
<el-col :span="8">
|
|
|
@@ -199,71 +204,42 @@
|
|
|
<stop offset="55%" stop-color="#f1f5f9" />
|
|
|
<stop offset="100%" stop-color="#e8eef5" />
|
|
|
</radialGradient>
|
|
|
- <linearGradient id="simBodyGrad" x1="0%" y1="0%" x2="100%" y2="100%">
|
|
|
- <stop offset="0%" stop-color="#fdf8f5" />
|
|
|
- <stop offset="35%" stop-color="#f5ebe3" />
|
|
|
- <stop offset="100%" stop-color="#e8ddd4" />
|
|
|
- </linearGradient>
|
|
|
- <linearGradient id="simStroke" x1="0%" y1="0%" x2="0%" y2="100%">
|
|
|
- <stop offset="0%" stop-color="#c9b8a8" />
|
|
|
- <stop offset="100%" stop-color="#a8988a" />
|
|
|
- </linearGradient>
|
|
|
- <filter id="simShadow" x="-25%" y="-15%" width="150%" height="130%">
|
|
|
- <feDropShadow dx="0" dy="6" stdDeviation="8" flood-color="#5c4a3d" flood-opacity="0.10" />
|
|
|
- </filter>
|
|
|
</defs>
|
|
|
|
|
|
<rect width="100%" height="100%" fill="url(#simWash)" rx="14" />
|
|
|
- <rect width="100%" height="100%" fill="url(#sim-grid)" rx="14" opacity="0.85" />
|
|
|
-
|
|
|
- <line class="axis-line" x1="200" y1="12" x2="200" y2="568" stroke="rgba(148,163,184,0.4)" stroke-width="1" stroke-dasharray="4 6" />
|
|
|
- <line class="axis-line" x1="12" y1="100" x2="388" y2="100" stroke="rgba(148,163,184,0.4)" stroke-width="1" stroke-dasharray="5 5" />
|
|
|
-
|
|
|
- <!-- 人体轮廓 -->
|
|
|
- <g filter="url(#simShadow)" stroke="url(#simStroke)" stroke-width="1.35" stroke-linejoin="round" stroke-linecap="round">
|
|
|
- <path d="
|
|
|
- M 200 28
|
|
|
- C 186 28, 174 38, 172 56
|
|
|
- C 170 70, 174 86, 178 96
|
|
|
- C 180 102, 162 108, 138 114
|
|
|
- C 114 124, 98 136, 88 150
|
|
|
- C 80 168, 76 192, 74 220
|
|
|
- C 72 252, 68 288, 64 318
|
|
|
- C 60 340, 54 352, 62 358
|
|
|
- C 68 364, 84 356, 96 332
|
|
|
- C 108 306, 112 272, 116 238
|
|
|
- C 120 208, 124 186, 128 192
|
|
|
- C 134 204, 136 238, 138 278
|
|
|
- C 142 330, 146 374, 148 408
|
|
|
- C 152 454, 144 510, 138 548
|
|
|
- C 134 568, 130 578, 144 582
|
|
|
- C 160 586, 170 582, 176 556
|
|
|
- C 182 514, 190 452, 200 424
|
|
|
- C 210 452, 218 514, 224 556
|
|
|
- C 230 582, 240 586, 256 582
|
|
|
- C 270 578, 266 568, 262 548
|
|
|
- C 256 510, 248 454, 252 408
|
|
|
- C 254 374, 258 330, 262 278
|
|
|
- C 264 238, 266 204, 272 192
|
|
|
- C 276 186, 280 208, 284 238
|
|
|
- C 288 272, 292 306, 304 332
|
|
|
- C 316 356, 332 364, 338 358
|
|
|
- C 346 352, 340 340, 336 318
|
|
|
- C 332 288, 328 252, 326 220
|
|
|
- C 324 192, 320 168, 312 150
|
|
|
- C 304 136, 286 124, 262 114
|
|
|
- C 238 108, 220 102, 222 96
|
|
|
- C 226 86, 230 70, 228 56
|
|
|
- C 226 38, 214 28, 200 28 Z" fill="url(#simBodyGrad)" />
|
|
|
- <path d="M 148 126 C 136 134, 124 158, 132 192 C 136 208, 152 212, 158 196 C 164 174, 162 142, 148 126 Z" fill="none" stroke="rgba(92,74,61,0.18)" stroke-width="1.1" />
|
|
|
- <path d="M 252 126 C 264 134, 276 158, 268 192 C 264 208, 248 212, 242 196 C 236 174, 238 142, 252 126 Z" fill="none" stroke="rgba(92,74,61,0.18)" stroke-width="1.1" />
|
|
|
- <path d="M 148 372 C 170 402, 186 412, 200 406 C 214 412, 230 402, 252 372" fill="none" stroke="rgba(92,74,61,0.14)" stroke-width="1.1" />
|
|
|
- </g>
|
|
|
-
|
|
|
- <line x1="200" y1="92" x2="200" y2="390" stroke="rgba(99,102,241,0.35)" stroke-width="2" stroke-dasharray="8 6" stroke-linecap="round" />
|
|
|
+ <image
|
|
|
+ :href="bodyBackImage"
|
|
|
+ x="0"
|
|
|
+ y="-10"
|
|
|
+ width="400"
|
|
|
+ height="600"
|
|
|
+ preserveAspectRatio="xMidYMid slice"
|
|
|
+ class="body-photo"
|
|
|
+ />
|
|
|
+ <rect width="100%" height="100%" fill="url(#sim-grid)" rx="14" opacity="0.35" />
|
|
|
+
|
|
|
+ <line class="axis-line" :x1="SVG_C7_X" y1="12" :x2="SVG_C7_X" y2="568" stroke="rgba(148,163,184,0.4)" stroke-width="1" stroke-dasharray="4 6" />
|
|
|
+ <line class="axis-line" x1="12" :y1="SVG_C7_Y" x2="388" :y2="SVG_C7_Y" stroke="rgba(148,163,184,0.4)" stroke-width="1" stroke-dasharray="5 5" />
|
|
|
+
|
|
|
+ <!-- 背部中线参考 -->
|
|
|
+ <line :x1="SVG_C7_X" :y1="SVG_C7_Y - 20" :x2="SVG_C7_X" :y2="SVG_S4_Y" stroke="rgba(99,102,241,0.35)" stroke-width="2" stroke-dasharray="8 6" stroke-linecap="round" />
|
|
|
+ <line
|
|
|
+ :x1="SVG_C7_X + 18"
|
|
|
+ :y1="SVG_C7_Y"
|
|
|
+ :x2="SVG_C7_X + 18"
|
|
|
+ :y2="currentSpineEndY"
|
|
|
+ stroke="rgba(14,165,233,0.9)"
|
|
|
+ stroke-width="3"
|
|
|
+ stroke-linecap="round"
|
|
|
+ />
|
|
|
+ <circle :cx="SVG_C7_X + 18" :cy="currentSpineEndY" r="5" fill="#0ea5e9" stroke="#fff" stroke-width="2" />
|
|
|
+ <text :x="SVG_C7_X + 28" :y="currentSpineEndY - 10" font-size="10" fill="#0369a1" font-weight="700" font-family="system-ui, sans-serif">
|
|
|
+ {{ fmtNum(currentSpineLengthCm) }} cm
|
|
|
+ </text>
|
|
|
+ <text :x="SVG_C7_X + 28" :y="currentSpineEndY + 6" font-size="10" fill="#0369a1" font-family="system-ui, sans-serif">脊柱终点</text>
|
|
|
|
|
|
<!-- C7 大椎穴标记 -->
|
|
|
- <g transform="translate(200, 100)">
|
|
|
+ <g :transform="`translate(${SVG_C7_X}, ${SVG_C7_Y})`">
|
|
|
<circle r="14" fill="none" stroke="#e85d5d" stroke-width="1" opacity="0.3">
|
|
|
<animate attributeName="r" values="8;16;8" dur="2.5s" repeatCount="indefinite" />
|
|
|
<animate attributeName="opacity" values="0.5;0;0.5" dur="2.5s" repeatCount="indefinite" />
|
|
|
@@ -278,8 +254,8 @@
|
|
|
|
|
|
<text x="208" y="24" font-size="10" fill="#94a3b8" font-family="system-ui, sans-serif">↑ 头侧</text>
|
|
|
<text x="208" y="570" font-size="10" fill="#94a3b8" font-family="system-ui, sans-serif">↓ 尾侧</text>
|
|
|
- <text x="14" y="92" font-size="10" fill="#94a3b8" font-family="system-ui, sans-serif">患者左 (−X)</text>
|
|
|
- <text x="386" y="92" text-anchor="end" font-size="10" fill="#94a3b8" font-family="system-ui, sans-serif">患者右 (+X)</text>
|
|
|
+ <text x="14" :y="SVG_C7_Y - 8" font-size="10" fill="#94a3b8" font-family="system-ui, sans-serif">患者左 (−X)</text>
|
|
|
+ <text x="386" text-anchor="end" :y="SVG_C7_Y - 8" font-size="10" fill="#94a3b8" font-family="system-ui, sans-serif">患者右 (+X)</text>
|
|
|
|
|
|
<!-- 穴位标记 -->
|
|
|
<g v-for="(m, idx) in markers" :key="idx">
|
|
|
@@ -288,16 +264,6 @@
|
|
|
<text :x="m.x" :y="m.y + 4" text-anchor="middle" font-size="8" font-weight="800" fill="#fff" font-family="system-ui, sans-serif" style="pointer-events:none">
|
|
|
{{ m.num }}
|
|
|
</text>
|
|
|
- <text
|
|
|
- :x="m.labelX" :y="m.y + 4"
|
|
|
- :text-anchor="m.anchor"
|
|
|
- font-size="10" font-weight="700" :fill="m.color"
|
|
|
- font-family="system-ui, sans-serif"
|
|
|
- paint-order="stroke fill"
|
|
|
- stroke="rgba(255,255,255,0.92)" stroke-width="3" stroke-linejoin="round"
|
|
|
- >
|
|
|
- {{ m.name }}
|
|
|
- </text>
|
|
|
<!-- 步骤连接线 -->
|
|
|
<line
|
|
|
v-if="idx > 0"
|
|
|
@@ -338,6 +304,15 @@
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
+
|
|
|
+ <div v-if="unmappedSteps.length" class="visual-note">
|
|
|
+ <div class="visual-note-title">以下穴位未叠加到后背图</div>
|
|
|
+ <div class="visual-note-text">
|
|
|
+ <span v-for="s in unmappedSteps" :key="s.stepOrder" class="visual-note-item">
|
|
|
+ {{ s.stepOrder }}. {{ s.acupointName }}
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
</el-card>
|
|
|
|
|
|
<!-- 推送数据 JSON -->
|
|
|
@@ -356,11 +331,12 @@
|
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
|
-import { computed, onMounted, ref, reactive } from 'vue'
|
|
|
+import { computed, onMounted, ref, reactive, watch } from 'vue'
|
|
|
import { ElMessage } from 'element-plus'
|
|
|
import { getProfilePage } from '@/api/user'
|
|
|
-import { getPlanPage } from '@/api/plan'
|
|
|
+import { getPlanPage, getUserPlanPage } from '@/api/plan'
|
|
|
import { getSimulationData } from '@/api/simulation'
|
|
|
+import bodyBackImage from '@/assets/acupoint-back-realistic.jpg'
|
|
|
|
|
|
const selectedUserId = ref(null)
|
|
|
const selectedMode = ref(null)
|
|
|
@@ -370,6 +346,7 @@ const selectedPlanId = ref(null)
|
|
|
const userOptions = ref([])
|
|
|
const usersLoading = ref(false)
|
|
|
const allPlans = ref([])
|
|
|
+const userPlans = ref([])
|
|
|
const plansLoading = ref(false)
|
|
|
const simulating = ref(false)
|
|
|
const pushData = ref(null)
|
|
|
@@ -381,6 +358,7 @@ const bodyForm = reactive({
|
|
|
age: '',
|
|
|
shoulderWidth: '',
|
|
|
bodyHeight: '',
|
|
|
+ spineLength: '',
|
|
|
fingerWidth1: '',
|
|
|
fingerWidth15: '',
|
|
|
fingerWidth3: '',
|
|
|
@@ -389,9 +367,16 @@ const bodyForm = reactive({
|
|
|
|
|
|
const canSimulate = computed(() => selectedUserId.value && selectedPlanId.value)
|
|
|
|
|
|
+const planSource = computed(() => {
|
|
|
+ // 专业模式:要求与“用户方案列表”保持一致,优先使用 user-plan 里该用户对应功效的方案
|
|
|
+ if (selectedMode.value === 2) return userPlans.value
|
|
|
+ // 其他模式暂仍使用全局方案列表
|
|
|
+ return allPlans.value
|
|
|
+})
|
|
|
+
|
|
|
const filteredPlans = computed(() => {
|
|
|
if (!selectedMode.value) return []
|
|
|
- let list = allPlans.value.filter((p) => p.modeType === selectedMode.value)
|
|
|
+ let list = planSource.value.filter((p) => p.modeType === selectedMode.value)
|
|
|
if (selectedMode.value === 2 && selectedEfficacy.value) {
|
|
|
list = list.filter((p) => p.effectType === selectedEfficacy.value)
|
|
|
}
|
|
|
@@ -410,22 +395,46 @@ const pushDataJson = computed(() => {
|
|
|
catch { return String(pushData.value) }
|
|
|
})
|
|
|
|
|
|
-// SVG coordinate mapping: C7 大椎穴 at (200, 100), scale 0.38 px/mm
|
|
|
+// SVG coordinate mapping: align mm offsets to the realistic back photo.
|
|
|
const SVG_C7_X = 200
|
|
|
-const SVG_C7_Y = 100
|
|
|
-const SCALE = 0.38
|
|
|
+// 参考经络示意图:大椎位于颈后下缘、后正中线处,视觉上略低于头颈连接点
|
|
|
+const SVG_C7_Y = 112
|
|
|
+const SVG_S4_Y = 520
|
|
|
+const DEFAULT_SPINE_LENGTH_MM = 450
|
|
|
+const MAX_VISUAL_SPINE_LENGTH_MM = 600
|
|
|
+const FRONT_ACUPOINT_NAMES = new Set(['中脘穴', '气海穴', '关元穴'])
|
|
|
+
|
|
|
+const currentSpineLengthMm = computed(() => {
|
|
|
+ const spineLengthCm = Number(pushData.value?.bodyData?.spineLength ?? bodyForm.spineLength)
|
|
|
+ return Number.isFinite(spineLengthCm) && spineLengthCm > 0
|
|
|
+ ? spineLengthCm * 10
|
|
|
+ : DEFAULT_SPINE_LENGTH_MM
|
|
|
+})
|
|
|
+
|
|
|
+const currentSpineLengthCm = computed(() => currentSpineLengthMm.value / 10)
|
|
|
+const visualScale = (SVG_S4_Y - SVG_C7_Y) / MAX_VISUAL_SPINE_LENGTH_MM
|
|
|
+const currentSpineEndY = computed(() =>
|
|
|
+ Math.min(SVG_S4_Y, SVG_C7_Y + currentSpineLengthMm.value * visualScale)
|
|
|
+)
|
|
|
|
|
|
function bodyToSvg(offsetXmm, offsetYmm) {
|
|
|
return {
|
|
|
- x: SVG_C7_X + Number(offsetXmm) * SCALE,
|
|
|
- y: SVG_C7_Y + Number(offsetYmm) * SCALE,
|
|
|
+ x: SVG_C7_X + Number(offsetXmm) * visualScale,
|
|
|
+ y: SVG_C7_Y + Number(offsetYmm) * visualScale,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+function isBackVisualStep(step) {
|
|
|
+ if (step.offsetX == null || step.offsetY == null) return false
|
|
|
+ if (FRONT_ACUPOINT_NAMES.has(step.acupointName)) return false
|
|
|
+ const isZeroFallback = Number(step.offsetX) === 0 && Number(step.offsetY) === 0 && step.acupointName !== '大椎穴'
|
|
|
+ return !isZeroFallback
|
|
|
+}
|
|
|
+
|
|
|
const markers = computed(() => {
|
|
|
const steps = pushData.value?.scheme?.steps || []
|
|
|
return steps
|
|
|
- .filter((s) => s.offsetX != null && s.offsetY != null)
|
|
|
+ .filter(isBackVisualStep)
|
|
|
.map((s, idx) => {
|
|
|
const { x, y } = bodyToSvg(s.offsetX, s.offsetY)
|
|
|
const techniqueColors = {
|
|
|
@@ -453,6 +462,11 @@ const markers = computed(() => {
|
|
|
})
|
|
|
})
|
|
|
|
|
|
+const unmappedSteps = computed(() => {
|
|
|
+ const steps = pushData.value?.scheme?.steps || []
|
|
|
+ return steps.filter((s) => !isBackVisualStep(s))
|
|
|
+})
|
|
|
+
|
|
|
function modeLabel(modeType) {
|
|
|
const map = { 1: '一键艾灸', 2: '专业模式', 3: '自定义模式', 4: '延年圣手' }
|
|
|
return map[modeType] || modeType
|
|
|
@@ -501,10 +515,36 @@ async function loadPlans() {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+async function loadUserPlans(userId) {
|
|
|
+ if (!userId) {
|
|
|
+ userPlans.value = []
|
|
|
+ return
|
|
|
+ }
|
|
|
+ try {
|
|
|
+ // user-plan 接口自身会确保“必需方案”(一键+8功效)存在并去重
|
|
|
+ const res = await getUserPlanPage({ userId, pageNum: 1, pageSize: 200 })
|
|
|
+ const records = Array.isArray(res.data?.records) ? res.data.records : []
|
|
|
+ // 这里用于下拉展示与选择 planId,因此把 userPlan 结构“平铺”为 plan 结构
|
|
|
+ userPlans.value = records
|
|
|
+ .filter((r) => r && r.planId)
|
|
|
+ .map((r) => ({
|
|
|
+ id: r.planId,
|
|
|
+ name: r.planName,
|
|
|
+ planCode: r.planCode,
|
|
|
+ modeType: r.modeType,
|
|
|
+ effectType: r.effectType,
|
|
|
+ _userPlanId: r.id,
|
|
|
+ }))
|
|
|
+ } catch {
|
|
|
+ userPlans.value = []
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
function onUserSelect(userId) {
|
|
|
pushData.value = null
|
|
|
if (!userId) {
|
|
|
Object.keys(bodyForm).forEach((k) => (bodyForm[k] = k === 'acupointTableId' ? null : ''))
|
|
|
+ userPlans.value = []
|
|
|
return
|
|
|
}
|
|
|
const u = userOptions.value.find((x) => x.id === userId)
|
|
|
@@ -513,10 +553,20 @@ function onUserSelect(userId) {
|
|
|
bodyForm.age = u.age ?? ''
|
|
|
bodyForm.shoulderWidth = u.shoulderWidth ?? ''
|
|
|
bodyForm.bodyHeight = u.bodyHeight ?? ''
|
|
|
+ bodyForm.spineLength = u.spineLength ?? ''
|
|
|
bodyForm.fingerWidth1 = u.fingerWidth1 ?? ''
|
|
|
bodyForm.fingerWidth15 = u.fingerWidth15 ?? ''
|
|
|
bodyForm.fingerWidth3 = u.fingerWidth3 ?? ''
|
|
|
bodyForm.acupointTableId = u.acupointTableId ?? null
|
|
|
+
|
|
|
+ // 同步加载该用户的“用户方案列表”,确保专业模式选择与其一致
|
|
|
+ loadUserPlans(userId).finally(() => {
|
|
|
+ // 若当前处于专业模式且已选功效,自动对齐默认方案
|
|
|
+ if (selectedMode.value === 2 && selectedEfficacy.value) {
|
|
|
+ const match = filteredPlans.value[0]
|
|
|
+ selectedPlanId.value = match ? match.id : null
|
|
|
+ }
|
|
|
+ })
|
|
|
}
|
|
|
|
|
|
function onModeChange() {
|
|
|
@@ -525,15 +575,14 @@ function onModeChange() {
|
|
|
pushData.value = null
|
|
|
|
|
|
if (selectedMode.value === 1) {
|
|
|
- const oneClick = allPlans.value.find((p) => p.modeType === 1)
|
|
|
+ const oneClick = planSource.value.find((p) => p.modeType === 1)
|
|
|
if (oneClick) selectedPlanId.value = oneClick.id
|
|
|
}
|
|
|
}
|
|
|
|
|
|
function onEfficacyChange() {
|
|
|
+ // 方案联动由 watch 统一处理,避免异步加载用户方案时错过自动选中
|
|
|
selectedPlanId.value = null
|
|
|
- const match = filteredPlans.value[0]
|
|
|
- if (match) selectedPlanId.value = match.id
|
|
|
}
|
|
|
|
|
|
async function runSimulation() {
|
|
|
@@ -565,6 +614,23 @@ onMounted(() => {
|
|
|
loadUsers()
|
|
|
loadPlans()
|
|
|
})
|
|
|
+
|
|
|
+// 进入专业模式时,确保 userPlans 已加载(否则功效筛选拿不到方案)
|
|
|
+watch([selectedMode, selectedUserId], async ([mode, uid]) => {
|
|
|
+ if (mode === 2 && uid) {
|
|
|
+ await loadUserPlans(uid)
|
|
|
+ }
|
|
|
+})
|
|
|
+
|
|
|
+// 专业模式:功效变化或用户方案加载完成后,自动选中该功效对应方案
|
|
|
+watch([selectedMode, selectedEfficacy, filteredPlans], ([mode, eff, list]) => {
|
|
|
+ if (mode !== 2) return
|
|
|
+ if (!eff) return
|
|
|
+ if (selectedPlanId.value) return
|
|
|
+ if (Array.isArray(list) && list.length) {
|
|
|
+ selectedPlanId.value = list[0].id
|
|
|
+ }
|
|
|
+})
|
|
|
</script>
|
|
|
|
|
|
<style scoped>
|
|
|
@@ -658,6 +724,11 @@ onMounted(() => {
|
|
|
width: 100%;
|
|
|
max-width: 420px;
|
|
|
border-radius: 14px;
|
|
|
+ overflow: hidden;
|
|
|
+ background: #f8fafc;
|
|
|
+}
|
|
|
+.body-photo {
|
|
|
+ pointer-events: none;
|
|
|
}
|
|
|
|
|
|
.marker-legend {
|
|
|
@@ -749,6 +820,31 @@ onMounted(() => {
|
|
|
color: #64748b;
|
|
|
margin-top: 2px;
|
|
|
}
|
|
|
+.visual-note {
|
|
|
+ margin-top: 12px;
|
|
|
+ padding: 10px 12px;
|
|
|
+ border: 1px solid #fde68a;
|
|
|
+ border-radius: 8px;
|
|
|
+ background: #fffbeb;
|
|
|
+}
|
|
|
+.visual-note-title {
|
|
|
+ font-size: 13px;
|
|
|
+ font-weight: 700;
|
|
|
+ color: #92400e;
|
|
|
+}
|
|
|
+.visual-note-text {
|
|
|
+ display: flex;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ gap: 6px;
|
|
|
+ margin-top: 6px;
|
|
|
+}
|
|
|
+.visual-note-item {
|
|
|
+ font-size: 12px;
|
|
|
+ color: #a16207;
|
|
|
+ padding: 2px 8px;
|
|
|
+ border-radius: 8px;
|
|
|
+ background: #fef3c7;
|
|
|
+}
|
|
|
|
|
|
.json-block {
|
|
|
background: #1e1e1e;
|