15 changed files with 1374 additions and 148 deletions
Split View
Diff Options
-
32App.vue
-
42apis/loginApi.js
-
29enums/index.js
-
6pages.json
-
35pages/agreement/index.vue
-
271pages/login/index.vue
-
126store/index.js
-
31uni_modules/uni-easyinput/changelog.md
-
56uni_modules/uni-easyinput/components/uni-easyinput/common.js
-
461uni_modules/uni-easyinput/components/uni-easyinput/uni-easyinput.vue
-
90uni_modules/uni-easyinput/package.json
-
11uni_modules/uni-easyinput/readme.md
-
84utils/hook.js
-
215utils/http/http.js
-
33utils/http/index.js
@ -1,18 +1,24 @@ |
|||
<script> |
|||
export default { |
|||
onLaunch: function() { |
|||
console.log('App Launch') |
|||
}, |
|||
onShow: function() { |
|||
console.log('App Show') |
|||
}, |
|||
onHide: function() { |
|||
console.log('App Hide') |
|||
} |
|||
} |
|||
import { go2 } from '@/utils/hook.js' |
|||
import store from '@/store/index.js' |
|||
export default { |
|||
onLaunch: function () { |
|||
const token = store.state.qnToken |
|||
if (!token) { |
|||
go2('login') |
|||
} |
|||
console.log('App launched') |
|||
}, |
|||
onShow: function () { |
|||
console.log('App Show') |
|||
}, |
|||
onHide: function () { |
|||
console.log('App Hide') |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style> |
|||
/*每个页面公共css */ |
|||
@import url("./common/css/reset.scss"); |
|||
/*每个页面公共css */ |
|||
@import url('./common/css/reset.scss'); |
|||
</style> |
|||
@ -0,0 +1,42 @@ |
|||
import http from '../utils/http/index.js' |
|||
|
|||
/** |
|||
* 手机登录获取验证码接口 |
|||
* @param {object} data 获取验证码参数 |
|||
* @returns 获取验证码结果 |
|||
* swagger:http://api-ops-uec-test.qniao.cn/uec/swagger-ui/index.html?urls.primaryName=CustomerApi#/%E7%99%BB%E5%BD%95%E8%AE%A4%E8%AF%81/authorizeByCaptchaUsingPOST
|
|||
*/ |
|||
export const getAuthCaptcha = (data) => { |
|||
return http.post({ |
|||
url: '/uec/get/auth-captcha', |
|||
data |
|||
}) |
|||
} |
|||
|
|||
/** |
|||
* 手机验证码登录,返回临时token |
|||
* @param {object} data 登录参数 |
|||
* @returns {object} 返回参数 {token: '', userId: ''} |
|||
* |
|||
* swagger:http://api-ops-uec-test.qniao.cn/uec/swagger-ui/index.html?urls.primaryName=CustomerApi#/%E7%99%BB%E5%BD%95%E8%AE%A4%E8%AF%81/authorizeByCaptchaUsingPOST
|
|||
*/ |
|||
export const loginByPhone = (data) => { |
|||
return http.post({ |
|||
url: '/uec/authorize/by-captcha', |
|||
data |
|||
}) |
|||
} |
|||
|
|||
/** |
|||
* 手机验证码登录,返回临时token |
|||
* @param {object} data 登录参数 |
|||
* @returns {string} 返回参数 token:string |
|||
* |
|||
* swagger:http://api-ops-yyt-test.qniao.cn/yyt-uec/swagger-ui/index.html?urls.primaryName=CustomerApi#/%E7%99%BB%E5%BD%95%E8%AE%A4%E8%AF%81/getProductLineTokenByLoginTokenUsingPOST
|
|||
*/ |
|||
export const getQnToken = (data) => { |
|||
return http.post({ |
|||
url: '/yyt-uec/authorize/get/product-line-token/by/login-token', |
|||
data |
|||
}) |
|||
} |
|||
@ -0,0 +1,29 @@ |
|||
/** |
|||
* 账号类型 |
|||
*/ |
|||
export const accountType = { |
|||
WX: 1, |
|||
PHONE: 2, |
|||
EMAIL: 3, |
|||
APPLEID: 4, |
|||
CUSTOM: 5 |
|||
} |
|||
|
|||
/** |
|||
* 验证码用途 |
|||
*/ |
|||
export const codePurpose = { |
|||
CERTIFICATION: 1, |
|||
RESET_LOGIN_PASSWORD: 2, |
|||
RESET_PHONE: 3, |
|||
BIND_BANK_CARD: 4, |
|||
RESET_CREDIT_PASSWORD: 5 |
|||
} |
|||
|
|||
/** |
|||
* 可验证账号类型 |
|||
*/ |
|||
export const verificationType = { |
|||
PHONE: 1, |
|||
EMAIL: 2 |
|||
} |
|||
@ -0,0 +1,35 @@ |
|||
<template> |
|||
<view class="content">agreement</view> |
|||
</template> |
|||
|
|||
<script> |
|||
export default {} |
|||
</script> |
|||
|
|||
<style> |
|||
.content { |
|||
display: flex; |
|||
flex-direction: column; |
|||
align-items: center; |
|||
justify-content: center; |
|||
} |
|||
|
|||
.logo { |
|||
height: 200rpx; |
|||
width: 200rpx; |
|||
margin-top: 200rpx; |
|||
margin-left: auto; |
|||
margin-right: auto; |
|||
margin-bottom: 50rpx; |
|||
} |
|||
|
|||
.text-area { |
|||
display: flex; |
|||
justify-content: center; |
|||
} |
|||
|
|||
.title { |
|||
font-size: 36rpx; |
|||
color: #8f8f94; |
|||
} |
|||
</style> |
|||
@ -1,15 +1,270 @@ |
|||
<template> |
|||
<view> |
|||
login |
|||
</view> |
|||
<view> |
|||
<uni-nav-bar |
|||
:fixed="true" |
|||
color="#ffffff" |
|||
background-color="#ffffff" |
|||
:status-bar="true" |
|||
:border="false" |
|||
left-icon="closeempty" |
|||
@clickLeft="close" |
|||
/> |
|||
<view class="logo_area"> |
|||
<image class="logo" src="/static/logo.png"></image> |
|||
<text class="title">纸掌柜</text> |
|||
</view> |
|||
<view class="form"> |
|||
<view class="phone"> |
|||
<uni-easyinput |
|||
v-model="phoneNumber" |
|||
:inputBorder="false" |
|||
:placeholderStyle="'font-size:32rpx;'" |
|||
placeholder="请输入手机号码" |
|||
:maxlength="11" |
|||
/> |
|||
</view> |
|||
<view class="captcha"> |
|||
<uni-easyinput |
|||
v-model="captcha" |
|||
:inputBorder="false" |
|||
:placeholderStyle="'font-size:32rpx;'" |
|||
placeholder="请输入验证码" |
|||
:maxlength="6" |
|||
/> |
|||
<view v-show="timer > 0" class="timer_area"> |
|||
<text class="timer">{{ `(${timer}S后) ` }}</text> |
|||
<text class="timer_text">重新获取</text> |
|||
</view> |
|||
<text v-show="timer <= 0" class="code" @click="getCode"> |
|||
获取验证码 |
|||
</text> |
|||
</view> |
|||
<view |
|||
class="login-button" |
|||
@click="login" |
|||
:style="{ opacity: disabled ? '0.5' : '' }" |
|||
> |
|||
登录 |
|||
</view> |
|||
</view> |
|||
<view class="agreement_area"> |
|||
<checkbox-group @change="onCheck"> |
|||
<checkbox |
|||
value="cb" |
|||
:checked="checked" |
|||
color="#000000" |
|||
style="transform: scale(0.7)" |
|||
/> |
|||
</checkbox-group> |
|||
<view class="agreement"> |
|||
已阅读并同意纸掌柜 |
|||
<text class="agreement_text" @click="jumpAgreement"> |
|||
《用户与隐私协议》 |
|||
</text> |
|||
</view> |
|||
</view> |
|||
<!-- |
|||
<uni-easyinput v-model="captcha" placeholder="验证码" /> |
|||
<button @click="getCode">获取验证码</button> |
|||
<button @click="login">登录</button> --> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
export default { |
|||
|
|||
} |
|||
import { getAuthCaptcha, loginByPhone, getQnToken } from '@/apis/loginApi' |
|||
import { accountType, verificationType, codePurpose } from '@/enums/index.js' |
|||
import store from '@/store/index.js' |
|||
import { go2, back } from '@/utils/hook.js' |
|||
export default { |
|||
data() { |
|||
return { |
|||
phoneNumber: '', |
|||
captcha: '', |
|||
timer: 0, |
|||
checked: false |
|||
} |
|||
}, |
|||
methods: { |
|||
// 退出登录 |
|||
close() { |
|||
back() |
|||
}, |
|||
onCheck(e) { |
|||
if (e.detail.value.length > 0) { |
|||
this.checked = true |
|||
} else { |
|||
this.checked = false |
|||
} |
|||
}, |
|||
jumpAgreement() { |
|||
go2('agreement') |
|||
}, |
|||
// 获取验证码 |
|||
getCode() { |
|||
if (this.phoneNumber.trim() === '') { |
|||
uni.showToast({ |
|||
title: '请输入手机号码', |
|||
icon: 'none' |
|||
}) |
|||
return |
|||
} |
|||
if (this.phoneNumber.trim().length !== 11) { |
|||
uni.showToast({ |
|||
title: '请输入正确的手机号码', |
|||
icon: 'none' |
|||
}) |
|||
return |
|||
} |
|||
this.countdown() |
|||
getAuthCaptcha({ |
|||
purpose: codePurpose.CERTIFICATION, |
|||
verifiableAccount: this.phoneNumber, |
|||
verifiableAccountType: verificationType.PHONE |
|||
}).then((res) => { |
|||
console.log(res) |
|||
}) |
|||
}, |
|||
// 倒计时 |
|||
countdown() { |
|||
this.timer = 60 |
|||
let timer = setInterval(() => { |
|||
this.timer-- |
|||
if (this.timer <= 0) { |
|||
clearInterval(timer) |
|||
} |
|||
}, 1000) |
|||
}, |
|||
// 登录 |
|||
login() { |
|||
if (this.disabled) { |
|||
return |
|||
} |
|||
if (!this.checked) { |
|||
uni.showToast({ |
|||
title: '请同意用户与隐私协议', |
|||
icon: 'none' |
|||
}) |
|||
return |
|||
} |
|||
loginByPhone({ |
|||
accountType: accountType.PHONE, |
|||
account: this.phoneNumber, |
|||
captcha: this.captcha |
|||
}).then((res) => { |
|||
if (res) { |
|||
store.commit('setUecToken', res.token) |
|||
getQnToken({ loginToken: res.token }).then((token) => { |
|||
if (token) { |
|||
store.commit('setToken', token) |
|||
// 登录成功先查看是否有下一个页面 |
|||
const nextPage = store.state.nextPage |
|||
if (nextPage.name) { |
|||
go2(nextPage.name, nextPage.data) |
|||
} else { |
|||
go2('mine') |
|||
} |
|||
store.commit('removeNextPage') |
|||
} |
|||
}) |
|||
} |
|||
}) |
|||
} |
|||
}, |
|||
computed: { |
|||
disabled() { |
|||
return ( |
|||
this.phoneNumber.trim() === '' || |
|||
this.phoneNumber.trim().length != 11 || |
|||
this.captcha.trim() === '' |
|||
) |
|||
} |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style> |
|||
|
|||
<style lang="scss"> |
|||
.logo_area { |
|||
margin-top: 187rpx; |
|||
width: 750rpx; |
|||
height: 100rpx; |
|||
display: flex; |
|||
justify-content: center; |
|||
align-items: center; |
|||
.logo { |
|||
width: 100rpx; |
|||
height: 100rpx; |
|||
margin-right: 20rpx; |
|||
} |
|||
.title { |
|||
opacity: 0.8; |
|||
font-size: 60rpx; |
|||
color: #000000; |
|||
letter-spacing: 9rpx; |
|||
text-align: center; |
|||
font-weight: 400; |
|||
} |
|||
} |
|||
.form { |
|||
width: 750rpx; |
|||
margin-top: 280rpx; |
|||
padding: 0 64rpx; |
|||
.phone { |
|||
width: 622rpx; |
|||
border-bottom: 2rpx solid #e0e0e0; |
|||
} |
|||
.captcha { |
|||
margin-top: 44rpx; |
|||
width: 622rpx; |
|||
border-bottom: 2rpx solid #e0e0e0; |
|||
display: flex; |
|||
justify-content: space-between; |
|||
align-items: center; |
|||
.timer_area { |
|||
width: auto; |
|||
flex: 0 0 auto; |
|||
.timer { |
|||
font-size: 32rpx; |
|||
color: #007aff; |
|||
} |
|||
.timer_area { |
|||
font-size: 32rpx; |
|||
color: #999999; |
|||
} |
|||
} |
|||
.code { |
|||
width: 160rpx; |
|||
font-size: 32rpx; |
|||
color: #007aff; |
|||
flex: 0 0 auto; |
|||
} |
|||
} |
|||
.login-button { |
|||
font-size: 32rpx; |
|||
margin-top: 92rpx; |
|||
width: 622rpx; |
|||
height: 86rpx; |
|||
border-radius: 42px; |
|||
display: flex; |
|||
justify-content: center; |
|||
align-items: center; |
|||
background-color: #007aff; |
|||
color: #ffffff; |
|||
} |
|||
} |
|||
.agreement_area { |
|||
position: fixed; |
|||
bottom: 108rpx; |
|||
width: 750rpx; |
|||
display: flex; |
|||
justify-content: center; |
|||
align-items: center; |
|||
.agreement { |
|||
font-size: 24rpx; |
|||
color: #555555; |
|||
.agreement_text { |
|||
font-size: 24rpx; |
|||
color: #007aff; |
|||
} |
|||
} |
|||
} |
|||
</style> |
|||
@ -1,7 +1,131 @@ |
|||
import Vue from 'vue' |
|||
import Vuex from 'vuex' |
|||
import { isObject } from '@/utils/is' |
|||
|
|||
let qnToken = null, |
|||
userInfo = null, |
|||
supplierInfo = null, |
|||
uecToken = null |
|||
try { |
|||
uecToken = uni.getStorageSync('uecToken') |
|||
qnToken = uni.getStorageSync('qnToken') |
|||
userInfo = uni.getStorageSync('userInfo') |
|||
if (userInfo) { |
|||
userInfo = JSON.parse(userInfo) |
|||
} |
|||
supplierInfo = uni.getStorageSync('supplierInfo') |
|||
if (supplierInfo) { |
|||
supplierInfo = JSON.parse(supplierInfo) |
|||
} |
|||
} catch (e) { |
|||
console.error('初始化错误:', e) |
|||
} |
|||
|
|||
Vue.use(Vuex) |
|||
const store = new Vuex.Store({ |
|||
state: {} |
|||
state: { |
|||
uecToken: uecToken || '', |
|||
qnToken: qnToken || '', // token
|
|||
userInfo: userInfo || {}, // 用户信息
|
|||
supplierInfo: supplierInfo || {}, // 纸盘商信息
|
|||
nextPage: { |
|||
name: '', |
|||
data: {} |
|||
} |
|||
}, |
|||
mutations: { |
|||
setUecToken(state, token) { |
|||
try { |
|||
uni.setStorageSync('uecToken', token) |
|||
state.uecToken = token |
|||
} catch (e) { |
|||
console.error('更改uecToken失败:', e) |
|||
} |
|||
}, |
|||
removeUecToken(state) { |
|||
try { |
|||
uni.removeStorageSync('uecToken') |
|||
state.uecToken = '' |
|||
} catch (e) { |
|||
console.error('删除uecToken失败:', e) |
|||
} |
|||
}, |
|||
setToken(state, token) { |
|||
try { |
|||
uni.setStorageSync('qnToken', token) |
|||
state.qnToken = token |
|||
} catch (e) { |
|||
console.error('更改token失败:', e) |
|||
} |
|||
}, |
|||
removeToken(state) { |
|||
try { |
|||
uni.removeStorageSync('qnToken') |
|||
state.qnToken = '' |
|||
} catch (e) { |
|||
console.error('删除token失败:', e) |
|||
} |
|||
}, |
|||
setUserInfo(state, userInfo) { |
|||
if (!isObject(userInfo)) { |
|||
console.error('userInfo必须是对象') |
|||
return |
|||
} |
|||
try { |
|||
uni.setStorageSync('userInfo', JSON.stringify(userInfo)) |
|||
state.userInfo = userInfo |
|||
} catch (e) { |
|||
console.error('更改userInfo失败:', e) |
|||
} |
|||
}, |
|||
removeUserInfo(state) { |
|||
try { |
|||
uni.removeStorageSync('userInfo') |
|||
state.userInfo = {} |
|||
} catch (e) { |
|||
console.error('删除userInfo失败:', e) |
|||
} |
|||
}, |
|||
setSupplierInfo(state, supplierInfo) { |
|||
if (!isObject(supplierInfo)) { |
|||
console.error('supplierInfo必须是对象') |
|||
return |
|||
} |
|||
try { |
|||
uni.setStorageSync('supplierInfo', JSON.stringify(supplierInfo)) |
|||
state.supplierInfo = supplierInfo |
|||
} catch (e) { |
|||
console.error('更改supplierInfo失败:', e) |
|||
} |
|||
}, |
|||
removeSupplierInfo(state) { |
|||
try { |
|||
uni.removeStorageSync('supplierInfo') |
|||
state.supplierInfo = {} |
|||
} catch (e) { |
|||
console.error('删除supplierInfo失败:', e) |
|||
} |
|||
}, |
|||
setNextPage(state, nextPage) { |
|||
if (!isObject(nextPage)) { |
|||
console.error('nextPage必须是对象') |
|||
return |
|||
} |
|||
state.nextPage.name = nextPage.name || '' |
|||
state.nextPage.data = nextPage.data || {} |
|||
}, |
|||
removeNextPage(state) { |
|||
state.nextPage.name = '' |
|||
state.nextPage.data = {} |
|||
} |
|||
}, |
|||
actions: { |
|||
logout({ commit }) { |
|||
commit('removeUecToken') |
|||
commit('removeToken') |
|||
commit('removeUserInfo') |
|||
commit('removeSupplierInfo') |
|||
} |
|||
} |
|||
}) |
|||
export default store |
|||
@ -0,0 +1,31 @@ |
|||
## 1.0.0(2021-11-19) |
|||
- 优化 组件UI,并提供设计资源,详见:[https://uniapp.dcloud.io/component/uniui/resource](https://uniapp.dcloud.io/component/uniui/resource) |
|||
- 文档迁移,详见:[https://uniapp.dcloud.io/component/uniui/uni-easyinput](https://uniapp.dcloud.io/component/uniui/uni-easyinput) |
|||
## 0.1.4(2021-08-20) |
|||
- 修复 在 uni-forms 的动态表单中默认值校验不通过的 bug |
|||
## 0.1.3(2021-08-11) |
|||
- 修复 在 uni-forms 中重置表单,错误信息无法清除的问题 |
|||
## 0.1.2(2021-07-30) |
|||
- 优化 vue3下事件警告的问题 |
|||
## 0.1.1 |
|||
- 优化 errorMessage 属性支持 Boolean 类型 |
|||
## 0.1.0(2021-07-13) |
|||
- 组件兼容 vue3,如何创建vue3项目,详见 [uni-app 项目支持 vue3 介绍](https://ask.dcloud.net.cn/article/37834) |
|||
## 0.0.16(2021-06-29) |
|||
- 修复 confirmType 属性(仅 type="text" 生效)导致多行文本框无法换行的 bug |
|||
## 0.0.15(2021-06-21) |
|||
- 修复 passwordIcon 属性拼写错误的 bug |
|||
## 0.0.14(2021-06-18) |
|||
- 新增 passwordIcon 属性,当type=password时是否显示小眼睛图标 |
|||
- 修复 confirmType 属性不生效的问题 |
|||
## 0.0.13(2021-06-04) |
|||
- 修复 disabled 状态可清出内容的 bug |
|||
## 0.0.12(2021-05-12) |
|||
- 新增 组件示例地址 |
|||
## 0.0.11(2021-05-07) |
|||
- 修复 input-border 属性不生效的问题 |
|||
## 0.0.10(2021-04-30) |
|||
- 修复 ios 遮挡文字、显示一半的问题 |
|||
## 0.0.9(2021-02-05) |
|||
- 调整为uni_modules目录规范 |
|||
- 优化 兼容 nvue 页面 |
|||
@ -0,0 +1,56 @@ |
|||
/** |
|||
* @desc 函数防抖 |
|||
* @param func 目标函数 |
|||
* @param wait 延迟执行毫秒数 |
|||
* @param immediate true - 立即执行, false - 延迟执行 |
|||
*/ |
|||
export const debounce = function(func, wait = 1000, immediate = true) { |
|||
let timer; |
|||
console.log(1); |
|||
return function() { |
|||
console.log(123); |
|||
let context = this, |
|||
args = arguments; |
|||
if (timer) clearTimeout(timer); |
|||
if (immediate) { |
|||
let callNow = !timer; |
|||
timer = setTimeout(() => { |
|||
timer = null; |
|||
}, wait); |
|||
if (callNow) func.apply(context, args); |
|||
} else { |
|||
timer = setTimeout(() => { |
|||
func.apply(context, args); |
|||
}, wait) |
|||
} |
|||
} |
|||
} |
|||
/** |
|||
* @desc 函数节流 |
|||
* @param func 函数 |
|||
* @param wait 延迟执行毫秒数 |
|||
* @param type 1 使用表时间戳,在时间段开始的时候触发 2 使用表定时器,在时间段结束的时候触发 |
|||
*/ |
|||
export const throttle = (func, wait = 1000, type = 1) => { |
|||
let previous = 0; |
|||
let timeout; |
|||
return function() { |
|||
let context = this; |
|||
let args = arguments; |
|||
if (type === 1) { |
|||
let now = Date.now(); |
|||
|
|||
if (now - previous > wait) { |
|||
func.apply(context, args); |
|||
previous = now; |
|||
} |
|||
} else if (type === 2) { |
|||
if (!timeout) { |
|||
timeout = setTimeout(() => { |
|||
timeout = null; |
|||
func.apply(context, args) |
|||
}, wait) |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,461 @@ |
|||
<template> |
|||
<view class="uni-easyinput" :class="{'uni-easyinput-error':msg}" :style="{color:inputBorder && msg?'#e43d33':styles.color}"> |
|||
<view class="uni-easyinput__content" :class="{'is-input-border':inputBorder ,'is-input-error-border':inputBorder && msg,'is-textarea':type==='textarea','is-disabled':disabled}" |
|||
:style="{'border-color':inputBorder && msg?'#dd524d':styles.borderColor,'background-color':disabled?styles.disableColor:''}"> |
|||
<uni-icons v-if="prefixIcon" class="content-clear-icon" :type="prefixIcon" color="#c0c4cc" @click="onClickIcon('prefix')"></uni-icons> |
|||
<textarea v-if="type === 'textarea'" class="uni-easyinput__content-textarea" :class="{'input-padding':inputBorder}" |
|||
:name="name" :value="val" :placeholder="placeholder" :placeholderStyle="placeholderStyle" :disabled="disabled" placeholder-class="uni-easyinput__placeholder-class" |
|||
:maxlength="inputMaxlength" :focus="focused" :autoHeight="autoHeight" @input="onInput" @blur="onBlur" @focus="onFocus" |
|||
@confirm="onConfirm"></textarea> |
|||
<input v-else :type="type === 'password'?'text':type" class="uni-easyinput__content-input" :style="{ |
|||
'padding-right':type === 'password' ||clearable || prefixIcon?'':'10px', |
|||
'padding-left':prefixIcon?'':'10px' |
|||
}" |
|||
:name="name" :value="val" :password="!showPassword && type === 'password'" :placeholder="placeholder" |
|||
:placeholderStyle="placeholderStyle" placeholder-class="uni-easyinput__placeholder-class" :disabled="disabled" :maxlength="inputMaxlength" :focus="focused" :confirmType="confirmType" @focus="onFocus" |
|||
@blur="onBlur" @input="onInput" @confirm="onConfirm" /> |
|||
<template v-if="type === 'password' && passwordIcon" > |
|||
<uni-icons v-if="val != '' " class="content-clear-icon" :class="{'is-textarea-icon':type==='textarea'}" :type="showPassword?'eye-slash-filled':'eye-filled'" |
|||
:size="18" color="#c0c4cc" @click="onEyes"></uni-icons> |
|||
</template> |
|||
<template v-else-if="suffixIcon"> |
|||
<uni-icons v-if="suffixIcon" class="content-clear-icon" :type="suffixIcon" color="#c0c4cc" @click="onClickIcon('suffix')"></uni-icons> |
|||
</template> |
|||
<template v-else> |
|||
<uni-icons class="content-clear-icon" :class="{'is-textarea-icon':type==='textarea'}" type="clear" :size="clearSize" |
|||
v-if="clearable && val && !disabled" color="#c0c4cc" @click="onClear"></uni-icons> |
|||
</template> |
|||
<slot name="right"></slot> |
|||
</view> |
|||
</view> |
|||
</template> |
|||
|
|||
<script> |
|||
// import { |
|||
// debounce, |
|||
// throttle |
|||
// } from './common.js' |
|||
/** |
|||
* Easyinput 输入框 |
|||
* @description 此组件可以实现表单的输入与校验,包括 "text" 和 "textarea" 类型。 |
|||
* @tutorial https://ext.dcloud.net.cn/plugin?id=3455 |
|||
* @property {String} value 输入内容 |
|||
* @property {String } type 输入框的类型(默认text) password/text/textarea/.. |
|||
* @value text 文本输入键盘 |
|||
* @value textarea 多行文本输入键盘 |
|||
* @value password 密码输入键盘 |
|||
* @value number 数字输入键盘,注意iOS上app-vue弹出的数字键盘并非9宫格方式 |
|||
* @value idcard 身份证输入键盘,信、支付宝、百度、QQ小程序 |
|||
* @value digit 带小数点的数字键盘 ,App的nvue页面、微信、支付宝、百度、头条、QQ小程序支持 |
|||
* @property {Boolean} clearable 是否显示右侧清空内容的图标控件,点击可清空输入框内容(默认true) |
|||
* @property {Boolean} autoHeight 是否自动增高输入区域,type为textarea时有效(默认true) |
|||
* @property {String } placeholder 输入框的提示文字 |
|||
* @property {String } placeholderStyle placeholder的样式(内联样式,字符串),如"color: #ddd" |
|||
* @property {Boolean} focus 是否自动获得焦点(默认false) |
|||
* @property {Boolean} disabled 是否禁用(默认false) |
|||
* @property {Number } maxlength 最大输入长度,设置为 -1 的时候不限制最大长度(默认140) |
|||
* @property {String } confirmType 设置键盘右下角按钮的文字,仅在type="text"时生效(默认done) |
|||
* @property {Number } clearSize 清除图标的大小,单位px(默认15) |
|||
* @property {String} prefixIcon 输入框头部图标 |
|||
* @property {String} suffixIcon 输入框尾部图标 |
|||
* @property {Boolean} trim 是否自动去除两端的空格 |
|||
* @value both 去除两端空格 |
|||
* @value left 去除左侧空格 |
|||
* @value right 去除右侧空格 |
|||
* @value start 去除左侧空格 |
|||
* @value end 去除右侧空格 |
|||
* @value all 去除全部空格 |
|||
* @value none 不去除空格 |
|||
* @property {Boolean} inputBorder 是否显示input输入框的边框(默认true) |
|||
* @property {Boolean} passwordIcon type=password时是否显示小眼睛图标 |
|||
* @property {Object} styles 自定义颜色 |
|||
* @event {Function} input 输入框内容发生变化时触发 |
|||
* @event {Function} focus 输入框获得焦点时触发 |
|||
* @event {Function} blur 输入框失去焦点时触发 |
|||
* @event {Function} confirm 点击完成按钮时触发 |
|||
* @event {Function} iconClick 点击图标时触发 |
|||
* @example <uni-easyinput v-model="mobile"></uni-easyinput> |
|||
*/ |
|||
|
|||
export default { |
|||
name: 'uni-easyinput', |
|||
emits:['click','iconClick','update:modelValue','input','focus','blur','confirm'], |
|||
model:{ |
|||
prop:'modelValue', |
|||
event:'update:modelValue' |
|||
}, |
|||
props: { |
|||
name: String, |
|||
value: [Number, String], |
|||
modelValue: [Number, String], |
|||
type: { |
|||
type: String, |
|||
default: 'text' |
|||
}, |
|||
clearable: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
autoHeight: { |
|||
type: Boolean, |
|||
default: false |
|||
}, |
|||
placeholder: String, |
|||
placeholderStyle: String, |
|||
focus: { |
|||
type: Boolean, |
|||
default: false |
|||
}, |
|||
disabled: { |
|||
type: Boolean, |
|||
default: false |
|||
}, |
|||
maxlength: { |
|||
type: [Number, String], |
|||
default: 140 |
|||
}, |
|||
confirmType: { |
|||
type: String, |
|||
default: 'done' |
|||
}, |
|||
clearSize: { |
|||
type: [Number, String], |
|||
default: 15 |
|||
}, |
|||
inputBorder: { |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
prefixIcon: { |
|||
type: String, |
|||
default: '' |
|||
}, |
|||
suffixIcon: { |
|||
type: String, |
|||
default: '' |
|||
}, |
|||
trim: { |
|||
type: [Boolean, String], |
|||
default: true |
|||
}, |
|||
passwordIcon:{ |
|||
type: Boolean, |
|||
default: true |
|||
}, |
|||
styles: { |
|||
type: Object, |
|||
default () { |
|||
return { |
|||
color: '#333', |
|||
disableColor: '#F7F6F6', |
|||
borderColor: '#e5e5e5' |
|||
} |
|||
} |
|||
}, |
|||
errorMessage:{ |
|||
type:[String,Boolean], |
|||
default:'' |
|||
} |
|||
}, |
|||
data() { |
|||
return { |
|||
focused: false, |
|||
errMsg: '', |
|||
val: '', |
|||
showMsg: '', |
|||
border: false, |
|||
isFirstBorder: false, |
|||
showClearIcon: false, |
|||
showPassword: false |
|||
}; |
|||
}, |
|||
computed: { |
|||
msg() { |
|||
return this.errorMessage || this.errMsg; |
|||
}, |
|||
// 因为uniapp的input组件的maxlength组件必须要数值,这里转为数值,用户可以传入字符串数值 |
|||
inputMaxlength() { |
|||
return Number(this.maxlength); |
|||
}, |
|||
}, |
|||
watch: { |
|||
value(newVal) { |
|||
if (this.errMsg) this.errMsg = '' |
|||
this.val = newVal |
|||
// fix by mehaotian is_reset 在 uni-forms 中定义 |
|||
if (this.form && this.formItem &&!this.is_reset) { |
|||
this.is_reset = false |
|||
this.formItem.setValue(newVal) |
|||
} |
|||
}, |
|||
modelValue(newVal) { |
|||
if (this.errMsg) this.errMsg = '' |
|||
this.val = newVal |
|||
if (this.form && this.formItem &&!this.is_reset) { |
|||
this.is_reset = false |
|||
this.formItem.setValue(newVal) |
|||
} |
|||
}, |
|||
focus(newVal) { |
|||
this.$nextTick(() => { |
|||
this.focused = this.focus |
|||
}) |
|||
} |
|||
}, |
|||
created() { |
|||
if(!this.value){ |
|||
this.val = this.modelValue |
|||
} |
|||
if(!this.modelValue){ |
|||
this.val = this.value |
|||
} |
|||
this.form = this.getForm('uniForms') |
|||
this.formItem = this.getForm('uniFormsItem') |
|||
if (this.form && this.formItem) { |
|||
if (this.formItem.name) { |
|||
if(!this.is_reset){ |
|||
this.is_reset = false |
|||
this.formItem.setValue(this.val) |
|||
} |
|||
this.rename = this.formItem.name |
|||
this.form.inputChildrens.push(this) |
|||
} |
|||
} |
|||
}, |
|||
mounted() { |
|||
this.$nextTick(() => { |
|||
this.focused = this.focus |
|||
}) |
|||
}, |
|||
methods: { |
|||
/** |
|||
* 初始化变量值 |
|||
*/ |
|||
init() { |
|||
|
|||
}, |
|||
onClickIcon(type) { |
|||
this.$emit('iconClick', type) |
|||
}, |
|||
/** |
|||
* 获取父元素实例 |
|||
*/ |
|||
getForm(name = 'uniForms') { |
|||
let parent = this.$parent; |
|||
let parentName = parent.$options.name; |
|||
while (parentName !== name) { |
|||
parent = parent.$parent; |
|||
if (!parent) return false; |
|||
parentName = parent.$options.name; |
|||
} |
|||
return parent; |
|||
}, |
|||
|
|||
onEyes() { |
|||
this.showPassword = !this.showPassword |
|||
}, |
|||
onInput(event) { |
|||
let value = event.detail.value; |
|||
// 判断是否去除空格 |
|||
if (this.trim) { |
|||
if (typeof(this.trim) === 'boolean' && this.trim) { |
|||
value = this.trimStr(value) |
|||
} |
|||
if (typeof(this.trim) === 'string') { |
|||
value = this.trimStr(value, this.trim) |
|||
} |
|||
}; |
|||
if (this.errMsg) this.errMsg = '' |
|||
this.val = value |
|||
// TODO 兼容 vue2 |
|||
this.$emit('input', value); |
|||
// TODO 兼容 vue3 |
|||
this.$emit('update:modelValue',value) |
|||
}, |
|||
|
|||
onFocus(event) { |
|||
this.$emit('focus', event); |
|||
}, |
|||
onBlur(event) { |
|||
let value = event.detail.value; |
|||
this.$emit('blur', event); |
|||
}, |
|||
onConfirm(e) { |
|||
this.$emit('confirm', e.detail.value); |
|||
}, |
|||
onClear(event) { |
|||
this.val = ''; |
|||
// TODO 兼容 vue2 |
|||
this.$emit('input', ''); |
|||
// TODO 兼容 vue2 |
|||
// TODO 兼容 vue3 |
|||
this.$emit('update:modelValue','') |
|||
}, |
|||
fieldClick() { |
|||
this.$emit('click'); |
|||
}, |
|||
trimStr(str, pos = 'both') { |
|||
if (pos === 'both') { |
|||
return str.trim(); |
|||
} else if (pos === 'left') { |
|||
return str.trimLeft(); |
|||
} else if (pos === 'right') { |
|||
return str.trimRight(); |
|||
} else if (pos === 'start') { |
|||
return str.trimStart() |
|||
} else if (pos === 'end') { |
|||
return str.trimEnd() |
|||
} else if (pos === 'all') { |
|||
return str.replace(/\s+/g, ''); |
|||
} else if (pos === 'none') { |
|||
return str; |
|||
} |
|||
return str; |
|||
} |
|||
} |
|||
}; |
|||
</script> |
|||
|
|||
<style lang="scss" scoped> |
|||
$uni-error: #e43d33; |
|||
$uni-border-1: #DCDFE6 !default; |
|||
.uni-easyinput { |
|||
/* #ifndef APP-NVUE */ |
|||
width: 100%; |
|||
/* #endif */ |
|||
flex: 1; |
|||
position: relative; |
|||
text-align: left; |
|||
color: #333; |
|||
font-size: 14px; |
|||
} |
|||
|
|||
.uni-easyinput__content { |
|||
flex: 1; |
|||
/* #ifndef APP-NVUE */ |
|||
width: 100%; |
|||
display: flex; |
|||
box-sizing: border-box; |
|||
min-height: 36px; |
|||
/* #endif */ |
|||
flex-direction: row; |
|||
align-items: center; |
|||
} |
|||
|
|||
.uni-easyinput__content-input { |
|||
/* #ifndef APP-NVUE */ |
|||
width: auto; |
|||
/* #endif */ |
|||
position: relative; |
|||
overflow: hidden; |
|||
flex: 1; |
|||
line-height: 1; |
|||
font-size: 14px; |
|||
} |
|||
.uni-easyinput__placeholder-class { |
|||
color: #999; |
|||
font-size: 12px; |
|||
font-weight: 200; |
|||
} |
|||
.is-textarea { |
|||
align-items: flex-start; |
|||
} |
|||
|
|||
.is-textarea-icon { |
|||
margin-top: 5px; |
|||
} |
|||
|
|||
.uni-easyinput__content-textarea { |
|||
position: relative; |
|||
overflow: hidden; |
|||
flex: 1; |
|||
line-height: 1.5; |
|||
font-size: 14px; |
|||
padding-top: 6px; |
|||
padding-bottom: 10px; |
|||
height: 80px; |
|||
/* #ifndef APP-NVUE */ |
|||
min-height: 80px; |
|||
width: auto; |
|||
/* #endif */ |
|||
} |
|||
|
|||
.input-padding { |
|||
padding-left: 10px; |
|||
} |
|||
|
|||
.content-clear-icon { |
|||
padding: 0 5px; |
|||
} |
|||
|
|||
.label-icon { |
|||
margin-right: 5px; |
|||
margin-top: -1px; |
|||
} |
|||
|
|||
// 显示边框 |
|||
.is-input-border { |
|||
/* #ifndef APP-NVUE */ |
|||
display: flex; |
|||
box-sizing: border-box; |
|||
/* #endif */ |
|||
flex-direction: row; |
|||
align-items: center; |
|||
border: 1px solid $uni-border-1; |
|||
border-radius: 4px; |
|||
} |
|||
|
|||
.uni-error-message { |
|||
position: absolute; |
|||
bottom: -17px; |
|||
left: 0; |
|||
line-height: 12px; |
|||
color: $uni-error; |
|||
font-size: 12px; |
|||
text-align: left; |
|||
} |
|||
|
|||
.uni-error-msg--boeder { |
|||
position: relative; |
|||
bottom: 0; |
|||
line-height: 22px; |
|||
} |
|||
|
|||
.is-input-error-border { |
|||
border-color: $uni-error; |
|||
.uni-easyinput__placeholder-class { |
|||
color: mix(#fff, $uni-error, 50%);; |
|||
} |
|||
} |
|||
|
|||
|
|||
.uni-easyinput--border { |
|||
margin-bottom: 0; |
|||
padding: 10px 15px; |
|||
// padding-bottom: 0; |
|||
border-top: 1px #eee solid; |
|||
} |
|||
|
|||
.uni-easyinput-error { |
|||
padding-bottom: 0; |
|||
} |
|||
|
|||
.is-first-border { |
|||
/* #ifndef APP-NVUE */ |
|||
border: none; |
|||
/* #endif */ |
|||
/* #ifdef APP-NVUE */ |
|||
border-width: 0; |
|||
/* #endif */ |
|||
} |
|||
|
|||
.is-disabled { |
|||
border-color: red; |
|||
background-color: #F7F6F6; |
|||
color: #D5D5D5; |
|||
.uni-easyinput__placeholder-class { |
|||
color: #D5D5D5; |
|||
font-size: 12px; |
|||
} |
|||
} |
|||
</style> |
|||
@ -0,0 +1,90 @@ |
|||
{ |
|||
"id": "uni-easyinput", |
|||
"displayName": "uni-easyinput 增强输入框", |
|||
"version": "1.0.0", |
|||
"description": "Easyinput 组件是对原生input组件的增强", |
|||
"keywords": [ |
|||
"uni-ui", |
|||
"uniui", |
|||
"input", |
|||
"uni-easyinput", |
|||
"输入框" |
|||
], |
|||
"repository": "https://github.com/dcloudio/uni-ui", |
|||
"engines": { |
|||
"HBuilderX": "" |
|||
}, |
|||
"directories": { |
|||
"example": "../../temps/example_temps" |
|||
}, |
|||
"dcloudext": { |
|||
"category": [ |
|||
"前端组件", |
|||
"通用组件" |
|||
], |
|||
"sale": { |
|||
"regular": { |
|||
"price": "0.00" |
|||
}, |
|||
"sourcecode": { |
|||
"price": "0.00" |
|||
} |
|||
}, |
|||
"contact": { |
|||
"qq": "" |
|||
}, |
|||
"declaration": { |
|||
"ads": "无", |
|||
"data": "无", |
|||
"permissions": "无" |
|||
}, |
|||
"npmurl": "https://www.npmjs.com/package/@dcloudio/uni-ui" |
|||
}, |
|||
"uni_modules": { |
|||
"dependencies": [ |
|||
"uni-scss", |
|||
"uni-icons" |
|||
], |
|||
"encrypt": [], |
|||
"platforms": { |
|||
"cloud": { |
|||
"tcb": "y", |
|||
"aliyun": "y" |
|||
}, |
|||
"client": { |
|||
"App": { |
|||
"app-vue": "y", |
|||
"app-nvue": "y" |
|||
}, |
|||
"H5-mobile": { |
|||
"Safari": "y", |
|||
"Android Browser": "y", |
|||
"微信浏览器(Android)": "y", |
|||
"QQ浏览器(Android)": "y" |
|||
}, |
|||
"H5-pc": { |
|||
"Chrome": "y", |
|||
"IE": "y", |
|||
"Edge": "y", |
|||
"Firefox": "y", |
|||
"Safari": "y" |
|||
}, |
|||
"小程序": { |
|||
"微信": "y", |
|||
"阿里": "y", |
|||
"百度": "y", |
|||
"字节跳动": "y", |
|||
"QQ": "y" |
|||
}, |
|||
"快应用": { |
|||
"华为": "u", |
|||
"联盟": "u" |
|||
}, |
|||
"Vue": { |
|||
"vue2": "y", |
|||
"vue3": "y" |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,11 @@ |
|||
|
|||
|
|||
### Easyinput 增强输入框 |
|||
> **组件名:uni-easyinput** |
|||
> 代码块: `uEasyinput` |
|||
|
|||
|
|||
easyinput 组件是对原生input组件的增强 ,是专门为配合表单组件[uni-forms](https://ext.dcloud.net.cn/plugin?id=2773)而设计的,easyinput 内置了边框,图标等,同时包含 input 所有功能 |
|||
|
|||
### [查看文档](https://uniapp.dcloud.io/component/uniui/uni-easyinput) |
|||
#### 如使用过程中有任何问题,或者您对uni-ui有一些好的建议,欢迎加入 uni-ui 交流群:871950839 |
|||
@ -1,14 +1,82 @@ |
|||
import store from '@/store/index' |
|||
// 框架方法封装
|
|||
const tabList = ['client','trade','mall','mine'] |
|||
const tabList = ['store', 'cart', 'mine'] |
|||
|
|||
/** |
|||
* @param {string} 跳转的tabBar页面 |
|||
* @param {string} 跳转的tabBar页面 |
|||
* @return {null} |
|||
*/ |
|||
export function tab2(tabPage) { |
|||
if(tabList.includes(tabPage)) { |
|||
uni.switchTab({ |
|||
url:`/pages/${tabPage}/index` |
|||
}) |
|||
} |
|||
} |
|||
if (tabList.includes(tabPage)) { |
|||
uni.switchTab({ |
|||
url: `/pages/${tabPage}/index` |
|||
}) |
|||
} |
|||
} |
|||
/** |
|||
* @param {string} 返回上一级 |
|||
* @return {null} |
|||
*/ |
|||
export function back() { |
|||
if (getCurrentPages().length > 1) { |
|||
uni.navigateBack({ |
|||
delta: 1 |
|||
}) |
|||
} else { |
|||
go2('client') |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 跳转到指定页面,包括tabBar页面 |
|||
* @param {string} url 页面名称 |
|||
* @param {object} data 页面参数 |
|||
* @param {string} isRedirect 是否重定向 默认false |
|||
* @return {null} |
|||
*/ |
|||
export function go2(url, data = {}, isRedirect = false) { |
|||
if (!url) { |
|||
console.error('请选择页面') |
|||
return |
|||
} |
|||
let param = '' |
|||
Object.keys(data).forEach((key) => { |
|||
if (param === '') { |
|||
param = `${key}=${data[key]}` |
|||
} else { |
|||
param += `&${key}=${data[key]}` |
|||
} |
|||
}) |
|||
if (tabList.includes(url)) { |
|||
uni.switchTab({ |
|||
url: `/pages/${url}/index${param ? '?' + param : ''}` |
|||
}) |
|||
} else { |
|||
if (isRedirect) { |
|||
uni.redirectTo({ |
|||
url: `/pages/${url}/index${param ? '?' + param : ''}` |
|||
}) |
|||
} else { |
|||
uni.navigateTo({ |
|||
url: `/pages/${url}/index${param ? '?' + param : ''}` |
|||
}) |
|||
} |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 跳转到指定页面,包括tabBar页面,校验是否已登录,未登录则跳转到登录页面 |
|||
* @param {string} url 页面名称 |
|||
* @param {object} data 页面参数 |
|||
* @param {string} isRedirect 是否重定向 默认false |
|||
* @return {null} |
|||
*/ |
|||
export function loginGo2(url, data = {}, isRedirect) { |
|||
const token = store.state.qnToken |
|||
if (token) { |
|||
go2(url, data, isRedirect) |
|||
} else { |
|||
store.commit('setNextPage', { name: url, data }) |
|||
go2('login') |
|||
} |
|||
} |
|||
@ -1,112 +1,109 @@ |
|||
import { |
|||
isFunction |
|||
} from '../is.js' |
|||
const urlEnv = process.env.NODE_ENV === 'production' ? '-test' : '' |
|||
import { isFunction } from '../is.js' |
|||
const urlEnv = process.env.NODE_ENV === 'production' ? '' : '-test' |
|||
const uplaodUrl = `https://api-ops-yyt${urlEnv}.qniao.cn/cloud-print-user-center/utils/uploadImage` |
|||
export default class Http { |
|||
constructor(config = {}, { |
|||
reqInterceptor, |
|||
resInterceptor, |
|||
tranformConfig |
|||
} = {}) { |
|||
this.baseUrl = config.baseUrl |
|||
this.header = config.header || { |
|||
'content-type': 'application/json;charset=UTF-8' |
|||
} |
|||
this.requestOption = config.requestOption || {} |
|||
this.reqInterceptor = reqInterceptor |
|||
this.resInterceptor = resInterceptor |
|||
this.tranformConfig = tranformConfig |
|||
} |
|||
post(config, options) { |
|||
return this.request({ |
|||
method: 'POST', |
|||
...config |
|||
}, options) |
|||
} |
|||
get(config, options) { |
|||
return this.request({ |
|||
method: 'GET', |
|||
...config |
|||
}, options) |
|||
} |
|||
/** |
|||
* @param {Object} config 和请求相关的参数 |
|||
* @param {Object} options 对请求数据进行额外处理的参数 |
|||
*/ |
|||
request(config, options) { |
|||
let conf = Object.assign({}, config) |
|||
const { |
|||
tranformConfig, |
|||
reqInterceptor, |
|||
resInterceptor |
|||
} = this |
|||
if (tranformConfig && isFunction(tranformConfig)) { |
|||
conf = tranformConfig(this, config) |
|||
} |
|||
let opt = Object.assign({}, this.requestOption, options) |
|||
if (reqInterceptor && isFunction(reqInterceptor)) { |
|||
conf = reqInterceptor(conf, opt) |
|||
} |
|||
return new Promise((resolve, reject) => { |
|||
uni.request({ |
|||
url: conf.url, |
|||
data: conf.data, |
|||
header: conf.header, |
|||
success: (res) => { |
|||
console.log('native response', res) |
|||
let data = resInterceptor(res, opt) |
|||
// 服务器错误也会用then抛出,需要自己判断data==null
|
|||
resolve(data) |
|||
}, |
|||
fail: (err) => { |
|||
uni.showToast({ |
|||
title: '发生未知错误,请联系客服' |
|||
}) |
|||
reject(err) |
|||
} |
|||
}) |
|||
}).catch(err => { |
|||
// 吃掉请求产生的异常
|
|||
// 后期可以记录
|
|||
console.log('native response error', err) |
|||
}) |
|||
} |
|||
// config:{}
|
|||
uploadFile(config, options) { |
|||
return new Promise((resolve, rejetc) => { |
|||
let conf = Object.assign({}, config) |
|||
conf.url = uplaodUrl |
|||
const { |
|||
reqInterceptor |
|||
} = this |
|||
let opt = Object.assign({}, this.requestOption, options) |
|||
if (reqInterceptor && isFunction(reqInterceptor)) { |
|||
conf = reqInterceptor(conf, opt) |
|||
} |
|||
delete conf.header['Content-Type'] |
|||
uni.uploadFile({ |
|||
url: conf.url, |
|||
header: { |
|||
...conf.header, |
|||
image: config.data.filePath, |
|||
// 'Content-Type': 'image/png'
|
|||
}, |
|||
filePath: config.data.filePath, |
|||
name: config.data.fileName || 'image', |
|||
formData: { |
|||
image: config.data.filePath |
|||
}, |
|||
success: (res) => { |
|||
uni.hideLoading() |
|||
resolve(res.data) |
|||
}, |
|||
fail: (err) => { |
|||
reject(err) |
|||
} |
|||
}) |
|||
}).catch(err => { |
|||
console.log('upload native err', err) |
|||
}) |
|||
} |
|||
constructor( |
|||
config = {}, |
|||
{ reqInterceptor, resInterceptor, tranformConfig } = {} |
|||
) { |
|||
this.baseUrl = config.baseUrl |
|||
this.header = config.header || { |
|||
'content-type': 'application/json;charset=UTF-8' |
|||
} |
|||
this.requestOption = config.requestOption || {} |
|||
this.reqInterceptor = reqInterceptor |
|||
this.resInterceptor = resInterceptor |
|||
this.tranformConfig = tranformConfig |
|||
} |
|||
post(config, options) { |
|||
return this.request( |
|||
{ |
|||
method: 'POST', |
|||
...config |
|||
}, |
|||
options |
|||
) |
|||
} |
|||
get(config, options) { |
|||
return this.request( |
|||
{ |
|||
method: 'GET', |
|||
...config |
|||
}, |
|||
options |
|||
) |
|||
} |
|||
/** |
|||
* @param {Object} config 和请求相关的参数 |
|||
* @param {Object} options 对请求数据进行额外处理的参数 |
|||
*/ |
|||
request(config, options) { |
|||
let conf = Object.assign({}, config) |
|||
const { tranformConfig, reqInterceptor, resInterceptor } = this |
|||
if (tranformConfig && isFunction(tranformConfig)) { |
|||
conf = tranformConfig(this, config) |
|||
} |
|||
let opt = Object.assign({}, this.requestOption, options) |
|||
if (reqInterceptor && isFunction(reqInterceptor)) { |
|||
conf = reqInterceptor(conf, opt) |
|||
} |
|||
return new Promise((resolve, reject) => { |
|||
uni.request({ |
|||
url: conf.url, |
|||
data: conf.data, |
|||
header: conf.header, |
|||
method: conf.method, |
|||
success: (res) => { |
|||
let data = resInterceptor(res, opt) |
|||
// 服务器错误也会用then抛出,需要自己判断data==null
|
|||
resolve(data) |
|||
}, |
|||
fail: (err) => { |
|||
uni.showToast({ |
|||
title: '发生未知错误,请联系客服' |
|||
}) |
|||
reject(err) |
|||
} |
|||
}) |
|||
}).catch((err) => { |
|||
// 吃掉请求产生的异常
|
|||
// 后期可以记录
|
|||
console.log('native response error', err) |
|||
}) |
|||
} |
|||
// config:{}
|
|||
uploadFile(config, options) { |
|||
return new Promise((resolve, rejetc) => { |
|||
let conf = Object.assign({}, config) |
|||
conf.url = uplaodUrl |
|||
const { reqInterceptor } = this |
|||
let opt = Object.assign({}, this.requestOption, options) |
|||
if (reqInterceptor && isFunction(reqInterceptor)) { |
|||
conf = reqInterceptor(conf, opt) |
|||
} |
|||
delete conf.header['Content-Type'] |
|||
uni.uploadFile({ |
|||
url: conf.url, |
|||
header: { |
|||
...conf.header, |
|||
image: config.data.filePath |
|||
// 'Content-Type': 'image/png'
|
|||
}, |
|||
filePath: config.data.filePath, |
|||
name: config.data.fileName || 'image', |
|||
formData: { |
|||
image: config.data.filePath |
|||
}, |
|||
success: (res) => { |
|||
uni.hideLoading() |
|||
resolve(res.data) |
|||
}, |
|||
fail: (err) => { |
|||
reject(err) |
|||
} |
|||
}) |
|||
}).catch((err) => { |
|||
console.log('upload native err', err) |
|||
}) |
|||
} |
|||
} |
|||
Write
Preview
Loading…
Cancel
Save