微信小程序登录修改
This commit is contained in:
@@ -739,7 +739,7 @@ async function initWebSocket() {
|
||||
// 构建WebSocket URL
|
||||
// 开发环境:ws://localhost:8180 或 ws://192.168.x.x:8180
|
||||
// 生产环境:wss://your-domain.com
|
||||
const protocol = 'ws:' // 开发环境使用ws,生产环境改为wss
|
||||
const protocol = 'wss:' // 开发环境使用ws,生产环境改为wss
|
||||
// 小程序使用原生WebSocket端点(不是SockJS端点)
|
||||
const wsUrl = `${protocol}//${WS_HOST}/urban-lifeline/workcase/ws/chat?token=${encodeURIComponent(token)}`
|
||||
|
||||
|
||||
@@ -227,7 +227,7 @@ async function initWebSocket() {
|
||||
// 构建WebSocket URL
|
||||
// 开发环境:ws://localhost:8180 或 ws://192.168.x.x:8180
|
||||
// 生产环境:wss://your-domain.com
|
||||
const protocol = 'ws:' // 开发环境使用ws,生产环境改为wss
|
||||
const protocol = 'wss:' // 开发环境使用ws,生产环境改为wss
|
||||
// 小程序使用原生WebSocket端点(不是SockJS端点)
|
||||
const wsUrl = `${protocol}//${WS_HOST}/urban-lifeline/workcase/ws/chat?token=${encodeURIComponent(token)}`
|
||||
|
||||
|
||||
@@ -80,6 +80,15 @@
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
// 退出按钮特殊样式
|
||||
.logout-btn {
|
||||
background: rgba(255, 59, 48, 0.1);
|
||||
|
||||
.btn-text {
|
||||
color: #ff3b30;
|
||||
}
|
||||
}
|
||||
|
||||
// 欢迎区域(机器人+浮动标签)
|
||||
.hero {
|
||||
position: relative;
|
||||
@@ -803,3 +812,94 @@
|
||||
.modal-btn .btn-text {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
// 手机号授权弹窗样式
|
||||
.phone-auth-modal {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: 1001;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.phone-auth-content {
|
||||
width: 85%;
|
||||
max-width: 340px;
|
||||
padding: 30px 24px;
|
||||
}
|
||||
|
||||
.phone-auth-body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.auth-icon-wrap {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.auth-icon {
|
||||
font-size: 40px;
|
||||
}
|
||||
|
||||
.auth-desc {
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
line-height: 1.6;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.phone-auth-footer {
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.phone-auth-btn {
|
||||
width: 100%;
|
||||
height: 48px;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
border-radius: 24px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.phone-auth-btn .btn-text {
|
||||
color: white;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.phone-auth-btn::after {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.skip-auth-btn {
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
background: transparent;
|
||||
border-radius: 20px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.skip-auth-btn .skip-text {
|
||||
color: #999;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.skip-auth-btn::after {
|
||||
border: none;
|
||||
}
|
||||
|
||||
@@ -4,9 +4,6 @@
|
||||
<view class="header" :style="{ paddingTop: headerPaddingTop + 'px', height: headerTotalHeight + 'px' }">
|
||||
<text class="title">泰豪小电</text>
|
||||
<view class="header-right">
|
||||
<button class="workcase-btn" @tap="switchMockUser" v-if="isMockMode">
|
||||
<text class="btn-text">切换</text>
|
||||
</button>
|
||||
<button class="workcase-btn" @tap="goToChatRoomList">
|
||||
<text class="btn-text">聊天室</text>
|
||||
</button>
|
||||
@@ -175,14 +172,40 @@
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 手机号授权弹窗 -->
|
||||
<view class="phone-auth-modal" v-if="showPhoneAuthModal">
|
||||
<view class="modal-mask"></view>
|
||||
<view class="modal-content phone-auth-content">
|
||||
<view class="modal-header">
|
||||
<text class="modal-title">欢迎使用泰豪小电</text>
|
||||
</view>
|
||||
<view class="modal-body phone-auth-body">
|
||||
<view class="auth-icon-wrap">
|
||||
<text class="auth-icon">📱</text>
|
||||
</view>
|
||||
<text class="auth-desc">为了给您提供更好的服务,需要获取您的手机号用于身份识别和工单通知</text>
|
||||
</view>
|
||||
<view class="modal-footer phone-auth-footer">
|
||||
<button
|
||||
class="modal-btn confirm phone-auth-btn"
|
||||
open-type="getPhoneNumber"
|
||||
@getphonenumber="onGetPhoneNumber"
|
||||
>
|
||||
<text class="btn-text">授权手机号登录</text>
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, nextTick, onMounted } from 'vue'
|
||||
import { guestAPI, aiChatAPI, workcaseChatAPI } from '@/api'
|
||||
import { guestAPI, aiChatAPI, workcaseChatAPI, fileAPI } from '@/api'
|
||||
import { clearLoginInfo } from '@/api/base'
|
||||
import type { TbWorkcaseDTO } from '@/types'
|
||||
import type { DifyFileInfo } from '@/types/ai/aiChat'
|
||||
import { AGENT_ID, FILE_DOWNLOAD_URL } from '@/config'
|
||||
import { AGENT_ID } from '@/config'
|
||||
// 前端消息展示类型
|
||||
interface ChatMessageItem {
|
||||
type: 'user' | 'bot'
|
||||
@@ -215,8 +238,12 @@
|
||||
phone: '',
|
||||
userId: ''
|
||||
})
|
||||
const isMockMode = ref(true) // 开发环境mock模式
|
||||
const userType = ref(false)
|
||||
|
||||
// 是否显示手机号授权弹窗
|
||||
const showPhoneAuthModal = ref(false)
|
||||
// 临时保存的微信登录code
|
||||
const tempWechatCode = ref('')
|
||||
// AI 对话相关
|
||||
const chatId = ref<string>('') // 当前会话ID
|
||||
const currentTaskId = ref<string>('') // 当前任务ID(用于停止)
|
||||
@@ -229,41 +256,74 @@
|
||||
|
||||
// 初始化用户信息
|
||||
async function initUserInfo() {
|
||||
// #ifdef MP-WEIXIN
|
||||
// 正式环境:从微信获取用户信息
|
||||
// wx.login({
|
||||
// success: (loginRes) => {
|
||||
// // 使用code换取openid等信息
|
||||
// console.log('微信登录code:', loginRes.code)
|
||||
// }
|
||||
// })
|
||||
// #endif
|
||||
|
||||
// 开发环境:使用mock数据
|
||||
if (isMockMode.value) {
|
||||
userInfo.value = {
|
||||
wechatId: '17857100377',
|
||||
username: '访客用户',
|
||||
phone: '17857100377',
|
||||
userId: ''
|
||||
try {
|
||||
// 1. 先尝试从缓存获取
|
||||
const cachedWechatId = uni.getStorageSync('wechatId')
|
||||
const cachedUserInfo = uni.getStorageSync('userInfo')
|
||||
const cachedToken = uni.getStorageSync('token')
|
||||
|
||||
if (cachedWechatId && cachedUserInfo && cachedToken) {
|
||||
// 有完整缓存,直接使用
|
||||
const parsedUserInfo = typeof cachedUserInfo === 'string' ? JSON.parse(cachedUserInfo) : cachedUserInfo
|
||||
userInfo.value = {
|
||||
wechatId: cachedWechatId,
|
||||
username: parsedUserInfo.username || parsedUserInfo.realName || '微信用户',
|
||||
phone: parsedUserInfo.phone || '',
|
||||
userId: parsedUserInfo.userId || ''
|
||||
}
|
||||
|
||||
// 判断用户类型
|
||||
if (parsedUserInfo.status === 'guest') {
|
||||
userType.value = false
|
||||
} else {
|
||||
userType.value = true
|
||||
}
|
||||
|
||||
console.log('使用缓存的用户信息:', userInfo.value)
|
||||
return
|
||||
}
|
||||
await doIdentify()
|
||||
|
||||
// 2. 没有缓存,自动登录
|
||||
await autoLogin()
|
||||
} catch (error) {
|
||||
console.error('初始化用户信息失败:', error)
|
||||
// 登录失败,尝试自动登录
|
||||
await autoLogin()
|
||||
}
|
||||
}
|
||||
|
||||
// 切换mock用户(开发调试用)
|
||||
function switchMockUser() {
|
||||
uni.showActionSheet({
|
||||
itemList: ['员工 (17857100375)', '访客 (17857100377)'],
|
||||
success: (res) => {
|
||||
if (res.tapIndex === 0) {
|
||||
userInfo.value = { wechatId: '17857100375', username: '员工用户', phone: '17857100375', userId: '' }
|
||||
} else {
|
||||
userInfo.value = { wechatId: '17857100377', username: '访客用户', phone: '17857100377', userId: '' }
|
||||
// 自动登录
|
||||
async function autoLogin() {
|
||||
uni.showLoading({ title: '初始化中...' })
|
||||
|
||||
try {
|
||||
// 使用 wx.login 获取 code
|
||||
uni.login({
|
||||
provider: 'weixin',
|
||||
success: async (loginRes) => {
|
||||
console.log('微信登录成功,code:', loginRes.code)
|
||||
uni.hideLoading()
|
||||
|
||||
// 保存code,等待手机号授权后使用
|
||||
tempWechatCode.value = loginRes.code
|
||||
|
||||
// 显示手机号授权弹窗
|
||||
showPhoneAuthModal.value = true
|
||||
},
|
||||
fail: (err) => {
|
||||
console.error('微信登录失败:', err)
|
||||
uni.hideLoading()
|
||||
uni.showToast({ title: '登录失败,请重试', icon: 'none' })
|
||||
}
|
||||
doIdentify()
|
||||
}
|
||||
})
|
||||
})
|
||||
} catch (error: any) {
|
||||
console.error('自动登录失败:', error)
|
||||
uni.hideLoading()
|
||||
uni.showToast({
|
||||
title: error.message || '登录失败',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// 调用identify接口
|
||||
@@ -304,6 +364,104 @@
|
||||
}
|
||||
}
|
||||
|
||||
// 获取手机号回调
|
||||
async function onGetPhoneNumber(e: any) {
|
||||
console.log('获取手机号回调:', e)
|
||||
|
||||
if (e.detail.errMsg !== 'getPhoneNumber:ok') {
|
||||
console.error('获取手机号失败:', e.detail)
|
||||
|
||||
// 如果是权限问题,提示用户
|
||||
if (e.detail.errno === 102) {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '该小程序暂未开通手机号快速验证功能,请联系管理员开通后再试。',
|
||||
showCancel: false
|
||||
})
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: '需要授权手机号才能使用',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 关闭弹窗
|
||||
showPhoneAuthModal.value = false
|
||||
|
||||
uni.showLoading({ title: '登录中...' })
|
||||
|
||||
try {
|
||||
const code = tempWechatCode.value
|
||||
const wechatId = code.substring(0, 20) // 使用部分code作为临时ID
|
||||
|
||||
// 获取手机号授权返回的数据
|
||||
const phoneCode = e.detail.code // 手机号授权code(推荐使用)
|
||||
const encryptedData = e.detail.encryptedData // 加密数据
|
||||
const iv = e.detail.iv // 解密向量
|
||||
|
||||
console.log('手机号授权数据:', { code, phoneCode, encryptedData: encryptedData?.substring(0, 50) + '...', iv })
|
||||
|
||||
// 调用 identify 接口
|
||||
// 后端可以选择使用 phoneCode 或 encryptedData+iv 来解密手机号
|
||||
const identifyRes = await guestAPI.identify({
|
||||
wechatId: wechatId,
|
||||
code: code, // 微信登录code
|
||||
phoneCode: phoneCode, // 手机号授权code(新版API推荐)
|
||||
encryptedData: encryptedData, // 加密数据(旧版API)
|
||||
iv: iv, // 解密向量(旧版API)
|
||||
loginType: 'wechat_miniprogram'
|
||||
})
|
||||
|
||||
uni.hideLoading()
|
||||
|
||||
if (identifyRes.success && identifyRes.data) {
|
||||
const loginDomain = identifyRes.data
|
||||
|
||||
// 保存登录信息
|
||||
uni.setStorageSync('token', loginDomain.token || '')
|
||||
uni.setStorageSync('userInfo', JSON.stringify(loginDomain.user))
|
||||
uni.setStorageSync('loginDomain', JSON.stringify(loginDomain))
|
||||
uni.setStorageSync('wechatId', wechatId)
|
||||
|
||||
// 更新用户信息
|
||||
userInfo.value = {
|
||||
wechatId: wechatId,
|
||||
username: loginDomain.user?.username || loginDomain.user?.realName || '微信用户',
|
||||
phone: loginDomain.user?.phone || '',
|
||||
userId: loginDomain.user?.userId || ''
|
||||
}
|
||||
|
||||
// 判断用户类型
|
||||
if (loginDomain.user?.status === 'guest') {
|
||||
userType.value = false
|
||||
} else {
|
||||
userType.value = true
|
||||
}
|
||||
|
||||
console.log('手机号授权登录成功:', userInfo.value)
|
||||
uni.showToast({ title: '登录成功', icon: 'success' })
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: identifyRes.message || '登录失败',
|
||||
icon: 'none'
|
||||
})
|
||||
// 登录失败,重新显示授权弹窗
|
||||
showPhoneAuthModal.value = true
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.error('手机号授权登录失败:', error)
|
||||
uni.hideLoading()
|
||||
uni.showToast({
|
||||
title: error.message || '登录失败',
|
||||
icon: 'none'
|
||||
})
|
||||
// 登录失败,重新显示授权弹窗
|
||||
showPhoneAuthModal.value = true
|
||||
}
|
||||
}
|
||||
|
||||
// 生命周期
|
||||
onMounted(() => {
|
||||
// 初始化用户信息
|
||||
@@ -885,7 +1043,7 @@
|
||||
|
||||
// 获取文件下载URL(通过文件ID)
|
||||
function getFileDownloadUrl(fileId: string): string {
|
||||
return `${FILE_DOWNLOAD_URL}${fileId}`
|
||||
return fileAPI.getDownloadUrl(fileId)
|
||||
}
|
||||
|
||||
// 判断文件ID对应的文件是否为图片
|
||||
@@ -938,6 +1096,7 @@
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
Reference in New Issue
Block a user