feat: 实现微信登录demo

This commit is contained in:
Burt 2024-01-16 10:15:20 +08:00
parent d84dd87dc7
commit 26068635dc
13 changed files with 224 additions and 35 deletions

View File

@ -3,9 +3,11 @@ import { defineManifestConfig } from '@uni-helper/vite-plugin-uni-manifest'
import path from 'node:path'
import { loadEnv } from 'vite'
// 获取环境变量的范例
const env = loadEnv(process.env.NODE_ENV!, path.resolve(process.cwd(), 'env'))
// console.log(env)
const { VITE_APP_TITLE, VITE_UNI_APPID, VITE_WX_APPID } = env
export default defineManifestConfig({
name: VITE_APP_TITLE,
appid: VITE_UNI_APPID,

View File

@ -1,4 +1,5 @@
import { defineUniPages } from '@uni-helper/vite-plugin-uni-pages'
import { isWxProd } from './vite.config'
export default defineUniPages({
globalStyle: {
@ -24,26 +25,42 @@ export default defineUniPages({
fontSize: '10px',
iconWidth: '24px',
spacing: '3px',
list: [
{
iconPath: 'static/tabbar/home.png',
selectedIconPath: 'static/tabbar/homeHL.png',
pagePath: 'pages/index/index',
text: '首页',
},
{
iconPath: 'static/tabbar/example.png',
selectedIconPath: 'static/tabbar/exampleHL.png',
pagePath: 'pages/demo/index',
text: '示例',
},
{
iconPath: 'static/tabbar/personal.png',
selectedIconPath: 'static/tabbar/personalHL.png',
pagePath: 'pages/my/index',
text: '我的',
},
],
list: isWxProd
? [
{
iconPath: 'static/tabbar/home.png',
selectedIconPath: 'static/tabbar/homeHL.png',
pagePath: 'pages/index/index',
text: '首页',
},
{
iconPath: 'static/tabbar/personal.png',
selectedIconPath: 'static/tabbar/personalHL.png',
pagePath: 'pages/my/index',
text: '我的',
},
]
: [
{
iconPath: 'static/tabbar/home.png',
selectedIconPath: 'static/tabbar/homeHL.png',
pagePath: 'pages/index/index',
text: '首页',
},
// 生产环境要注释掉demo所以分开来写
{
iconPath: 'static/tabbar/example.png',
selectedIconPath: 'static/tabbar/exampleHL.png',
pagePath: 'pages/demo/index',
text: '示例',
},
{
iconPath: 'static/tabbar/personal.png',
selectedIconPath: 'static/tabbar/personalHL.png',
pagePath: 'pages/my/index',
text: '我的',
},
],
},
// 你也可以定义 pages 字段,它具有最高的优先级。
pages: [],

View File

@ -0,0 +1,7 @@
# fly-login
点击“点击显示微信头像”按钮后,出现的半屏登录弹窗,可以在任意页面引入。
仿“掘金小册”小程序。
![掘金小册登录](screenshot.png)

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -0,0 +1,116 @@
<template>
<view class="fly-login" v-if="show">
<view class="fly-login-mask" />
<view class="fly-login-content px-4">
<view class="font-bold h-16 leading-16">获取您的昵称头像</view>
<view
class="rounded-full bg-light-600 w-6 h-6 text-center absolute top-4 right-4"
@click="onClose"
>
<view class="i-carbon-close text-gray-700" />
</view>
<view
class="flex items-center h-16 leading-16 border-b-gray-400 border-b-solid border-[1rpx]"
>
<text class="mr-4 flex-shrink-0">头像</text>
<button
class="bg-transparent flex items-center after:b-none w-full h-12 leading-12"
open-type="chooseAvatar"
@chooseavatar="onChooseAvatar"
>
<image class="w-8 h-8 rounded-full" :src="avatarUrl"></image>
<text class="ml-auto i-carbon-chevron-right"></text>
</button>
</view>
<view
class="flex items-center h-16 leading-16 border-b-gray-400 border-b-solid border-1 mt-4"
>
<text class="mr-4 flex-shrink-0">昵称</text>
<input type="nickname" placeholder="请输入昵称" @change="onChange" />
</view>
<button
size="default"
type="default"
style="color: #fff; background-color: #1aad19; border-color: #1aad19"
class="text-center leading-12 w-40 my-4"
@click="onSubmit"
>
确定
</button>
</view>
</view>
</template>
<script lang="ts" setup>
import { useUserStore } from '@/store'
import defaultAvatarUrl from './defaultAvatar.png'
const userStore = useUserStore()
const show = ref(true)
const avatarUrl = ref(defaultAvatarUrl)
const nickname = ref('')
const onClose = () => {
show.value = false
}
const onChooseAvatar = (e) => {
const { avatarUrl: url } = e.detail
avatarUrl.value = url
//
console.log(url)
}
const onChange = (e) => {
const { value } = e.detail
nickname.value = value
}
const onSubmit = () => {
// 1
// 2
if (avatarUrl.value === defaultAvatarUrl) {
uni.showToast({
title: '请选择头像',
icon: 'none',
})
return
}
if (!nickname.value) {
uni.showToast({
title: '请填写昵称',
icon: 'none',
})
return
}
console.log('保存用户信息')
userStore.setUserInfo({ nickname: nickname.value, avatar: avatarUrl.value })
}
</script>
<style lang="scss" scoped>
.fly-login {
position: fixed;
inset: 0;
.fly-login-mask {
position: fixed;
inset: 0;
background-color: rgb(0 0 0 / 30%);
}
.fly-login-content {
position: fixed;
right: 0;
bottom: 0;
left: 0;
background-color: #fff;
border-top-left-radius: 16px;
border-top-right-radius: 16px;
}
}
</style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 275 KiB

View File

@ -56,7 +56,7 @@
"type": "page"
},
{
"path": "pages/login/login",
"path": "pages/login/index",
"type": "page",
"style": {
"navigationBarTitleText": "登录"

40
src/pages/login/index.vue Normal file
View File

@ -0,0 +1,40 @@
<route lang="json5">
{
style: { navigationBarTitleText: '登录' },
}
</route>
<template>
<view class="p-4">
<view class="flex items-center leading-6" v-if="hasLogin">
<image class="w-8 h-8 rounded-full" :src="userStore.userInfo?.avatar"></image>
<view class="ml-2">{{ userStore.userInfo?.nickname }}</view>
</view>
<view class="flex items-center leading-6" v-else @click="show = true">
<fly-login v-if="show" />
<view class="i-carbon-user-avatar"></view>
<view class="ml-2">点击显示微信头像</view>
</view>
<fly-content :line="10" />
<button v-if="hasLogin" class="mt-2" @click="logout">退出登录</button>
</view>
</template>
<script lang="ts" setup>
import { useUserStore } from '@/store'
const show = ref(false)
const userStore = useUserStore()
const hasLogin = computed(() => userStore.userInfo?.nickname)
const logout = () => {
uni.showModal({
title: '确认退出当前账号?',
success: (res) => {
if (res.confirm) {
show.value = false
userStore.clearUserInfo()
}
},
})
}
</script>

View File

@ -1,9 +0,0 @@
<route lang="json5">
{
style: { navigationBarTitleText: '登录' },
}
</route>
<template>
<view>登录</view>
</template>

View File

@ -5,4 +5,12 @@
</route>
<template>
<view>我的</view>
<view @click="goLoginPage">去登录</view>
</template>
<script lang="ts" setup>
const goLoginPage = () => {
uni.navigateTo({ url: '/pages/login/index' })
}
// openId
</script>

4
src/typings.d.ts vendored
View File

@ -1,6 +1,6 @@
export type UserInfo = {
username: string
token: string
nickname: string
avatar: string
}
export type UserItem = {
username: string

2
uni-pages.d.ts vendored
View File

@ -6,7 +6,7 @@
interface NavigateToOptions {
url: "pages/index/index" |
"pages/demo/index" |
"pages/login/login" |
"pages/login/index" |
"pages/my/index" |
"pages/demo/demo/clock" |
"pages/demo/demo/component-auto-import" |

View File

@ -24,9 +24,13 @@ import AutoImport from 'unplugin-auto-import/vite'
import viteCompression from 'vite-plugin-compression'
import ViteRestart from 'vite-plugin-restart'
import { visualizer } from 'rollup-plugin-visualizer'
// TODO: 很多用户无法安装这个插件所以先注释掉了,如果你可以安装成功,那就可以放开这个注释,以及下面的配置
// TODO: 很多用户无法安装这个插件所以先注释掉了如果你可以安装成功那就可以放开这个注释以及下面的viteImagemin配置
// 另外小程序有主包2M的限制所以一般图片会放到图片服务器不放本地那这个插件就没用所以在开发h5的时候使用本地图片才用得到既然如此那就不装吧
// import viteImagemin from 'vite-plugin-imagemin'
export const isWxProd =
process.env.UNI_PLATFORM === 'mp-weixin' && process.env.NODE_ENV === 'production'
// https://vitejs.dev/config/
export default ({ command, mode }) => {
console.log(mode === process.env.NODE_ENV)
@ -43,11 +47,15 @@ export default ({ command, mode }) => {
const env = loadEnv(mode, path.resolve(process.cwd(), 'env'))
// console.log(env)
console.log(process.env.UNI_PLATFORM) // 得到 mp-weixin, h5 等
return defineConfig({
envDir: './env', // 自定义env目录
plugins: [
UniPages({
exclude: ['**/components/**/**.*'],
// TODO: 生产环境小程序要过滤掉demodemo里面很多图片超过2M的包大小
exclude: isWxProd
? ['**/components/**/**.*', '**/demo/**/**.*']
: ['**/components/**/**.*'],
}),
UniLayouts(),
UniPlatform(),