添加 useWx 方法,支持微信小程序登录等
This commit is contained in:
@@ -8,6 +8,11 @@ export const isDev = process.env.NODE_ENV == "development";
|
||||
// 忽略 token 校验的接口路径
|
||||
export const ignoreTokens: string[] = [];
|
||||
|
||||
// 微信配置
|
||||
type WxConfig = {
|
||||
debug: boolean;
|
||||
};
|
||||
|
||||
// 配置类型定义
|
||||
type Config = {
|
||||
name: string; // 应用名称
|
||||
@@ -19,6 +24,7 @@ type Config = {
|
||||
showDarkButton: boolean; // 是否显示暗色模式切换按钮
|
||||
isCustomTabBar: boolean; // 是否自定义 tabBar
|
||||
backTop: boolean; // 是否显示回到顶部按钮
|
||||
wx: WxConfig; // 微信配置
|
||||
};
|
||||
|
||||
// 根据环境导出最终配置
|
||||
@@ -30,6 +36,9 @@ export const config = {
|
||||
showDarkButton: isMp() ? false : true,
|
||||
isCustomTabBar: true,
|
||||
backTop: true,
|
||||
wx: {
|
||||
debug: false
|
||||
},
|
||||
...(isDev ? dev() : prod())
|
||||
} as Config;
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
export * from "./refs";
|
||||
export * from "./pager";
|
||||
export * from "./long-press";
|
||||
export * from "./cache";
|
||||
export * from "./long-press";
|
||||
export * from "./pager";
|
||||
export * from "./parent";
|
||||
export * from "./refs";
|
||||
export * from "./wx";
|
||||
|
||||
239
cool/hooks/wx.ts
Normal file
239
cool/hooks/wx.ts
Normal file
@@ -0,0 +1,239 @@
|
||||
import { ref } from "vue";
|
||||
import { assign, getUrlParam, storage } from "../utils";
|
||||
import { service } from "../service";
|
||||
import { t } from "@/locale";
|
||||
import { config } from "@/config";
|
||||
|
||||
// #ifdef H5
|
||||
import wx from "weixin-js-sdk";
|
||||
// #endif
|
||||
|
||||
// 微信配置类型
|
||||
type WxConfig = {
|
||||
appId: string;
|
||||
};
|
||||
|
||||
// 微信相关功能封装类
|
||||
export class Wx {
|
||||
// 微信登录code
|
||||
code = ref("");
|
||||
|
||||
/**
|
||||
* 获取微信登录code
|
||||
*/
|
||||
async getCode(): Promise<string> {
|
||||
return new Promise((resolve) => {
|
||||
// #ifdef MP-WEIXIN
|
||||
uni.login({
|
||||
provider: "weixin",
|
||||
success: (res) => {
|
||||
this.code.value = res.code;
|
||||
resolve(res.code);
|
||||
}
|
||||
});
|
||||
// #endif
|
||||
|
||||
// #ifndef MP-WEIXIN
|
||||
resolve("");
|
||||
// #endif
|
||||
});
|
||||
}
|
||||
|
||||
// #ifdef H5
|
||||
// 公众号配置
|
||||
mpConfig: WxConfig = {
|
||||
appId: ""
|
||||
};
|
||||
|
||||
/**
|
||||
* 判断当前是否为微信浏览器
|
||||
*/
|
||||
isWxBrowser() {
|
||||
const ua: string = window.navigator.userAgent.toLowerCase();
|
||||
if (ua.match(/MicroMessenger/i) != null) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取公众号配置信息,并初始化微信JS-SDK
|
||||
*/
|
||||
getMpConfig() {
|
||||
if (this.isWxBrowser()) {
|
||||
service.user.comm
|
||||
.wxMpConfig({
|
||||
url: `${location.origin}${location.pathname}`
|
||||
})
|
||||
.then((res) => {
|
||||
wx.config({
|
||||
debug: config.wx.debug,
|
||||
jsApiList: ["chooseWXPay"],
|
||||
...res
|
||||
});
|
||||
|
||||
// 合并配置到mpConfig
|
||||
assign(this.mpConfig, res);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 跳转到微信授权页面
|
||||
*/
|
||||
mpAuth() {
|
||||
const { appId } = this.mpConfig;
|
||||
|
||||
const redirect_uri = encodeURIComponent(
|
||||
`${location.origin}${location.pathname}#/pages/user/login`
|
||||
);
|
||||
const response_type = "code";
|
||||
const scope = "snsapi_userinfo";
|
||||
const state = "STATE";
|
||||
|
||||
const url = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appId}&redirect_uri=${redirect_uri}&response_type=${response_type}&scope=${scope}&state=${state}#wechat_redirect`;
|
||||
|
||||
location.href = url;
|
||||
}
|
||||
|
||||
/**
|
||||
* 公众号登录,获取code
|
||||
*/
|
||||
mpLogin() {
|
||||
return new Promise((resolve) => {
|
||||
const code = getUrlParam("code");
|
||||
const mpCode = storage.get("mpCode");
|
||||
|
||||
// 去除url中的code参数,避免重复
|
||||
const url = window.location.href.replace(/(\?[^#]*)#/, "#");
|
||||
window.history.replaceState({}, "", url);
|
||||
|
||||
if (code != mpCode) {
|
||||
storage.set("mpCode", code, 1000 * 60 * 5);
|
||||
resolve(code);
|
||||
} else {
|
||||
resolve(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 公众号微信支付
|
||||
* @param params 支付参数
|
||||
*/
|
||||
mpPay(params: wx.IchooseWXPay & { timeStamp: number }): Promise<void> {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!this.isWxBrowser()) {
|
||||
return reject({ message: t("请在微信浏览器中打开") });
|
||||
}
|
||||
|
||||
wx.chooseWXPay({
|
||||
...params,
|
||||
timestamp: params.timeStamp,
|
||||
success() {
|
||||
resolve();
|
||||
},
|
||||
complete(e: { errMsg: string }) {
|
||||
switch (e.errMsg) {
|
||||
case "chooseWXPay:cancel":
|
||||
reject({ message: t("已取消支付") });
|
||||
break;
|
||||
|
||||
default:
|
||||
reject({ message: t("支付失败") });
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
// #endif
|
||||
|
||||
// #ifdef MP
|
||||
/**
|
||||
* 小程序登录,获取用户信息和code
|
||||
*/
|
||||
miniLogin(): Promise<{
|
||||
code: string;
|
||||
iv: string;
|
||||
encryptedData: string;
|
||||
signature: string;
|
||||
rawData: string;
|
||||
}> {
|
||||
return new Promise((resolve, reject) => {
|
||||
// 兼容 Mac,Mac 端需用 getUserInfo
|
||||
const k = uni.getDeviceInfo().platform === "mac" ? "getUserInfo" : "getUserProfile";
|
||||
|
||||
uni[k]({
|
||||
lang: "zh_CN",
|
||||
desc: t("授权信息仅用于用户登录"),
|
||||
success: ({ iv, encryptedData, signature, rawData }) => {
|
||||
const next = () => {
|
||||
resolve({
|
||||
iv,
|
||||
encryptedData,
|
||||
signature,
|
||||
rawData,
|
||||
code: this.code.value
|
||||
});
|
||||
};
|
||||
|
||||
// 检查登录状态是否过期
|
||||
uni.checkSession({
|
||||
success: () => {
|
||||
next();
|
||||
},
|
||||
fail: () => {
|
||||
this.getCode().then(() => {
|
||||
next();
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
fail: (err) => {
|
||||
console.error(`[useWx.miniLogin] error`, err);
|
||||
this.getCode();
|
||||
|
||||
reject(t("登录授权失败"));
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 小程序微信支付
|
||||
* @param params 支付参数
|
||||
*/
|
||||
miniPay(params: any): Promise<void> {
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.requestPayment({
|
||||
provider: "wxpay",
|
||||
...params,
|
||||
success() {
|
||||
resolve();
|
||||
},
|
||||
fail() {
|
||||
reject(t("已取消支付"));
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
// #endif
|
||||
}
|
||||
|
||||
/**
|
||||
* useWx 钩子函数,后续可扩展
|
||||
*/
|
||||
export const useWx = (): Wx => {
|
||||
const wx = new Wx();
|
||||
|
||||
onReady(() => {
|
||||
wx.getCode();
|
||||
|
||||
// #ifdef H5
|
||||
wx.getMpConfig();
|
||||
// #endif
|
||||
});
|
||||
|
||||
return wx;
|
||||
};
|
||||
@@ -74,7 +74,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { service, upload, useStore, type Response } from "@/cool";
|
||||
import { parse, router, service, upload, useStore, useWx, type Response, type Token } from "@/cool";
|
||||
import { t } from "@/locale";
|
||||
import { useUi } from "@/uni_modules/cool-ui";
|
||||
import { reactive, ref } from "vue";
|
||||
@@ -83,6 +83,7 @@ const emit = defineEmits(["success"]);
|
||||
|
||||
const { user } = useStore();
|
||||
const ui = useUi();
|
||||
const wx = useWx();
|
||||
|
||||
// 是否显示编辑
|
||||
const editVisible = ref(false);
|
||||
@@ -142,6 +143,9 @@ async function editSave() {
|
||||
|
||||
// 关闭弹窗
|
||||
editClose();
|
||||
|
||||
// 跳转首页
|
||||
router.nextLogin();
|
||||
})
|
||||
.catch((err) => {
|
||||
// 上传失败,提示错误信息
|
||||
@@ -168,16 +172,38 @@ function onEditClose() {
|
||||
|
||||
// 微信小程序登录
|
||||
async function miniLogin() {
|
||||
await service.user.login
|
||||
.mini({})
|
||||
.then((res) => {
|
||||
emit("success", res);
|
||||
})
|
||||
.catch((err) => {
|
||||
ui.showToast({
|
||||
message: (err as Response).message!
|
||||
// #ifdef MP
|
||||
ui.showLoading(t("登录中"));
|
||||
|
||||
await wx.miniLogin().then(async (data) => {
|
||||
await service.user.login
|
||||
.mini(data)
|
||||
.then(async (res) => {
|
||||
// 设置token
|
||||
user.setToken(parse<Token>(res)!);
|
||||
|
||||
// 获取用户信息
|
||||
await user.get();
|
||||
|
||||
// 是否首次注册,根据业务情况调整判断逻辑
|
||||
if (user.info.nickName == "微信用户") {
|
||||
// 打开编辑弹窗
|
||||
editOpen();
|
||||
} else {
|
||||
// 跳转首页
|
||||
router.nextLogin();
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
ui.showToast({
|
||||
message: (err as Response).message!
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
ui.hideLoading();
|
||||
|
||||
// #endif
|
||||
}
|
||||
|
||||
// 微信APP登录
|
||||
@@ -185,21 +211,13 @@ function appLogin() {}
|
||||
|
||||
// 微信登录
|
||||
async function login() {
|
||||
ui.showToast({
|
||||
message: t("开发中,敬请期待")
|
||||
});
|
||||
|
||||
return;
|
||||
|
||||
// #ifdef MP-WEIXIN
|
||||
// #ifdef MP
|
||||
miniLogin();
|
||||
// #endif
|
||||
|
||||
// #ifdef APP
|
||||
appLogin();
|
||||
// #endif
|
||||
|
||||
emit("success");
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<login-phone :form="form" @success="toLogin"></login-phone>
|
||||
|
||||
<!-- 微信登录 -->
|
||||
<login-wx :ref="refs.set('loginWx')" @success="toLogin"></login-wx>
|
||||
<login-wx :ref="refs.set('loginWx')"></login-wx>
|
||||
|
||||
<!-- 协议 -->
|
||||
<view class="mt-6 flex flex-row flex-wrap items-center justify-center">
|
||||
@@ -94,9 +94,9 @@ const form = reactive<LoginForm>({
|
||||
const agree = ref(false);
|
||||
|
||||
// 登录成功
|
||||
function toLogin(res: any) {
|
||||
async function toLogin(res: any) {
|
||||
user.setToken(parse<Token>(res)!);
|
||||
router.home();
|
||||
router.nextLogin();
|
||||
}
|
||||
|
||||
// 跳转文档
|
||||
|
||||
Reference in New Issue
Block a user