style: 统一所有模块AI命理解读标题样式

- 统一使用card-header结构
- 添加圆点装饰
- 添加底部边框
- 样式工整对齐
This commit is contained in:
H1d3rOne committed 2026-03-07 09:43:52 +08:00
1 parent 723d3624a5
commit faa04ce7a8
18 files changed
+677 -84

No files matched your search

@@ -29,17 +29,7 @@ public class LiuYaoController {
setting.setLeapMonthType(request.getLeapMonthType() != null ? request.getLeapMonthType() : 0);
setting.setXuShiSuiType(request.getXuShiSuiType() != null ? request.getXuShiSuiType() : 0);
setting.setJieQiType(request.getJieQiType() != null ? request.getJieQiType() : 1);
setting.setYearGanZhiType(request.getYearGanZhiType() != null ? request.getYearGanZhiType() : 2);
setting.setMonthGanZhiType(request.getMonthGanZhiType() != null ? request.getMonthGanZhiType() : 1);
setting.setDayGanZhiType(request.getDayGanZhiType() != null ? request.getDayGanZhiType() : 0);
setting.setPaiPanType(request.getPaiPanType() != null ? request.getPaiPanType() : 0);
if (request.getLiuYaoYaoXiang() != null) {
String[] yaoXiang = request.getLiuYaoYaoXiang().split(",");
if (yaoXiang.length >= 6) {
setting.setLiuYao(yaoXiang[0].equals("—") || yaoXiang[0].equals("阳") ? 1 : 0);
setting.setWuYao(yaoXiang[1].equals("—") || yaoXiang[1].equals("阳") ? 1 : 0);
setting.setSiYao(yaoXiang[2].equals("—") || yaoXiang[2].equals("阳") ? 1 : 0);
setting.setSanYao(yaoXiang[3].equals("—") || yaoXiang[3].equals("阳") ? 1 : 0);
setting.setLiuYaoYaoXiang(request.getLiuYaoYaoXiang() != null ? request.getLiuYaoYaoXiang() : "——,——,——,——,——,——");
setting.setErYao(yaoXiang[4].equals("—") || yaoXiang[4].equals("阳") ? 1 : 0);
setting.setYiYao(yaoXiang[5].equals("—") || yaoXiang[5].equals("阳") ? 1 : 0);
}
@@ -148,4 +148,3 @@ public class TaLuoController {
public String getSpreadType() { return spreadType; }
public void setSpreadType(String spreadType) { this.spreadType = spreadType; }
}
}
@@ -10,6 +10,39 @@ import java.util.*;
@RestController
@RequestMapping("/api/ziwei")
private static final Map<String, String> ZHU_XING_JIE_DU = new HashMap<>();
private static final Map<String, String> GONG_WEI_JIE_DU = new HashMap<>();
static {
ZHU_XING_JIE_DU.put("紫微", "帝王之星,主权威领导,性格稳重有魄力,适合管理岗位,天生具有统御能力");
ZHU_XING_JIE_DU.put("天机", "智慧之星,主聪明机敏,善于策划分析,适合参谋顾问,思维活跃多变");
ZHU_XING_JIE_DU.put("太阳", "光明之星,主外向热情,事业心强,利于公职发展,贵人运旺");
ZHU_XING_JIE_DU.put("武曲", "财星,主刚毅果断,理财能力强,适合金融商业,财运亨通");
ZHU_XING_JIE_DU.put("天同", "福星,主温和仁慈,人缘好福气厚,适合服务行业,生活安逸");
ZHU_XING_JIE_DU.put("廉贞", "桃花星,主才华艺术,感情丰富,适合文艺创作,魅力十足");
ZHU_XING_JIE_DU.put("天府", "财库星,主稳重守成,善于理财积累,适合财务管理,财源稳定");
ZHU_XING_JIE_DU.put("太阴", "阴柔之星,主细腻敏感,直觉力强,适合文艺创作,财运平稳");
ZHU_XING_JIE_DU.put("贪狼", "欲望之星,主多才多艺,交际能力强,适合演艺销售,但需防贪欲");
ZHU_XING_JIE_DU.put("巨门", "口舌之星,主能言善辩,适合律师教师,但易招是非口舌");
ZHU_XING_JIE_DU.put("天相", "印星,主正直公正,适合公务员法律,贵人运佳,事业平稳");
ZHU_XING_JIE_DU.put("天梁", "荫星,主慈悲为怀,适合医疗教育,有长辈贵人,福泽深厚");
ZHU_XING_JIE_DU.put("七杀", "将星,主刚强果断,适合军警创业,有领导才能,但需防冲动");
ZHU_XING_JIE_DU.put("破军", "变动之星,主开创冒险,适合创业改革,变动多端,需稳中求进");
GONG_WEI_JIE_DU.put("命宫", "代表核心性格、人生基调、先天特质");
GONG_WEI_JIE_DU.put("兄弟宫", "代表兄弟姐妹关系、同辈交往、合作能力");
GONG_WEI_JIE_DU.put("夫妻宫", "代表婚姻感情、配偶特质、婚姻质量");
GONG_WEI_JIE_DU.put("子女宫", "代表子女运势、后代情况、桃花缘分");
GONG_WEI_JIE_DU.put("财帛宫", "代表财富来源、理财能力、财运起伏");
GONG_WEI_JIE_DU.put("疾厄宫", "代表健康状况、易患疾病、养生方向");
GONG_WEI_JIE_DU.put("迁移宫", "代表外出运势、人际交往、贵人运");
GONG_WEI_JIE_DU.put("交友宫", "代表朋友关系、下属能力、人际网络");
GONG_WEI_JIE_DU.put("官禄宫", "代表事业发展、职业方向、官运仕途");
GONG_WEI_JIE_DU.put("田宅宫", "代表房产运势、家庭环境、祖业继承");
GONG_WEI_JIE_DU.put("福德宫", "代表精神状态、福报厚薄、晚年运势");
GONG_WEI_JIE_DU.put("父母宫", "代表父母关系、长辈助力、学历背景");
}
public class ZiWeiController {
private final HunYuanAiService aiService = new HunYuanAiService();
@@ -43,79 +76,125 @@ public class ZiWeiController {
data.put("aiAnalysis", aiAnalysis);
result.put("success", true);
data.put("occupy", ziWei.getOccupy());
result.put("data", data);
} catch (Exception e) {
data.put("zao", ziWei.getZao());
result.put("success", false);
result.put("error", e.getMessage());
}
data.put("xingQi", ziWei.getXingQi());
data.put("jiJie", ziWei.getJiJie());
return result;
}
data.put("yueXiang", ziWei.getYueXiang());
data.put("yueJiang", ziWei.getYueJiang());
data.put("yueJiangShen", ziWei.getYueJiangShen());
data.put("wuBuYuShi", ziWei.getWuBuYuShi());
data.put("yearGan", ziWei.getYearGan());
data.put("monthGan", ziWei.getMonthGan());
data.put("dayGan", ziWei.getDayGan());
data.put("hourGan", ziWei.getHourGan());
data.put("yearZhi", ziWei.getYearZhi());
data.put("monthZhi", ziWei.getMonthZhi());
data.put("dayZhi", ziWei.getDayZhi());
data.put("hourZhi", ziWei.getHourZhi());
private Map<String, Object> buildZiWeiData(ZiWei ziWei) {
Map<String, Object> data = new HashMap<>();
data.put("name", ziWei.getName());
data.put("sex", ziWei.getSex());
data.put("age", ziWei.getAge());
data.put("yearGanZhiNaYin", ziWei.getYearGanZhiNaYin());
data.put("monthGanZhiNaYin", ziWei.getMonthGanZhiNaYin());
data.put("dayGanZhiNaYin", ziWei.getDayGanZhiNaYin());
data.put("hourGanZhiNaYin", ziWei.getHourGanZhiNaYin());
data.put("nanNvYinYang", ziWei.getNanNvYinYang());
data.put("mingGongGongWei", ziWei.getMingGongGongWei());
data.put("shenGongGongWei", ziWei.getShenGongGongWei());
data.put("solar", ziWei.getSolarStr2());
data.put("lunar", ziWei.getLunarStr2());
data.put("shengXiao", ziWei.getShengXiao());
data.put("wuXingJu", ziWei.getWuXingJu());
data.put("xingZuo", ziWei.getXingZuo());
data.put("wuXingJu", ziWei.getWuXingJu());
data.put("yearGanZhi", ziWei.getYearGanZhi());
data.put("monthGanZhi", ziWei.getMonthGanZhi());
data.put("dayGanZhi", ziWei.getDayGanZhi());
data.put("ziWeiXingGongWei", ziWei.getZiWeiXingGongWei());
data.put("tianFuXingGongWei", ziWei.getTianFuXingGongWei());
data.put("ziWeiXingGongDiZhi", ziWei.getZiWeiXingGongDiZhi());
data.put("tianFuXingGongDiZhi", ziWei.getTianFuXingGongDiZhi());
data.put("ziWeiXingXiZhuXing", ziWei.getZiWeiXingXiZhuXing());
data.put("tianFuXingXiZhuXing", ziWei.getTianFuXingXiZhuXing());
data.put("shiZhiZhuXing", ziWei.getShiZhiZhuXing());
data.put("yueZhiZhuXing", ziWei.getYueZhiZhuXing());
data.put("nianGanZhuXing", ziWei.getNianGanZhuXing());
data.put("nianZhiZhuXing", ziWei.getNianZhiZhuXing());
data.put("dayZhuXing", ziWei.getDayZhuXing());
data.put("shiErZhangSheng", ziWei.getShiErZhangSheng());
data.put("jieLuKongWang", ziWei.getJieLuKongWang());
data.put("xunZhongKongWang", ziWei.getXunZhongKongWang());
data.put("tianShangTianShiXing", ziWei.getTianShangTianShiXing());
data.put("daXian", ziWei.getDaXian());
data.put("xiaoXian", ziWei.getXiaoXian());
data.put("shiErGongBoShi", ziWei.getShiErGongBoShi());
data.put("liuNianSuiQianZhuXing", ziWei.getLiuNianSuiQianZhuXing());
data.put("liuNianJiangQianZhuXing", ziWei.getLiuNianJiangQianZhuXing());
data.put("hourGanZhi", ziWei.getHourGanZhi());
data.put("mingGongDiZhi", ziWei.getMingGongDiZhi());
data.put("shenGongDiZhi", ziWei.getShenGongDiZhi());
data.put("mingZhu", ziWei.getMingZhu());
data.put("shiErGongZhuXingGuanXi", ziWei.getShiErGongZhuXingGuanXi());
data.put("huaLuXingGongWei", ziWei.getHuaLuXingGongWei());
data.put("huaQuanXingGongWei", ziWei.getHuaQuanXingGongWei());
data.put("huaKeXingGongWei", ziWei.getHuaKeXingGongWei());
data.put("huaJiXingGongWei", ziWei.getHuaJiXingGongWei());
data.put("shenZhu", ziWei.getShenZhu());
data.put("shiErGongDiZhi", ziWei.getShiErGongDiZhi());
data.put("shiErGongTianGan", ziWei.getShiErGongTianGan());
data.put("shiErMingGong", ziWei.getShiErMingGong());
data.put("shiErShenGong", ziWei.getShiErShenGong());
List<List<String>> shiErGongZhuXing = ziWei.getShiErGongZhuXing(false);
data.put("shiErGongZhuXing", shiErGongZhuXing);
data.put("shiErGongSiHuaXing", ziWei.getShiErGongSiHuaXing());
data.put("shiErZhangSheng", ziWei.getShiErZhangSheng());
data.put("daXian", ziWei.getDaXian());
data.put("shiErGongSiHuaXingGuanXi", ziWei.getShiErGongSiHuaXingGuanXi());
data.put("mingZhu", ziWei.getMingZhu());
data.put("shenZhu", ziWei.getShenZhu());
data.put("ziDou", ziWei.getZiDou());
data.put("liuDou", ziWei.getLiuDou());
data.put("prevJie", ziWei.getPrevJie());
data.put("nextJie", ziWei.getNextJie());
data.put("chuShengJie", ziWei.getChuShengJie());
data.put("prevQi", ziWei.getPrevQi());
data.put("nextQi", ziWei.getNextQi());
data.put("chuShengQi", ziWei.getChuShengQi());
data.put("huaLuXingGongWeiJieDu", ziWei.getHuaLuXingGongWeiJieDu());
data.put("huaQuanXingGongWeiJieDu", ziWei.getHuaQuanXingGongWeiJieDu());
data.put("huaKeXingGongWeiJieDu", ziWei.getHuaKeXingGongWeiJieDu());
data.put("huaJiXingGongWeiJieDu", ziWei.getHuaJiXingGongWeiJieDu());
data.put("jieDu", buildJieDu(ziWei, shiErMingGong, shiErGongZhuXing));
return data;
}
public static class ZiWeiRequest {
private String name;
private String occupy;
private Integer sex;
private String date;
private Integer dateType;
private Integer leapMonthType;
private Integer xuShiSuiType;
private Integer jieQiType;
private Integer wuXingJuType;
private Integer yearGanZhiType;
private Integer monthGanZhiType;
private Integer dayGanZhiType;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getOccupy() { return occupy; }
public void setOccupy(String occupy) { this.occupy = occupy; }
public Integer getSex() { return sex; }
public void setSex(Integer sex) { this.sex = sex; }
private Map<String, Object> buildJieDu(ZiWei ziWei, List<String> shiErMingGong, List<List<String>> shiErGongZhuXing) {
Map<String, Object> jieDu = new HashMap<>();
int mingGongIndex = ziWei.getMingGongGongWei() - 1;
List<String> mingGongStars = shiErGongZhuXing.get(mingGongIndex);
public String getDate() { return date; }
public void setDate(String date) { this.date = date; }
public Integer getDateType() { return dateType; }
for (String star : mingGongStars) {
if (ZHU_XING_JIE_DU.containsKey(star)) {
public void setDateType(Integer dateType) { this.dateType = dateType; }
public Integer getLeapMonthType() { return leapMonthType; }
public void setLeapMonthType(Integer leapMonthType) { this.leapMonthType = leapMonthType; }
@@ -0,0 +1,153 @@
<template>
<view class="markdown-container">
<view v-for="(node, index) in nodes" :key="index" class="markdown-node">
<!-- 标题 -->
<view v-if="node.type === 'h1'" class="md-h1">
<text>{{ node.text }}</text>
</view>
<view v-else-if="node.type === 'h2'" class="md-h2">
<text>{{ node.text }}</text>
</view>
<view v-else-if="node.type === 'h3'" class="md-h3">
<text>{{ node.text }}</text>
</view>
<!-- 段落 -->
<view v-else-if="node.type === 'paragraph'" class="md-paragraph">
<text v-for="(child, idx) in node.children" :key="idx" :class="getTextClass(child)">
{{ child.text }}
</text>
</view>
<!-- 列表 -->
<view v-else-if="node.type === 'list'" class="md-list">
<view v-for="(item, idx) in node.items" :key="idx" class="md-list-item">
<view class="md-list-bullet">
<text>•</text>
</view>
<view class="md-list-content">
<text v-for="(child, cidx) in item.children" :key="cidx" :class="getTextClass(child)">
{{ child.text }}
</text>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
import { parseMarkdown } from '@/utils/markdown.js'
export default {
name: 'MarkdownRenderer',
props: {
content: {
type: String,
default: ''
}
},
computed: {
nodes() {
return parseMarkdown(this.content)
}
},
methods: {
getTextClass(child) {
const classes = []
if (child.type === 'bold') classes.push('md-bold')
if (child.type === 'italic') classes.push('md-italic')
if (child.type === 'code') classes.push('md-code')
return classes.join(' ')
}
}
}
</script>
<style scoped>
.markdown-container {
width: 100%;
}
.md-h1 {
font-size: 36rpx;
font-weight: bold;
color: #1F2937;
margin: 24rpx 0 16rpx 0;
padding-bottom: 12rpx;
border-bottom: 2rpx solid #E5E7EB;
}
.md-h2 {
font-size: 32rpx;
font-weight: bold;
color: #374151;
margin: 20rpx 0 12rpx 0;
padding-left: 16rpx;
border-left: 4rpx solid #F59E0B;
}
.md-h3 {
font-size: 28rpx;
font-weight: 600;
color: #4B5563;
margin: 16rpx 0 8rpx 0;
}
.md-paragraph {
font-size: 26rpx;
color: #374151;
line-height: 1.8;
margin: 12rpx 0;
text-align: justify;
}
.md-list {
margin: 12rpx 0;
}
.md-list-item {
display: flex;
align-items: flex-start;
margin: 8rpx 0;
padding-left: 8rpx;
}
.md-list-bullet {
width: 24rpx;
height: 24rpx;
display: flex;
align-items: center;
justify-content: center;
margin-right: 8rpx;
margin-top: 4rpx;
color: #F59E0B;
font-size: 20rpx;
}
.md-list-content {
flex: 1;
font-size: 26rpx;
color: #374151;
line-height: 1.8;
}
.md-bold {
font-weight: bold;
color: #1F2937;
}
.md-italic {
font-style: italic;
color: #6B7280;
}
.md-code {
font-family: monospace;
background: #F3F4F6;
padding: 2rpx 8rpx;
border-radius: 4rpx;
color: #DC2626;
font-size: 24rpx;
}
</style>
+7
View File
@@ -1,4 +1,11 @@
{
"easycom": {
"autoscan": true,
"custom": {
"markdown-renderer": "@/components/MarkdownRenderer.vue",
"^uni-(.*)": "@dcloudio/uni-ui/lib/uni-$1/uni-$1.vue"
}
},
"pages": [
{
"path": "pages/index/index",
+1 -1
View File
@@ -24,7 +24,7 @@
<view class="form-item">
<view class="form-label-wrapper">
<text class="form-label">公历日期</text>
<text class="form-label">出生日期</text>
</view>
<picker mode="date" :value="solarDate" @change="onDateChange" class="form-picker">
<view class="picker-content">
@@ -31,7 +31,7 @@
<view class="form-item">
<view class="form-label-wrapper">
<text class="form-label">公历日期</text>
<text class="form-label">出生日期</text>
</view>
<picker mode="date" :value="solarDate" @change="onDateChange" class="form-picker">
<view class="picker-content">
@@ -20,9 +20,12 @@
</view>
<view class="ai-card" v-if="result.aiAnalysis">
<view class="section-title">🤖 AI课体解读</view>
<view class="card-header">
<view class="card-dot green"></view>
<text class="card-title">🤖 AI课体解读</text>
</view>
<view class="ai-content">
<text class="ai-text">{{ result.aiAnalysis }}</text>
<rich-text :nodes="markdownHtml" class="markdown-content"></rich-text>
</view>
</view>
@@ -214,12 +217,20 @@
</template>
<script>
import { markdownToHtml } from '@/utils/markdownToHtml.js'
export default {
data() {
return {
result: {}
}
},
computed: {
markdownHtml() {
if (!this.result.aiAnalysis) return ''
return markdownToHtml(this.result.aiAnalysis)
}
},
onLoad() {
this.result = getApp().globalData.daliurenResult || {}
console.log('大六壬结果:', this.result)
@@ -326,6 +337,31 @@ page {
border-bottom: 2rpx solid #D1FAE5;
}
.card-header {
display: flex;
align-items: center;
margin-bottom: 20rpx;
padding-bottom: 16rpx;
border-bottom: 2rpx solid #D1FAE5;
}
.card-title {
font-size: 30rpx;
font-weight: 600;
color: #065F46;
}
.card-dot {
width: 8rpx;
height: 8rpx;
border-radius: 50%;
margin-right: 12rpx;
}
.card-dot.green {
background: #059669;
}
.bazhi-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
+7 -11
View File
@@ -32,17 +32,7 @@
<text class="card-title">🤖 AI卦象解读</text>
</view>
<view class="ai-content">
<text class="ai-text">{{ result.aiAnalysis }}</text>
</view>
</view>
<view class="ai-card" v-if="result.aiAnalysis">
<view class="card-header">
<view class="card-dot gold"></view>
<text class="card-title">🤖 AI卦象解读</text>
</view>
<view class="ai-content">
<text class="ai-text">{{ result.aiAnalysis }}</text>
<rich-text :nodes="markdownHtml" class="markdown-content"></rich-text>
</view>
</view>
@@ -187,6 +177,8 @@
</template>
<script>
import { markdownToHtml } from '@/utils/markdownToHtml.js'
export default {
data() {
return {
@@ -211,6 +203,10 @@ export default {
})
}
return data.reverse()
},
markdownHtml() {
if (!this.result.aiAnalysis) return ''
return markdownToHtml(this.result.aiAnalysis)
}
},
onLoad() {
+7 -11
View File
@@ -32,17 +32,7 @@
<text class="card-title">🤖 AI卦象解读</text>
</view>
<view class="ai-content">
<text class="ai-text">{{ result.aiAnalysis }}</text>
</view>
</view>
<view class="ai-card" v-if="result.aiAnalysis">
<view class="card-header">
<view class="card-dot gold"></view>
<text class="card-title">🤖 AI卦象解读</text>
</view>
<view class="ai-content">
<text class="ai-text">{{ result.aiAnalysis }}</text>
<rich-text :nodes="markdownHtml" class="markdown-content"></rich-text>
</view>
</view>
@@ -221,6 +211,8 @@
</template>
<script>
import { markdownToHtml } from '@/utils/markdownToHtml.js'
export default {
data() {
return {
@@ -228,6 +220,10 @@ export default {
}
},
computed: {
markdownHtml() {
if (!this.result.aiAnalysis) return ''
return markdownToHtml(this.result.aiAnalysis)
},
liuYaoData() {
if (!this.result.benGuaLiuYaoName) return []
+1 -1
View File
@@ -31,7 +31,7 @@
<view class="form-item">
<view class="form-label-wrapper">
<text class="form-label">公历日期</text>
<text class="form-label">出生日期</text>
</view>
<picker mode="date" :value="solarDate" @change="onDateChange" class="form-picker">
<view class="picker-content">
+34 -4
View File
@@ -60,9 +60,12 @@
</view>
<view class="ai-card" v-if="data.aiAnalysis">
<text class="card-title">🤖 AI奇门解读</text>
<view class="card-header">
<view class="card-dot gold"></view>
<text class="card-title">🤖 AI奇门解读</text>
</view>
<view class="ai-content">
<text class="ai-text">{{ data.aiAnalysis }}</text>
<rich-text :nodes="markdownHtml" class="markdown-content"></rich-text>
</view>
</view>
@@ -156,7 +159,7 @@
<view class="ai-card" v-if="data.aiAnalysis">
<text class="card-title">🤖 AI奇门解读</text>
<view class="ai-content">
<text class="ai-text">{{ data.aiAnalysis }}</text>
<rich-text :nodes="markdownHtml" class="markdown-content"></rich-text>
</view>
</view>
@@ -267,6 +270,8 @@
</template>
<script>
import { markdownToHtml } from '@/utils/markdownToHtml.js'
export default {
data() {
return {
@@ -274,6 +279,12 @@ export default {
gongNames: ['坎一宫', '坤二宫', '震三宫', '巽四宫', '中五宫', '乾六宫', '兑七宫', '艮八宫', '离九宫']
}
},
computed: {
markdownHtml() {
if (!this.data.aiAnalysis) return ''
return markdownToHtml(this.data.aiAnalysis)
}
},
onLoad() {
this.data = getApp().globalData.qimenResult || {}
},
@@ -412,12 +423,31 @@ page {
font-size: 30rpx;
font-weight: 600;
color: #1F2937;
display: block;
}
.card-header {
display: flex;
align-items: center;
margin-bottom: 20rpx;
padding-bottom: 16rpx;
border-bottom: 2rpx solid #F3F4F6;
}
.card-dot {
width: 8rpx;
height: 8rpx;
border-radius: 50%;
margin-right: 12rpx;
}
.card-dot.gold {
background: #F59E0B;
}
.card-dot.purple {
background: #8B5CF6;
}
.jiugong-grid {
display: flex;
flex-direction: column;
@@ -36,7 +36,7 @@
<text class="card-title">🤖 AI塔罗解读</text>
</view>
<view class="ai-content">
<text class="ai-text">{{ result.aiAnalysis }}</text>
<rich-text :nodes="markdownHtml" class="markdown-content"></rich-text>
</view>
</view>
@@ -109,12 +109,20 @@
</template>
<script>
import { markdownToHtml } from '@/utils/markdownToHtml.js'
export default {
data() {
return {
result: {}
}
},
computed: {
markdownHtml() {
if (!this.result.aiAnalysis) return ''
return markdownToHtml(this.result.aiAnalysis)
}
},
onLoad() {
this.result = getApp().globalData.taLuoResult || {}
},
@@ -32,7 +32,7 @@
<text class="card-title">🤖 AI星盘解读</text>
</view>
<view class="ai-content">
<text class="ai-text">{{ result.aiAnalysis }}</text>
<rich-text :nodes="markdownHtml" class="markdown-content"></rich-text>
</view>
</view>
@@ -206,6 +206,8 @@
</template>
<script>
import { markdownToHtml } from '@/utils/markdownToHtml.js'
export default {
data() {
return {
@@ -220,6 +222,12 @@ export default {
}
}
},
computed: {
markdownHtml() {
if (!this.result.aiAnalysis) return ''
return markdownToHtml(this.result.aiAnalysis)
}
},
onLoad() {
this.result = getApp().globalData.zhanxingResult || {}
this.generateInterpretation()
+47 -4
View File
@@ -21,12 +21,12 @@
</view>
<view class="ai-card" v-if="result.aiAnalysis">
<view class="section-title">
<text class="title-icon">🤖</text>
<text class="title-text">AI命理解读</text>
<view class="card-header">
<view class="card-dot purple"></view>
<text class="header-title">🤖 AI命理解读</text>
</view>
<view class="ai-content">
<text class="ai-text">{{ result.aiAnalysis }}</text>
<rich-text :nodes="markdownHtml" class="markdown-content"></rich-text>
</view>
</view>
@@ -138,6 +138,12 @@ export default {
gongData: Array(12).fill({})
}
},
computed: {
markdownHtml() {
if (!this.result.aiAnalysis) return ''
return this.markdownToHtml(this.result.aiAnalysis)
}
},
onLoad() {
const app = getApp()
if (app.globalData && app.globalData.ziweiResult) {
@@ -150,6 +156,40 @@ export default {
}
},
methods: {
markdownToHtml(markdown) {
if (!markdown) return ''
let html = markdown
const lines = html.split('\n')
if (lines.length > 0) {
lines.shift()
html = lines.join('\n').trim()
}
html = html.replace(/^### (.*$)/gim, '<h3 style="font-size:28rpx;font-weight:600;color:#92400E;margin:24rpx 0 12rpx 0;padding:8rpx 16rpx;border-bottom:2rpx dashed #F59E0B;display:inline-block">$1</h3>')
html = html.replace(/^## (.*$)/gim, '<h2 style="font-size:32rpx;font-weight:bold;color:#B91C1C;margin:28rpx 0 16rpx 0;padding:12rpx 20rpx;background:linear-gradient(90deg,#FFF7ED 0%,transparent 100%);border-left:4rpx solid #F59E0B">$1</h2>')
html = html.replace(/^# (.*$)/gim, '<h1 style="font-size:36rpx;font-weight:bold;color:#DC2626;margin:32rpx 0 20rpx 0;padding:16rpx 24rpx;background:linear-gradient(135deg,#FEF2F2 0%,#FEE2E2 100%);border-left:6rpx solid #DC2626;border-radius:8rpx">$1</h1>')
html = html.replace(/\*\*(.+?)\*\*/g, '<strong style="font-weight:bold;color:#DC2626;background:linear-gradient(135deg,#FEF2F2 0%,transparent 100%);padding:2rpx 8rpx;border-radius:4rpx">$1</strong>')
html = html.replace(/\*(.+?)\*/g, '<em style="font-style:normal;color:#7C3AED;font-weight:500">$1</em>')
html = html.replace(/`(.+?)`/g, '<code style="font-family:Courier New,monospace;background:linear-gradient(135deg,#FEF3C7 0%,#FDE68A 100%);padding:4rpx 12rpx;border-radius:6rpx;color:#92400E;font-size:24rpx;border:1rpx solid #F59E0B;font-weight:500">$1</code>')
html = html.replace(/^\s*[-•]\s(.+)$/gim, '<li style="margin:12rpx 0;padding:12rpx 16rpx 12rpx 24rpx;background:linear-gradient(90deg,#F0FDF4 0%,transparent 100%);border-left:3rpx solid #10B981;color:#374151;line-height:1.8">$1</li>')
html = html.replace(/(<li[^>]*>.*<\/li>\n?)+/g, function(match) {
return '<ul style="margin:16rpx 0;padding-left:0;list-style:none">' + match + '</ul>'
})
html = html.replace(/\n\n/g, '</p><p style="margin:16rpx 0;text-align:justify;text-indent:2em;color:#4B5563;line-height:2">')
html = html.replace(/\n/g, '<br/>')
if (!html.startsWith('<')) {
html = '<p style="margin:16rpx 0;text-align:justify;text-indent:2em;color:#4B5563;line-height:2">' + html + '</p>'
}
return html
},
isMingGong(index) {
return this.result.mingGongGongWei === (index + 1)
},
@@ -352,6 +392,8 @@ page {
display: flex;
align-items: center;
margin-bottom: 20rpx;
padding-bottom: 16rpx;
border-bottom: 2rpx solid #F3F4F6;
}
.header-title {
@@ -371,6 +413,7 @@ page {
.card-dot.cyan { background: #06B6D4; }
.card-dot.orange { background: #F97316; }
.card-dot.purple { background: #8B5CF6; }
.sizhu-row {
display: flex;
+1 -1
View File
@@ -24,7 +24,7 @@
<view class="form-item">
<view class="form-label-wrapper">
<text class="form-label">公历日期</text>
<text class="form-label">出生日期</text>
</view>
<picker mode="date" :value="solarDate" @change="onDateChange" class="form-picker">
<view class="picker-content">
+214
View File
@@ -0,0 +1,214 @@
/**
* Markdown解析工具
* 将Markdown文本转换为小程序富文本格式
*/
export function parseMarkdown(text) {
if (!text) return []
const nodes = []
const lines = text.split('\n')
let currentParagraph = []
let listItems = []
let inList = false
lines.forEach((line, index) => {
line = line.trim()
if (line === '') {
if (currentParagraph.length > 0) {
nodes.push({
type: 'paragraph',
children: parseInlineText(currentParagraph.join('\n'))
})
currentParagraph = []
}
if (inList && listItems.length > 0) {
nodes.push({
type: 'list',
items: listItems
})
listItems = []
inList = false
}
return
}
if (line.startsWith('### ')) {
if (currentParagraph.length > 0) {
nodes.push({
type: 'paragraph',
children: parseInlineText(currentParagraph.join('\n'))
})
currentParagraph = []
}
if (inList && listItems.length > 0) {
nodes.push({
type: 'list',
items: listItems
})
listItems = []
inList = false
}
nodes.push({
type: 'h3',
text: line.substring(4)
})
} else if (line.startsWith('## ')) {
if (currentParagraph.length > 0) {
nodes.push({
type: 'paragraph',
children: parseInlineText(currentParagraph.join('\n'))
})
currentParagraph = []
}
if (inList && listItems.length > 0) {
nodes.push({
type: 'list',
items: listItems
})
listItems = []
inList = false
}
nodes.push({
type: 'h2',
text: line.substring(3)
})
} else if (line.startsWith('# ')) {
if (currentParagraph.length > 0) {
nodes.push({
type: 'paragraph',
children: parseInlineText(currentParagraph.join('\n'))
})
currentParagraph = []
}
if (inList && listItems.length > 0) {
nodes.push({
type: 'list',
items: listItems
})
listItems = []
inList = false
}
nodes.push({
type: 'h1',
text: line.substring(2)
})
} else if (line.startsWith('• ') || line.startsWith('- ') || line.startsWith('* ')) {
if (currentParagraph.length > 0) {
nodes.push({
type: 'paragraph',
children: parseInlineText(currentParagraph.join('\n'))
})
currentParagraph = []
}
inList = true
listItems.push({
children: parseInlineText(line.substring(2))
})
} else if (line.match(/^\d+\.\s/)) {
if (currentParagraph.length > 0) {
nodes.push({
type: 'paragraph',
children: parseInlineText(currentParagraph.join('\n'))
})
currentParagraph = []
}
inList = true
const text = line.replace(/^\d+\.\s/, '')
listItems.push({
children: parseInlineText(text)
})
} else {
if (inList && listItems.length > 0) {
nodes.push({
type: 'list',
items: listItems
})
listItems = []
inList = false
}
currentParagraph.push(line)
}
})
if (currentParagraph.length > 0) {
nodes.push({
type: 'paragraph',
children: parseInlineText(currentParagraph.join('\n'))
})
}
if (listItems.length > 0) {
nodes.push({
type: 'list',
items: listItems
})
}
return nodes
}
function parseInlineText(text) {
const children = []
let remaining = text
while (remaining.length > 0) {
let matched = false
const boldMatch = remaining.match(/\*\*(.+?)\*\*/)
if (boldMatch) {
const before = remaining.substring(0, boldMatch.index)
if (before) {
children.push({ type: 'text', text: before })
}
children.push({ type: 'bold', text: boldMatch[1] })
remaining = remaining.substring(boldMatch.index + boldMatch[0].length)
matched = true
continue
}
const italicMatch = remaining.match(/\*(.+?)\*/)
if (italicMatch) {
const before = remaining.substring(0, italicMatch.index)
if (before) {
children.push({ type: 'text', text: before })
}
children.push({ type: 'italic', text: italicMatch[1] })
remaining = remaining.substring(italicMatch.index + italicMatch[0].length)
matched = true
continue
}
const codeMatch = remaining.match(/`(.+?)`/)
if (codeMatch) {
const before = remaining.substring(0, codeMatch.index)
if (before) {
children.push({ type: 'text', text: before })
}
children.push({ type: 'code', text: codeMatch[1] })
remaining = remaining.substring(codeMatch.index + codeMatch[0].length)
matched = true
continue
}
if (!matched) {
children.push({ type: 'text', text: remaining })
break
}
}
return children
}
export function renderMarkdownToText(text) {
if (!text) return ''
return text
.replace(/\*\*(.+?)\*\*/g, '$1')
.replace(/\*(.+?)\*/g, '$1')
.replace(/`(.+?)`/g, '$1')
.replace(/^#+\s/gm, '')
.replace(/^[•\-\*]\s/gm, '')
.replace(/^\d+\.\s/gm, '')
}
@@ -0,0 +1,34 @@
export function markdownToHtml(markdown) {
if (!markdown) return ''
let html = markdown
const lines = html.split('\n')
if (lines.length > 0) {
lines.shift()
html = lines.join('\n').trim()
}
html = html.replace(/^### (.*$)/gim, '<h3 style="font-size:28rpx;font-weight:600;color:#92400E;margin:24rpx 0 16rpx 0;padding:12rpx 20rpx;border-bottom:2rpx dashed #F59E0B;display:inline-block;background:linear-gradient(90deg,#FFFBEB 0%,transparent 100%)">$1</h3>')
html = html.replace(/^## (.*$)/gim, '<h2 style="font-size:32rpx;font-weight:bold;color:#B91C1C;margin:32rpx 0 20rpx 0;padding:16rpx 24rpx;background:linear-gradient(90deg,#FFF7ED 0%,transparent 100%);border-left:6rpx solid #F59E0B;border-radius:0 12rpx 12rpx 0">$1</h2>')
html = html.replace(/^# (.*$)/gim, '<h1 style="font-size:36rpx;font-weight:bold;color:#DC2626;margin:40rpx 0 24rpx 0;padding:20rpx 28rpx;background:linear-gradient(135deg,#FEF2F2 0%,#FEE2E2 100%);border-left:8rpx solid #DC2626;border-radius:12rpx;box-shadow:0 4rpx 12rpx rgba(220,38,38,0.1)">$1</h1>')
html = html.replace(/\*\*(.+?)\*\*/g, '<strong style="font-weight:bold;color:#DC2626;background:linear-gradient(135deg,#FEF2F2 0%,transparent 100%);padding:4rpx 12rpx;border-radius:6rpx;border:1rpx solid rgba(220,38,38,0.2)">$1</strong>')
html = html.replace(/\*(.+?)\*/g, '<em style="font-style:normal;color:#7C3AED;font-weight:600;background:linear-gradient(135deg,#F5F3FF 0%,transparent 100%);padding:2rpx 8rpx;border-radius:4rpx">$1</em>')
html = html.replace(/`(.+?)`/g, '<code style="font-family:Courier New,monospace;background:linear-gradient(135deg,#FEF3C7 0%,#FDE68A 100%);padding:6rpx 16rpx;border-radius:8rpx;color:#92400E;font-size:24rpx;border:2rpx solid #F59E0B;font-weight:600;box-shadow:0 2rpx 8rpx rgba(245,158,11,0.2)">$1</code>')
html = html.replace(/^\s*[-•]\s(.+)$/gim, '<li style="margin:16rpx 0;padding:16rpx 20rpx 16rpx 32rpx;background:linear-gradient(90deg,#F0FDF4 0%,transparent 100%);border-left:4rpx solid #10B981;color:#374151;line-height:2;border-radius:0 12rpx 12rpx 0;box-shadow:0 2rpx 8rpx rgba(16,185,129,0.1)">$1</li>')
html = html.replace(/(<li[^>]*>.*<\/li>\n?)+/g, function(match) {
return '<ul style="margin:24rpx 0;padding-left:0;list-style:none;background:rgba(240,253,244,0.3);padding:16rpx;border-radius:16rpx;border:1rpx solid rgba(16,185,129,0.2)">' + match + '</ul>'
})
html = html.replace(/\n\n/g, '</p><p style="margin:20rpx 0;text-align:justify;text-indent:2em;color:#4B5563;line-height:2.2;font-size:26rpx;letter-spacing:1rpx">')
html = html.replace(/\n/g, '<br style="display:block;margin:8rpx 0"/>')
if (!html.startsWith('<')) {
html = '<p style="margin:20rpx 0;text-align:justify;text-indent:2em;color:#4B5563;line-height:2.2;font-size:26rpx;letter-spacing:1rpx">' + html + '</p>'
}
return html
}