diff --git a/cloudfunctions/categoriesCreate/index.js b/cloudfunctions/categoriesCreate/index.js
new file mode 100644
index 0000000..9737a10
--- /dev/null
+++ b/cloudfunctions/categoriesCreate/index.js
@@ -0,0 +1,75 @@
+const cloud = require('wx-server-sdk');
+
+cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV });
+
+function validatePayload(event) {
+ const id = String(event.id || '').trim();
+ const name = String(event.name || '').trim();
+ const icon = String(event.icon || '').trim();
+ const color = String(event.color || '').trim();
+ const sortOrder = Number(event.sortOrder || 0);
+ const parentId =
+ event.parentId === undefined || event.parentId === null
+ ? null
+ : String(event.parentId).trim();
+
+ if (!id) throw new Error('分类 id 不能为空');
+ if (!name) throw new Error('分类名称不能为空');
+ if (!icon) throw new Error('分类图标不能为空');
+ if (!color) throw new Error('分类颜色不能为空');
+ if (!Number.isFinite(sortOrder)) throw new Error('分类排序不合法');
+
+ return {
+ id,
+ name,
+ icon,
+ color,
+ sortOrder,
+ parentId,
+ };
+}
+
+exports.main = async (event) => {
+ try {
+ const payload = validatePayload(event);
+ const db = cloud.database();
+ const collection = db.collection('categories');
+
+ try {
+ await collection.doc(payload.id).get();
+ return {
+ success: false,
+ message: '分类已存在',
+ };
+ } catch (error) {
+ // 文档不存在时继续创建
+ }
+
+ await collection.doc(payload.id).set({
+ data: {
+ name: payload.name,
+ icon: payload.icon,
+ color: payload.color,
+ sortOrder: payload.sortOrder,
+ parentId: payload.parentId,
+ },
+ });
+
+ return {
+ success: true,
+ data: {
+ id: payload.id,
+ name: payload.name,
+ icon: payload.icon,
+ color: payload.color,
+ sortOrder: payload.sortOrder,
+ parentId: payload.parentId,
+ },
+ };
+ } catch (error) {
+ return {
+ success: false,
+ message: error instanceof Error ? error.message : '创建分类失败',
+ };
+ }
+};
diff --git a/cloudfunctions/categoriesCreate/package.json b/cloudfunctions/categoriesCreate/package.json
new file mode 100644
index 0000000..7b4b08f
--- /dev/null
+++ b/cloudfunctions/categoriesCreate/package.json
@@ -0,0 +1,8 @@
+{
+ "name": "categories-create",
+ "version": "1.0.0",
+ "main": "index.js",
+ "dependencies": {
+ "wx-server-sdk": "^3.0.4"
+ }
+}
diff --git a/cloudfunctions/categoriesQuery/index.js b/cloudfunctions/categoriesQuery/index.js
new file mode 100644
index 0000000..f0ae7e8
--- /dev/null
+++ b/cloudfunctions/categoriesQuery/index.js
@@ -0,0 +1,23 @@
+const cloud = require('wx-server-sdk');
+
+cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV });
+
+exports.main = async () => {
+ try {
+ const db = cloud.database();
+ const { data } = await db
+ .collection('categories')
+ .orderBy('sortOrder', 'asc')
+ .get();
+
+ return {
+ success: true,
+ data,
+ };
+ } catch (error) {
+ return {
+ success: false,
+ message: error instanceof Error ? error.message : '查询分类失败',
+ };
+ }
+};
diff --git a/cloudfunctions/categoriesQuery/package.json b/cloudfunctions/categoriesQuery/package.json
new file mode 100644
index 0000000..9c6952c
--- /dev/null
+++ b/cloudfunctions/categoriesQuery/package.json
@@ -0,0 +1,8 @@
+{
+ "name": "categories-query",
+ "version": "1.0.0",
+ "main": "index.js",
+ "dependencies": {
+ "wx-server-sdk": "^3.0.4"
+ }
+}
diff --git a/cloudfunctions/categoriesUpdate/index.js b/cloudfunctions/categoriesUpdate/index.js
new file mode 100644
index 0000000..698f2d2
--- /dev/null
+++ b/cloudfunctions/categoriesUpdate/index.js
@@ -0,0 +1,74 @@
+const cloud = require('wx-server-sdk');
+
+cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV });
+
+function validatePayload(event) {
+ const id = String(event.id || '').trim();
+ const name = String(event.name || '').trim();
+ const icon = String(event.icon || '').trim();
+ const color = String(event.color || '').trim();
+ const sortOrder = Number(event.sortOrder || 0);
+ const parentId =
+ event.parentId === undefined || event.parentId === null
+ ? null
+ : String(event.parentId).trim();
+
+ if (!id) throw new Error('分类 id 不能为空');
+ if (!name) throw new Error('分类名称不能为空');
+ if (!icon) throw new Error('分类图标不能为空');
+ if (!color) throw new Error('分类颜色不能为空');
+ if (!Number.isFinite(sortOrder)) throw new Error('分类排序不合法');
+
+ return {
+ id,
+ name,
+ icon,
+ color,
+ sortOrder,
+ parentId,
+ };
+}
+
+exports.main = async (event) => {
+ try {
+ const payload = validatePayload(event);
+ const db = cloud.database();
+ const collection = db.collection('categories');
+
+ try {
+ await collection.doc(payload.id).get();
+ } catch (error) {
+ return {
+ success: false,
+ message: '分类不存在,无法更新',
+ };
+ }
+
+ await collection.doc(payload.id).update({
+ data: {
+ name: payload.name,
+ icon: payload.icon,
+ color: payload.color,
+ sortOrder: payload.sortOrder,
+ parentId: payload.parentId,
+ },
+ });
+
+ return {
+ success: true,
+ data: {
+ _id: payload.id,
+ name: payload.name,
+ icon: payload.icon,
+ color: payload.color,
+ sortOrder: payload.sortOrder,
+ parentId: payload.parentId,
+ },
+ };
+ } catch (error) {
+ return {
+ success: false,
+ message: error instanceof Error ? error.message : '更新分类失败',
+ };
+ }
+};
diff --git a/cloudfunctions/categoriesUpdate/package.json b/cloudfunctions/categoriesUpdate/package.json
new file mode 100644
index 0000000..8a1c731
--- /dev/null
+++ b/cloudfunctions/categoriesUpdate/package.json
@@ -0,0 +1,8 @@
+{
+ "name": "categories-update",
+ "version": "1.0.0",
+ "main": "index.js",
+ "dependencies": {
+ "wx-server-sdk": "^3.0.4"
+ }
+}
diff --git a/miniprogram/app.json b/miniprogram/app.json
index b797416..9f40e28 100644
--- a/miniprogram/app.json
+++ b/miniprogram/app.json
@@ -13,6 +13,7 @@
"pages": [
"guide/guide",
"debug/debug",
+ "categoryManage/categoryManage",
"index/index",
"mathIndex/mathIndex",
"focusIndex/focusIndex",
diff --git a/miniprogram/pages/profile/profile.less b/miniprogram/pages/profile/profile.less
index 7c153f6..2043622 100644
--- a/miniprogram/pages/profile/profile.less
+++ b/miniprogram/pages/profile/profile.less
@@ -237,6 +237,11 @@ page {
flex-shrink: 0;
}
+.profile-row__icon-emoji {
+ font-size: 36rpx;
+ line-height: 1;
+}
+
.profile-row__label {
font-size: 30rpx;
font-weight: 600;
diff --git a/miniprogram/pages/profile/profile.ts b/miniprogram/pages/profile/profile.ts
index e1db4e9..2c90016 100644
--- a/miniprogram/pages/profile/profile.ts
+++ b/miniprogram/pages/profile/profile.ts
@@ -7,12 +7,14 @@ Page({
printCount: 0,
favoriteCount: 0,
version: '',
+ isDevEnv: false,
},
onLoad() {
const info = wx.getAccountInfoSync();
const version = info.miniProgram.version || '开发版';
- this.setData({ version });
+ const isDevEnv = info.miniProgram.envVersion === 'develop';
+ this.setData({ version, isDevEnv });
},
onShow() {
@@ -48,6 +50,10 @@ Page({
wx.showToast({ title: '功能开发中', icon: 'none' });
},
+ onGoToDebug() {
+ wx.navigateTo({ url: '/supportPages/debug/debug' });
+ },
+
onGoToFeedback() {
wx.showToast({ title: '功能开发中', icon: 'none' });
},
diff --git a/miniprogram/pages/profile/profile.wxml b/miniprogram/pages/profile/profile.wxml
index 61e6df8..7a1e326 100644
--- a/miniprogram/pages/profile/profile.wxml
+++ b/miniprogram/pages/profile/profile.wxml
@@ -99,6 +99,18 @@
›
+
+
+
+ 🛠️
+
+ Debug 工具
+
+ ›
+
diff --git a/miniprogram/supportPages/categoryManage/categoryManage.json b/miniprogram/supportPages/categoryManage/categoryManage.json
new file mode 100644
index 0000000..3e8029c
--- /dev/null
+++ b/miniprogram/supportPages/categoryManage/categoryManage.json
@@ -0,0 +1,10 @@
+{
+ "navigationBarTitleText": "分类管理",
+ "navigationBarTextStyle": "black",
+ "navigationBarBackgroundColor": "#F8F0E0",
+ "backgroundColor": "#F8F0E0",
+ "enablePullDownRefresh": true,
+ "usingComponents": {
+ "toy-button": "/toy/button-v2/button"
+ }
+}
diff --git a/miniprogram/supportPages/categoryManage/categoryManage.less b/miniprogram/supportPages/categoryManage/categoryManage.less
new file mode 100644
index 0000000..b5f0df2
--- /dev/null
+++ b/miniprogram/supportPages/categoryManage/categoryManage.less
@@ -0,0 +1,233 @@
+@import '../../style/theme.less';
+
+page {
+ min-height: 100%;
+ background: @bg-header;
+}
+
+.category-manage-page {
+ min-height: 100vh;
+ padding: 24rpx;
+ background: @bg-header;
+ box-sizing: border-box;
+}
+
+.category-manage-page__summary {
+ display: flex;
+}
+
+.category-manage-page__summary-card {
+ flex: 1;
+ padding: 28rpx 20rpx;
+ background: @bg-white;
+ border-radius: @radius-xl;
+ text-align: center;
+ box-shadow: @shadow;
+}
+
+.category-manage-page__summary-card+.category-manage-page__summary-card {
+ margin-left: 20rpx;
+}
+
+.category-manage-page__summary-num {
+ display: block;
+ font-size: 40rpx;
+ font-weight: 800;
+ color: @text-title;
+}
+
+.category-manage-page__summary-label {
+ display: block;
+ margin-top: 10rpx;
+ font-size: 22rpx;
+ color: @text-secondary;
+}
+
+.category-manage-page__hint,
+.category-manage-page__loading {
+ margin-top: 24rpx;
+ padding: 24rpx 28rpx;
+ background: @bg-white;
+ border-radius: @radius;
+ font-size: 24rpx;
+ line-height: 1.6;
+ color: @text-secondary;
+ box-shadow: @shadow;
+}
+
+.category-manage-page__list,
+.category-manage-page__cloud-only {
+ margin-top: 24rpx;
+}
+
+.category-manage-page__section-title {
+ display: block;
+ margin: 0 4rpx 16rpx;
+ font-size: 26rpx;
+ font-weight: 700;
+ color: @text-secondary;
+}
+
+.category-card {
+ padding: 28rpx;
+ margin-bottom: 20rpx;
+ background: @bg-white;
+ border-radius: @radius-xl;
+ box-shadow: @shadow;
+ border: 2rpx solid transparent;
+}
+
+.category-card--synced {
+ border-color: fade(#93d333, 30%);
+}
+
+.category-card--missing {
+ border-color: fade(#ffb703, 40%);
+}
+
+.category-card--outdated {
+ border-color: fade(#ff8f1f, 35%);
+}
+
+.category-card--cloud-only {
+ border-color: fade(#8ecae6, 35%);
+}
+
+.category-card__header {
+ display: flex;
+ align-items: flex-start;
+ justify-content: space-between;
+}
+
+.category-card__meta {
+ display: flex;
+ align-items: center;
+ min-width: 0;
+ flex: 1;
+}
+
+.category-card__icon {
+ width: 72rpx;
+ height: 72rpx;
+ border-radius: 50%;
+ background: fade(@brand, 18%);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-size: 34rpx;
+ line-height: 72rpx;
+ text-align: center;
+ flex-shrink: 0;
+}
+
+.category-card__title-box {
+ min-width: 0;
+ margin-left: 20rpx;
+ display: flex;
+ flex-direction: column;
+ justify-content: space-between;
+}
+
+.category-card__title-box-inner {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: space-between;
+
+ .category-card__id {
+ margin-left: 20rpx;
+ font-size: 26rpx;
+ color: @text-secondary;
+ }
+}
+
+.category-card__title {
+ display: block;
+ font-size: 30rpx;
+ font-weight: 700;
+ color: @text-title;
+}
+
+.category-card__subtitle {
+ display: block;
+ margin-top: 6rpx;
+ font-size: 22rpx;
+ color: @text-secondary;
+}
+
+.category-card__badge {
+ margin-left: 16rpx;
+ padding: 8rpx 16rpx;
+ border-radius: 999rpx;
+ font-size: 22rpx;
+ font-weight: 700;
+ color: #888;
+ white-space: nowrap;
+}
+
+.category-card__right {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: flex-end;
+ flex-shrink: 0;
+ margin-left: 16rpx;
+ gap: 16rpx;
+}
+
+.category-card__diff {
+ display: block;
+ margin-top: 20rpx;
+ font-size: 24rpx;
+ line-height: 1.6;
+ color: @text-secondary;
+}
+
+.category-card__detail {
+ margin-top: 16rpx;
+ padding: 20rpx 22rpx;
+ background: fade(@brand, 12%);
+ border-radius: @radius;
+}
+
+.category-card__detail-label {
+ display: block;
+ font-size: 22rpx;
+ font-weight: 700;
+ color: @text-secondary;
+}
+
+.category-card__detail-text {
+ display: block;
+ margin-top: 8rpx;
+ font-size: 24rpx;
+ line-height: 1.6;
+ color: @text-title;
+}
+
+.category-card__action {
+ margin-left: 16rpx;
+ padding: 0 22rpx;
+ height: 56rpx;
+ line-height: 56rpx;
+ border-radius: 999rpx;
+ border: none;
+ background: @brand;
+ color: @text-selected-btn;
+ font-size: 24rpx;
+ font-weight: 700;
+}
+
+.category-card__action[disabled] {
+ opacity: 0.6;
+}
+
+.category-card__action--missing {
+ background: #f7ee47;
+ color: #1f2937;
+}
+
+.category-card__action--outdated {
+ background: #93d333;
+ color: #1f2937;
+}
\ No newline at end of file
diff --git a/miniprogram/supportPages/categoryManage/categoryManage.ts b/miniprogram/supportPages/categoryManage/categoryManage.ts
new file mode 100644
index 0000000..b70181d
--- /dev/null
+++ b/miniprogram/supportPages/categoryManage/categoryManage.ts
@@ -0,0 +1,259 @@
+import { CATEGORY_LIST } from '../../core/data/categories';
+
+type CloudCategory = {
+ _id: string;
+ name: string;
+ icon: string;
+ color: string;
+ sortOrder: number;
+ parentId?: string | null;
+};
+
+type CompareStatus = 'synced' | 'missing' | 'outdated';
+
+type CompareItem = {
+ id: string;
+ name: string;
+ icon: string;
+ sortOrder: number;
+ status: CompareStatus;
+ statusText: string;
+ diffText: string;
+ actionText: string;
+ cloudCategory: CloudCategory | null;
+};
+
+type CloudFunctionResult = {
+ success?: boolean;
+ message?: string;
+ data?: T;
+};
+
+const DEFAULT_CATEGORY_COLORS = [
+ '#F7EE47',
+ '#93D333',
+ '#FFB703',
+ '#8ECAE6',
+ '#FF8FAB',
+ '#CDB4DB',
+];
+
+function getDefaultCategoryColor(id: string, index: number): string {
+ const hashBase = `${id}-${index}`;
+ let hash = 0;
+ for (let i = 0; i < hashBase.length; i++) {
+ hash = (hash * 33 + hashBase.charCodeAt(i)) | 0;
+ }
+ return DEFAULT_CATEGORY_COLORS[
+ Math.abs(hash) % DEFAULT_CATEGORY_COLORS.length
+ ];
+}
+
+function buildCompareItems(cloudCategories: CloudCategory[]): {
+ items: CompareItem[];
+ cloudOnlyCategories: CloudCategory[];
+ syncedCount: number;
+ missingCount: number;
+ outdatedCount: number;
+} {
+ const cloudMap = new Map();
+ for (const item of cloudCategories) {
+ cloudMap.set(item._id, item);
+ }
+
+ let syncedCount = 0;
+ let missingCount = 0;
+ let outdatedCount = 0;
+
+ const items = CATEGORY_LIST.map((localCategory, index) => {
+ const cloudCategory = cloudMap.get(localCategory.id) || null;
+ const sortOrder = index;
+
+ if (!cloudCategory) {
+ missingCount += 1;
+ return {
+ id: localCategory.id,
+ name: localCategory.name,
+ icon: localCategory.icon,
+ sortOrder,
+ status: 'missing' as CompareStatus,
+ statusText: '待新增',
+ diffText: '',
+ actionText: '新增',
+ cloudCategory: null,
+ };
+ }
+
+ const diffFields: string[] = [];
+ if (cloudCategory.name !== localCategory.name) diffFields.push('名称');
+ if (cloudCategory.icon !== localCategory.icon) diffFields.push('图标');
+ if ((cloudCategory.sortOrder ?? 0) !== sortOrder)
+ diffFields.push('排序');
+
+ if (diffFields.length > 0) {
+ outdatedCount += 1;
+ return {
+ id: localCategory.id,
+ name: localCategory.name,
+ icon: localCategory.icon,
+ sortOrder,
+ status: 'outdated' as CompareStatus,
+ statusText: '待更新',
+ diffText: `字段不一致:${diffFields.join('、')}。`,
+ actionText: '更新',
+ cloudCategory,
+ };
+ }
+
+ syncedCount += 1;
+ return {
+ id: localCategory.id,
+ name: localCategory.name,
+ icon: localCategory.icon,
+ sortOrder,
+ status: 'synced' as CompareStatus,
+ statusText: '已同步',
+ diffText: '',
+ actionText: '',
+ cloudCategory,
+ };
+ });
+
+ const localIds = new Set(CATEGORY_LIST.map((item) => item.id));
+ const cloudOnlyCategories = cloudCategories.filter(
+ (item) => !localIds.has(item._id),
+ );
+
+ return {
+ items,
+ cloudOnlyCategories,
+ syncedCount,
+ missingCount,
+ outdatedCount,
+ };
+}
+
+async function callCategoryFunction(
+ name: string,
+ data?: Record,
+): Promise> {
+ const response = (await wx.cloud.callFunction({
+ name,
+ data: data || {},
+ })) as { result?: CloudFunctionResult };
+
+ return response.result || {};
+}
+
+Page({
+ data: {
+ loading: false,
+ syncingId: '',
+ compareItems: [] as CompareItem[],
+ cloudOnlyCategories: [] as CloudCategory[],
+ syncedCount: 0,
+ missingCount: 0,
+ outdatedCount: 0,
+ },
+
+ onLoad() {
+ void this.loadCategories();
+ },
+
+ async onPullDownRefresh() {
+ await this.loadCategories();
+ wx.stopPullDownRefresh();
+ },
+
+ async loadCategories() {
+ this.setData({ loading: true });
+
+ try {
+ const result =
+ await callCategoryFunction('categoriesQuery');
+
+ if (!result.success) {
+ throw new Error(result.message || '获取分类失败');
+ }
+
+ const compareData = buildCompareItems(result.data || []);
+ this.setData({
+ loading: false,
+ compareItems: compareData.items,
+ cloudOnlyCategories: compareData.cloudOnlyCategories,
+ syncedCount: compareData.syncedCount,
+ missingCount: compareData.missingCount,
+ outdatedCount: compareData.outdatedCount,
+ });
+ } catch (error) {
+ this.setData({ loading: false });
+ wx.showToast({
+ title: error instanceof Error ? error.message : '获取分类失败',
+ icon: 'none',
+ });
+ }
+ },
+
+ async onTapSync(e: WechatMiniprogram.TouchEvent) {
+ const id = e.currentTarget.dataset.id as string;
+ if (!id || this.data.syncingId) return;
+
+ const item = this.data.compareItems.find((entry) => entry.id === id);
+ if (!item || !item.actionText) return;
+
+ const confirmed = await new Promise((resolve) => {
+ wx.showModal({
+ title: `${item.actionText}分类`,
+ content: `确认将「${item.name}」同步到云端吗?`,
+ success: (res) => resolve(!!res.confirm),
+ fail: () => resolve(false),
+ });
+ });
+
+ if (!confirmed) return;
+
+ this.setData({ syncingId: id });
+
+ const payload = {
+ id: item.id,
+ name: item.name,
+ icon: item.icon,
+ color:
+ item.cloudCategory?.color ||
+ getDefaultCategoryColor(item.id, item.sortOrder),
+ sortOrder: item.sortOrder,
+ parentId: item.cloudCategory?.parentId ?? null,
+ };
+
+ try {
+ const functionName =
+ item.status === 'missing'
+ ? 'categoriesCreate'
+ : 'categoriesUpdate';
+ const result = await callCategoryFunction(
+ functionName,
+ payload,
+ );
+
+ if (!result.success) {
+ throw new Error(result.message || `${item.actionText}失败`);
+ }
+
+ wx.showToast({
+ title: `${item.actionText}成功`,
+ icon: 'success',
+ });
+ await this.loadCategories();
+ } catch (error) {
+ wx.showToast({
+ title:
+ error instanceof Error
+ ? error.message
+ : `${item.actionText}失败`,
+ icon: 'none',
+ });
+ } finally {
+ this.setData({ syncingId: '' });
+ }
+ },
+});
diff --git a/miniprogram/supportPages/categoryManage/categoryManage.wxml b/miniprogram/supportPages/categoryManage/categoryManage.wxml
new file mode 100644
index 0000000..1f17f5e
--- /dev/null
+++ b/miniprogram/supportPages/categoryManage/categoryManage.wxml
@@ -0,0 +1,110 @@
+
+
+
+ {{syncedCount}}
+ 已同步
+
+
+ {{missingCount}}
+ 待新增
+
+
+ {{outdatedCount}}
+ 待更新
+
+
+
+
+ 以本地 `CATEGORY_LIST` 为基准,逐项比对云端 `categories` 集合。
+
+
+
+ 正在加载分类数据...
+
+
+
+
+
+
+
+ {{item.diffText}}
+
+
+
+ 云端
+
+ {{item.cloudCategory.name}} · {{item.cloudCategory.icon}} ·
+ 排序 {{item.cloudCategory.sortOrder}}
+
+
+
+
+
+
+ 仅云端存在的分类
+
+
+
+
+
diff --git a/miniprogram/supportPages/debug/debug.json b/miniprogram/supportPages/debug/debug.json
index 784022f..088b2e9 100644
--- a/miniprogram/supportPages/debug/debug.json
+++ b/miniprogram/supportPages/debug/debug.json
@@ -1,16 +1,6 @@
{
- "navigationBarTitleText": "Debug",
- "navigationBarBackgroundColor": "#FFD719",
- "homeButton": true,
- "backgroundColor": "#F6F6F6",
- "enablePullDownRefresh": false,
- "usingComponents": {
- "toy-button": "../../toy/button-v2/button",
- "van-radio": "@vant/weapp/radio/index",
- "van-radio-group": "@vant/weapp/radio-group/index",
- "van-cell": "@vant/weapp/cell/index",
- "van-cell-group": "@vant/weapp/cell-group/index",
- "van-switch": "@vant/weapp/switch/index",
- "van-field": "@vant/weapp/field/index"
- }
+ "navigationBarTitleText": "Debug 工具",
+ "navigationBarTextStyle": "black",
+ "navigationBarBackgroundColor": "#F8F0E0",
+ "backgroundColor": "#F8F0E0"
}
diff --git a/miniprogram/supportPages/debug/debug.less b/miniprogram/supportPages/debug/debug.less
index c32450a..804440b 100644
--- a/miniprogram/supportPages/debug/debug.less
+++ b/miniprogram/supportPages/debug/debug.less
@@ -1,31 +1,127 @@
+@import '../../style/theme.less';
+
+page {
+ min-height: 100%;
+ background: @bg-header;
+}
+
.debug-page {
min-height: 100vh;
- padding: 20rpx;
- background-color: #F6F6F6;
+ padding: 24rpx;
+ background: @bg-header;
+ box-sizing: border-box;
+}
- .debug-wrapper {
- margin-top: 30rpx;
- background-color: #fff;
- border-radius: 20rpx;
- overflow: hidden;
+.debug-page__hero {
+ padding: 48rpx 40rpx;
+ background: @bg-white;
+ border-radius: @radius-xl;
+ box-shadow: @shadow;
+}
- .centered-title {
- text-align: center;
- color: #666;
- border-top: 0 none;
- }
+.debug-page__hero-title {
+ display: block;
+ font-size: 40rpx;
+ font-weight: 800;
+ color: @text-title;
+}
- .debug-cell {
- display: flex;
- align-items: center;
- justify-content: space-between;
- }
- }
+.debug-page__hero-desc {
+ display: block;
+ margin-top: 16rpx;
+ font-size: 26rpx;
+ line-height: 1.6;
+ color: @text-secondary;
+}
- .btn-area {
- display: flex;
- align-items: center;
- justify-content: center;
- margin-top: 40rpx;
- }
-}
\ No newline at end of file
+.debug-page__section {
+ margin-top: 32rpx;
+}
+
+.debug-page__section-title {
+ display: block;
+ margin: 0 8rpx 20rpx;
+ font-size: 26rpx;
+ font-weight: 700;
+ color: @text-secondary;
+}
+
+.debug-page__rows {
+ display: flex;
+ flex-direction: column;
+}
+
+.debug-row + .debug-row {
+ margin-top: 24rpx;
+}
+
+.debug-row {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 34rpx 36rpx;
+ background: @bg-white;
+ border-radius: 999rpx;
+ border: 1rpx solid rgba(124, 118, 106, 0.12);
+ box-shadow: @shadow;
+}
+
+.debug-row__left {
+ display: flex;
+ align-items: center;
+ min-width: 0;
+ flex: 1;
+}
+
+.debug-row__icon-bg {
+ width: 84rpx;
+ height: 84rpx;
+ border-radius: 50%;
+ background: fade(@brand, 18%);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ flex-shrink: 0;
+}
+
+.debug-row__icon {
+ font-size: 36rpx;
+ line-height: 1;
+}
+
+.debug-row__content {
+ min-width: 0;
+ margin-left: 24rpx;
+}
+
+.debug-row__label {
+ display: block;
+ font-size: 30rpx;
+ font-weight: 700;
+ color: @text-title;
+}
+
+.debug-row__desc {
+ display: block;
+ margin-top: 8rpx;
+ font-size: 22rpx;
+ line-height: 1.5;
+ color: @text-secondary;
+}
+
+.debug-row__chevron {
+ margin-left: 16rpx;
+ font-size: 40rpx;
+ font-weight: 300;
+ color: @text-gray;
+}
+
+.debug-page__notice {
+ margin-top: 32rpx;
+ padding: 24rpx 28rpx;
+ border-radius: @radius;
+ background: fade(#ff8f1f, 12%);
+ color: #b06b1a;
+ font-size: 24rpx;
+ line-height: 1.6;
+}
diff --git a/miniprogram/supportPages/debug/debug.ts b/miniprogram/supportPages/debug/debug.ts
index 2259583..88eec5c 100644
--- a/miniprogram/supportPages/debug/debug.ts
+++ b/miniprogram/supportPages/debug/debug.ts
@@ -1,43 +1,44 @@
-import { defaultPrintConfig } from '../../config/config';
+type DebugEntry = {
+ id: string;
+ title: string;
+ subtitle: string;
+ icon: string;
+ path: string;
+};
+
+const DEBUG_ENTRIES: DebugEntry[] = [
+ {
+ id: 'category-manage',
+ title: '分类管理',
+ subtitle: '对比本地与云端分类数据,执行新增或更新。',
+ icon: '🗂️',
+ path: '/supportPages/categoryManage/categoryManage',
+ },
+];
Page({
data: {
- printConfig: defaultPrintConfig,
- enableDebug: false,
+ entries: DEBUG_ENTRIES,
+ isDevEnv: true,
},
onLoad() {
- const printConfig = getApp().getPrintConfig() || defaultPrintConfig;
- const enableDebug = wx.getStorageSync('enableDebug') || false;
- this.setData({ printConfig, enableDebug });
+ const envVersion = wx.getAccountInfoSync().miniProgram.envVersion;
+ const isDevEnv = envVersion === 'develop';
+ this.setData({ isDevEnv });
+
+ if (!isDevEnv) {
+ wx.showToast({
+ title: '仅开发版可用',
+ icon: 'none',
+ });
+ }
},
- onChangeHeader(e: WechatMiniprogram.CustomEvent) {
- const header = e.detail.value as PrintHeader;
- this.setData({ printConfig: { ...this.data.printConfig, header } });
- },
-
- onClickHeaderSetting(e: WechatMiniprogram.CustomEvent) {
- const header = e.currentTarget.dataset.name as PrintHeader;
- this.setData({ printConfig: { ...this.data.printConfig, header } });
- },
-
- onAppNameChange(e: WechatMiniprogram.CustomEvent) {
- const appName = e.detail + '';
- this.setData({ printConfig: { ...this.data.printConfig, appName } });
- },
-
- onConfirm() {
- getApp().setPrintConfig(this.data.printConfig);
- const enableDebug = this.data.enableDebug;
- wx.setStorageSync('enableDebug', enableDebug);
- wx.setEnableDebug({ enableDebug });
- wx.navigateBack();
- },
-
- /** 真机调试线上包 */
- toggleDebug() {
- const enableDebug = !this.data.enableDebug;
- this.setData({ enableDebug });
+ onTapEntry(e: WechatMiniprogram.TouchEvent) {
+ if (!this.data.isDevEnv) return;
+ const path = e.currentTarget.dataset.path as string;
+ if (!path) return;
+ wx.navigateTo({ url: path });
},
});
diff --git a/miniprogram/supportPages/debug/debug.wxml b/miniprogram/supportPages/debug/debug.wxml
index 3e722ef..cd707b7 100644
--- a/miniprogram/supportPages/debug/debug.wxml
+++ b/miniprogram/supportPages/debug/debug.wxml
@@ -1,78 +1,35 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 确定
-
+
+ Debug 工具页
+
+ 仅开发环境可见,用于发布前检查和同步调试数据。
+
-
-
-
+
+ 入口列表
+
+
+
+
+ {{item.icon}}
+
+
+ {{item.title}}
+ {{item.subtitle}}
+
+
+ ›
+
+
+
+
+
+ 当前不是开发环境,此页仅供调试使用。
+
diff --git a/miniprogram/supportPages/index/index.ts b/miniprogram/supportPages/index/index.ts
index 324f7a2..00d2cfd 100644
--- a/miniprogram/supportPages/index/index.ts
+++ b/miniprogram/supportPages/index/index.ts
@@ -449,7 +449,7 @@ Page({
onDebugEntryTap() {
wx.navigateTo({
- url: '/pages/debug/debug',
+ url: '/supportPages/debug/debug',
});
},
diff --git a/miniprogram/supportPages/index/index.wxml b/miniprogram/supportPages/index/index.wxml
index 36b818b..d9f7c8e 100644
--- a/miniprogram/supportPages/index/index.wxml
+++ b/miniprogram/supportPages/index/index.wxml
@@ -99,7 +99,7 @@
is-link
title="debug页面"
link-type="navigateTo"
- url="/pages/debug/debug" />
+ url="/supportPages/debug/debug" />