From 75fad97d5dbee5a32ac586cbfee2d8e1d73dd1f2 Mon Sep 17 00:00:00 2001
From: comlibmb <1844410276@qq.com>
Date: Thu, 22 Jan 2026 08:54:47 +0800
Subject: [PATCH] =?UTF-8?q?=E9=A1=B9=E7=9B=AE=E6=AD=A3=E5=B8=B8=E5=90=AF?=
=?UTF-8?q?=E5=8A=A8?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
App.uvue | 40 ++
UNI_APP_X_MIGRATION.md | 198 ++++++++
ak/config.uts | 15 +
index.html | 2 +
main.js | 2 +
main.uts | 7 +
manifest.json | 1 +
pages.json | 68 ++-
pages/info/comindex.uvue | 2 +-
pages/info/detail.uvue | 2 +-
pages/info/settings.uvue | 2 +-
pages/info/topic-detail.uvue | 2 +-
pages/info/topics.uvue | 2 +-
pages/info/video-player.uvue | 2 +-
pages/mall/pages-config.json | 51 ++-
pages/sense/senseDataService.uts | 132 ++++++
pages/sense/types.uts | 16 +
pages/user/boot.uvue | 166 +++++++
pages/user/login.uvue | 743 ++++++++++++-------------------
pages/user/register.uvue | 706 ++++++++++++-----------------
pages/user/terms.uvue | 131 ++++++
platformConfig.json | 7 +
uni_modules/i18n/README.md | 67 +++
uni_modules/i18n/index.uts | 39 ++
uni_modules/i18n/package.json | 9 +
utils/i18nfun.uts | 2 +-
utils/sapi.uts | 88 ++++
utils/utils.uts | 6 +-
28 files changed, 1621 insertions(+), 887 deletions(-)
create mode 100644 UNI_APP_X_MIGRATION.md
create mode 100644 ak/config.uts
create mode 100644 main.js
create mode 100644 pages/sense/senseDataService.uts
create mode 100644 pages/sense/types.uts
create mode 100644 pages/user/boot.uvue
create mode 100644 pages/user/terms.uvue
create mode 100644 platformConfig.json
create mode 100644 uni_modules/i18n/README.md
create mode 100644 uni_modules/i18n/index.uts
create mode 100644 uni_modules/i18n/package.json
create mode 100644 utils/sapi.uts
diff --git a/App.uvue b/App.uvue
index be71360a..1e48bf62 100644
--- a/App.uvue
+++ b/App.uvue
@@ -1,5 +1,11 @@
+ APP 已挂载(dev probe)
+
+ 去启动页 boot
+ 去登录 login
+ 去商城首页
+
@@ -11,4 +17,38 @@
.app-root {
min-height: 100vh;
}
+
+.dev-probe {
+ position: fixed;
+ left: 16rpx;
+ top: 16rpx;
+ z-index: 999999;
+ padding: 10rpx 14rpx;
+ border-radius: 12rpx;
+ background: rgba(17, 24, 39, 0.82);
+ color: #fff;
+ font-size: 22rpx;
+ line-height: 1.2;
+}
+
+.dev-nav {
+ position: fixed;
+ left: 16rpx;
+ top: 64rpx;
+ z-index: 999999;
+ display: flex;
+ flex-direction: column;
+ gap: 10rpx;
+}
+
+.dev-nav-btn {
+ display: inline-block;
+ padding: 10rpx 14rpx;
+ border-radius: 12rpx;
+ background: rgba(255, 255, 255, 0.92);
+ color: #111827;
+ font-size: 22rpx;
+ border: 2rpx solid rgba(17, 24, 39, 0.12);
+ text-decoration: none;
+}
diff --git a/UNI_APP_X_MIGRATION.md b/UNI_APP_X_MIGRATION.md
new file mode 100644
index 00000000..7b847032
--- /dev/null
+++ b/UNI_APP_X_MIGRATION.md
@@ -0,0 +1,198 @@
+# uni-app X 迁移操作总结
+
+## 操作日期
+2024年(具体日期根据实际情况填写)
+
+## 操作背景
+项目需要从传统的 uni-app 迁移到 **uni-app X**,以支持 `.uvue` 文件在 H5 浏览器中正确渲染。
+
+## 问题分析
+对比根项目(`akmon`)和 `mall` 项目,发现以下关键差异:
+
+1. **缺少 uni-app X 配置**:`mall/manifest.json` 中缺少 `"uni-app-x": {}` 配置项
+2. **存在 .vue 文件**:项目中有 23 个 `.vue` 文件,这些文件在 uni-app X 中无法被正确编译到 H5
+3. **编译器配置**:需要确保 HBuilderX 使用 uni-app X 编译器
+
+## 执行的操作
+
+### 1. 添加 uni-app X 配置
+
+在 `manifest.json` 中添加了 `"uni-app-x": {}` 配置项:
+
+```json
+{
+ "vueVersion": "3",
+ "uni-app-x": {},
+ "h5": {
+ "title": "mall",
+ "router": {
+ "mode": "hash",
+ "base": "./"
+ }
+ }
+}
+```
+
+**位置**:`manifest.json` 第 66 行
+
+**作用**:
+- 告诉 HBuilderX 这是一个 uni-app X 项目
+- 启用 uni-app X 编译链,支持 `.uvue` 文件编译到 H5
+- 确保 `.uvue` 文件能够被正确编译和渲染
+
+### 2. 删除所有 .vue 文件
+
+删除了项目中所有 `.vue` 文件,共 23 个文件:
+
+**删除的文件列表**:
+- `pages/user/boot.vue`
+- `pages/user/login.vue`
+- `pages/user/register.vue`
+- `pages/user/forgot-password.vue`
+- `pages/user/profile.vue`
+- `pages/user/center.vue`
+- `pages/user/terms.vue`
+- `pages/mall/consumer/index.vue`
+- `pages/mall/consumer/product-detail.vue`
+- `pages/mall/consumer/order-detail.vue`
+- `pages/mall/consumer/profile.vue`
+- `pages/mall/consumer/subscription/plan-list.vue`
+- `pages/mall/consumer/subscription/plan-detail.vue`
+- `pages/mall/consumer/subscription/subscribe-checkout.vue`
+- `pages/mall/consumer/subscription/my-subscriptions.vue`
+- `pages/mall/merchant/index.vue`
+- `pages/mall/delivery/index.vue`
+- `pages/mall/admin/index.vue`
+- `pages/mall/admin/subscription/plan-management.vue`
+- `pages/mall/admin/subscription/user-subscriptions.vue`
+- `pages/mall/service/index.vue`
+- `pages/mall/analytics/index.vue`
+- `pages/mall/nfc/security/index.vue`
+
+**删除命令**:
+```powershell
+Set-Location -Path 'd:\datas\hfkj\akmon\mall'
+Get-ChildItem -Recurse -Filter *.vue | Remove-Item -Force
+```
+
+**原因**:
+- `.vue` 文件在 uni-app X 中无法被正确编译到 H5 浏览器
+- 所有页面和组件应使用 `.uvue` 格式
+- 导入语句会自动识别 `.uvue` 扩展名(导入时无需显式指定扩展名)
+
+## 技术说明
+
+### uni-app X vs 传统 uni-app
+
+| 特性 | 传统 uni-app | uni-app X |
+| ------------- | --------------------- | ---------------------- |
+| 文件格式 | `.vue` | `.uvue` |
+| 脚本语言 | JavaScript/TypeScript | UTS (TypeScript 扩展) |
+| 编译器 | uni-app 编译器 | uni-app X 编译器 |
+| H5 渲染 | 需要编译 | 需要编译(但支持更好) |
+| manifest.json | 不需要 `uni-app-x` | 需要 `"uni-app-x": {}` |
+
+### 导入语句说明
+
+删除 `.vue` 文件后,所有导入语句会自动使用对应的 `.uvue` 文件:
+
+```typescript
+// 之前(.vue)
+import LoginPage from './pages/user/login.vue'
+
+// 现在(.uvue,扩展名可省略)
+import LoginPage from './pages/user/login.uvue'
+// 或者
+import LoginPage from './pages/user/login' // 自动识别 .uvue
+```
+
+## 后续操作
+
+### 1. 验证配置
+
+1. 打开 HBuilderX
+2. 打开 `mall` 项目
+3. 检查编译器:**工具** → **切换编译器** → 确认选择 **uni-app X**
+4. 如果未选择,请切换到 uni-app X 编译器
+
+### 2. 运行到 H5
+
+1. 在 HBuilderX 中,点击菜单:**运行** → **运行到浏览器** → **Chrome**(或内置浏览器)
+2. 等待编译完成
+3. 浏览器会自动打开并显示应用
+
+### 3. 发行 H5
+
+如果需要打包发布:
+
+1. 点击菜单:**发行** → **网站-H5**
+2. 等待编译完成
+3. 编译产物在 `unpackage/dist/build/h5` 目录
+4. 将整个 `h5` 目录部署到 Web 服务器
+
+### 4. 检查页面
+
+确保所有页面都有对应的 `.uvue` 文件:
+
+- 检查 `pages.json` 中配置的所有页面路径
+- 确认每个页面都有对应的 `.uvue` 文件
+- 如果缺少,需要从备份或版本控制中恢复并转换为 `.uvue` 格式
+
+## 注意事项
+
+1. **编译器版本**:必须使用支持 uni-app X 的 HBuilderX 版本
+2. **文件格式**:所有页面和组件必须使用 `.uvue` 格式,不能混用 `.vue`
+3. **UTS 语法**:`.uvue` 文件中的 `
+
+
diff --git a/main.js b/main.js
new file mode 100644
index 00000000..2c1e55ed
--- /dev/null
+++ b/main.js
@@ -0,0 +1,2 @@
+// Bridge entry to ensure Vite serves JS MIME while loading UTS entry.
+import './main.uts'
diff --git a/main.uts b/main.uts
index 8d952888..234c8c9b 100644
--- a/main.uts
+++ b/main.uts
@@ -1,7 +1,14 @@
import { createSSRApp } from 'vue'
import App from './App.uvue'
+import i18n from '@/uni_modules/i18n/index.uts'
export function createApp() {
const app = createSSRApp(App)
+
+ // 注册 i18n 全局属性,使组件可以使用 $t 方法
+ app.config.globalProperties.$t = (key: string, values?: any, locale?: string): string => {
+ return i18n.global.t(key, values, locale)
+ }
+
return { app }
}
diff --git a/manifest.json b/manifest.json
index f75da367..98b47747 100644
--- a/manifest.json
+++ b/manifest.json
@@ -63,6 +63,7 @@
"enable": false
},
"vueVersion": "3",
+ "uni-app-x": {},
"h5": {
"title": "mall",
"router": {
diff --git a/pages.json b/pages.json
index 5ff409d6..fed5ab00 100644
--- a/pages.json
+++ b/pages.json
@@ -1,5 +1,18 @@
{
"pages": [
+ {
+ "path": "pages/mall/consumer/index",
+ "style": {
+ "navigationBarTitleText": "商城首页",
+ "navigationStyle": "custom"
+ }
+ },
+ {
+ "path": "pages/user/boot",
+ "style": {
+ "navigationBarTitleText": ""
+ }
+ },
{
"path": "pages/user/login",
"style": {
@@ -31,10 +44,9 @@
}
},
{
- "path": "pages/mall/consumer/index",
+ "path": "pages/user/terms",
"style": {
- "navigationBarTitleText": "商城首页",
- "navigationStyle": "custom"
+ "navigationBarTitleText": "用户协议与隐私政策"
}
},
{
@@ -142,10 +154,60 @@
]
}
],
+ "tabBar": {
+ "custom": true,
+ "color": "#7A7E83",
+ "selectedColor": "#3cc51f",
+ "borderStyle": "black",
+ "backgroundColor": "#ffffff",
+ "list": [
+ {
+ "pagePath": "pages/mall/consumer/index",
+ "iconPath": "static/tab-home.png",
+ "selectedIconPath": "static/tab-home-current.png",
+ "text": "首页"
+ },
+ {
+ "pagePath": "pages/mall/consumer/category",
+ "iconPath": "static/tab-category.png",
+ "selectedIconPath": "static/tab-category-current.png",
+ "text": "分类"
+ },
+ {
+ "pagePath": "pages/mall/consumer/cart",
+ "iconPath": "static/tab-cart.png",
+ "selectedIconPath": "static/tab-cart-current.png",
+ "text": "购物车"
+ },
+ {
+ "pagePath": "pages/mall/consumer/profile",
+ "iconPath": "static/tab-profile.png",
+ "selectedIconPath": "static/tab-profile-current.png",
+ "text": "我的"
+ }
+ ]
+ },
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "mall",
"navigationBarBackgroundColor": "#FFFFFF",
"backgroundColor": "#F8F8F8"
+ },
+ "condition": {
+ "current": 0,
+ "list": [
+ {
+ "name": "消费者端首页",
+ "path": "pages/mall/consumer/index"
+ },
+ {
+ "name": "启动页(登录态判断)",
+ "path": "pages/user/boot"
+ },
+ {
+ "name": "登录页",
+ "path": "pages/user/login"
+ }
+ ]
}
}
\ No newline at end of file
diff --git a/pages/info/comindex.uvue b/pages/info/comindex.uvue
index 2dddd9a4..25736772 100644
--- a/pages/info/comindex.uvue
+++ b/pages/info/comindex.uvue
@@ -442,7 +442,7 @@
import supa from '@/components/supadb/aksupainstance.uts'
import { OrderOptions } from '@/components/supadb/aksupa.uts'
import { tt } from '@/utils/i18nfun.uts'
- import i18n from '@/i18n/index.uts' // 保留用于语言切换和全局配置
+ import i18n from '@/uni_modules/i18n/index.uts' // 保留用于语言切换和全局配置
import { ResponsiveState, InfoContent } from '@/pages/info/types.uts'
import { LanguageOption } from '@/pages/user/types.uts'
diff --git a/pages/info/detail.uvue b/pages/info/detail.uvue
index 125eda7f..7b2c4d56 100644
--- a/pages/info/detail.uvue
+++ b/pages/info/detail.uvue
@@ -229,7 +229,7 @@
import { state as userState, getCurrentUser, setUserProfile, setIsLoggedIn } from '@/utils/store.uts'
import { setClipboardData } from '@/uni_modules/lime-clipboard'
import { tt } from '@/utils/i18nfun.uts'
- import i18n from '@/i18n/index.uts' // 保留用于语言切换
+ import i18n from '@/uni_modules/i18n/index.uts' // 保留用于语言切换
// 页面参数
const contentId = ref('')
diff --git a/pages/info/settings.uvue b/pages/info/settings.uvue
index b9201e69..6a96b7f5 100644
--- a/pages/info/settings.uvue
+++ b/pages/info/settings.uvue
@@ -302,7 +302,7 @@
import type { UserPreferences } from './types.uts'
import supa from '@/components/supadb/aksupainstance.uts'
import { tt } from '@/utils/i18nfun.uts'
-import i18n from '@/i18n/index.uts' // 保留用于语言切换
+import i18n from '@/uni_modules/i18n/index.uts' // 保留用于语言切换
// 用户信息
const userName = ref('用户')
diff --git a/pages/info/topic-detail.uvue b/pages/info/topic-detail.uvue
index 60db2015..a3f19401 100644
--- a/pages/info/topic-detail.uvue
+++ b/pages/info/topic-detail.uvue
@@ -222,7 +222,7 @@ import {
} from './types.uts'
import supa from '@/components/supadb/aksupainstance.uts'
import { tt } from '@/utils/i18nfun.uts'
-import i18n from '@/i18n/index.uts' // 保留用于语言切换
+import i18n from '@/uni_modules/i18n/index.uts' // 保留用于语言切换
// 页面参数
const topicId = ref('')
diff --git a/pages/info/topics.uvue b/pages/info/topics.uvue
index bd8fe4a6..391ca1ae 100644
--- a/pages/info/topics.uvue
+++ b/pages/info/topics.uvue
@@ -191,7 +191,7 @@ import {
} from './types.uts'
import supa from '@/components/supadb/aksupainstance.uts'
import { tt } from '@/utils/i18nfun.uts'
-import i18n from '@/i18n/index.uts' // 保留用于语言切换
+import i18n from '@/uni_modules/i18n/index.uts' // 保留用于语言切换
// 页面状态
const pageState = ref({
diff --git a/pages/info/video-player.uvue b/pages/info/video-player.uvue
index 12bb9846..19bf509d 100644
--- a/pages/info/video-player.uvue
+++ b/pages/info/video-player.uvue
@@ -282,7 +282,7 @@ import {
import { formatRelativeTimeKey } from './types.uts'
import supa from '@/components/supadb/aksupainstance.uts'
import { tt } from '@/utils/i18nfun.uts'
-import i18n from '@/i18n/index.uts'
+import i18n from '@/uni_modules/i18n/index.uts'
// 页面参数
const videoId = ref('')
diff --git a/pages/mall/pages-config.json b/pages/mall/pages-config.json
index e129a494..f4985a33 100644
--- a/pages/mall/pages-config.json
+++ b/pages/mall/pages-config.json
@@ -13,6 +13,48 @@
"navigationStyle": "custom"
}
},
+ {
+ "path": "pages/user/boot",
+ "style": {
+ "navigationBarTitleText": ""
+ }
+ },
+ {
+ "path": "pages/user/login",
+ "style": {
+ "navigationBarTitleText": "登录"
+ }
+ },
+ {
+ "path": "pages/user/register",
+ "style": {
+ "navigationBarTitleText": "注册"
+ }
+ },
+ {
+ "path": "pages/user/forgot-password",
+ "style": {
+ "navigationBarTitleText": "忘记密码"
+ }
+ },
+ {
+ "path": "pages/user/terms",
+ "style": {
+ "navigationBarTitleText": "用户协议与隐私政策"
+ }
+ },
+ {
+ "path": "pages/user/center",
+ "style": {
+ "navigationBarTitleText": "用户中心"
+ }
+ },
+ {
+ "path": "pages/user/profile",
+ "style": {
+ "navigationBarTitleText": "个人资料"
+ }
+ },
{
"path": "pages/mall/merchant/index",
"style": {
@@ -219,8 +261,7 @@
"style": {
"navigationBarTitleText": "收货地址"
}
- }
- ,
+ },
{
"path": "subscription/plan-list",
"style": {
@@ -499,6 +540,10 @@
"name": "消费者端首页",
"path": "pages/mall/consumer/index"
},
+ {
+ "name": "启动页(登录态判断)",
+ "path": "pages/user/boot"
+ },
{
"name": "商家端首页",
"path": "pages/mall/merchant/index"
@@ -521,4 +566,4 @@
}
]
}
-}
+}
\ No newline at end of file
diff --git a/pages/sense/senseDataService.uts b/pages/sense/senseDataService.uts
new file mode 100644
index 00000000..f12f19eb
--- /dev/null
+++ b/pages/sense/senseDataService.uts
@@ -0,0 +1,132 @@
+import supa, { supaReady } from '@/components/supadb/aksupainstance.uts'
+import type { DeviceInfo, DeviceParams } from './types.uts'
+
+// 服务响应类型
+export type ServiceResponse = {
+ error: Error | null
+ data: T | null
+}
+
+// 设备数据服务类
+export class SenseDataService {
+ // 表名常量(根据实际数据库表名调整)
+ private static readonly TABLE_NAME = 'sense_devices'
+
+ /**
+ * 获取设备列表
+ */
+ static async getDevices(params: DeviceParams): Promise>> {
+ try {
+ await supaReady
+ const res = await supa.from(SenseDataService.TABLE_NAME)
+ .select('*', {})
+ .eq('user_id', params.user_id)
+ .execute()
+
+ if (res.status >= 200 && res.status < 300 && res.data != null) {
+ const data = res.data as any
+ const devices = Array.isArray(data) ? data as Array : []
+ return { error: null, data: devices }
+ } else {
+ return {
+ error: new Error(`获取设备列表失败: ${res.status}`),
+ data: null
+ }
+ }
+ } catch (error) {
+ return {
+ error: error instanceof Error ? error : new Error(String(error)),
+ data: null
+ }
+ }
+ }
+
+ /**
+ * 绑定新设备
+ */
+ static async bindDevice(deviceData: UTSJSONObject): Promise> {
+ try {
+ await supaReady
+ const res = await supa.from(SenseDataService.TABLE_NAME)
+ .insert(deviceData)
+ .select('*', {})
+ .single()
+ .execute()
+
+ if (res.status >= 200 && res.status < 300 && res.data != null) {
+ const device = res.data as DeviceInfo
+ return { error: null, data: device }
+ } else {
+ return {
+ error: new Error(`绑定设备失败: ${res.status}`),
+ data: null
+ }
+ }
+ } catch (error) {
+ return {
+ error: error instanceof Error ? error : new Error(String(error)),
+ data: null
+ }
+ }
+ }
+
+ /**
+ * 解绑设备
+ */
+ static async unbindDevice(deviceId: string): Promise> {
+ try {
+ await supaReady
+ const res = await supa.from(SenseDataService.TABLE_NAME)
+ .delete()
+ .eq('id', deviceId)
+ .execute()
+
+ if (res.status >= 200 && res.status < 300) {
+ return { error: null, data: null }
+ } else {
+ return {
+ error: new Error(`解绑设备失败: ${res.status}`),
+ data: null
+ }
+ }
+ } catch (error) {
+ return {
+ error: error instanceof Error ? error : new Error(String(error)),
+ data: null
+ }
+ }
+ }
+
+ /**
+ * 更新设备配置
+ */
+ static async updateDevice(deviceId: string, configData: UTSJSONObject): Promise> {
+ try {
+ await supaReady
+ const res = await supa.from(SenseDataService.TABLE_NAME)
+ .update(configData)
+ .eq('id', deviceId)
+ .select('*', {})
+ .single()
+ .execute()
+
+ if (res.status >= 200 && res.status < 300 && res.data != null) {
+ const device = res.data as DeviceInfo
+ return { error: null, data: device }
+ } else {
+ return {
+ error: new Error(`更新设备配置失败: ${res.status}`),
+ data: null
+ }
+ }
+ } catch (error) {
+ return {
+ error: error instanceof Error ? error : new Error(String(error)),
+ data: null
+ }
+ }
+ }
+}
+
+// 导出类型
+export type { DeviceParams }
diff --git a/pages/sense/types.uts b/pages/sense/types.uts
new file mode 100644
index 00000000..c5255450
--- /dev/null
+++ b/pages/sense/types.uts
@@ -0,0 +1,16 @@
+// 设备信息类型
+export type DeviceInfo = {
+ id: string
+ device_name?: string
+ status?: string // 'online' | 'offline' | 其他状态
+ user_id?: string
+ // 可根据实际需求添加更多字段
+ [key: string]: any
+}
+
+// 设备查询参数类型
+export type DeviceParams = {
+ user_id: string
+ // 可根据实际需求添加更多查询参数
+ [key: string]: any
+}
diff --git a/pages/user/boot.uvue b/pages/user/boot.uvue
new file mode 100644
index 00000000..51175aa0
--- /dev/null
+++ b/pages/user/boot.uvue
@@ -0,0 +1,166 @@
+
+
+
+
+
+
+ Mall
+ 正品保障 · 省心售后
+
+
+
+
+
+ 正在检查登录状态…
+ 通常数秒内自动进入首页或登录页
+
+
+
+ 前往登录
+ 我要注册
+
+
+
+
+
+
+
+
diff --git a/pages/user/login.uvue b/pages/user/login.uvue
index 19d645e8..4bd0b118 100644
--- a/pages/user/login.uvue
+++ b/pages/user/login.uvue
@@ -1,90 +1,82 @@
-
-
-
-
-