merge home

This commit is contained in:
LittleBoy 2022-11-21 08:49:18 +08:00
parent 39429c4347
commit 86b1cd4d5f
21 changed files with 441 additions and 155 deletions

15
.gitignore vendored
View File

@ -1,14 +1 @@
# Windows
[Dd]esktop.ini
Thumbs.db
$RECYCLE.BIN/
# macOS
.DS_Store
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
# Node.js
node_modules/
/node_modules/

View File

@ -1,5 +1,6 @@
{
"pages": [
"pages/user/login",
"pages/personal/personal",
"pages/index/index",
"pages/logs/logs"

View File

@ -3,16 +3,9 @@ App<IAppOption>({
globalData: {},
onLaunch() {
// 展示本地存储能力
const logs = wx.getStorageSync('logs') || []
logs.unshift(Date.now())
wx.setStorageSync('logs', logs)
// 登录
// wx.login({
// success: res => {
// console.log(res.code)
// // 发送 res.code 到后台换取 openId, sessionKey, unionId
// },
// })
const token = wx.getStorageSync('user-token')
if (token) {
this.globalData.token = token;
}
},
})

10
miniprogram/app.wxss Normal file
View File

@ -0,0 +1,10 @@
/**app.wxss**/
.container {
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
padding: 200rpx 0;
box-sizing: border-box;
}

18
miniprogram/config.ts Normal file
View File

@ -0,0 +1,18 @@
type ApplicationConfig = {
api_url: string
env: 'dev' | 'test' | 'prod'
}
const ConfigData = {
dev: {
api_url: 'http://localhost:8001',
env: 'dev'
},
prod: {
api_url: 'http://localhost:8001',
env: 'prod'
}
}
const config = ConfigData['dev'] as ApplicationConfig
export default config

View File

@ -3,83 +3,47 @@
const app = getApp<IAppOption>()
Page({
data: {
motto: 'Hello World',
userInfo: {},
open_id: '',
hasUserInfo: false,
canIUse: wx.canIUse('button.open-type.getUserInfo'),
canIUseGetUserProfile: false,
canIUseOpenData: wx.canIUse('open-data.type.userAvatarUrl') && wx.canIUse('open-data.type.userNickName') // 如需尝试获取用户信息可改为false
},
// 事件处理函数
bindViewTap() {
wx.navigateTo({
url: '../logs/logs',
})
},
onLoad() {
// @ts-ignore
if (wx.getUserProfile) {
this.setData({
canIUseGetUserProfile: true
})
}
},
getUserProfile() {
// 推荐使用wx.getUserProfile获取用户信息开发者每次通过该接口获取用户个人信息均需用户确认开发者妥善保管用户快速填写的头像昵称避免重复弹窗
wx.getUserProfile({
desc: '展示用户信息', // 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写
success: (res) => {
console.log(res)
this.setData({
userInfo: res.userInfo,
hasUserInfo: true
})
}
})
},
getUserInfo(e: any) {
// 用户授权操作后的回调
// 并直接返回匿名的用户个人信息
console.log(e)
this.setData({
userInfo: e.detail.userInfo,
hasUserInfo: true
})
},
user_login() {
wx.login({
success: ({ code }) => {
if (!code) {
wx.showToast({
title: '获取授权数据失败'
})
return;
}
// 发起请求
wx.request({
url: 'http://localhost:8080/wechat/login',
data: { code },
method: 'GET',
success: (result) => {
if (result.statusCode != 200) {
wx.showToast({
title: '登录失败'
})
return;
}
this.setData({
open_id: result.data.toString()
})
}
})
},
fail: () => {
wx.showToast({
title: '授权失败'
})
}
})
data: {
motto: 'Hello World',
userInfo: {},
hasUserInfo: false,
canIUse: wx.canIUse('button.open-type.getUserInfo'),
canIUseGetUserProfile: false,
canIUseOpenData: wx.canIUse('open-data.type.userAvatarUrl') && wx.canIUse('open-data.type.userNickName') // 如需尝试获取用户信息可改为false
},
// 事件处理函数
bindViewTap() {
wx.navigateTo({
url: '../logs/logs',
})
},
onLoad() {
// @ts-ignore
if (wx.getUserProfile) {
this.setData({
canIUseGetUserProfile: true
})
}
},
getUserProfile() {
// 推荐使用wx.getUserProfile获取用户信息开发者每次通过该接口获取用户个人信息均需用户确认开发者妥善保管用户快速填写的头像昵称避免重复弹窗
wx.getUserProfile({
desc: '展示用户信息', // 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写
success: (res) => {
console.log(res)
this.setData({
userInfo: res.userInfo,
hasUserInfo: true
})
}
})
},
getUserInfo(e: any) {
// 不推荐使用getUserInfo获取用户信息预计自2021年4月13日起getUserInfo将不再弹出弹窗并直接返回匿名的用户个人信息
console.log(e)
this.setData({
userInfo: e.detail.userInfo,
hasUserInfo: true
})
}
})

View File

@ -1,27 +1,21 @@
<!--index.wxml-->
<view class="container">
<view class="userinfo">
<!-- <block wx:if="{{canIUseOpenData}}">
<block wx:if="{{canIUseOpenData}}">
<view class="userinfo-avatar" bindtap="bindViewTap">
<open-data type="userAvatarUrl"></open-data>
</view>
<open-data type="userNickName"></open-data>
</block> -->
<!-- <block wx:if="{{!hasUserInfo}}">
</block>
<block wx:elif="{{!hasUserInfo}}">
<button wx:if="{{canIUseGetUserProfile}}" bindtap="getUserProfile"> 获取头像昵称 </button>
<button wx:elif="{{canIUse}}"
open-type="getUserInfo"
bindgetuserinfo="getUserInfo"> 获取头像昵称 </button>
<button wx:elif="{{canIUse}}" open-type="getUserInfo" bindgetuserinfo="getUserInfo"> 获取头像昵称 </button>
<view wx:else> 请使用1.4.4及以上版本基础库 </view>
</block>
<block wx:else>
<image bindtap="bindViewTap" class="userinfo-avatar" src="{{userInfo.avatarUrl}}" mode="cover"></image>
<text class="userinfo-nickname">昵称:{{userInfo.nickName}}</text>
</block> -->
<button bindtap="user_login">登录</button>
<view>
{{open_id}}
</view>
<text class="userinfo-nickname">{{userInfo.nickName}}</text>
</block>
</view>
<view class="usermotto">
<text class="user-motto">{{motto}}</text>

View File

@ -0,0 +1,19 @@
/**index.wxss**/
.userinfo {
display: flex;
flex-direction: column;
align-items: center;
color: #aaa;
}
.userinfo-avatar {
overflow: hidden;
width: 128rpx;
height: 128rpx;
margin: 20rpx;
border-radius: 50%;
}
.usermotto {
margin-top: 200px;
}

View File

@ -0,0 +1,3 @@
{
"usingComponents": {}
}

View File

@ -0,0 +1,86 @@
import message from "../../utils/message"
import { getUserProfile, login } from "../../utils/promise-hooks"
import request, { BizError } from "../../utils/request";
// pages/user/login.ts
Page({
/**
*
*/
data: {
},
/**
* --
*/
async onLoad() {
},
async onGetUserInfo() {
message.showLoading()
try {
const data = await getUserProfile()
const res = await request('/wechat/login', data)
console.log(res)
} finally {
message.hideLoading()
}
},
async getCode() {
try {
const code = await login()
console.log(res)
} catch (e) {
message.toast(e)
}
},
/**
* --
*/
onReady() {
},
/**
* --
*/
onShow() {
},
/**
* --
*/
onHide() {
},
/**
* --
*/
onUnload() {
},
/**
* --
*/
onPullDownRefresh() {
},
/**
*
*/
onReachBottom() {
},
/**
*
*/
onShareAppMessage() {
}
})

View File

@ -0,0 +1,9 @@
<!--user/login.wxml-->
<view class="container">
<view class="userinfo">
<button bindtap="onGetUserInfo">立即登录</button>
</view>
<view class="usermotto">
<text class="user-motto">{{motto}}</text>
</view>
</view>

View File

@ -0,0 +1 @@
/* pages/user/login.wxss */

7
miniprogram/utils/log.ts Normal file
View File

@ -0,0 +1,7 @@
import config from "../config";
export default function log(...args: any[]) {
if (config.env !== 'prod') {
console.log(...args)
}
}

View File

@ -0,0 +1,28 @@
import { BizError } from "./request";
type ToastIcon = 'success' | 'error' | 'none';
export function toast(message: string|any, icon: ToastIcon = 'none') {
if(message instanceof BizError){
message = message.message
}
return wx.showToast({
title: message,
duration: 2000,
icon
})
}
export function showLoading({ message = '加载中...', mask = true }) {
return wx.showLoading({
title: message,
mask
})
}
export function hideLoading(){
wx.hideLoading()
}
export default {
toast,
showLoading,
hideLoading,
}

View File

@ -0,0 +1,65 @@
import message from "./message"
/**
* wx.login
* @param timeout
*/
export function login(timeout = 10000) {
return new Promise<string>((resolve, reject) => {
wx.login({
timeout, // 超时为10s
success: (res) => {
if (res.code) resolve(res.code)
else {
message.toast('登录失败,' + res.errMsg, 'error')
reject('登录失败,' + res.errMsg)
}
},
fail: (e) => {
message.toast('登录失败,请重新登录', 'error')
reject('登录失败,' + e.errMsg)
}
})
})
}
type UserProfileData = {
/**
* (BASE64)
*/
encryptedData: string
/**
* (BASE64)
*/
iv: string
/**
* auth.code2Session
* 使 code openidunionidsession_key
*/
code: string
}
export function getUserProfile(timeout = 10000) {
return new Promise<UserProfileData>((resolve, reject) => {
login(timeout).then(code => {
wx.getUserProfile({
desc: '展示用户信息并参与相关活动',
success: (res) => {
console.log(res)
if (res.errMsg == 'getUserProfile:ok' && res.encryptedData) {
resolve({
encryptedData: res.encryptedData,
iv: res.iv,
code
})
} else {
message.toast('登录失败,请重新登录', 'error')
reject('登录失败,' + res.errMsg)
}
},
fail: (e) => {
message.toast('登录失败,请重新登录', 'error')
reject('登录失败,' + e.errMsg)
}
})
}).catch(reject)
});
}

View File

@ -0,0 +1,62 @@
import config from "../config";
import log from "./log";
export class BizError extends Error {
code: number;
constructor(message: string, code = 500) {
super(message);
this.code = code;
}
}
type ApiResponse<T> = {
code: 0 | number
message: string
data: T
}
type HttpMethod = "GET" | "POST" | "PUT" | "DELETE"
function request<T>(api: string, data: any = null, method: HttpMethod = 'POST') {
const header: {
[key: string]: string
} = {}
// 判断是否有token
const token = getApp().globalData.token
if (token) { // 如果有token 添加token头
header.token = token
}
// 对于post请求发送json数据
if (method === 'POST') {
header['content-type'] = 'application/json'
}
return new Promise((resolve, reject) => {
wx.request<ApiResponse<T>>({
url: config.api_url + api,
data,
header,
method,
success: (res) => {
// 验证http的响应码是否正常
if (res.statusCode !== 200) {
reject(new BizError('请求数据失败(server)', -1))
return;
}
if(!res.data){
reject(new BizError('请求数据失败(empty)', -1))
return;
}
const result = res.data
// 验证接口是否正确
if (result.code !== 0) {
reject(new BizError(result.message, result.code))
return;
}
resolve(result.data)
},
fail: (e) => {
log(e)
reject(new BizError('请求数据失败(http)', -1))
}
})
})
}
export default request

42
package-lock.json generated Normal file
View File

@ -0,0 +1,42 @@
{
"name": "miniprogram-ts-less-quickstart",
"version": "1.0.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "miniprogram-ts-less-quickstart",
"version": "1.0.0",
"devDependencies": {
"@types/node": "^18.11.9",
"miniprogram-api-typings": "^2.12.0"
}
},
"node_modules/@types/node": {
"version": "18.11.9",
"resolved": "https://registry.npmmirror.com/@types/node/-/node-18.11.9.tgz",
"integrity": "sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg==",
"dev": true
},
"node_modules/miniprogram-api-typings": {
"version": "2.12.0",
"resolved": "https://registry.npmmirror.com/miniprogram-api-typings/-/miniprogram-api-typings-2.12.0.tgz",
"integrity": "sha512-ibvbqeslVFur0IAvTxLMvsbtvVcMo6gwvOnj0YZHV7aeDLu091VQRrETT2QuiG9P6aZWRcxeNGJChRKVPCp9VQ==",
"dev": true
}
},
"dependencies": {
"@types/node": {
"version": "18.11.9",
"resolved": "https://registry.npmmirror.com/@types/node/-/node-18.11.9.tgz",
"integrity": "sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg==",
"dev": true
},
"miniprogram-api-typings": {
"version": "2.12.0",
"resolved": "https://registry.npmmirror.com/miniprogram-api-typings/-/miniprogram-api-typings-2.12.0.tgz",
"integrity": "sha512-ibvbqeslVFur0IAvTxLMvsbtvVcMo6gwvOnj0YZHV7aeDLu091VQRrETT2QuiG9P6aZWRcxeNGJChRKVPCp9VQ==",
"dev": true
}
}
}

View File

@ -2,14 +2,12 @@
"name": "miniprogram-ts-less-quickstart",
"version": "1.0.0",
"description": "",
"scripts": {
},
"scripts": {},
"keywords": [],
"author": "",
"license": "",
"dependencies": {
},
"devDependencies": {
"miniprogram-api-typings": "^2.8.3-1"
"@types/node": "^18.11.9",
"miniprogram-api-typings": "^3.6.0"
}
}

View File

@ -1,31 +1,30 @@
{
"description": "项目配置文件",
"packOptions": {
"ignore": [],
"include": []
},
"miniprogramRoot": "miniprogram/",
"compileType": "miniprogram",
"projectname": "ts-less-demo",
"setting": {
"useCompilerPlugins": [
"typescript",
"less"
],
"babelSetting": {
"ignore": [],
"disablePlugins": [],
"outputPath": ""
}
},
"simulatorType": "wechat",
"simulatorPluginLibVersion": {},
"condition": {},
"srcMiniprogramRoot": "miniprogram/",
"appid": "wxafc2a812fe936d88",
"libVersion": "2.27.2",
"editorSetting": {
"tabIndent": "insertSpaces",
"tabSize": 4
"description": "项目配置文件",
"packOptions": {
"ignore": [],
"include": []
},
"miniprogramRoot": "miniprogram/",
"compileType": "miniprogram",
"projectname": "ts-demo",
"setting": {
"useCompilerPlugins": [
"typescript"
],
"babelSetting": {
"ignore": [],
"disablePlugins": [],
"outputPath": ""
}
},
"simulatorType": "wechat",
"simulatorPluginLibVersion": {},
"condition": {},
"srcMiniprogramRoot": "miniprogram/",
"appid": "wxafc2a812fe936d88",
"libVersion": "2.27.3",
"editorSetting": {
"tabIndent": "insertSpaces",
"tabSize": 2
}
}

View File

@ -1,9 +1,8 @@
{
"description": "项目私有配置文件。此文件中的内容将覆盖 project.config.json 中的相同字段。项目的改动优先同步到此文件中。详见文档https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html",
"projectname": "PointApp",
"setting": {
"compileHotReLoad": true,
"urlCheck": false
},
"libVersion": "2.23.0"
"description": "项目私有配置文件。此文件中的内容将覆盖 project.config.json 中的相同字段。项目的改动优先同步到此文件中。详见文档https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html",
"projectname": "userlogin-demo",
"setting": {
"compileHotReLoad": true,
"urlCheck": false
}
}

1
typings/index.d.ts vendored
View File

@ -3,6 +3,7 @@
interface IAppOption {
globalData: {
userInfo?: WechatMiniprogram.UserInfo,
token?: string
}
userInfoReadyCallback?: WechatMiniprogram.GetUserInfoSuccessCallback,
}