12 changed files with 398 additions and 108 deletions
-
3envs/.env.development
-
3envs/.env.production
-
1package.json
-
5src/api/index.js
-
37src/api/loading.js
-
89src/api/server.js
-
37src/api/upload.js
-
19src/pages/index/index.vue
-
5src/styles/iconfonts.scss
-
101src/styles/methods.scss
-
106src/uni.scss
-
100src/utils/polish.js
@ -1,4 +1,5 @@ |
|||||
|
# 测试环境配置文件 |
||||
# 接口地址 |
# 接口地址 |
||||
VITE_API_BASE=https://api.test.com |
|
||||
|
VITE_API_BASE=https://test.ouxuanzhineng.cn |
||||
# 头条小程序 appid |
# 头条小程序 appid |
||||
VITE_TOUTIAO_APPID=ttc690b02d599a28ee01 |
VITE_TOUTIAO_APPID=ttc690b02d599a28ee01 |
@ -1,4 +1,5 @@ |
|||||
|
# 生成环境配置文件 |
||||
# 接口地址 |
# 接口地址 |
||||
VITE_API_BASE=https://api.formal.com |
|
||||
|
VITE_API_BASE=https://miniapp.ouxuanzhineng.cn |
||||
# 头条小程序 appid |
# 头条小程序 appid |
||||
VITE_TOUTIAO_APPID=ttc690b02d599a28ee01-p |
VITE_TOUTIAO_APPID=ttc690b02d599a28ee01-p |
@ -0,0 +1,5 @@ |
|||||
|
import server from './server'; |
||||
|
|
||||
|
// 公共
|
||||
|
export const login = params => server.post({ url: '/Admino/AdminUser/login', ...params }); // 登录
|
||||
|
export const stadiumFind = params => server.post({ url: '/stadium/find', ...params }); // 登录
|
@ -0,0 +1,37 @@ |
|||||
|
class Loading { |
||||
|
times = 0 |
||||
|
timer = null |
||||
|
// https://developers.weixin.qq.com/community/develop/doc/0008e440e6cb58d4050a4b7e451c00?_at=1619083932616
|
||||
|
// showLoading 与 hideLoading 尽量成对出现,不然会报错
|
||||
|
// => (in promise) MiniProgramError{"errMsg":"hideLoading:fail toast can't be found"}Object
|
||||
|
isLoading = false |
||||
|
show(loading) { |
||||
|
if (loading === false) return // 如果传入的 loading 属性为 false,则不处理
|
||||
|
clearTimeout(this.timer) // 如果有多个请求同时进行,则用最后请求的 loading
|
||||
|
|
||||
|
this.times++ |
||||
|
this.timer = setTimeout(() => { |
||||
|
this.isLoading = true; |
||||
|
uni.showLoading({ |
||||
|
title: loading ?? '加载中', |
||||
|
mask: true |
||||
|
}) |
||||
|
}, 200) // 设定延迟,如果请求超过 200ms 才显示 loading
|
||||
|
} |
||||
|
|
||||
|
hide(loading) { |
||||
|
if (loading === false) return |
||||
|
|
||||
|
this.times-- |
||||
|
if (this.times <= 0) { |
||||
|
clearTimeout(this.timer) |
||||
|
if(this.isLoading){ |
||||
|
uni.hideLoading(); |
||||
|
this.isLoading = false; |
||||
|
} |
||||
|
this.times = 0 |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
export default Loading |
@ -0,0 +1,89 @@ |
|||||
|
// 引入 uni-ajax 模块
|
||||
|
// https://uniajax.ponjs.com/
|
||||
|
import ajax from 'uni-ajax'; |
||||
|
import Loading from './loading' |
||||
|
import { showModal, routeTo } from '@/utils/polish'; |
||||
|
const loading = new Loading(); |
||||
|
|
||||
|
// 定义 pending 状态的 Promise,用于避免进入 catch 回调
|
||||
|
const pending = new Promise(() => {}) |
||||
|
|
||||
|
// 创建请求实例
|
||||
|
const server = ajax.create({ |
||||
|
// 初始配置
|
||||
|
baseURL: __API__, |
||||
|
loading: 'loading...', |
||||
|
}) |
||||
|
|
||||
|
// 添加请求拦截器
|
||||
|
server.interceptors.request.use( |
||||
|
config => { |
||||
|
let _token = uni.getStorageSync('token'); |
||||
|
if(_token)config.data.ustoken = _token; |
||||
|
loading.show(config.loading); |
||||
|
return config; |
||||
|
}, |
||||
|
error => { |
||||
|
console.error('server.interceptors.request error -> ', error); |
||||
|
return Promise.reject(error); |
||||
|
} |
||||
|
) |
||||
|
|
||||
|
// 添加响应拦截器
|
||||
|
server.interceptors.response.use( |
||||
|
response => { |
||||
|
loading.hide(response.config.loading); |
||||
|
if(response?.data?.code === 0)return formatResponse(response); |
||||
|
console.error(`get ${response?.config?.url} err -> `, response) |
||||
|
// return errorHandle({
|
||||
|
// Catch: response?.config?.catch || false,
|
||||
|
// content: response?.data?.smsg ?? '请求失败',
|
||||
|
// data: response,
|
||||
|
// success: () => {
|
||||
|
// // 登录超时
|
||||
|
// if(response?.data?.error === '201')loginHandle();
|
||||
|
// if(response?.data?.error === '704'&&response?.data?.smsg === 'ustoken不能为空')loginHandle();
|
||||
|
// }
|
||||
|
// })
|
||||
|
}, |
||||
|
error => { |
||||
|
loading.hide(error.config.loading); |
||||
|
console.error('server.interceptors.response error -> ', error); |
||||
|
// return errorHandle({
|
||||
|
// Catch: error?.config?.catch || false,
|
||||
|
// // 404 拦截 data 会存在错误信息
|
||||
|
// content: error?.data ?? error?.errMsg ?? '请求失败',
|
||||
|
// data: error,
|
||||
|
// })
|
||||
|
} |
||||
|
) |
||||
|
|
||||
|
function formatResponse(response){ |
||||
|
let _data = response?.data?.data || null; |
||||
|
|
||||
|
return _data; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* 在有返回错误的拦截器里返回 pending 状态的 Promise |
||||
|
* |
||||
|
* 传值 config.catch 判断是否需要返回错误,如果是 true 返回错误信息,否则不返回。 |
||||
|
*/ |
||||
|
function errorHandle({ Catch = true, content = '', data = {}, success }) { |
||||
|
console.error(`get ${data?.config?.url} err -> `, data) |
||||
|
showModal({ |
||||
|
content: content || '请求失败', |
||||
|
success: success |
||||
|
}) |
||||
|
|
||||
|
return Catch ? Promise.reject(data) : pending; |
||||
|
} |
||||
|
|
||||
|
function loginHandle() { |
||||
|
uni.removeStorageSync('token'); |
||||
|
routeTo(`/pages/login/index`, 'rL'); |
||||
|
} |
||||
|
|
||||
|
|
||||
|
// 导出 create 创建后的实例
|
||||
|
export default server; |
@ -0,0 +1,37 @@ |
|||||
|
/** |
||||
|
* @param { Object } options |
||||
|
* @param { String } options.url 请求地址 |
||||
|
* @param { String } options.api 请求接口 |
||||
|
* @param { String } options.filePath 文件路径 |
||||
|
* @param { Function } options.onProgressCallBack 上传进度回调 |
||||
|
* @param { Object } options.formData 请求参数 |
||||
|
* @returns { Promise } |
||||
|
* |
||||
|
* */ |
||||
|
export const uploadFile = ({ url = __API__, api = '/Admino/AdminUser/uploadImgs', filePath, onProgress, formData = {} }) => { |
||||
|
return new Promise((rs,rj)=>{ |
||||
|
let uploadTask = wx.uploadFile({ |
||||
|
url: url + api, |
||||
|
filePath, |
||||
|
formData, |
||||
|
name:'file', |
||||
|
success: res=>{ |
||||
|
if (res.statusCode >= 200 && res.statusCode < 300) { |
||||
|
let _json = res?.data || '' |
||||
|
let _data = JSON.parse(_json); |
||||
|
if(_data?.scode){ |
||||
|
rs(_data?.data); |
||||
|
}else{ |
||||
|
rj(_data) |
||||
|
} |
||||
|
|
||||
|
} else { |
||||
|
rj(res) |
||||
|
} |
||||
|
}, |
||||
|
fail: rj |
||||
|
}) |
||||
|
|
||||
|
uploadTask.onProgressUpdate(onProgress) |
||||
|
}) |
||||
|
} |
@ -0,0 +1,5 @@ |
|||||
|
// iconfont 圆圈白勾成功 () |
||||
|
@mixin circleSuccess { |
||||
|
font-family: 'circleSuccess'; |
||||
|
src: url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAALgAAsAAAAABqwAAAKRAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHFQGYACCcAqBJIE5ATYCJAMICwYABCAFhGcHMxv4BcgekiSBOox5QEIkAShQPHytoe/v7YVZIWoiB6jiSGV8HMhwna3ylUBCd25yLrOx2ixQVN+NkAtJ2y+nGSl0wOqFHPB5QMXkyO+mdp/Mok//czm+uwLaIB/A25PG2tSmAwuwlx1GYy/CXkwN0yu/wgBeI9BgURbPnaKKBhBwx1IdhPAmqoMsPe5kkQX+3CHLMFwn1AydmsUXJek5waf/fvyzHP4kZUFkHd0WCmD3Zyl7FI/VMMU3T8sVwN0SShSYBWTirDtwwEs0Ubw0GLwNw9ws+FlWbqsXh9YI9teJ1CYwBLnPxNP8R01NIMfaJcDJpCak/iB2vOnuTjFHmu/vmRONt7fM4YabG29bU8NpZeHY7eb7+vvkh+8iNVw07OasuIekLkc7M/XOtDu6LiDLsVL9dqbLcdHwPNf93EJP+8d6aVpK6U9mOQ3PRfmu3ZbY//vOL+9IqpYzdmwAKhF68FY8/c/9PPwfs7sDV379GzP4fja474XDTNSd0BD8vQYvs6oi80RSRkdqIFma5EtokG4qwtLhbaqy8y4joU7nvZpqDWZQqDOMZPI0lBotQ406q9BgRuHsRp1MXiLXY9wYgNBmEZIWX6HQ5gTJ5Hso9fiEGm3+ocFFNC/XaDz4fIJYigTIDUKZN3SsFNQTrUNir8qSOm8TIrYM3TA2KqYcLkY6InOMsPvEOEoxxMTQYBHdDamqAU1iOBFPoyRKzbToaNz0kSje0EA+AmFRiADiDIJkPIMOW3xa/L06iKiXikUGIk0BwiZD4lCsKDEDkGKpPqjkQVax9RHFoSgMwggIaaAi3glRqQyQ2dzJCeFRUaQJPlOaaImHh0qjtpdrf4/DKhCqFLJJof5KQrooGloDAAAAAA==') format('woff2'); |
||||
|
} |
@ -0,0 +1,101 @@ |
|||||
|
@charset "UTF-8"; |
||||
|
/* 水平flex */ |
||||
|
@mixin ctf($justtify: flex-start){ |
||||
|
display: flex; |
||||
|
align-items: center; |
||||
|
justify-content: $justtify; |
||||
|
} |
||||
|
|
||||
|
/* 文字样式 */ |
||||
|
@mixin flcw($size: 28upx, $height: 40upx, $color: #333, $weight: 400){ |
||||
|
font-size: $size; |
||||
|
line-height: $height; |
||||
|
color: $color; |
||||
|
font-weight: $weight; |
||||
|
} |
||||
|
|
||||
|
@mixin tHide($line: 1) { |
||||
|
display: -webkit-box; |
||||
|
word-break: break-all; |
||||
|
text-overflow: ellipsis; |
||||
|
overflow: hidden; |
||||
|
-webkit-box-orient: vertical; |
||||
|
-webkit-line-clamp:$line; |
||||
|
} |
||||
|
|
||||
|
@mixin isPd($height: 0){ |
||||
|
padding-bottom: $height; |
||||
|
padding-bottom: calc( $height + constant(safe-area-inset-bottom)); /* 兼容 iOS < 11.2 */ |
||||
|
padding-bottom: calc( $height + env(safe-area-inset-bottom)); /* 兼容 iOS >= 11.2 */ |
||||
|
} |
||||
|
|
||||
|
@mixin fBot{ |
||||
|
position: fixed; |
||||
|
left: 0; |
||||
|
bottom: 0; |
||||
|
width: 100%; |
||||
|
padding: 10upx 20upx; |
||||
|
@include isPd(10upx); |
||||
|
} |
||||
|
|
||||
|
@mixin cirBtn($color: #FF873D){ |
||||
|
text-align: center; |
||||
|
border-radius: 56upx; |
||||
|
background: $color; |
||||
|
@include flcw(32upx, 92upx, #fff, 500); |
||||
|
} |
||||
|
|
||||
|
@mixin clearBtn{ |
||||
|
margin: 0; |
||||
|
padding: 0; |
||||
|
line-height: 0; |
||||
|
background-color: transparent; |
||||
|
border-radius: 0; |
||||
|
&::after{ |
||||
|
position: unset !important; |
||||
|
border: unset; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@mixin FixedLineBtn($color: #FF873D) { |
||||
|
position: fixed; |
||||
|
left: 0; |
||||
|
bottom: 0; |
||||
|
width: 100%; |
||||
|
padding-top: 18upx; |
||||
|
padding-bottom: 20upx; |
||||
|
padding-bottom: calc( 20upx + constant(safe-area-inset-bottom)); /* 兼容 iOS < 11.2 */ |
||||
|
padding-bottom: calc( 20upx + env(safe-area-inset-bottom)); /* 兼容 iOS >= 11.2 */ |
||||
|
border-top: 2upx solid #D8D8D8; |
||||
|
background-color: #fff; |
||||
|
>view{ |
||||
|
margin: 0 auto; |
||||
|
width: 702upx; |
||||
|
height: 88upx; |
||||
|
line-height: 88upx; |
||||
|
text-align: center; |
||||
|
font-size: 32upx; |
||||
|
border-radius: 44upx; |
||||
|
color: #fff; |
||||
|
background-color: $color; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@mixin lineBtn($color: #FF873D){ |
||||
|
margin: 0 auto; |
||||
|
width: 702upx; |
||||
|
text-align: center; |
||||
|
border-radius: 44upx; |
||||
|
background-color: $color; |
||||
|
@include flcw(32upx, 88upx, #fff, 500); |
||||
|
} |
||||
|
|
||||
|
@mixin fixedMask { |
||||
|
position: fixed; |
||||
|
left: 0; |
||||
|
top: 0; |
||||
|
right: 0; |
||||
|
bottom: 0; |
||||
|
width: 100%; |
||||
|
background-color: rgba(0, 0, 0, .5); |
||||
|
} |
@ -1,103 +1,5 @@ |
|||||
/* uniapp 全局样式 */ |
|
||||
$mColor: #009874; |
|
||||
|
|
||||
/* 水平flex */ |
|
||||
@mixin ctf($justtify: flex-start){ |
|
||||
display: flex; |
|
||||
align-items: center; |
|
||||
justify-content: $justtify; |
|
||||
} |
|
||||
|
|
||||
/* 文字样式 */ |
|
||||
@mixin flcw($size: 28upx, $height: 40upx, $color: #333, $weight: 400){ |
|
||||
font-size: $size; |
|
||||
line-height: $height; |
|
||||
color: $color; |
|
||||
font-weight: $weight; |
|
||||
} |
|
||||
|
|
||||
@mixin tHide($line: 1) { |
|
||||
display: -webkit-box; |
|
||||
word-break: break-all; |
|
||||
text-overflow: ellipsis; |
|
||||
overflow: hidden; |
|
||||
-webkit-box-orient: vertical; |
|
||||
-webkit-line-clamp:$line; |
|
||||
} |
|
||||
|
|
||||
@mixin isPd($height: 0){ |
|
||||
padding-bottom: $height; |
|
||||
padding-bottom: calc( $height + constant(safe-area-inset-bottom)); /* 兼容 iOS < 11.2 */ |
|
||||
padding-bottom: calc( $height + env(safe-area-inset-bottom)); /* 兼容 iOS >= 11.2 */ |
|
||||
} |
|
||||
|
|
||||
@mixin fBot{ |
|
||||
position: fixed; |
|
||||
left: 0; |
|
||||
bottom: 0; |
|
||||
width: 100%; |
|
||||
padding: 10upx 20upx; |
|
||||
@include isPd(10upx); |
|
||||
} |
|
||||
|
@use '@/styles/methods.scss' as *; |
||||
|
@use '@/styles/iconfonts.scss' as *; |
||||
|
|
||||
@mixin cirBtn($color: #FF873D){ |
|
||||
text-align: center; |
|
||||
border-radius: 56upx; |
|
||||
background: $color; |
|
||||
@include flcw(32upx, 92upx, #fff, 500); |
|
||||
} |
|
||||
|
|
||||
@mixin clearBtn{ |
|
||||
margin: 0; |
|
||||
padding: 0; |
|
||||
line-height: 0; |
|
||||
background-color: transparent; |
|
||||
border-radius: 0; |
|
||||
&::after{ |
|
||||
position: unset !important; |
|
||||
border: unset; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
@mixin FixedLineBtn($color: #FF873D) { |
|
||||
position: fixed; |
|
||||
left: 0; |
|
||||
bottom: 0; |
|
||||
width: 100%; |
|
||||
padding-top: 18upx; |
|
||||
padding-bottom: 20upx; |
|
||||
padding-bottom: calc( 20upx + constant(safe-area-inset-bottom)); /* 兼容 iOS < 11.2 */ |
|
||||
padding-bottom: calc( 20upx + env(safe-area-inset-bottom)); /* 兼容 iOS >= 11.2 */ |
|
||||
border-top: 2upx solid #D8D8D8; |
|
||||
background-color: #fff; |
|
||||
>view{ |
|
||||
margin: 0 auto; |
|
||||
width: 702upx; |
|
||||
height: 88upx; |
|
||||
line-height: 88upx; |
|
||||
text-align: center; |
|
||||
font-size: 32upx; |
|
||||
border-radius: 44upx; |
|
||||
color: #fff; |
|
||||
background-color: $color; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
@mixin lineBtn($color: #FF873D){ |
|
||||
margin: 0 auto; |
|
||||
width: 702upx; |
|
||||
text-align: center; |
|
||||
border-radius: 44upx; |
|
||||
background-color: $color; |
|
||||
@include flcw(32upx, 88upx, #fff, 500); |
|
||||
} |
|
||||
|
|
||||
@mixin fixedMask { |
|
||||
position: fixed; |
|
||||
left: 0; |
|
||||
top: 0; |
|
||||
right: 0; |
|
||||
bottom: 0; |
|
||||
width: 100%; |
|
||||
background-color: rgba(0, 0, 0, .5); |
|
||||
} |
|
||||
|
/* uniapp 全局样式 */ |
||||
|
$mColor: skyblue; |
@ -0,0 +1,100 @@ |
|||||
|
// 路由跳转
|
||||
|
export const routeTo = (url = '', type = 'nT', delta = 1) => { |
||||
|
if(!url)return uni.navigateBack({ delta }); |
||||
|
switch(type){ |
||||
|
case 'nT': uni.navigateTo({ url, fail: _=> uni.switchTab({ url }) }); |
||||
|
break |
||||
|
case 'rT': uni.redirectTo({ url, fail: _=> uni.switchTab({ url }) }); |
||||
|
break |
||||
|
case 'rL': uni.reLaunch({ url, fail: _=> uni.switchTab({ url }) }); |
||||
|
break |
||||
|
case 'sT': uni.switchTab({ url, fail: _=> uni.navigateTo({ url }) }); |
||||
|
break |
||||
|
case 'nB': uni.navigateBack({ delta }); |
||||
|
break |
||||
|
default: uni.navigateBack({ delta: 1 }); |
||||
|
break |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
export const showModal = ({ |
||||
|
title = '提示', |
||||
|
content = '', |
||||
|
showCancel = false, |
||||
|
cancelText = '取消', |
||||
|
confirmText = '确定', |
||||
|
confirmColor = '#10367A', |
||||
|
success, |
||||
|
fail, |
||||
|
complete |
||||
|
}) => { |
||||
|
uni.showModal({ |
||||
|
title, |
||||
|
content, |
||||
|
showCancel, |
||||
|
cancelText, |
||||
|
confirmColor, |
||||
|
confirmText, |
||||
|
success, |
||||
|
fail, |
||||
|
complete |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
export function showNone(txt, duration=1500){ |
||||
|
uni.showToast({ |
||||
|
mask: true, |
||||
|
title: txt, |
||||
|
icon: 'none', |
||||
|
duration, |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
export function debounce(func, wait, immediate) { |
||||
|
let timeout, args, context, timestamp, result; |
||||
|
const later = function() { |
||||
|
// 据上一次触发时间间隔
|
||||
|
const last = +new Date() - timestamp; |
||||
|
// 上次被包装函数被调用时间间隔last小于设定时间间隔wait
|
||||
|
if (last < wait && last > 0) { |
||||
|
timeout = setTimeout(later, wait - last); |
||||
|
} else { |
||||
|
timeout = null; |
||||
|
// 如果设定为immediate===true,因为开始边界已经调用过了此处无需调用
|
||||
|
if (!immediate) { |
||||
|
result = func.apply(context, args); |
||||
|
if (!timeout) context = args = null; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
return function(...args) { |
||||
|
context = this; |
||||
|
timestamp = +new Date(); |
||||
|
const callNow = immediate && !timeout; |
||||
|
// 如果延时不存在,重新设定延时
|
||||
|
if (!timeout) timeout = setTimeout(later, wait); |
||||
|
if (callNow) { |
||||
|
result = func.apply(context, args); |
||||
|
context = args = null; |
||||
|
} |
||||
|
return result; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
export function jsonStr(data){ |
||||
|
return encodeURIComponent(JSON.stringify(data)) |
||||
|
} |
||||
|
|
||||
|
export function jsonPar(json){ |
||||
|
return JSON.parse(decodeURIComponent(decodeURIComponent(json))) |
||||
|
} |
||||
|
|
||||
|
|
||||
|
export default { |
||||
|
routeTo, |
||||
|
showModal, |
||||
|
showNone, |
||||
|
debounce, |
||||
|
jsonStr, |
||||
|
jsonPar |
||||
|
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue