Files
ai-dimension/client/src/App.vue
T
txai-dev 2a111d21c0 feat: v1.3.0 差异化重构——星图点亮体系
P0 修复:
- 详情页正文渲染(content 分段),71 条知识不再空白
- 问答页去登录墙:游客每日 3 次(IP 限流),登录后每日 5 次
- 修正问答配额为真正的每日重置语义

点亮闭环:
- KnowledgeLit 模型 + 服务端判题(POST /:id/quiz,答案不下发)
- /api/knowledge/stats 星域统计 + 点亮进度 + streak + litIds
- AI 批量生成 71 条读后检测题(scripts/generate-quiz.js)

设计系统 2.0:
- 70 个统一线性图标替换全部 emoji 图标
- 主题 token mixin 化,修复 H5 暗色级联 bug,MP 跟随系统(darkmode)
- 首页星域导航(进度环)、我的页学习者档案、星域列表页重写
- 硬编码色清理,误植 map 页移除

服务端加固:
- trust proxy 真实 IP、错误信息脱敏、ask 独立限流、无效 ObjectId 404
- seo.js ESM→CJS(修复容器启动)、AI 导师"维度精灵"人格化
2026-09-12 23:39:05 +08:00

170 lines
4.0 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="app-root">
<slot />
</view>
</template>
<script setup>
import { onLaunch, onShow, onHide } from '@dcloudio/uni-app'
onLaunch(() => {
initTheme()
})
onShow(() => {})
onHide(() => {})
// 主题:'auto'(默认,跟随系统)| 'light' | 'dark'
function initTheme() {
const theme = uni.getStorageSync('theme') || 'auto'
applyTheme(theme)
// auto 模式下监听系统切换(H5)
if (theme === 'auto' && typeof window !== 'undefined' && window.matchMedia) {
const mq = window.matchMedia('(prefers-color-scheme: dark)')
const onChange = () => applyTheme('auto')
if (mq.addEventListener) mq.addEventListener('change', onChange)
else if (mq.addListener) mq.addListener(onChange)
}
}
function resolveTheme(theme) {
if (theme !== 'auto') return theme
if (typeof window !== 'undefined' && window.matchMedia) {
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
}
return 'light'
}
function applyTheme(theme) {
const resolved = resolveTheme(theme)
try {
// H5 环境:操作 document class
const root = document.documentElement
root.classList.remove('theme-dark', 'theme-light')
root.classList.add(resolved === 'dark' ? 'theme-dark' : 'theme-light')
} catch (e) {
// 小程序环境:document 不存在,深色由 manifest darkmode + CSS 媒体查询接管
}
applyTabBarTheme(resolved)
}
function applyTabBarTheme(theme) {
try {
if (theme === 'dark') {
uni.setTabBarStyle({
color: 'rgba(255,255,255,0.35)',
selectedColor: '#a2b2ff',
backgroundColor: '#181828',
borderStyle: 'black'
})
} else {
uni.setTabBarStyle({
color: 'rgba(0,0,0,0.3)',
selectedColor: '#5b5ff8',
backgroundColor: '#ffffff',
borderStyle: 'white'
})
}
} catch (e) {
// 非 tabBar 页面或不支持时忽略
}
}
</script>
<style lang="scss">
/* ============================================
宇之然AI维度 — 全局主题
变量 mixin 唯一出处:styles/theme.scss
============================================ */
/* 小程序基础:浅色默认 */
page {
@include theme-light-vars;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
background-color: var(--bg-primary);
color: var(--text-secondary);
font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Display', 'Segoe UI', Roboto, sans-serif;
}
/* H5:html 类切换主题(需覆盖 page 上的浅色定义,特异性更高) */
/* #ifdef H5 */
html.theme-light page { @include theme-light-vars; }
html.theme-dark, html.theme-dark page { @include theme-dark-vars; }
/* #endif */
/* 小程序:跟随系统深色(需 manifest darkmode: true) */
/* #ifdef MP-WEIXIN */
@media (prefers-color-scheme: dark) {
page { @include theme-dark-vars; }
}
/* #endif */
view {
box-sizing: border-box;
}
::-webkit-scrollbar {
display: none;
width: 0;
height: 0;
}
/* 页面布局统一 */
.page-layout {
min-height: 100vh;
padding: 0 20px 30px;
background: var(--bg-primary);
}
.page-subtitle {
display: block;
font-size: 13px;
color: var(--text-tertiary);
margin-top: 4px;
}
/* 卡片通用 */
.card {
background: var(--glass-bg);
border: 1px solid var(--glass-border);
border-radius: var(--radius-lg);
box-shadow: var(--card-shadow, none);
transition: all 0.3s ease;
}
.gradient-brand {
background: linear-gradient(135deg, var(--color-brand), var(--color-brand-light));
}
.gradient-text {
background: linear-gradient(135deg, var(--color-brand-light), var(--color-brand));
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
/* 区块标题(统一) */
.section-header {
display: flex;
align-items: center;
justify-content: space-between;
margin: 24px 0 12px;
.section-title {
font-size: 16px;
font-weight: 700;
color: var(--text-primary);
display: flex;
align-items: center;
gap: 6px;
}
.section-more {
font-size: 12px;
color: var(--text-tertiary);
}
}
</style>