408249787 2 周之前
父节点
当前提交
07060759ed

+ 222 - 0
.cool/service/index copy.ts

@@ -0,0 +1,222 @@
+import { isDev, ignoreTokens, config } from "@/config";
+import { locale, t } from "../locale";
+import { isNull, isObject, parse, storage } from "../utils";
+import { useStore } from "../store";
+
+// 请求参数类型定义
+export type RequestOptions = {
+	url: string; // 请求地址
+	method?: RequestMethod; // 请求方法
+	data?: any; // 请求体数据
+	params?: any; // URL参数
+	header?: any; // 请求头
+	timeout?: number; // 超时时间
+	withCredentials?: boolean; // 是否携带凭证
+	firstIpv4?: boolean; // 是否优先使用IPv4
+	enableChunked?: boolean; // 是否启用分块传输
+};
+
+// 响应数据类型定义
+export type Response = {
+	code: number;
+	message: string;
+	data?: any;
+};
+
+// 请求队列(用于等待token刷新后继续请求)
+let requests: ((token: string) => void)[] = [];
+
+// 标记token是否正在刷新
+let isRefreshing = false;
+
+// 判断当前url是否忽略token校验
+const isIgnoreToken = (url: string) => {
+	return ignoreTokens.some((e) => {
+		const pattern = e.replace(/\*/g, ".*");
+		return new RegExp(pattern).test(url);
+	});
+};
+
+/**
+ * 通用请求方法
+ * @param options 请求参数
+ * @returns Promise<T>
+ */
+export function request<R = any>(options: RequestOptions): Promise<Response> {
+	let { url, method = "GET", data = {}, header = {}, timeout = 60000 } = options;
+
+	const { user } = useStore();
+
+	// 开发环境下打印请求信息
+	if (isDev) {
+		console.log(`[${method}] ${url}`);
+	}
+
+	// 拼接基础url
+	if (!url.startsWith("http")) {
+		url = config.baseUrl + url;
+	}
+
+	// 获取当前token
+	let Authorization: string | null = user.token;
+
+	console.log(Authorization);
+
+
+	return new Promise((resolve, reject) => {
+		// 发起请求的实际函数
+		const next = () => {
+			console.log(222);
+
+			uni.request({
+				url,
+				method,
+				data,
+				header: {
+					Authorization,
+					language: locale.value,
+					...(header as UTSJSONObject)
+				},
+				timeout,
+
+				success(res) {
+					console.log(res);
+
+					// 401 无权限
+					if (res.statusCode == 401) {
+						user.logout();
+						reject({ message: t("无权限") } as Response);
+					}
+
+					// 502 服务异常
+					else if (res.statusCode == 502) {
+						reject({
+							message: t("服务异常")
+						} as Response);
+					}
+
+					// 404 未找到
+					else if (res.statusCode == 404) {
+						return reject({
+							message: `[404] ${url}`
+						} as Response);
+					}
+
+					// 200 正常响应
+					else if (res.statusCode == 0 || 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);
+					}
+				},
+
+				// 网络请求失败
+				fail(err) {
+					reject({ message: err.errMsg } as Response);
+				}
+			});
+		};
+		console.log(2222);
+		next();
+		// 非刷新token接口才进行token有效性校验
+		if (!options.url.includes("/refreshToken")) {
+			if (!isNull(Authorization)) {
+				// 判断token是否过期
+				// if (storage.isExpired("token")) {
+				// 	// 判断refreshToken是否过期
+				// 	if (storage.isExpired("refreshToken")) {
+				// 		// 刷新token也过期,直接退出登录
+				// 		user.logout();
+				// 		return;
+				// 	}
+
+				// 	// 如果当前没有在刷新token,则发起刷新
+				// 	if (!isRefreshing) {
+				// 		isRefreshing = true;
+				// 		user.refreshToken()
+				// 			.then((token) => {
+				// 				// 刷新成功后,执行队列中的请求
+				// 				requests.forEach((cb) => cb(token));
+				// 				requests = [];
+				// 				isRefreshing = false;
+				// 			})
+				// 			.catch((err) => {
+				// 				reject(err);
+				// 				user.logout();
+				// 			});
+				// 	}
+
+				// 	// 将当前请求加入队列,等待token刷新后再执行
+				// 	new Promise((resolve) => {
+				// 		requests.push((token: string) => {
+				// 			// 重新设置token
+				// 			Authorization = token;
+				// 			next();
+				// 			resolve(true);
+				// 		});
+				// 	});
+				// 	// 此处return,等待token刷新
+				// 	return;
+				// }
+
+			}
+		}
+
+		// token有效,直接发起请求
+		// next();
+	});
+}
+export function useGet<R = any>(url: string, params?: any, config?: RequestOptions): Promise<Response> {
+	const options: RequestOptions = {
+		url,
+		params,
+		method: 'GET',
+		...config,
+	}
+	return request<R>(options)
+}
+export function usePost<R = any>(url: string, data?: any, config?: RequestOptions): Promise<Response> {
+	const options: RequestOptions = {
+		url,
+		data,
+		method: 'POST',
+		...config,
+	}
+	return request<R>(options)
+}
+export function usePut<R = any>(url: string, data?: any, config?: RequestOptions): Promise<Response> {
+	const options: RequestOptions = {
+		url,
+		data,
+		method: 'PUT',
+		...config,
+	}
+	return request<R>(options)
+}
+export function useDelete<R = any>(url: string, data?: any, config?: RequestOptions): Promise<Response> {
+	const options: RequestOptions = {
+		url,
+		data,
+		method: 'DELETE',
+		...config,
+	}
+	return request<R>(options)
+}

+ 24 - 72
.cool/service/index.ts

@@ -17,10 +17,10 @@ export type RequestOptions = {
 };
 
 // 响应数据类型定义
-export type Response<R = any> = {
-	code: number;
-	message: string;
-	data?: R;
+export type Response = {
+	code?: number;
+	message?: string;
+	data?: any;
 };
 
 // 请求队列(用于等待token刷新后继续请求)
@@ -42,32 +42,32 @@ const isIgnoreToken = (url: string) => {
  * @param options 请求参数
  * @returns Promise<T>
  */
-export function request<R = any>(options: RequestOptions): Promise<Response<R>> {
+export function request(options: RequestOptions): Promise<any | null> {
 	let { url, method = "GET", data = {}, header = {}, timeout = 60000 } = options;
 
 	const { user } = useStore();
 
-	// 开发环境下打印请求信息
-	if (isDev) {
-		console.log(`[${method}] ${url}`);
-	}
+	
 
 	// 拼接基础url
 	if (!url.startsWith("http")) {
 		url = config.baseUrl + url;
 	}
-
+// 开发环境下打印请求信息
+	if (isDev) {
+		console.log(`[${method}] ${url}`);
+	}
 	// 获取当前token
 	let Authorization: string | null = user.token;
 
-	console.log(Authorization);
-
+	// 如果是忽略token的接口,则不携带token
+	if (isIgnoreToken(url)) {
+		Authorization = null;
+	}
 
 	return new Promise((resolve, reject) => {
 		// 发起请求的实际函数
 		const next = () => {
-			console.log(222);
-
 			uni.request({
 				url,
 				method,
@@ -80,8 +80,6 @@ export function request<R = any>(options: RequestOptions): Promise<Response<R>>
 				timeout,
 
 				success(res) {
-					console.log(res);
-
 					// 401 无权限
 					if (res.statusCode == 401) {
 						user.logout();
@@ -103,7 +101,7 @@ export function request<R = any>(options: RequestOptions): Promise<Response<R>>
 					}
 
 					// 200 正常响应
-					else if (res.statusCode == 0 || res.statusCode == 200) {
+					else if (res.statusCode == 200) {
 						if (res.data == null) {
 							resolve(null);
 						} else if (!isObject(res.data as any)) {
@@ -134,89 +132,43 @@ export function request<R = any>(options: RequestOptions): Promise<Response<R>>
 				}
 			});
 		};
-		console.log(2222);
+
 		next();
-		// 非刷新token接口才进行token有效性校验
-		if (!options.url.includes("/refreshToken")) {
-			if (!isNull(Authorization)) {
-				// 判断token是否过期
-				// if (storage.isExpired("token")) {
-				// 	// 判断refreshToken是否过期
-				// 	if (storage.isExpired("refreshToken")) {
-				// 		// 刷新token也过期,直接退出登录
-				// 		user.logout();
-				// 		return;
-				// 	}
-
-				// 	// 如果当前没有在刷新token,则发起刷新
-				// 	if (!isRefreshing) {
-				// 		isRefreshing = true;
-				// 		user.refreshToken()
-				// 			.then((token) => {
-				// 				// 刷新成功后,执行队列中的请求
-				// 				requests.forEach((cb) => cb(token));
-				// 				requests = [];
-				// 				isRefreshing = false;
-				// 			})
-				// 			.catch((err) => {
-				// 				reject(err);
-				// 				user.logout();
-				// 			});
-				// 	}
-
-				// 	// 将当前请求加入队列,等待token刷新后再执行
-				// 	new Promise((resolve) => {
-				// 		requests.push((token: string) => {
-				// 			// 重新设置token
-				// 			Authorization = token;
-				// 			next();
-				// 			resolve(true);
-				// 		});
-				// 	});
-				// 	// 此处return,等待token刷新
-				// 	return;
-				// }
-
-			}
-		}
-
-		// token有效,直接发起请求
-		// next();
 	});
 }
-export function useGet<R = any, T = any>(url: string, params?: T, config?: RequestOptions): Promise<Response<R>> {
+export function useGet(url: string, params?: any, config?: RequestOptions): Promise<Response> {
 	const options: RequestOptions = {
 		url,
 		params,
 		method: 'GET',
 		...config,
 	}
-	return request<R>(options)
+	return request(options)
 }
-export function usePost<R = any, T = any>(url: string, data?: T, config?: RequestOptions): Promise<Response<R>> {
+export function usePost(url: string, data?: any, config?: RequestOptions): Promise<Response> {
 	const options: RequestOptions = {
 		url,
 		data,
 		method: 'POST',
 		...config,
 	}
-	return request<R>(options)
+	return request(options)
 }
-export function usePut<R = any, T = any>(url: string, data?: T, config?: RequestOptions): Promise<Response<R>> {
+export function usePut(url: string, data?: any, config?: RequestOptions): Promise<Response> {
 	const options: RequestOptions = {
 		url,
 		data,
 		method: 'PUT',
 		...config,
 	}
-	return request<R>(options)
+	return request(options)
 }
-export function useDelete<R = any, T = any>(url: string, data?: T, config?: RequestOptions): Promise<Response<R>> {
+export function useDelete(url: string, data?: any, config?: RequestOptions): Promise<Response> {
 	const options: RequestOptions = {
 		url,
 		data,
 		method: 'DELETE',
 		...config,
 	}
-	return request<R>(options)
+	return request(options)
 }

+ 8 - 5
.cool/utils/stringify.ts

@@ -1,9 +1,12 @@
-export function stringify(obj: Record<string, any>) {
-  if (!obj) return '';
-  else if (typeof obj === 'object') {
-    return Object.keys(obj)
-      .map((key) => `${key}=${obj[key]}`)
+import { isArray, isObject, keys, get } from './comm';
+
+export function stringify(obj: any) {
+  if (isObject(obj)) {
+    return keys(obj)
+      .map((key) => `${key}=${get(obj, key)}`)
       .join('&');
+  } else if (isArray(obj)) {
+    return JSON.stringify(obj);
   }
   return '';
 }

+ 1 - 1
.hbuilderx/launch.json

@@ -8,7 +8,7 @@
         {
             "customPlaygroundType" : "device",
             "localRepoPath" : "",
-            "packageName" : "com.iflytek.inputmethod.miui",
+            "packageName" : "com.example.test1",
             "playground" : "standard",
             "type" : "uni-app:app-android"
         },

+ 3 - 0
.vscode/settings.json

@@ -22,5 +22,8 @@
 	"scss.lint.unknownAtRules": "ignore",
 	"[xml]": {
 		"editor.defaultFormatter": "redhat.vscode-xml"
+	},
+	"[vue]": {
+		"editor.defaultFormatter": "esbenp.prettier-vscode"
 	}
 }

+ 2 - 8
config/proxy.ts

@@ -2,16 +2,10 @@ export const proxy = {
 	// 开发环境配置
 	dev: {
 		// 本地地址
-		target: "http://127.0.0.1:5001",
+		target: "http://192.168.1.7:5001",
 		changeOrigin: true,
 		rewrite: (path: string) => path.replace("/dev", "")
 	},
-	api: {
-		// 测试
-		target: "http://127.0.0.1:5001",
-		changeOrigin: true,
-		rewrite: (path: string) => path.replace("/api", "")
-	},
 	// 生产环境配置
 	prod: {
 		// 官方测试地址
@@ -21,4 +15,4 @@ export const proxy = {
 	}
 };
 
-export const value = "api";
+export const value = "dev";

+ 12 - 13
pages.json

@@ -5,20 +5,13 @@
 			"style": {
 				"navigationStyle": "custom"
 			}
-		}
-	],
-	"subPackages": [
+		},
 		{
-			"root": "pages/user",
-			"pages": [
-				{
-					"path": "login",
-					"style": {
-						"navigationStyle": "custom",
-						"disableScroll": true
-					}
-				}
-			]
+			"path": "pages/user/login",
+			"style": {
+				"navigationStyle": "custom",
+				"disableScroll": true
+			}
 		}
 	],
 	"globalStyle": {
@@ -42,6 +35,12 @@
 				"iconPath": "/static/icon/tabbar/home.png",
 				"selectedIconPath": "/static/icon/tabbar/home2.png",
 				"text": "首页"
+			},
+			{
+				"pagePath": "pages/user/login",
+				"iconPath": "/static/icon/tabbar/home.png",
+				"selectedIconPath": "/static/icon/tabbar/home2.png",
+				"text": "login"
 			}
 		]
 	},

+ 105 - 0
pages/user/components/login/phone copy.uvue

@@ -0,0 +1,105 @@
+<template>
+	<view class="flex flex-col mb-5">
+		<cl-text :size="18" :pt="{ className: 'font-bold' }">{{ t("您好,欢迎登录!") }}</cl-text>
+		<cl-text :pt="{ className: 'mt-2' }" color="info">{{
+			t("首次登录将自动为您完成注册")
+		}}</cl-text>
+	</view>
+
+	<view class="flex flex-col">
+		<view class="mb-3 flex flex-row">
+			<cl-input v-model="loginModel.username" prefix-icon="device-fill" :placeholder="t('请输入手机号')" :border="false" :pt="{
+				className: parseClass([
+					'!h-[45px] flex-1 !rounded-xl !px-4',
+					[isDark, '!bg-surface-70', '!bg-white']
+				]),
+				prefixIcon: {
+					className: 'mr-1'
+				}
+			}"></cl-input>
+		</view>
+
+		<view class="relative flex flex-row items-center mb-5">
+			<cl-input v-model="loginModel.password" prefix-icon="device-fill" :placeholder="t('请输入手机号')" :border="false" :pt="{
+				className: parseClass([
+					'!h-[45px] flex-1 !rounded-xl !px-4',
+					[isDark, '!bg-surface-70', '!bg-white']
+				]),
+				prefixIcon: {
+					className: 'mr-1'
+				}
+			}"></cl-input>
+		</view>
+
+		<cl-button @tap="toLogin">
+		登录
+		</cl-button>
+	</view>
+</template>
+
+<script setup lang="ts">
+import { computed, inject,reactive, ref, type PropType } from "vue";
+import type { LoginForm } from "../../types";
+import SmsBtn from "../sms-btn.uvue";
+import { isDark, parseClass, request, useRefs, type Response, t, stringify } from "@/.cool";
+import { useUi } from "@/uni_modules/cool-ui";
+// import { loginApi } from "@/api/user";
+
+const props = defineProps({
+	form: {
+		type: Object as PropType<LoginForm>,
+		default: () => ({})
+	}
+});
+const loginModel = reactive({
+	username: 'superadmin',
+	password: '123456',
+	randomStr: 0,
+	grant_type: 'password',
+	scope: 'server',
+	loginType: 88
+})
+const emit = defineEmits(["success"]);
+
+const ui = useUi();
+const refs = useRefs();
+
+// 是否同意
+const isAgree = inject("isAgree") as () => boolean;
+
+// 是否显示验证码
+const showCode = ref(false);
+
+// 是否加载中
+const loading = ref(false);
+
+// 是否禁用
+const disabled = computed(() => {
+	return props.form.phone == "" || props.form.smsCode == "";
+});
+
+// 登录
+async function toLogin() {
+	if (!isAgree()) {
+		return;
+	}
+
+	// loading.value = true;
+
+	await request({
+		url: `/oauth/token?${stringify(loginModel)}`,
+		method: 'POST',
+		data: loginModel
+	})
+		.then((res) => {
+			emit("success", res);
+		})
+		.catch((err) => {
+			ui.showToast({
+				message: (err as Response).message!
+			});
+		});
+
+	loading.value = false;
+}
+</script>

+ 52 - 31
pages/user/components/login/phone.uvue

@@ -8,44 +8,67 @@
 
 	<view class="flex flex-col">
 		<view class="mb-3 flex flex-row">
-			<cl-input v-model="loginModel.username" prefix-icon="device-fill" :placeholder="t('请输入手机号')" :border="false" :pt="{
-				className: parseClass([
-					'!h-[45px] flex-1 !rounded-xl !px-4',
-					[isDark, '!bg-surface-70', '!bg-white']
-				]),
-				prefixIcon: {
-					className: 'mr-1'
-				}
-			}"></cl-input>
+			<cl-input
+				v-model="loginModel.username"
+				prefix-icon="device-fill"
+				:placeholder="t('请输入手机号')"
+				:border="false"
+				:pt="{
+					className: parseClass([
+						'!h-[45px] flex-1 !rounded-xl !px-4',
+						[isDark, '!bg-surface-70', '!bg-white']
+					]),
+					prefixIcon: {
+						className: 'mr-1'
+					}
+				}"
+			></cl-input>
 		</view>
 
 		<view class="relative flex flex-row items-center mb-5">
-			<cl-input v-model="loginModel.password" prefix-icon="device-fill" :placeholder="t('请输入手机号')" :border="false" :pt="{
-				className: parseClass([
-					'!h-[45px] flex-1 !rounded-xl !px-4',
-					[isDark, '!bg-surface-70', '!bg-white']
-				]),
-				prefixIcon: {
-					className: 'mr-1'
-				}
-			}"></cl-input>
+			<cl-input
+				v-model="loginModel.password"
+				:clearable="false"
+				type="number"
+				prefix-icon="shield-check-fill"
+				:border="false"
+				:pt="{
+					className: parseClass([
+						'!h-[45px] flex-1 !rounded-xl !px-4',
+						[isDark, '!bg-surface-70', '!bg-white']
+					]),
+					prefixIcon: {
+						className: 'mr-1'
+					}
+				}"
+			>
+			</cl-input>
 		</view>
 
-		<cl-button :pt="{
-			className: '!h-[45px] !rounded-xl'
-		}" :loading="loading" :disabled="disabled" @tap="toLogin">
+		<cl-button
+			:loading="loading"
+			:disabled="disabled"
+			@tap="toLogin"
+		>
 			{{ t("登录") }}
 		</cl-button>
 	</view>
 </template>
 
 <script setup lang="ts">
-import { computed, inject, ref, type PropType, reactive } from "vue";
+import { computed, inject,reactive, ref, type PropType } from "vue";
 import type { LoginForm } from "../../types";
 import SmsBtn from "../sms-btn.uvue";
 import { isDark, parseClass, request, useRefs, type Response, t, stringify } from "@/.cool";
 import { useUi } from "@/uni_modules/cool-ui";
-// import { loginApi } from "@/api/user";
+ type LoginModal = {
+	username: string;
+	password: string;
+	randomStr: number;
+	grant_type: string;
+	scope: string;
+	loginType: number;
+};
 
 const props = defineProps({
 	form: {
@@ -53,8 +76,8 @@ const props = defineProps({
 		default: () => ({})
 	}
 });
-const loginModel = reactive({
-	username: 'superadmin',
+const loginModel = reactive<LoginModal>({
+	username: 'gg',
 	password: '123456',
 	randomStr: 0,
 	grant_type: 'password',
@@ -87,13 +110,11 @@ async function toLogin() {
 	}
 
 	const { phone, smsCode } = props.form;
-
-	// loading.value = true;
-
-	await request<any>({
-		url: `/oauth/token?${stringify(loginModel)}`,
+const loginData = JSON.parse(JSON.stringify(loginModel)) as UTSJSONObject;
+		await request({
+		url: `/oauth/token?${stringify(loginData)}`,
 		method: 'POST',
-		data: loginModel
+		data: loginData
 	})
 		.then((res) => {
 			emit("success", res);