登录添加手机号

This commit is contained in:
kron
2025-12-03 15:19:17 +08:00
parent f9548f1373
commit d9ac803902
8 changed files with 101 additions and 54 deletions

View File

@@ -162,13 +162,14 @@ export const getProvinceData = () => {
return request("GET", "/index/provinces/list"); return request("GET", "/index/provinces/list");
}; };
export const loginAPI = async (nickName, avatarData, code) => { export const loginAPI = async (phone, nickName, avatarData, code) => {
const result = await request("POST", "/index/code", { const result = await request("POST", "/index/code", {
appName: "shoot", appName: "shoot",
appId: "wxa8f5989dcd45cc23", appId: "wxa8f5989dcd45cc23",
nickName, nickName,
avatarData, avatarData,
code, code,
phone,
}); });
uni.setStorageSync( uni.setStorageSync(
`${uni.getAccountInfoSync().miniProgram.envVersion}_token`, `${uni.getAccountInfoSync().miniProgram.envVersion}_token`,
@@ -519,3 +520,7 @@ export const addNoteAPI = async (id, remark) => {
export const removePointRecord = async (id) => { export const removePointRecord = async (id) => {
return request("DELETE", `/user/score/sheet/delete?id=${id}`); return request("DELETE", `/user/score/sheet/delete?id=${id}`);
}; };
export const getPhoneNumberAPI = (data) => {
return request("POST", "/index/getPhone", data);
};

View File

@@ -7,7 +7,7 @@ const props = defineProps({
}, },
height: { height: {
type: String, type: String,
default: "260px", default: "630rpx",
}, },
onClose: { onClose: {
type: Function, type: Function,
@@ -56,12 +56,9 @@ watch(
> >
<image <image
v-if="!noBg" v-if="!noBg"
src="https://static.shelingxingqiu.com/attachment/2025-08-05/dbuaf19pf7qd8ps0uh.png" src="https://static.shelingxingqiu.com/attachment/2025-12-03/deocxa1dgzebjc0hvo.png"
mode="widthFix" mode="widthFix"
/> />
<view class="close-btn" @click="onClose" v-if="!noBg">
<image src="../static/close-yellow.png" mode="widthFix" />
</view>
<slot></slot> <slot></slot>
</view> </view>
</view> </view>
@@ -94,14 +91,4 @@ watch(
position: absolute; position: absolute;
z-index: -1; z-index: -1;
} }
.close-btn {
display: flex;
justify-content: flex-end;
position: absolute;
right: 0;
}
.close-btn > image {
width: 40px;
height: 40px;
}
</style> </style>

View File

@@ -3,7 +3,14 @@ import { ref } from "vue";
import { onShow } from "@dcloudio/uni-app"; import { onShow } from "@dcloudio/uni-app";
import Avatar from "@/components/Avatar.vue"; import Avatar from "@/components/Avatar.vue";
import SButton from "@/components/SButton.vue"; import SButton from "@/components/SButton.vue";
import { getMyDevicesAPI, loginAPI, getHomeData } from "@/apis";
import { wxLogin } from "@/util";
import {
getMyDevicesAPI,
loginAPI,
getHomeData,
getPhoneNumberAPI,
} from "@/apis";
import useStore from "@/store"; import useStore from "@/store";
const store = useStore(); const store = useStore();
const { updateUser, updateDevice } = store; const { updateUser, updateDevice } = store;
@@ -18,6 +25,7 @@ const props = defineProps({
}, },
}); });
const agree = ref(false); const agree = ref(false);
const phone = ref("");
const avatarUrl = ref(""); const avatarUrl = ref("");
const nickName = ref(""); const nickName = ref("");
const loading = ref(false); const loading = ref(false);
@@ -25,6 +33,17 @@ const handleAgree = () => {
agree.value = !agree.value; agree.value = !agree.value;
}; };
async function getphonenumber(e) {
if (e.detail.code) {
const wxResult = await wxLogin();
const result = await getPhoneNumberAPI({
...e.detail,
code: wxResult.code,
});
if (result.phone) phone.value = result.phone;
}
}
function onChooseAvatar(e) { function onChooseAvatar(e) {
avatarUrl.value = e.detail.avatarUrl; avatarUrl.value = e.detail.avatarUrl;
} }
@@ -33,8 +52,14 @@ function onNicknameChange(e) {
nickName.value = e.detail.value; nickName.value = e.detail.value;
} }
const handleLogin = () => { const handleLogin = async () => {
if (loading.value) return; if (loading.value) return;
if (!phone.value) {
return uni.showToast({
title: "请获取手机号",
icon: "none",
});
}
if (!avatarUrl.value) { if (!avatarUrl.value) {
return uni.showToast({ return uni.showToast({
title: "请选择头像", title: "请选择头像",
@@ -54,34 +79,24 @@ const handleLogin = () => {
}); });
} }
loading.value = true; loading.value = true;
uni.login({ const wxResult = await wxLogin();
provider: "weixin",
success: async (loginRes) => {
const { code } = loginRes;
const fileManager = uni.getFileSystemManager(); const fileManager = uni.getFileSystemManager();
const avatarBase64 = fileManager.readFileSync(avatarUrl.value, "base64"); const avatarBase64 = fileManager.readFileSync(avatarUrl.value, "base64");
const base64Url = `data:image/png;base64,${avatarBase64}`; const base64Url = `data:image/png;base64,${avatarBase64}`;
const result = await loginAPI(nickName.value, base64Url, code); const result = await loginAPI(
phone.value,
nickName.value,
base64Url,
wxResult.code
);
const data = await getHomeData(); const data = await getHomeData();
if (data.user) updateUser(data.user); if (data.user) updateUser(data.user);
const devices = await getMyDevicesAPI(); const devices = await getMyDevicesAPI();
if (devices.bindings && devices.bindings.length) { if (devices.bindings && devices.bindings.length) {
updateDevice( updateDevice(devices.bindings[0].deviceId, devices.bindings[0].deviceName);
devices.bindings[0].deviceId,
devices.bindings[0].deviceName
);
} }
props.onClose();
},
fail: (err) => {
loading.value = false; loading.value = false;
uni.showToast({ props.onClose();
title: "登录失败",
icon: "none",
});
console.error("登录失败:", err);
},
});
}; };
const openServiceLink = () => { const openServiceLink = () => {
@@ -111,6 +126,21 @@ onShow(() => {
<template> <template>
<view class="container" :style="{ background: noBg ? '#fff' : 'none' }"> <view class="container" :style="{ background: noBg ? '#fff' : 'none' }">
<view class="avatar" :style="{ borderColor: noBg ? '#E3E3E3' : '#fff3' }">
<text :style="{ color: noBg ? '#666' : '#fff' }">手机:</text>
<button
:open-type="!phone ? 'getPhoneNumber' : ''"
@getphonenumber="getphonenumber"
class="login-btn"
hover-class="none"
>
<text v-if="phone" :style="{ color: noBg ? '#333' : '#fff' }">{{
phone
}}</text>
<text v-else :style="{ color: noBg ? '#666' : '#fff9' }">点击获取</text>
<image src="../static/enter.png" mode="widthFix" />
</button>
</view>
<view class="avatar" :style="{ borderColor: noBg ? '#E3E3E3' : '#fff3' }"> <view class="avatar" :style="{ borderColor: noBg ? '#E3E3E3' : '#fff3' }">
<text :style="{ color: noBg ? '#666' : '#fff' }">头像:</text> <text :style="{ color: noBg ? '#666' : '#fff' }">头像:</text>
<button <button
@@ -138,7 +168,7 @@ onShow(() => {
<SButton :rounded="20" width="80vw" :onClick="handleLogin"> <SButton :rounded="20" width="80vw" :onClick="handleLogin">
<block v-if="!loading"> <block v-if="!loading">
<image <image
src="../static/wechat-icon.png" :src="`../static/wechat-icon${noBg ? '' : '-black'}.png`"
mode="widthFix" mode="widthFix"
class="wechat-icon" class="wechat-icon"
/> />
@@ -191,7 +221,7 @@ onShow(() => {
display: flex; display: flex;
align-items: center; align-items: center;
margin-bottom: 20px; margin-bottom: 20px;
border-bottom: 1rpx solid #fff3; border-bottom: 1rpx solid #ffffff1a;
} }
.avatar { .avatar {
margin: 0; margin: 0;
@@ -200,7 +230,7 @@ onShow(() => {
.nickname > text { .nickname > text {
width: 20%; width: 20%;
font-size: 14px; font-size: 14px;
line-height: 55px; line-height: 120rpx;
} }
.avatar > button > text { .avatar > button > text {
color: #fff9; color: #fff9;
@@ -209,7 +239,7 @@ onShow(() => {
.nickname > input { .nickname > input {
flex: 1; flex: 1;
font-size: 14px; font-size: 14px;
line-height: 55px; line-height: 120rpx;
} }
.wechat-icon { .wechat-icon {
width: 24px; width: 24px;
@@ -220,8 +250,8 @@ onShow(() => {
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
font-size: 13px; font-size: 22rpx;
margin-top: 15px; margin: 30rpx 0;
color: #8a8a8a; color: #8a8a8a;
} }
.protocol > image { .protocol > image {

View File

@@ -413,7 +413,11 @@ onHide(() => {});
<text class="tips">创建者点击下一步所有人即可进入游戏</text> <text class="tips">创建者点击下一步所有人即可进入游戏</text>
</view> </view>
</view> </view>
<SModal :show="showModal" :onClose="() => (showModal = false)"> <SModal
:show="showModal"
:onClose="() => (showModal = false)"
height="520rpx"
>
<view class="btns"> <view class="btns">
<SButton :onClick="exitRoom" width="200px" :rounded="20"> <SButton :onClick="exitRoom" width="200px" :rounded="20">
暂时离开 暂时离开

View File

@@ -147,7 +147,11 @@ onShow(async () => {
</SButton> </SButton>
</view> </view>
</view> </view>
<SModal :show="showModal" :onClose="() => (showModal = false)"> <SModal
:show="showModal"
:onClose="() => (showModal = false)"
height="520rpx"
>
<view v-if="warnning" class="warnning"> <view v-if="warnning" class="warnning">
{{ warnning }} {{ warnning }}
</view> </view>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 381 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 713 B

View File

@@ -813,3 +813,20 @@ export const getDirectionText = (angle = 0) => {
return "右下"; return "右下";
} }
}; };
export const wxLogin = () => {
return new Promise((resolve, reject) => {
uni.login({
provider: "weixin",
success: resolve,
fail: (err) => {
uni.showToast({
title: "登录失败",
icon: "none",
});
console.error("登录失败:", err);
reject(err);
},
});
});
};