first commit
This commit is contained in:
179
components/LoginPopup/LoginPopup.vue
Normal file
179
components/LoginPopup/LoginPopup.vue
Normal file
@@ -0,0 +1,179 @@
|
||||
<template>
|
||||
<uni-popup ref="popupRef" type="bottom" :safe-area="false">
|
||||
<view class="popup-container">
|
||||
<view class="popup-header">
|
||||
<text class="popup-title">登录授权</text>
|
||||
</view>
|
||||
|
||||
<view class="avatar-nickname">
|
||||
<button open-type="chooseAvatar" @chooseavatar="onChooseAvatar" class="avatar-selector custom-button">
|
||||
<image v-if="avatarUrl" :src="avatarUrl" class="avatar-preview" />
|
||||
<text v-else>获取头像</text>
|
||||
</button>
|
||||
<input
|
||||
class="nickname-input"
|
||||
type="nickname"
|
||||
v-model="nickname"
|
||||
placeholder="请输入昵称"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<button class="confirm-btn custom-button" @tap="confirmLogin">确认登录</button>
|
||||
</view>
|
||||
</uni-popup>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import { useUserStore } from '@/stores/user'
|
||||
import { getPlatformProvider } from '@/utils/system'
|
||||
import { apiLogin } from '@/api/auth.js'
|
||||
import { wxLogin } from '@/utils/login.js'
|
||||
|
||||
// import { connectSocket, sendSocketMessage } from '@/utils/socket.js'
|
||||
|
||||
const popupRef = ref(null)
|
||||
const avatarUrl = ref('')
|
||||
const nickname = ref('')
|
||||
|
||||
const userStore = useUserStore()
|
||||
|
||||
const emit = defineEmits(['logind'])
|
||||
|
||||
const open = () => {
|
||||
popupRef.value.open()
|
||||
}
|
||||
|
||||
const close = () => {
|
||||
popupRef.value.close()
|
||||
}
|
||||
|
||||
const onChooseAvatar = (e) => {
|
||||
avatarUrl.value = e.detail.avatarUrl
|
||||
}
|
||||
|
||||
const confirmLogin = async () => {
|
||||
try {
|
||||
const platform = getPlatformProvider()
|
||||
if (platform === 'mp-weixin') {
|
||||
const code = await wxLogin()
|
||||
console.log('准备登录:', { code, nickname: nickname.value, avatarUrl: avatarUrl.value })
|
||||
// console.log('准备登录:', { code, nickname: nickname.value, avatarUrl: 'http://tmp/HXhtcEwQ5A3B58476c91ba545ab67c6bf9c67d9c2559.jpeg' })
|
||||
|
||||
const fileKeyRes = await uni.uploadFile({
|
||||
url: 'https://apis.lihailezzc.com/api/common/upload',
|
||||
filePath: avatarUrl.value,
|
||||
name: 'file', // 和后端接收文件字段名一致
|
||||
header: {
|
||||
'x-app-id': '6846f093fdf841f6189ef0b5',
|
||||
},
|
||||
})
|
||||
if(fileKeyRes.statusCode < 400) {
|
||||
const keyJson = JSON.parse(fileKeyRes.data)
|
||||
const url = `https://file.lihailezzc.com/${keyJson?.data.key}`
|
||||
const loginRes = await apiLogin({ code, nickname: nickname.value, avatarUrl: url })
|
||||
// 保存用户信息到store
|
||||
userStore.setUserInfo({
|
||||
nickName: loginRes?.user?.nickname || nickname.value,
|
||||
avatarUrl: loginRes?.user?.avatar || url,
|
||||
id: loginRes?.user?.id
|
||||
})
|
||||
|
||||
userStore.setToken(loginRes.token)
|
||||
|
||||
uni.showToast({ title: '登录成功', icon: 'success' })
|
||||
emit('logind')
|
||||
popupRef.value.close()
|
||||
|
||||
// connectSocket()
|
||||
|
||||
// 重置临时变量
|
||||
avatarUrl.value = ''
|
||||
nickname.value = ''
|
||||
} else {
|
||||
throw Error('获取失败')
|
||||
}
|
||||
|
||||
}
|
||||
} catch (err) {
|
||||
uni.showToast({ title: '登录失败', icon: 'none' })
|
||||
console.error(err)
|
||||
}
|
||||
}
|
||||
defineExpose({ open, close })
|
||||
</script>
|
||||
|
||||
<style lang='scss'>
|
||||
.custom-button {
|
||||
border: none;
|
||||
outline: none;
|
||||
background-color: transparent;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
line-height: normal;
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
.custom-button::after {
|
||||
border: none;
|
||||
}
|
||||
.popup-container {
|
||||
background-color: #fff;
|
||||
padding: 40rpx 30rpx 60rpx;
|
||||
border-top-left-radius: 30rpx;
|
||||
border-top-right-radius: 30rpx;
|
||||
|
||||
.popup-header {
|
||||
text-align: center;
|
||||
margin-bottom: 30rpx;
|
||||
|
||||
.popup-title {
|
||||
font-size: 36rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
.avatar-nickname {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
margin-bottom: 30rpx;
|
||||
|
||||
.avatar-selector {
|
||||
width: 145rpx;
|
||||
height: 145rpx;
|
||||
border-radius: 50%;
|
||||
font-size: 26rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 20rpx;
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
.avatar-preview {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.nickname-input {
|
||||
width: 80%;
|
||||
border: 1rpx solid #ccc;
|
||||
border-radius: 20rpx;
|
||||
padding: 20rpx;
|
||||
font-size: 26rpx;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.confirm-btn {
|
||||
background-color: #07c160;
|
||||
color: white;
|
||||
font-size: 30rpx;
|
||||
border-radius: 50rpx;
|
||||
padding: 20rpx 0;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
69
components/custom-content/custom-content.vue
Normal file
69
components/custom-content/custom-content.vue
Normal file
@@ -0,0 +1,69 @@
|
||||
<template>
|
||||
<view class="contentItem" :style="{background: bgColor, height: height, paddingTop: paddingTopValue }">
|
||||
<view class="topRow" :style="{ '--component-color': textColor }">
|
||||
<view class="title">{{title}}</view>
|
||||
<view class="enTitle">{{enTitle}}</view>
|
||||
</view>
|
||||
|
||||
<view class="content">
|
||||
<slot name="content"></slot>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
defineProps({
|
||||
title: { type: String, default: ""},
|
||||
enTitle: { type: String, default: "" },
|
||||
bgColor: { type: String, default: "#262626" },
|
||||
height: { type: String, default: "320rpx" },
|
||||
textColor: { type: String, default: "#B2B2B2" },
|
||||
paddingTopValue: { type: String, default: "0rpx" },
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.contentItem {
|
||||
width: 750rpx;
|
||||
|
||||
.topRow {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 50rpx 0;
|
||||
color: var(--component-color);
|
||||
|
||||
.title {
|
||||
font-size: 20rpx;
|
||||
}
|
||||
|
||||
.enTitle {
|
||||
width: 200rpx;
|
||||
font-size: 15rpx;
|
||||
text-align: center;
|
||||
margin-top: 10rpx;
|
||||
position: relative;
|
||||
&::before,
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
width: calc(50% - 60rpx); // 减去左右 padding 的宽度
|
||||
height: 1rpx;
|
||||
background-color: var(--component-color);
|
||||
transform: translateY(-90%);
|
||||
}
|
||||
|
||||
&::before {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
&::after {
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
70
components/layout/layout.vue
Normal file
70
components/layout/layout.vue
Normal file
@@ -0,0 +1,70 @@
|
||||
<template>
|
||||
<view class="layout">
|
||||
<custom-nav-bar></custom-nav-bar>
|
||||
<view class="header">
|
||||
<slot name="header"></slot>
|
||||
</view>
|
||||
<view class="main">
|
||||
<slot name="main"></slot>
|
||||
</view>
|
||||
<view class="footer">
|
||||
<footer-loayot></footer-loayot>
|
||||
</view>
|
||||
<view class="float">
|
||||
<!-- #ifdef MP -->
|
||||
<button class="item" open-type="contact">
|
||||
<uni-icons type="phone-filled" size="26" color="#888"></uni-icons>
|
||||
</button>
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef MP -->
|
||||
<button class="item" @click="clickContact">
|
||||
<uni-icons type="phone-filled" size="26" color="#888"></uni-icons>
|
||||
</button>
|
||||
<!-- #endif -->
|
||||
<!-- <view @click="onRefresh">
|
||||
|
||||
|
||||
</view> -->
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.layout{
|
||||
width: 100vw;
|
||||
background-color: #222;
|
||||
.header{
|
||||
min-height: 100rpx;
|
||||
}
|
||||
.main{
|
||||
min-height: 200rpx;
|
||||
}
|
||||
.footer{
|
||||
min-height: 120rpx;
|
||||
background: orange;
|
||||
}
|
||||
.float {
|
||||
position: fixed;
|
||||
right: 30rpx;
|
||||
bottom: 80rpx;
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
|
||||
.item {
|
||||
width: 90rpx;
|
||||
height: 90rpx;
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
border-radius: 50%;
|
||||
margin-bottom: 20rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 1px solid #eee;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user