Browse Source

init api logic && scss

dev
刘嘉炜 1 week ago
parent
commit
2a68a3cbdc
  1. 3
      envs/.env.development
  2. 3
      envs/.env.production
  3. 1
      package.json
  4. 5
      src/api/index.js
  5. 37
      src/api/loading.js
  6. 89
      src/api/server.js
  7. 37
      src/api/upload.js
  8. 15
      src/pages/index/index.vue
  9. 5
      src/styles/iconfonts.scss
  10. 101
      src/styles/methods.scss
  11. 106
      src/uni.scss
  12. 100
      src/utils/polish.js

3
envs/.env.development

@ -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

3
envs/.env.production

@ -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

1
package.json

@ -54,6 +54,7 @@
"@dcloudio/uni-mp-xhs": "3.0.0-4060420250429001", "@dcloudio/uni-mp-xhs": "3.0.0-4060420250429001",
"@dcloudio/uni-quickapp-webview": "3.0.0-4060420250429001", "@dcloudio/uni-quickapp-webview": "3.0.0-4060420250429001",
"jsonc-parser": "^3.3.1", "jsonc-parser": "^3.3.1",
"uni-ajax": "^2.5.1",
"vue": "^3.4.21", "vue": "^3.4.21",
"vue-i18n": "^9.1.9" "vue-i18n": "^9.1.9"
}, },

5
src/api/index.js

@ -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 }); // 登录

37
src/api/loading.js

@ -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

89
src/api/server.js

@ -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;

37
src/api/upload.js

@ -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)
})
}

15
src/pages/index/index.vue

@ -2,19 +2,30 @@
import { onLoad } from '@dcloudio/uni-app'; import { onLoad } from '@dcloudio/uni-app';
import { deepClone } from "@/utils"; import { deepClone } from "@/utils";
import { accAdd } from "@/utils/calculation"; import { accAdd } from "@/utils/calculation";
import { stadiumFind } from "@/api";
onLoad(() => { onLoad(() => {
console.log('deepClone', deepClone({ a: 1, b: { c: 2 } })); console.log('deepClone', deepClone({ a: 1, b: { c: 2 } }));
console.log('accAdd', accAdd(0.1, 0.2)); console.log('accAdd', accAdd(0.1, 0.2));
stadiumFind({ data: { brand_id: 63 }, loading: '加载...' })
.then(res=>{
console.log('stadiumFind', res);
})
}); });
</script> </script>
<template> <template>
<view class="index-index">hello</view>
<view class="index-index">hello &#xe605;</view>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
@font-face{
@include circleSuccess;
}
.index-index{ .index-index{
color: $mColor;
text-align: center;
@include flcw(28upx, 32upx, $mColor, 500);
font-family: circleSuccess;
} }
</style> </style>

5
src/styles/iconfonts.scss

@ -0,0 +1,5 @@
// iconfont 圆圈白勾成功 (&#xe605;)
@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');
}

101
src/styles/methods.scss

@ -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);
}

106
src/uni.scss

@ -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;

100
src/utils/polish.js

@ -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
}
Loading…
Cancel
Save