chore: establish V1.1 recovery baseline

This commit is contained in:
2026-09-09 22:05:00 +08:00
commit b46b48eb33
947 changed files with 155471 additions and 0 deletions
+77
View File
@@ -0,0 +1,77 @@
/**
* 微信小程序全局类型声明
*/
/// <reference types="miniprogram-api-typings" />
// ===== Stores 模块类型 =====
declare module '../../stores' {
export const authStore: {
state: { isLoggedIn: boolean; userId: string | null; phoneBound: boolean; authStatus: string }
loginWithWechat: (code: string) => Promise<any>
logout: () => Promise<void>
}
export const userStore: {
state: { userState: any; profile: any }
hydrate: () => void
fetchStatus: () => Promise<void>
subscribe: (cb: (state: any) => void) => () => void
bindToPage: (page: any, fields: Record<string, string>) => () => void
}
export const matchStore: {
state: { recommendations: any[]; recState: string; likersCount: number }
fetchRecommendations: () => Promise<void>
loadMoreRecommendations: () => Promise<void>
fetchLikersCount: () => Promise<void>
like: (userId: string) => Promise<any>
pass: (userId: string) => Promise<void>
block: (userId: string, reason?: string) => Promise<void>
unmatch: (matchId: string) => Promise<void>
confirmSuccess: (matchId: string) => Promise<any>
subscribe: (cb: (state: any) => void) => () => void
bindToPage: (page: any, fields: Record<string, string>) => () => void
}
export const messageStore: {
state: { conversations: any[]; currentConversationId: string | null }
openConversation: (id: string) => Promise<void>
closeConversation: () => void
fetchConversations: () => Promise<void>
markConversationRead: (id: string) => Promise<void>
markConversationBlocked: (id: string) => void
onMessage: (convId: string, cb: (msg: any) => void) => () => void
subscribe: (cb: (state: any) => void) => () => void
bindToPage: (page: any, fields: Record<string, string>) => () => void
}
export const appStore: {
state: { loading: boolean }
init: () => Promise<void>
toast: (msg: string) => void
toastSuccess: (msg: string) => void
toastError: (msg: string, fallback?: string) => void
showLoading: (msg?: string) => void
hideLoading: () => void
confirm: (opts: { title: string; content: string; confirmText: string; danger?: boolean }) => Promise<boolean>
}
export const blockUser: (userId: string, reason?: string) => Promise<void>
export const likeUser: (userId: string) => Promise<any>
}
// ===== Constants 模块类型 =====
declare module '../../constants' {
export const ROUTE: {
TAB: { HOME: string; DISCOVER: string; MESSAGES: string; ACTIVITY: string; MINE: string }
MAIN: { DISCOVER: string; FATE_CENTER: string }
DETAIL: { PROFILE_DETAIL: string; ACTIVITY_REGISTER: string; MATCHMAKER_APPLY: string; LIKERS: string; MATCHMAKER_PROGRESS: string }
REVIEW: { PENDING: string; REJECTED: string; ACCOUNT_STATUS: string }
AUTH: { LOGIN: string }
}
export const to: {
detail: (userId: string) => string
chat: (convId: string) => string
}
export const BUSINESS_LIMITS: { MAX_PROFILE_PHOTOS: number }
export const RECOMMENDATION_STATE: { IDLE: string; LOADING: string; ERROR: string; EMPTY: string }
export const PROFILE_REVIEW: { NOT_SUBMITTED: string; PENDING: string; APPROVED: string; NEED_EDIT: string; REJECTED: string }
export const ACCOUNT_STATUS: { NORMAL: string; BANNED: string; SUSPENDED: string }
export const DANGER_ACTION: { BLOCK: string; UNMATCH: string }
export const BUSINESS_ERROR_CODE: { PROFILE_NOT_APPROVED: string; ACCOUNT_BANNED: string }
}
+79
View File
@@ -0,0 +1,79 @@
// 全局类型声明 — 供 miniapp TypeScript 页面使用
/// <reference types="miniprogram-api-typings" />
// Page 全局声明(微信小程序全局函数)
declare function Page<T>(obj: T & WechatMiniprogram.Page.ILifetime): void;
// Stores 模块声明
declare module '../../stores' {
export const authStore: {
state: { isLoggedIn: boolean; userId: string | null; phoneBound: boolean; authStatus: string; lastError: any }
loginWithWechat: (code: string) => Promise<any>
logout: () => Promise<void>
}
export const userStore: {
state: { userState: any; profile: any }
hydrate: () => void
fetchStatus: () => Promise<void>
subscribe: (cb: (state: any) => void) => () => void
bindToPage: (page: any, fields: Record<string, string>) => () => void
}
export const matchStore: {
state: { recommendations: any[]; recState: string; likersCount: number; matches: any[] }
fetchRecommendations: () => Promise<void>
loadMoreRecommendations: () => Promise<void>
fetchLikersCount: () => Promise<void>
like: (userId: string) => Promise<any>
pass: (userId: string) => Promise<void>
block: (userId: string, reason?: string) => Promise<void>
unmatch: (matchId: string) => Promise<void>
confirmSuccess: (matchId: string) => Promise<any>
subscribe: (cb: (state: any) => void) => () => void
bindToPage: (page: any, fields: Record<string, string>) => () => void
}
export const messageStore: {
state: { conversations: any[]; currentConversationId: string | null; connectionState: string }
openConversation: (id: string) => Promise<void>
closeConversation: () => void
fetchConversations: () => Promise<void>
markConversationRead: (id: string) => Promise<void>
markConversationBlocked: (id: string) => void
onMessage: (convId: string, cb: (msg: any) => void) => () => void
subscribe: (cb: (state: any) => void) => () => void
bindToPage: (page: any, fields: Record<string, string>) => () => void
}
export const appStore: {
state: { loading: boolean }
init: () => Promise<void>
toast: (msg: string) => void
toastSuccess: (msg: string) => void
toastError: (msg: string, fallback?: string) => void
showLoading: (msg?: string) => void
hideLoading: () => void
confirm: (opts: { title: string; content: string; confirmText: string; danger?: boolean }) => Promise<boolean>
}
export const blockUser: (userId: string, reason?: string) => Promise<void>
export const likeUser: (userId: string) => Promise<any>
}
// Constants 模块声明
declare module '../../constants' {
export const ROUTE: {
TAB: { HOME: string; DISCOVER: string; MESSAGES: string; ACTIVITY: string; MINE: string }
MAIN: { DISCOVER: string; FATE_CENTER: string }
DETAIL: { PROFILE_DETAIL: string; ACTIVITY_REGISTER: string; MATCHMAKER_APPLY: string; LIKERS: string; MATCHMAKER_PROGRESS: string }
REVIEW: { PENDING: string; REJECTED: string; ACCOUNT_STATUS: string }
AUTH: { LOGIN: string }
}
export const to: {
detail: (userId: string) => string
chat: (convId: string) => string
report: (userId: string) => string
}
export const BUSINESS_LIMITS: { MAX_PROFILE_PHOTOS: number }
export const RECOMMENDATION_STATE: { IDLE: string; LOADING: string; ERROR: string; EMPTY: string }
export const PROFILE_REVIEW: { NOT_SUBMITTED: string; PENDING: string; APPROVED: string; NEED_EDIT: string; REJECTED: string }
export const ACCOUNT_STATUS: { NORMAL: string; BANNED: string; SUSPENDED: string }
export const DANGER_ACTION: { BLOCK: string; UNMATCH: string }
export const BUSINESS_ERROR_CODE: { PROFILE_NOT_APPROVED: string; ACCOUNT_BANNED: string }
}
+241
View File
@@ -0,0 +1,241 @@
/**
* 业务类型定义(规范 §134 types 目录)
*
* 统一存放 User / Profile / PartnerPreference / MatchRelation / Conversation /
* Activity / MatchmakerService / Report 等核心类型。
* 配合 package.json 的 `tsc --noEmit` 提供 IntelliSense 与类型检查。
* 状态字符串引用 constants/statusEnums.js 的同名常量,避免魔法字符串。
*/
// ============ 统一 API 响应(规范 §1 API 规范) ============
export interface ApiResponse<T = unknown> {
success: boolean;
code: string;
message: string;
data: T;
requestId?: string;
}
export interface ApiError {
code: string;
message: string;
requestId?: string;
/** 原始错误(仅 NETWORK_ERROR 携带) */
error?: unknown;
}
// ============ User / Profile(规范 §107-108) ============
export interface User {
userId: string;
displayName: string; // 前台显示:王女士
age: number; // 前台显示:32
heightCm?: number;
regionName: string; // 前台显示:丹阳
educationCode?: string; // 本科 / 大专 / 硕士 等
occupationCode?: string; // 教师 / 制造业 等(不公开 XX公司XX部门)
maritalStatus?: MaritalStatus;
avatarUrl?: string;
verified?: boolean; // 已实名
reviewed?: boolean; // 已审核
photoUrls?: string[];
}
export type MaritalStatus = 'never_married' | 'divorced' | 'widowed';
export interface Profile {
userId: string;
displayName: string;
avatarUrl?: string;
photoUrls: string[];
birthDate?: string; // 服务端存储完整,前台只显示 age
heightCm?: number;
regionName: string;
educationCode?: string;
occupationCode?: string;
maritalStatus: MaritalStatus;
hasChildren: boolean;
smoking: boolean;
drinking?: DrinkingHabit;
interests: string[];
intro: string; // 自我介绍
intent: RelationshipIntent; // 婚恋态度
}
export type DrinkingHabit = 'never' | 'occasionally' | 'frequently';
export type RelationshipIntent =
| 'serious_marriage' // 认真找对象结婚
| 'getting_to_know' // 先了解
| 'open_minded'; // 顺其自然
// ============ PartnerPreference(择偶条件,规范 §30) ============
export interface PartnerPreference {
ageMin: number;
ageMax: number;
ageImportance: PreferenceImportance; // 必须符合 / 最好符合
heightMin?: number;
heightMax?: number;
heightImportance: PreferenceImportance;
region: string[]; // [丹阳]
regionImportance: PreferenceImportance;
maritalStatusAccepted: MaritalStatus[];
educationAccepted: string[]; // [不限/大专+/本科+]
acceptChildren: 'any' | 'accept' | 'reject';
intentAligned: boolean; // 婚恋计划一致
}
export type PreferenceImportance = 'required' | 'preferred'; // 必须符合 / 最好符合
// ============ MatchRelation / Recommendation(规范 §22-25, §107-108) ============
export type RelationStatus =
| 'neutral'
| 'liked'
| 'passed'
| 'mutual_match'
| 'blocked'
| 'unmatched';
export interface Recommendation extends User {
recommendationReasons: string[]; // 最多 3~4 条,弱文字
recommendationLevel?: 'high' | 'medium' | 'normal';
relationStatus: RelationStatus;
likeStatus?: 'liked' | 'passed';
}
export interface LikeResult {
relationStatus: RelationStatus;
mutualMatch: boolean;
matchedConversationId?: string;
}
// ============ Conversation / Message(规范 §35-38, §61-63) ============
export interface Conversation {
conversationId: string;
targetUserId: string;
targetDisplayName: string;
targetAvatarUrl?: string;
lastMessage?: string;
lastMessageAt?: number; // 服务端时间戳
unreadCount: number;
relationStatus: RelationStatus;
canSendMessage: boolean; // 仅 mutual_match + 双方正常 + 未拉黑 + 未解除
}
export type MessageSendStatus = 'sending' | 'sent' | 'failed';
export type ChatBubbleType = 'self' | 'other' | 'system';
export interface Message {
messageId: string; // 前端去重依据(规范 §106)
conversationId: string;
senderId: string;
bubbleType: ChatBubbleType;
content: string;
sentAt: number;
sendStatus?: MessageSendStatus; // 本地消息状态
}
// ============ Activity(规范 §43-46) ============
export type ActivityStatus =
| 'draft'
| 'registration_open'
| 'registration_closed'
| 'ongoing'
| 'ended'
| 'cancelled';
export type RegistrationStatus =
| 'not_applied'
| 'pending'
| 'approved'
| 'rejected'
| 'cancelled';
export interface Activity {
activityId: string;
title: string;
coverUrl?: string;
startAt: number;
endAt: number;
location: string;
organizer: string; // 主办单位
suitableFor?: string; // 适合人群
intro: string;
schedule?: string;
notes?: string;
feeType: 'free' | 'paid'; // 前台重点突出 公益免费
status: ActivityStatus;
capacity?: number;
}
// ============ MatchmakerService(规范 §48-50) ============
export type MatchmakerServiceStatus =
| 'submitted'
| 'assigned'
| 'in_service'
| 'waiting_user'
| 'completed'
| 'cancelled';
export type MatchmakerRecommendationStatus =
| 'pending_view'
| 'viewed'
| 'liked'
| 'passed'
| 'mutual_match'
| 'expired';
export interface MatchmakerService {
serviceId: string;
userId: string;
matchmakerId?: string;
matchmakerName?: string;
matchmakerOrg?: string; // 所属公益机构
status: MatchmakerServiceStatus;
requirement: string;
lastFollowUpAt?: number;
}
export interface MatchmakerRecommendation extends User {
serviceId: string;
recommendationStatus: MatchmakerRecommendationStatus;
recommendReason: string;
}
// ============ Report(规范 §41-42) ============
export type ReportType = 'fraud' | 'harassment' | 'ad' | 'inappropriate' | 'other';
export type RiskLevel = 'normal' | 'attention' | 'high' | 'banned';
export interface Report {
reportId: string;
targetUserId: string;
type: ReportType;
reason: string;
evidencePhotoUrls?: string[];
submittedAt: number;
status: 'pending' | 'processing' | 'resolved';
}
// ============ 全局用户状态聚合(规范 §6, §141) ============
export interface UserState {
isLoggedIn: boolean;
hasPhone: boolean;
isRealNameVerified: boolean;
profileCompletionStatus: 'not_started' | 'in_progress' | 'completed';
profileReviewStatus: 'not_submitted' | 'pending' | 'approved' | 'need_edit' | 'rejected';
accountStatus: 'normal' | 'reviewing_risk' | 'limited' | 'suspended' | 'banned' | 'closed';
relationshipStatus: 'searching' | 'getting_to_know' | 'paused' | 'matched_successfully' | 'service_exited';
recommendationEnabled: boolean;
searchVisibility: boolean;
matchmakerEnabled: boolean;
activityRecommendationEnabled: boolean;
}
// ============ 隐私设置(规范 §59) ============
export interface PrivacySettings {
visibleInRecommendations: boolean;
visibleInSearch: boolean;
showOccupation: boolean;
showLifestylePhotos: boolean;
receiveActivityRecommendations: boolean;
acceptMatchmakerRecommendations: boolean;
}
+248
View File
@@ -0,0 +1,248 @@
/**
* 小程序全局类型定义
*/
// ===== 用户 & 账号 =====
export interface User {
id: string
wechatOpenid: string
phone: string | null
accountStatus: AccountStatus
relationshipStatus: RelationshipStatus
recommendationEnabled: boolean
lastLoginAt: string | null
createdAt: string
}
export type AccountStatus = 'normal' | 'reviewing_risk' | 'limited' | 'suspended' | 'banned' | 'closed'
export type RelationshipStatus = 'searching' | 'getting_to_know' | 'paused' | 'matched_successfully' | 'service_exited'
// ===== 资料 =====
export interface UserProfile {
userId: string
displayName: string | null
gender: 'male' | 'female' | 'other'
birthDate: string | null
heightCm: number | null
regionCode: string | null
regionName: string | null
maritalStatus: string | null
childrenStatus: string | null
educationCode: string | null
occupationCode: string | null
profileCompletion: number
profileStatus: ProfileStatus
createdAt: string
}
export type ProfileStatus = 'in_progress' | 'completed' | 'pending_review' | 'approved' | 'need_edit' | 'rejected'
// ===== 择偶偏好 =====
export interface UserPreference {
userId: string
minAge: number | null
maxAge: number | null
agePriority: 'required' | 'preferred'
minHeightCm: number | null
maxHeightCm: number | null
heightPriority: 'required' | 'preferred'
regionScope: string[] | null
regionPriority: 'required' | 'preferred'
maritalStatuses: string[] | null
maritalPriority: 'required' | 'preferred'
}
// ===== 关系 =====
export interface Match {
id: string
userAId: string
userBId: string
status: MatchStatus
source: string
matchedAt: string
successfulAt: string | null
}
export type MatchStatus = 'active' | 'getting_to_know' | 'unmatched' | 'successful'
export interface UserRelation {
id: string
userId: string
targetUserId: string
relationType: RelationType
createdAt: string
}
export type RelationType = 'liked' | 'passed' | 'blocked'
// ===== 推荐 =====
export interface RecommendationCandidate {
userId: string
recommendationLevel: 'high' | 'medium' | 'normal'
recommendationReasons: string[]
displayName?: string
age?: number
heightCm?: number
regionName?: string
}
// ===== 聊天 =====
export interface Conversation {
conversationId: string
matchId: string
otherUserId: string
otherDisplayName: string
otherAvatarUrl: string
lastMessageAt: string
unreadCount: number
status: ConversationStatus
canSendMessage: boolean
}
export type ConversationStatus = 'active' | 'unmatched' | 'blocked'
export interface Message {
messageId: string
conversationId: string
senderId: string
messageType: MessageType
content: string | null
fileId: string | null
status: MessageStatus
createdAt: string
mine: boolean
bubbleType: 'self' | 'other'
}
export type MessageType = 'text' | 'image' | 'system' | 'risk_notice'
export type MessageStatus = 'sent' | 'delivered' | 'read' | 'failed'
// ===== 活动 =====
export interface Activity {
id: string
title: string
description: string
status: ActivityStatus
totalLimit: number
maleLimit: number | null
femaleLimit: number | null
currentMaleCount: number
currentFemaleCount: number
registrationStartAt: string
registrationEndAt: string
activityStartAt: string
activityEndAt: string
location: string
address: string
category: string
coverImageUrl: string
}
export type ActivityStatus = 'draft' | 'registration_open' | 'registration_closed' | 'ongoing' | 'ended' | 'cancelled'
export interface ActivityRegistration {
id: string
activityId: string
userId: string
status: RegistrationStatus
registeredAt: string
checkinStatus: CheckinStatus
}
export type RegistrationStatus = 'pending' | 'approved' | 'rejected' | 'cancelled'
export type CheckinStatus = 'not_checked_in' | 'checked_in'
// ===== 举报 & 申诉 =====
export interface Report {
id: string
reporterId: string
targetUserId: string
reportType: ReportType
content: string
status: ReportStatus
createdAt: string
}
export type ReportType = 'fake_profile' | 'fake_marital_status' | 'harassment' | 'pornography' | 'advertising' | 'fraud' | 'money_inducement' | 'impersonation'
export type ReportStatus = 'pending' | 'processing' | 'resolved'
export interface Appeal {
id: string
appealId: string
reporterId: string
content: string
status: AppealStatus
createdAt: string
}
export type AppealStatus = 'pending' | 'processing' | 'resolved' | 'rejected'
// ===== 照片 =====
export interface UserPhoto {
id: string
userId: string
fileKey: string
photoType: 'avatar' | 'lifestyle'
sortOrder: number
reviewStatus: ReviewStatus
url?: string
}
export type ReviewStatus = 'pending' | 'approved' | 'need_edit' | 'rejected'
// ===== 认证 =====
export interface AuthTokens {
accessToken: string
refreshToken: string
expiresIn: number
userId: string
isNewUser: boolean
}
// ===== 成功牵手请求 =====
export interface SuccessRequest {
requestId: string
matchId: string
initiatedBy: string
status: 'pending' | 'confirmed' | 'declined'
confirmedBy: string | null
createdAt: string
resolvedAt: string | null
}
// ===== API 响应 =====
export interface ApiResponse<T = any> {
success: boolean
code: string
message: string
data: T
}
// ===== 分页 =====
export interface PageResult<T> {
items: T[]
nextCursor: string | null
hasMore: boolean
}
// ===== Like 结果 =====
export interface LikeResult {
action: 'liked'
mutual: boolean
mutualMatch?: boolean
matchCreated?: boolean
matchedConversationId?: string
}
// ===== 通知 =====
export interface Notification {
id: string
userId: string
type: string
title: string
content: string
targetType: string | null
targetId: string | null
isRead: boolean
createdAt: string
}