Selaa lähdekoodia

- 弃用 service 请求,重新设计了 request 请求方案。
- 用户信息绑定方式更改为 userInfo

icssoa 7 kuukautta sitten
vanhempi
commit
d4c7467f8b

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
.cool/eps.json


+ 0 - 341
.cool/eps.ts

@@ -1,341 +0,0 @@
-export type UserAddressEntity = {
-	/**
-	 * ID
-	 */
-	id?: number;
-
-	/**
-	 * 用户ID
-	 */
-	userId?: number;
-
-	/**
-	 * 联系人
-	 */
-	contact?: string;
-
-	/**
-	 * 手机号
-	 */
-	phone?: string;
-
-	/**
-	 * 省
-	 */
-	province?: string;
-
-	/**
-	 * 市
-	 */
-	city?: string;
-
-	/**
-	 * 区
-	 */
-	district?: string;
-
-	/**
-	 * 地址
-	 */
-	address?: string;
-
-	/**
-	 * 是否默认
-	 */
-	isDefault?: boolean;
-
-	/**
-	 * 创建时间
-	 */
-	createTime?: string;
-
-	/**
-	 * 更新时间
-	 */
-	updateTime?: string;
-
-	/**
-	 * 任意键值
-	 */
-};
-
-export type UserInfoEntity = {
-	/**
-	 * ID
-	 */
-	id?: number;
-
-	/**
-	 * 登录唯一ID
-	 */
-	unionid?: string;
-
-	/**
-	 * 头像
-	 */
-	avatarUrl?: string;
-
-	/**
-	 * 昵称
-	 */
-	nickName?: string;
-
-	/**
-	 * 手机号
-	 */
-	phone?: string;
-
-	/**
-	 * 性别
-	 */
-	gender?: number;
-
-	/**
-	 * 状态
-	 */
-	status?: number;
-
-	/**
-	 * 登录方式
-	 */
-	loginType?: number;
-
-	/**
-	 * 密码
-	 */
-	password?: string;
-
-	/**
-	 * 介绍
-	 */
-	description?: string;
-
-	/**
-	 * 生日
-	 */
-	birthday?: string;
-
-	/**
-	 * 省
-	 */
-	province?: string;
-
-	/**
-	 * 市
-	 */
-	city?: string;
-
-	/**
-	 * 区
-	 */
-	district?: string;
-
-	/**
-	 * 创建时间
-	 */
-	createTime?: string;
-
-	/**
-	 * 更新时间
-	 */
-	updateTime?: string;
-
-	/**
-	 * 任意键值
-	 */
-};
-
-export type json = any;
-
-export type PagePagination = {
-	size: number;
-	page: number;
-	total: number;
-};
-
-export interface PageResponse<T> {
-	pagination: PagePagination;
-	list: T[];
-}
-
-export type UserAddressPageResponse = {
-	pagination: PagePagination;
-	list: UserAddressEntity[];
-};
-
-export type BaseComm = {
-	/**
-	 * 文件上传模式
-	 */
-	uploadMode(data?: any): Promise<any>;
-
-	/**
-	 * 文件上传
-	 */
-	upload(data?: any): Promise<any>;
-
-	/**
-	 * 参数配置
-	 */
-	param(data?: any): Promise<any>;
-
-	/**
-	 * 实体信息与路径
-	 */
-	eps(data?: any): Promise<any>;
-};
-
-export type DictInfo = {
-	/**
-	 * 获得所有字典类型
-	 */
-	types(data?: any): Promise<any>;
-
-	/**
-	 * 获得字典数据
-	 */
-	data(data?: any): Promise<any>;
-};
-
-export type UserAddress = {
-	/**
-	 * 默认地址
-	 */
-	default(data?: any): Promise<any>;
-
-	/**
-	 * 删除
-	 */
-	delete(data?: any): Promise<any>;
-
-	/**
-	 * 修改
-	 */
-	update(data?: any): Promise<any>;
-
-	/**
-	 * 单个信息
-	 */
-	info(data?: any): Promise<UserAddressEntity>;
-
-	/**
-	 * 列表查询
-	 */
-	list(data?: any): Promise<UserAddressEntity[]>;
-
-	/**
-	 * 分页查询
-	 */
-	page(data?: any): Promise<UserAddressPageResponse>;
-
-	/**
-	 * 新增
-	 */
-	add(data?: any): Promise<any>;
-};
-
-export type UserComm = {
-	/**
-	 * 获取微信公众号配置
-	 */
-	wxMpConfig(data?: any): Promise<any>;
-};
-
-export type UserInfo = {
-	/**
-	 * 更新用户密码
-	 */
-	updatePassword(data?: any): Promise<any>;
-
-	/**
-	 * 更新用户信息
-	 */
-	updatePerson(data?: any): Promise<any>;
-
-	/**
-	 * 绑定手机号
-	 */
-	bindPhone(data?: any): Promise<any>;
-
-	/**
-	 * 绑定小程序手机号
-	 */
-	miniPhone(data?: any): Promise<any>;
-
-	/**
-	 * 获取用户信息
-	 */
-	person(data?: any): Promise<any>;
-
-	/**
-	 * 注销
-	 */
-	logoff(data?: any): Promise<any>;
-};
-
-export type UserLogin = {
-	/**
-	 * 刷新token
-	 */
-	refreshToken(data?: any): Promise<any>;
-
-	/**
-	 * 绑定小程序手机号
-	 */
-	miniPhone(data?: any): Promise<any>;
-
-	/**
-	 * 一键手机号登录
-	 */
-	uniPhone(data?: any): Promise<any>;
-
-	/**
-	 * 密码登录
-	 */
-	password(data?: any): Promise<any>;
-
-	/**
-	 * 图片验证码
-	 */
-	captcha(data?: any): Promise<any>;
-
-	/**
-	 * 验证码
-	 */
-	smsCode(data?: any): Promise<any>;
-
-	/**
-	 * 微信APP授权登录
-	 */
-	wxApp(data?: any): Promise<any>;
-
-	/**
-	 * 手机号登录
-	 */
-	phone(data?: any): Promise<any>;
-
-	/**
-	 * 小程序登录
-	 */
-	mini(data?: any): Promise<any>;
-
-	/**
-	 * 公众号登录
-	 */
-	mp(data?: any): Promise<any>;
-};
-
-export type DictKey = "brand" | "occupation";
-
-export type BaseInterface = { comm: BaseComm };
-
-export type DictInterface = { info: DictInfo };
-
-export type UserInterface = {
-	address: UserAddress;
-	comm: UserComm;
-	info: UserInfo;
-	login: UserLogin;
-};
-
-export type Service = { base: BaseInterface; dict: DictInterface; user: UserInterface };

+ 4 - 4
.vscode/template.code-snippets

@@ -12,7 +12,7 @@
 			"</template>",
 			"",
 			"<script lang=\"ts\" setup>",
-			"import { service, router } from \"@/cool\";",
+			"import { router } from \"@/cool\";",
 			"",
 			"</script>",
 			"",
@@ -35,7 +35,7 @@
 			"",
 			"<script lang=\"ts\" setup>",
 			"import { ref } from \"vue\";",
-			"import { service, router } from \"@/cool\";",
+			"import { router } from \"@/cool\";",
 			"",
 			"// 是否可见",
 			"const visible = ref(false);",
@@ -90,7 +90,7 @@
 			"",
 			"<script lang=\"ts\" setup>",
 			"import { ref } from \"vue\";",
-			"import { usePager } from \"@/cool\";",
+			"import { usePager, request } from \"@/cool\";",
 			"import { useUi } from \"@/uni_modules/cool-ui\";",
 			"",
 			"const ui = useUi();",
@@ -98,7 +98,7 @@
 			"const listViewRef = ref<ClListViewComponentPublicInstance | null>(null);",
 			"",
 			"const { refresh, listView, loading, loadMore } = usePager((params) => {",
-			"    return service.$1.page(params);",
+			"    return request({ $1 });",
 			"});",
 			"",
 			"async function onPull() {",

+ 2 - 5
App.uvue

@@ -15,13 +15,10 @@ export default {
 		console.log("App Show");
 
 		// 根据业务情况判断是否要预先调用
-		// const { dict, user } = useStore();
+		const { user } = useStore();
 
 		// 获取用户信息,未登录不执行
-		// user.get();
-
-		// 刷新字典数据
-		// dict.refresh(null);
+		user.get();
 	},
 	onHide: function () {
 		console.log("App Hide");

+ 18 - 10
components/sms-btn.uvue

@@ -59,7 +59,7 @@
 import { computed, reactive, ref } from "vue";
 import { useUi } from "@/uni_modules/cool-ui";
 import { $t, t } from "@/locale";
-import { isDark, parse, service, type Response } from "@/cool";
+import { isDark, parse, request, type Response } from "@/cool";
 
 const props = defineProps({
 	phone: String
@@ -144,18 +144,23 @@ async function getCaptcha() {
 		data: string;
 	};
 
-	await service.user.login
-		.captcha({
+	await request({
+		url: "/app/user/login/captcha",
+		method: "POST",
+		data: {
 			color: isDark.value ? "#ffffff" : "#2c3142",
 			phone: props.phone,
 			width: 200,
 			height: 70
-		})
+		}
+	})
 		.then((res) => {
-			const data = parse<Res>(res)!;
+			if (res != null) {
+				const data = parse<Res>(res)!;
 
-			captchaId.value = data.captchaId;
-			captcha.img = data.data;
+				captchaId.value = data.captchaId;
+				captcha.img = data.data;
+			}
 		})
 		.catch((err) => {
 			ui.showToast({
@@ -173,12 +178,15 @@ async function send() {
 	if (code.value != "") {
 		captcha.sending = true;
 
-		await service.user.login
-			.smsCode({
+		await request({
+			url: "/app/user/login/smsCode",
+			method: "POST",
+			data: {
 				phone: props.phone,
 				code: code.value,
 				captchaId: captchaId.value
-			})
+			}
+		})
 			.then(() => {
 				ui.showToast({
 					message: t("短信已发送,请查收")

+ 4 - 4
cool/hooks/pager.ts

@@ -16,7 +16,7 @@ type PagerResponse = {
 };
 
 // 分页回调函数类型
-type PagerCallback = (params: UTSJSONObject) => Promise<UTSJSONObject>;
+type PagerCallback = (params: UTSJSONObject) => Promise<any>;
 
 // 分页器类
 export class Pager {
@@ -75,9 +75,6 @@ export class Pager {
 					this.size = pagination.size;
 					this.total = pagination.total;
 
-					// 更新加载完成状态
-					this.finished.value = this.list.value.length >= this.total;
-
 					// 更新列表数据
 					if (data.page == 1) {
 						this.list.value = [...list];
@@ -85,6 +82,9 @@ export class Pager {
 						this.list.value.push(...list);
 					}
 
+					// 更新加载完成状态
+					this.finished.value = this.list.value.length >= this.total;
+
 					resolve(res);
 				})
 				.catch((err) => {

+ 2 - 0
cool/hooks/refs.ts

@@ -2,10 +2,12 @@ import { reactive } from "vue";
 import { isNull } from "../utils";
 
 // #ifdef APP
+// @ts-ignore
 type Instance = ComponentPublicInstance | null;
 // #endif
 
 // #ifndef APP
+// @ts-ignore
 type Instance = any;
 // #endif
 

+ 16 - 8
cool/hooks/wx.ts

@@ -1,6 +1,6 @@
 import { ref } from "vue";
 import { assign, getUrlParam, storage } from "../utils";
-import { service } from "../service";
+import { request } from "../service";
 import { t } from "@/locale";
 import { config } from "@/config";
 
@@ -62,20 +62,28 @@ export class Wx {
 	 */
 	getMpConfig() {
 		if (this.isWxBrowser()) {
-			service.user.comm
-				.wxMpConfig({
+			request({
+				url: "/app/user/common/wxMpConfig",
+				method: "POST",
+				data: {
 					url: `${location.origin}${location.pathname}`
-				})
-				.then((res) => {
+				}
+			}).then((res) => {
+				if (res != null) {
 					wx.config({
 						debug: config.wx.debug,
-						jsApiList: ["chooseWXPay"],
-						...res
+						jsApiList: res.jsApiList || ["chooseWXPay"],
+						appId: res.appId,
+						timestamp: res.timestamp,
+						nonceStr: res.nonceStr,
+						signature: res.signature,
+						openTagList: res.openTagList
 					});
 
 					// 合并配置到mpConfig
 					assign(this.mpConfig, res);
-				});
+				}
+			});
 		}
 	}
 

+ 1 - 0
cool/index.ts

@@ -42,3 +42,4 @@ export * from "./store";
 export * from "./theme";
 export * from "./upload";
 export * from "./utils";
+export * from "./types";

+ 24 - 25
cool/service/index.ts

@@ -1,4 +1,3 @@
-import type { Service } from "../types";
 import { isDev, ignoreTokens, config } from "@/config";
 import { locale, t } from "@/locale";
 import { isNull, isObject, parse, storage } from "../utils";
@@ -43,7 +42,7 @@ const isIgnoreToken = (url: string) => {
  * @param options 请求参数
  * @returns Promise<T>
  */
-export function request<T = any>(options: RequestOptions): Promise<T> {
+export function request(options: RequestOptions): Promise<any | null> {
 	let { url, method = "GET", data = {}, header = {}, timeout = 60000 } = options;
 
 	const { user } = useStore();
@@ -84,40 +83,43 @@ export function request<T = any>(options: RequestOptions): Promise<T> {
 					// 401 无权限
 					if (res.statusCode == 401) {
 						user.logout();
-						return reject({ message: t("无权限") } as Response);
+						reject({ message: t("无权限") } as Response);
 					}
 
 					// 502 服务异常
-					if (res.statusCode == 502) {
-						return reject({
+					else if (res.statusCode == 502) {
+						reject({
 							message: t("服务异常")
 						} as Response);
 					}
 
 					// 404 未找到
-					if (res.statusCode == 404) {
+					else if (res.statusCode == 404) {
 						return reject({
 							message: `[404] ${url}`
 						} as Response);
 					}
 
 					// 200 正常响应
-					if (res.statusCode == 200) {
-						if (!isObject(res.data as any)) {
-							resolve(res.data as T);
-							return;
-						}
-
-						// 解析响应数据
-						const { code, message, data } = parse<Response>(res.data ?? { code: 0 })!;
-
-						switch (code) {
-							case 1000:
-								resolve(data as T);
-								break;
-							default:
-								reject({ message, code } as Response);
-								break;
+					else if (res.statusCode == 200) {
+						if (res.data == null) {
+							resolve(null);
+						} else if (!isObject(res.data as any)) {
+							resolve(res.data);
+						} else {
+							// 解析响应数据
+							const { code, message, data } = parse<Response>(
+								res.data ?? { code: 0 }
+							)!;
+
+							switch (code) {
+								case 1000:
+									resolve(data);
+									break;
+								default:
+									reject({ message, code } as Response);
+									break;
+							}
 						}
 					} else {
 						reject({ message: t("服务异常") } as Response);
@@ -178,6 +180,3 @@ export function request<T = any>(options: RequestOptions): Promise<T> {
 		next();
 	});
 }
-
-// 服务对象(实际会在其他地方赋值)
-export const service = {} as Service;

+ 15 - 16
cool/store/dict.ts

@@ -1,6 +1,5 @@
 import { reactive } from "vue";
-import { service } from "../service";
-import type { DictKey } from "../types";
+import { request } from "../service";
 import { forInObject, isNull, parse } from "../utils";
 
 // 字典项类型定义
@@ -40,7 +39,7 @@ export class Dict {
 	 * @param key 字典key
 	 * @returns 字典项数组
 	 */
-	get(key: DictKey): DictItem[] {
+	get(key: string): DictItem[] {
 		return this.find(key)?.list ?? new Array<DictItem>();
 	}
 
@@ -50,7 +49,7 @@ export class Dict {
 	 * @param value 字典项值
 	 * @returns 字典项或null
 	 */
-	getItem(key: DictKey, value: any): DictItem | null {
+	getItem(key: string, value: any): DictItem | null {
 		const item = this.get(key).find((e) => e.value == value);
 
 		if (isNull(item)) {
@@ -66,7 +65,7 @@ export class Dict {
 	 * @param values 字典项值数组
 	 * @returns 字典项数组
 	 */
-	getItems(key: DictKey, values: any[]): DictItem[] {
+	getItems(key: string, values: any[]): DictItem[] {
 		return values.map((e) => this.getItem(key, e)).filter((e) => !isNull(e)) as DictItem[];
 	}
 
@@ -76,7 +75,7 @@ export class Dict {
 	 * @param value 字典项值
 	 * @returns 字典项label字符串
 	 */
-	getItemLabel(key: DictKey, value: any): string {
+	getItemLabel(key: string, value: any): string {
 		const item = this.getItem(key, value);
 
 		if (isNull(item) || isNull(item?.label)) {
@@ -90,8 +89,16 @@ export class Dict {
 	 * 刷新字典数据
 	 * @param types 可选,指定需要刷新的字典key数组
 	 */
-	async refresh(types?: DictKey[] | null): Promise<void> {
-		const res = await service.dict.info.data({ types });
+	async refresh(types?: string[] | null): Promise<void> {
+		const res = await request({
+			url: "/app/dict/info/data",
+			method: "POST",
+			data: { types }
+		});
+
+		if (res == null) {
+			return;
+		}
 
 		// 遍历返回的字典数据
 		forInObject(res, (arr, key) => {
@@ -127,11 +134,3 @@ export class Dict {
 
 // 单例字典对象
 export const dict = new Dict();
-
-/**
- * 获取字典实例
- * @returns Dict实例
- */
-export function useDict() {
-	return dict;
-}

+ 47 - 59
cool/store/user.ts

@@ -1,28 +1,21 @@
-import { reactive } from "vue";
-import type { UserInfoEntity } from "../types";
-import { forInObject, isNull, parse, storage } from "../utils";
-import { service } from "../service";
+import { computed, ref } from "vue";
+import { forInObject, isNull, isObject, parse, storage } from "../utils";
 import { router } from "../router";
+import { request } from "../service";
+import type { UserInfo } from "@/types";
 
-/**
- * Token类型定义
- * @property token 访问token
- * @property expire token过期时间(秒)
- * @property refreshToken 刷新token
- * @property refreshExpire 刷新token过期时间(秒)
- */
 export type Token = {
-	token: string;
-	expire: number;
-	refreshToken: string;
-	refreshExpire: number;
+	token: string; // 访问token
+	expire: number; // token过期时间(秒)
+	refreshToken: string; // 刷新token
+	refreshExpire: number; // 刷新token过期时间(秒)
 };
 
 export class User {
 	/**
-	 * 用户信息,响应式对象,属性结构见UserInfoEntity
+	 * 用户信息,响应式对象
 	 */
-	info = reactive<UserInfoEntity>({});
+	info = ref<UserInfo | null>(null);
 
 	/**
 	 * 当前token,字符串或null
@@ -40,7 +33,9 @@ export class User {
 		this.token = token == "" ? null : token;
 
 		// 初始化用户信息
-		this.set(userInfo!);
+		if (userInfo != null && isObject(userInfo)) {
+			this.set(userInfo);
+		}
 	}
 
 	/**
@@ -49,10 +44,11 @@ export class User {
 	 */
 	async get() {
 		if (this.token != null) {
-			await service.user.info
-				.person({})
+			await request({
+				url: "/app/user/info/person"
+			})
 				.then((res) => {
-					if (!isNull(res)) {
+					if (res != null) {
 						this.set(res);
 					}
 				})
@@ -71,13 +67,8 @@ export class User {
 			return;
 		}
 
-		// 先清空原有信息
-		this.remove();
-
-		// 逐项赋值到响应式info对象
-		forInObject(data, (value, key) => {
-			this.info[key] = value;
-		});
+		// 设置
+		this.info.value = parse<UserInfo>(data)!;
 
 		// 持久化到本地存储
 		storage.set("userInfo", data, 0);
@@ -87,43 +78,38 @@ export class User {
 	 * 更新用户信息(本地与服务端同步)
 	 * @param data 新的用户信息
 	 */
-	async update(data: UserInfoEntity) {
-		if (isNull(data) || this.isNull()) {
+	async update(data: any) {
+		if (isNull(data) || isNull(this.info.value)) {
 			return;
 		}
 
-		const params = { ...data };
-
 		// 本地同步更新
-		forInObject(params as any, (value, key) => {
-			this.info[key] = value;
+		forInObject(data, (value, key) => {
+			this.info.value![key] = value;
 		});
 
 		// 同步到服务端
-		await service.user.info.updatePerson(params);
+		await request({
+			url: "/app/user/info/updatePerson",
+			method: "POST",
+			data
+		});
 	}
 
 	/**
-	 * 移除用户信息(仅清空本地响应式对象,不清除本地存储)
+	 * 移除用户信息
 	 */
 	remove() {
-		forInObject({ ...this.info } as any, (_, key) => {
-			// #ifdef APP
-			this.info[key] = null;
-			// #endif
-
-			// #ifndef APP
-			delete this.info[key];
-			// #endif
-		});
+		this.info.value = null;
+		storage.remove("userInfo");
 	}
 
 	/**
-	 * 判断用户信息是否为空(以id字段为准)
+	 * 判断用户信息是否为空
 	 * @returns boolean
 	 */
 	isNull() {
-		return isNull(this.info["id"]);
+		return this.info.value == null;
 	}
 
 	/**
@@ -164,16 +150,21 @@ export class User {
 	 */
 	refreshToken(): Promise<string> {
 		return new Promise((resolve, reject) => {
-			service.user.login
-				.refreshToken({
+			request({
+				url: "/app/user/login/refreshToken",
+				method: "POST",
+				data: {
 					refreshToken: storage.get("refreshToken")
-				})
+				}
+			})
 				.then((res) => {
-					const token = parse<Token>(res);
+					if (res != null) {
+						const token = parse<Token>(res);
 
-					if (token != null) {
-						this.setToken(token);
-						resolve(token.token);
+						if (token != null) {
+							this.setToken(token);
+							resolve(token.token);
+						}
 					}
 				})
 				.catch((err) => {
@@ -189,9 +180,6 @@ export class User {
 export const user = new User();
 
 /**
- * 获取用户单例实例(组合式API用法)
- * @returns User
+ * 用户信息,响应式对象
  */
-export function useUser() {
-	return user;
-}
+export const userInfo = computed(() => user.info.value);

+ 0 - 2
cool/types/index.ts

@@ -1,5 +1,3 @@
-export * from "@/.cool/eps";
-
 export type PushAnimationType =
 	| "auto"
 	| "none"

+ 12 - 6
cool/upload/index.ts

@@ -1,5 +1,5 @@
 import { config } from "@/config";
-import { service } from "../service";
+import { request } from "../service";
 import { basename, extname, filename, parse, parseObject, pathJoin, uuid } from "../utils";
 import { useStore } from "../store";
 
@@ -57,8 +57,11 @@ export type LocalUploadResponse = {
 
 // 获取上传模式(本地/云端及云类型)
 async function getUploadMode(): Promise<UploadMode> {
-	const res = await service.base.comm.uploadMode({});
-	return parse<UploadMode>(res)!;
+	const res = await request({
+		url: "/app/base/comm/uploadMode"
+	});
+
+	return parse<UploadMode>(res!)!;
 }
 
 /**
@@ -199,10 +202,13 @@ export async function uploadFile(
 			}
 
 			// 获取云上传参数
-			service.base.comm
-				.upload(data)
+			request({
+				url: "/app/base/comm/upload",
+				method: "POST",
+				data
+			})
 				.then((res) => {
-					const d = parse<CloudUploadResponse>(res)!;
+					const d = parse<CloudUploadResponse>(res!)!;
 
 					switch (type) {
 						// 腾讯云COS

+ 2 - 2
package.json

@@ -1,6 +1,6 @@
 {
 	"name": "cool-unix",
-	"version": "8.0.17",
+	"version": "8.0.18",
 	"license": "MIT",
 	"scripts": {
 		"build-ui": "node ./uni_modules/cool-ui/scripts/generate-types.js",
@@ -15,7 +15,7 @@
 		"@babel/parser": "^7.27.5",
 		"@babel/types": "^7.27.6",
 		"@cool-vue/ai": "^1.1.6",
-		"@cool-vue/vite-plugin": "^8.2.8",
+		"@cool-vue/vite-plugin": "^8.2.9",
 		"@dcloudio/types": "^3.4.16",
 		"@types/node": "^24.0.15",
 		"@vue/compiler-sfc": "^3.5.16",

+ 2 - 2
pages/demo/data/list-view.uvue

@@ -42,11 +42,11 @@ const data = ref<ClListViewItem[]>([]);
 onReady(() => {
 	ui.showLoading();
 
-	request<UTSJSONObject[]>({
+	request({
 		url: "https://unix.cool-js.com/data/pca_flat.json"
 	})
 		.then((res) => {
-			data.value = useListView(res);
+			data.value = useListView(res as UTSJSONObject[]);
 		})
 		.catch((err) => {
 			console.error(err);

+ 4 - 4
pages/index/my.uvue

@@ -22,7 +22,7 @@
 			<view class="flex flex-col justify-center items-center pt-6 pb-3">
 				<view class="relative overflow-visible" @tap="toEdit">
 					<cl-avatar
-						:src="user.info.avatarUrl"
+						:src="userInfo?.avatarUrl"
 						:size="150"
 						:pt="{ className: '!rounded-3xl', icon: { size: 60 } }"
 					>
@@ -38,9 +38,9 @@
 
 				<view class="flex-1 flex flex-col justify-center items-center w-full" @tap="toEdit">
 					<cl-text :pt="{ className: '!text-xl mt-5 mb-1 font-bold' }">{{
-						user.info.nickName ?? t("未登录")
+						userInfo?.nickName ?? t("未登录")
 					}}</cl-text>
-					<cl-text color="info" v-if="!user.isNull()">{{ user.info.phone }}</cl-text>
+					<cl-text color="info" v-if="!user.isNull()">{{ userInfo?.phone }}</cl-text>
 				</view>
 			</view>
 
@@ -242,7 +242,7 @@
 </template>
 
 <script setup lang="ts">
-import { router, useStore } from "@/cool";
+import { router, userInfo, useStore } from "@/cool";
 import { t } from "@/locale";
 import { useUi } from "@/uni_modules/cool-ui";
 import Tabbar from "@/components/tabbar.uvue";

+ 7 - 4
pages/user/components/login/phone.uvue

@@ -73,7 +73,7 @@ import { t } from "@/locale";
 import { computed, inject, ref, type PropType } from "vue";
 import type { LoginForm } from "../../types";
 import SmsBtn from "@/components/sms-btn.uvue";
-import { isDark, parseClass, service, useRefs, type Response } from "@/cool";
+import { isDark, parseClass, request, useRefs, type Response } from "@/cool";
 import { useUi } from "@/uni_modules/cool-ui";
 
 const props = defineProps({
@@ -112,11 +112,14 @@ async function toLogin() {
 
 	loading.value = true;
 
-	await service.user.login
-		.phone({
+	await request({
+		url: "/app/user/login/phone",
+		method: "POST",
+		data: {
 			phone,
 			smsCode
-		})
+		}
+	})
 		.then((res) => {
 			emit("success", res);
 		})

+ 20 - 6
pages/user/components/login/wx.uvue

@@ -74,7 +74,17 @@
 </template>
 
 <script setup lang="ts">
-import { parse, router, service, upload, useStore, useWx, type Response, type Token } from "@/cool";
+import {
+	parse,
+	request,
+	router,
+	upload,
+	userInfo,
+	useStore,
+	useWx,
+	type Response,
+	type Token
+} from "@/cool";
 import { t } from "@/locale";
 import { useUi } from "@/uni_modules/cool-ui";
 import { reactive, ref } from "vue";
@@ -176,8 +186,11 @@ async function miniLogin() {
 	ui.showLoading(t("登录中"));
 
 	await wx.miniLogin().then(async (data) => {
-		await service.user.login
-			.mini(data)
+		await request({
+			url: "/app/user/login/mini",
+			method: "POST",
+			data
+		})
 			.then(async (res) => {
 				// 设置token
 				user.setToken(parse<Token>(res)!);
@@ -186,7 +199,7 @@ async function miniLogin() {
 				await user.get();
 
 				// 是否首次注册,根据业务情况调整判断逻辑
-				if (user.info.nickName == "微信用户") {
+				if (userInfo.value?.nickName == "微信用户") {
 					// 打开编辑弹窗
 					editOpen();
 				} else {
@@ -202,12 +215,13 @@ async function miniLogin() {
 	});
 
 	ui.hideLoading();
-
 	// #endif
 }
 
 // 微信APP登录
-function appLogin() {}
+function appLogin() {
+	// 开发中
+}
 
 // 微信登录
 async function login() {

+ 2 - 2
pages/user/edit-description.uvue

@@ -21,7 +21,7 @@
 </template>
 
 <script setup lang="ts">
-import { router, useStore } from "@/cool";
+import { router, userInfo, useStore } from "@/cool";
 import { t } from "@/locale";
 import { useUi } from "@/uni_modules/cool-ui";
 import { ref } from "vue";
@@ -47,6 +47,6 @@ async function confirm() {
 }
 
 onReady(() => {
-	content.value = user.info.description ?? "";
+	content.value = userInfo.value?.description ?? "";
 });
 </script>

+ 2 - 2
pages/user/edit-name.uvue

@@ -35,7 +35,7 @@
 </template>
 
 <script setup lang="ts">
-import { router, useStore } from "@/cool";
+import { router, userInfo, useStore } from "@/cool";
 import { t } from "@/locale";
 import { useUi } from "@/uni_modules/cool-ui";
 import { ref } from "vue";
@@ -75,6 +75,6 @@ async function confirm() {
 
 // 页面加载时,设置输入框内容
 onReady(() => {
-	content.value = user.info.nickName ?? "";
+	content.value = userInfo.value?.nickName ?? "";
 });
 </script>

+ 12 - 12
pages/user/edit.uvue

@@ -12,7 +12,7 @@
 					<!-- #endif -->
 
 					<cl-avatar
-						:src="user.info.avatarUrl"
+						:src="userInfo?.avatarUrl"
 						:size="150"
 						:pt="{ className: '!rounded-3xl', icon: { size: 60 } }"
 						@tap="uploadAvatar"
@@ -35,10 +35,10 @@
 					justify="start"
 					@tap="router.to('/pages/user/edit-name')"
 				>
-					<cl-text>{{ user.info.nickName }}</cl-text>
+					<cl-text>{{ userInfo?.nickName }}</cl-text>
 				</cl-list-item>
 				<cl-list-item label="手机号" hoverable justify="start">
-					<cl-text>{{ user.info.phone }}</cl-text>
+					<cl-text>{{ userInfo?.phone }}</cl-text>
 				</cl-list-item>
 			</cl-list>
 
@@ -50,10 +50,10 @@
 					justify="start"
 					@tap="router.to('/pages/user/edit-description')"
 				>
-					<cl-text color="info" v-if="user.info.description == null">{{
+					<cl-text color="info" v-if="userInfo?.description == null">{{
 						t("介绍一下自己")
 					}}</cl-text>
-					<cl-text ellipsis v-else>{{ user.info.description }}</cl-text>
+					<cl-text ellipsis v-else>{{ userInfo?.description }}</cl-text>
 				</cl-list-item>
 			</cl-list>
 
@@ -76,8 +76,8 @@
 					justify="start"
 					@tap="open('birthday')"
 				>
-					<cl-text>{{ user.info.birthday }}</cl-text>
-					<cl-text color="info" v-if="user.info.birthday == null">{{
+					<cl-text>{{ userInfo?.birthday }}</cl-text>
+					<cl-text color="info" v-if="userInfo?.birthday == null">{{
 						t("选择生日")
 					}}</cl-text>
 				</cl-list-item>
@@ -98,7 +98,7 @@
 
 			<cl-select
 				:title="t('选择性别')"
-				:model-value="user.info.gender"
+				:model-value="userInfo?.gender"
 				:ref="refs.set('gender')"
 				:options="genderOptions"
 				:show-trigger="false"
@@ -107,7 +107,7 @@
 
 			<cl-select-date
 				:title="t('选择生日')"
-				:model-value="user.info.birthday"
+				:model-value="userInfo?.birthday"
 				:ref="refs.set('birthday')"
 				type="date"
 				:end="today"
@@ -127,7 +127,7 @@
 </template>
 
 <script setup lang="ts">
-import { dayUts, router, upload, useRefs, useStore, type Response } from "@/cool";
+import { dayUts, router, upload, useRefs, useStore, type Response, userInfo } from "@/cool";
 import { t } from "@/locale";
 import { useCascader, useUi, type ClSelectOption } from "@/uni_modules/cool-ui";
 import { computed, ref } from "vue";
@@ -158,7 +158,7 @@ const genderOptions = ref<ClSelectOption[]>([
 
 // 性别文本
 const genderText = computed(() => {
-	return [t("保密"), t("男"), t("女")][user.info.gender!];
+	return [t("保密"), t("男"), t("女")][userInfo.value?.gender!];
 });
 
 // 性别改变
@@ -188,7 +188,7 @@ const regionOptions = useCascader(pca);
 
 // 地区文本
 const regionText = computed(() => {
-	return [user.info.province, user.info.city, user.info.district]
+	return [userInfo.value?.province, userInfo.value?.city, userInfo.value?.district]
 		.filter((e) => e != null)
 		.join(" - ");
 });

+ 5 - 5
pnpm-lock.yaml

@@ -28,8 +28,8 @@ importers:
         specifier: ^1.1.6
         version: 1.1.6
       '@cool-vue/vite-plugin':
-        specifier: ^8.2.8
-        version: 8.2.8
+        specifier: ^8.2.9
+        version: 8.2.9
       '@dcloudio/types':
         specifier: ^3.4.16
         version: 3.4.16
@@ -88,8 +88,8 @@ packages:
     resolution: {integrity: sha512-+5vEnjuMHhmOlAlozasGMaSkx2TZ5p45nOuLzx88ZVyqO0dMYXUJ5I8eVR5XV7huYCLCw7dYwfVg5B03ngsYwg==}
     hasBin: true
 
-  '@cool-vue/vite-plugin@8.2.8':
-    resolution: {integrity: sha512-MoiNQt/9Dr8e+P39LIaCEz2Y0OvdDauK9mGseyUCEmyKFRuF5KEmTlDzr2ChW/Z7IQMvXZnj47wiAmyuEzxwLA==}
+  '@cool-vue/vite-plugin@8.2.9':
+    resolution: {integrity: sha512-Dl/yW/JWWJNmChwMj5CFUV4qZRD5axXYZ1dqpuyBWDD1kWsvNY8PaL7VGDos3/8SpUsDYPXCv+yK/Fd32A6o9w==}
 
   '@dcloudio/types@3.4.16':
     resolution: {integrity: sha512-gJIr1OWtePTDDdjtp8Kh72S/ZGLunoSfHiUvRtXhBmAFNkDWuAKFO90hv62k3GYN/st04xUBQNtBfvhu/YHjww==}
@@ -1376,7 +1376,7 @@ snapshots:
     transitivePeerDependencies:
       - debug
 
-  '@cool-vue/vite-plugin@8.2.8':
+  '@cool-vue/vite-plugin@8.2.9':
     dependencies:
       '@vue/compiler-sfc': 3.5.17
       axios: 1.10.0

+ 17 - 0
types/index.ts

@@ -0,0 +1,17 @@
+export type UserInfo = {
+	unionid: string; // 用户唯一id
+	id: number; // 用户id
+	nickName: string; // 昵称
+	avatarUrl?: string; // 头像
+	phone: string; // 手机号
+	gender: number; // 性别
+	status: number; // 状态
+	description?: string; // 描述
+	loginType: number; // 登录类型
+	province?: string; // 省份
+	city?: string; // 城市
+	district?: string; // 区县
+	birthday?: string; // 生日
+	createTime: string; // 创建时间
+	updateTime: string; // 更新时间
+};

+ 1 - 5
vite.config.ts

@@ -19,11 +19,7 @@ export default defineConfig({
 			proxy,
 			tailwind: {
 				enable: true
-			},
-			eps: {
-				dist: ".cool"
-			},
-			clean: true // 是否纯净版
+			}
 		})
 	],
 

Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä