This commit is contained in:
Jason 2022-09-07 20:58:01 +08:00
parent 67ccf1b607
commit 5c0105e786
16 changed files with 353 additions and 31 deletions

View File

@ -157,6 +157,7 @@ const setData = async () => {
getData()
feedback.msgSuccess('保存成功')
}
getData()
</script>
<style lang="scss" scoped>
.decoration-tabbar {

12
app/src/api/account.ts Normal file
View File

@ -0,0 +1,12 @@
import { client } from '@/utils/client'
import request from '@/utils/request'
// 登录
export function login(data: Record<string, any>) {
return request.post({ url: '/login/check', data: { ...data, client } })
}
//注册
export function register(data: Record<string, any>) {
return request.post({ url: '/login/register', data: { ...data, client } })
}

6
app/src/api/app.ts Normal file
View File

@ -0,0 +1,6 @@
import request from '@/utils/request'
//注册
export function smsSend(data: Record<string, any>) {
return request.post({ url: '/sms/send', data: data })
}

View File

@ -3,3 +3,19 @@ export enum ThemeEnum {
LIGHT = 'light',
DARK = 'dark'
}
// 客户端
export enum ClientEnum {
MP_WEIXIN = 1, // 微信-小程序
OA_WEIXIN = 2, // 微信-公众号
H5 = 3, // H5
IOS = 5, //苹果
ANDROID = 6 //安卓
}
export enum SMSEnum {
LOGIN = 101,
BIND_MOBILE = 102,
CHANGE_MOBILE = 103,
FIND_PASSWORD = 104
}

View File

@ -23,6 +23,12 @@
"style": {
"navigationBarTitleText": "登录"
}
},
{
"path": "pages/register/register",
"style": {
"navigationBarTitleText": "注册"
}
}
],
"globalStyle": {

View File

@ -1,46 +1,169 @@
<template>
<view class="login">
<view class="login min-h-full flex flex-col items-center px-[40rpx] pt-[80rpx] box-border">
<view>
<u-image src="" mode="widthFix" height="160" width="160" />
</view>
<view class="mt-4">这里是商城名称</view>
<view class="w-full mt-[60rpx]">
<u-form :model="formData" borderBottom>
<u-form-item borderBottom>
<u-icon class="mr-2" :size="36" name="/static/images/icon_user.png" />
<u-input
v-model="formData.mobile"
:border="false"
placeholder="请输入账号/手机号码"
/>
</u-form-item>
<u-form-item borderBottom>
<u-icon class="mr-2" :size="36" name="/static/images/icon_password.png" />
<u-input placeholder="请输入密码" :border="false" />
<view
class="border-l border-solid border-0 border-light pl-3 text-muted leading-4"
>
忘记密码
</view>
</u-form-item>
<u-form borderBottom>
<template v-if="scene == LoginTypeEnum.ACCOUNT">
<u-form-item borderBottom>
<u-icon class="mr-2" :size="36" name="/static/images/icon_user.png" />
<u-input
class="flex-1"
v-model="formData.username"
:border="false"
placeholder="请输入账号/手机号码"
/>
</u-form-item>
<u-form-item borderBottom>
<u-icon class="mr-2" :size="36" name="/static/images/icon_password.png" />
<u-input
class="flex-1"
v-model="formData.password"
type="password"
placeholder="请输入密码"
:border="false"
/>
<view
class="border-l border-solid border-0 border-light pl-3 text-muted leading-4 ml-3"
>
忘记密码
</view>
</u-form-item>
</template>
<template v-if="scene == LoginTypeEnum.MOBILE">
<u-form-item borderBottom>
<u-icon class="mr-2" :size="36" name="/static/images/icon_mobile.png" />
<u-input
class="flex-1"
v-model="formData.mobile"
:border="false"
placeholder="请输入手机号码"
/>
</u-form-item>
<u-form-item borderBottom>
<u-icon class="mr-2" :size="36" name="/static/images/icon_code.png" />
<u-input
class="flex-1"
v-model="formData.code"
placeholder="请输入验证码"
:border="false"
/>
<view
class="border-l border-solid border-0 border-light pl-3 text-muted leading-4 ml-3 w-[180rpx]"
@click="sendSms"
>
<u-verification-code
ref="uCodeRef"
:seconds="60"
@change="codeChange"
change-text="x秒"
/>
{{ codeTips }}
</view>
</u-form-item>
</template>
</u-form>
<view class="mt-[60rpx]">
<u-checkbox v-model="isCheckAgreement" shape="circle">
<view class="text-xs flex">
已阅读并同意
<navigator class="text-primary">服务协议</navigator>
<navigator class="text-primary">隐私协议</navigator>
</view>
</u-checkbox>
</view>
<view class="mt-[40rpx]">
<u-button type="primary" shape="circle" @click="accountLogin(scene)">
</u-button>
</view>
<view class="text-content flex justify-between mt-[40rpx]">
<view v-if="scene == LoginTypeEnum.MOBILE" @click="scene = LoginTypeEnum.ACCOUNT">
账号密码登录
</view>
<view v-if="scene == LoginTypeEnum.ACCOUNT" @click="scene = LoginTypeEnum.MOBILE">
短信验证码登录
</view>
<navigator url="/pages/register/register">注册账号</navigator>
</view>
<view class="mt-[80rpx]">
<u-divider>第三方登录</u-divider>
<div class="flex justify-center mt-[40rpx]">
<div class="flex flex-col items-center" @click="wxLogin">
<u-icon name="/static/images/icon_wx.png" size="80" />
<div class="text-sm mt-[10px]">微信登录</div>
</div>
</div>
</view>
</view>
</view>
</template>
<script setup lang="ts">
import { reactive } from 'vue'
import { login } from '@/api/account'
import { smsSend } from '@/api/app'
import { SMSEnum } from '@/enums/appEnums'
import { reactive, ref, shallowRef } from 'vue'
enum LoginTypeEnum {
MOBILE = 'mobile',
ACCOUNT = 'account',
MNP = 'mnp'
}
const uCodeRef = shallowRef()
const scene = ref(LoginTypeEnum.ACCOUNT)
const codeTips = ref('')
const isCheckAgreement = ref(false)
const formData = reactive({
username: '',
password: '',
code: '',
mobile: ''
})
const codeChange = (text: string) => {
codeTips.value = text
}
const sendSms = async () => {
if (!formData.mobile) return uni.$u.toast('请输入手机号码')
if (uCodeRef.value?.canGetCode) {
await smsSend({
scene: SMSEnum.LOGIN,
mobile: formData.mobile
})
uni.$u.toast('发送成功')
uCodeRef.value?.start()
}
}
const accountLogin = async (scene: LoginTypeEnum) => {
if (!isCheckAgreement.value) return uni.$u.toast('请勾选已阅读并同意《服务协议》和《隐私协议》')
if (scene == LoginTypeEnum.ACCOUNT) {
if (!formData.username) return uni.$u.toast('请输入账号/手机号码')
if (!formData.password) return uni.$u.toast('请输入密码')
}
if (scene == LoginTypeEnum.MOBILE) {
if (!formData.mobile) return uni.$u.toast('请输入手机号码')
if (!formData.code) return uni.$u.toast('请输入验证码')
}
await login({ ...formData, scene })
uni.$u.toast('登录成功')
uni.navigateBack()
}
const wxLogin = async () => {
const data: any = await uni.login({
provider: 'weixin'
})
accountLogin(LoginTypeEnum.MNP)
}
</script>
<style lang="scss">
page {
height: 100%;
}
.login {
@apply min-h-full flex flex-col items-center px-[40rpx] pt-[80rpx] box-border;
}
</style>

View File

@ -0,0 +1,76 @@
<template>
<view class="register min-h-full flex flex-col items-center px-[40rpx] pt-[40rpx] box-border">
<view class="w-full">
<u-form borderBottom :label-width="150">
<u-form-item label="创建账号" borderBottom>
<u-input
class="flex-1"
v-model="accountData.username"
:border="false"
placeholder="请输入账号"
/>
</u-form-item>
<u-form-item label="设置密码" borderBottom>
<u-input
class="flex-1"
type="password"
v-model="accountData.password"
placeholder="请输入字母+数字组合的密码"
:border="false"
/>
</u-form-item>
<u-form-item label="确认密码" borderBottom>
<u-input
class="flex-1"
type="password"
v-model="accountData.password2"
placeholder="请确认密码"
:border="false"
/>
</u-form-item>
</u-form>
<view class="mt-[60rpx]">
<u-checkbox v-model="isCheckAgreement" shape="circle">
<view class="text-xs flex">
已阅读并同意
<navigator class="text-primary">服务协议</navigator>
<navigator class="text-primary">隐私协议</navigator>
</view>
</u-checkbox>
</view>
<view class="mt-[40rpx]">
<u-button type="primary" shape="circle" @click="accountRegister"> 注册 </u-button>
</view>
</view>
</view>
</template>
<script setup lang="ts">
import { register } from '@/api/account'
import { reactive, ref } from 'vue'
const isCheckAgreement = ref(false)
const accountData = reactive({
username: '',
password: '',
password2: ''
})
const accountRegister = async () => {
if (!isCheckAgreement.value) return uni.$u.toast('请勾选已阅读并同意《服务协议》和《隐私协议》')
if (!accountData.username) return uni.$u.toast('请输入账号')
if (!accountData.password) return uni.$u.toast('请输入密码')
if (!accountData.password2) return uni.$u.toast('请输入确认密码')
if (accountData.password != accountData.password2) return uni.$u.toast('两次输入的密码不一致')
await register(accountData)
uni.$u.toast('组册成功')
uni.navigateBack()
}
</script>
<style lang="scss">
page {
height: 100%;
}
</style>

View File

@ -0,0 +1,6 @@
import { App } from 'vue'
import { createPinia } from 'pinia'
const pinia = createPinia()
export default (app: App) => {
app.use(pinia)
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 679 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

8
app/src/stores/app.ts Normal file
View File

@ -0,0 +1,8 @@
import { defineStore } from 'pinia'
export const useAppStore = defineStore({
id: 'userStore',
state: () => ({}),
getters: {},
actions: {}
})

12
app/src/stores/user.ts Normal file
View File

@ -0,0 +1,12 @@
import { getClient } from '@/utils/client'
import { defineStore } from 'pinia'
export const useAppStore = defineStore({
id: 'appStore',
// convert to a function
state: () => ({
client: getClient()
}),
getters: {},
actions: {}
})

View File

@ -429,7 +429,7 @@
.u-form-item {
@include vue-flex;
// align-items: flex-start;
padding: 10rpx 0;
padding: 15rpx 0;
font-size: 28rpx;
color: $u-main-color;
box-sizing: border-box;
@ -485,10 +485,8 @@
&__slot {
flex: 1;
/* #ifndef MP */
@include vue-flex;
align-items: center;
/* #endif */
}
&__icon {

57
app/src/utils/client.ts Normal file
View File

@ -0,0 +1,57 @@
import { ClientEnum } from '@/enums/appEnums'
/**
* @description
* @return { Boolean }
*/
export const isWeixinClient = () => {
// #ifdef H5
return /MicroMessenger/i.test(navigator.userAgent)
// #endif
}
/**
* @description
* @return { Object }
*/
export const getClient = () => {
//@ts-ignore
return handleClientEvent({
// 微信小程序
MP_WEIXIN: () => ClientEnum['MP_WEIXIN'],
// 微信公众号
OA_WEIXIN: () => ClientEnum['OA_WEIXIN'],
// H5
H5: () => ClientEnum['H5'],
// APP
IOS: () => ClientEnum['IOS'],
ANDROID: () => ClientEnum['ANDROID'],
// 其它
OTHER: () => null
})
}
// 根据端处理事件
//@ts-ignore
export const handleClientEvent = ({ MP_WEIXIN, OA_WEIXIN, H5, IOS, ANDROID, OTHER }) => {
// #ifdef MP-WEIXIN
return MP_WEIXIN()
// #endif
// #ifdef H5
return isWeixinClient() ? OA_WEIXIN() : H5()
// #endif
// #ifdef APP-PLUS
const system = uni.getSystemInfoSync()
if (system.platform == 'ios') {
return IOS()
} else {
return ANDROID()
}
// #endif
return OTHER()
}
export const client = getClient()

View File

@ -32,11 +32,11 @@ const requestHooks: RequestHooks = {
if (!isTransformResponse) {
return response.data
}
console.log(response.data)
const { code, data, msg } = response.data as any
switch (code) {
case RequestCodeEnum.SUCCESS:
return data
case RequestCodeEnum.PARAMS_TYPE_ERROR:
case RequestCodeEnum.PARAMS_VALID_ERROR:
case RequestCodeEnum.REQUEST_METHOD_ERROR:
@ -47,7 +47,8 @@ const requestHooks: RequestHooks = {
case RequestCodeEnum.NO_PERMISSTION:
case RequestCodeEnum.FAILED:
case RequestCodeEnum.SYSTEM_ERROR:
return Promise.reject(data)
uni.$u.toast(msg)
return Promise.reject(msg)
case RequestCodeEnum.TOKEN_INVALID:
case RequestCodeEnum.TOKEN_EMPTY:
@ -63,13 +64,13 @@ const defaultOptions: HttpRequestOptions = {
requestOptions: {
timeout: 10 * 1000
},
baseUrl: 'https://likeadmin-java.yixiangonline.com',
baseUrl: import.meta.env.VITE_APP_BASE_URL,
//是否返回默认的响应
isReturnDefaultResponse: false,
// 需要对返回数据进行处理
isTransformResponse: true,
// 接口拼接地址
urlPrefix: '/api',
urlPrefix: 'api',
// 忽略重复请求
ignoreCancel: false,
// 是否携带token