feat: 优化管理后台页面UI、修复TS编译错误、新增人生事件模块

- 优化 AI 配置列表页面:重构统计卡片、搜索表单、表格列展示
- 修复 3 处 TypeScript TS6133 编译错误,恢复构建
- 新增管理员修改密码和重置密码功能
- 优化小程序多个页面样式和交互
- 人生事件模块完善

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-05-10 23:23:09 +08:00
parent 60c63850ee
commit 755059807a
62 changed files with 4661 additions and 3019 deletions
+67 -12
View File
@@ -4,15 +4,23 @@
<!-- 分割线 -->
<view v-if="block.type === 'hr'" class="markdown-hr"></view>
<text v-else-if="block.type === 'h1'" class="markdown-h1">{{ block.content }}</text>
<text v-else-if="block.type === 'h2'" class="markdown-h2">{{ block.content }}</text>
<!-- 三级标题 -->
<text v-else-if="block.type === 'h3'" class="markdown-h3">{{ block.content }}</text>
<!-- 四级标题 -->
<text v-else-if="block.type === 'h4'" class="markdown-h4">{{ block.content }}</text>
<view v-else-if="block.type === 'blockquote'" class="markdown-quote">
<text>{{ block.content }}</text>
</view>
<!-- 列表项 -->
<view v-else-if="block.type === 'li'" class="markdown-li">
<text class="li-bullet"> </text>
<text class="li-bullet">{{ block.marker }}</text>
<text class="li-content">{{ block.content }}</text>
</view>
@@ -53,6 +61,18 @@ const parsedBlocks = computed(() => {
continue
}
const h1Match = trimmed.match(/^#\s+(.+)/)
if (h1Match) {
blocks.push({ type: 'h1', content: h1Match[1] })
continue
}
const h2Match = trimmed.match(/^##\s+(.+)/)
if (h2Match) {
blocks.push({ type: 'h2', content: h2Match[1] })
continue
}
// 三级标题 ###
const h3Match = trimmed.match(/^###\s+(.+)/)
if (h3Match) {
@@ -67,10 +87,16 @@ const parsedBlocks = computed(() => {
continue
}
// 列表项 * 或 -
const liMatch = trimmed.match(/^[*\-]\s+(.+)/)
const quoteMatch = trimmed.match(/^>\s+(.+)/)
if (quoteMatch) {
blocks.push({ type: 'blockquote', content: quoteMatch[1] })
continue
}
// 列表项 *、-、+ 或 1.
const liMatch = trimmed.match(/^([*\-+]|\d+\.)\s+(.+)/)
if (liMatch) {
blocks.push({ type: 'li', content: liMatch[1] })
blocks.push({ type: 'li', marker: /^\d+\./.test(liMatch[1]) ? liMatch[1] : '•', content: liMatch[2] })
continue
}
@@ -117,7 +143,7 @@ const parseBoldText = (text) => {
.markdown-container {
display: flex;
flex-direction: column;
gap: 16rpx;
gap: 14rpx;
}
/* 分割线 */
@@ -133,24 +159,52 @@ const parseBoldText = (text) => {
}
/* 标题 */
.markdown-h1,
.markdown-h2,
.markdown-h3 {
display: block;
font-size: 30rpx;
font-weight: 600;
color: rgba(243, 232, 255, 0.95);
margin: 20rpx 0 12rpx 0;
color: rgba(248, 244, 255, 0.96);
line-height: 1.4;
font-weight: 800;
}
.markdown-h1 {
font-size: 32rpx;
margin: 4rpx 0 10rpx 0;
}
.markdown-h2 {
font-size: 30rpx;
margin: 14rpx 0 8rpx 0;
}
.markdown-h3 {
font-size: 28rpx;
margin: 12rpx 0 6rpx 0;
}
.markdown-h4 {
display: block;
font-size: 28rpx;
font-weight: 600;
font-size: 26rpx;
font-weight: 800;
color: rgba(243, 232, 255, 0.95);
margin: 16rpx 0 8rpx 0;
margin: 10rpx 0 4rpx 0;
line-height: 1.4;
}
.markdown-quote {
padding: 16rpx 18rpx;
border-left: 5rpx solid rgba(180, 108, 255, 0.8);
border-radius: 14rpx;
color: rgba(218, 202, 246, 0.82);
background: rgba(168, 85, 247, 0.1);
}
.markdown-quote text {
font-size: 24rpx;
line-height: 1.65;
}
/* 列表项 */
.markdown-li {
display: flex;
@@ -164,6 +218,7 @@ const parseBoldText = (text) => {
color: #C084FC;
font-size: 24rpx;
line-height: 1.5;
min-width: 28rpx;
flex-shrink: 0;
}
+10 -3
View File
@@ -16,7 +16,6 @@ import { ref, onMounted, onUnmounted } from 'vue'
const isPlaying = ref(false)
const bottomPosition = ref('180rpx')
const audioContext = null
let audioInstance = null
// 背景音乐 URL - 使用原型中的音乐
@@ -29,9 +28,18 @@ const initAudio = () => {
audioInstance.loop = true
audioInstance.autoplay = false
audioInstance.onPlay(() => {
isPlaying.value = true
})
audioInstance.onPause(() => {
isPlaying.value = false
})
audioInstance.onError((err) => {
console.error('音乐播放失败:', err)
isPlaying.value = false
uni.showToast({ title: '音乐资源暂不可用', icon: 'none' })
})
audioInstance.onEnded(() => {
@@ -47,8 +55,7 @@ const toggleMusic = async () => {
audioInstance.pause()
} else {
try {
await audioInstance.play()
isPlaying.value = true
audioInstance.play()
} catch (err) {
console.error('音乐播放失败:', err)
isPlaying.value = false