feat: 完成全部接口替换为新后端接口
This commit is contained in:
@@ -1,3 +1,6 @@
|
||||
import { compareCountDescending } from '../../pages/category/category.model';
|
||||
import { managementRequest } from '../../services/admin-api';
|
||||
import { resolvePreviewUrl } from '../../config/assets';
|
||||
import { CATEGORY_LIST } from '../../core/data/categories';
|
||||
|
||||
type WorksheetItem = {
|
||||
@@ -13,8 +16,8 @@ type WorksheetItem = {
|
||||
tagsText: string;
|
||||
status: 'draft' | 'active' | 'hidden';
|
||||
sortOrder: number;
|
||||
downloads: number;
|
||||
likes: number;
|
||||
downloads: string;
|
||||
likes: string;
|
||||
updatedAt: string;
|
||||
// display helpers
|
||||
ageBand: string;
|
||||
@@ -32,13 +35,6 @@ type Stats = {
|
||||
hidden: number;
|
||||
};
|
||||
|
||||
type CloudFunctionResult<T> = {
|
||||
success?: boolean;
|
||||
message?: string;
|
||||
data?: T;
|
||||
stats?: Stats;
|
||||
};
|
||||
|
||||
const DIFFICULTY_LABELS: Record<number, string> = {
|
||||
1: '入门',
|
||||
2: '基础',
|
||||
@@ -82,7 +78,7 @@ function formatWorksheet(raw: Record<string, unknown>): WorksheetItem {
|
||||
title: String(raw.title || ''),
|
||||
subtitle: String(raw.subtitle || ''),
|
||||
category: String(raw.category || ''),
|
||||
previewImg: String(raw.previewImg || ''),
|
||||
previewImg: resolvePreviewUrl(raw.previewImg),
|
||||
ageMin,
|
||||
ageMax,
|
||||
difficulty,
|
||||
@@ -92,8 +88,8 @@ function formatWorksheet(raw: Record<string, unknown>): WorksheetItem {
|
||||
: '',
|
||||
status: status as WorksheetItem['status'],
|
||||
sortOrder: Number(raw.sortOrder) || 0,
|
||||
downloads: Number(raw.downloads) || 0,
|
||||
likes: Number(raw.likes) || 0,
|
||||
downloads: String(raw.downloads || '0'),
|
||||
likes: String(raw.likes || '0'),
|
||||
updatedAt: raw.updatedAt ? String(raw.updatedAt) : '',
|
||||
ageBand: `${ageMin}-${ageMax}岁`,
|
||||
difficultyLabel: DIFFICULTY_LABELS[difficulty] || '基础',
|
||||
@@ -104,17 +100,6 @@ function formatWorksheet(raw: Record<string, unknown>): WorksheetItem {
|
||||
};
|
||||
}
|
||||
|
||||
async function callCloudFunction<T>(
|
||||
name: string,
|
||||
data?: Record<string, unknown>,
|
||||
): Promise<CloudFunctionResult<T>> {
|
||||
const response = (await wx.cloud.callFunction({
|
||||
name,
|
||||
data: data || {},
|
||||
})) as { result?: CloudFunctionResult<T> };
|
||||
return response.result || {};
|
||||
}
|
||||
|
||||
Page({
|
||||
data: {
|
||||
categories: CATEGORY_LIST,
|
||||
@@ -139,8 +124,8 @@ Page({
|
||||
this.setData({ loading: true });
|
||||
|
||||
try {
|
||||
const result = await callCloudFunction<WorksheetItem[]>(
|
||||
'worksheetsQuery',
|
||||
const result = await managementRequest<WorksheetItem[]>(
|
||||
'worksheets.list',
|
||||
{
|
||||
category: this.data.activeCategoryId,
|
||||
rawStats: true,
|
||||
@@ -155,7 +140,9 @@ Page({
|
||||
.map((raw) =>
|
||||
formatWorksheet(raw as unknown as Record<string, unknown>),
|
||||
)
|
||||
.sort((a, b) => b.downloads - a.downloads);
|
||||
.sort((a, b) =>
|
||||
compareCountDescending(a.downloads, b.downloads),
|
||||
);
|
||||
|
||||
this.setData({
|
||||
loading: false,
|
||||
@@ -204,7 +191,7 @@ Page({
|
||||
this.setData({ updatingId: id });
|
||||
|
||||
try {
|
||||
const result = await callCloudFunction('worksheetsUpdateStatus', {
|
||||
const result = await managementRequest('worksheets.status', {
|
||||
id,
|
||||
status: target,
|
||||
});
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { managementRequest } from '../../services/admin-api';
|
||||
import { CATEGORY_LIST } from '../../core/data/categories';
|
||||
|
||||
type CloudCategory = {
|
||||
@@ -23,12 +24,6 @@ type CompareItem = {
|
||||
cloudCategory: CloudCategory | null;
|
||||
};
|
||||
|
||||
type CloudFunctionResult<T> = {
|
||||
success?: boolean;
|
||||
message?: string;
|
||||
data?: T;
|
||||
};
|
||||
|
||||
const DEFAULT_CATEGORY_COLORS = [
|
||||
'#F7EE47',
|
||||
'#93D333',
|
||||
@@ -133,18 +128,6 @@ function buildCompareItems(cloudCategories: CloudCategory[]): {
|
||||
};
|
||||
}
|
||||
|
||||
async function callCategoryFunction<T>(
|
||||
name: string,
|
||||
data?: Record<string, unknown>,
|
||||
): Promise<CloudFunctionResult<T>> {
|
||||
const response = (await wx.cloud.callFunction({
|
||||
name,
|
||||
data: data || {},
|
||||
})) as { result?: CloudFunctionResult<T> };
|
||||
|
||||
return response.result || {};
|
||||
}
|
||||
|
||||
Page({
|
||||
data: {
|
||||
loading: false,
|
||||
@@ -170,7 +153,7 @@ Page({
|
||||
|
||||
try {
|
||||
const result =
|
||||
await callCategoryFunction<CloudCategory[]>('categoriesQuery');
|
||||
await managementRequest<CloudCategory[]>('categories.list');
|
||||
|
||||
if (!result.success) {
|
||||
throw new Error(result.message || '获取分类失败');
|
||||
@@ -204,7 +187,7 @@ Page({
|
||||
const confirmed = await new Promise<boolean>((resolve) => {
|
||||
wx.showModal({
|
||||
title: `${item.actionText}分类`,
|
||||
content: `确认将「${item.name}」同步到云端吗?`,
|
||||
content: `确认将「${item.name}」同步到新后端吗?`,
|
||||
success: (res) => resolve(!!res.confirm),
|
||||
fail: () => resolve(false),
|
||||
});
|
||||
@@ -228,9 +211,9 @@ Page({
|
||||
try {
|
||||
const functionName =
|
||||
item.status === 'missing'
|
||||
? 'categoriesCreate'
|
||||
: 'categoriesUpdate';
|
||||
const result = await callCategoryFunction<CloudCategory>(
|
||||
? 'categories.create'
|
||||
: 'categories.update';
|
||||
const result = await managementRequest<CloudCategory>(
|
||||
functionName,
|
||||
payload,
|
||||
);
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
import { compareCountDescending } from '../../pages/category/category.model';
|
||||
import { apiRequest } from '../../services/api-request';
|
||||
import { managementRequest } from '../../services/admin-api';
|
||||
import { resolvePreviewUrl } from '../../config/assets';
|
||||
import { CATEGORY_LIST } from '../../core/data/categories';
|
||||
|
||||
type SimpleWorksheet = {
|
||||
@@ -13,8 +17,8 @@ type SimpleWorksheet = {
|
||||
isHot: boolean;
|
||||
path: string;
|
||||
ageBand: string;
|
||||
downloads: number;
|
||||
likes: number;
|
||||
downloads: string;
|
||||
likes: string;
|
||||
};
|
||||
|
||||
type SectionConfig = {
|
||||
@@ -43,12 +47,6 @@ type PageConfig = {
|
||||
[key: string]: unknown;
|
||||
};
|
||||
|
||||
type CloudFunctionResult<T> = {
|
||||
success?: boolean;
|
||||
message?: string;
|
||||
data?: T;
|
||||
};
|
||||
|
||||
function formatSimple(raw: Record<string, unknown>): SimpleWorksheet {
|
||||
const ageMin = Number(raw.ageMin) || 0;
|
||||
const ageMax = Number(raw.ageMax) || 0;
|
||||
@@ -57,7 +55,7 @@ function formatSimple(raw: Record<string, unknown>): SimpleWorksheet {
|
||||
title: String(raw.title || ''),
|
||||
subtitle: String(raw.subtitle || ''),
|
||||
category: String(raw.category || ''),
|
||||
previewImg: String(raw.previewImg || ''),
|
||||
previewImg: resolvePreviewUrl(raw.previewImg),
|
||||
ageMin,
|
||||
ageMax,
|
||||
difficulty: Number(raw.difficulty) || 2,
|
||||
@@ -65,22 +63,11 @@ function formatSimple(raw: Record<string, unknown>): SimpleWorksheet {
|
||||
isHot: !!raw.isHot,
|
||||
path: String(raw.path || ''),
|
||||
ageBand: `${ageMin}-${ageMax}岁`,
|
||||
downloads: Number(raw.downloads) || 0,
|
||||
likes: Number(raw.likes) || 0,
|
||||
downloads: String(raw.downloads || '0'),
|
||||
likes: String(raw.likes || '0'),
|
||||
};
|
||||
}
|
||||
|
||||
async function callCloudFunction<T>(
|
||||
name: string,
|
||||
data?: Record<string, unknown>,
|
||||
): Promise<CloudFunctionResult<T>> {
|
||||
const response = (await wx.cloud.callFunction({
|
||||
name,
|
||||
data: data || {},
|
||||
})) as { result?: CloudFunctionResult<T> };
|
||||
return response.result || {};
|
||||
}
|
||||
|
||||
Page({
|
||||
data: {
|
||||
featured: [] as SimpleWorksheet[],
|
||||
@@ -122,15 +109,15 @@ Page({
|
||||
|
||||
async loadTimerStatus() {
|
||||
try {
|
||||
const db = wx.cloud.database();
|
||||
const { data } = await db
|
||||
.collection('settings')
|
||||
.doc('homeAutoRefresh')
|
||||
.get();
|
||||
this.setData({ timerEnabled: (data as { enabled?: boolean }).enabled !== false });
|
||||
const data = await apiRequest<{ enabled: boolean }>(
|
||||
'/admin/site/timer',
|
||||
);
|
||||
this.setData({
|
||||
timerEnabled: (data as { enabled?: boolean }).enabled !== false,
|
||||
});
|
||||
} catch {
|
||||
// Document doesn't exist — default enabled
|
||||
this.setData({ timerEnabled: true });
|
||||
// 权限或网络失败不能被当成已启用。
|
||||
this.setData({ timerEnabled: false });
|
||||
}
|
||||
},
|
||||
|
||||
@@ -139,13 +126,14 @@ Page({
|
||||
try {
|
||||
// Fetch in parallel: active worksheets + saved page config
|
||||
const [wsResult, configResult] = await Promise.all([
|
||||
callCloudFunction<SimpleWorksheet[]>('worksheetsQuery', {
|
||||
managementRequest<SimpleWorksheet[]>('worksheets.list', {
|
||||
status: 'active',
|
||||
}),
|
||||
callCloudFunction<PageConfig>('pageConfigFetch'),
|
||||
managementRequest<PageConfig>('site.config'),
|
||||
]);
|
||||
|
||||
if (!wsResult.success) throw new Error(wsResult.message || '查询失败');
|
||||
if (!wsResult.success)
|
||||
throw new Error(wsResult.message || '查询失败');
|
||||
|
||||
const allActive = (wsResult.data || []).map((raw) =>
|
||||
formatSimple(raw as unknown as Record<string, unknown>),
|
||||
@@ -156,16 +144,21 @@ Page({
|
||||
|
||||
// featured: always top-5 by downloads; hot: always top-5 by likes
|
||||
const featured: SimpleWorksheet[] = [...allActive]
|
||||
.sort((a, b) => (b.downloads ?? 0) - (a.downloads ?? 0))
|
||||
.sort((a, b) =>
|
||||
compareCountDescending(a.downloads, b.downloads),
|
||||
)
|
||||
.slice(0, 5);
|
||||
const hot: SimpleWorksheet[] = [...allActive]
|
||||
.sort((a, b) => (b.likes ?? 0) - (a.likes ?? 0))
|
||||
.sort((a, b) => compareCountDescending(a.likes, b.likes))
|
||||
.slice(0, 5);
|
||||
|
||||
// Restore saved sections from config
|
||||
const savedHome = (configResult.data as PageConfig | undefined)?.home;
|
||||
const savedHome = (configResult.data as PageConfig | undefined)
|
||||
?.home;
|
||||
const savedSections: HomeConfigItem[] = savedHome?.sections || [];
|
||||
const savedSectionMap = new Map(savedSections.map((s) => [s.id, s]));
|
||||
const savedSectionMap = new Map(
|
||||
savedSections.map((s) => [s.id, s]),
|
||||
);
|
||||
|
||||
const sections: SectionConfig[] = CATEGORY_LIST.map((c) => {
|
||||
const saved = savedSectionMap.get(c.id);
|
||||
@@ -184,7 +177,13 @@ Page({
|
||||
};
|
||||
});
|
||||
|
||||
this.setData({ loading: false, allActive, featured, hot, sections });
|
||||
this.setData({
|
||||
loading: false,
|
||||
allActive,
|
||||
featured,
|
||||
hot,
|
||||
sections,
|
||||
});
|
||||
} catch (error) {
|
||||
this.setData({ loading: false });
|
||||
wx.showToast({
|
||||
@@ -202,7 +201,7 @@ Page({
|
||||
|
||||
this.setData({ timerLoading: true });
|
||||
try {
|
||||
const result = await callCloudFunction('homeTimerControl', {
|
||||
const result = await managementRequest('site.timer', {
|
||||
enabled: newEnabled,
|
||||
});
|
||||
if (!result.success) {
|
||||
@@ -335,9 +334,9 @@ Page({
|
||||
this.setData({ building: true });
|
||||
|
||||
try {
|
||||
const result = await callCloudFunction<{
|
||||
const result = await managementRequest<{
|
||||
version: number;
|
||||
}>('pageContentBuild', {
|
||||
}>('site.rebuild', {
|
||||
page: 'home',
|
||||
featuredIds: this.data.featured.map((w) => w._id),
|
||||
hotIds: this.data.hot.map((w) => w._id),
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { apiRequest } from '../../services/api-request';
|
||||
import { disablePageShareMenu } from '../../base/pageMixin';
|
||||
import { clearUser } from '../../utils/auth';
|
||||
import { clearUser, refreshUser } from '../../utils/auth';
|
||||
|
||||
Page({
|
||||
onLoad() {
|
||||
@@ -22,15 +23,8 @@ Page({
|
||||
async doClearProfile() {
|
||||
wx.showLoading({ title: '处理中...', mask: true });
|
||||
try {
|
||||
const res = await wx.cloud.callFunction({
|
||||
name: 'userSettings',
|
||||
data: { action: 'clearProfile' },
|
||||
});
|
||||
const result = (res?.result as any) || {};
|
||||
if (result.code !== 0) {
|
||||
throw new Error(result.message || '操作失败');
|
||||
}
|
||||
clearUser();
|
||||
await apiRequest('/me/profile', { method: 'DELETE' });
|
||||
await refreshUser();
|
||||
wx.hideLoading();
|
||||
wx.showToast({ title: '已删除', icon: 'success' });
|
||||
} catch (e) {
|
||||
@@ -58,15 +52,8 @@ Page({
|
||||
async doDeleteAccount() {
|
||||
wx.showLoading({ title: '处理中...', mask: true });
|
||||
try {
|
||||
const res = await wx.cloud.callFunction({
|
||||
name: 'userSettings',
|
||||
data: { action: 'deleteAccount' },
|
||||
});
|
||||
const result = (res?.result as any) || {};
|
||||
if (result.code !== 0) {
|
||||
throw new Error(result.message || '操作失败');
|
||||
}
|
||||
clearUser();
|
||||
await apiRequest('/me', { method: 'DELETE' });
|
||||
clearUser(true);
|
||||
wx.hideLoading();
|
||||
|
||||
wx.reLaunch({ url: '/pages/home/home' });
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { managementRequest } from '../../services/admin-api';
|
||||
import { MOCK_SEED_COUNTS } from './mockLikes';
|
||||
import {
|
||||
MATH_WORKSHEET_DEFINITIONS,
|
||||
@@ -21,17 +22,6 @@ type CloudFunctionResult<T> = {
|
||||
results?: Array<{ id: string | null; ok: boolean; error?: string }>;
|
||||
};
|
||||
|
||||
async function callCloudFunction<T>(
|
||||
name: string,
|
||||
data?: Record<string, unknown>,
|
||||
): Promise<CloudFunctionResult<T>> {
|
||||
const response = (await wx.cloud.callFunction({
|
||||
name,
|
||||
data: data || {},
|
||||
})) as { result?: CloudFunctionResult<T> };
|
||||
return response.result || {};
|
||||
}
|
||||
|
||||
function inferGradeFromAge(ageMin: number, ageMax: number): number {
|
||||
const centerAge = Math.round((ageMin + ageMax) / 2);
|
||||
const ageGradeMap: Record<number, number> = {
|
||||
@@ -224,7 +214,7 @@ Page({
|
||||
const startedAt = Date.now();
|
||||
|
||||
try {
|
||||
const patchRes = await callCloudFunction('worksheetsBatchPatch', {
|
||||
const patchRes = await managementRequest('worksheets.batch', {
|
||||
patches,
|
||||
dryRun: false,
|
||||
});
|
||||
@@ -262,7 +252,7 @@ Page({
|
||||
const startedAt = Date.now();
|
||||
|
||||
try {
|
||||
const rebuildRes = await callCloudFunction('pageContentBuild', {
|
||||
const rebuildRes = await managementRequest('site.rebuild', {
|
||||
page: 'all',
|
||||
});
|
||||
const elapsed = Math.round((Date.now() - startedAt) / 1000);
|
||||
@@ -358,7 +348,7 @@ Page({
|
||||
}),
|
||||
);
|
||||
|
||||
const patchRes = await callCloudFunction('worksheetsBatchPatch', {
|
||||
const patchRes = await managementRequest('worksheets.batch', {
|
||||
patches,
|
||||
dryRun: false,
|
||||
});
|
||||
@@ -415,8 +405,8 @@ Page({
|
||||
const startedAt = Date.now();
|
||||
|
||||
try {
|
||||
const queryRes = await callCloudFunction<Array<{ _id: string }>>(
|
||||
'worksheetsQuery',
|
||||
const queryRes = await managementRequest<Array<{ _id: string }>>(
|
||||
'worksheets.list',
|
||||
{},
|
||||
);
|
||||
|
||||
@@ -438,7 +428,7 @@ Page({
|
||||
return;
|
||||
}
|
||||
|
||||
const patchRes = await callCloudFunction('worksheetsBatchPatch', {
|
||||
const patchRes = await managementRequest('worksheets.batch', {
|
||||
patches,
|
||||
dryRun: false,
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user