refactor: 重构移动端页面布局与资源路径,优化打包配置

1. 新增layout.uts统一管理页面尺寸与安全区计算
2. 修正图片资源路径到static/mobile目录
3. 调整App.vue与AppIcon组件样式适配多端
4. 为微信小程序配置打包忽略规则减少包体积
5. 修复API请求错误抛出类型,完善类型定义
6. 补充README文档说明项目运行与维护规范
7. 优化多个页面的样式与生命周期逻辑
This commit is contained in:
hujun
2026-09-15 16:16:55 +08:00
parent 626cef9d38
commit b0ee4f9d7e
67 changed files with 80727 additions and 189 deletions
+7 -7
View File
@@ -13,7 +13,7 @@ export function saveSession(token: string, phone: string): void {
export function getSession(): UTSJSONObject | null {
const value = uni.getStorageSync(SESSION_KEY)
if (value == null) return null
if (value == null || typeof value != 'object') return null
return value as UTSJSONObject
}
@@ -25,7 +25,7 @@ export function clearSession(): void {
uni.removeStorageSync(SESSION_KEY)
}
const apiMessage = (error: unknown, fallback: string): string => {
const apiMessage = (error: any | null, fallback: string): string => {
if (error == null) return fallback
const text = error.toString()
return text.length > 0 ? text : fallback
@@ -65,12 +65,12 @@ export async function requestSmsCode(phone: string): Promise<boolean> {
export async function loginWithSms(phone: string, code: string): Promise<string> {
if (API_BASE_URL.length == 0) {
await wait(300)
if (code.length != 6) throw '验证码应为 6 位数字'
if (code.length != 6) throw new Error('验证码应为 6 位数字')
return 'demo-sms-token'
}
const result = await requestJson('/auth/sms-login', 'POST', { phone, code })
const token = result['token'] as string | null
if (token == null || token.length == 0) throw '登录响应缺少 token'
if (token == null || token.length == 0) throw new Error('登录响应缺少 token')
return token
}
@@ -81,7 +81,7 @@ export async function loginWithPassword(phone: string, password: string): Promis
}
const result = await requestJson('/auth/password-login', 'POST', { phone, password })
const token = result['token'] as string | null
if (token == null || token.length == 0) throw '登录响应缺少 token'
if (token == null || token.length == 0) throw new Error('登录响应缺少 token')
return token
}
@@ -93,7 +93,7 @@ export async function submitAssessment(payload: UTSJSONObject): Promise<string>
}
const result = await requestJson('/assessments', 'POST', payload)
const id = result['id'] as string | null
if (id == null || id.length == 0) throw '评估提交成功但未返回编号'
if (id == null || id.length == 0) throw new Error('评估提交成功但未返回编号')
return id
}
@@ -118,7 +118,7 @@ export async function sendAssistantMessage(message: string): Promise<string> {
}
const result = await requestJson('/assistant/messages', 'POST', { message })
const reply = result['reply'] as string | null
if (reply == null || reply.length == 0) throw '助手暂时没有返回内容'
if (reply == null || reply.length == 0) throw new Error('助手暂时没有返回内容')
return reply
}
+39
View File
@@ -0,0 +1,39 @@
import { ref, onMounted, onUnmounted } from 'vue'
import { onResize } from '@dcloudio/uni-app'
export type PageLayout = {
pageStyle: () => string,
contentStyle: (offset: number, minimum: boolean) => string,
statusStyle: (offset: number) => string,
bottomStyle: (padding: number) => string
}
// 原生渲染不支持 vh/calc,统一以窗口尺寸计算,并随旋转更新。
export function usePageLayout(): PageLayout {
const windowInfo = ref(uni.getWindowInfo())
const refresh = () => { windowInfo.value = uni.getWindowInfo() }
onMounted(() => refresh())
// #ifdef APP
onResize((_options) => { refresh() })
// #endif
// #ifndef APP
const handleResize = (_options: OnWindowResizeCallbackResult) => { refresh() }
uni.onWindowResize(handleResize)
onUnmounted(() => { uni.offWindowResize(handleResize) })
// #endif
const rpx = (value: number): number => value * windowInfo.value.windowWidth / 750
const status = (): number => windowInfo.value.statusBarHeight ?? 0
const pageStyle = (): string => 'min-height:' + windowInfo.value.windowHeight + 'px;'
const contentStyle = (offset: number, minimum: boolean): string => {
// #ifdef WEB
return (minimum ? 'min-height:' : 'height:') + 'calc(100vh - ' + status() + 'px - ' + offset + 'rpx);'
// #endif
// #ifndef WEB
const height = Math.max(0, windowInfo.value.windowHeight - status() - rpx(offset))
return (minimum ? 'min-height:' : 'height:') + height + 'px;'
// #endif
}
const statusStyle = (offset: number): string => 'height:' + (status() + rpx(offset)) + 'px;'
const bottomStyle = (padding: number): string => 'padding-bottom:' + (rpx(padding) + (windowInfo.value.safeAreaInsets?.bottom ?? 0)) + 'px;'
return { pageStyle, contentStyle, statusStyle, bottomStyle }
}