初始化代码
This commit is contained in:
320
uniapp/uni-app/components/abnor.vue
Normal file
320
uniapp/uni-app/components/abnor.vue
Normal file
@@ -0,0 +1,320 @@
|
||||
<template>
|
||||
<view class="abnor" :style="{paddingBottom: percent}">
|
||||
<view class="abnor-box">
|
||||
<image mode="aspectFit" class="abnor-image" v-if="pimage" :src="pimage"></image>
|
||||
<view class="abnor-text" v-if="ptitle">{{ptitle}}</view>
|
||||
<view @tap.stop="emitAbnorTipTap" class="abnor-tip" :class="[{'tip-flex':!tipMax}]"
|
||||
:style="{maxWidth:tipMax,textAlign:tipMax?'left':''}" v-if="ptip">
|
||||
<text v-for="(item,index) in ptip" :key="index"
|
||||
:style="{color:item.color == 1 ? primaryColor:''}">{{item.text}}</text>
|
||||
</view>
|
||||
<block v-if="pbutton">
|
||||
<block v-for="(item,index) in pbutton" :key="index">
|
||||
<view class="abnor-btn" :class="btnSize"
|
||||
:style="{background:item.type == 'confirm' ? primaryColor : '',color:item.type == 'confirm'?'white':''}"
|
||||
@tap.stop="emitAbnorTap(index)">{{item.text}}</view>
|
||||
</block>
|
||||
</block>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
const Types = {
|
||||
'REQUEST_ERROR': {
|
||||
image: 'https://lbqny.migugu.com/admin/public/request-error.png',
|
||||
title: '网络加载失败',
|
||||
button: [{
|
||||
text: '点击刷新',
|
||||
type: 'confirm'
|
||||
}],
|
||||
tip: []
|
||||
},
|
||||
'NOT_FOUND': {
|
||||
image: 'https://lbqny.migugu.com/admin/public/not-found.png',
|
||||
title: '很抱歉,找不到你要访问的页面',
|
||||
button: [{
|
||||
text: '返回',
|
||||
type: 'cancel'
|
||||
}],
|
||||
tip: []
|
||||
},
|
||||
'DATA': {
|
||||
// image: 'https://lbqny.migugu.com/admin/public/no-data-2.png',
|
||||
// image: 'https://lbqny.migugu.com/admin/public/no-data.png',
|
||||
image: '/static/image/loading/no-data.png',
|
||||
title: '没有相关数据哦',
|
||||
button: [],
|
||||
tip: [{
|
||||
text: '',
|
||||
color: 0
|
||||
}]
|
||||
},
|
||||
'FOLLOW': {
|
||||
image: 'https://lbqny.migugu.com/admin/public/no-follow.png',
|
||||
title: '关注有趣的人',
|
||||
button: [],
|
||||
tip: [{
|
||||
text: '不再错过他们每一条动态',
|
||||
color: 0
|
||||
}]
|
||||
},
|
||||
'FEED': {
|
||||
image: 'https://lbqny.migugu.com/admin/public/no-feed.png',
|
||||
title: '还没有任何反馈哦',
|
||||
button: [],
|
||||
tip: []
|
||||
},
|
||||
'SHOP': {
|
||||
image: 'https://lbqny.migugu.com/admin/public/no-shop.png',
|
||||
title: '稍后再来试试吧~',
|
||||
button: [],
|
||||
tip: []
|
||||
},
|
||||
'WEIBO': {
|
||||
image: 'https://lbqny.migugu.com/admin/public/no-weibo.png',
|
||||
title: '',
|
||||
button: [],
|
||||
tip: []
|
||||
},
|
||||
'SEARCH': {
|
||||
image: 'https://lbqny.migugu.com/admin/public/no-search.png',
|
||||
title: '抱歉!没找到相关商品~',
|
||||
button: [],
|
||||
tip: []
|
||||
},
|
||||
'TAG': {
|
||||
image: 'https://lbqny.migugu.com/admin/public/no-tag.png',
|
||||
title: '',
|
||||
button: [],
|
||||
tip: []
|
||||
},
|
||||
'MESSAGE': {
|
||||
image: 'https://lbqny.migugu.com/admin/public/no-message.png',
|
||||
title: '消息通知空空如也',
|
||||
button: [],
|
||||
tip: []
|
||||
},
|
||||
'LIVE': {
|
||||
image: 'https://lbqny.migugu.com/admin/public/no-live.png',
|
||||
title: '',
|
||||
button: [],
|
||||
tip: []
|
||||
},
|
||||
'ORDER': {
|
||||
image: 'https://lbqny.migugu.com/admin/public/no-order.png',
|
||||
title: "还没有相关订单哦",
|
||||
button: [],
|
||||
tip: []
|
||||
},
|
||||
'CART': {
|
||||
image: 'https://lbqny.migugu.com/admin/public/no-cart.png',
|
||||
title: '购物车还是空的哦~',
|
||||
button: [{
|
||||
text: '去逛逛',
|
||||
type: 'confirm'
|
||||
}],
|
||||
tip: []
|
||||
},
|
||||
'FOOTPRINT': {
|
||||
image: 'https://lbqny.migugu.com/admin/public/no-footprint.png',
|
||||
title: '你还没有足迹~',
|
||||
button: [],
|
||||
tip: []
|
||||
},
|
||||
'COUPON': {
|
||||
// image: 'https://lbqny.migugu.com/admin/public/no-coupon.png',
|
||||
image: '/static/image/loading/coupon.png',
|
||||
title: '暂无卡券',
|
||||
button: [],
|
||||
tip: [{
|
||||
text: '去首页逛逛吧~',
|
||||
color: 0
|
||||
}]
|
||||
},
|
||||
'REDUCTION': {
|
||||
image: 'https://lbqny.migugu.com/admin/reduction/nodata.png',
|
||||
title: '您当前没有满减券,请向工作人员索取',
|
||||
button: [],
|
||||
tip: []
|
||||
}
|
||||
}
|
||||
import {
|
||||
mapState,
|
||||
} from 'vuex';
|
||||
export default {
|
||||
name: 'abnor',
|
||||
props: {
|
||||
type: {
|
||||
type: String,
|
||||
default () {
|
||||
return 'DATA'
|
||||
}
|
||||
},
|
||||
image: {
|
||||
type: String,
|
||||
default () {
|
||||
return ''
|
||||
}
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default () {
|
||||
return ''
|
||||
}
|
||||
},
|
||||
tip: {
|
||||
type: Array,
|
||||
default () {
|
||||
return []
|
||||
}
|
||||
},
|
||||
button: {
|
||||
type: Array,
|
||||
default () {
|
||||
return []
|
||||
}
|
||||
},
|
||||
tipTap: {
|
||||
type: String,
|
||||
default () {
|
||||
return ''
|
||||
}
|
||||
},
|
||||
tipMax: {
|
||||
type: String,
|
||||
default () {
|
||||
return '100%'
|
||||
}
|
||||
},
|
||||
btnSize: {
|
||||
type: String,
|
||||
default () {
|
||||
return 'big'
|
||||
}
|
||||
},
|
||||
percent: {
|
||||
type: String,
|
||||
default () {
|
||||
return '100%'
|
||||
}
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.init();
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
pimage: '',
|
||||
ptitle: '',
|
||||
ptip: '',
|
||||
pbutton: ''
|
||||
}
|
||||
},
|
||||
computed: mapState({
|
||||
primaryColor: state => state.config.configInfo.primaryColor,
|
||||
subColor: state => state.config.configInfo.subColor,
|
||||
}),
|
||||
methods: {
|
||||
emitAbnorTipTap() {
|
||||
let {
|
||||
tipTap = ''
|
||||
} = this
|
||||
if (!tipTap) return
|
||||
this.$emit(tipTap);
|
||||
},
|
||||
emitAbnorTap(index) {
|
||||
let {
|
||||
type
|
||||
} = this.pbutton[index]
|
||||
this.$emit(type);
|
||||
},
|
||||
init() {
|
||||
let type = this.type;
|
||||
// console.log(type, "=====type", this.image);
|
||||
if (Types[type]) {
|
||||
this.pimage = this.image || Types[type].image;
|
||||
this.ptitle = this.title || Types[type].title;
|
||||
this.pbutton = this.button.length > 0 ? this.button : Types[type].button;
|
||||
this.ptip = this.tip.length > 0 ? this.tip : Types[type].tip;
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.abnor {
|
||||
position: relative;
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 0;
|
||||
padding-bottom: 100%;
|
||||
overflow: hidden;
|
||||
|
||||
.abnor-box {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
.abnor-image {
|
||||
width: 514rpx;
|
||||
height: 260rpx;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.abnor-text {
|
||||
margin-top: 30rpx;
|
||||
color: #333;
|
||||
font-size: 30rpx;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.abnor-tip {
|
||||
margin: 15rpx 0 10rpx 0;
|
||||
color: #999;
|
||||
font-size: 26rpx;
|
||||
text-align: center;
|
||||
max-height: 30vh;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.tip-flex {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.abnor-btn {
|
||||
min-width: 228rpx;
|
||||
height: 66rpx;
|
||||
margin-top: 30rpx;
|
||||
padding: 0 30rpx;
|
||||
background-color: #eee;
|
||||
border: 0 none;
|
||||
border-radius: 10rpx;
|
||||
color: #333;
|
||||
font-size: 28rpx;
|
||||
text-align: center;
|
||||
// overflow: hidden;
|
||||
line-height: 66rpx;
|
||||
}
|
||||
|
||||
.abnor-btn.big {
|
||||
width: 690rpx;
|
||||
height: 100rpx;
|
||||
line-height: 100rpx;
|
||||
font-size: 32rpx;
|
||||
margin-top: 40rpx;
|
||||
border-radius: 50rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
492
uniapp/uni-app/components/auth.vue
Normal file
492
uniapp/uni-app/components/auth.vue
Normal file
@@ -0,0 +1,492 @@
|
||||
<template>
|
||||
<view style="width:100%">
|
||||
<block v-if="needAuth">
|
||||
<view @tap="toShowAuth">
|
||||
<slot></slot>
|
||||
</view>
|
||||
</block>
|
||||
<block v-else>
|
||||
<view @tap="go(1)">
|
||||
<slot></slot>
|
||||
</view>
|
||||
</block>
|
||||
<uni-popup ref="show_auth_item">
|
||||
<view class="auth-box fill-base flex-column flex-center radius-26">
|
||||
<block v-if="pType === 'userInfo'">
|
||||
<view class="auth-top fill-base flex-column flex-center" :style="{backgroundColor:primaryColor}">
|
||||
<view class="flex-center pd-lg">
|
||||
<view class="auth-info" style="overflow: hidden;">
|
||||
<button class="auth-info" open-type="chooseAvatar" @chooseavatar="onChooseAvatar">
|
||||
<image class="avatar" :src="avatarUrl || '/static/mine/default_user.png'"></image>
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
<view class="f-paragraph c-base">选择头像</view>
|
||||
</view>
|
||||
<view class="auth-w mt-lg mb-lg">
|
||||
<view class="auth-input">
|
||||
<view style="width:110rpx;">昵称:</view>
|
||||
<view>
|
||||
<input type="nickname" v-module="nickName" placeholder="请输入昵称" @blur="onBlur"/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</block>
|
||||
<block v-if="pType == 'phone'">
|
||||
<image class="auth-img" :src="`/static/mine/auth.png`">
|
||||
</image>
|
||||
</block>
|
||||
<view class="space-sm"></view>
|
||||
<view class="f-caption" :style="{color:primaryColor}">{{contentList[pType][0]}}</view>
|
||||
<view class="space-lg"></view>
|
||||
<view class="space-lg"></view>
|
||||
<block v-if="pType === 'userInfo'">
|
||||
<button @tap.stop="authUserProfile" hover-class="btn-hover" class="clear-btn flex-center auth-btn"
|
||||
:style="{backgroundColor:primaryColor,color:'white'}">{{btn_text||contentList[pType][1]}}</button>
|
||||
</block>
|
||||
<block v-if="pType === 'phone'">
|
||||
<button open-type="getPhoneNumber" hover-class="btn-hover" @getphonenumber="authPhone"
|
||||
class="clear-btn flex-center auth-btn" :style="{backgroundColor:primaryColor,color:'white'}">
|
||||
{{btn_text||contentList[pType][1]}}
|
||||
</button>
|
||||
</block>
|
||||
<block v-if="pType === 'setting'">
|
||||
<button open-type="openSetting" hover-class="btn-hover" @opensetting="openSetting"
|
||||
class="clear-btn flex-center auth-btn" :style="{backgroundColor:primaryColor,color:'white'}">
|
||||
{{btn_text||contentList[pType][1]}}
|
||||
</button>
|
||||
</block>
|
||||
<view @tap="go(pType == 'phone' && !userInfo.phone ? 2 : 1)" class="f-caption c-caption mt-md"
|
||||
v-if="!must">{{pType=='userInfo'?'暂不授权':'暂不登录'}}</view>
|
||||
<view class="space-md"></view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
|
||||
|
||||
<uni-popup ref="show_phone_item" :maskClick="false">
|
||||
<view class="common-popup-content popup-phone pd-lg flex-center flex-column fill-base">
|
||||
<view class="f-md-title c-black">请输入手机号</view>
|
||||
<view class="space-lg pb-lg"></view>
|
||||
<view class="space-lg pb-lg"></view>
|
||||
<view class="flex-center mb-lg">
|
||||
<view class="input-info sm mr-md radius-16">
|
||||
<input v-model="subForm.phone" type="number"
|
||||
class="item-input flex-y-center pl-lg pr-lg f-sm-title c-title"
|
||||
placeholder-class="c-placeholder" :placeholder="rule[0].errorMsg" />
|
||||
</view>
|
||||
<view @tap="toSend" class="send-btn flex-center c-base radius-16"
|
||||
:style="{background:primaryColor}">
|
||||
{{authTime>0?`(${authTime}s)`:'发送'}}
|
||||
</view>
|
||||
</view>
|
||||
<view class="input-info radius-16">
|
||||
<input v-model="subForm.short_code" type="number"
|
||||
class="item-input flex-y-center pl-lg pr-lg f-sm-title c-title" maxlength="6"
|
||||
placeholder-class="c-placeholder" :placeholder="rule[1].errorMsg" />
|
||||
</view>
|
||||
<view class="button">
|
||||
<view @tap.stop="go(3)" class="item-child">
|
||||
取消
|
||||
</view>
|
||||
<view @tap.stop="submit" class="item-child" :style="{background: primaryColor,color:'#fff'}">
|
||||
确定
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
|
||||
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
mapState,
|
||||
mapActions,
|
||||
mapMutations,
|
||||
} from "vuex"
|
||||
export default {
|
||||
components: {},
|
||||
name: 'auth',
|
||||
props: {
|
||||
needAuth: {
|
||||
type: Boolean,
|
||||
default () {
|
||||
return false
|
||||
}
|
||||
},
|
||||
must: {
|
||||
type: Boolean,
|
||||
default () {
|
||||
return false
|
||||
}
|
||||
},
|
||||
userMust: {
|
||||
type: Boolean,
|
||||
default () {
|
||||
return true
|
||||
}
|
||||
},
|
||||
showAuth: {
|
||||
type: Boolean,
|
||||
default () {
|
||||
return false
|
||||
}
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default () {
|
||||
return 'phone'
|
||||
}
|
||||
},
|
||||
btn_text: {
|
||||
type: String,
|
||||
default () {
|
||||
return ''
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: mapState({
|
||||
primaryColor: state => state.config.configInfo.primaryColor,
|
||||
subColor: state => state.config.configInfo.subColor,
|
||||
configInfo: state => state.config.configInfo,
|
||||
commonOptions: state => state.user.commonOptions,
|
||||
userInfo: state => state.user.userInfo,
|
||||
}),
|
||||
created() {
|
||||
this.init();
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
contentList: {
|
||||
userInfo: ['尊贵的用户,获取授权是为了能更好的为你服务', '立即授权'],
|
||||
phone: ['尊贵的用户,登录后我们才能更好的为你服务', '立即登录'],
|
||||
setting: ['为了功能正常使用,你需要打开设置并开启获取相应权限', '打开设置'],
|
||||
},
|
||||
pType: '',
|
||||
pMust: '',
|
||||
authTime: 0,
|
||||
timer: null,
|
||||
subForm: {
|
||||
phone: '',
|
||||
short_code: ''
|
||||
},
|
||||
rule: [{
|
||||
name: "phone",
|
||||
checkType: "isMobile",
|
||||
errorMsg: "请输入手机号",
|
||||
regText: "手机号"
|
||||
}, {
|
||||
name: "short_code",
|
||||
checkType: "isNotNull",
|
||||
errorMsg: "请输入短信验证码",
|
||||
regText: "短信验证码"
|
||||
}],
|
||||
avatarUrl:'',
|
||||
lockTap: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['getUserInfo', 'getAuthUserProfile', 'getAuthPhone', ]),
|
||||
init() {
|
||||
let {
|
||||
type,
|
||||
must,
|
||||
showAuth
|
||||
} = this
|
||||
this.$set(this, 'pType', type)
|
||||
this.$set(this, 'pMust', must)
|
||||
if (!showAuth) return
|
||||
this.$refs.show_auth_item.open()
|
||||
},
|
||||
async authPhone(e) {
|
||||
let {
|
||||
pMust
|
||||
} = this
|
||||
let phone = await this.getAuthPhone({
|
||||
e,
|
||||
})
|
||||
console.log(pMust, phone, "===== pMust auth_phone");
|
||||
if (!phone) {
|
||||
this.go(pMust ? 2 : 1)
|
||||
return false
|
||||
} else {
|
||||
this.$set(this, 'pType', 'userInfo')
|
||||
this.$set(this, 'pMust', this.userMust)
|
||||
console.log(this.PType, this.pMust, "====auth_to_userInfo");
|
||||
if (!this.pMust) return
|
||||
this.$refs.show_auth_item.open()
|
||||
}
|
||||
},
|
||||
async onChooseAvatar(e) {
|
||||
this.reloadAvatar = await this.$api.base.uploadFile({
|
||||
filePath: e.detail.avatarUrl,
|
||||
filetype: 'picture'
|
||||
})
|
||||
this.avatarUrl = this.reloadAvatar.attachment_path
|
||||
},
|
||||
async onBlur(e){
|
||||
//console.log(e)
|
||||
this.nickName = e.detail.value
|
||||
},
|
||||
async authUserProfile(e) {
|
||||
// #ifdef APP-PLUS
|
||||
uni.getUserInfo({
|
||||
provider: 'weixin',
|
||||
success: res => {
|
||||
let {
|
||||
userInfo = {}
|
||||
} = res
|
||||
this.toUpdateUserInfo(userInfo)
|
||||
}
|
||||
})
|
||||
// #endif
|
||||
// #ifndef APP-PLUS
|
||||
uni.getUserProfile({
|
||||
desc: '用于完善个人资料', // 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写
|
||||
success: (res) => {
|
||||
let {
|
||||
userInfo = {},
|
||||
encryptedData,
|
||||
iv,
|
||||
} = res
|
||||
let param = Object.assign({}, userInfo, {
|
||||
encryptedData,
|
||||
iv,
|
||||
});
|
||||
this.toUpdateUserInfo(param)
|
||||
},
|
||||
fail: (res) => {
|
||||
console.log(res, "=====fail");
|
||||
this.toUpdateUserInfo()
|
||||
}
|
||||
})
|
||||
// #endif
|
||||
},
|
||||
async toUpdateUserInfo(userInfo = {}) {
|
||||
let {
|
||||
pMust
|
||||
} = this
|
||||
if (userInfo.nickName) {
|
||||
let {
|
||||
coupon_atv_id = 0
|
||||
} = this.commonOptions
|
||||
userInfo.coupon_atv_id = coupon_atv_id,
|
||||
userInfo.avatarUrl = this.avatarUrl,
|
||||
userInfo.nickName = this.nickName
|
||||
await this.getAuthUserProfile(userInfo)
|
||||
}
|
||||
console.log(pMust, userInfo, "===== pMust auth_userinfo");
|
||||
this.go(pMust && !userInfo.nickName ? 2 : 1);
|
||||
},
|
||||
toShowAuth() {
|
||||
let {
|
||||
phone = ''
|
||||
} = this.userInfo
|
||||
let type = !phone ? 'phone' : 'userInfo'
|
||||
this.$set(this, 'pType', type)
|
||||
console.log(this.userInfo, phone, this.pType, "=====toShowAuth")
|
||||
let refs_key = 'show_auth_item'
|
||||
// #ifndef MP-WEIXIN
|
||||
refs_key = 'show_phone_item'
|
||||
if (this.configInfo.short_code_status * 1 == 0) {
|
||||
this.go(1)
|
||||
return
|
||||
}
|
||||
// #endif
|
||||
this.$refs[refs_key].open()
|
||||
},
|
||||
go(type = 1) {
|
||||
this.lockTap = false
|
||||
this.$emit(type == 1 ? 'go' : 'hide')
|
||||
let refs_key = type == 3 ? 'show_phone_item' : 'show_auth_item'
|
||||
this.$refs[refs_key].close();
|
||||
this.toResetItem()
|
||||
},
|
||||
toResetItem() {
|
||||
this.timer && clearTimeout(this.timer)
|
||||
this.authTime = 0
|
||||
this.subForm = {
|
||||
phone: '',
|
||||
short_code: ''
|
||||
}
|
||||
},
|
||||
//表单验证
|
||||
validate(param, is_send = false) {
|
||||
let validate = new this.$util.Validate();
|
||||
this.rule.map(item => {
|
||||
let {
|
||||
name,
|
||||
} = item
|
||||
if (name == 'short_code' && is_send) return
|
||||
validate.add(param[name], item);
|
||||
})
|
||||
let message = validate.start();
|
||||
return message;
|
||||
},
|
||||
async toSend() {
|
||||
let {
|
||||
authTime
|
||||
} = this
|
||||
if (authTime) return
|
||||
let {
|
||||
phone = ''
|
||||
} = this.subForm
|
||||
let msg = this.validate({
|
||||
phone
|
||||
}, true);
|
||||
if (msg) {
|
||||
this.$util.showToast({
|
||||
title: msg
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (this.lockTap) return
|
||||
this.lockTap = true
|
||||
this.$util.showLoading()
|
||||
try {
|
||||
await this.$api.user.sendShortMsg({
|
||||
phone
|
||||
})
|
||||
this.$util.hideAll()
|
||||
this.lockTap = false
|
||||
let time = 60
|
||||
this.timer = setInterval(() => {
|
||||
if (time === 0) {
|
||||
clearTimeout(this.timer)
|
||||
return
|
||||
}
|
||||
time--
|
||||
this.authTime = time
|
||||
}, 1000)
|
||||
} catch (e) {
|
||||
setTimeout(() => {
|
||||
this.lockTap = false
|
||||
this.$util.hideAll()
|
||||
}, 2000)
|
||||
}
|
||||
},
|
||||
async openSetting(e) {
|
||||
// Handle the openSetting event
|
||||
console.log('openSetting event:', e);
|
||||
// The setting was opened, now check if the required permission was granted
|
||||
// You may need to implement specific logic based on your permission requirements
|
||||
},
|
||||
async submit() {
|
||||
let param = this.$util.deepCopy(this.subForm)
|
||||
let msg = this.validate(param);
|
||||
if (msg) {
|
||||
this.$util.showToast({
|
||||
title: msg
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (param.short_code.length != 6) {
|
||||
this.$util.showToast({
|
||||
title: `请输入6位数短信验证码`
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if (this.lockTap) return
|
||||
this.lockTap = true
|
||||
this.$util.showLoading()
|
||||
try {
|
||||
await this.$api.user.bindUserPhone(param)
|
||||
this.$util.hideAll()
|
||||
this.lockTap = false
|
||||
this.$refs.show_phone_item.close()
|
||||
this.toResetItem()
|
||||
await this.getUserInfo()
|
||||
setTimeout(() => {
|
||||
this.$emit('go')
|
||||
}, 500)
|
||||
} catch (e) {
|
||||
setTimeout(() => {
|
||||
this.lockTap = false
|
||||
this.$util.hideAll()
|
||||
}, 2000)
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
<style lang="scss">
|
||||
.auth-box {
|
||||
width: 630rpx;
|
||||
height: auto;
|
||||
padding: 0 30rpx 30rpx 30rpx;
|
||||
overflow: hidden;
|
||||
|
||||
.auth-img {
|
||||
width: 322rpx;
|
||||
height: 341rpx;
|
||||
/* background: #f4f6f8; */
|
||||
}
|
||||
|
||||
.auth-btn {
|
||||
width: 100%;
|
||||
height: 85rpx;
|
||||
border-radius: 8rpx;
|
||||
}
|
||||
|
||||
.auth-info {
|
||||
width: 120rpx;
|
||||
height: 120rpx;
|
||||
background: #f4f6f8;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.auth-top {
|
||||
width: 930rpx;
|
||||
height: 260rpx;
|
||||
border-radius: 0 0 50% 50%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
|
||||
.auth-w{
|
||||
width:100%;
|
||||
}
|
||||
|
||||
|
||||
.auth-input{
|
||||
align-items: center;
|
||||
background: #efeff5;
|
||||
display: flex;
|
||||
padding: 20rpx;
|
||||
border-radius: 8rpx;
|
||||
}
|
||||
|
||||
.popup-phone {
|
||||
width: 630rpx;
|
||||
|
||||
.input-info {
|
||||
width: 570rpx;
|
||||
height: 90rpx;
|
||||
background: #F7F7F7;
|
||||
|
||||
.item-input {
|
||||
height: 90rpx;
|
||||
font-size: 32rpx;
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
|
||||
.input-info.sm {
|
||||
width: 400rpx;
|
||||
}
|
||||
|
||||
.send-btn {
|
||||
width: 150rpx;
|
||||
height: 90rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
215
uniapp/uni-app/components/banner.vue
Normal file
215
uniapp/uni-app/components/banner.vue
Normal file
@@ -0,0 +1,215 @@
|
||||
<template>
|
||||
<!-- 轮播图广告 -->
|
||||
<view class='swiper-box' :style='{margin:`0 ${margin}rpx`,borderRadius:`${.3125}rem`}'>
|
||||
<swiper class="swiper-ad" :indicator-dots="false" :autoplay="autoplay" :indicator-color="indicatorColor"
|
||||
:indicator-active-color="indicatorActiveColor" :circular="circular"
|
||||
:previous-margin="list.length>1?previousMargin:0" :next-margin="list.length>1?nextMargin:0"
|
||||
@change="handerChange" :style="{height:`${11.375}rem`,borderRadius:`${.3125}rem`}"
|
||||
easing-function="linear">
|
||||
<swiper-item v-for="(item,index) in list" :key="index">
|
||||
<view class='img-box rel' :style="{borderRadius:`${.3125}rem`}" @tap='changeItem(item,index)'>
|
||||
<image mode="aspectFill" lazy-load :src='item.img || item.cover || item' class="swiper-ad__img"
|
||||
:style="{borderRadius:`${.3125}rem`}" />
|
||||
<view class="abs play-video flex-center" :style="{borderRadius:`${.3125}rem`}"
|
||||
v-if="haveVideo && index == 0"><i class="iconfont icon-bofang"></i>
|
||||
</view>
|
||||
</view>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
<view class='numbers' v-if="list.length>1&&indicatorType=='number'" :style="{textAlign:indicatorStyle}">
|
||||
<view class="number">{{activeIndex+1}}/{{list.length}}</view>
|
||||
</view>
|
||||
<view class='dots' v-if="list.length>1&&indicatorType=='dot'" :style="{textAlign:indicatorStyle}">
|
||||
<view class='dot' v-for="(item,index) in list" :key="index"
|
||||
:style='{backgroundColor:index==activeIndex?indicatorActiveColor:indicatorColor,width:index==activeIndex? `${dotWidth}rpx` :"12rpx"}'>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
mapState,
|
||||
} from 'vuex';
|
||||
export default {
|
||||
name: 'banner',
|
||||
props: {
|
||||
list: {
|
||||
type: Array,
|
||||
default () {
|
||||
return [1, 2, 3]
|
||||
}
|
||||
},
|
||||
height: {
|
||||
type: Number,
|
||||
default () {
|
||||
return 400
|
||||
}
|
||||
},
|
||||
indicatorType: {
|
||||
type: String,
|
||||
default () {
|
||||
return "dot"
|
||||
}
|
||||
},
|
||||
indicatorColor: {
|
||||
type: String,
|
||||
default () {
|
||||
return "#FEFFFE"
|
||||
}
|
||||
},
|
||||
indicatorActiveColor: {
|
||||
type: String,
|
||||
default () {
|
||||
return "#fff"
|
||||
}
|
||||
},
|
||||
indicatorStyle: {
|
||||
type: String,
|
||||
default () {
|
||||
return 'center'
|
||||
}
|
||||
},
|
||||
circular: {
|
||||
type: Boolean,
|
||||
default () {
|
||||
return true
|
||||
}
|
||||
},
|
||||
autoplay: {
|
||||
type: Boolean,
|
||||
default () {
|
||||
return false
|
||||
}
|
||||
},
|
||||
previousMargin: {
|
||||
type: Number,
|
||||
default () {
|
||||
return 0
|
||||
}
|
||||
},
|
||||
nextMargin: {
|
||||
type: Number,
|
||||
default () {
|
||||
return 0
|
||||
}
|
||||
},
|
||||
dotWidth: {
|
||||
type: Number,
|
||||
default () {
|
||||
return 12
|
||||
}
|
||||
},
|
||||
margin: {
|
||||
type: Number,
|
||||
default () {
|
||||
return 0
|
||||
}
|
||||
},
|
||||
borderRadius: {
|
||||
type: Number,
|
||||
default () {
|
||||
return 0
|
||||
}
|
||||
},
|
||||
haveVideo: {
|
||||
type: Boolean,
|
||||
default () {
|
||||
return false
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
activeIndex: 0
|
||||
}
|
||||
},
|
||||
computed: mapState({
|
||||
configInfo: state => state.config.configInfo,
|
||||
commonOptions: state => state.user.commonOptions,
|
||||
}),
|
||||
methods: {
|
||||
handerChange: function(e) {
|
||||
this.activeIndex = e.detail.current;
|
||||
},
|
||||
changeItem(item, index) {
|
||||
this.$emit("change", {
|
||||
item,
|
||||
index
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.swiper-box {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
.img-box {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
.swiper-ad__img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.play-video {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
background: rgba(0, 0, 0, 0.2);
|
||||
|
||||
.iconfont {
|
||||
font-size: 100rpx;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.dots {
|
||||
position: absolute;
|
||||
z-index: 20rpx;
|
||||
text-align: right;
|
||||
width: 100%;
|
||||
transform: translateY(-48rpx);
|
||||
padding: 0 20rpx;
|
||||
|
||||
.dot {
|
||||
display: inline-block;
|
||||
height: 12rpx;
|
||||
width: 12rpx;
|
||||
background-color: #FEFFFE;
|
||||
border-radius: 6rpx;
|
||||
margin: 0 8rpx;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.numbers {
|
||||
position: absolute;
|
||||
z-index: 20rpx;
|
||||
text-align: right;
|
||||
width: 100%;
|
||||
transform: translateY(-80rpx);
|
||||
padding: 0 20rpx;
|
||||
|
||||
.number {
|
||||
display: inline-block;
|
||||
width: 90rpx;
|
||||
line-height: 50rpx;
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
border-radius: 45rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
323
uniapp/uni-app/components/column.vue
Normal file
323
uniapp/uni-app/components/column.vue
Normal file
@@ -0,0 +1,323 @@
|
||||
<template>
|
||||
<view>
|
||||
<!-- 轮播图 -->
|
||||
<view v-if="type=='swiper'" class='column-box' :style='{paddingTop:whiteSpace+"rpx",paddingBottom:whiteSpace+"rpx",paddingLeft:wingBlank+"rpx",paddingRight:wingBlank+"rpx"}'>
|
||||
<swiper class="swiper-category" @change="handerChange" :style="{height:(146*formatRowNum+20*(formatRowNum-1))+'rpx'}">
|
||||
<swiper-item class="swiper-category-item" v-for="(pitem,pindex) in formatList" :key="pindex">
|
||||
<view v-for="(item,index) in pitem" :key="index" class="column-item" :style="{width:100/colNum + '%',marginTop:index<colNum? '0' : '20rpx'}"
|
||||
@tap='change(item)'>
|
||||
<image mode="aspectFill" lazy-load v-if="item.icon" class="column-img" :src="item.icon"></image>
|
||||
<view v-else class="column-no-img" :style="{background:colorList[index%8],borderRadius:'50%',margin:'0rpx auto'}">
|
||||
{{getFirstText(item.cate_name)}}
|
||||
</view>
|
||||
<view class='column-text'>{{item.cate_name}}</view>
|
||||
</view>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
<view class='dots' v-if="formatList.length>1">
|
||||
<view class='dot' v-for="(item,index) in formatList.length" :key="index" :style='{background:index==current?indicatorActiveColor:indicatorColor}'></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
||||
<!-- 滑动 -->
|
||||
<view v-if="type=='scroll'" class='column-box' :style='{paddingTop:whiteSpace+"rpx",paddingBottom:whiteSpace+"rpx",paddingLeft:wingBlank+"rpx",paddingRight:wingBlank+"rpx"}'>
|
||||
<scroll-view scroll-x class='scroll-x' @scroll="handerScroll">
|
||||
<view class='scroll-x-item' v-for="(pItem,pindex) in formatList" :key="pindex">
|
||||
<view class='column-item' v-for="(item,index) in pItem" :key="index" :style='{width:(750/colNum)+"rpx"}' @tap='change(item)'>
|
||||
<image mode="aspectFill" lazy-load class='column-img' :src='item.icon'></image>
|
||||
<view class='column-text'>{{item.cate_name}}</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class='ink-bar-box' v-if="list.length>formatRowNum*colNum">
|
||||
<view class="ui-tabs-ink-bar-wrapper">
|
||||
<view class="ui-tabs-ink-bar" :style='{left:left+"rpx",background:indicatorActiveColor}'></view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
|
||||
|
||||
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'column',
|
||||
props: {
|
||||
type: {
|
||||
type: String,
|
||||
default () {
|
||||
return "swiper"
|
||||
}
|
||||
},
|
||||
list: {
|
||||
type: Array,
|
||||
default () {
|
||||
return []
|
||||
}
|
||||
},
|
||||
colNum: {
|
||||
type: Number,
|
||||
default () {
|
||||
return 4
|
||||
}
|
||||
},
|
||||
rowNum: {
|
||||
type: Number,
|
||||
default () {
|
||||
return 2
|
||||
}
|
||||
},
|
||||
indicatorActiveColor: {
|
||||
type: String,
|
||||
default () {
|
||||
return '#f6f5fa'
|
||||
}
|
||||
},
|
||||
indicatorColor: {
|
||||
type: String,
|
||||
default () {
|
||||
return '#f6f5fa'
|
||||
}
|
||||
},
|
||||
wingBlank: {
|
||||
type: Number,
|
||||
default () {
|
||||
return 0
|
||||
}
|
||||
},
|
||||
whiteSpace: {
|
||||
type: Number,
|
||||
default () {
|
||||
return 30
|
||||
}
|
||||
},
|
||||
borderRadius: {
|
||||
type: Number,
|
||||
default () {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
activeIndex: 0,
|
||||
newList: [],
|
||||
left: 0,
|
||||
current: 0,
|
||||
colorList: ["#fc7f87", "#56b4fc", "#f8ae41", "#11dd9e", "#fba745", "#fb7c85", "#46adfc", "#fc7d86"]
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
formatRowNum() {
|
||||
let {
|
||||
colNum,
|
||||
rowNum,
|
||||
list
|
||||
} = this;
|
||||
let length = list.length;
|
||||
let newRowNum = length <= colNum ? 1 : rowNum;
|
||||
return newRowNum
|
||||
},
|
||||
formatList() {
|
||||
let {
|
||||
colNum,
|
||||
rowNum,
|
||||
type,
|
||||
list,
|
||||
formatRowNum
|
||||
} = this;
|
||||
|
||||
|
||||
let index = 0;
|
||||
let length = list.length;
|
||||
let newList = [];
|
||||
|
||||
let count = formatRowNum * colNum
|
||||
// let count = type == 'scroll' ? colNum : formatRowNum * colNum
|
||||
while (index < length) {
|
||||
newList.push(list.slice(index, index += count));
|
||||
}
|
||||
return newList
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
handerScroll: function(e) {
|
||||
let {
|
||||
scrollLeft,
|
||||
scrollWidth
|
||||
} = e.detail;
|
||||
let windowWidth = uni.getSystemInfoSync().windowWidth;
|
||||
let left = scrollLeft * 30 / (scrollWidth - windowWidth);
|
||||
this.left = left
|
||||
},
|
||||
handerChange: function(e) {
|
||||
this.current = e.detail.current;
|
||||
},
|
||||
change(item) {
|
||||
this.$emit("change", item)
|
||||
},
|
||||
getFirstText(d) {
|
||||
d = d || '名称'
|
||||
return d.slice(0, 1)
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<style lang="scss">
|
||||
/* 轮播图 */
|
||||
.column-box {
|
||||
background: #fff;
|
||||
font-size: 24rpx;
|
||||
color: #888;
|
||||
|
||||
.swiper-category {
|
||||
width: 100%;
|
||||
background: #fff;
|
||||
font-size: 24rpx;
|
||||
color: #666;
|
||||
border-radius: 10rpx;
|
||||
|
||||
.swiper-category-item {
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
flex-wrap: wrap;
|
||||
background: #fff;
|
||||
|
||||
|
||||
.column-item {
|
||||
margin-top: 20rpx;
|
||||
float: left;
|
||||
|
||||
|
||||
.column-img {
|
||||
width: 100rpx;
|
||||
height: 100rpx;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.column-no-img {
|
||||
width: 100rpx;
|
||||
height: 100rpx;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 36rpx;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.column-text {
|
||||
margin-top: 10rpx;
|
||||
text-align: center;
|
||||
color: #454A53;
|
||||
width: 100%;
|
||||
padding: 0 10%;
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.scroll-x {
|
||||
white-space: nowrap;
|
||||
background: #fff;
|
||||
padding: 20rpx 0;
|
||||
|
||||
.scroll-x-item {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
vertical-align: text-top;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.column-item {
|
||||
margin-top: 20rpx;
|
||||
float: left;
|
||||
|
||||
|
||||
.column-img {
|
||||
width: 100rpx;
|
||||
height: 100rpx;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.column-text {
|
||||
margin-top: 10rpx;
|
||||
text-align: center;
|
||||
color: #454A53;
|
||||
width: 100%;
|
||||
padding: 0 10%;
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.dots {
|
||||
background: white;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
padding-top: 20rpx;
|
||||
|
||||
.dot {
|
||||
height: 16rpx;
|
||||
width: 16rpx;
|
||||
background: #ddd;
|
||||
border-radius: 8rpx;
|
||||
margin: 0 8rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.ink-bar-box {
|
||||
background: #fff;
|
||||
padding-bottom: 20rpx;
|
||||
|
||||
.ui-tabs-ink-bar-wrapper {
|
||||
width: 60rpx;
|
||||
background: #ddd;
|
||||
position: relative;
|
||||
left: 345rpx;
|
||||
bottom: 0;
|
||||
height: 8rpx;
|
||||
transform-origin: 50% 50%;
|
||||
transition: width 250ms ease-out, left 250ms ease-out;
|
||||
overflow: hidden;
|
||||
border-radius: 4rpx;
|
||||
|
||||
.ui-tabs-ink-bar {
|
||||
position: absolute;
|
||||
width: 30rpx;
|
||||
background: #e74d45;
|
||||
height: 8rpx;
|
||||
border-radius: 4rpx;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
</style>
|
||||
188
uniapp/uni-app/components/common-popup.vue
Normal file
188
uniapp/uni-app/components/common-popup.vue
Normal file
@@ -0,0 +1,188 @@
|
||||
<template>
|
||||
<uni-popup type="center" :maskClick="maskClick" ref="common_popup">
|
||||
<view class="common-popup-content fill-base">
|
||||
<view class="title" v-if="ptitle">{{ptitle}}</view>
|
||||
<view class="desc" v-if="pdesc">{{pdesc}}</view>
|
||||
<image mode="aspectFill" lazy-load class="image" :class="imgSize" :src="info.image" v-if="info.image">
|
||||
</image>
|
||||
<view class="name ellipsis-3" v-if="info.name">{{info.name}}</view>
|
||||
<view class="button">
|
||||
<block v-for="(item,index) in pbutton" :key="index">
|
||||
<view @tap.stop="toEmit(index)" class="item-child"
|
||||
:style="{background: item.type == 'confirm' ? primaryColor : '',color:item.type == 'confirm' ?'white':''}">
|
||||
{{item.title}}
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
const Types = {
|
||||
'CANCEL_ORDER': {
|
||||
title: '取消订单',
|
||||
desc: '请确认是否取消订单,取消后将无法恢复',
|
||||
text: '确认取消'
|
||||
},
|
||||
'END_ORDER': {
|
||||
title: '确认收货',
|
||||
desc: '请确认是否收货,收货后将无法恢复',
|
||||
text: '确认收货'
|
||||
},
|
||||
'HX_ORDER': {
|
||||
title: '核销订单',
|
||||
desc: '请确认是否核销订单,核销订单后将无法恢复',
|
||||
text: '确认核销'
|
||||
},
|
||||
'DELETE_ORDER': {
|
||||
title: '删除订单',
|
||||
desc: '请确认是否删除订单,删除后将无法恢复',
|
||||
text: '确认删除'
|
||||
},
|
||||
'REFUND_ORDER': {
|
||||
title: '申请退款',
|
||||
desc: '请确认是否申请退款',
|
||||
text: '确认申请'
|
||||
},
|
||||
'CANCEL_REFUND_ORDER': {
|
||||
title: '取消退款',
|
||||
desc: '请确认是否取消退款',
|
||||
text: '确认取消'
|
||||
},
|
||||
'NO_PASS_REFUND': {
|
||||
title: '拒绝退款',
|
||||
desc: '请确认是否拒绝退款',
|
||||
text: '确认拒绝'
|
||||
},
|
||||
'HX_CODE': {
|
||||
title: '核销码',
|
||||
desc: '请出示二维码给核销人员',
|
||||
},
|
||||
'CHANGE_UP_ITEM': {
|
||||
title: '上架',
|
||||
desc: '请确认是否上架',
|
||||
text: '确认上架'
|
||||
},
|
||||
'CHANGE_DOWN_ITEM': {
|
||||
title: '下架',
|
||||
desc: '请确认是否下架',
|
||||
text: '确认下架'
|
||||
},
|
||||
'DEL_ITEM': {
|
||||
title: '删除',
|
||||
desc: '请确认是否删除此数据,删除后将无法恢复',
|
||||
text: '确认删除'
|
||||
},
|
||||
}
|
||||
import {
|
||||
mapState,
|
||||
} from "vuex"
|
||||
export default {
|
||||
components: {},
|
||||
props: {
|
||||
maskClick: {
|
||||
type: Boolean,
|
||||
default () {
|
||||
return false
|
||||
}
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default () {
|
||||
return 'CANCEL_ORDER'
|
||||
}
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default () {
|
||||
return ''
|
||||
}
|
||||
},
|
||||
desc: {
|
||||
type: String,
|
||||
default () {
|
||||
return ''
|
||||
}
|
||||
},
|
||||
text: {
|
||||
type: String,
|
||||
default () {
|
||||
return ''
|
||||
}
|
||||
},
|
||||
info: {
|
||||
type: Object,
|
||||
default () {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
button: {
|
||||
type: Array,
|
||||
default () {
|
||||
return [{
|
||||
title: '取消',
|
||||
type: 'cancel'
|
||||
}, {
|
||||
title: '确定取消',
|
||||
type: 'confirm'
|
||||
}]
|
||||
}
|
||||
},
|
||||
imgSize: {
|
||||
type: String,
|
||||
default () {
|
||||
return ''
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.init();
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
ptitle: '',
|
||||
pdesc: '',
|
||||
pbutton: [],
|
||||
}
|
||||
},
|
||||
computed: mapState({
|
||||
primaryColor: state => state.config.configInfo.primaryColor,
|
||||
subColor: state => state.config.configInfo.subColor,
|
||||
}),
|
||||
methods: {
|
||||
init() {
|
||||
let {
|
||||
type,
|
||||
} = this;
|
||||
if (Types[type]) {
|
||||
this.ptitle = this.title || Types[type].title
|
||||
this.pdesc = this.desc || Types[type].desc
|
||||
this.pbutton = this.button
|
||||
if (this.text || Types[type].text) {
|
||||
this.pbutton[1].title = this.text || Types[type].text
|
||||
}
|
||||
}
|
||||
},
|
||||
open() {
|
||||
this.$refs.common_popup.open()
|
||||
},
|
||||
close() {
|
||||
this.$refs.common_popup.close()
|
||||
},
|
||||
toEmit(index) {
|
||||
let {
|
||||
type
|
||||
} = this.button[index]
|
||||
if (type == 'cancel') {
|
||||
this.close()
|
||||
} else {
|
||||
this.$emit(type)
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
</style>
|
||||
69
uniapp/uni-app/components/fix-bottom-button.vue
Normal file
69
uniapp/uni-app/components/fix-bottom-button.vue
Normal file
@@ -0,0 +1,69 @@
|
||||
<template>
|
||||
<view class="content" :style="{background: bgColor}">
|
||||
<block v-for="(item,index) in text" :key="index">
|
||||
<view @click="confirm(item)" class="bottom-view"
|
||||
:style="{width:(100/ text.length)+ '%',margin:text.length==1?'0 30rpx':index==0?'0 0 0 30rpx': index == text.length -1 ? '0 30rpx 0 0' : '',borderRadius:text.length==1?'88rpx':index==0?'88rpx 0 0 88rpx': index== text.length -1 ? '0 88rpx 88rpx 0' : '',background: item.type == 'confirm'? primaryColor : subColor}">
|
||||
{{ item.text }}
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
mapState,
|
||||
} from "vuex"
|
||||
export default {
|
||||
props: {
|
||||
text: {
|
||||
type: Array,
|
||||
default () {
|
||||
return [{
|
||||
text: '保存',
|
||||
type: 'confirm'
|
||||
}]
|
||||
}
|
||||
},
|
||||
bgColor: {
|
||||
type: String,
|
||||
default () {
|
||||
return '#fff'
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: mapState({
|
||||
primaryColor: state => state.config.configInfo.primaryColor,
|
||||
subColor: state => state.config.configInfo.subColor,
|
||||
}),
|
||||
methods: {
|
||||
confirm(item) {
|
||||
this.$emit(item.type)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.content {
|
||||
position: fixed;
|
||||
bottom: 0rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 128rpx;
|
||||
z-index: 997;
|
||||
height: calc(128rpx + env(safe-area-inset-bottom) / 2);
|
||||
padding-bottom: calc(env(safe-area-inset-bottom) / 2);
|
||||
|
||||
.bottom-view {
|
||||
width: auto;
|
||||
height: 88rpx;
|
||||
line-height: 88rpx;
|
||||
text-align: center;
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
79
uniapp/uni-app/components/fixed.vue
Normal file
79
uniapp/uni-app/components/fixed.vue
Normal file
@@ -0,0 +1,79 @@
|
||||
<template>
|
||||
<view>
|
||||
<view class="ui-fixed" :class="{'fixed-top':position=='top','fixed-bottom':position=='bottom'}"
|
||||
:style="{zIndex:zIndex}">
|
||||
<slot></slot>
|
||||
</view>
|
||||
<view :style="{height:height+'px'}"></view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'fixed',
|
||||
props: {
|
||||
position: {
|
||||
type: [String],
|
||||
default () {
|
||||
return 'top'
|
||||
}
|
||||
},
|
||||
zIndex: {
|
||||
type: Number,
|
||||
default () {
|
||||
return 999
|
||||
}
|
||||
},
|
||||
refresh: {
|
||||
type: Boolean,
|
||||
default () {
|
||||
return false
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
height: uni.getSystemInfoSync().windowWidth * 100 / 750
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.setHeight();
|
||||
},
|
||||
onReady() {
|
||||
this.setHeight();
|
||||
},
|
||||
watch: {
|
||||
refresh(val) {
|
||||
console.log(val, "=======val")
|
||||
if (val) return
|
||||
this.setHeight()
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
setHeight() {
|
||||
var _this = this;
|
||||
var query = uni.createSelectorQuery().in(this);
|
||||
query.select('.ui-fixed').boundingClientRect(function(res) {
|
||||
_this.height = res.height;
|
||||
}).exec();
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<style>
|
||||
.ui-fixed {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.fixed-top {
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.fixed-bottom {
|
||||
bottom: 0;
|
||||
}
|
||||
</style>
|
||||
62
uniapp/uni-app/components/jyf-Parser/handler.sjs
Normal file
62
uniapp/uni-app/components/jyf-Parser/handler.sjs
Normal file
@@ -0,0 +1,62 @@
|
||||
var inlineTags = {
|
||||
abbr: true,
|
||||
b: true,
|
||||
big: true,
|
||||
code: true,
|
||||
del: true,
|
||||
em: true,
|
||||
font: true,
|
||||
i: true,
|
||||
ins: true,
|
||||
label: true,
|
||||
mark: true,
|
||||
q: true,
|
||||
s: true,
|
||||
small: true,
|
||||
span: true,
|
||||
strong: true,
|
||||
u: true
|
||||
}
|
||||
export default {
|
||||
getStyle: function(style, display) {
|
||||
var res = "";
|
||||
var reg = getRegExp("float\s*:\s*[^;]*", "i");
|
||||
if (reg.test(style)) res += reg.exec(style)[0];
|
||||
reg = getRegExp("margin[^;]*", "gi");
|
||||
var margin = reg.exec(style);
|
||||
while (margin) {
|
||||
res += (';' + margin[0]);
|
||||
margin = reg.exec(style);
|
||||
}
|
||||
reg = getRegExp("display\s*:\s*([^;]*)", "i");
|
||||
if (reg.test(style) && reg.exec(style)[1] != "flex") res += (';' + reg.exec(style)[0]);
|
||||
else res += (';display:' + display);
|
||||
reg = getRegExp("flex\s*:[^;]*", "i");
|
||||
if (reg.test(style)) res += (';' + reg.exec(style)[0]);
|
||||
reg = getRegExp("[^;\s]*width[^;]*", "ig");
|
||||
var width = reg.exec(style);
|
||||
while (width) {
|
||||
res += (';' + width[0]);
|
||||
width = reg.exec(style);
|
||||
}
|
||||
return res;
|
||||
},
|
||||
setImgStyle: function(item, imgMode) {
|
||||
if (imgMode == "widthFix")
|
||||
item.attrs.style = (item.attrs.style || '') + ";height:auto !important";
|
||||
if (getRegExp("[^-]width[^pev;]+").test(";" + item.attrs.style))
|
||||
item.attrs.style = (item.attrs.style || '') + ";width:100%";
|
||||
if (item.attrs.style)
|
||||
item.attrs.style = item.attrs.style.replace(getRegExp('margin[^;]*', "gi"), "");
|
||||
return [item];
|
||||
},
|
||||
setStyle: function(item) {
|
||||
if (item.attrs.style)
|
||||
item.attrs.style = item.attrs.style.replace(getRegExp("width[^;]*?%", "gi"), "width:100%").replace(getRegExp(
|
||||
'margin[^;]+', "gi"), "");
|
||||
return [item];
|
||||
},
|
||||
notContinue: function(item) {
|
||||
return !(item.c || inlineTags[item.name] || item["continue"]);
|
||||
}
|
||||
}
|
||||
56
uniapp/uni-app/components/jyf-Parser/handler.wxs
Normal file
56
uniapp/uni-app/components/jyf-Parser/handler.wxs
Normal file
@@ -0,0 +1,56 @@
|
||||
var inlineTags = {
|
||||
abbr: true,
|
||||
b: true,
|
||||
big: true,
|
||||
code: true,
|
||||
del: true,
|
||||
em: true,
|
||||
font: true,
|
||||
i: true,
|
||||
ins: true,
|
||||
label: true,
|
||||
mark: true,
|
||||
q: true,
|
||||
s: true,
|
||||
small: true,
|
||||
span: true,
|
||||
strong: true,
|
||||
u: true
|
||||
}
|
||||
module.exports = {
|
||||
getStyle: function(style, display) {
|
||||
var res = "";
|
||||
var reg = getRegExp("float[^;]+(?![\s\S]*?float)", "i");
|
||||
if (reg.test(style)) res += reg.exec(style)[0];
|
||||
reg = getRegExp("margin[^;]+", "gi");
|
||||
if (reg.test(style)) res += (';' + style.match(reg).join(';'));
|
||||
reg = getRegExp("display\s*:\s*([^;]*)(?![\s\S]*?display)", "i");
|
||||
if (reg.test(style) && reg.exec(style)[1] != "flex") res += (';' + reg.exec(style)[0]);
|
||||
else res += (';display:' + display);
|
||||
reg = getRegExp("flex[^;]*:[^;]+", "ig");
|
||||
if (reg.test(style)) res += (';' + style.match(reg).join(';'));
|
||||
reg = getRegExp("[^;\s]*width[^;]+", "ig");
|
||||
if (reg.test(style)) res += (';' + style.match(reg).join(';'));
|
||||
return res;
|
||||
},
|
||||
setImgStyle: function(item, imgMode, imgLoad) {
|
||||
if (imgMode == "widthFix") item.attrs.style = (item.attrs.style || '') + ";height:auto !important";
|
||||
if (item.attrs.style)
|
||||
item.attrs.style = item.attrs.style.replace(getRegExp("width[^;]*?%", "gi"), "width:100%").replace(getRegExp(
|
||||
'margin[^;]+', "gi"), "");
|
||||
if (!imgLoad) {
|
||||
delete item.attrs.src;
|
||||
item.attrs.style += ";width:20px !important;height:20px !important";
|
||||
}
|
||||
return [item];
|
||||
},
|
||||
setStyle: function(item) {
|
||||
if (item.attrs.style)
|
||||
item.attrs.style = item.attrs.style.replace(getRegExp("width[^;]*?%", "gi"), "width:100%").replace(getRegExp(
|
||||
'margin[^;]+', "gi"), "");
|
||||
return [item];
|
||||
},
|
||||
notContinue: function(item) {
|
||||
return !(item.c || inlineTags[item.name] || item["continue"]);
|
||||
}
|
||||
}
|
||||
622
uniapp/uni-app/components/jyf-Parser/index.vue
Normal file
622
uniapp/uni-app/components/jyf-Parser/index.vue
Normal file
@@ -0,0 +1,622 @@
|
||||
<!--
|
||||
parser 主模块组件
|
||||
github地址:https://github.com/jin-yufeng/Parser
|
||||
文档地址:https://jin-yufeng.github.io/Parser
|
||||
插件市场:https://ext.dcloud.net.cn/plugin?id=805
|
||||
author:JinYufeng
|
||||
-->
|
||||
<template>
|
||||
<view>
|
||||
<!--#ifdef H5-->
|
||||
<slot v-if="!html && !nodes.length"></slot>
|
||||
<div :id="'rtf' + uid" :style="(selectable ? 'user-select:text;-webkit-user-select:text;' : '') + (showWithAnimation ? ('opacity:0;' + showAnimation) : '')"></div>
|
||||
<!--#endif-->
|
||||
<!--#ifndef H5-->
|
||||
<slot v-if="!html[0].name && !html[0].type && !nodes.length"></slot>
|
||||
<!--#endif-->
|
||||
<!--#ifdef MP-ALIPAY-->
|
||||
<view class="_contain" :style="(selectable ? 'user-select:text;-webkit-user-select:text;' : '') + (showWithAnimation ? ('opacity:0;' + showAnimation) : '')">
|
||||
<trees :nodes="nodes.length ? nodes : (html[0].name || html[0].type ? html : [])" :imgMode="imgMode" />
|
||||
</view>
|
||||
<!--#endif-->
|
||||
<!--#ifndef MP-ALIPAY || H5-->
|
||||
<trees class="_contain" :style="'display:block;' + (selectable ? 'user-select:text;-webkit-user-select:text;' : '') + (showWithAnimation ? ('opacity:0;' + showAnimation) : '')"
|
||||
:nodes="nodes.length ? nodes : (html[0].name || html[0].type ? html : [])" :imgMode="imgMode" :loadVideo="loadVideo" />
|
||||
<!--#endif-->
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// #ifndef H5
|
||||
import trees from "./trees"
|
||||
var document; // document 补丁包,详见 https://jin-yufeng.github.io/Parser/#/instructions?id=document
|
||||
const parseHtmlSync = require('./libs/MpHtmlParser.js').parseHtmlSync;
|
||||
// #ifdef APP-PLUS
|
||||
const cache = {};
|
||||
// #endif
|
||||
// #ifndef APP-PLUS
|
||||
const cache = getApp().parserCache = {};
|
||||
// #endif
|
||||
const CssHandler = require("./libs/CssHandler.js");
|
||||
// 散列函数(计算 cache 的 key)
|
||||
const Hash = (str) => {
|
||||
for (var i = 0, hash = 5381, len = str.length; i < len; i++)
|
||||
hash += (hash << 5) + str.charCodeAt(i);
|
||||
return hash;
|
||||
};
|
||||
// #endif
|
||||
// 动画
|
||||
const showAnimation =
|
||||
"transition:400ms ease 0ms;transition-property:transform,opacity;transform-origin:50% 50% 0;-webkit-transition:400ms ease 0ms;-webkit-transform:;-webkit-transition-property:transform,opacity;-webkit-transform-origin:50% 50% 0;opacity: 1"
|
||||
const config = require('./libs/config.js');
|
||||
// #ifdef MP-WEIXIN || MP-QQ || MP-BAIDU || MP-TOUTIAO
|
||||
// 图片链接去重
|
||||
const Deduplication = (src) => {
|
||||
if (src.indexOf("http") != 0) return src;
|
||||
var newSrc = '';
|
||||
for (var i = 0; i < src.length; i++) {
|
||||
newSrc += (Math.random() >= 0.5 ? src[i].toUpperCase() : src[i].toLowerCase());
|
||||
if (src[i] == '/' && src[i - 1] != '/' && src[i + 1] != '/') break;
|
||||
}
|
||||
newSrc += src.substring(i + 1);
|
||||
return newSrc;
|
||||
}
|
||||
// #endif
|
||||
export default {
|
||||
name: 'parser',
|
||||
data() {
|
||||
return {
|
||||
// #ifdef APP-PLUS
|
||||
loadVideo: false,
|
||||
// #endif
|
||||
// #ifdef H5
|
||||
uid: this._uid,
|
||||
showAnimation: '',
|
||||
// #endif
|
||||
// #ifndef H5
|
||||
showAnimation: {},
|
||||
controls: {},
|
||||
// #endif
|
||||
nodes: []
|
||||
}
|
||||
},
|
||||
// #ifndef H5
|
||||
components: {
|
||||
trees
|
||||
},
|
||||
// #endif
|
||||
props: {
|
||||
'html': {
|
||||
type: null,
|
||||
default: null
|
||||
},
|
||||
'autocopy': {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// #ifndef MP-ALIPAY
|
||||
'autopause': {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// #endif
|
||||
'autopreview': {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
'autosetTitle': {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
'domain': {
|
||||
type: String,
|
||||
default: null
|
||||
},
|
||||
'imgMode': {
|
||||
type: String,
|
||||
default: 'default'
|
||||
},
|
||||
// #ifdef MP-WEIXIN || MP-QQ || H5 || APP-PLUS
|
||||
'lazyLoad': {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// #endif
|
||||
'selectable': {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
'tagStyle': {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
'showWithAnimation': {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
'useAnchor': {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
'useCache': {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
html(html) {
|
||||
this.setContent(html, undefined, true);
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.imgList = [];
|
||||
this.imgList.each = function(f) {
|
||||
for (var i = 0; i < this.length; i++) {
|
||||
// #ifdef MP-ALIPAY || APP-PLUS
|
||||
this[i] = f(this[i], i, this) || this[i];
|
||||
// #endif
|
||||
// #ifndef MP-ALIPAY || APP-PLUS
|
||||
var newSrc = f(this[i], i, this);
|
||||
if (newSrc) {
|
||||
if (this.includes(newSrc)) this[i] = Deduplication(newSrc);
|
||||
else this[i] = newSrc;
|
||||
}
|
||||
// #endif
|
||||
}
|
||||
}
|
||||
this.setContent(this.html, undefined, true);
|
||||
},
|
||||
// #ifdef H5
|
||||
beforeDestroy() {
|
||||
if (this._observer) this._observer.disconnect();
|
||||
},
|
||||
// #endif
|
||||
methods: {
|
||||
// #ifdef H5
|
||||
setContent(html, options, observed) {
|
||||
if (typeof options == "object")
|
||||
for (var key in options) {
|
||||
key = key.replace(/-(\w)/g, function() {
|
||||
return arguments[1].toUpperCase();
|
||||
})
|
||||
this[key] = options[key];
|
||||
}
|
||||
html = html || '';
|
||||
if (!html) {
|
||||
if (this.rtf) this.rtf.parentNode.removeChild(this.rtf);
|
||||
return;
|
||||
}
|
||||
if (typeof html != 'string') html = this.Dom2Str(html.nodes || html);
|
||||
// 处理 rpx
|
||||
if (/[0-9.]*?rpx/.test(html)) {
|
||||
const rpx = uni.getSystemInfoSync().screenWidth / 750;
|
||||
html = html.replace(/([0-9.]*?)rpx/g, function() {
|
||||
return parseFloat(arguments[1]) * rpx + "px";
|
||||
})
|
||||
}
|
||||
// 处理 tag-style 和 userAgentStyles
|
||||
var style = "<style>";
|
||||
for (var item in config.userAgentStyles)
|
||||
style += (item + '{' + config.userAgentStyles[item] + '}');
|
||||
for (var item in this.tagStyle)
|
||||
style += (item + '{' + this.tagStyle[item] + '}');
|
||||
style += "</style>";
|
||||
html = style + html;
|
||||
if (this.rtf) this.rtf.parentNode.removeChild(this.rtf);
|
||||
this.rtf = document.createElement('div');
|
||||
this.rtf.innerHTML = html;
|
||||
for (var style of this.rtf.getElementsByTagName("style")) {
|
||||
style.innerHTML = style.innerHTML.replace(/\s*body/g, "#rtf" + this._uid);
|
||||
style.setAttribute("scoped", "true");
|
||||
}
|
||||
// 懒加载
|
||||
if (this.lazyLoad && IntersectionObserver) {
|
||||
if (this._observer) this._observer.disconnect();
|
||||
this._observer = new IntersectionObserver(changes => {
|
||||
for (var change of changes) {
|
||||
if (change.isIntersecting) {
|
||||
change.target.src = change.target.getAttribute("data-src");
|
||||
change.target.removeAttribute("data-src");
|
||||
this._observer.unobserve(change.target);
|
||||
}
|
||||
}
|
||||
}, {
|
||||
rootMargin: "1000px 0px 1000px 0px"
|
||||
})
|
||||
}
|
||||
var component = this;
|
||||
// 获取标题
|
||||
var title = this.rtf.getElementsByTagName("title");
|
||||
if (title.length && this.autosetTitle)
|
||||
uni.setNavigationBarTitle({
|
||||
title: title[0].innerText
|
||||
})
|
||||
// 图片处理
|
||||
this.imgList.length = 0;
|
||||
var imgs = this.rtf.getElementsByTagName("img");
|
||||
for (var i = 0; i < imgs.length; i++) {
|
||||
var img = imgs[i];
|
||||
img.style.maxWidth = "100%";
|
||||
img.i = i;
|
||||
if (this.domain && img.getAttribute("src")[0] == "/") {
|
||||
if (img.getAttribute("src")[1] == "/")
|
||||
img.src = (this.domain.includes("://") ? this.domain.split("://")[0] : "http") + ':' + img.getAttribute("src");
|
||||
else img.src = this.domain + img.getAttribute("src");
|
||||
}
|
||||
component.imgList.push(img.src);
|
||||
if (img.parentElement.nodeName != 'A') {
|
||||
img.onclick = function() {
|
||||
if (!this.hasAttribute('ignore')) {
|
||||
var preview = true;
|
||||
this.ignore = () => preview = false;
|
||||
component.$emit('imgtap', this);
|
||||
if (preview && component.autopreview) {
|
||||
uni.previewImage({
|
||||
current: this.i,
|
||||
urls: component.imgList
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
img.onerror = function() {
|
||||
component.$emit('error', {
|
||||
source: "img",
|
||||
target: this
|
||||
});
|
||||
}
|
||||
if (component.lazyLoad && this._observer) {
|
||||
img.setAttribute("data-src", img.src);
|
||||
img.removeAttribute("src");
|
||||
this._observer.observe(img);
|
||||
}
|
||||
}
|
||||
// 链接处理
|
||||
var links = this.rtf.getElementsByTagName("a");
|
||||
for (var link of links) {
|
||||
link.onclick = function(e) {
|
||||
var jump = true,
|
||||
href = this.getAttribute("href");
|
||||
component.$emit('linkpress', {
|
||||
href,
|
||||
ignore: () => jump = false
|
||||
});
|
||||
if (jump && href) {
|
||||
if (href[0] == '#') {
|
||||
if (component.useAnchor) {
|
||||
component.navigateTo({
|
||||
id: href.substring(1)
|
||||
})
|
||||
}
|
||||
} else if (href.indexOf("http") == 0 || href.indexOf("//") == 0)
|
||||
return true;
|
||||
else {
|
||||
uni.navigateTo({
|
||||
url: href
|
||||
})
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// 视频处理
|
||||
var videos = this.rtf.getElementsByTagName("video");
|
||||
component.videoContexts = videos;
|
||||
for (var video of videos) {
|
||||
video.style.maxWidth = "100%";
|
||||
video.onerror = function() {
|
||||
component.$emit('error', {
|
||||
source: "video",
|
||||
target: this
|
||||
});
|
||||
}
|
||||
video.onplay = function() {
|
||||
if (component.autopause) {
|
||||
for (var video of component.videoContexts) {
|
||||
if (video != this)
|
||||
video.pause();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 音频处理
|
||||
var audios = this.rtf.getElementsByTagName("audios");
|
||||
for (var audio of audios) {
|
||||
audio.onerror = function(e) {
|
||||
component.$emit('error', {
|
||||
source: "audio",
|
||||
target: this
|
||||
});
|
||||
}
|
||||
}
|
||||
document.getElementById("rtf" + this._uid).appendChild(this.rtf);
|
||||
if (this.showWithAnimation)
|
||||
this.showAnimation = showAnimation;
|
||||
if (!observed) this.nodes = [0];
|
||||
this.$nextTick(() => {
|
||||
this.$emit("ready", this.rtf.getBoundingClientRect());
|
||||
})
|
||||
},
|
||||
Dom2Str(nodes) {
|
||||
var str = "";
|
||||
for (var node of nodes) {
|
||||
if (node.type == "text")
|
||||
str += node.text;
|
||||
else {
|
||||
str += ('<' + node.name);
|
||||
for (var attr in node.attrs || {})
|
||||
str += (' ' + attr + '="' + node.attrs[attr] + '"');
|
||||
if (!node.children || !node.children.length) str += "/>";
|
||||
else str += ('>' + this.Dom2Str(node.children) + "</" + node.name + '>');
|
||||
}
|
||||
}
|
||||
return str;
|
||||
},
|
||||
getText(whiteSpace = true) {
|
||||
if (!whiteSpace) return this.rtf.innerText.replace(/\s/g, '');
|
||||
return this.rtf.innerText;
|
||||
},
|
||||
navigateTo(obj) {
|
||||
if (!obj.id) {
|
||||
window.scrollTo(0, this.rtf.offsetTop);
|
||||
return obj.success ? obj.success({
|
||||
errMsg: "pageScrollTo:ok"
|
||||
}) : null;
|
||||
}
|
||||
var target = document.getElementById(obj.id);
|
||||
if (!target) return obj.fail ? obj.fail({
|
||||
errMsg: "Label Not Found"
|
||||
}) : null;
|
||||
uni.pageScrollTo({
|
||||
scrollTop: this.rtf.offsetTop + target.offsetTop,
|
||||
success: obj.success,
|
||||
fail: obj.fail
|
||||
});
|
||||
},
|
||||
// #endif
|
||||
// #ifndef H5
|
||||
setContent(html, options, observed) {
|
||||
if (typeof options == "object")
|
||||
for (var key in options) {
|
||||
key = key.replace(/-(\w)/g, function() {
|
||||
return arguments[1].toUpperCase();
|
||||
})
|
||||
this[key] = options[key];
|
||||
}
|
||||
if (this.showWithAnimation)
|
||||
this.showAnimation = showAnimation;
|
||||
if (!html) {
|
||||
if (observed) return;
|
||||
else this.nodes = [];
|
||||
} else if (typeof html == "string") {
|
||||
var res;
|
||||
// 缓存读取
|
||||
if (this.useCache) {
|
||||
var hash = Hash(html);
|
||||
if (cache[hash])
|
||||
res = cache[hash];
|
||||
else {
|
||||
res = parseHtmlSync(html, this);
|
||||
cache[hash] = res;
|
||||
}
|
||||
} else res = parseHtmlSync(html, this);
|
||||
this.nodes = res;
|
||||
this.$emit('parse', res);
|
||||
} else if (html.constructor == Array) {
|
||||
if (!observed) this.nodes = html;
|
||||
else this.nodes = [];
|
||||
// 非本插件产生的 array 需要进行一些转换
|
||||
if (html.length && html[0].PoweredBy != "Parser") {
|
||||
const Parser = {
|
||||
_imgNum: 0,
|
||||
_videoNum: 0,
|
||||
_audioNum: 0,
|
||||
_domain: this.domain,
|
||||
_protocol: this.domain ? (this.domain.includes("://") ? this.domain.split("://")[0] : "http") : undefined,
|
||||
_STACK: [],
|
||||
CssHandler: new CssHandler(this.tagStyle)
|
||||
};
|
||||
Parser.CssHandler.getStyle('');
|
||||
const DFS = (nodes) => {
|
||||
for (var node of nodes) {
|
||||
if (node.type == "text") continue;
|
||||
node.attrs = node.attrs || {};
|
||||
for (var item in node.attrs) {
|
||||
if (!config.trustAttrs[item]) node.attrs[item] = undefined;
|
||||
else if (typeof node.attrs[item] != "string") node.attrs[item] = node.attrs[item].toString();
|
||||
}
|
||||
config.LabelAttrsHandler(node, Parser);
|
||||
if (config.blockTags[node.name]) node.name = 'div';
|
||||
else if (!config.trustTags[node.name]) node.name = 'span';
|
||||
if (node.children && node.children.length) {
|
||||
Parser._STACK.push(node);
|
||||
DFS(node.children);
|
||||
Parser._STACK.pop();
|
||||
} else node.children = undefined;
|
||||
}
|
||||
}
|
||||
DFS(html);
|
||||
this.nodes = html;
|
||||
}
|
||||
} else if (typeof html == 'object' && html.nodes) {
|
||||
this.nodes = html.nodes;
|
||||
console.warn("Parser 类型错误:object 类型已废弃,请直接将 html 设置为 object.nodes (array 类型)");
|
||||
} else {
|
||||
return this.$emit('error', {
|
||||
source: "parse",
|
||||
errMsg: "传入的nodes数组格式不正确!应该传入的类型是array,实际传入的类型是:" + typeof html.nodes
|
||||
});
|
||||
}
|
||||
// #ifdef APP-PLUS
|
||||
this.loadVideo = false;
|
||||
// #endif
|
||||
if (document) this.document = new document("html", this.html || html, this);
|
||||
this.$nextTick(() => {
|
||||
this.imgList.length = 0;
|
||||
this.videoContexts = [];
|
||||
const getContext = (components) => {
|
||||
for (let component of components) {
|
||||
if (component.$options.name == "trees") {
|
||||
var observered = false;
|
||||
for (var item of component.nodes) {
|
||||
if (item.continue) continue;
|
||||
if (item.name == 'img') {
|
||||
if (item.attrs.src && item.attrs.i) {
|
||||
// #ifndef MP-ALIPAY || APP-PLUS
|
||||
if (this.imgList.indexOf(item.attrs.src) == -1)
|
||||
this.imgList[item.attrs.i] = item.attrs.src;
|
||||
else this.imgList[item.attrs.i] = Deduplication(item.attrs.src);
|
||||
// #endif
|
||||
// #ifdef MP-ALIPAY || APP-PLUS
|
||||
this.imgList[item.attrs.i] = item.attrs.src;
|
||||
// #endif
|
||||
}
|
||||
// #ifndef MP-ALIPAY
|
||||
if (!observered) {
|
||||
observered = true;
|
||||
if (this.lazyLoad && uni.createIntersectionObserver) {
|
||||
if (component._observer) component._observer.disconnect();
|
||||
component._observer = uni.createIntersectionObserver(component);
|
||||
component._observer.relativeToViewport({
|
||||
top: 1000,
|
||||
bottom: 1000
|
||||
}).observe('.img', res => {
|
||||
component.imgLoad = true;
|
||||
component._observer.disconnect();
|
||||
component._observer = null;
|
||||
})
|
||||
} else
|
||||
component.imgLoad = true;
|
||||
}
|
||||
// #endif
|
||||
}
|
||||
// #ifndef MP-ALIPAY
|
||||
else if (item.name == 'video') {
|
||||
var context = uni.createVideoContext(item.attrs.id, component);
|
||||
context.id = item.attrs.id;
|
||||
this.videoContexts.push(context);
|
||||
}
|
||||
// #endif
|
||||
// #ifdef MP-WEIXIN
|
||||
else if (item.name == 'audio' && item.attrs.autoplay)
|
||||
wx.createAudioContext(item.attrs.id, component).play();
|
||||
// #endif
|
||||
// 设置标题
|
||||
else if (item.name == "title") {
|
||||
if (item.children[0].type == "text" && item.children[0].text && this.autosetTitle)
|
||||
uni.setNavigationBarTitle({
|
||||
title: item.children[0].text
|
||||
})
|
||||
}
|
||||
// #ifdef MP-BAIDU || MP-ALIPAY
|
||||
if (item.attrs && item.attrs.id) {
|
||||
this.anchors = this.anchors || [];
|
||||
this.anchors.push({
|
||||
id: item.attrs.id,
|
||||
node: component
|
||||
})
|
||||
}
|
||||
// #endif
|
||||
}
|
||||
}
|
||||
if (component.$children.length)
|
||||
getContext(component.$children)
|
||||
}
|
||||
}
|
||||
// #ifdef MP-TOUTIAO
|
||||
setTimeout(() => {
|
||||
// #endif
|
||||
getContext(this.$children)
|
||||
uni.createSelectorQuery().in(this).select("._contain").boundingClientRect(res => {
|
||||
this.$emit("ready", res);
|
||||
}).exec();
|
||||
// #ifdef MP-TOUTIAO
|
||||
}, 200)
|
||||
// #endif
|
||||
// #ifdef APP-PLUS
|
||||
setTimeout(() => {
|
||||
this.loadVideo = true;
|
||||
}, 3000);
|
||||
// #endif
|
||||
})
|
||||
},
|
||||
getText(whiteSpace = true) {
|
||||
var text = "";
|
||||
const DFS = (node) => {
|
||||
if (node.type == "text") return text += node.text;
|
||||
else {
|
||||
if (whiteSpace && (((node.name == 'p' || node.name == "div" || node.name == "tr" || node.name == "li" ||
|
||||
/h[1-6]/.test(node.name)) && text && text[text.length - 1] != '\n') || node.name == "br"))
|
||||
text += '\n';
|
||||
for (var child of node.children || [])
|
||||
DFS(child);
|
||||
if (whiteSpace && (node.name == 'p' || node.name == "div" || node.name == "tr" || node.name == "li" || /h[1-6]/.test(
|
||||
node.name)) && text && text[text.length - 1] != '\n')
|
||||
text += '\n';
|
||||
else if (whiteSpace && node.name == "td") text += '\t';
|
||||
}
|
||||
}
|
||||
var nodes = ((this.nodes && this.nodes.length) ? this.nodes : (this.html[0] && (this.html[0].name || this.html[0].type) ?
|
||||
this.html : []));
|
||||
if (!nodes.length) return "";
|
||||
for (var node of nodes)
|
||||
DFS(node);
|
||||
return text;
|
||||
},
|
||||
navigateTo(obj) {
|
||||
var Scroll = (selector, component) => {
|
||||
const query = uni.createSelectorQuery().in(component ? component : this);
|
||||
query.select(selector).boundingClientRect();
|
||||
query.selectViewport().scrollOffset();
|
||||
query.exec(res => {
|
||||
if (!res || !res[0])
|
||||
return obj.fail ? obj.fail({
|
||||
errMsg: "Label Not Found"
|
||||
}) : null;
|
||||
uni.pageScrollTo({
|
||||
scrollTop: res[1].scrollTop + res[0].top,
|
||||
success: obj.success,
|
||||
fail: obj.fail
|
||||
})
|
||||
})
|
||||
}
|
||||
if (!obj.id) Scroll("._contain");
|
||||
else {
|
||||
// #ifndef MP-BAIDU || MP-ALIPAY
|
||||
Scroll('._contain >>> #' + obj.id + ', ._contain >>> .' + obj.id);
|
||||
// #endif
|
||||
// #ifdef MP-BAIDU || MP-ALIPAY
|
||||
for (var anchor of this.anchors) {
|
||||
if (anchor.id == obj.id) {
|
||||
Scroll("#" + obj.id + ", ." + obj.id, anchor.node);
|
||||
}
|
||||
}
|
||||
// #endif
|
||||
}
|
||||
},
|
||||
// #endif
|
||||
getVideoContext(id) {
|
||||
if (!id) return this.videoContexts;
|
||||
else {
|
||||
for (var video of this.videoContexts) {
|
||||
if (video.id == id) return video;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
/* #ifndef MP-BAIDU */
|
||||
:host {
|
||||
display: block;
|
||||
overflow: scroll;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
/* #endif */
|
||||
</style>
|
||||
149
uniapp/uni-app/components/jyf-Parser/libs/CssHandler.js
Normal file
149
uniapp/uni-app/components/jyf-Parser/libs/CssHandler.js
Normal file
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
解析和匹配 Css 的选择器
|
||||
github地址:https://github.com/jin-yufeng/Parser
|
||||
文档地址:https://jin-yufeng.github.io/Parser
|
||||
author:JinYufeng
|
||||
*/
|
||||
const userAgentStyles = require("./config.js").userAgentStyles;
|
||||
class CssHandler {
|
||||
constructor(tagStyle = {}) {
|
||||
this.styles = Object.assign({}, tagStyle);
|
||||
};
|
||||
getStyle(data) {
|
||||
var style = '';
|
||||
data = data.replace(/<[sS][tT][yY][lL][eE][\s\S]*?>([\s\S]*?)<\/[sS][tT][yY][lL][eE][\s\S]*?>/g, function() {
|
||||
style += arguments[1];
|
||||
return '';
|
||||
})
|
||||
this.styles = new CssParser(style, this.styles).parse();
|
||||
return data;
|
||||
};
|
||||
parseCss(css) {
|
||||
return new CssParser(css, {}, true).parse();
|
||||
};
|
||||
match(name, attrs) {
|
||||
var tmp, matched = ((tmp = this.styles[name]) ? (tmp + ';') : '');
|
||||
if (attrs.class) {
|
||||
var classes = attrs.class.split(' ');
|
||||
for (var i = 0; i < classes.length; i++)
|
||||
if (tmp = this.styles['.' + classes[i]])
|
||||
matched += (tmp + ';');
|
||||
}
|
||||
if (tmp = this.styles['#' + attrs.id])
|
||||
matched += tmp;
|
||||
return matched;
|
||||
};
|
||||
}
|
||||
module.exports = CssHandler;
|
||||
|
||||
function isBlankChar(c) {
|
||||
return c == ' ' || c == '\u00A0' || c == '\t' || c == '\r' || c == '\n' || c == '\f';
|
||||
};
|
||||
class CssParser {
|
||||
constructor(data, tagStyle, api) {
|
||||
this.data = data;
|
||||
this.res = tagStyle;
|
||||
if (!api)
|
||||
for (var item in userAgentStyles) {
|
||||
if (tagStyle[item]) tagStyle[item] = userAgentStyles[item] + ';' + tagStyle[item];
|
||||
else tagStyle[item] = userAgentStyles[item];
|
||||
}
|
||||
this._floor = 0;
|
||||
this._i = 0;
|
||||
this._list = [];
|
||||
this._comma = false;
|
||||
this._sectionStart = 0;
|
||||
this._state = this.Space;
|
||||
};
|
||||
parse() {
|
||||
for (; this._i < this.data.length; this._i++)
|
||||
this._state(this.data[this._i]);
|
||||
return this.res;
|
||||
};
|
||||
// 状态机
|
||||
Space(c) {
|
||||
if (c == '.' || c == '#' || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
|
||||
this._sectionStart = this._i;
|
||||
this._state = this.StyleName;
|
||||
} else if (c == '/' && this.data[this._i + 1] == '*')
|
||||
this.Comment();
|
||||
else if (!isBlankChar(c) && c != ';')
|
||||
this._state = this.Ignore;
|
||||
};
|
||||
Comment() {
|
||||
this._i = this.data.indexOf("*/", this._i);
|
||||
if (this._i == -1) this._i = this.data.length;
|
||||
this._i++;
|
||||
this._state = this.Space;
|
||||
};
|
||||
Ignore(c) {
|
||||
if (c == '{') this._floor++;
|
||||
else if (c == '}' && --this._floor <= 0) {
|
||||
this._list = [];
|
||||
this._state = this.Space;
|
||||
}
|
||||
};
|
||||
StyleName(c) {
|
||||
if (isBlankChar(c)) {
|
||||
this._list.push(this.data.substring(this._sectionStart, this._i));
|
||||
this._state = this.NameSpace;
|
||||
} else if (c == '{') {
|
||||
this._list.push(this.data.substring(this._sectionStart, this._i));
|
||||
this._floor = 1;
|
||||
this._sectionStart = this._i + 1;
|
||||
this.Content();
|
||||
} else if (c == ',') {
|
||||
this._list.push(this.data.substring(this._sectionStart, this._i));
|
||||
this._sectionStart = this._i + 1;
|
||||
this._comma = true;
|
||||
} else if (!(c >= 'a' && c <= 'z') && !(c >= 'A' && c <= 'Z') && !(c >= '0' && c <= '9') && c != '.' && c != '#' &&
|
||||
c != '-' && c != '_')
|
||||
this._state = this.Ignore;
|
||||
};
|
||||
NameSpace(c) {
|
||||
if (c == '{') {
|
||||
this._floor = 1;
|
||||
this._sectionStart = this._i + 1;
|
||||
this.Content();
|
||||
} else if (c == ',') {
|
||||
this._comma = true;
|
||||
this._sectionStart = this._i + 1;
|
||||
this._state = this.StyleName;
|
||||
} else if (!isBlankChar(c)) {
|
||||
if (this._comma) {
|
||||
this._state = this.StyleName;
|
||||
this._sectionStart = this._i;
|
||||
this._i--;
|
||||
this._comma = false;
|
||||
} else this._state = this.Ignore;
|
||||
}
|
||||
};
|
||||
Content() {
|
||||
this._i = this.data.indexOf('}', this._i);
|
||||
if (this._i == -1) this._i = this.data.length;
|
||||
// 去除空白符
|
||||
var flag = false,
|
||||
pos, content = this.data.substring(this._sectionStart, this._i);
|
||||
for (var i = 0; i < content.length; i++) {
|
||||
if (isBlankChar(content[i])) {
|
||||
if (!flag) {
|
||||
pos = i;
|
||||
flag = true;
|
||||
}
|
||||
} else {
|
||||
if (flag) {
|
||||
if (pos == 0) content = content.substring(i);
|
||||
else if (i - pos > 1) content = content.substring(0, pos) + (content[pos - 1] == ';' ? (pos--, '') : ' ') +
|
||||
content.substring(i);
|
||||
i = pos;
|
||||
flag = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (flag) content = content.substring(0, pos);
|
||||
for (var i = 0; i < this._list.length; i++)
|
||||
this.res[this._list[i]] = (this.res[this._list[i]] || '') + content;
|
||||
this._list = [];
|
||||
this._state = this.Space;
|
||||
}
|
||||
}
|
||||
430
uniapp/uni-app/components/jyf-Parser/libs/MpHtmlParser.js
Normal file
430
uniapp/uni-app/components/jyf-Parser/libs/MpHtmlParser.js
Normal file
@@ -0,0 +1,430 @@
|
||||
/*
|
||||
将 html 解析为适用于小程序 rich-text 的 DOM 结构
|
||||
github地址:https://github.com/jin-yufeng/Parser
|
||||
文档地址:https://jin-yufeng.github.io/Parser
|
||||
author:JinYufeng
|
||||
*/
|
||||
const CssHandler = require("./CssHandler.js");
|
||||
const config = require("./config.js");
|
||||
var emoji; // 需要使用 emoji 补丁包时将此行改为 const emoji = require("./emoji.js");
|
||||
|
||||
function isBlankChar(c) {
|
||||
return c == ' ' || c == '\u00A0' || c == '\t' || c == '\r' || c == '\n' || c == '\f';
|
||||
};
|
||||
class MpHtmlParser {
|
||||
constructor(data, options = {}, cb) {
|
||||
this.cb = cb;
|
||||
this.CssHandler = new CssHandler(options.tagStyle);
|
||||
this.data = data;
|
||||
this.DOM = [];
|
||||
// #ifdef MP-BAIDU || MP-TOUTIAO
|
||||
this._imgMode = options.imgMode;
|
||||
// #endif
|
||||
this._attrName = '';
|
||||
this._attrValue = '';
|
||||
this._attrs = {};
|
||||
this._domain = options.domain;
|
||||
this._protocol = options.domain ? (options.domain.includes("://") ? this._domain.split("://")[0] : "http") :
|
||||
undefined;
|
||||
this._i = 0;
|
||||
this._sectionStart = 0;
|
||||
this._state = this.Text;
|
||||
this._STACK = [];
|
||||
this._tagName = '';
|
||||
this._audioNum = 0;
|
||||
this._imgNum = 0;
|
||||
this._videoNum = 0;
|
||||
this._useAnchor = options.useAnchor;
|
||||
this._whiteSpace = false;
|
||||
};
|
||||
parse() {
|
||||
if (this.CssHandler) this.data = this.CssHandler.getStyle(this.data);
|
||||
if (emoji) this.data = emoji.parseEmoji(this.data);
|
||||
// 高亮处理
|
||||
if (config.highlight)
|
||||
this.data = this.data.replace(/<[pP][rR][eE]([\s\S]*?)>([\s\S]*?)<\/[pP][rR][eE][\s\S]*?>/g, function() {
|
||||
return "<pre" + arguments[1] + '>' + config.highlight(arguments[2], "<pre" + arguments[1] + '>') + "</pre>";
|
||||
})
|
||||
for (var len = this.data.length; this._i < len; this._i++)
|
||||
this._state(this.data[this._i]);
|
||||
if (this._state == this.Text) this.setText();
|
||||
while (this._STACK.length)
|
||||
this.popNode(this._STACK.pop());
|
||||
// #ifdef MP-BAIDU || MP-TOUTIAO
|
||||
const inlineTags = config.makeMap("abbr,b,big,code,del,em,font,i,ins,label,mark,q,s,small,span,strong,sub,sup,u")
|
||||
// 将顶层标签的一些样式提取出来给 rich-text
|
||||
const setContain = function(nodes) {
|
||||
for (var element of nodes) {
|
||||
if (element.type == "text")
|
||||
continue;
|
||||
if (!element.c) {
|
||||
var res = "";
|
||||
var style = element.attrs.style;
|
||||
var reg = /float[^;]+(?![\s\S]*?float)/i;
|
||||
if (reg.test(style)) res += reg.exec(style)[0];
|
||||
reg = /margin[^;]+/gi;
|
||||
if (reg.test(style)) res += (';' + style.match(reg).join(';'));
|
||||
reg = /display\s*:\s*([^;]*)(?![\s\S]*?display)/i;
|
||||
if (reg.test(style) && reg.exec(style)[1] != "flex") res += (';' + reg.exec(style)[0]);
|
||||
else if (inlineTags[element.name]) res += ";display:inline";
|
||||
else res += (";display:" + (element.name == 'img' ? 'inline-block' : 'block'));
|
||||
reg = /flex[^;]*:[^;]+/gi;
|
||||
if (reg.test(style)) res += (';' + style.match(reg).join(';'));
|
||||
reg = /[^;\s]*width[^;]+/gi;
|
||||
if (reg.test(style)) res += (';' + style.match(reg).join(';'));
|
||||
element.attrs.containStyle = res;
|
||||
if (/[^-]width[^pev;]+/.test(";" + style))
|
||||
element.attrs.style += ";width:100%";
|
||||
let addMargin = "";
|
||||
if (/margin\s*:/.test(style)) addMargin = ';margin:0';
|
||||
else if (/margin-top/.test(style)) addMargin = ';margin-top:0';
|
||||
else if (/margin-bottom/.test(style)) addMargin = ';margin-bottom:0';
|
||||
element.attrs.style = (element.attrs.style || '').replace(/margin[^;]*/gi, "");
|
||||
element.attrs.style += addMargin;
|
||||
} else setContain(element.children);
|
||||
}
|
||||
};
|
||||
setContain(this.DOM);
|
||||
// #endif
|
||||
if (this.DOM.length) this.DOM[0].PoweredBy = "Parser";
|
||||
// console.log(this.DOM)
|
||||
if (this.cb)
|
||||
this.cb(this.DOM)
|
||||
else return this.DOM;
|
||||
};
|
||||
// 设置属性
|
||||
setAttr() {
|
||||
if (config.trustAttrs[this._attrName])
|
||||
this._attrs[this._attrName] = (this._attrValue ? this._attrValue : (this._attrName == "src" ? "" : "true"));
|
||||
this._attrValue = '';
|
||||
while (isBlankChar(this.data[this._i])) this._i++;
|
||||
if (this.checkClose()) this.setNode();
|
||||
else this._state = this.AttrName;
|
||||
};
|
||||
// 设置文本节点
|
||||
setText() {
|
||||
var text = this.getSelection();
|
||||
if (text) {
|
||||
if (!this._whiteSpace) {
|
||||
// 移除空白符
|
||||
var flag = false,
|
||||
has = false,
|
||||
pos;
|
||||
for (var i = 0; i < text.length; i++) {
|
||||
if (isBlankChar(text[i])) {
|
||||
if (!flag) {
|
||||
pos = i;
|
||||
flag = true;
|
||||
}
|
||||
} else {
|
||||
has = true;
|
||||
if (flag) {
|
||||
if (i - pos > 1) text = text.substring(0, pos) + ' ' + text.substring(i);
|
||||
i = pos;
|
||||
flag = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (flag) text = text.substring(0, pos) + ' ';
|
||||
if (!text || !has) return;
|
||||
}
|
||||
// 检查实体
|
||||
// #ifdef MP-BAIDU || MP-ALIPAY || MP-TOUTIAO
|
||||
var entities = {
|
||||
lt: "<",
|
||||
gt: ">",
|
||||
amp: "&",
|
||||
quot: '"',
|
||||
apos: "'",
|
||||
nbsp: "\u00A0",
|
||||
ensp: "\u2002",
|
||||
emsp: "\u2003",
|
||||
ndash: "–",
|
||||
mdash: "—",
|
||||
middot: "·",
|
||||
lsquo: "‘",
|
||||
rsquo: "’",
|
||||
ldquo: "“",
|
||||
rdquo: "”",
|
||||
bull: "•",
|
||||
hellip: "…",
|
||||
permil: "‰",
|
||||
copy: "©",
|
||||
reg: "®",
|
||||
trade: "™",
|
||||
times: "×",
|
||||
divide: "÷",
|
||||
cent: "¢",
|
||||
pound: "£",
|
||||
yen: "¥",
|
||||
euro: "€",
|
||||
sect: "§"
|
||||
};
|
||||
// #endif
|
||||
var i = text.indexOf('&'),
|
||||
j, decode;
|
||||
while (i != -1 && i < text.length) {
|
||||
j = text.indexOf(';', i);
|
||||
if (j - i >= 2 && j - i <= 7) {
|
||||
var entity = text.substring(i + 1, j);
|
||||
// #ifdef MP-WEIXIN || MP-QQ || APP-PLUS
|
||||
if (!entity.includes("sp") && !entity.includes("lt") && !entity.includes("gt")) {
|
||||
decode = true
|
||||
break;
|
||||
}
|
||||
// #endif
|
||||
// #ifdef MP-BAIDU || MP-ALIPAY || MP-TOUTIAO
|
||||
if (entities[entity]) text = text.substring(0, i) + entities[entity] + text.substring(j + 1);
|
||||
// #endif
|
||||
}
|
||||
i = text.indexOf('&', i + 1);
|
||||
}
|
||||
var slibings = this._STACK.length ? this._STACK[this._STACK.length - 1].children : this.DOM;
|
||||
if (slibings.length && slibings[slibings.length - 1].type == "text") {
|
||||
slibings[slibings.length - 1].text += text;
|
||||
if (decode) slibings[slibings.length - 1].decode = true;
|
||||
} else
|
||||
slibings.push({
|
||||
type: "text",
|
||||
text,
|
||||
decode
|
||||
})
|
||||
}
|
||||
};
|
||||
// 设置元素节点
|
||||
setNode() {
|
||||
var slibings = this._STACK.length ? this._STACK[this._STACK.length - 1].children : this.DOM;
|
||||
var node = {
|
||||
name: this._tagName.toLowerCase(),
|
||||
attrs: this._attrs
|
||||
}
|
||||
config.LabelAttrsHandler(node, this);
|
||||
this._attrs = {};
|
||||
if (this.data[this._i] == '>') {
|
||||
if (!config.selfClosingTags[this._tagName]) {
|
||||
if (config.ignoreTags[node.name]) {
|
||||
var j = this._i;
|
||||
// 处理要被移除的标签
|
||||
while (this._i < this.data.length) {
|
||||
this._i = this.data.indexOf("</", this._i);
|
||||
if (this._i == -1) return this._i = this.data.length;
|
||||
this._i += 2;
|
||||
this._sectionStart = this._i;
|
||||
while (!isBlankChar(this.data[this._i]) && this.data[this._i] != '>' && this.data[this._i] != '/') this._i++;
|
||||
if (this.data.substring(this._sectionStart, this._i).toLowerCase() == node.name) {
|
||||
this._i = this.data.indexOf('>', this._i);
|
||||
if (this._i == -1) this._i = this.data.length;
|
||||
else this._sectionStart = this._i + 1;
|
||||
this._state = this.Text;
|
||||
// 处理svg
|
||||
if (node.name == "svg") {
|
||||
var src = this.data.substring(j, this._i + 1);
|
||||
if (!node.attrs.xmlns) src = " xmlns=\"http://www.w3.org/2000/svg\"" + src;
|
||||
this._i = j;
|
||||
while (this.data[j] != '<') j--;
|
||||
src = this.data.substring(j, this._i) + src;
|
||||
this._i = this._sectionStart - 1;
|
||||
node.name = "img";
|
||||
node.attrs = {
|
||||
src: "data:image/svg+xml;utf8," + src.replace(/#/g, "%23"),
|
||||
ignore: "true"
|
||||
}
|
||||
slibings.push(node);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return;
|
||||
} else this._STACK.push(node);
|
||||
node.children = [];
|
||||
}
|
||||
} else this._i++;
|
||||
this._sectionStart = this._i + 1;
|
||||
this._state = this.Text;
|
||||
if (!config.ignoreTags[node.name]) {
|
||||
// 检查空白符是否有效
|
||||
if (node.name == "pre" || (node.attrs.style && node.attrs.style.toLowerCase().includes("white-space") && node.attrs
|
||||
.style.toLowerCase().includes("pre"))) {
|
||||
this._whiteSpace = true;
|
||||
node.pre = true;
|
||||
}
|
||||
slibings.push(node);
|
||||
}
|
||||
};
|
||||
// 标签出栈处理
|
||||
popNode(node) {
|
||||
// 替换一些标签名
|
||||
if (config.blockTags[node.name]) node.name = 'div';
|
||||
else if (!config.trustTags[node.name]) node.name = 'span';
|
||||
// 空白符处理
|
||||
if (node.pre) {
|
||||
this._whiteSpace = false;
|
||||
node.pre = undefined;
|
||||
for (var i = 0; i < this._STACK.length; i++)
|
||||
if (this._STACK[i].pre)
|
||||
this._whiteSpace = true;
|
||||
}
|
||||
// 处理表格的边框
|
||||
if (node.name == 'table') {
|
||||
if (node.attrs.border)
|
||||
node.attrs.style = "border:" + node.attrs.border + "px solid gray;" + (node.attrs.style || '');
|
||||
if (node.attrs.hasOwnProperty("cellspacing"))
|
||||
node.attrs.style = "border-spacing:" + node.attrs.cellspacing + "px;" + (node.attrs.style || '');
|
||||
|
||||
function setBorder(elem) {
|
||||
if (elem.name == 'th' || elem.name == 'td') {
|
||||
if (node.attrs.border)
|
||||
elem.attrs.style = "border:" + node.attrs.border + "px solid gray;" + (elem.attrs.style || '');
|
||||
if (node.attrs.hasOwnProperty("cellpadding"))
|
||||
elem.attrs.style = "padding:" + node.attrs.cellpadding + "px;" + (elem.attrs.style || '');
|
||||
return;
|
||||
}
|
||||
if (elem.type == 'text') return;
|
||||
for (var i = 0; i < elem.children.length; i++)
|
||||
setBorder(elem.children[i]);
|
||||
}
|
||||
if (node.attrs.border || node.attrs.hasOwnProperty("cellpadding"))
|
||||
for (var i = 0; i < node.children.length; i++)
|
||||
setBorder(node.children[i]);
|
||||
}
|
||||
// 合并一些不必要的层,减小节点深度
|
||||
if (node.children.length == 1 && node.name == "div" && node.children[0].name == "div") {
|
||||
var child = node.children[0];
|
||||
node.attrs.style = node.attrs.style || '';
|
||||
child.attrs.style = child.attrs.style || '';
|
||||
if (node.attrs.style.includes("padding") && (node.attrs.style.includes("margin") || child.attrs.style.includes(
|
||||
"margin")) && node.attrs.style.includes("display") && child.attrs.style.includes("display") && !(node.attrs.id &&
|
||||
node.attrs.id) && !(node.attrs.class && child.attrs.class)) {
|
||||
if (child.attrs.style.includes("padding"))
|
||||
child.attrs.style = "box-sizing:border-box;" + child.attrs.style;
|
||||
node.attrs.style = node.attrs.style + ";" + child.attrs.style;
|
||||
node.attrs.id = (child.attrs.id || '') + (node.attrs.id || '');
|
||||
node.attrs.class = (child.attrs.class || '') + (node.attrs.class || '');
|
||||
node.children = child.children;
|
||||
}
|
||||
}
|
||||
// 多层样式处理
|
||||
if (this.CssHandler.pop)
|
||||
this.CssHandler.pop(node);
|
||||
};
|
||||
// 工具函数
|
||||
checkClose() {
|
||||
if (this.data[this._i] == '>' || (this.data[this._i] == '/' && this.data[this._i + 1] == '>'))
|
||||
return true;
|
||||
return false;
|
||||
};
|
||||
getSelection(trim) {
|
||||
var str = (this._sectionStart == this._i ? '' : this.data.substring(this._sectionStart, this._i));
|
||||
while (trim && isBlankChar(this.data[++this._i]));
|
||||
if (trim) this._i--;
|
||||
this._sectionStart = this._i + 1;
|
||||
return str;
|
||||
};
|
||||
// 状态机
|
||||
Text(c) {
|
||||
if (c == '<') {
|
||||
var next = this.data[this._i + 1];
|
||||
if ((next >= 'a' && next <= 'z') || (next >= 'A' && next <= 'Z')) {
|
||||
this.setText();
|
||||
this._state = this.TagName;
|
||||
} else if (next == '/') {
|
||||
this.setText();
|
||||
this._i++;
|
||||
next = this.data[this._i + 1];
|
||||
if ((next >= 'a' && next <= 'z') || (next >= 'A' && next <= 'Z')) {
|
||||
this._sectionStart = this._i + 1;
|
||||
this._state = this.EndTag;
|
||||
} else
|
||||
this._state = this.Comment;
|
||||
} else if (next == '!') {
|
||||
this.setText();
|
||||
this._state = this.Comment;
|
||||
}
|
||||
}
|
||||
};
|
||||
Comment() {
|
||||
if (this.data.substring(this._i + 1, this._i + 3) == "--" || this.data.substring(this._i + 1, this._i + 7) ==
|
||||
"[CDATA[") {
|
||||
this._i = this.data.indexOf("-->", this._i + 1);
|
||||
if (this._i == -1) return this._i = this.data.length;
|
||||
else this._i = this._i + 2;
|
||||
} else {
|
||||
this._i = this.data.indexOf(">", this._i + 1);
|
||||
if (this._i == -1) return this._i = this.data.length;
|
||||
}
|
||||
this._sectionStart = this._i + 1;
|
||||
this._state = this.Text;
|
||||
};
|
||||
TagName(c) {
|
||||
if (isBlankChar(c)) {
|
||||
this._tagName = this.getSelection(true);
|
||||
if (this.checkClose()) this.setNode();
|
||||
else this._state = this.AttrName;
|
||||
} else if (this.checkClose()) {
|
||||
this._tagName = this.getSelection();
|
||||
this.setNode();
|
||||
}
|
||||
};
|
||||
AttrName(c) {
|
||||
if (isBlankChar(c)) {
|
||||
this._attrName = this.getSelection(true).toLowerCase();
|
||||
if (this.data[this._i] == '=') {
|
||||
while (isBlankChar(this.data[++this._i]));
|
||||
this._sectionStart = this._i;
|
||||
this._i--;
|
||||
this._state = this.AttrValue;
|
||||
} else this.setAttr();
|
||||
} else if (c == '=') {
|
||||
this._attrName = this.getSelection().toLowerCase();
|
||||
while (isBlankChar(this.data[++this._i]));
|
||||
this._sectionStart = this._i;
|
||||
this._i--;
|
||||
this._state = this.AttrValue;
|
||||
} else if (this.checkClose()) {
|
||||
this._attrName = this.getSelection().toLowerCase();
|
||||
this.setAttr();
|
||||
}
|
||||
};
|
||||
AttrValue(c) {
|
||||
if (c == '"' || c == "'") {
|
||||
this._sectionStart++;
|
||||
if ((this._i = this.data.indexOf(c, this._i + 1)) == -1) return this._i = this.data.length;
|
||||
} else
|
||||
for (; !isBlankChar(this.data[this._i] && this.data[this._i] != '/' && this.data[this._i] != '>'); this._i++);
|
||||
this._attrValue = this.getSelection();
|
||||
while (this._attrValue.includes(""")) this._attrValue = this._attrValue.replace(""", '');
|
||||
this.setAttr();
|
||||
};
|
||||
EndTag(c) {
|
||||
if (isBlankChar(c) || c == '>' || c == '/') {
|
||||
var name = this.getSelection().toLowerCase();
|
||||
var flag = false;
|
||||
for (var i = this._STACK.length - 1; i >= 0; i--)
|
||||
if (this._STACK[i].name == name) {
|
||||
flag = true;
|
||||
break;
|
||||
}
|
||||
if (flag) {
|
||||
var node;
|
||||
while (flag) {
|
||||
node = this._STACK.pop();
|
||||
if (node.name == name) flag = false;
|
||||
this.popNode(node);
|
||||
}
|
||||
} else if (name == 'p' || name == "br") {
|
||||
var slibings = this._STACK.length ? this._STACK[this._STACK.length - 1].children : this.DOM;
|
||||
var node = {
|
||||
name
|
||||
}
|
||||
slibings.push(node);
|
||||
}
|
||||
this._i = this.data.indexOf('>', this._i);
|
||||
if (this._i == -1) this._i = this.data.length;
|
||||
else this._state = this.Text;
|
||||
}
|
||||
};
|
||||
};
|
||||
module.exports = {
|
||||
parseHtml: (data, options) => new Promise((resolve) => new MpHtmlParser(data, options, resolve).parse()),
|
||||
parseHtmlSync: (data, options) => new MpHtmlParser(data, options).parse()
|
||||
};
|
||||
247
uniapp/uni-app/components/jyf-Parser/libs/config.js
Normal file
247
uniapp/uni-app/components/jyf-Parser/libs/config.js
Normal file
@@ -0,0 +1,247 @@
|
||||
// <<<<<<< HEAD
|
||||
/* 配置文件 */
|
||||
// =======
|
||||
/* 配置文件 xxx*/
|
||||
// >>>>>>> 53c74b30a29ef2e569158438db4f5df4b7480643
|
||||
function makeMap(str) {
|
||||
var map = Object.create(null),
|
||||
list = str.split(',');
|
||||
for (var item of list)
|
||||
map[item] = true;
|
||||
return map;
|
||||
}
|
||||
// 信任的属性列表,不在列表中的属性将被移除
|
||||
const trustAttrs = makeMap(
|
||||
"align,alt,app-id,appId,"
|
||||
// #ifdef MP-BAIDU
|
||||
+
|
||||
"appid,apid,"
|
||||
// #endif
|
||||
+
|
||||
"author,autoplay,border,cellpadding,cellspacing,class,color,colspan,controls,data-src,dir,face,height,href,id,ignore,loop,muted,name,path,poster,rowspan,size,span,src,start,style,type,lbType,lbtype,"
|
||||
// #ifdef MP-WEIXIN || MP-QQ
|
||||
+
|
||||
"unit-id,unitId,"
|
||||
// #endif
|
||||
+
|
||||
"width,xmlns"
|
||||
);
|
||||
// 信任的标签,将保持标签名不变
|
||||
const trustTags = makeMap(
|
||||
"a,abbr,ad,audio,b,blockquote,br,code,col,colgroup,dd,del,dl,dt,div,em,fieldset,h1,h2,h3,h4,h5,h6,hr,i,img,ins,label,legend,li,ol,p,q,source,span,strong,sub,sup,table,tbody,td,tfoot,th,thead,tr,title,u,ul,video,iframe"
|
||||
);
|
||||
// 块级标签,将被转为 div
|
||||
const blockTags = makeMap("address,article,aside,body,center,cite,footer,header,html,nav,pre,section");
|
||||
// 被移除的标签(其中 svg 系列标签会被转为图片)
|
||||
const ignoreTags = makeMap(
|
||||
"area,base,basefont,canvas,circle,command,ellipse,embed,frame,head,input,isindex,keygen,line,link,map,meta,param,path,polygon,rect,script,source,svg,textarea,track,use,wbr,"
|
||||
);
|
||||
// 只能用 rich-text 显示的标签(其中图片不能预览、不能显示视频、音频等)
|
||||
const richOnlyTags = makeMap(
|
||||
"a,ad,audio,colgroup,fieldset,legend,li,ol,sub,sup,table,tbody,td,tfoot,th,thead,tr,ul,video,iframe,");
|
||||
// 自闭合标签
|
||||
const selfClosingTags = makeMap(
|
||||
"area,base,basefont,br,col,circle,ellipse,embed,frame,hr,img,input,isindex,keygen,line,link,meta,param,path,polygon,rect,source,track,use,wbr,"
|
||||
);
|
||||
// 默认的标签样式
|
||||
var userAgentStyles = {
|
||||
a: "color:#366092;word-break:break-all;padding:1.5px 0 1.5px 0",
|
||||
address: "font-style:italic",
|
||||
blockquote: "background-color:#f6f6f6;border-left:3px solid #dbdbdb;color:#6c6c6c;padding:5px 0 5px 10px",
|
||||
center: "text-align:center",
|
||||
cite: "font-style:italic",
|
||||
code: "padding:0 1px 0 1px;margin-left:2px;margin-right:2px;background-color:#f8f8f8;border-radius:3px",
|
||||
dd: "margin-left:40px",
|
||||
img: "max-width:100%",
|
||||
mark: "background-color:yellow",
|
||||
pre: "font-family:monospace;white-space:pre;overflow:scroll",
|
||||
s: "text-decoration:line-through",
|
||||
u: "text-decoration:underline"
|
||||
};
|
||||
// #ifndef MP-ALIPAY || H5
|
||||
const SDKVersion = uni.getSystemInfoSync().SDKVersion;
|
||||
|
||||
function versionHigherThan(version = '') {
|
||||
var v1 = SDKVersion.split('.'),
|
||||
v2 = version.split('.');
|
||||
while (v1.length != v2.length)
|
||||
v1.length < v2.length ? v1.push('0') : v2.push('0');
|
||||
for (var i = 0; i < v1.length; i++) {
|
||||
if (v1[i] == v2[i]) continue;
|
||||
if (parseInt(v1[i]) > parseInt(v2[i])) return true;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
// #endif
|
||||
// #ifdef MP-WEIXIN || MP-QQ
|
||||
// 版本兼容
|
||||
if (versionHigherThan("2.7.1")) {
|
||||
trustTags.bdi = true;
|
||||
trustTags.bdo = true;
|
||||
trustTags.caption = true;
|
||||
trustTags.rt = true;
|
||||
trustTags.ruby = true;
|
||||
ignoreTags.rp = true;
|
||||
trustTags.big = true;
|
||||
trustTags.small = true;
|
||||
trustTags.pre = true;
|
||||
trustTags.iframe = true;
|
||||
richOnlyTags.bdi = true;
|
||||
richOnlyTags.bdo = true;
|
||||
richOnlyTags.caption = true;
|
||||
richOnlyTags.rt = true;
|
||||
richOnlyTags.ruby = true;
|
||||
richOnlyTags.pre = true;
|
||||
blockTags.pre = undefined;
|
||||
} else {
|
||||
blockTags.caption = true;
|
||||
userAgentStyles.big = "display:inline;font-size:1.2em";
|
||||
userAgentStyles.small = "display:inline;font-size:0.8em";
|
||||
}
|
||||
// #endif
|
||||
function bubbling(Parser) {
|
||||
for (var i = Parser._STACK.length - 1; i >= 0; i--) {
|
||||
if (!richOnlyTags[Parser._STACK[i].name])
|
||||
Parser._STACK[i].c = 1;
|
||||
else return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
module.exports = {
|
||||
// 高亮处理函数
|
||||
highlight: null,
|
||||
// 处理标签的属性,需要通过组件递归方式显示的标签需要调用 bubbling(Parser)
|
||||
LabelAttrsHandler(node, Parser) {
|
||||
node.attrs.style = Parser.CssHandler.match(node.name, node.attrs, node) + (node.attrs.style || '');
|
||||
switch (node.name) {
|
||||
case "ul":
|
||||
case "ol":
|
||||
case "li":
|
||||
case "dd":
|
||||
case "dl":
|
||||
case "dt":
|
||||
case "div":
|
||||
case "span":
|
||||
case "em":
|
||||
case 'p':
|
||||
let default_p_style = "max-width: 100% !important;display:block;"
|
||||
if (node.attrs.style) {
|
||||
node.attrs.style = node.attrs.style.includes('width:') ? default_p_style : node.attrs.style + default_p_style
|
||||
}
|
||||
if (node.attrs.align) {
|
||||
node.attrs.style = "text-align:" + node.attrs.align + ';' + node.attrs.style;
|
||||
node.attrs.align = undefined;
|
||||
}
|
||||
break;
|
||||
case "img":
|
||||
if (node.attrs.height) {
|
||||
node.attrs.height = 'auto'
|
||||
}
|
||||
let default_style = "max-width: 100% !important;display:block;"
|
||||
if (node.attrs.style) {
|
||||
node.attrs.style = node.attrs.style.includes('height:') ? default_style : node.attrs.style + default_style
|
||||
}
|
||||
if (node.attrs["data-src"]) {
|
||||
node.attrs.src = node.attrs.src || node.attrs["data-src"];
|
||||
node.attrs["data-src"] = undefined;
|
||||
}
|
||||
// #ifdef MP-BAIDU || MP-TOUTIAO
|
||||
if (Parser._imgMode == "widthFix") node.attrs.style = node.attrs.style + ";height:auto !important;";
|
||||
// #endif
|
||||
if (node.attrs.src) {
|
||||
if (!node.attrs.ignore) {
|
||||
if (bubbling(Parser)) node.attrs.i = (Parser._imgNum++).toString();
|
||||
else node.attrs.ignore = "true";
|
||||
}
|
||||
if (Parser._domain && node.attrs.src[0] == '/') {
|
||||
if (node.attrs.src[1] == '/') node.attrs.src = Parser._protocol + ":" + node.attrs.src;
|
||||
else node.attrs.src = Parser._domain + node.attrs.src;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'a':
|
||||
case "ad":
|
||||
bubbling(Parser);
|
||||
break;
|
||||
case "font":
|
||||
if (node.attrs.color) {
|
||||
node.attrs.style = "color:" + node.attrs.color + ';' + node.attrs.style;
|
||||
node.attrs.color = undefined;
|
||||
}
|
||||
if (node.attrs.face) {
|
||||
node.attrs.style = "font-family:" + node.attrs.face + ';' + node.attrs.style;
|
||||
node.attrs.face = undefined;
|
||||
}
|
||||
if (node.attrs.size) {
|
||||
var size = parseInt(node.attrs.size);
|
||||
if (size < 1) size = 1;
|
||||
else if (size > 7) size = 7;
|
||||
var map = ["xx-small", "x-small", "small", "medium", "large", "x-large", "xx-large"];
|
||||
node.attrs.style = "font-size:" + map[size - 1] + ';' + node.attrs.style;
|
||||
node.attrs.size = undefined;
|
||||
}
|
||||
break;
|
||||
case 'iframe':
|
||||
case "video":
|
||||
case "audio":
|
||||
node.attrs.loop = node.attrs.hasOwnProperty('loop') || false;
|
||||
node.attrs.controls = node.attrs.hasOwnProperty(
|
||||
'controls') || true;
|
||||
node.attrs.autoplay = node.attrs.hasOwnProperty('autoplay') || false;
|
||||
if (node.attrs.id) Parser['_' + node.name + "Num"]++;
|
||||
else node.attrs.id = (node.name + (++Parser['_' + node.name + "Num"]));
|
||||
if (node.name == "video") {
|
||||
node.attrs.style = node.attrs.style || '';
|
||||
if (node.attrs.width) {
|
||||
node.attrs.style = "width:" + parseFloat(node.attrs.width) + (node.attrs.height.includes('%') ? '%' : "px") +
|
||||
';' + node.attrs.style;
|
||||
node.attrs.width = undefined;
|
||||
}
|
||||
if (node.attrs.height) {
|
||||
node.attrs.style = "height:" + parseFloat(node.attrs.height) + (node.attrs.height.includes('%') ? '%' : "px") +
|
||||
';' + node.attrs.style;
|
||||
node.attrs.height = undefined;
|
||||
}
|
||||
if (Parser._videoNum > 3) node.lazyLoad = true;
|
||||
}
|
||||
// 新增iframe【create_by_xx】
|
||||
if (node.name == 'iframe') {
|
||||
// console.log(node.attrs, "====iframe attrs");
|
||||
}
|
||||
node.attrs.source = [];
|
||||
if (node.attrs.src) node.attrs.source.push(node.attrs.src);
|
||||
if (!node.attrs.controls && !node.attrs.autoplay)
|
||||
console.warn("存在没有controls属性的 " + node.name + " 标签,可能导致无法播放", node);
|
||||
bubbling(Parser);
|
||||
break;
|
||||
case "source":
|
||||
var parent = Parser._STACK[Parser._STACK.length - 1];
|
||||
if (parent && (parent.name == "video" || parent.name == "audio")) {
|
||||
parent.attrs.source.push(node.attrs.src);
|
||||
if (!parent.attrs.src) parent.attrs.src = node.attrs.src;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (Parser._domain && node.attrs.style.includes("url"))
|
||||
node.attrs.style = node.attrs.style.replace(/url\s*\(['"\s]*(\S*?)['"\s]*\)/, function() {
|
||||
var src = arguments[1];
|
||||
if (src && src[0] == '/') {
|
||||
if (src[1] == '/') return "url(" + Parser._protocol + ':' + src + ')';
|
||||
else return "url(" + Parser._domain + src + ')';
|
||||
} else return arguments[0];
|
||||
})
|
||||
if (!node.attrs.style) node.attrs.style = undefined;
|
||||
if (Parser._useAnchor && node.attrs.id) bubbling(Parser);
|
||||
},
|
||||
trustAttrs,
|
||||
trustTags,
|
||||
blockTags,
|
||||
ignoreTags,
|
||||
selfClosingTags,
|
||||
userAgentStyles,
|
||||
// #ifndef MP-ALIPAY || H5
|
||||
versionHigherThan,
|
||||
// #endif
|
||||
makeMap
|
||||
}
|
||||
392
uniapp/uni-app/components/jyf-Parser/trees.vue
Normal file
392
uniapp/uni-app/components/jyf-Parser/trees.vue
Normal file
@@ -0,0 +1,392 @@
|
||||
<!--
|
||||
trees 递归显示组件
|
||||
github地址:https://github.com/jin-yufeng/Parser
|
||||
文档地址:https://jin-yufeng.github.io/Parser
|
||||
插件市场:https://ext.dcloud.net.cn/plugin?id=805
|
||||
author:JinYufeng
|
||||
-->
|
||||
<template>
|
||||
<view style="display: inherit; white-space: inherit;">
|
||||
<block v-for="(item, index) in nodes" v-bind:key="index">
|
||||
<!--#ifdef MP-WEIXIN || MP-QQ || MP-ALIPAY || APP-PLUS-->
|
||||
<block v-if="handler.notContinue(item)">
|
||||
<!--#endif-->
|
||||
<!--#ifdef MP-BAIDU || MP-TOUTIAO-->
|
||||
<block v-if="!item.c">
|
||||
<!--#endif-->
|
||||
<!--图片-->
|
||||
<!--#ifdef MP-WEIXIN || MP-QQ || MP-ALIPAY || APP-PLUS-->
|
||||
<rich-text v-if="item.name=='img'" :id="item.attrs.id" class="img" :style="'text-indent:0;'+handler.getStyle(item.attrs.style, 'inline-block')"
|
||||
:nodes='handler.setImgStyle(item, imgMode, imgLoad)' :data-attrs="item.attrs" @tap='previewEvent' />
|
||||
<!--#endif-->
|
||||
<!--#ifdef MP-BAIDU || MP-TOUTIAO-->
|
||||
<rich-text v-if="item.name=='img'" :id="item.attrs.id" :style="'text-indent:0;'+item.attrs.containStyle" :nodes='[item]'
|
||||
:data-attrs="item.attrs" @tap='previewEvent' />
|
||||
<!--#endif-->
|
||||
<!--文本-->
|
||||
<!--#ifdef MP-WEIXIN || MP-QQ || APP-PLUS-->
|
||||
<block v-else-if="item.type=='text'">
|
||||
<text v-if="!item.decode" decode>{{item.text}}</text>
|
||||
<rich-text v-else style="display:inline-block" :nodes="[item]"></rich-text>
|
||||
</block>
|
||||
<!--#endif-->
|
||||
<!--#ifdef MP-ALIPAY-->
|
||||
<text v-else-if="item.type=='text'" decode>{{item.text}}</text>
|
||||
<!--#endif-->
|
||||
<text v-else-if="item.name=='br'">\n</text>
|
||||
<!--视频-->
|
||||
<block v-else-if="item.name=='video'">
|
||||
<!--#ifdef APP-PLUS-->
|
||||
<view v-if="(!loadVideo||item.lazyLoad)&&!controls[item.attrs.id].play" :id="item.attrs.id" :class="'_video '+(item.attrs.class||'')"
|
||||
:style="item.attrs.style||''" @tap="_loadVideo" />
|
||||
<!--#endif-->
|
||||
<!--#ifndef APP-PLUS-->
|
||||
<view v-if="item.lazyLoad&&!controls[item.attrs.id].play" :id="item.attrs.id" :class="'_video '+(item.attrs.class||'')"
|
||||
:style="item.attrs.style||''" @tap="_loadVideo" />
|
||||
<!--#endif-->
|
||||
<video v-else :src="controls[item.attrs.id]?item.attrs.source[controls[item.attrs.id].index] : item.attrs.src"
|
||||
:id="item.attrs.id" :loop="item.attrs.loop" :controls="item.attrs.controls" :autoplay="item.attrs.autoplay||(controls[item.attrs.id]&&controls[item.attrs.id].play)"
|
||||
:unit-id="item.attrs['unit-id']" :class="item.attrs.class" :muted="item.attrs.muted" :style="item.attrs.style||''"
|
||||
:data-source="item.attrs.source" @play="playEvent" @error="videoError" />
|
||||
</block>
|
||||
<!-- iframe 【create_by_xx】-->
|
||||
<block v-else-if="item.name=='iframe'">
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<!-- 腾讯视频 -->
|
||||
<txv-video :vid="item.attrs.src" :playerid="item.attrs.src" width="100%" height="100%" :controls="true" :autoplay="false"
|
||||
:isHiddenStop="true" v-if="item.attrs.lbType=='vid' || item.attrs.lbtype=='vid'">
|
||||
</txv-video>
|
||||
<!-- #endif -->
|
||||
</block>
|
||||
<!--音频-->
|
||||
<audio v-else-if="item.name=='audio'" :src="controls[item.attrs.id]?item.attrs.source[controls[item.attrs.id].index] : item.attrs.src"
|
||||
:id="item.attrs.id" :loop="item.attrs.loop" :controls="item.attrs.controls" :poster="item.attrs.poster" :name="item.attrs.name"
|
||||
:author="item.attrs.author" :class="item.attrs.class" :style="item.attrs.style||''" :data-source="item.attrs.source"
|
||||
@error="audioError" />
|
||||
<!--链接-->
|
||||
<view v-else-if="item.name=='a'" :class="'_a '+(item.attrs.class||'')" :style="item.attrs.style||''" :data-attrs="item.attrs"
|
||||
hover-class="navigator-hover" :hover-start-time="25" :hover-stay-time="300" @tap="tapEvent">
|
||||
<trees :nodes="item.children" :imgMode="imgMode" />
|
||||
</view>
|
||||
<!--广告-->
|
||||
<!--#ifdef MP-WEIXIN || MP-QQ-->
|
||||
<ad v-else-if="item.name=='ad'" :unit-id="item.attrs['unit-id']" :class="item.attrs.class||''" :style="item.attrs.style||''"
|
||||
@error="adError"></ad>
|
||||
<!--#endif-->
|
||||
<!--#ifdef MP-BAIDU-->
|
||||
<ad v-else-if="item.name=='ad'" :appid="item.attrs.appid" :apid="item.attrs.apid" :type="item.attrs.type" :class="item.attrs.class||''"
|
||||
:style="item.attrs.style" @error="adError"></ad>
|
||||
<!--#endif-->
|
||||
<!--富文本-->
|
||||
<!--#ifdef MP-WEIXIN || MP-QQ || MP-ALIPAY || APP-PLUS-->
|
||||
<rich-text v-else :id="item.attrs.id" :class="'__'+item.name" :style="''+handler.getStyle(item.attrs.style, 'block')"
|
||||
:nodes="handler.setStyle(item)" />
|
||||
<!--#endif-->
|
||||
<!--#ifdef MP-BAIDU || MP-TOUTIAO-->
|
||||
<rich-text v-else :id="item.attrs.id" :style="item.attrs?item.attrs.containStyle:''" :nodes="[item]" />
|
||||
<!--#endif-->
|
||||
</block>
|
||||
<!--#ifdef MP-ALIPAY-->
|
||||
<view v-else :id="item.attrs.id" :class="'_'+item.name+' '+(item.attrs.class||'')" :style="item.attrs.style||''">
|
||||
<trees :nodes="item.children" :imgMode="imgMode" />
|
||||
</view>
|
||||
<!--#endif-->
|
||||
<!--#ifndef MP-ALIPAY-->
|
||||
<trees v-else :class="item.attrs.id+' _'+item.name+' '+(item.attrs.class||'')" :style="item.attrs.style||''" :nodes="item.children"
|
||||
:imgMode="imgMode" :loadVideo="loadVideo" />
|
||||
<!--#endif-->
|
||||
</block>
|
||||
</view>
|
||||
</template>
|
||||
<script module="handler" lang="wxs" src="./handler.wxs"></script>
|
||||
<script module="handler" lang="sjs" src="./handler.sjs"></script>
|
||||
<script>
|
||||
import trees from "./trees"
|
||||
export default {
|
||||
components: {
|
||||
trees
|
||||
},
|
||||
name: 'trees',
|
||||
data() {
|
||||
return {
|
||||
controls: {},
|
||||
// #ifdef MP-WEIXIN || MP-QQ || APP-PLUS
|
||||
imgLoad: true
|
||||
// #endif
|
||||
}
|
||||
},
|
||||
props: {
|
||||
nodes: {
|
||||
type: Array,
|
||||
default: []
|
||||
},
|
||||
// #ifdef APP-PLUS
|
||||
loadVideo: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// #endif
|
||||
imgMode: {
|
||||
type: String,
|
||||
default: "default"
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// 获取顶层组件
|
||||
this._top = this.$parent;
|
||||
while (this._top.$options.name != 'parser') {
|
||||
if (this._top._top) {
|
||||
this._top = this._top._top;
|
||||
break;
|
||||
}
|
||||
this._top = this._top.$parent;
|
||||
}
|
||||
},
|
||||
// #ifdef MP-WEIXIN || MP-QQ || APP-PLUS
|
||||
beforeDestroy() {
|
||||
if (this._observer)
|
||||
this._observer.disconnect();
|
||||
},
|
||||
// #endif
|
||||
methods: {
|
||||
// #ifndef MP-ALIPAY
|
||||
playEvent(e) {
|
||||
if ((this._top.videoContexts || []).length > 1 && this._top.autopause) {
|
||||
for (var video of this._top.videoContexts) {
|
||||
if (video.id == e.currentTarget.id) continue;
|
||||
video.pause();
|
||||
}
|
||||
}
|
||||
},
|
||||
// #endif
|
||||
previewEvent(e) {
|
||||
var attrs = e.currentTarget.dataset.attrs;
|
||||
if (!attrs.ignore) {
|
||||
var preview = true;
|
||||
this._top.$emit('imgtap', {
|
||||
id: e.currentTarget.id,
|
||||
src: attrs.src,
|
||||
ignore: () => preview = false
|
||||
})
|
||||
if (preview && this._top.autopreview) {
|
||||
var urls = this._top.imgList || [],
|
||||
current = urls[attrs.i] ? attrs.i : (urls = [attrs.src], 0);
|
||||
uni.previewImage({
|
||||
current,
|
||||
urls
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
tapEvent(e) {
|
||||
var jump = true,
|
||||
attrs = e.currentTarget.dataset.attrs;
|
||||
attrs.ignore = () => jump = false;
|
||||
this._top.$emit('linkpress', attrs);
|
||||
if (jump) {
|
||||
// #ifdef MP
|
||||
if (attrs['app-id'] || attrs.appId) {
|
||||
return uni.navigateToMiniProgram({
|
||||
appId: attrs['app-id'] || attrs.appId,
|
||||
path: attrs.path || ''
|
||||
})
|
||||
}
|
||||
// #endif
|
||||
if (attrs.href) {
|
||||
if (attrs.href[0] == "#") {
|
||||
if (this._top.useAnchor)
|
||||
this._top.navigateTo({
|
||||
id: attrs.href.substring(1)
|
||||
})
|
||||
} else if (attrs.href.indexOf("http") == 0 || attrs.href.indexOf("//") == 0) {
|
||||
if (this._top.autocopy) {
|
||||
uni.setClipboardData({
|
||||
data: attrs.href,
|
||||
success() {
|
||||
uni.showToast({
|
||||
title: '链接已复制'
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
} else
|
||||
uni.navigateTo({
|
||||
url: attrs.href
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
triggerError(source, target, errMsg, errCode, context) {
|
||||
this._top.$emit('error', {
|
||||
source,
|
||||
target,
|
||||
errMsg,
|
||||
errCode,
|
||||
context
|
||||
});
|
||||
},
|
||||
loadSource(target) {
|
||||
// console.log(target)
|
||||
var index = (this.controls[target.id] ? this.controls[target.id].index : 0) + 1;
|
||||
if (index < target.dataset.source.length) {
|
||||
this.$set(this.controls[target.id], "index", index);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
adError(e) {
|
||||
this.triggerError("ad", e.currentTarget, "", e.detail.errorCode);
|
||||
},
|
||||
videoError(e) {
|
||||
if (!this.loadSource(e.currentTarget) && this._top)
|
||||
this.triggerError("video", e.currentTarget, e.detail.errMsg, undefined, uni.createVideoContext(e.currentTarget.id,
|
||||
this));
|
||||
},
|
||||
audioError(e) {
|
||||
if (!this.loadSource(e.currentTarget))
|
||||
this.triggerError("audio", e.currentTarget, e.detail.errMsg);
|
||||
},
|
||||
_loadVideo(e) {
|
||||
this.$set(this.controls, e.currentTarget.id, {
|
||||
play: true,
|
||||
index: 0
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
/* 可以在这里引入自定义的外部样式 */
|
||||
|
||||
/* 链接受到点击的hover-class,可自定义修改 */
|
||||
.navigator-hover {
|
||||
opacity: 0.7;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* 以下内容不建议修改 */
|
||||
/* #ifndef MP-BAIDU */
|
||||
:host {
|
||||
display: inherit;
|
||||
float: inherit;
|
||||
}
|
||||
|
||||
/* #endif */
|
||||
|
||||
._b,
|
||||
._strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
._big {
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
._small {
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
._blockquote,
|
||||
._div,
|
||||
._p {
|
||||
display: block;
|
||||
}
|
||||
|
||||
._code {
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
._del {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
._em,
|
||||
._i {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
._h1 {
|
||||
font-size: 2em;
|
||||
}
|
||||
|
||||
._h2 {
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
._h3 {
|
||||
font-size: 1.17em;
|
||||
}
|
||||
|
||||
._h5 {
|
||||
font-size: 0.67em;
|
||||
}
|
||||
|
||||
._h1,
|
||||
._h2,
|
||||
._h3,
|
||||
._h4,
|
||||
._h5,
|
||||
._h6 {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
._ins {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
._q::before {
|
||||
content: '"';
|
||||
}
|
||||
|
||||
._q::after {
|
||||
content: '"';
|
||||
}
|
||||
|
||||
._a,
|
||||
._abbr,
|
||||
._b,
|
||||
._big,
|
||||
._small,
|
||||
._code,
|
||||
._del,
|
||||
._em,
|
||||
._i,
|
||||
._ins,
|
||||
._label,
|
||||
._q,
|
||||
._span,
|
||||
._strong {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
/* #ifdef MP-WEIXIN || MP-QQ || MP-ALIPAY */
|
||||
.__sub,
|
||||
.__sup,
|
||||
.__bdo,
|
||||
.__bdi,
|
||||
.__ruby,
|
||||
.__rt {
|
||||
display: inline-block !important;
|
||||
}
|
||||
|
||||
/* #endif */
|
||||
._video {
|
||||
background-color: black;
|
||||
width: 300px;
|
||||
height: 225px;
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
._video::after {
|
||||
content: '';
|
||||
border-width: 15px 0 15px 30px;
|
||||
border-style: solid;
|
||||
border-color: transparent transparent transparent white;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
margin: -15px 0 0 -15px;
|
||||
}
|
||||
</style>
|
||||
131
uniapp/uni-app/components/load-more.vue
Normal file
131
uniapp/uni-app/components/load-more.vue
Normal file
@@ -0,0 +1,131 @@
|
||||
<template>
|
||||
<view class='load-more'>
|
||||
<block v-if="!loading&&noMore">
|
||||
<view class="loadmore__line"></view>
|
||||
<text class="loadmore__text">{{noMoreText}}</text>
|
||||
<view class="loadmore__line"></view>
|
||||
</block>
|
||||
<block v-if="loading">
|
||||
<view class="weui-loading"></view>
|
||||
<text class="loadmore__text">{{loadText}}</text>
|
||||
</block>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'load-more',
|
||||
props: {
|
||||
loadText: {
|
||||
type: String,
|
||||
default () {
|
||||
return '努力加载中'
|
||||
}
|
||||
},
|
||||
noMoreText: {
|
||||
type: String,
|
||||
default () {
|
||||
return '没有更多了'
|
||||
}
|
||||
},
|
||||
noMore: {
|
||||
type: Boolean,
|
||||
default () {
|
||||
return false
|
||||
}
|
||||
},
|
||||
loading: {
|
||||
type: Boolean,
|
||||
default () {
|
||||
return true
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.load-more {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 90rpx;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.loading-icon {
|
||||
width: 30rpx;
|
||||
height: 30rpx;
|
||||
margin-right: 8rpx;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
animation: weuiLoading 1s steps(12, end) infinite;
|
||||
background: url('https://s10.mogucdn.com/mlcdn/c45406/171016_4a61e09hcadd157gadhdeje55e82c_32x32.png') no-repeat;
|
||||
-webkit-background-size: 100%;
|
||||
background-size: 100%;
|
||||
}
|
||||
|
||||
.loadmore__text {
|
||||
margin: 0 8rpx 0 8rpx;
|
||||
color: #333;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.loadmore__line {
|
||||
width: 100rpx;
|
||||
height: 1rpx;
|
||||
border-top: 1rpx solid #d2d2d2;
|
||||
}
|
||||
|
||||
/* 加载中动画 */
|
||||
.weui-loading {
|
||||
margin: 0 5px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
-webkit-animation: a 1s steps(12) infinite;
|
||||
animation: a 1s steps(12) infinite;
|
||||
background: transparent url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMjAiIGhlaWdodD0iMTIwIiB2aWV3Qm94PSIwIDAgMTAwIDEwMCI+PHBhdGggZmlsbD0ibm9uZSIgZD0iTTAgMGgxMDB2MTAwSDB6Ii8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjRTlFOUU5IiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAgLTMwKSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iIzk4OTY5NyIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSgzMCAxMDUuOTggNjUpIi8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjOUI5OTlBIiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0icm90YXRlKDYwIDc1Ljk4IDY1KSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iI0EzQTFBMiIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSg5MCA2NSA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNBQkE5QUEiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoMTIwIDU4LjY2IDY1KSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iI0IyQjJCMiIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSgxNTAgNTQuMDIgNjUpIi8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjQkFCOEI5IiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0icm90YXRlKDE4MCA1MCA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNDMkMwQzEiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoLTE1MCA0NS45OCA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNDQkNCQ0IiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoLTEyMCA0MS4zNCA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNEMkQyRDIiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoLTkwIDM1IDY1KSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iI0RBREFEQSIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSgtNjAgMjQuMDIgNjUpIi8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjRTJFMkUyIiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0icm90YXRlKC0zMCAtNS45OCA2NSkiLz48L3N2Zz4=) no-repeat;
|
||||
background-size: 100%
|
||||
}
|
||||
|
||||
.weui-loading.weui-loading_transparent {
|
||||
background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120' viewBox='0 0 100 100'%3E%3Cpath fill='none' d='M0 0h100v100H0z'/%3E%3Crect xmlns='http://www.w3.org/2000/svg' width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.56)' rx='5' ry='5' transform='translate(0 -30)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.5)' rx='5' ry='5' transform='rotate(30 105.98 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.43)' rx='5' ry='5' transform='rotate(60 75.98 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.38)' rx='5' ry='5' transform='rotate(90 65 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.32)' rx='5' ry='5' transform='rotate(120 58.66 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.28)' rx='5' ry='5' transform='rotate(150 54.02 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.25)' rx='5' ry='5' transform='rotate(180 50 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.2)' rx='5' ry='5' transform='rotate(-150 45.98 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.17)' rx='5' ry='5' transform='rotate(-120 41.34 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.14)' rx='5' ry='5' transform='rotate(-90 35 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.1)' rx='5' ry='5' transform='rotate(-60 24.02 65)'/%3E%3Crect width='7' height='20' x='46.5' y='40' fill='rgba(255,255,255,.03)' rx='5' ry='5' transform='rotate(-30 -5.98 65)'/%3E%3C/svg%3E")
|
||||
}
|
||||
|
||||
@-webkit-keyframes a {
|
||||
0% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg)
|
||||
}
|
||||
|
||||
to {
|
||||
-webkit-transform: rotate(1turn);
|
||||
transform: rotate(1turn)
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes a {
|
||||
0% {
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg)
|
||||
}
|
||||
|
||||
to {
|
||||
-webkit-transform: rotate(1turn);
|
||||
transform: rotate(1turn)
|
||||
}
|
||||
}
|
||||
</style>
|
||||
107
uniapp/uni-app/components/login-info.vue
Normal file
107
uniapp/uni-app/components/login-info.vue
Normal file
@@ -0,0 +1,107 @@
|
||||
<template>
|
||||
<view>
|
||||
<view class="login-info pd-lg flex-center rel" v-if="isShowLogin">
|
||||
<view @tap.stop="toClose" class="login-close flex-center radius abs">
|
||||
<i class="iconfont icon-add c-base"></i>
|
||||
</view>
|
||||
<image mode="aspectFill" lazy-load class="logo-img radius" :src="configInfo.app_logo"></image>
|
||||
<view class="flex-center flex-1 ml-md">
|
||||
<view class="flex-1">
|
||||
<view class="f-title c-base max-380 ellipsis">{{`欢迎来到${configInfo.app_text}`}}</view>
|
||||
<view class="text f-caption">登录后获取更多精彩内容</view>
|
||||
</view>
|
||||
<view @tap.stop="toLogin" class="login-btn flex-center f-desc c-base radius"
|
||||
:style="{background:primaryColor}">去登录</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
mapState,
|
||||
mapActions,
|
||||
mapMutations
|
||||
} from "vuex"
|
||||
export default {
|
||||
components: {},
|
||||
props: {},
|
||||
mounted() {
|
||||
this.init();
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
}
|
||||
},
|
||||
computed: mapState({
|
||||
primaryColor: state => state.config.configInfo.primaryColor,
|
||||
subColor: state => state.config.configInfo.subColor,
|
||||
configInfo: state => state.config.configInfo,
|
||||
isShowLogin: state => state.user.isShowLogin
|
||||
}),
|
||||
methods: {
|
||||
...mapActions(['getConfigInfo', 'getUserInfo']),
|
||||
...mapMutations(['updateUserItem']),
|
||||
async init() {
|
||||
},
|
||||
toClose() {
|
||||
this.updateUserItem({
|
||||
key: 'isShowLogin',
|
||||
val: false
|
||||
})
|
||||
},
|
||||
toLogin() {
|
||||
let pages = getCurrentPages();
|
||||
let {
|
||||
route
|
||||
} = pages[pages.length - 1]
|
||||
this.updateUserItem({
|
||||
key: 'loginPage',
|
||||
val: `/${route}`
|
||||
})
|
||||
this.$util.goUrl({
|
||||
url: `/pages/login?type=1`
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.login-info {
|
||||
position: fixed;
|
||||
left: 20rpx;
|
||||
bottom: 20rpx;
|
||||
width: 710rpx;
|
||||
height: 139rpx;
|
||||
background: rgba(0, 0, 0, 0.8);
|
||||
border-radius: 16rpx;
|
||||
|
||||
.logo-img {
|
||||
width: 90rpx;
|
||||
height: 90rpx;
|
||||
}
|
||||
|
||||
.text {
|
||||
color: #9E9E9E;
|
||||
}
|
||||
|
||||
.login-btn {
|
||||
width: 150rpx;
|
||||
height: 54rpx;
|
||||
}
|
||||
|
||||
.login-close {
|
||||
top: -10rpx;
|
||||
right: -10rpx;
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
background: #000;
|
||||
|
||||
.iconfont {
|
||||
font-size: 24rpx;
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
121
uniapp/uni-app/components/mask.vue
Normal file
121
uniapp/uni-app/components/mask.vue
Normal file
@@ -0,0 +1,121 @@
|
||||
<template>
|
||||
<view :class="['ui-mask ','center',effect,{'show':show}]" @tap="handleMaskTap" :style='{top:top,background:background}'>
|
||||
<slot></slot>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'mask',
|
||||
props: {
|
||||
background: {
|
||||
type: String,
|
||||
default: "rgba(0, 0, 0, 0.5)"
|
||||
},
|
||||
show: {
|
||||
type: Boolean
|
||||
},
|
||||
top: {
|
||||
type: String,
|
||||
default () {
|
||||
return '0'
|
||||
}
|
||||
},
|
||||
effect: {
|
||||
type: String
|
||||
},
|
||||
hideDelay: {
|
||||
type: Number
|
||||
},
|
||||
hideOnTap: {
|
||||
type: Number,
|
||||
default () {
|
||||
return 1
|
||||
}
|
||||
},
|
||||
blur: {
|
||||
type: String
|
||||
}
|
||||
},
|
||||
created() {
|
||||
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
show(newValue, oldValue) {
|
||||
var _this = this;
|
||||
|
||||
if (newValue) {
|
||||
this.selfShow = false
|
||||
} else {
|
||||
if (this.hideDelay) {
|
||||
setTimeout(function() {
|
||||
_this.selfShow = false
|
||||
}, this.hideDelay);
|
||||
} else {
|
||||
_this.selfShow = false
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleMaskTap(e) {
|
||||
if (this.hideOnTap) {
|
||||
this.show = false;
|
||||
this.$emit('hide')
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<style>
|
||||
.ui-mask {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
transition: all 0.25s ease-in;
|
||||
-webkit-backface-visibility: hidden;
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.center {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.ui-mask.scale-out {
|
||||
transition: all 0.25s ease-in;
|
||||
transform: scale(0);
|
||||
}
|
||||
|
||||
.ui-mask.scale-out.show {
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
.ui-mask.scale-in {
|
||||
transition: all 0.25s ease-in;
|
||||
transform: scale(1.5);
|
||||
}
|
||||
|
||||
.ui-mask.scale-in.show {
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
.ui-mask.show {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
</style>
|
||||
188
uniapp/uni-app/components/min-countdown.vue
Normal file
188
uniapp/uni-app/components/min-countdown.vue
Normal file
@@ -0,0 +1,188 @@
|
||||
<template>
|
||||
<view class="min-countdown" :class="className" :style="{color:color}">
|
||||
<rich-text :nodes="time" v-if="type == 1"></rich-text>
|
||||
<!-- x天x时x分x秒 -->
|
||||
<view class="flex-y-center" v-if="type == 2">
|
||||
<view class="count-tag flex-center" :class="[{'haveColor':borderColor}]"
|
||||
:style="{background:bgColor,border:borderColor?`1rpx solid ${borderColor}`:``,width:time.d*1>99?'54rpx':''}">
|
||||
{{time.d}}
|
||||
</view>
|
||||
<view class="text" :style="{color:textColor}">天</view>
|
||||
<view class="count-tag flex-center" :class="[{'haveColor':borderColor}]"
|
||||
:style="{background:bgColor,border:borderColor?`1rpx solid ${borderColor}`:``}">{{time.h}}</view>
|
||||
<view class="text" :style="{color:textColor}">时</view>
|
||||
<view class="count-tag flex-center" :class="[{'haveColor':borderColor}]"
|
||||
:style="{background:bgColor,border:borderColor?`1rpx solid ${borderColor}`:``}">
|
||||
{{time.m}}
|
||||
</view>
|
||||
<view class="text" :style="{color:textColor}">分</view>
|
||||
<view class="count-tag flex-center" :class="[{'haveColor':borderColor}]"
|
||||
:style="{background:bgColor,border:borderColor?`1rpx solid ${borderColor}`:``}">{{time.s}}</view>
|
||||
<view class="text" :style="{color:textColor}">秒</view>
|
||||
</view>
|
||||
<!-- 时:分:秒 -->
|
||||
<view class="flex-y-center" v-if="type == 3">
|
||||
<view class="count-tag flex-center" :class="[{'haveColor':borderColor}]"
|
||||
:style="{background:bgColor,border:borderColor?`1rpx solid ${borderColor}`:``,width:time.all_h*1>99?className=='mini'?'48rpx':className=='sm'?'54rpx':'66rpx':''}">
|
||||
{{time.all_h}}
|
||||
</view>
|
||||
<view class="text" :style="{color:textColor}">:</view>
|
||||
<view class="count-tag flex-center" :class="[{'haveColor':borderColor}]"
|
||||
:style="{background:bgColor,border:borderColor?`1rpx solid ${borderColor}`:``}">
|
||||
{{time.m}}
|
||||
</view>
|
||||
<view class="text" :style="{color:textColor}">:</view>
|
||||
<view class="count-tag flex-center" :class="[{'haveColor':borderColor}]"
|
||||
:style="{background:bgColor,border:borderColor?`1rpx solid ${borderColor}`:``}">
|
||||
{{time.s}}
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="type==4">{{`${time.all_h}:${time.m}:${time.s}`}}</view>
|
||||
<view v-if="type==5">{{`${time.all_h}小时${time.m}分${time.s}秒`}}</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
mapState,
|
||||
} from 'vuex';
|
||||
export default {
|
||||
name: 'min-countdown',
|
||||
props: {
|
||||
type: {
|
||||
type: Number,
|
||||
default: 1
|
||||
},
|
||||
targetTime: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
format: {
|
||||
type: String,
|
||||
default: '{%d}天{%h}小时{%m}分{%s}秒'
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
default: '#39b54a'
|
||||
},
|
||||
bgColor: {
|
||||
type: String,
|
||||
default: '#fff'
|
||||
},
|
||||
textColor: {
|
||||
type: String,
|
||||
default: '#39b54a'
|
||||
},
|
||||
borderColor: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
className: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
time: '00:00:00'
|
||||
}
|
||||
},
|
||||
computed: mapState({
|
||||
primaryColor: state => state.config.configInfo.primaryColor,
|
||||
subColor: state => state.config.configInfo.subColor,
|
||||
}),
|
||||
methods: {
|
||||
init() {
|
||||
setTimeout(() => {
|
||||
this.getTime()
|
||||
}, 1000)
|
||||
},
|
||||
getTime() {
|
||||
let time = {}
|
||||
let format = this.format
|
||||
|
||||
function formatNumber(num) {
|
||||
return num > 9 ? `${num}` : `0${num}`
|
||||
}
|
||||
const gapTime = Math.ceil((this.targetTime - new Date().getTime()) / 1000)
|
||||
if (gapTime >= 0) {
|
||||
time.d = formatNumber(parseInt(gapTime / 86400))
|
||||
let lastTime = gapTime % 86400;
|
||||
time.h = formatNumber(parseInt(lastTime / 3600))
|
||||
lastTime = lastTime % 3600;
|
||||
time.all_h = time.d * 24 + time.h * 1
|
||||
time.m = formatNumber(parseInt(lastTime / 60))
|
||||
time.s = formatNumber(lastTime % 60);
|
||||
['d', 'h', 'm', 's'].forEach(item => {
|
||||
const day = time[item].split('');
|
||||
format = format.replace('{%' + item + '}', time[item])
|
||||
format = format.replace('{%' + item + '0}', day[0])
|
||||
format = format.replace('{%' + item + '1}', day[1])
|
||||
format = format.replace('{%' + item + '2}', day[2] ? day[2] : '0')
|
||||
})
|
||||
this.time = this.type == 1 ? format : time
|
||||
this.init()
|
||||
} else {
|
||||
this.$emit('callback')
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getTime()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.min-countdown {
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
.count-tag {
|
||||
width: 42rpx;
|
||||
height: 42rpx;
|
||||
margin: 0 10rpx;
|
||||
padding: 0 10rpx;
|
||||
border-radius: 4rpx;
|
||||
}
|
||||
|
||||
.text {
|
||||
color: #fff;
|
||||
font-size: 20rpx;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
.min-countdown.mini {
|
||||
.count-tag {
|
||||
width: 36rpx;
|
||||
height: 29rpx;
|
||||
border-radius: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
.min-countdown.sm {
|
||||
.count-tag {
|
||||
width: 42rpx;
|
||||
height: 42rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.min-countdown.md {
|
||||
.count-tag {
|
||||
width: 54rpx;
|
||||
height: 54rpx;
|
||||
font-size: 32rpx;
|
||||
}
|
||||
|
||||
.text {
|
||||
font-size: 28rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.haveColor {
|
||||
transform: rotateZ(360deg);
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Arnout Kazemier
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,92 @@
|
||||
# EventEmitter3
|
||||
|
||||
[](https://www.npmjs.com/package/eventemitter3)[](https://travis-ci.org/primus/eventemitter3)[](https://david-dm.org/primus/eventemitter3)[](https://coveralls.io/r/primus/eventemitter3?branch=master)[](https://webchat.freenode.net/?channels=primus)
|
||||
|
||||
[](https://saucelabs.com/u/eventemitter3)
|
||||
|
||||
EventEmitter3 is a high performance EventEmitter. It has been micro-optimized
|
||||
for various of code paths making this, one of, if not the fastest EventEmitter
|
||||
available for Node.js and browsers. The module is API compatible with the
|
||||
EventEmitter that ships by default with Node.js but there are some slight
|
||||
differences:
|
||||
|
||||
- Domain support has been removed.
|
||||
- We do not `throw` an error when you emit an `error` event and nobody is
|
||||
listening.
|
||||
- The `newListener` and `removeListener` events have been removed as they
|
||||
are useful only in some uncommon use-cases.
|
||||
- The `setMaxListeners`, `getMaxListeners`, `prependListener` and
|
||||
`prependOnceListener` methods are not available.
|
||||
- Support for custom context for events so there is no need to use `fn.bind`.
|
||||
- The `removeListener` method removes all matching listeners, not only the
|
||||
first.
|
||||
|
||||
It's a drop in replacement for existing EventEmitters, but just faster. Free
|
||||
performance, who wouldn't want that? The EventEmitter is written in EcmaScript 3
|
||||
so it will work in the oldest browsers and node versions that you need to
|
||||
support.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
$ npm install --save eventemitter3
|
||||
```
|
||||
|
||||
## CDN
|
||||
|
||||
Recommended CDN:
|
||||
|
||||
```text
|
||||
https://unpkg.com/eventemitter3@latest/umd/eventemitter3.min.js
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
After installation the only thing you need to do is require the module:
|
||||
|
||||
```js
|
||||
var EventEmitter = require('eventemitter3');
|
||||
```
|
||||
|
||||
And you're ready to create your own EventEmitter instances. For the API
|
||||
documentation, please follow the official Node.js documentation:
|
||||
|
||||
http://nodejs.org/api/events.html
|
||||
|
||||
### Contextual emits
|
||||
|
||||
We've upgraded the API of the `EventEmitter.on`, `EventEmitter.once` and
|
||||
`EventEmitter.removeListener` to accept an extra argument which is the `context`
|
||||
or `this` value that should be set for the emitted events. This means you no
|
||||
longer have the overhead of an event that required `fn.bind` in order to get a
|
||||
custom `this` value.
|
||||
|
||||
```js
|
||||
var EE = new EventEmitter()
|
||||
, context = { foo: 'bar' };
|
||||
|
||||
function emitted() {
|
||||
console.log(this === context); // true
|
||||
}
|
||||
|
||||
EE.once('event-name', emitted, context);
|
||||
EE.on('another-event', emitted, context);
|
||||
EE.removeListener('another-event', emitted, context);
|
||||
```
|
||||
|
||||
### Tests and benchmarks
|
||||
|
||||
This module is well tested. You can run:
|
||||
|
||||
- `npm test` to run the tests under Node.js.
|
||||
- `npm run test-browser` to run the tests in real browsers via Sauce Labs.
|
||||
|
||||
We also have a set of benchmarks to compare EventEmitter3 with some available
|
||||
alternatives. To run the benchmarks run `npm run benchmark`.
|
||||
|
||||
Tests and benchmarks are not included in the npm package. If you want to play
|
||||
with them you have to clone the GitHub repository.
|
||||
|
||||
## License
|
||||
|
||||
[MIT](LICENSE)
|
||||
67
uniapp/uni-app/components/miniprogram_npm/eventemitter3/index.d.ts
vendored
Normal file
67
uniapp/uni-app/components/miniprogram_npm/eventemitter3/index.d.ts
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
type EventNames<T extends string | symbol | { [K in string | symbol]: any[] }> = T extends string | symbol ? T : keyof T;
|
||||
type EventArgs<T extends string | symbol | { [K in string | symbol]: any[] }, K extends EventNames<T>> = T extends string | symbol ? any[] : K extends keyof T ? T[K] : never;
|
||||
|
||||
/**
|
||||
* Minimal `EventEmitter` interface that is molded against the Node.js
|
||||
* `EventEmitter` interface.
|
||||
*/
|
||||
declare class EventEmitter<EventTypes extends string | symbol | { [K in keyof EventTypes]: any[] } = string | symbol> {
|
||||
static prefixed: string | boolean;
|
||||
|
||||
/**
|
||||
* Return an array listing the events for which the emitter has registered
|
||||
* listeners.
|
||||
*/
|
||||
eventNames(): Array<EventNames<EventTypes>>;
|
||||
|
||||
/**
|
||||
* Return the listeners registered for a given event.
|
||||
*/
|
||||
listeners<T extends EventNames<EventTypes>>(event: T): Array<EventEmitter.ListenerFn<EventArgs<EventTypes, T>>>;
|
||||
|
||||
/**
|
||||
* Return the number of listeners listening to a given event.
|
||||
*/
|
||||
listenerCount(event: EventNames<EventTypes>): number;
|
||||
|
||||
/**
|
||||
* Calls each of the listeners registered for a given event.
|
||||
*/
|
||||
emit<T extends EventNames<EventTypes>>(event: T, ...args: EventArgs<EventTypes, T>): boolean;
|
||||
|
||||
/**
|
||||
* Add a listener for a given event.
|
||||
*/
|
||||
on<T extends EventNames<EventTypes>>(event: T, fn: EventEmitter.ListenerFn<EventArgs<EventTypes, T>>, context?: any): this;
|
||||
addListener<T extends EventNames<EventTypes>>(event: T, fn: EventEmitter.ListenerFn<EventArgs<EventTypes, T>>, context?: any): this;
|
||||
|
||||
/**
|
||||
* Add a one-time listener for a given event.
|
||||
*/
|
||||
once<T extends EventNames<EventTypes>>(event: T, fn: EventEmitter.ListenerFn<EventArgs<EventTypes, T>>, context?: any): this;
|
||||
|
||||
/**
|
||||
* Remove the listeners of a given event.
|
||||
*/
|
||||
removeListener<T extends EventNames<EventTypes>>(event: T, fn?: EventEmitter.ListenerFn<EventArgs<EventTypes, T>>, context?: any, once?: boolean): this;
|
||||
off<T extends EventNames<EventTypes>>(event: T, fn?: EventEmitter.ListenerFn<EventArgs<EventTypes, T>>, context?: any, once?: boolean): this;
|
||||
|
||||
/**
|
||||
* Remove all listeners, or those of the specified event.
|
||||
*/
|
||||
removeAllListeners(event?: EventNames<EventTypes>): this;
|
||||
}
|
||||
|
||||
declare namespace EventEmitter {
|
||||
export interface ListenerFn<Args extends any[] = any[]> {
|
||||
(...args: Args): void;
|
||||
}
|
||||
|
||||
export interface EventEmitterStatic {
|
||||
new<EventTypes extends string | symbol | { [K in keyof EventTypes]: any[] } = string | symbol>(): EventEmitter<EventTypes>;
|
||||
}
|
||||
|
||||
export const EventEmitter: EventEmitterStatic;
|
||||
}
|
||||
|
||||
export = EventEmitter;
|
||||
347
uniapp/uni-app/components/miniprogram_npm/eventemitter3/index.js
Normal file
347
uniapp/uni-app/components/miniprogram_npm/eventemitter3/index.js
Normal file
@@ -0,0 +1,347 @@
|
||||
'use strict';
|
||||
|
||||
var has = Object.prototype.hasOwnProperty,
|
||||
prefix = '~';
|
||||
/**
|
||||
* Constructor to create a storage for our `EE` objects.
|
||||
* An `Events` instance is a plain object whose properties are event names.
|
||||
*
|
||||
* @constructor
|
||||
* @private
|
||||
*/
|
||||
|
||||
function Events() {} //
|
||||
// We try to not inherit from `Object.prototype`. In some engines creating an
|
||||
// instance in this way is faster than calling `Object.create(null)` directly.
|
||||
// If `Object.create(null)` is not supported we prefix the event names with a
|
||||
// character to make sure that the built-in object properties are not
|
||||
// overridden or used as an attack vector.
|
||||
//
|
||||
|
||||
|
||||
if (Object.create) {
|
||||
Events.prototype = Object.create(null); //
|
||||
// This hack is needed because the `__proto__` property is still inherited in
|
||||
// some old browsers like Android 4, iPhone 5.1, Opera 11 and Safari 5.
|
||||
//
|
||||
|
||||
if (!new Events().__proto__) prefix = false;
|
||||
}
|
||||
/**
|
||||
* Representation of a single event listener.
|
||||
*
|
||||
* @param {Function} fn The listener function.
|
||||
* @param {*} context The context to invoke the listener with.
|
||||
* @param {Boolean} [once=false] Specify if the listener is a one-time listener.
|
||||
* @constructor
|
||||
* @private
|
||||
*/
|
||||
|
||||
|
||||
function EE(fn, context, once) {
|
||||
this.fn = fn;
|
||||
this.context = context;
|
||||
this.once = once || false;
|
||||
}
|
||||
/**
|
||||
* Add a listener for a given event.
|
||||
*
|
||||
* @param {EventEmitter} emitter Reference to the `EventEmitter` instance.
|
||||
* @param {(String|Symbol)} event The event name.
|
||||
* @param {Function} fn The listener function.
|
||||
* @param {*} context The context to invoke the listener with.
|
||||
* @param {Boolean} once Specify if the listener is a one-time listener.
|
||||
* @returns {EventEmitter}
|
||||
* @private
|
||||
*/
|
||||
|
||||
|
||||
function addListener(emitter, event, fn, context, once) {
|
||||
if (typeof fn !== 'function') {
|
||||
throw new TypeError('The listener must be a function');
|
||||
}
|
||||
|
||||
var listener = new EE(fn, context || emitter, once),
|
||||
evt = prefix ? prefix + event : event;
|
||||
if (!emitter._events[evt]) emitter._events[evt] = listener, emitter._eventsCount++;else if (!emitter._events[evt].fn) emitter._events[evt].push(listener);else emitter._events[evt] = [emitter._events[evt], listener];
|
||||
return emitter;
|
||||
}
|
||||
/**
|
||||
* Clear event by name.
|
||||
*
|
||||
* @param {EventEmitter} emitter Reference to the `EventEmitter` instance.
|
||||
* @param {(String|Symbol)} evt The Event name.
|
||||
* @private
|
||||
*/
|
||||
|
||||
|
||||
function clearEvent(emitter, evt) {
|
||||
if (--emitter._eventsCount === 0) emitter._events = new Events();else delete emitter._events[evt];
|
||||
}
|
||||
/**
|
||||
* Minimal `EventEmitter` interface that is molded against the Node.js
|
||||
* `EventEmitter` interface.
|
||||
*
|
||||
* @constructor
|
||||
* @public
|
||||
*/
|
||||
|
||||
|
||||
function EventEmitter() {
|
||||
this._events = new Events();
|
||||
this._eventsCount = 0;
|
||||
}
|
||||
/**
|
||||
* Return an array listing the events for which the emitter has registered
|
||||
* listeners.
|
||||
*
|
||||
* @returns {Array}
|
||||
* @public
|
||||
*/
|
||||
|
||||
|
||||
EventEmitter.prototype.eventNames = function eventNames() {
|
||||
var names = [],
|
||||
events,
|
||||
name;
|
||||
if (this._eventsCount === 0) return names;
|
||||
|
||||
for (name in events = this._events) {
|
||||
if (has.call(events, name)) names.push(prefix ? name.slice(1) : name);
|
||||
}
|
||||
|
||||
if (Object.getOwnPropertySymbols) {
|
||||
return names.concat(Object.getOwnPropertySymbols(events));
|
||||
}
|
||||
|
||||
return names;
|
||||
};
|
||||
/**
|
||||
* Return the listeners registered for a given event.
|
||||
*
|
||||
* @param {(String|Symbol)} event The event name.
|
||||
* @returns {Array} The registered listeners.
|
||||
* @public
|
||||
*/
|
||||
|
||||
|
||||
EventEmitter.prototype.listeners = function listeners(event) {
|
||||
var evt = prefix ? prefix + event : event,
|
||||
handlers = this._events[evt];
|
||||
if (!handlers) return [];
|
||||
if (handlers.fn) return [handlers.fn];
|
||||
|
||||
for (var i = 0, l = handlers.length, ee = new Array(l); i < l; i++) {
|
||||
ee[i] = handlers[i].fn;
|
||||
}
|
||||
|
||||
return ee;
|
||||
};
|
||||
/**
|
||||
* Return the number of listeners listening to a given event.
|
||||
*
|
||||
* @param {(String|Symbol)} event The event name.
|
||||
* @returns {Number} The number of listeners.
|
||||
* @public
|
||||
*/
|
||||
|
||||
|
||||
EventEmitter.prototype.listenerCount = function listenerCount(event) {
|
||||
var evt = prefix ? prefix + event : event,
|
||||
listeners = this._events[evt];
|
||||
if (!listeners) return 0;
|
||||
if (listeners.fn) return 1;
|
||||
return listeners.length;
|
||||
};
|
||||
/**
|
||||
* Calls each of the listeners registered for a given event.
|
||||
*
|
||||
* @param {(String|Symbol)} event The event name.
|
||||
* @returns {Boolean} `true` if the event had listeners, else `false`.
|
||||
* @public
|
||||
*/
|
||||
|
||||
|
||||
EventEmitter.prototype.emit = function emit(event, a1, a2, a3, a4, a5) {
|
||||
var evt = prefix ? prefix + event : event;
|
||||
if (!this._events[evt]) return false;
|
||||
var listeners = this._events[evt],
|
||||
len = arguments.length,
|
||||
args,
|
||||
i;
|
||||
|
||||
if (listeners.fn) {
|
||||
if (listeners.once) this.removeListener(event, listeners.fn, undefined, true);
|
||||
|
||||
switch (len) {
|
||||
case 1:
|
||||
return listeners.fn.call(listeners.context), true;
|
||||
|
||||
case 2:
|
||||
return listeners.fn.call(listeners.context, a1), true;
|
||||
|
||||
case 3:
|
||||
return listeners.fn.call(listeners.context, a1, a2), true;
|
||||
|
||||
case 4:
|
||||
return listeners.fn.call(listeners.context, a1, a2, a3), true;
|
||||
|
||||
case 5:
|
||||
return listeners.fn.call(listeners.context, a1, a2, a3, a4), true;
|
||||
|
||||
case 6:
|
||||
return listeners.fn.call(listeners.context, a1, a2, a3, a4, a5), true;
|
||||
}
|
||||
|
||||
for (i = 1, args = new Array(len - 1); i < len; i++) {
|
||||
args[i - 1] = arguments[i];
|
||||
}
|
||||
|
||||
listeners.fn.apply(listeners.context, args);
|
||||
} else {
|
||||
var length = listeners.length,
|
||||
j;
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
if (listeners[i].once) this.removeListener(event, listeners[i].fn, undefined, true);
|
||||
|
||||
switch (len) {
|
||||
case 1:
|
||||
listeners[i].fn.call(listeners[i].context);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
listeners[i].fn.call(listeners[i].context, a1);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
listeners[i].fn.call(listeners[i].context, a1, a2);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
listeners[i].fn.call(listeners[i].context, a1, a2, a3);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (!args) for (j = 1, args = new Array(len - 1); j < len; j++) {
|
||||
args[j - 1] = arguments[j];
|
||||
}
|
||||
listeners[i].fn.apply(listeners[i].context, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
/**
|
||||
* Add a listener for a given event.
|
||||
*
|
||||
* @param {(String|Symbol)} event The event name.
|
||||
* @param {Function} fn The listener function.
|
||||
* @param {*} [context=this] The context to invoke the listener with.
|
||||
* @returns {EventEmitter} `this`.
|
||||
* @public
|
||||
*/
|
||||
|
||||
|
||||
EventEmitter.prototype.on = function on(event, fn, context) {
|
||||
return addListener(this, event, fn, context, false);
|
||||
};
|
||||
/**
|
||||
* Add a one-time listener for a given event.
|
||||
*
|
||||
* @param {(String|Symbol)} event The event name.
|
||||
* @param {Function} fn The listener function.
|
||||
* @param {*} [context=this] The context to invoke the listener with.
|
||||
* @returns {EventEmitter} `this`.
|
||||
* @public
|
||||
*/
|
||||
|
||||
|
||||
EventEmitter.prototype.once = function once(event, fn, context) {
|
||||
return addListener(this, event, fn, context, true);
|
||||
};
|
||||
/**
|
||||
* Remove the listeners of a given event.
|
||||
*
|
||||
* @param {(String|Symbol)} event The event name.
|
||||
* @param {Function} fn Only remove the listeners that match this function.
|
||||
* @param {*} context Only remove the listeners that have this context.
|
||||
* @param {Boolean} once Only remove one-time listeners.
|
||||
* @returns {EventEmitter} `this`.
|
||||
* @public
|
||||
*/
|
||||
|
||||
|
||||
EventEmitter.prototype.removeListener = function removeListener(event, fn, context, once) {
|
||||
var evt = prefix ? prefix + event : event;
|
||||
if (!this._events[evt]) return this;
|
||||
|
||||
if (!fn) {
|
||||
clearEvent(this, evt);
|
||||
return this;
|
||||
}
|
||||
|
||||
var listeners = this._events[evt];
|
||||
|
||||
if (listeners.fn) {
|
||||
if (listeners.fn === fn && (!once || listeners.once) && (!context || listeners.context === context)) {
|
||||
clearEvent(this, evt);
|
||||
}
|
||||
} else {
|
||||
for (var i = 0, events = [], length = listeners.length; i < length; i++) {
|
||||
if (listeners[i].fn !== fn || once && !listeners[i].once || context && listeners[i].context !== context) {
|
||||
events.push(listeners[i]);
|
||||
}
|
||||
} //
|
||||
// Reset the array, or remove it completely if we have no more listeners.
|
||||
//
|
||||
|
||||
|
||||
if (events.length) this._events[evt] = events.length === 1 ? events[0] : events;else clearEvent(this, evt);
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
/**
|
||||
* Remove all listeners, or those of the specified event.
|
||||
*
|
||||
* @param {(String|Symbol)} [event] The event name.
|
||||
* @returns {EventEmitter} `this`.
|
||||
* @public
|
||||
*/
|
||||
|
||||
|
||||
EventEmitter.prototype.removeAllListeners = function removeAllListeners(event) {
|
||||
var evt;
|
||||
|
||||
if (event) {
|
||||
evt = prefix ? prefix + event : event;
|
||||
if (this._events[evt]) clearEvent(this, evt);
|
||||
} else {
|
||||
this._events = new Events();
|
||||
this._eventsCount = 0;
|
||||
}
|
||||
|
||||
return this;
|
||||
}; //
|
||||
// Alias methods names because people roll like that.
|
||||
//
|
||||
|
||||
|
||||
EventEmitter.prototype.off = EventEmitter.prototype.removeListener;
|
||||
EventEmitter.prototype.addListener = EventEmitter.prototype.on; //
|
||||
// Expose the prefix.
|
||||
//
|
||||
|
||||
EventEmitter.prefixed = prefix; //
|
||||
// Allow `EventEmitter` to be imported as module namespace.
|
||||
//
|
||||
|
||||
EventEmitter.EventEmitter = EventEmitter; //
|
||||
// Expose the module.
|
||||
//
|
||||
|
||||
if ('undefined' !== typeof module) {
|
||||
module.exports = EventEmitter;
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,84 @@
|
||||
{
|
||||
"_from": "eventemitter3@^4.0.0",
|
||||
"_id": "eventemitter3@4.0.0",
|
||||
"_inBundle": false,
|
||||
"_integrity": "sha512-qerSRB0p+UDEssxTtm6EDKcE7W4OaoisfIMl4CngyEhjpYglocpNg6UEqCvemdGhosAsg4sO2dXJOdyBifPGCg==",
|
||||
"_location": "/eventemitter3",
|
||||
"_phantomChildren": {},
|
||||
"_requested": {
|
||||
"type": "range",
|
||||
"registry": true,
|
||||
"raw": "eventemitter3@^4.0.0",
|
||||
"name": "eventemitter3",
|
||||
"escapedName": "eventemitter3",
|
||||
"rawSpec": "^4.0.0",
|
||||
"saveSpec": null,
|
||||
"fetchSpec": "^4.0.0"
|
||||
},
|
||||
"_requiredBy": [
|
||||
"/widget-ui"
|
||||
],
|
||||
"_resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.0.tgz",
|
||||
"_shasum": "d65176163887ee59f386d64c82610b696a4a74eb",
|
||||
"_spec": "eventemitter3@^4.0.0",
|
||||
"_where": "C:\\Users\\sanfordsun\\WeChatProjects\\minicode-177\\node_modules\\widget-ui",
|
||||
"author": {
|
||||
"name": "Arnout Kazemier"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/primus/eventemitter3/issues"
|
||||
},
|
||||
"bundleDependencies": false,
|
||||
"deprecated": false,
|
||||
"description": "EventEmitter3 focuses on performance while maintaining a Node.js AND browser compatible interface.",
|
||||
"devDependencies": {
|
||||
"assume": "~2.2.0",
|
||||
"browserify": "~16.2.0",
|
||||
"mocha": "~6.1.0",
|
||||
"nyc": "~14.1.0",
|
||||
"pre-commit": "~1.2.0",
|
||||
"sauce-browsers": "~2.0.0",
|
||||
"sauce-test": "~1.3.3",
|
||||
"uglify-js": "~3.6.0"
|
||||
},
|
||||
"files": [
|
||||
"index.js",
|
||||
"index.d.ts",
|
||||
"umd"
|
||||
],
|
||||
"homepage": "https://github.com/primus/eventemitter3#readme",
|
||||
"keywords": [
|
||||
"EventEmitter",
|
||||
"EventEmitter2",
|
||||
"EventEmitter3",
|
||||
"Events",
|
||||
"addEventListener",
|
||||
"addListener",
|
||||
"emit",
|
||||
"emits",
|
||||
"emitter",
|
||||
"event",
|
||||
"once",
|
||||
"pub/sub",
|
||||
"publish",
|
||||
"reactor",
|
||||
"subscribe"
|
||||
],
|
||||
"license": "MIT",
|
||||
"main": "index.js",
|
||||
"name": "eventemitter3",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/primus/eventemitter3.git"
|
||||
},
|
||||
"scripts": {
|
||||
"benchmark": "find benchmarks/run -name '*.js' -exec benchmarks/start.sh {} \\;",
|
||||
"browserify": "rm -rf umd && mkdir umd && browserify index.js -s EventEmitter3 -o umd/eventemitter3.js",
|
||||
"minify": "uglifyjs umd/eventemitter3.js --source-map -cm -o umd/eventemitter3.min.js",
|
||||
"prepublishOnly": "npm run browserify && npm run minify",
|
||||
"test": "nyc --reporter=html --reporter=text mocha test/test.js",
|
||||
"test-browser": "node test/browser.js"
|
||||
},
|
||||
"typings": "index.d.ts",
|
||||
"version": "4.0.0"
|
||||
}
|
||||
@@ -0,0 +1,404 @@
|
||||
(function (f) {
|
||||
if (typeof exports === "object" && typeof module !== "undefined") {
|
||||
module.exports = f();
|
||||
} else if (typeof define === "function" && define.amd) {
|
||||
define([], f);
|
||||
} else {
|
||||
var g;
|
||||
|
||||
if (typeof window !== "undefined") {
|
||||
g = window;
|
||||
} else if (typeof global !== "undefined") {
|
||||
g = global;
|
||||
} else if (typeof self !== "undefined") {
|
||||
g = self;
|
||||
} else {
|
||||
g = this;
|
||||
}
|
||||
|
||||
g.EventEmitter3 = f();
|
||||
}
|
||||
})(function () {
|
||||
var define, module, exports;
|
||||
return function () {
|
||||
function r(e, n, t) {
|
||||
function o(i, f) {
|
||||
if (!n[i]) {
|
||||
if (!e[i]) {
|
||||
var c = "function" == typeof require && require;
|
||||
if (!f && c) return c(i, !0);
|
||||
if (u) return u(i, !0);
|
||||
var a = new Error("Cannot find module '" + i + "'");
|
||||
throw a.code = "MODULE_NOT_FOUND", a;
|
||||
}
|
||||
|
||||
var p = n[i] = {
|
||||
exports: {}
|
||||
};
|
||||
e[i][0].call(p.exports, function (r) {
|
||||
var n = e[i][1][r];
|
||||
return o(n || r);
|
||||
}, p, p.exports, r, e, n, t);
|
||||
}
|
||||
|
||||
return n[i].exports;
|
||||
}
|
||||
|
||||
for (var u = "function" == typeof require && require, i = 0; i < t.length; i++) o(t[i]);
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
return r;
|
||||
}()({
|
||||
1: [function (require, module, exports) {
|
||||
'use strict';
|
||||
|
||||
var has = Object.prototype.hasOwnProperty,
|
||||
prefix = '~';
|
||||
/**
|
||||
* Constructor to create a storage for our `EE` objects.
|
||||
* An `Events` instance is a plain object whose properties are event names.
|
||||
*
|
||||
* @constructor
|
||||
* @private
|
||||
*/
|
||||
|
||||
function Events() {} //
|
||||
// We try to not inherit from `Object.prototype`. In some engines creating an
|
||||
// instance in this way is faster than calling `Object.create(null)` directly.
|
||||
// If `Object.create(null)` is not supported we prefix the event names with a
|
||||
// character to make sure that the built-in object properties are not
|
||||
// overridden or used as an attack vector.
|
||||
//
|
||||
|
||||
|
||||
if (Object.create) {
|
||||
Events.prototype = Object.create(null); //
|
||||
// This hack is needed because the `__proto__` property is still inherited in
|
||||
// some old browsers like Android 4, iPhone 5.1, Opera 11 and Safari 5.
|
||||
//
|
||||
|
||||
if (!new Events().__proto__) prefix = false;
|
||||
}
|
||||
/**
|
||||
* Representation of a single event listener.
|
||||
*
|
||||
* @param {Function} fn The listener function.
|
||||
* @param {*} context The context to invoke the listener with.
|
||||
* @param {Boolean} [once=false] Specify if the listener is a one-time listener.
|
||||
* @constructor
|
||||
* @private
|
||||
*/
|
||||
|
||||
|
||||
function EE(fn, context, once) {
|
||||
this.fn = fn;
|
||||
this.context = context;
|
||||
this.once = once || false;
|
||||
}
|
||||
/**
|
||||
* Add a listener for a given event.
|
||||
*
|
||||
* @param {EventEmitter} emitter Reference to the `EventEmitter` instance.
|
||||
* @param {(String|Symbol)} event The event name.
|
||||
* @param {Function} fn The listener function.
|
||||
* @param {*} context The context to invoke the listener with.
|
||||
* @param {Boolean} once Specify if the listener is a one-time listener.
|
||||
* @returns {EventEmitter}
|
||||
* @private
|
||||
*/
|
||||
|
||||
|
||||
function addListener(emitter, event, fn, context, once) {
|
||||
if (typeof fn !== 'function') {
|
||||
throw new TypeError('The listener must be a function');
|
||||
}
|
||||
|
||||
var listener = new EE(fn, context || emitter, once),
|
||||
evt = prefix ? prefix + event : event;
|
||||
if (!emitter._events[evt]) emitter._events[evt] = listener, emitter._eventsCount++;else if (!emitter._events[evt].fn) emitter._events[evt].push(listener);else emitter._events[evt] = [emitter._events[evt], listener];
|
||||
return emitter;
|
||||
}
|
||||
/**
|
||||
* Clear event by name.
|
||||
*
|
||||
* @param {EventEmitter} emitter Reference to the `EventEmitter` instance.
|
||||
* @param {(String|Symbol)} evt The Event name.
|
||||
* @private
|
||||
*/
|
||||
|
||||
|
||||
function clearEvent(emitter, evt) {
|
||||
if (--emitter._eventsCount === 0) emitter._events = new Events();else delete emitter._events[evt];
|
||||
}
|
||||
/**
|
||||
* Minimal `EventEmitter` interface that is molded against the Node.js
|
||||
* `EventEmitter` interface.
|
||||
*
|
||||
* @constructor
|
||||
* @public
|
||||
*/
|
||||
|
||||
|
||||
function EventEmitter() {
|
||||
this._events = new Events();
|
||||
this._eventsCount = 0;
|
||||
}
|
||||
/**
|
||||
* Return an array listing the events for which the emitter has registered
|
||||
* listeners.
|
||||
*
|
||||
* @returns {Array}
|
||||
* @public
|
||||
*/
|
||||
|
||||
|
||||
EventEmitter.prototype.eventNames = function eventNames() {
|
||||
var names = [],
|
||||
events,
|
||||
name;
|
||||
if (this._eventsCount === 0) return names;
|
||||
|
||||
for (name in events = this._events) {
|
||||
if (has.call(events, name)) names.push(prefix ? name.slice(1) : name);
|
||||
}
|
||||
|
||||
if (Object.getOwnPropertySymbols) {
|
||||
return names.concat(Object.getOwnPropertySymbols(events));
|
||||
}
|
||||
|
||||
return names;
|
||||
};
|
||||
/**
|
||||
* Return the listeners registered for a given event.
|
||||
*
|
||||
* @param {(String|Symbol)} event The event name.
|
||||
* @returns {Array} The registered listeners.
|
||||
* @public
|
||||
*/
|
||||
|
||||
|
||||
EventEmitter.prototype.listeners = function listeners(event) {
|
||||
var evt = prefix ? prefix + event : event,
|
||||
handlers = this._events[evt];
|
||||
if (!handlers) return [];
|
||||
if (handlers.fn) return [handlers.fn];
|
||||
|
||||
for (var i = 0, l = handlers.length, ee = new Array(l); i < l; i++) {
|
||||
ee[i] = handlers[i].fn;
|
||||
}
|
||||
|
||||
return ee;
|
||||
};
|
||||
/**
|
||||
* Return the number of listeners listening to a given event.
|
||||
*
|
||||
* @param {(String|Symbol)} event The event name.
|
||||
* @returns {Number} The number of listeners.
|
||||
* @public
|
||||
*/
|
||||
|
||||
|
||||
EventEmitter.prototype.listenerCount = function listenerCount(event) {
|
||||
var evt = prefix ? prefix + event : event,
|
||||
listeners = this._events[evt];
|
||||
if (!listeners) return 0;
|
||||
if (listeners.fn) return 1;
|
||||
return listeners.length;
|
||||
};
|
||||
/**
|
||||
* Calls each of the listeners registered for a given event.
|
||||
*
|
||||
* @param {(String|Symbol)} event The event name.
|
||||
* @returns {Boolean} `true` if the event had listeners, else `false`.
|
||||
* @public
|
||||
*/
|
||||
|
||||
|
||||
EventEmitter.prototype.emit = function emit(event, a1, a2, a3, a4, a5) {
|
||||
var evt = prefix ? prefix + event : event;
|
||||
if (!this._events[evt]) return false;
|
||||
var listeners = this._events[evt],
|
||||
len = arguments.length,
|
||||
args,
|
||||
i;
|
||||
|
||||
if (listeners.fn) {
|
||||
if (listeners.once) this.removeListener(event, listeners.fn, undefined, true);
|
||||
|
||||
switch (len) {
|
||||
case 1:
|
||||
return listeners.fn.call(listeners.context), true;
|
||||
|
||||
case 2:
|
||||
return listeners.fn.call(listeners.context, a1), true;
|
||||
|
||||
case 3:
|
||||
return listeners.fn.call(listeners.context, a1, a2), true;
|
||||
|
||||
case 4:
|
||||
return listeners.fn.call(listeners.context, a1, a2, a3), true;
|
||||
|
||||
case 5:
|
||||
return listeners.fn.call(listeners.context, a1, a2, a3, a4), true;
|
||||
|
||||
case 6:
|
||||
return listeners.fn.call(listeners.context, a1, a2, a3, a4, a5), true;
|
||||
}
|
||||
|
||||
for (i = 1, args = new Array(len - 1); i < len; i++) {
|
||||
args[i - 1] = arguments[i];
|
||||
}
|
||||
|
||||
listeners.fn.apply(listeners.context, args);
|
||||
} else {
|
||||
var length = listeners.length,
|
||||
j;
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
if (listeners[i].once) this.removeListener(event, listeners[i].fn, undefined, true);
|
||||
|
||||
switch (len) {
|
||||
case 1:
|
||||
listeners[i].fn.call(listeners[i].context);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
listeners[i].fn.call(listeners[i].context, a1);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
listeners[i].fn.call(listeners[i].context, a1, a2);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
listeners[i].fn.call(listeners[i].context, a1, a2, a3);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (!args) for (j = 1, args = new Array(len - 1); j < len; j++) {
|
||||
args[j - 1] = arguments[j];
|
||||
}
|
||||
listeners[i].fn.apply(listeners[i].context, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
/**
|
||||
* Add a listener for a given event.
|
||||
*
|
||||
* @param {(String|Symbol)} event The event name.
|
||||
* @param {Function} fn The listener function.
|
||||
* @param {*} [context=this] The context to invoke the listener with.
|
||||
* @returns {EventEmitter} `this`.
|
||||
* @public
|
||||
*/
|
||||
|
||||
|
||||
EventEmitter.prototype.on = function on(event, fn, context) {
|
||||
return addListener(this, event, fn, context, false);
|
||||
};
|
||||
/**
|
||||
* Add a one-time listener for a given event.
|
||||
*
|
||||
* @param {(String|Symbol)} event The event name.
|
||||
* @param {Function} fn The listener function.
|
||||
* @param {*} [context=this] The context to invoke the listener with.
|
||||
* @returns {EventEmitter} `this`.
|
||||
* @public
|
||||
*/
|
||||
|
||||
|
||||
EventEmitter.prototype.once = function once(event, fn, context) {
|
||||
return addListener(this, event, fn, context, true);
|
||||
};
|
||||
/**
|
||||
* Remove the listeners of a given event.
|
||||
*
|
||||
* @param {(String|Symbol)} event The event name.
|
||||
* @param {Function} fn Only remove the listeners that match this function.
|
||||
* @param {*} context Only remove the listeners that have this context.
|
||||
* @param {Boolean} once Only remove one-time listeners.
|
||||
* @returns {EventEmitter} `this`.
|
||||
* @public
|
||||
*/
|
||||
|
||||
|
||||
EventEmitter.prototype.removeListener = function removeListener(event, fn, context, once) {
|
||||
var evt = prefix ? prefix + event : event;
|
||||
if (!this._events[evt]) return this;
|
||||
|
||||
if (!fn) {
|
||||
clearEvent(this, evt);
|
||||
return this;
|
||||
}
|
||||
|
||||
var listeners = this._events[evt];
|
||||
|
||||
if (listeners.fn) {
|
||||
if (listeners.fn === fn && (!once || listeners.once) && (!context || listeners.context === context)) {
|
||||
clearEvent(this, evt);
|
||||
}
|
||||
} else {
|
||||
for (var i = 0, events = [], length = listeners.length; i < length; i++) {
|
||||
if (listeners[i].fn !== fn || once && !listeners[i].once || context && listeners[i].context !== context) {
|
||||
events.push(listeners[i]);
|
||||
}
|
||||
} //
|
||||
// Reset the array, or remove it completely if we have no more listeners.
|
||||
//
|
||||
|
||||
|
||||
if (events.length) this._events[evt] = events.length === 1 ? events[0] : events;else clearEvent(this, evt);
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
/**
|
||||
* Remove all listeners, or those of the specified event.
|
||||
*
|
||||
* @param {(String|Symbol)} [event] The event name.
|
||||
* @returns {EventEmitter} `this`.
|
||||
* @public
|
||||
*/
|
||||
|
||||
|
||||
EventEmitter.prototype.removeAllListeners = function removeAllListeners(event) {
|
||||
var evt;
|
||||
|
||||
if (event) {
|
||||
evt = prefix ? prefix + event : event;
|
||||
if (this._events[evt]) clearEvent(this, evt);
|
||||
} else {
|
||||
this._events = new Events();
|
||||
this._eventsCount = 0;
|
||||
}
|
||||
|
||||
return this;
|
||||
}; //
|
||||
// Alias methods names because people roll like that.
|
||||
//
|
||||
|
||||
|
||||
EventEmitter.prototype.off = EventEmitter.prototype.removeListener;
|
||||
EventEmitter.prototype.addListener = EventEmitter.prototype.on; //
|
||||
// Expose the prefix.
|
||||
//
|
||||
|
||||
EventEmitter.prefixed = prefix; //
|
||||
// Allow `EventEmitter` to be imported as module namespace.
|
||||
//
|
||||
|
||||
EventEmitter.EventEmitter = EventEmitter; //
|
||||
// Expose the module.
|
||||
//
|
||||
|
||||
if ('undefined' !== typeof module) {
|
||||
module.exports = EventEmitter;
|
||||
}
|
||||
}, {}]
|
||||
}, {}, [1])(1);
|
||||
});
|
||||
162
uniapp/uni-app/components/miniprogram_npm/eventemitter3/umd/eventemitter3.min.js
vendored
Normal file
162
uniapp/uni-app/components/miniprogram_npm/eventemitter3/umd/eventemitter3.min.js
vendored
Normal file
@@ -0,0 +1,162 @@
|
||||
!function (e) {
|
||||
if ("object" == typeof exports && "undefined" != typeof module) module.exports = e();else if ("function" == typeof define && define.amd) define([], e);else {
|
||||
("undefined" != typeof window ? window : "undefined" != typeof global ? global : "undefined" != typeof self ? self : this).EventEmitter3 = e();
|
||||
}
|
||||
}(function () {
|
||||
return function i(s, f, c) {
|
||||
function u(t, e) {
|
||||
if (!f[t]) {
|
||||
if (!s[t]) {
|
||||
var n = "function" == typeof require && require;
|
||||
if (!e && n) return n(t, !0);
|
||||
if (a) return a(t, !0);
|
||||
var r = new Error("Cannot find module '" + t + "'");
|
||||
throw r.code = "MODULE_NOT_FOUND", r;
|
||||
}
|
||||
|
||||
var o = f[t] = {
|
||||
exports: {}
|
||||
};
|
||||
s[t][0].call(o.exports, function (e) {
|
||||
return u(s[t][1][e] || e);
|
||||
}, o, o.exports, i, s, f, c);
|
||||
}
|
||||
|
||||
return f[t].exports;
|
||||
}
|
||||
|
||||
for (var a = "function" == typeof require && require, e = 0; e < c.length; e++) u(c[e]);
|
||||
|
||||
return u;
|
||||
}({
|
||||
1: [function (e, t, n) {
|
||||
"use strict";
|
||||
|
||||
var r = Object.prototype.hasOwnProperty,
|
||||
v = "~";
|
||||
|
||||
function o() {}
|
||||
|
||||
function f(e, t, n) {
|
||||
this.fn = e, this.context = t, this.once = n || !1;
|
||||
}
|
||||
|
||||
function i(e, t, n, r, o) {
|
||||
if ("function" != typeof n) throw new TypeError("The listener must be a function");
|
||||
var i = new f(n, r || e, o),
|
||||
s = v ? v + t : t;
|
||||
return e._events[s] ? e._events[s].fn ? e._events[s] = [e._events[s], i] : e._events[s].push(i) : (e._events[s] = i, e._eventsCount++), e;
|
||||
}
|
||||
|
||||
function u(e, t) {
|
||||
0 == --e._eventsCount ? e._events = new o() : delete e._events[t];
|
||||
}
|
||||
|
||||
function s() {
|
||||
this._events = new o(), this._eventsCount = 0;
|
||||
}
|
||||
|
||||
Object.create && (o.prototype = Object.create(null), new o().__proto__ || (v = !1)), s.prototype.eventNames = function () {
|
||||
var e,
|
||||
t,
|
||||
n = [];
|
||||
if (0 === this._eventsCount) return n;
|
||||
|
||||
for (t in e = this._events) r.call(e, t) && n.push(v ? t.slice(1) : t);
|
||||
|
||||
return Object.getOwnPropertySymbols ? n.concat(Object.getOwnPropertySymbols(e)) : n;
|
||||
}, s.prototype.listeners = function (e) {
|
||||
var t = v ? v + e : e,
|
||||
n = this._events[t];
|
||||
if (!n) return [];
|
||||
if (n.fn) return [n.fn];
|
||||
|
||||
for (var r = 0, o = n.length, i = new Array(o); r < o; r++) i[r] = n[r].fn;
|
||||
|
||||
return i;
|
||||
}, s.prototype.listenerCount = function (e) {
|
||||
var t = v ? v + e : e,
|
||||
n = this._events[t];
|
||||
return n ? n.fn ? 1 : n.length : 0;
|
||||
}, s.prototype.emit = function (e, t, n, r, o, i) {
|
||||
var s = v ? v + e : e;
|
||||
if (!this._events[s]) return !1;
|
||||
var f,
|
||||
c,
|
||||
u = this._events[s],
|
||||
a = arguments.length;
|
||||
|
||||
if (u.fn) {
|
||||
switch (u.once && this.removeListener(e, u.fn, void 0, !0), a) {
|
||||
case 1:
|
||||
return u.fn.call(u.context), !0;
|
||||
|
||||
case 2:
|
||||
return u.fn.call(u.context, t), !0;
|
||||
|
||||
case 3:
|
||||
return u.fn.call(u.context, t, n), !0;
|
||||
|
||||
case 4:
|
||||
return u.fn.call(u.context, t, n, r), !0;
|
||||
|
||||
case 5:
|
||||
return u.fn.call(u.context, t, n, r, o), !0;
|
||||
|
||||
case 6:
|
||||
return u.fn.call(u.context, t, n, r, o, i), !0;
|
||||
}
|
||||
|
||||
for (c = 1, f = new Array(a - 1); c < a; c++) f[c - 1] = arguments[c];
|
||||
|
||||
u.fn.apply(u.context, f);
|
||||
} else {
|
||||
var l,
|
||||
p = u.length;
|
||||
|
||||
for (c = 0; c < p; c++) switch (u[c].once && this.removeListener(e, u[c].fn, void 0, !0), a) {
|
||||
case 1:
|
||||
u[c].fn.call(u[c].context);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
u[c].fn.call(u[c].context, t);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
u[c].fn.call(u[c].context, t, n);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
u[c].fn.call(u[c].context, t, n, r);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (!f) for (l = 1, f = new Array(a - 1); l < a; l++) f[l - 1] = arguments[l];
|
||||
u[c].fn.apply(u[c].context, f);
|
||||
}
|
||||
}
|
||||
|
||||
return !0;
|
||||
}, s.prototype.on = function (e, t, n) {
|
||||
return i(this, e, t, n, !1);
|
||||
}, s.prototype.once = function (e, t, n) {
|
||||
return i(this, e, t, n, !0);
|
||||
}, s.prototype.removeListener = function (e, t, n, r) {
|
||||
var o = v ? v + e : e;
|
||||
if (!this._events[o]) return this;
|
||||
if (!t) return u(this, o), this;
|
||||
var i = this._events[o];
|
||||
if (i.fn) i.fn !== t || r && !i.once || n && i.context !== n || u(this, o);else {
|
||||
for (var s = 0, f = [], c = i.length; s < c; s++) (i[s].fn !== t || r && !i[s].once || n && i[s].context !== n) && f.push(i[s]);
|
||||
|
||||
f.length ? this._events[o] = 1 === f.length ? f[0] : f : u(this, o);
|
||||
}
|
||||
return this;
|
||||
}, s.prototype.removeAllListeners = function (e) {
|
||||
var t;
|
||||
return e ? (t = v ? v + e : e, this._events[t] && u(this, t)) : (this._events = new o(), this._eventsCount = 0), this;
|
||||
}, s.prototype.off = s.prototype.removeListener, s.prototype.addListener = s.prototype.on, s.prefixed = v, s.EventEmitter = s, void 0 !== t && (t.exports = s);
|
||||
}, {}]
|
||||
}, {}, [1])(1);
|
||||
});
|
||||
File diff suppressed because one or more lines are too long
1295
uniapp/uni-app/components/miniprogram_npm/widget-ui/css-layout.js
Normal file
1295
uniapp/uni-app/components/miniprogram_npm/widget-ui/css-layout.js
Normal file
File diff suppressed because it is too large
Load Diff
172
uniapp/uni-app/components/miniprogram_npm/widget-ui/element.ts
Normal file
172
uniapp/uni-app/components/miniprogram_npm/widget-ui/element.ts
Normal file
@@ -0,0 +1,172 @@
|
||||
|
||||
import computeLayout from "./css-layout";
|
||||
import { getDefaultStyle, scalableStyles, layoutAffectedStyles } from "./style";
|
||||
|
||||
type LayoutData = {
|
||||
left: number,
|
||||
top: number,
|
||||
width: number,
|
||||
height: number
|
||||
};
|
||||
|
||||
type LayoutNode = {
|
||||
id: number,
|
||||
style: Object,
|
||||
children: LayoutNode[],
|
||||
layout?: LayoutData
|
||||
};
|
||||
|
||||
let uuid = 0;
|
||||
|
||||
class Element {
|
||||
public static uuid(): number {
|
||||
return uuid++;
|
||||
}
|
||||
|
||||
public parent: Element | null = null;
|
||||
public id: number = Element.uuid();
|
||||
public style: { [key: string]: any } = {};
|
||||
public computedStyle: { [key: string]: any } = {};
|
||||
public lastComputedStyle: { [key: string]: any } = {};
|
||||
public children: { [key: string]: Element } = {};
|
||||
public layoutBox: LayoutData = { left: 0, top: 0, width: 0, height: 0 };
|
||||
|
||||
constructor(style: { [key: string]: any } = {}) {
|
||||
// 拷贝一份,防止被外部逻辑修改
|
||||
style = Object.assign(getDefaultStyle(), style);
|
||||
this.computedStyle = Object.assign(getDefaultStyle(), style);
|
||||
this.lastComputedStyle = Object.assign(getDefaultStyle(), style);
|
||||
|
||||
Object.keys(style).forEach(key => {
|
||||
Object.defineProperty(this.style, key, {
|
||||
configurable: true,
|
||||
enumerable: true,
|
||||
get: () => style[key],
|
||||
set: (value: any) => {
|
||||
if (value === style[key] || value === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.lastComputedStyle = this.computedStyle[key]
|
||||
style[key] = value
|
||||
this.computedStyle[key] = value
|
||||
|
||||
// 如果设置的是一个可缩放的属性, 计算自己
|
||||
if (scalableStyles.includes(key) && this.style.scale) {
|
||||
this.computedStyle[key] = value * this.style.scale
|
||||
}
|
||||
|
||||
// 如果设置的是 scale, 则把所有可缩放的属性计算
|
||||
if (key === "scale") {
|
||||
scalableStyles.forEach(prop => {
|
||||
if (style[prop]) {
|
||||
this.computedStyle[prop] = style[prop] * value
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if (key === "hidden") {
|
||||
if (value) {
|
||||
layoutAffectedStyles.forEach((key: string) => {
|
||||
this.computedStyle[key] = 0;
|
||||
});
|
||||
} else {
|
||||
layoutAffectedStyles.forEach((key: string) => {
|
||||
this.computedStyle[key] = this.lastComputedStyle[key];
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
if (this.style.scale) {
|
||||
scalableStyles.forEach((key: string) => {
|
||||
if (this.style[key]) {
|
||||
const computedValue = this.style[key] * this.style.scale;
|
||||
this.computedStyle[key] = computedValue;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (style.hidden) {
|
||||
layoutAffectedStyles.forEach((key: string) => {
|
||||
this.computedStyle[key] = 0;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
getAbsolutePosition(element: Element) {
|
||||
if (!element) {
|
||||
return this.getAbsolutePosition(this)
|
||||
}
|
||||
|
||||
if (!element.parent) {
|
||||
return {
|
||||
left: 0,
|
||||
top: 0
|
||||
}
|
||||
}
|
||||
|
||||
const {left, top} = this.getAbsolutePosition(element.parent)
|
||||
|
||||
return {
|
||||
left: left + element.layoutBox.left,
|
||||
top: top + element.layoutBox.top
|
||||
}
|
||||
}
|
||||
|
||||
public add(element: Element) {
|
||||
element.parent = this;
|
||||
this.children[element.id] = element;
|
||||
}
|
||||
|
||||
public remove(element?: Element) {
|
||||
// 删除自己
|
||||
if (!element) {
|
||||
Object.keys(this.children).forEach(id => {
|
||||
const child = this.children[id]
|
||||
child.remove()
|
||||
delete this.children[id]
|
||||
})
|
||||
} else if (this.children[element.id]) {
|
||||
// 是自己的子节点才删除
|
||||
element.remove()
|
||||
delete this.children[element.id];
|
||||
}
|
||||
}
|
||||
|
||||
public getNodeTree(): LayoutNode {
|
||||
return {
|
||||
id: this.id,
|
||||
style: this.computedStyle,
|
||||
children: Object.keys(this.children).map((id: string) => {
|
||||
const child = this.children[id];
|
||||
return child.getNodeTree();
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
public applyLayout(layoutNode: LayoutNode) {
|
||||
["left", "top", "width", "height"].forEach((key: string) => {
|
||||
if (layoutNode.layout && typeof layoutNode.layout[key] === "number") {
|
||||
this.layoutBox[key] = layoutNode.layout[key];
|
||||
if (this.parent && (key === "left" || key === "top")) {
|
||||
this.layoutBox[key] += this.parent.layoutBox[key];
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
layoutNode.children.forEach((child: LayoutNode) => {
|
||||
this.children[child.id].applyLayout(child);
|
||||
});
|
||||
}
|
||||
|
||||
layout() {
|
||||
const nodeTree = this.getNodeTree();
|
||||
computeLayout(nodeTree);
|
||||
this.applyLayout(nodeTree);
|
||||
}
|
||||
}
|
||||
|
||||
export default Element;
|
||||
15
uniapp/uni-app/components/miniprogram_npm/widget-ui/event.ts
Normal file
15
uniapp/uni-app/components/miniprogram_npm/widget-ui/event.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import _EventEmitter from "eventemitter3";
|
||||
const emitter = new _EventEmitter();
|
||||
export default class EventEmitter {
|
||||
public emit(event: string, data?: any) {
|
||||
emitter.emit(event, data);
|
||||
}
|
||||
|
||||
public on(event: string, callback) {
|
||||
emitter.on(event, callback);
|
||||
}
|
||||
|
||||
public off(event: string, callback) {
|
||||
emitter.off(event, callback);
|
||||
}
|
||||
}
|
||||
746
uniapp/uni-app/components/miniprogram_npm/widget-ui/index.js
Normal file
746
uniapp/uni-app/components/miniprogram_npm/widget-ui/index.js
Normal file
@@ -0,0 +1,746 @@
|
||||
module.exports = function () {
|
||||
var __MODS__ = {};
|
||||
|
||||
var __DEFINE__ = function (modId, func, req) {
|
||||
var m = {
|
||||
exports: {}
|
||||
};
|
||||
__MODS__[modId] = {
|
||||
status: 0,
|
||||
func: func,
|
||||
req: req,
|
||||
m: m
|
||||
};
|
||||
};
|
||||
|
||||
var __REQUIRE__ = function (modId, source) {
|
||||
if (!__MODS__[modId]) return require(source);
|
||||
|
||||
if (!__MODS__[modId].status) {
|
||||
var m = {
|
||||
exports: {}
|
||||
};
|
||||
__MODS__[modId].status = 1;
|
||||
|
||||
__MODS__[modId].func(__MODS__[modId].req, m, m.exports);
|
||||
|
||||
if (typeof m.exports === "object") {
|
||||
__MODS__[modId].m.exports.__proto__ = m.exports.__proto__;
|
||||
Object.keys(m.exports).forEach(function (k) {
|
||||
__MODS__[modId].m.exports[k] = m.exports[k];
|
||||
var desp = Object.getOwnPropertyDescriptor(m.exports, k);
|
||||
if (desp && desp.configurable) Object.defineProperty(m.exports, k, {
|
||||
set: function (val) {
|
||||
__MODS__[modId].m.exports[k] = val;
|
||||
},
|
||||
get: function () {
|
||||
return __MODS__[modId].m.exports[k];
|
||||
}
|
||||
});
|
||||
});
|
||||
if (m.exports.__esModule) Object.defineProperty(__MODS__[modId].m.exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
} else {
|
||||
__MODS__[modId].m.exports = m.exports;
|
||||
}
|
||||
}
|
||||
|
||||
return __MODS__[modId].m.exports;
|
||||
};
|
||||
|
||||
var __REQUIRE_WILDCARD__ = function (obj) {
|
||||
if (obj && obj.__esModule) {
|
||||
return obj;
|
||||
} else {
|
||||
var newObj = {};
|
||||
|
||||
if (obj != null) {
|
||||
for (var k in obj) {
|
||||
if (Object.prototype.hasOwnProperty.call(obj, k)) newObj[k] = obj[k];
|
||||
}
|
||||
}
|
||||
|
||||
newObj.default = obj;
|
||||
return newObj;
|
||||
}
|
||||
};
|
||||
|
||||
var __REQUIRE_DEFAULT__ = function (obj) {
|
||||
return obj && obj.__esModule ? obj.default : obj;
|
||||
};
|
||||
|
||||
__DEFINE__(1572960819414, function (require, module, exports) {
|
||||
!function (t, e) {
|
||||
if ("object" == typeof exports && "object" == typeof module) module.exports = e();else if ("function" == typeof define && define.amd) define([], e);else {
|
||||
var o = e();
|
||||
|
||||
for (var r in o) ("object" == typeof exports ? exports : t)[r] = o[r];
|
||||
}
|
||||
}(this, function () {
|
||||
return function (t) {
|
||||
var e = {};
|
||||
|
||||
function o(r) {
|
||||
if (e[r]) return e[r].exports;
|
||||
var i = e[r] = {
|
||||
i: r,
|
||||
l: !1,
|
||||
exports: {}
|
||||
};
|
||||
return t[r].call(i.exports, i, i.exports, o), i.l = !0, i.exports;
|
||||
}
|
||||
|
||||
return o.m = t, o.c = e, o.d = function (t, e, r) {
|
||||
o.o(t, e) || Object.defineProperty(t, e, {
|
||||
enumerable: !0,
|
||||
get: r
|
||||
});
|
||||
}, o.r = function (t) {
|
||||
"undefined" != typeof Symbol && Symbol.toStringTag && Object.defineProperty(t, Symbol.toStringTag, {
|
||||
value: "Module"
|
||||
}), Object.defineProperty(t, "__esModule", {
|
||||
value: !0
|
||||
});
|
||||
}, o.t = function (t, e) {
|
||||
if (1 & e && (t = o(t)), 8 & e) return t;
|
||||
if (4 & e && "object" == typeof t && t && t.__esModule) return t;
|
||||
var r = Object.create(null);
|
||||
if (o.r(r), Object.defineProperty(r, "default", {
|
||||
enumerable: !0,
|
||||
value: t
|
||||
}), 2 & e && "string" != typeof t) for (var i in t) o.d(r, i, function (e) {
|
||||
return t[e];
|
||||
}.bind(null, i));
|
||||
return r;
|
||||
}, o.n = function (t) {
|
||||
var e = t && t.__esModule ? function () {
|
||||
return t.default;
|
||||
} : function () {
|
||||
return t;
|
||||
};
|
||||
return o.d(e, "a", e), e;
|
||||
}, o.o = function (t, e) {
|
||||
return Object.prototype.hasOwnProperty.call(t, e);
|
||||
}, o.p = "", o(o.s = 0);
|
||||
}([function (t, e, o) {
|
||||
var r = this && this.__importDefault || function (t) {
|
||||
return t && t.__esModule ? t : {
|
||||
default: t
|
||||
};
|
||||
};
|
||||
|
||||
Object.defineProperty(e, "__esModule", {
|
||||
value: !0
|
||||
});
|
||||
|
||||
var i = r(o(1)),
|
||||
l = o(2),
|
||||
n = 0,
|
||||
a = function () {
|
||||
function t(e) {
|
||||
var o = this;
|
||||
void 0 === e && (e = {}), this.parent = null, this.id = t.uuid(), this.style = {}, this.computedStyle = {}, this.lastComputedStyle = {}, this.children = {}, this.layoutBox = {
|
||||
left: 0,
|
||||
top: 0,
|
||||
width: 0,
|
||||
height: 0
|
||||
}, e = Object.assign(l.getDefaultStyle(), e), this.computedStyle = Object.assign(l.getDefaultStyle(), e), this.lastComputedStyle = Object.assign(l.getDefaultStyle(), e), Object.keys(e).forEach(function (t) {
|
||||
Object.defineProperty(o.style, t, {
|
||||
configurable: !0,
|
||||
enumerable: !0,
|
||||
get: function () {
|
||||
return e[t];
|
||||
},
|
||||
set: function (r) {
|
||||
r !== e[t] && void 0 !== r && (o.lastComputedStyle = o.computedStyle[t], e[t] = r, o.computedStyle[t] = r, l.scalableStyles.includes(t) && o.style.scale && (o.computedStyle[t] = r * o.style.scale), "scale" === t && l.scalableStyles.forEach(function (t) {
|
||||
e[t] && (o.computedStyle[t] = e[t] * r);
|
||||
}), "hidden" === t && (r ? l.layoutAffectedStyles.forEach(function (t) {
|
||||
o.computedStyle[t] = 0;
|
||||
}) : l.layoutAffectedStyles.forEach(function (t) {
|
||||
o.computedStyle[t] = o.lastComputedStyle[t];
|
||||
})));
|
||||
}
|
||||
});
|
||||
}), this.style.scale && l.scalableStyles.forEach(function (t) {
|
||||
if (o.style[t]) {
|
||||
var e = o.style[t] * o.style.scale;
|
||||
o.computedStyle[t] = e;
|
||||
}
|
||||
}), e.hidden && l.layoutAffectedStyles.forEach(function (t) {
|
||||
o.computedStyle[t] = 0;
|
||||
});
|
||||
}
|
||||
|
||||
return t.uuid = function () {
|
||||
return n++;
|
||||
}, t.prototype.getAbsolutePosition = function (t) {
|
||||
if (!t) return this.getAbsolutePosition(this);
|
||||
if (!t.parent) return {
|
||||
left: 0,
|
||||
top: 0
|
||||
};
|
||||
var e = this.getAbsolutePosition(t.parent),
|
||||
o = e.left,
|
||||
r = e.top;
|
||||
return {
|
||||
left: o + t.layoutBox.left,
|
||||
top: r + t.layoutBox.top
|
||||
};
|
||||
}, t.prototype.add = function (t) {
|
||||
t.parent = this, this.children[t.id] = t;
|
||||
}, t.prototype.remove = function (t) {
|
||||
var e = this;
|
||||
t ? this.children[t.id] && (t.remove(), delete this.children[t.id]) : Object.keys(this.children).forEach(function (t) {
|
||||
e.children[t].remove(), delete e.children[t];
|
||||
});
|
||||
}, t.prototype.getNodeTree = function () {
|
||||
var t = this;
|
||||
return {
|
||||
id: this.id,
|
||||
style: this.computedStyle,
|
||||
children: Object.keys(this.children).map(function (e) {
|
||||
return t.children[e].getNodeTree();
|
||||
})
|
||||
};
|
||||
}, t.prototype.applyLayout = function (t) {
|
||||
var e = this;
|
||||
["left", "top", "width", "height"].forEach(function (o) {
|
||||
t.layout && "number" == typeof t.layout[o] && (e.layoutBox[o] = t.layout[o], !e.parent || "left" !== o && "top" !== o || (e.layoutBox[o] += e.parent.layoutBox[o]));
|
||||
}), t.children.forEach(function (t) {
|
||||
e.children[t.id].applyLayout(t);
|
||||
});
|
||||
}, t.prototype.layout = function () {
|
||||
var t = this.getNodeTree();
|
||||
i.default(t), this.applyLayout(t);
|
||||
}, t;
|
||||
}();
|
||||
|
||||
e.default = a;
|
||||
}, function (t, e, o) {
|
||||
o.r(e);
|
||||
|
||||
var r = function () {
|
||||
var t,
|
||||
e = "inherit",
|
||||
o = "ltr",
|
||||
r = "rtl",
|
||||
i = "row",
|
||||
l = "row-reverse",
|
||||
n = "column",
|
||||
a = "column-reverse",
|
||||
u = "flex-start",
|
||||
d = "center",
|
||||
s = "flex-end",
|
||||
y = "space-between",
|
||||
c = "space-around",
|
||||
f = "flex-start",
|
||||
h = "center",
|
||||
p = "flex-end",
|
||||
g = "stretch",
|
||||
v = "relative",
|
||||
m = "absolute",
|
||||
b = {
|
||||
row: "left",
|
||||
"row-reverse": "right",
|
||||
column: "top",
|
||||
"column-reverse": "bottom"
|
||||
},
|
||||
x = {
|
||||
row: "right",
|
||||
"row-reverse": "left",
|
||||
column: "bottom",
|
||||
"column-reverse": "top"
|
||||
},
|
||||
w = {
|
||||
row: "left",
|
||||
"row-reverse": "right",
|
||||
column: "top",
|
||||
"column-reverse": "bottom"
|
||||
},
|
||||
S = {
|
||||
row: "width",
|
||||
"row-reverse": "width",
|
||||
column: "height",
|
||||
"column-reverse": "height"
|
||||
};
|
||||
|
||||
function W(t) {
|
||||
return void 0 === t;
|
||||
}
|
||||
|
||||
function L(t) {
|
||||
return t === i || t === l;
|
||||
}
|
||||
|
||||
function k(t, e) {
|
||||
if (void 0 !== t.style.marginStart && L(e)) return t.style.marginStart;
|
||||
var o = null;
|
||||
|
||||
switch (e) {
|
||||
case "row":
|
||||
o = t.style.marginLeft;
|
||||
break;
|
||||
|
||||
case "row-reverse":
|
||||
o = t.style.marginRight;
|
||||
break;
|
||||
|
||||
case "column":
|
||||
o = t.style.marginTop;
|
||||
break;
|
||||
|
||||
case "column-reverse":
|
||||
o = t.style.marginBottom;
|
||||
}
|
||||
|
||||
return void 0 !== o ? o : void 0 !== t.style.margin ? t.style.margin : 0;
|
||||
}
|
||||
|
||||
function j(t, e) {
|
||||
if (void 0 !== t.style.marginEnd && L(e)) return t.style.marginEnd;
|
||||
var o = null;
|
||||
|
||||
switch (e) {
|
||||
case "row":
|
||||
o = t.style.marginRight;
|
||||
break;
|
||||
|
||||
case "row-reverse":
|
||||
o = t.style.marginLeft;
|
||||
break;
|
||||
|
||||
case "column":
|
||||
o = t.style.marginBottom;
|
||||
break;
|
||||
|
||||
case "column-reverse":
|
||||
o = t.style.marginTop;
|
||||
}
|
||||
|
||||
return null != o ? o : void 0 !== t.style.margin ? t.style.margin : 0;
|
||||
}
|
||||
|
||||
function B(t, e) {
|
||||
if (void 0 !== t.style.borderStartWidth && t.style.borderStartWidth >= 0 && L(e)) return t.style.borderStartWidth;
|
||||
var o = null;
|
||||
|
||||
switch (e) {
|
||||
case "row":
|
||||
o = t.style.borderLeftWidth;
|
||||
break;
|
||||
|
||||
case "row-reverse":
|
||||
o = t.style.borderRightWidth;
|
||||
break;
|
||||
|
||||
case "column":
|
||||
o = t.style.borderTopWidth;
|
||||
break;
|
||||
|
||||
case "column-reverse":
|
||||
o = t.style.borderBottomWidth;
|
||||
}
|
||||
|
||||
return null != o && o >= 0 ? o : void 0 !== t.style.borderWidth && t.style.borderWidth >= 0 ? t.style.borderWidth : 0;
|
||||
}
|
||||
|
||||
function E(t, e) {
|
||||
if (void 0 !== t.style.borderEndWidth && t.style.borderEndWidth >= 0 && L(e)) return t.style.borderEndWidth;
|
||||
var o = null;
|
||||
|
||||
switch (e) {
|
||||
case "row":
|
||||
o = t.style.borderRightWidth;
|
||||
break;
|
||||
|
||||
case "row-reverse":
|
||||
o = t.style.borderLeftWidth;
|
||||
break;
|
||||
|
||||
case "column":
|
||||
o = t.style.borderBottomWidth;
|
||||
break;
|
||||
|
||||
case "column-reverse":
|
||||
o = t.style.borderTopWidth;
|
||||
}
|
||||
|
||||
return null != o && o >= 0 ? o : void 0 !== t.style.borderWidth && t.style.borderWidth >= 0 ? t.style.borderWidth : 0;
|
||||
}
|
||||
|
||||
function C(t, e) {
|
||||
return function (t, e) {
|
||||
if (void 0 !== t.style.paddingStart && t.style.paddingStart >= 0 && L(e)) return t.style.paddingStart;
|
||||
var o = null;
|
||||
|
||||
switch (e) {
|
||||
case "row":
|
||||
o = t.style.paddingLeft;
|
||||
break;
|
||||
|
||||
case "row-reverse":
|
||||
o = t.style.paddingRight;
|
||||
break;
|
||||
|
||||
case "column":
|
||||
o = t.style.paddingTop;
|
||||
break;
|
||||
|
||||
case "column-reverse":
|
||||
o = t.style.paddingBottom;
|
||||
}
|
||||
|
||||
return null != o && o >= 0 ? o : void 0 !== t.style.padding && t.style.padding >= 0 ? t.style.padding : 0;
|
||||
}(t, e) + B(t, e);
|
||||
}
|
||||
|
||||
function T(t, e) {
|
||||
return function (t, e) {
|
||||
if (void 0 !== t.style.paddingEnd && t.style.paddingEnd >= 0 && L(e)) return t.style.paddingEnd;
|
||||
var o = null;
|
||||
|
||||
switch (e) {
|
||||
case "row":
|
||||
o = t.style.paddingRight;
|
||||
break;
|
||||
|
||||
case "row-reverse":
|
||||
o = t.style.paddingLeft;
|
||||
break;
|
||||
|
||||
case "column":
|
||||
o = t.style.paddingBottom;
|
||||
break;
|
||||
|
||||
case "column-reverse":
|
||||
o = t.style.paddingTop;
|
||||
}
|
||||
|
||||
return null != o && o >= 0 ? o : void 0 !== t.style.padding && t.style.padding >= 0 ? t.style.padding : 0;
|
||||
}(t, e) + E(t, e);
|
||||
}
|
||||
|
||||
function O(t, e) {
|
||||
return B(t, e) + E(t, e);
|
||||
}
|
||||
|
||||
function _(t, e) {
|
||||
return k(t, e) + j(t, e);
|
||||
}
|
||||
|
||||
function R(t, e) {
|
||||
return C(t, e) + T(t, e);
|
||||
}
|
||||
|
||||
function A(t, e) {
|
||||
return e.style.alignSelf ? e.style.alignSelf : t.style.alignItems ? t.style.alignItems : "stretch";
|
||||
}
|
||||
|
||||
function P(t, e) {
|
||||
if (e === r) {
|
||||
if (t === i) return l;
|
||||
if (t === l) return i;
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
function D(t, e) {
|
||||
return function (t) {
|
||||
return t === n || t === a;
|
||||
}(t) ? P(i, e) : n;
|
||||
}
|
||||
|
||||
function H(t) {
|
||||
return t.style.position ? t.style.position : "relative";
|
||||
}
|
||||
|
||||
function M(t) {
|
||||
return H(t) === v && t.style.flex > 0;
|
||||
}
|
||||
|
||||
function I(t, e) {
|
||||
return t.layout[S[e]] + _(t, e);
|
||||
}
|
||||
|
||||
function N(t, e) {
|
||||
return void 0 !== t.style[S[e]] && t.style[S[e]] >= 0;
|
||||
}
|
||||
|
||||
function F(t, e) {
|
||||
return void 0 !== t.style[e];
|
||||
}
|
||||
|
||||
function q(t, e) {
|
||||
return void 0 !== t.style[e] ? t.style[e] : 0;
|
||||
}
|
||||
|
||||
function z(t, e, o) {
|
||||
var r = {
|
||||
row: t.style.minWidth,
|
||||
"row-reverse": t.style.minWidth,
|
||||
column: t.style.minHeight,
|
||||
"column-reverse": t.style.minHeight
|
||||
}[e],
|
||||
i = {
|
||||
row: t.style.maxWidth,
|
||||
"row-reverse": t.style.maxWidth,
|
||||
column: t.style.maxHeight,
|
||||
"column-reverse": t.style.maxHeight
|
||||
}[e],
|
||||
l = o;
|
||||
return void 0 !== i && i >= 0 && l > i && (l = i), void 0 !== r && r >= 0 && l < r && (l = r), l;
|
||||
}
|
||||
|
||||
function U(t, e) {
|
||||
return t > e ? t : e;
|
||||
}
|
||||
|
||||
function G(t, e) {
|
||||
void 0 === t.layout[S[e]] && N(t, e) && (t.layout[S[e]] = U(z(t, e, t.style[S[e]]), R(t, e)));
|
||||
}
|
||||
|
||||
function J(t, e, o) {
|
||||
e.layout[x[o]] = t.layout[S[o]] - e.layout[S[o]] - e.layout[w[o]];
|
||||
}
|
||||
|
||||
function K(t, e) {
|
||||
return void 0 !== t.style[b[e]] ? q(t, b[e]) : -q(t, x[e]);
|
||||
}
|
||||
|
||||
function Q(r, E, Q) {
|
||||
var X = function (t, r) {
|
||||
var i;
|
||||
return (i = t.style.direction ? t.style.direction : e) === e && (i = void 0 === r ? o : r), i;
|
||||
}(r, Q),
|
||||
Y = P(function (t) {
|
||||
return t.style.flexDirection ? t.style.flexDirection : n;
|
||||
}(r), X),
|
||||
Z = D(Y, X),
|
||||
$ = P(i, X);
|
||||
|
||||
G(r, Y), G(r, Z), r.layout.direction = X, r.layout[b[Y]] += k(r, Y) + K(r, Y), r.layout[x[Y]] += j(r, Y) + K(r, Y), r.layout[b[Z]] += k(r, Z) + K(r, Z), r.layout[x[Z]] += j(r, Z) + K(r, Z);
|
||||
var tt = r.children.length,
|
||||
et = R(r, $);
|
||||
|
||||
if (function (t) {
|
||||
return void 0 !== t.style.measure;
|
||||
}(r)) {
|
||||
var ot = !W(r.layout[S[$]]),
|
||||
rt = t;
|
||||
rt = N(r, $) ? r.style.width : ot ? r.layout[S[$]] : E - _(r, $), rt -= et;
|
||||
var it = !N(r, $) && !ot,
|
||||
lt = !N(r, n) && W(r.layout[S[n]]);
|
||||
|
||||
if (it || lt) {
|
||||
var nt = r.style.measure(rt);
|
||||
it && (r.layout.width = nt.width + et), lt && (r.layout.height = nt.height + R(r, n));
|
||||
}
|
||||
|
||||
if (0 === tt) return;
|
||||
}
|
||||
|
||||
var at,
|
||||
ut,
|
||||
dt,
|
||||
st,
|
||||
yt = function (t) {
|
||||
return "wrap" === t.style.flexWrap;
|
||||
}(r),
|
||||
ct = function (t) {
|
||||
return t.style.justifyContent ? t.style.justifyContent : "flex-start";
|
||||
}(r),
|
||||
ft = C(r, Y),
|
||||
ht = C(r, Z),
|
||||
pt = R(r, Y),
|
||||
gt = R(r, Z),
|
||||
vt = !W(r.layout[S[Y]]),
|
||||
mt = !W(r.layout[S[Z]]),
|
||||
bt = L(Y),
|
||||
xt = null,
|
||||
wt = null,
|
||||
St = t;
|
||||
|
||||
vt && (St = r.layout[S[Y]] - pt);
|
||||
|
||||
for (var Wt = 0, Lt = 0, kt = 0, jt = 0, Bt = 0, Et = 0; Lt < tt;) {
|
||||
var Ct,
|
||||
Tt = 0,
|
||||
Ot = 0,
|
||||
_t = 0,
|
||||
Rt = 0,
|
||||
At = vt && ct === u || !vt && ct !== d,
|
||||
Pt = At ? tt : Wt,
|
||||
Dt = !0,
|
||||
Ht = tt,
|
||||
Mt = null,
|
||||
It = null,
|
||||
Nt = ft,
|
||||
Ft = 0;
|
||||
|
||||
for (at = Wt; at < tt; ++at) {
|
||||
if ((dt = r.children[at]).lineIndex = Et, dt.nextAbsoluteChild = null, dt.nextFlexChild = null, (Xt = A(r, dt)) === g && H(dt) === v && mt && !N(dt, Z)) dt.layout[S[Z]] = U(z(dt, Z, r.layout[S[Z]] - gt - _(dt, Z)), R(dt, Z));else if (H(dt) === m) for (null === xt && (xt = dt), null !== wt && (wt.nextAbsoluteChild = dt), wt = dt, ut = 0; ut < 2; ut++) st = 0 !== ut ? i : n, !W(r.layout[S[st]]) && !N(dt, st) && F(dt, b[st]) && F(dt, x[st]) && (dt.layout[S[st]] = U(z(dt, st, r.layout[S[st]] - R(r, st) - _(dt, st) - q(dt, b[st]) - q(dt, x[st])), R(dt, st)));
|
||||
var qt = 0;
|
||||
|
||||
if (vt && M(dt) ? (Ot++, _t += dt.style.flex, null === Mt && (Mt = dt), null !== It && (It.nextFlexChild = dt), It = dt, qt = R(dt, Y) + _(dt, Y)) : (Ct = t, bt || (Ct = N(r, $) ? r.layout[S[$]] - et : E - _(r, $) - et), 0 === kt && V(dt, Ct, X), H(dt) === v && (Rt++, qt = I(dt, Y))), yt && vt && Tt + qt > St && at !== Wt) {
|
||||
Rt--, kt = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
At && (H(dt) !== v || M(dt)) && (At = !1, Pt = at), Dt && (H(dt) !== v || Xt !== g && Xt !== f || W(dt.layout[S[Z]])) && (Dt = !1, Ht = at), At && (dt.layout[w[Y]] += Nt, vt && J(r, dt, Y), Nt += I(dt, Y), Ft = U(Ft, z(dt, Z, I(dt, Z)))), Dt && (dt.layout[w[Z]] += jt + ht, mt && J(r, dt, Z)), kt = 0, Tt += qt, Lt = at + 1;
|
||||
}
|
||||
|
||||
var zt = 0,
|
||||
Ut = 0,
|
||||
Gt = 0;
|
||||
|
||||
if (Gt = vt ? St - Tt : U(Tt, 0) - Tt, 0 !== Ot) {
|
||||
var Jt,
|
||||
Kt,
|
||||
Qt = Gt / _t;
|
||||
|
||||
for (It = Mt; null !== It;) (Jt = Qt * It.style.flex + R(It, Y)) !== (Kt = z(It, Y, Jt)) && (Gt -= Kt, _t -= It.style.flex), It = It.nextFlexChild;
|
||||
|
||||
for ((Qt = Gt / _t) < 0 && (Qt = 0), It = Mt; null !== It;) It.layout[S[Y]] = z(It, Y, Qt * It.style.flex + R(It, Y)), Ct = t, N(r, $) ? Ct = r.layout[S[$]] - et : bt || (Ct = E - _(r, $) - et), V(It, Ct, X), dt = It, It = It.nextFlexChild, dt.nextFlexChild = null;
|
||||
} else ct !== u && (ct === d ? zt = Gt / 2 : ct === s ? zt = Gt : ct === y ? (Gt = U(Gt, 0), Ut = Ot + Rt - 1 != 0 ? Gt / (Ot + Rt - 1) : 0) : ct === c && (zt = (Ut = Gt / (Ot + Rt)) / 2));
|
||||
|
||||
for (Nt += zt, at = Pt; at < Lt; ++at) H(dt = r.children[at]) === m && F(dt, b[Y]) ? dt.layout[w[Y]] = q(dt, b[Y]) + B(r, Y) + k(dt, Y) : (dt.layout[w[Y]] += Nt, vt && J(r, dt, Y), H(dt) === v && (Nt += Ut + I(dt, Y), Ft = U(Ft, z(dt, Z, I(dt, Z)))));
|
||||
|
||||
var Vt = r.layout[S[Z]];
|
||||
|
||||
for (mt || (Vt = U(z(r, Z, Ft + gt), gt)), at = Ht; at < Lt; ++at) if (H(dt = r.children[at]) === m && F(dt, b[Z])) dt.layout[w[Z]] = q(dt, b[Z]) + B(r, Z) + k(dt, Z);else {
|
||||
var Xt,
|
||||
Yt = ht;
|
||||
if (H(dt) === v) if ((Xt = A(r, dt)) === g) W(dt.layout[S[Z]]) && (dt.layout[S[Z]] = U(z(dt, Z, Vt - gt - _(dt, Z)), R(dt, Z)));else if (Xt !== f) {
|
||||
var Zt = Vt - gt - I(dt, Z);
|
||||
Yt += Xt === h ? Zt / 2 : Zt;
|
||||
}
|
||||
dt.layout[w[Z]] += jt + Yt, mt && J(r, dt, Z);
|
||||
}
|
||||
|
||||
jt += Ft, Bt = U(Bt, Nt), Et += 1, Wt = Lt;
|
||||
}
|
||||
|
||||
if (Et > 1 && mt) {
|
||||
var $t = r.layout[S[Z]] - gt,
|
||||
te = $t - jt,
|
||||
ee = 0,
|
||||
oe = ht,
|
||||
re = function (t) {
|
||||
return t.style.alignContent ? t.style.alignContent : "flex-start";
|
||||
}(r);
|
||||
|
||||
re === p ? oe += te : re === h ? oe += te / 2 : re === g && $t > jt && (ee = te / Et);
|
||||
var ie = 0;
|
||||
|
||||
for (at = 0; at < Et; ++at) {
|
||||
var le = ie,
|
||||
ne = 0;
|
||||
|
||||
for (ut = le; ut < tt; ++ut) if (H(dt = r.children[ut]) === v) {
|
||||
if (dt.lineIndex !== at) break;
|
||||
W(dt.layout[S[Z]]) || (ne = U(ne, dt.layout[S[Z]] + _(dt, Z)));
|
||||
}
|
||||
|
||||
for (ie = ut, ne += ee, ut = le; ut < ie; ++ut) if (H(dt = r.children[ut]) === v) {
|
||||
var ae = A(r, dt);
|
||||
if (ae === f) dt.layout[w[Z]] = oe + k(dt, Z);else if (ae === p) dt.layout[w[Z]] = oe + ne - j(dt, Z) - dt.layout[S[Z]];else if (ae === h) {
|
||||
var ue = dt.layout[S[Z]];
|
||||
dt.layout[w[Z]] = oe + (ne - ue) / 2;
|
||||
} else ae === g && (dt.layout[w[Z]] = oe + k(dt, Z));
|
||||
}
|
||||
|
||||
oe += ne;
|
||||
}
|
||||
}
|
||||
|
||||
var de = !1,
|
||||
se = !1;
|
||||
if (vt || (r.layout[S[Y]] = U(z(r, Y, Bt + T(r, Y)), pt), Y !== l && Y !== a || (de = !0)), mt || (r.layout[S[Z]] = U(z(r, Z, jt + gt), gt), Z !== l && Z !== a || (se = !0)), de || se) for (at = 0; at < tt; ++at) dt = r.children[at], de && J(r, dt, Y), se && J(r, dt, Z);
|
||||
|
||||
for (wt = xt; null !== wt;) {
|
||||
for (ut = 0; ut < 2; ut++) st = 0 !== ut ? i : n, !W(r.layout[S[st]]) && !N(wt, st) && F(wt, b[st]) && F(wt, x[st]) && (wt.layout[S[st]] = U(z(wt, st, r.layout[S[st]] - O(r, st) - _(wt, st) - q(wt, b[st]) - q(wt, x[st])), R(wt, st))), F(wt, x[st]) && !F(wt, b[st]) && (wt.layout[b[st]] = r.layout[S[st]] - wt.layout[S[st]] - q(wt, x[st]));
|
||||
|
||||
dt = wt, wt = wt.nextAbsoluteChild, dt.nextAbsoluteChild = null;
|
||||
}
|
||||
}
|
||||
|
||||
function V(t, e, r) {
|
||||
t.shouldUpdate = !0;
|
||||
var i = t.style.direction || o;
|
||||
!t.isDirty && t.lastLayout && t.lastLayout.requestedHeight === t.layout.height && t.lastLayout.requestedWidth === t.layout.width && t.lastLayout.parentMaxWidth === e && t.lastLayout.direction === i ? (t.layout.width = t.lastLayout.width, t.layout.height = t.lastLayout.height, t.layout.top = t.lastLayout.top, t.layout.left = t.lastLayout.left) : (t.lastLayout || (t.lastLayout = {}), t.lastLayout.requestedWidth = t.layout.width, t.lastLayout.requestedHeight = t.layout.height, t.lastLayout.parentMaxWidth = e, t.lastLayout.direction = i, t.children.forEach(function (t) {
|
||||
t.layout.width = void 0, t.layout.height = void 0, t.layout.top = 0, t.layout.left = 0;
|
||||
}), Q(t, e, r), t.lastLayout.width = t.layout.width, t.lastLayout.height = t.layout.height, t.lastLayout.top = t.layout.top, t.lastLayout.left = t.layout.left);
|
||||
}
|
||||
|
||||
return {
|
||||
layoutNodeImpl: Q,
|
||||
computeLayout: V,
|
||||
fillNodes: function t(e) {
|
||||
return e.layout && !e.isDirty || (e.layout = {
|
||||
width: void 0,
|
||||
height: void 0,
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0
|
||||
}), e.style || (e.style = {}), e.children || (e.children = []), e.children.forEach(t), e;
|
||||
}
|
||||
};
|
||||
}();
|
||||
|
||||
e.default = function (t) {
|
||||
r.fillNodes(t), r.computeLayout(t);
|
||||
};
|
||||
}, function (t, e, o) {
|
||||
Object.defineProperty(e, "__esModule", {
|
||||
value: !0
|
||||
});
|
||||
e.textStyles = ["color", "fontSize", "textAlign", "fontWeight", "lineHeight", "lineBreak"];
|
||||
e.scalableStyles = ["left", "top", "right", "bottom", "width", "height", "margin", "marginLeft", "marginRight", "marginTop", "marginBottom", "padding", "paddingLeft", "paddingRight", "paddingTop", "paddingBottom", "borderWidth", "borderLeftWidth", "borderRightWidth", "borderTopWidth", "borderBottomWidth"];
|
||||
e.layoutAffectedStyles = ["margin", "marginTop", "marginBottom", "marginLeft", "marginRight", "padding", "paddingTop", "paddingBottom", "paddingLeft", "paddingRight", "width", "height"];
|
||||
|
||||
e.getDefaultStyle = function () {
|
||||
return {
|
||||
left: void 0,
|
||||
top: void 0,
|
||||
right: void 0,
|
||||
bottom: void 0,
|
||||
width: void 0,
|
||||
height: void 0,
|
||||
maxWidth: void 0,
|
||||
maxHeight: void 0,
|
||||
minWidth: void 0,
|
||||
minHeight: void 0,
|
||||
margin: void 0,
|
||||
marginLeft: void 0,
|
||||
marginRight: void 0,
|
||||
marginTop: void 0,
|
||||
marginBottom: void 0,
|
||||
padding: void 0,
|
||||
paddingLeft: void 0,
|
||||
paddingRight: void 0,
|
||||
paddingTop: void 0,
|
||||
paddingBottom: void 0,
|
||||
borderWidth: void 0,
|
||||
flexDirection: void 0,
|
||||
justifyContent: void 0,
|
||||
alignItems: void 0,
|
||||
alignSelf: void 0,
|
||||
flex: void 0,
|
||||
flexWrap: void 0,
|
||||
position: void 0,
|
||||
hidden: !1,
|
||||
scale: 1
|
||||
};
|
||||
};
|
||||
}]).default;
|
||||
});
|
||||
}, function (modId) {
|
||||
var map = {};
|
||||
return __REQUIRE__(map[modId], modId);
|
||||
});
|
||||
|
||||
return __REQUIRE__(1572960819414);
|
||||
}(); //# sourceMappingURL=index.js.map
|
||||
File diff suppressed because one or more lines are too long
87
uniapp/uni-app/components/miniprogram_npm/widget-ui/style.ts
Normal file
87
uniapp/uni-app/components/miniprogram_npm/widget-ui/style.ts
Normal file
@@ -0,0 +1,87 @@
|
||||
const textStyles: string[] = ["color", "fontSize", "textAlign", "fontWeight", "lineHeight", "lineBreak"];
|
||||
|
||||
const scalableStyles: string[] = ["left", "top", "right", "bottom", "width", "height",
|
||||
"margin", "marginLeft", "marginRight", "marginTop", "marginBottom",
|
||||
"padding", "paddingLeft", "paddingRight", "paddingTop", "paddingBottom",
|
||||
"borderWidth", "borderLeftWidth", "borderRightWidth", "borderTopWidth", "borderBottomWidth"];
|
||||
|
||||
const layoutAffectedStyles: string[] = [
|
||||
"margin", "marginTop", "marginBottom", "marginLeft", "marginRight",
|
||||
"padding", "paddingTop", "paddingBottom", "paddingLeft", "paddingRight",
|
||||
"width", "height"];
|
||||
|
||||
type Style = {
|
||||
left: number,
|
||||
top: number,
|
||||
right: number,
|
||||
bottom: number,
|
||||
width: number,
|
||||
height: number,
|
||||
maxWidth: number,
|
||||
maxHeight: number,
|
||||
minWidth: number,
|
||||
minHeight: number,
|
||||
margin: number,
|
||||
marginLeft: number,
|
||||
marginRight: number,
|
||||
marginTop: number,
|
||||
marginBottom: number,
|
||||
padding: number,
|
||||
paddingLeft: number,
|
||||
paddingRight: number,
|
||||
paddingTop: number,
|
||||
paddingBottom: number,
|
||||
borderWidth: number,
|
||||
borderLeftWidth: number,
|
||||
borderRightWidth: number,
|
||||
borderTopWidth: number,
|
||||
borderBottomWidth: number,
|
||||
flexDirection: "column" | "row",
|
||||
justifyContent: "flex-start" | "center" | "flex-end" | "space-between" | "space-around",
|
||||
alignItems: "flex-start" | "center" | "flex-end" | "stretch",
|
||||
alignSelf: "flex-start" | "center" | "flex-end" | "stretch",
|
||||
flex: number,
|
||||
flexWrap: "wrap" | "nowrap",
|
||||
position: "relative" | "absolute",
|
||||
|
||||
hidden: boolean,
|
||||
scale: number
|
||||
}
|
||||
|
||||
const getDefaultStyle = () => ({
|
||||
left: undefined,
|
||||
top: undefined,
|
||||
right: undefined,
|
||||
bottom: undefined,
|
||||
width: undefined,
|
||||
height: undefined,
|
||||
maxWidth: undefined,
|
||||
maxHeight: undefined,
|
||||
minWidth: undefined,
|
||||
minHeight: undefined,
|
||||
margin: undefined,
|
||||
marginLeft: undefined,
|
||||
marginRight: undefined,
|
||||
marginTop: undefined,
|
||||
marginBottom: undefined,
|
||||
padding: undefined,
|
||||
paddingLeft: undefined,
|
||||
paddingRight: undefined,
|
||||
paddingTop: undefined,
|
||||
paddingBottom: undefined,
|
||||
borderWidth: undefined,
|
||||
flexDirection: undefined,
|
||||
justifyContent: undefined,
|
||||
alignItems: undefined,
|
||||
alignSelf: undefined,
|
||||
flex: undefined,
|
||||
flexWrap: undefined,
|
||||
position: undefined,
|
||||
|
||||
hidden: false,
|
||||
scale: 1
|
||||
})
|
||||
|
||||
export {
|
||||
getDefaultStyle, scalableStyles, textStyles, layoutAffectedStyles
|
||||
}
|
||||
219
uniapp/uni-app/components/miniprogram_npm/wxml-to-canvas/draw.js
Normal file
219
uniapp/uni-app/components/miniprogram_npm/wxml-to-canvas/draw.js
Normal file
@@ -0,0 +1,219 @@
|
||||
class Draw {
|
||||
constructor(canvas, context) {
|
||||
this.canvas = canvas;
|
||||
this.ctx = context;
|
||||
}
|
||||
|
||||
roundRect(x, y, w, h, r, fill = true, stroke = false) {
|
||||
if (r < 0) return;
|
||||
const ctx = this.ctx;
|
||||
ctx.beginPath();
|
||||
ctx.arc(x + r, y + r, r, Math.PI, Math.PI * 3 / 2);
|
||||
ctx.arc(x + w - r, y + r, r, Math.PI * 3 / 2, 0);
|
||||
ctx.arc(x + w - r, y + h - r, r, 0, Math.PI / 2);
|
||||
ctx.arc(x + r, y + h - r, r, Math.PI / 2, Math.PI);
|
||||
ctx.lineTo(x, y + r);
|
||||
if (stroke) ctx.stroke();
|
||||
if (fill) ctx.fill();
|
||||
}
|
||||
|
||||
drawView(box, style) {
|
||||
const ctx = this.ctx;
|
||||
const {
|
||||
left: x,
|
||||
top: y,
|
||||
width: w,
|
||||
height: h
|
||||
} = box;
|
||||
const {
|
||||
borderRadius = 0,
|
||||
borderWidth = 0,
|
||||
borderColor,
|
||||
color = '#000',
|
||||
backgroundColor = 'transparent'
|
||||
} = style;
|
||||
ctx.save(); // 外环
|
||||
|
||||
if (borderWidth > 0) {
|
||||
ctx.fillStyle = borderColor || color;
|
||||
this.roundRect(x, y, w, h, borderRadius);
|
||||
} // 内环
|
||||
|
||||
|
||||
ctx.fillStyle = backgroundColor;
|
||||
const innerWidth = w - 2 * borderWidth;
|
||||
const innerHeight = h - 2 * borderWidth;
|
||||
const innerRadius = borderRadius - borderWidth >= 0 ? borderRadius - borderWidth : 0;
|
||||
this.roundRect(x + borderWidth, y + borderWidth, innerWidth, innerHeight, innerRadius);
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
async drawImage(img, box, style) {
|
||||
await new Promise((resolve, reject) => {
|
||||
const ctx = this.ctx;
|
||||
const canvas = this.canvas;
|
||||
const {
|
||||
borderRadius = 0
|
||||
} = style;
|
||||
const {
|
||||
left: x,
|
||||
top: y,
|
||||
width: w,
|
||||
height: h
|
||||
} = box;
|
||||
ctx.save();
|
||||
this.roundRect(x, y, w, h, borderRadius, false, false);
|
||||
ctx.clip();
|
||||
const Image = canvas.createImage();
|
||||
|
||||
Image.onload = () => {
|
||||
ctx.drawImage(Image, x, y, w, h);
|
||||
ctx.restore();
|
||||
resolve();
|
||||
};
|
||||
|
||||
Image.onerror = () => {
|
||||
reject();
|
||||
};
|
||||
|
||||
Image.src = img;
|
||||
});
|
||||
} // eslint-disable-next-line complexity
|
||||
|
||||
|
||||
drawText(text, box, style) {
|
||||
const ctx = this.ctx;
|
||||
let {
|
||||
left: x,
|
||||
top: y,
|
||||
width: w,
|
||||
height: h
|
||||
} = box;
|
||||
let {
|
||||
color = '#000',
|
||||
lineHeight = '1.4em',
|
||||
fontSize = 14,
|
||||
textAlign = 'left',
|
||||
verticalAlign = 'top',
|
||||
backgroundColor = 'transparent'
|
||||
} = style;
|
||||
if (!text || lineHeight > h) return;
|
||||
ctx.save();
|
||||
|
||||
if (lineHeight) {
|
||||
// 2em
|
||||
lineHeight = Math.ceil(parseFloat(lineHeight.replace('em')) * fontSize);
|
||||
}
|
||||
|
||||
ctx.textBaseline = 'top';
|
||||
ctx.font = `${fontSize}px sans-serif`;
|
||||
ctx.textAlign = textAlign; // 背景色
|
||||
|
||||
ctx.fillStyle = backgroundColor;
|
||||
this.roundRect(x, y, w, h, 0); // 文字颜色
|
||||
|
||||
ctx.fillStyle = color; // 水平布局
|
||||
|
||||
switch (textAlign) {
|
||||
case 'left':
|
||||
break;
|
||||
|
||||
case 'center':
|
||||
x += 0.5 * w;
|
||||
break;
|
||||
|
||||
case 'right':
|
||||
x += w;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
const textWidth = ctx.measureText(text).width;
|
||||
const actualHeight = Math.ceil(textWidth / w) * lineHeight;
|
||||
let paddingTop = Math.ceil((h - actualHeight) / 2);
|
||||
if (paddingTop < 0) paddingTop = 0; // 垂直布局
|
||||
|
||||
switch (verticalAlign) {
|
||||
case 'top':
|
||||
break;
|
||||
|
||||
case 'middle':
|
||||
y += paddingTop;
|
||||
break;
|
||||
|
||||
case 'bottom':
|
||||
y += 2 * paddingTop;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
const inlinePaddingTop = Math.ceil((lineHeight - fontSize) / 2); // 不超过一行
|
||||
|
||||
if (textWidth <= w) {
|
||||
ctx.fillText(text, x, y + inlinePaddingTop);
|
||||
return;
|
||||
} // 多行文本
|
||||
|
||||
|
||||
const chars = text.split('');
|
||||
const _y = y; // 逐行绘制
|
||||
|
||||
let line = '';
|
||||
|
||||
for (const ch of chars) {
|
||||
const testLine = line + ch;
|
||||
const testWidth = ctx.measureText(testLine).width;
|
||||
|
||||
if (testWidth > w) {
|
||||
ctx.fillText(line, x, y + inlinePaddingTop);
|
||||
y += lineHeight;
|
||||
line = ch;
|
||||
if (y + lineHeight > _y + h) break;
|
||||
} else {
|
||||
line = testLine;
|
||||
}
|
||||
} // 避免溢出
|
||||
|
||||
|
||||
if (y + lineHeight <= _y + h) {
|
||||
ctx.fillText(line, x, y + inlinePaddingTop);
|
||||
}
|
||||
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
async drawNode(element) {
|
||||
const {
|
||||
layoutBox,
|
||||
computedStyle,
|
||||
name
|
||||
} = element;
|
||||
const {
|
||||
src,
|
||||
text
|
||||
} = element.attributes;
|
||||
|
||||
if (name === 'view') {
|
||||
this.drawView(layoutBox, computedStyle);
|
||||
} else if (name === 'image') {
|
||||
await this.drawImage(src, layoutBox, computedStyle);
|
||||
} else if (name === 'text') {
|
||||
this.drawText(text, layoutBox, computedStyle);
|
||||
}
|
||||
|
||||
const childs = Object.values(element.children);
|
||||
|
||||
for (const child of childs) {
|
||||
await this.drawNode(child);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
Draw
|
||||
};
|
||||
@@ -0,0 +1,34 @@
|
||||
const $filterNullChildren = children => {
|
||||
children = deepFlatten(children);
|
||||
return children.filter(child => child != null);
|
||||
};
|
||||
|
||||
const deepFlatten = arr => {
|
||||
let flatten = arr => [].concat(...arr);
|
||||
|
||||
return flatten(arr.map(x => Array.isArray(x) ? deepFlatten(x) : x));
|
||||
};
|
||||
|
||||
export default ((data, opt) => {
|
||||
const {
|
||||
View,
|
||||
Text,
|
||||
Image
|
||||
} = opt;
|
||||
Object.assign(data, {});
|
||||
return new View({
|
||||
style: {},
|
||||
attr: {
|
||||
"needRoot": true
|
||||
},
|
||||
children: $filterNullChildren([new Canvas({
|
||||
style: {},
|
||||
attr: {
|
||||
"id": "canvas",
|
||||
"type": "2d",
|
||||
"style": "width: " + data.width + "px; height: " + data.height + "px;"
|
||||
},
|
||||
children: $filterNullChildren([])
|
||||
})])
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,109 @@
|
||||
<template>
|
||||
<view>
|
||||
<canvas id="canvas" type="2d" :style="'width: ' + width + 'px; height: ' + height + 'px;'"></canvas>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
const xmlParse = require("./xml-parser");
|
||||
const {
|
||||
Widget
|
||||
} = require("./widget");
|
||||
const {
|
||||
Draw
|
||||
} = require("./draw");
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
|
||||
components: {},
|
||||
props: {
|
||||
width: {
|
||||
type: Number,
|
||||
default: 400
|
||||
},
|
||||
height: {
|
||||
type: Number,
|
||||
default: 300
|
||||
}
|
||||
},
|
||||
|
||||
beforeMount() {
|
||||
const dpr = wx.getSystemInfoSync().pixelRatio;
|
||||
const query = this.createSelectorQuery();
|
||||
this.dpr = dpr;
|
||||
query.select('#canvas').fields({
|
||||
node: true,
|
||||
size: true
|
||||
}).exec(res => {
|
||||
console.log(res, "==res");
|
||||
const canvas = res[0].node;
|
||||
const ctx = canvas.getContext('2d');
|
||||
canvas.width = res[0].width * dpr;
|
||||
canvas.height = res[0].height * dpr;
|
||||
ctx.scale(dpr, dpr);
|
||||
this.ctx = ctx;
|
||||
this.canvas = canvas;
|
||||
});
|
||||
},
|
||||
|
||||
methods: {
|
||||
async renderToCanvas(args) {
|
||||
const {
|
||||
wxml,
|
||||
style
|
||||
} = args; // 清空画布
|
||||
|
||||
const ctx = this.ctx;
|
||||
const canvas = this.canvas;
|
||||
|
||||
if (!ctx || !canvas) {
|
||||
return Promise.reject(new Error('renderToCanvas: fail canvas has not been created'));
|
||||
}
|
||||
|
||||
ctx.clearRect(0, 0, this.width, this.height);
|
||||
const {
|
||||
root: xom
|
||||
} = xmlParse(wxml);
|
||||
const widget = new Widget(xom, style);
|
||||
const container = widget.init();
|
||||
this.boundary = {
|
||||
top: container.layoutBox.top,
|
||||
left: container.layoutBox.left,
|
||||
width: container.computedStyle.width,
|
||||
height: container.computedStyle.height
|
||||
};
|
||||
const draw = new Draw(canvas, ctx);
|
||||
await draw.drawNode(container);
|
||||
return Promise.resolve(container);
|
||||
},
|
||||
|
||||
canvasToTempFilePath(args = {}) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const {
|
||||
top,
|
||||
left,
|
||||
width,
|
||||
height
|
||||
} = this.boundary;
|
||||
wx.canvasToTempFilePath({
|
||||
x: left,
|
||||
y: top,
|
||||
width,
|
||||
height,
|
||||
destWidth: width * this.dpr,
|
||||
destHeight: height * this.dpr,
|
||||
canvas: this.canvas,
|
||||
fileType: args.fileType || 'png',
|
||||
quality: args.quality || 1,
|
||||
success: resolve,
|
||||
fail: reject
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -0,0 +1,34 @@
|
||||
const hex = color => {
|
||||
let result = null;
|
||||
|
||||
if (/^#/.test(color) && (color.length === 7 || color.length === 9)) {
|
||||
return color; // eslint-disable-next-line no-cond-assign
|
||||
} else if ((result = /^(rgb|rgba)\((.+)\)/.exec(color)) !== null) {
|
||||
return '#' + result[2].split(',').map((part, index) => {
|
||||
part = part.trim();
|
||||
part = index === 3 ? Math.floor(parseFloat(part) * 255) : parseInt(part, 10);
|
||||
part = part.toString(16);
|
||||
|
||||
if (part.length === 1) {
|
||||
part = '0' + part;
|
||||
}
|
||||
|
||||
return part;
|
||||
}).join('');
|
||||
} else {
|
||||
return '#00000000';
|
||||
}
|
||||
};
|
||||
|
||||
const splitLineToCamelCase = str => str.split('-').map((part, index) => {
|
||||
if (index === 0) {
|
||||
return part;
|
||||
}
|
||||
|
||||
return part[0].toUpperCase() + part.slice(1);
|
||||
}).join('');
|
||||
|
||||
module.exports = {
|
||||
hex,
|
||||
splitLineToCamelCase
|
||||
};
|
||||
@@ -0,0 +1,88 @@
|
||||
const Block = require("@/components/miniprogram_npm/widget-ui/index.js");
|
||||
|
||||
const {
|
||||
splitLineToCamelCase
|
||||
} = require("./utils.js");
|
||||
|
||||
class Element extends Block {
|
||||
constructor(prop) {
|
||||
super(prop.style);
|
||||
this.name = prop.name;
|
||||
this.attributes = prop.attributes;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Widget {
|
||||
constructor(xom, style) {
|
||||
this.xom = xom;
|
||||
this.style = style;
|
||||
this.inheritProps = ['fontSize', 'lineHeight', 'textAlign', 'verticalAlign', 'color'];
|
||||
}
|
||||
|
||||
init() {
|
||||
this.container = this.create(this.xom);
|
||||
this.container.layout();
|
||||
this.inheritStyle(this.container);
|
||||
return this.container;
|
||||
} // 继承父节点的样式
|
||||
|
||||
|
||||
inheritStyle(node) {
|
||||
const parent = node.parent || null;
|
||||
const children = node.children || {};
|
||||
const computedStyle = node.computedStyle;
|
||||
|
||||
if (parent) {
|
||||
this.inheritProps.forEach(prop => {
|
||||
computedStyle[prop] = computedStyle[prop] || parent.computedStyle[prop];
|
||||
});
|
||||
}
|
||||
|
||||
Object.values(children).forEach(child => {
|
||||
this.inheritStyle(child);
|
||||
});
|
||||
}
|
||||
|
||||
create(node) {
|
||||
let classNames = (node.attributes.class || '').split(' ');
|
||||
classNames = classNames.map(item => splitLineToCamelCase(item.trim()));
|
||||
const style = {};
|
||||
classNames.forEach(item => {
|
||||
Object.assign(style, this.style[item] || {});
|
||||
});
|
||||
const args = {
|
||||
name: node.name,
|
||||
style
|
||||
};
|
||||
const attrs = Object.keys(node.attributes);
|
||||
const attributes = {};
|
||||
|
||||
for (const attr of attrs) {
|
||||
const value = node.attributes[attr];
|
||||
const CamelAttr = splitLineToCamelCase(attr);
|
||||
|
||||
if (value === '' || value === 'true') {
|
||||
attributes[CamelAttr] = true;
|
||||
} else if (value === 'false') {
|
||||
attributes[CamelAttr] = false;
|
||||
} else {
|
||||
attributes[CamelAttr] = value;
|
||||
}
|
||||
}
|
||||
|
||||
attributes.text = node.content;
|
||||
args.attributes = attributes;
|
||||
const element = new Element(args);
|
||||
node.children.forEach(childNode => {
|
||||
const childElement = this.create(childNode);
|
||||
element.add(childElement);
|
||||
});
|
||||
return element;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
Widget
|
||||
};
|
||||
@@ -0,0 +1,153 @@
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Expose `parse`.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Parse the given string of `xml`.
|
||||
*
|
||||
* @param {String} xml
|
||||
* @return {Object}
|
||||
* @api public
|
||||
*/
|
||||
function parse(xml) {
|
||||
xml = xml.trim(); // strip comments
|
||||
|
||||
xml = xml.replace(/<!--[\s\S]*?-->/g, '');
|
||||
return document();
|
||||
/**
|
||||
* XML document.
|
||||
*/
|
||||
|
||||
function document() {
|
||||
return {
|
||||
declaration: declaration(),
|
||||
root: tag()
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Declaration.
|
||||
*/
|
||||
|
||||
|
||||
function declaration() {
|
||||
const m = match(/^<\?xml\s*/);
|
||||
if (!m) return; // tag
|
||||
|
||||
const node = {
|
||||
attributes: {}
|
||||
}; // attributes
|
||||
|
||||
while (!(eos() || is('?>'))) {
|
||||
const attr = attribute();
|
||||
if (!attr) return node;
|
||||
node.attributes[attr.name] = attr.value;
|
||||
}
|
||||
|
||||
match(/\?>\s*/);
|
||||
return node;
|
||||
}
|
||||
/**
|
||||
* Tag.
|
||||
*/
|
||||
|
||||
|
||||
function tag() {
|
||||
const m = match(/^<([\w-:.]+)\s*/);
|
||||
if (!m) return; // name
|
||||
|
||||
const node = {
|
||||
name: m[1],
|
||||
attributes: {},
|
||||
children: []
|
||||
}; // attributes
|
||||
|
||||
while (!(eos() || is('>') || is('?>') || is('/>'))) {
|
||||
const attr = attribute();
|
||||
if (!attr) return node;
|
||||
node.attributes[attr.name] = attr.value;
|
||||
} // self closing tag
|
||||
|
||||
|
||||
if (match(/^\s*\/>\s*/)) {
|
||||
return node;
|
||||
}
|
||||
|
||||
match(/\??>\s*/); // content
|
||||
|
||||
node.content = content(); // children
|
||||
|
||||
let child;
|
||||
|
||||
while (child = tag()) {
|
||||
node.children.push(child);
|
||||
} // closing
|
||||
|
||||
|
||||
match(/^<\/[\w-:.]+>\s*/);
|
||||
return node;
|
||||
}
|
||||
/**
|
||||
* Text content.
|
||||
*/
|
||||
|
||||
|
||||
function content() {
|
||||
const m = match(/^([^<]*)/);
|
||||
if (m) return m[1];
|
||||
return '';
|
||||
}
|
||||
/**
|
||||
* Attribute.
|
||||
*/
|
||||
|
||||
|
||||
function attribute() {
|
||||
const m = match(/([\w:-]+)\s*=\s*("[^"]*"|'[^']*'|\w+)\s*/);
|
||||
if (!m) return;
|
||||
return {
|
||||
name: m[1],
|
||||
value: strip(m[2])
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Strip quotes from `val`.
|
||||
*/
|
||||
|
||||
|
||||
function strip(val) {
|
||||
return val.replace(/^['"]|['"]$/g, '');
|
||||
}
|
||||
/**
|
||||
* Match `re` and advance the string.
|
||||
*/
|
||||
|
||||
|
||||
function match(re) {
|
||||
const m = xml.match(re);
|
||||
if (!m) return;
|
||||
xml = xml.slice(m[0].length);
|
||||
return m;
|
||||
}
|
||||
/**
|
||||
* End-of-source.
|
||||
*/
|
||||
|
||||
|
||||
function eos() {
|
||||
return xml.length == 0;
|
||||
}
|
||||
/**
|
||||
* Check for `prefix`.
|
||||
*/
|
||||
|
||||
|
||||
function is(prefix) {
|
||||
return xml.indexOf(prefix) == 0;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = parse;
|
||||
194
uniapp/uni-app/components/search.vue
Normal file
194
uniapp/uni-app/components/search.vue
Normal file
@@ -0,0 +1,194 @@
|
||||
<template>
|
||||
<view class='search-box'
|
||||
:style='{padding:`${padding}rpx`,margin:`${margin}rpx`,borderRadius:`${radius}rpx`,background:backgroundColor}'>
|
||||
<view class='search-item' :class="[{'flex-y-center': type == 'text'},{'flex-between': type == 'input'}]"
|
||||
:style='{borderRadius:`${radius}rpx`,background:searchColor,color:frontColor}'>
|
||||
<block v-if="type=='text'">
|
||||
<i class="iconfont icon-search"></i>
|
||||
<view class='ml-md f-paragraph'>{{placeholder}}</view>
|
||||
</block>
|
||||
<block v-if="type=='input'">
|
||||
<view class="flex-y-center flex-1">
|
||||
<i class="iconfont icon-search"></i>
|
||||
<input type='text' class="flex-1 f-paragraph ml-md mr-md" :disabled="disabled"
|
||||
:placeholder='placeholder'
|
||||
:placeholder-class='frontColor === "#fff" ? "c-base" : "c-placeholder"' confirm-type="search"
|
||||
@input="handerInput" :value="keyword" @confirm="confirm" :auto-focus="autofocus"></input>
|
||||
</view>
|
||||
<view class=' search-item-btn flex-center radius' :style="{background:primaryColor}" @tap='confirm'
|
||||
v-if="showbtn">搜索
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
mapState,
|
||||
} from "vuex"
|
||||
export default {
|
||||
name: 'search',
|
||||
props: {
|
||||
type: {
|
||||
type: String,
|
||||
default () {
|
||||
return 'text'
|
||||
}
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default () {
|
||||
return "请输入关键字进行搜索"
|
||||
}
|
||||
},
|
||||
searchStyle: {
|
||||
type: String,
|
||||
default () {
|
||||
return 'circle'
|
||||
}
|
||||
},
|
||||
textAlign: {
|
||||
type: String,
|
||||
default () {
|
||||
return 'center'
|
||||
}
|
||||
},
|
||||
padding: {
|
||||
type: Number,
|
||||
default () {
|
||||
return 30
|
||||
}
|
||||
},
|
||||
margin: {
|
||||
type: Number,
|
||||
default () {
|
||||
return 0
|
||||
}
|
||||
},
|
||||
radius: {
|
||||
type: Number,
|
||||
default () {
|
||||
return 0
|
||||
}
|
||||
},
|
||||
backgroundColor: {
|
||||
type: String,
|
||||
default () {
|
||||
return '#fff'
|
||||
}
|
||||
},
|
||||
searchColor: {
|
||||
type: String,
|
||||
default () {
|
||||
return '#F6F5FA'
|
||||
}
|
||||
},
|
||||
frontColor: {
|
||||
type: String,
|
||||
default () {
|
||||
return '#888'
|
||||
}
|
||||
},
|
||||
autofocus: {
|
||||
type: Boolean,
|
||||
default () {
|
||||
return false
|
||||
}
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default () {
|
||||
return false
|
||||
}
|
||||
},
|
||||
showbtn: {
|
||||
type: Boolean,
|
||||
default () {
|
||||
return false
|
||||
}
|
||||
},
|
||||
focus: {
|
||||
type: Boolean,
|
||||
default () {
|
||||
return false
|
||||
}
|
||||
},
|
||||
keyword: {
|
||||
type: String,
|
||||
default () {
|
||||
return ''
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
text: '',
|
||||
searchImg: 'https://lbqny.migugu.com/admin/public/search.png'
|
||||
}
|
||||
},
|
||||
computed: mapState({
|
||||
primaryColor: state => state.config.configInfo.primaryColor,
|
||||
subColor: state => state.config.configInfo.subColor,
|
||||
}),
|
||||
methods: {
|
||||
confirm(e) {
|
||||
let val = this.text;
|
||||
this.$emit("confirm", val)
|
||||
},
|
||||
handerInput(e) {
|
||||
let val = e.detail.value;
|
||||
this.text = val;
|
||||
this.$emit("input", val)
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
<style>
|
||||
.search-box {
|
||||
padding: 16rpx 16rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: #efeff5;
|
||||
}
|
||||
|
||||
.search-item {
|
||||
width: 100%;
|
||||
height: 70rpx;
|
||||
background: #ffffff;
|
||||
border-radius: 30rpx;
|
||||
padding: 0 0 0 25rpx;
|
||||
line-height: 1;
|
||||
font-size: 26rpx;
|
||||
}
|
||||
|
||||
.search-item-btn {
|
||||
width: 110rpx;
|
||||
height: 70rpx;
|
||||
font-size: 26rpx;
|
||||
font-weight: 400;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
.search-btn {
|
||||
padding: 0 20rpx 0 40rpx;
|
||||
}
|
||||
|
||||
.flex-1 {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.icon-md {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
}
|
||||
|
||||
.ml-md {
|
||||
margin-left: 16rpx;
|
||||
}
|
||||
</style>
|
||||
132
uniapp/uni-app/components/tab.vue
Normal file
132
uniapp/uni-app/components/tab.vue
Normal file
@@ -0,0 +1,132 @@
|
||||
<template>
|
||||
<view>
|
||||
<scroll-view scroll-x class='tab-list' :scroll-into-view="'tab'+(activeIndex-1)" :scroll-with-animation="true"
|
||||
:style="{background: bgColor}">
|
||||
<view class='tab-item text-bold rel' v-for="(item,index) in list" :key="index"
|
||||
@tap='handerTabChange(index)' :id="'tab'+index"
|
||||
:style="{width:width,height:height,lineHeight:height,color:index==activeIndex? activeColor : color,fontSize:fontSize}">
|
||||
{{item.title || item}}
|
||||
<view class="abs line" :style="{background: activeColor}" v-if="index==activeIndex && haveLine"></view>
|
||||
<view v-if="item.number" class="item-msg c-base f-icontext abs"
|
||||
:style="{width: item.number<10 ? '30rpx' : '50rpx',right: msgRight }">
|
||||
{{item.number < 100 ? item.number : '99+'}}
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'tab',
|
||||
props: {
|
||||
list: {
|
||||
type: Array,
|
||||
default () {
|
||||
return []
|
||||
}
|
||||
},
|
||||
activeIndex: {
|
||||
type: Number || String,
|
||||
default () {
|
||||
return 0
|
||||
}
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
default () {
|
||||
return '#333'
|
||||
}
|
||||
},
|
||||
activeColor: {
|
||||
type: String,
|
||||
default () {
|
||||
return '#e73535'
|
||||
}
|
||||
},
|
||||
bgColor: {
|
||||
type: String,
|
||||
default () {
|
||||
return '#fff'
|
||||
}
|
||||
},
|
||||
width: {
|
||||
type: String,
|
||||
default () {
|
||||
return ''
|
||||
}
|
||||
},
|
||||
height: {
|
||||
type: String,
|
||||
default () {
|
||||
return ''
|
||||
}
|
||||
},
|
||||
haveLine: {
|
||||
type: Boolean,
|
||||
default () {
|
||||
return true
|
||||
}
|
||||
},
|
||||
msgRight: {
|
||||
type: String,
|
||||
default () {
|
||||
return '5rpx'
|
||||
}
|
||||
},
|
||||
fontSize: {
|
||||
type: String,
|
||||
default () {
|
||||
return '28rpx'
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handerTabChange(index) {
|
||||
this.$emit('change', index);
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.tab-list {
|
||||
white-space: nowrap;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.tab-item {
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
line-height: 100rpx;
|
||||
padding: 0 20rpx;
|
||||
border-color: #fff;
|
||||
box-sizing: border-box;
|
||||
|
||||
.line {
|
||||
width: 80rpx;
|
||||
height: 6rpx;
|
||||
border-radius: 6rpx;
|
||||
left: 50%;
|
||||
bottom: 0rpx;
|
||||
margin-left: -40rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.item-msg {
|
||||
width: 30rpx;
|
||||
height: 30rpx;
|
||||
line-height: 30rpx;
|
||||
border-radius: 15rpx 15rpx 15rpx 0;
|
||||
background: #f12c20;
|
||||
top: 5rpx;
|
||||
}
|
||||
</style>
|
||||
87
uniapp/uni-app/components/tabbar.vue
Normal file
87
uniapp/uni-app/components/tabbar.vue
Normal file
@@ -0,0 +1,87 @@
|
||||
<template>
|
||||
<view class="custom-tabbar fix flex-center" :class="[{'fill-base b-1px-t':configInfo.tabBar[1].name}]">
|
||||
<block v-if="configInfo.tabBar[1].name">
|
||||
<view @tap.stop="changeTab(index)" class="flex-center flex-column mt-sm"
|
||||
:style="{width: 100/configInfo.tabBar.length + '%'}" v-for="(item,index) in configInfo.tabBar"
|
||||
:key="index">
|
||||
<image mode="aspectFill" lazy-load class="cover"
|
||||
:src="cur == index ? item.selected_img : item.default_img"></image>
|
||||
<view class="text" :style="{color:cur == index ? primaryColor : '#666'}">{{item.name}}</view>
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
mapState,
|
||||
mapMutations
|
||||
} from "vuex"
|
||||
export default {
|
||||
components: {},
|
||||
props: {
|
||||
cur: {
|
||||
type: String,
|
||||
default () {
|
||||
return '0'
|
||||
}
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {}
|
||||
},
|
||||
computed: mapState({
|
||||
primaryColor: state => state.config.configInfo.primaryColor,
|
||||
subColor: state => state.config.configInfo.subColor,
|
||||
configInfo: state => state.config.configInfo,
|
||||
commonOptions: state => state.user.commonOptions,
|
||||
}),
|
||||
created() {
|
||||
let that = this;
|
||||
let sysheight = uni.getSystemInfoSync().windowHeight
|
||||
let configInfo = JSON.parse(JSON.stringify(this.configInfo))
|
||||
let {
|
||||
navBarHeight
|
||||
} = configInfo
|
||||
const query = uni.createSelectorQuery().in(this);
|
||||
query.select('.custom-tabbar').boundingClientRect(data => {
|
||||
let curSysHeight = sysheight - data.height - navBarHeight
|
||||
configInfo.curSysHeight = curSysHeight
|
||||
configInfo.tabbarHeight = data.height
|
||||
this.updateConfigItem({
|
||||
key: 'configInfo',
|
||||
val: configInfo
|
||||
})
|
||||
}).exec();
|
||||
},
|
||||
methods: {
|
||||
...mapMutations(['updateConfigItem']),
|
||||
// 点击跳转
|
||||
changeTab(index) {
|
||||
this.$emit('change',
|
||||
index
|
||||
);
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.custom-tabbar {
|
||||
height: 98rpx;
|
||||
bottom: 0;
|
||||
height: calc(98rpx + env(safe-area-inset-bottom) / 2);
|
||||
padding-bottom: calc(env(safe-area-inset-bottom) / 2);
|
||||
|
||||
.cover {
|
||||
width: 44rpx;
|
||||
height: 44rpx;
|
||||
}
|
||||
|
||||
.text {
|
||||
font-size: 22rpx;
|
||||
margin-top: 5rpx;
|
||||
height: 32rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
134
uniapp/uni-app/components/timeline.vue
Normal file
134
uniapp/uni-app/components/timeline.vue
Normal file
@@ -0,0 +1,134 @@
|
||||
<template>
|
||||
<view>
|
||||
<view class='record-box fill-base radius-24'>
|
||||
<view class='record-item' :class="[{'b-1px-l': index != list.length -1}]" v-for="(item,index) in list"
|
||||
:key="index">
|
||||
<view class='c-caption rel'>
|
||||
<text class="item-tag abs" :class="[{'cur':info.pay_type > item.pay_type -1}]"
|
||||
:style="{border:`5rpx solid ${primaryColor}`,background: info.pay_type > item.pay_type -1 ? activeColor : ''}"></text>
|
||||
<view class="item-text f-paragraph c-title flex-y-baseline">
|
||||
{{item[type]}}
|
||||
</view>
|
||||
</view>
|
||||
<view class="f-caption c-caption">{{item.time_text}}</view>
|
||||
<image @tap.stop="toPreviewImage(index)" mode="aspectFill" class="item-img mt-sm radius-10"
|
||||
:src="item.cover">
|
||||
</image>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'timeline',
|
||||
props: {
|
||||
list: {
|
||||
type: Object,
|
||||
default () {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
info: {
|
||||
type: Object,
|
||||
default () {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default () {
|
||||
return ''
|
||||
}
|
||||
},
|
||||
activeColor: {
|
||||
type: String,
|
||||
default () {
|
||||
return '#39b54a'
|
||||
}
|
||||
},
|
||||
primaryColor: {
|
||||
type: String,
|
||||
default () {
|
||||
return '#39b54a'
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
toPreviewImage(index) {
|
||||
let {
|
||||
cover: current
|
||||
} = this.list[index]
|
||||
let urls = this.list.map(item => {
|
||||
return item.cover
|
||||
})
|
||||
this.$util.previewImage({
|
||||
current,
|
||||
urls
|
||||
})
|
||||
},
|
||||
async toMap(key) {
|
||||
let {
|
||||
info
|
||||
} = this
|
||||
await this.$util.checkAuth({
|
||||
type: 'userLocation'
|
||||
})
|
||||
await uni.getLocation({
|
||||
type: 'gcj02',
|
||||
})
|
||||
await uni.openLocation({
|
||||
latitude: info[`${key}_lat`] * 1,
|
||||
longitude: info[`${key}_lng`] * 1,
|
||||
name: info[`${key}_address`],
|
||||
scale: 28
|
||||
})
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.record-item {
|
||||
padding: 0rpx 0rpx 30rpx 40rpx;
|
||||
margin-left: 13rpx;
|
||||
|
||||
.item-tag {
|
||||
width: 19rpx;
|
||||
height: 19rpx;
|
||||
background: #EEF5F2;
|
||||
border: 5rpx solid #39b54a;
|
||||
transform: rotateZ(360deg);
|
||||
border-radius: 50%;
|
||||
top: 0rpx;
|
||||
left: -52rpx;
|
||||
}
|
||||
|
||||
.item-text {
|
||||
line-height: 34rpx;
|
||||
}
|
||||
|
||||
.item-img {
|
||||
width: 158rpx;
|
||||
height: 120rpx;
|
||||
background: #f4f6f8;
|
||||
}
|
||||
}
|
||||
|
||||
.record-item.b-1px-l::before {
|
||||
border: 1rpx solid #DBDBDB;
|
||||
transform: rotateZ(360deg);
|
||||
}
|
||||
|
||||
.record-item:nth-child(5) {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
</style>
|
||||
256
uniapp/uni-app/components/uni-nav-bar.vue
Normal file
256
uniapp/uni-app/components/uni-nav-bar.vue
Normal file
@@ -0,0 +1,256 @@
|
||||
<template>
|
||||
<view class="uni-navbar" :class="{'uni-navbar-fixed':isFixed,'uni-navbar-shadow':hasShadow}"
|
||||
:style="{backgroundColor:backgroundColor,height:navBarHeight+'px'}">
|
||||
<uni-status-bar v-if="insertStatusBar"></uni-status-bar>
|
||||
<view class="uni-navbar-header" :style="{color:color}">
|
||||
<view class="uni-navbar-header-btns left" @tap="onClickLeft">
|
||||
<slot name="left"></slot>
|
||||
<view v-if="leftIcon || leftText" class="uni-navbar-btn-text"><i class="iconfont" :class="leftIcon"
|
||||
v-if="leftIcon"></i>{{leftText || ''}}</view>
|
||||
</view>
|
||||
<block v-if="!onlyLeft">
|
||||
<view class="uni-navbar-container" :class="[{'flex-center':title},{'flex-y-center':image}]">
|
||||
<view v-if="title" class="uni-navbar-container-title ellipsis">{{title}}</view>
|
||||
<image mode="aspectFill" lazy-load class="seckill-nav" :src="image" v-if="image">
|
||||
</image>
|
||||
<!-- 标题插槽 -->
|
||||
<slot></slot>
|
||||
</view>
|
||||
<view class="uni-navbar-header-btns right" @tap="onClickRight">
|
||||
<view v-if="rightText" class="uni-navbar-btn-text">{{rightText}}</view>
|
||||
<slot name="right"></slot>
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import uniStatusBar from '@/components/uni-status-bar.vue';
|
||||
export default {
|
||||
components: {
|
||||
uniStatusBar
|
||||
},
|
||||
props: {
|
||||
/**
|
||||
* 标题文字
|
||||
*/
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
/**
|
||||
* 标题图片
|
||||
*/
|
||||
image: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
/**
|
||||
* 左侧按钮图标
|
||||
*/
|
||||
leftIcon: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
/**
|
||||
* 左侧按钮文本
|
||||
*/
|
||||
leftText: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
/**
|
||||
* 右侧按钮文本
|
||||
*/
|
||||
rightText: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
/**
|
||||
* 是否固定在顶部
|
||||
*/
|
||||
fixed: {
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
},
|
||||
/**
|
||||
* 按钮图标和文字颜色
|
||||
*/
|
||||
color: {
|
||||
type: String,
|
||||
default: '#000'
|
||||
},
|
||||
/**
|
||||
* 背景颜色
|
||||
*/
|
||||
backgroundColor: {
|
||||
type: String,
|
||||
default: '#FFF'
|
||||
},
|
||||
/**
|
||||
* 是否仅有左侧
|
||||
*/
|
||||
onlyLeft: {
|
||||
type: [Boolean],
|
||||
default: false
|
||||
},
|
||||
/**
|
||||
* 是否包含状态栏,默认固定在顶部时包含
|
||||
*/
|
||||
statusBar: {
|
||||
type: [Boolean, String],
|
||||
default: ''
|
||||
},
|
||||
/**
|
||||
* 是否使用阴影,默认根据背景色判断
|
||||
*/
|
||||
shadow: {
|
||||
type: Boolean,
|
||||
default () {
|
||||
return false
|
||||
}
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
isFixed() {
|
||||
return String(this.fixed) === 'true'
|
||||
},
|
||||
insertStatusBar() {
|
||||
switch (String(this.statusBar)) {
|
||||
case 'true':
|
||||
return true
|
||||
case 'false':
|
||||
return false
|
||||
default:
|
||||
return this.isFixed
|
||||
}
|
||||
},
|
||||
hasShadow() {
|
||||
var backgroundColor = this.backgroundColor
|
||||
switch (this.shadow) {
|
||||
case true:
|
||||
return true
|
||||
case false:
|
||||
return false
|
||||
default:
|
||||
return backgroundColor !== 'transparent' && backgroundColor.indexOf('rgba') < 0
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
navBarHeight: uni.getSystemInfoSync().statusBarHeight * 1 + 44
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* 左侧按钮点击事件
|
||||
*/
|
||||
onClickLeft() {
|
||||
let {
|
||||
leftIcon = ''
|
||||
} = this
|
||||
if (leftIcon == 'icon-left') {
|
||||
this.$util.goUrl({
|
||||
url: 1,
|
||||
openType: `navigateBack`
|
||||
})
|
||||
} else if (leftIcon == 'iconshouye') {
|
||||
this.$util.goUrl({
|
||||
url: `/pages/home`,
|
||||
openType: 'reLaunch'
|
||||
})
|
||||
} else {
|
||||
this.$emit('clickLeft')
|
||||
this.$emit('click-left')
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 右侧按钮点击事件
|
||||
*/
|
||||
onClickRight() {
|
||||
this.$emit('clickRight')
|
||||
this.$emit('click-right')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.uni-navbar {
|
||||
display: block;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.uni-navbar-shadow {
|
||||
box-shadow: 0 1px 6px #ccc;
|
||||
}
|
||||
|
||||
.uni-navbar.uni-navbar-fixed {
|
||||
position: fixed;
|
||||
z-index: 999999999;
|
||||
}
|
||||
|
||||
.uni-navbar-header {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
width: 100%;
|
||||
/* #ifdef MP-BAIDU */
|
||||
height: 38px;
|
||||
line-height: 38px;
|
||||
font-size: 15px;
|
||||
/* #endif */
|
||||
/* #ifndef MP-BAIDU */
|
||||
height: 44px;
|
||||
line-height: 44px;
|
||||
font-size: 14px;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.uni-navbar-header-btns {
|
||||
display: inline-flex;
|
||||
flex-wrap: nowrap;
|
||||
flex-shrink: 0;
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
.uni-navbar-header-btns.left {
|
||||
padding-left: 30rpx;
|
||||
}
|
||||
|
||||
.uni-navbar-header-btns.right {
|
||||
padding-right: 30rpx;
|
||||
}
|
||||
|
||||
.uni-navbar-btn-text {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.uni-navbar-btn-text.iconfont {
|
||||
font-size: 40rpx;
|
||||
}
|
||||
|
||||
.uni-navbar-container {
|
||||
width: 100%;
|
||||
margin: 0 5px;
|
||||
}
|
||||
|
||||
.uni-navbar-container-title {
|
||||
/* #ifdef MP-BAIDU */
|
||||
height: 38px;
|
||||
line-height: 38px;
|
||||
/* #endif */
|
||||
/* #ifndef MP-BAIDU */
|
||||
height: 44px;
|
||||
line-height: 44px;
|
||||
/* #endif */
|
||||
font-size: 15px;
|
||||
max-width: 330rpx;
|
||||
/* text-align: center; */
|
||||
/* padding-right: 30px; */
|
||||
}
|
||||
</style>
|
||||
196
uniapp/uni-app/components/uni-popup.vue
Normal file
196
uniapp/uni-app/components/uni-popup.vue
Normal file
@@ -0,0 +1,196 @@
|
||||
<template>
|
||||
<view v-if="showPopup" class="uni-popup">
|
||||
<view :class="[ani, animation ? 'ani' : '', !custom ? 'uni-custom' : '']" class="uni-popup__mask"
|
||||
@click="close(true)" />
|
||||
<view :class="[type, ani, animation ? 'ani' : '', !custom ? 'uni-custom' : '']" class="uni-popup__wrapper"
|
||||
@click="close(true)">
|
||||
<view class="uni-popup__wrapper-box" @click.stop="clear">
|
||||
<slot />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'UniPopup',
|
||||
props: {
|
||||
// 开启动画
|
||||
animation: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// 弹出层类型,可选值,top: 顶部弹出层;bottom:底部弹出层;center:全屏弹出层
|
||||
type: {
|
||||
type: String,
|
||||
default: 'center'
|
||||
},
|
||||
// 是否开启自定义
|
||||
custom: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
maskClick: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
show: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
ani: '',
|
||||
showPopup: false
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
show(newValue) {
|
||||
if (newValue) {
|
||||
this.open()
|
||||
} else {
|
||||
this.close()
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {},
|
||||
methods: {
|
||||
clear() {},
|
||||
open() {
|
||||
this.$emit('change', {
|
||||
show: true
|
||||
})
|
||||
this.showPopup = true
|
||||
this.$nextTick(() => {
|
||||
setTimeout(() => {
|
||||
this.ani = 'uni-' + this.type
|
||||
}, 30)
|
||||
})
|
||||
},
|
||||
close(type) {
|
||||
if (!this.maskClick && type) return
|
||||
this.$emit('change', {
|
||||
show: false
|
||||
})
|
||||
this.ani = ''
|
||||
this.$nextTick(() => {
|
||||
setTimeout(() => {
|
||||
this.showPopup = false
|
||||
}, 300)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
@charset "UTF-8";
|
||||
|
||||
.uni-popup {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 998;
|
||||
overflow: hidden
|
||||
}
|
||||
|
||||
.uni-popup__mask {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 998;
|
||||
background: rgba(0, 0, 0, .4);
|
||||
opacity: 0
|
||||
}
|
||||
|
||||
.uni-popup__mask.ani {
|
||||
transition: all .3s
|
||||
}
|
||||
|
||||
.uni-popup__mask.uni-bottom,
|
||||
.uni-popup__mask.uni-center,
|
||||
.uni-popup__mask.uni-top {
|
||||
opacity: 1
|
||||
}
|
||||
|
||||
.uni-popup__wrapper {
|
||||
position: absolute;
|
||||
z-index: 999;
|
||||
box-sizing: border-box
|
||||
}
|
||||
|
||||
.uni-popup__wrapper.ani {
|
||||
transition: all .3s
|
||||
}
|
||||
|
||||
.uni-popup__wrapper.top {
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
transform: translateY(-100%)
|
||||
}
|
||||
|
||||
.uni-popup__wrapper.bottom {
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
transform: translateY(100%)
|
||||
}
|
||||
|
||||
.uni-popup__wrapper.center {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
transform: scale(1.2);
|
||||
opacity: 0
|
||||
}
|
||||
|
||||
.uni-popup__wrapper-box {
|
||||
position: relative;
|
||||
box-sizing: border-box
|
||||
}
|
||||
|
||||
.uni-popup__wrapper.uni-custom .uni-popup__wrapper-box {
|
||||
/* padding: 30upx; */
|
||||
// background: #fff
|
||||
}
|
||||
|
||||
.uni-popup__wrapper.uni-custom.center .uni-popup__wrapper-box {
|
||||
position: relative;
|
||||
/* max-width: 80%;
|
||||
max-height: 80%; */
|
||||
overflow-y: scroll;
|
||||
border-radius: 25rpx;
|
||||
}
|
||||
|
||||
.uni-popup__wrapper.uni-custom.bottom .uni-popup__wrapper-box {
|
||||
width: 100%;
|
||||
// max-height: 500px;
|
||||
overflow-y: scroll;
|
||||
border-radius: 25rpx 25rpx 0 0;
|
||||
}
|
||||
|
||||
.uni-popup__wrapper.uni-custom.top .uni-popup__wrapper-box {
|
||||
width: 100%;
|
||||
// max-height: 500px;
|
||||
overflow-y: scroll;
|
||||
border-radius: 0 0 25rpx 25rpx;
|
||||
}
|
||||
|
||||
.uni-popup__wrapper.uni-bottom,
|
||||
.uni-popup__wrapper.uni-top {
|
||||
transform: translateY(0)
|
||||
}
|
||||
|
||||
.uni-popup__wrapper.uni-center {
|
||||
transform: scale(1);
|
||||
opacity: 1
|
||||
}
|
||||
</style>
|
||||
160
uniapp/uni-app/components/uni-segmented-control.vue
Normal file
160
uniapp/uni-app/components/uni-segmented-control.vue
Normal file
@@ -0,0 +1,160 @@
|
||||
<template>
|
||||
<view class="segmented-control" :class="styleType" :style="wrapStyle">
|
||||
<view v-for="(item, index) in values" class="segmented-control-item" :class="styleType" :key="index"
|
||||
:style="index === currentIndex ? activeStyle : itemStyle" @click="onClick(index)">
|
||||
{{item.title}}
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'uni-segmented-control',
|
||||
props: {
|
||||
current: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
values: {
|
||||
type: Array,
|
||||
default () {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
activeColor: {
|
||||
type: String,
|
||||
default: '#007aff'
|
||||
},
|
||||
styleType: {
|
||||
type: String,
|
||||
default: 'button'
|
||||
},
|
||||
haveBorder: {
|
||||
type: Boolean,
|
||||
default () {
|
||||
return false
|
||||
}
|
||||
},
|
||||
lockTap: {
|
||||
type: Boolean,
|
||||
default () {
|
||||
return true
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
currentIndex: this.current
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
current(val) {
|
||||
if (val !== this.currentIndex) {
|
||||
this.currentIndex = val;
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
wrapStyle() {
|
||||
let styleString = '';
|
||||
switch (this.styleType) {
|
||||
case 'text':
|
||||
styleString = `border:0;`;
|
||||
break;
|
||||
default:
|
||||
styleString = this.haveBorder ? `border: 1rpx solid ${this.activeColor};` : ``;
|
||||
break;
|
||||
}
|
||||
return styleString;
|
||||
},
|
||||
itemStyle() {
|
||||
let styleString = '';
|
||||
switch (this.styleType) {
|
||||
case 'text':
|
||||
styleString = `color:#000;border-left:0;`;
|
||||
break;
|
||||
default:
|
||||
styleString = `color:#222;background:#eddbba;border-color:#fff;`;
|
||||
break;
|
||||
}
|
||||
return styleString;
|
||||
},
|
||||
activeStyle() {
|
||||
let styleString = '';
|
||||
switch (this.styleType) {
|
||||
case 'text':
|
||||
styleString = `color:${this.activeColor};border-left:0;border-bottom-style:solid;`;
|
||||
break;
|
||||
default:
|
||||
styleString = `color:#fff;border-color:${this.activeColor};background-color:${this.activeColor}`;
|
||||
break;
|
||||
}
|
||||
return styleString;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onClick(index) {
|
||||
let {
|
||||
lockTap,
|
||||
currentIndex
|
||||
} = this
|
||||
console.log(lockTap, currentIndex);
|
||||
if (currentIndex !== index || !lockTap) {
|
||||
this.currentIndex = index;
|
||||
this.$emit('clickItem', index);
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.segmented-control {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
font-size: 26rpx;
|
||||
border-radius: 5rpx;
|
||||
box-sizing: border-box;
|
||||
margin: 0 auto;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.segmented-control.button {
|
||||
border-radius: 54rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.segmented-control.text {
|
||||
border: 0;
|
||||
border-radius: 0rpx;
|
||||
}
|
||||
|
||||
|
||||
.segmented-control-item {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
line-height: 54rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.segmented-control-item.button {
|
||||
border-left: 1upx solid;
|
||||
}
|
||||
|
||||
.segmented-control-item.button:first-child {
|
||||
border-radius: 54rpx 0 0 54rpx;
|
||||
}
|
||||
|
||||
.segmented-control-item.button:last-child {
|
||||
border-radius: 0 54rpx 54rpx 0;
|
||||
}
|
||||
|
||||
.segmented-control-item.text {
|
||||
border-left: 0;
|
||||
}
|
||||
|
||||
.segmented-control-item:first-child {
|
||||
border-left-width: 0;
|
||||
}
|
||||
</style>
|
||||
29
uniapp/uni-app/components/uni-status-bar.vue
Normal file
29
uniapp/uni-app/components/uni-status-bar.vue
Normal file
@@ -0,0 +1,29 @@
|
||||
<template>
|
||||
<view class="uni-status-bar" :style="style">
|
||||
<slot></slot>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
computed: {
|
||||
style() {
|
||||
//#ifdef APP-PLUS
|
||||
return ''
|
||||
//#endif
|
||||
//#ifndef APP-PLUS
|
||||
return `height:${uni.getSystemInfoSync().statusBarHeight}px`
|
||||
//#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.uni-status-bar {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 20px;
|
||||
height: var(--status-bar-height);
|
||||
}
|
||||
</style>
|
||||
326
uniapp/uni-app/components/upload.vue
Normal file
326
uniapp/uni-app/components/upload.vue
Normal file
@@ -0,0 +1,326 @@
|
||||
<template>
|
||||
<view
|
||||
:class="[{'flex-warp':!imgTypeList.includes(imgclass) || !imgclass},{'flex-center flex-column':imgTypeList.includes(imgclass)}]">
|
||||
<block v-for="(item,index) in imagelist" :key="index">
|
||||
<view class="rel item-child radius-16" :class="[imgclass,{'margin border': imgsize > 1}]">
|
||||
<image mode="aspectFill" lazy-load @tap="previewImage(item,imagelist)" class="upload-img radius-16"
|
||||
:src="item.path" v-if="filetype == 'picture'"></image>
|
||||
<video :id="`video_${index}`" class="ipload-video radius-16" :loop="false" enable-play-gesture
|
||||
enable-progress-gesture :show-center-play-btn="true" :controls="true" :src="item.path"
|
||||
:data-id="item.id" objectFit="cover" :data-index="index" @play="onPlay" @pause="onPause"
|
||||
@ended="onEnded" @timeupdate="onTimeUpdate" @waiting="onWaiting" @progress="onProgress"
|
||||
@loadedmetadata="onLoadedMetaData" v-if="filetype == 'video'">
|
||||
</video>
|
||||
<block v-if="imgauth">
|
||||
<block v-if="imgsize>1">
|
||||
<view @tap="toDel(index)" class="guanbi abs flex-center" :class="[imgclass]"
|
||||
style="z-index: 1;"><i class="iconfont icon-add rotate-45 c-base"></i></view>
|
||||
</block>
|
||||
<block v-else>
|
||||
<view @tap="chooseImage"
|
||||
class="flex-center flex-column item-child border upload-item radius-16 abs"
|
||||
:class="[imgclass]" style="top:0;margin-top:0;background:rgba(0,0,0,0.5);">
|
||||
<view class="upload-icon flex-center c-base radius-16">
|
||||
<i class="iconfont icon-camera"></i>
|
||||
</view>
|
||||
<view class="f-caption c-base mt-sm">重新上传</view>
|
||||
</view>
|
||||
</block>
|
||||
</block>
|
||||
</view>
|
||||
</block>
|
||||
<view @tap="chooseImage" class="radius-16 flex-center flex-column item-child border rel upload-item fill-body"
|
||||
:class="[imgclass,{'margin': imgsize > 1}]" v-if="imgauth && imagelist.length < imgsize">
|
||||
<image mode="aspectFill" lazy-load class="item-child md bg-img abs radius-16"
|
||||
style="width: 292rpx;height: 200rpx;" :src="bgimg" v-if="bgimg">
|
||||
</image>
|
||||
<block v-else>
|
||||
<view class="upload-icon flex-center c-desc radius-16">
|
||||
<i class="iconfont icon-camera"></i>
|
||||
</view>
|
||||
<view class="f-caption c-caption mt-sm" v-if="text">{{text}}</view>
|
||||
<view class="cur-imgsize f-caption c-caption" v-if="imgsize>1">{{`${imagelist.length}/${imgsize}`}}
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
mapState,
|
||||
mapActions,
|
||||
} from 'vuex';
|
||||
export default {
|
||||
props: {
|
||||
// 图片列表
|
||||
imagelist: {
|
||||
type: Array,
|
||||
default () {
|
||||
return []
|
||||
}
|
||||
},
|
||||
// 图片参数名
|
||||
imgtype: {
|
||||
type: String,
|
||||
default () {
|
||||
return ''
|
||||
}
|
||||
},
|
||||
// 图片张数
|
||||
imgsize: {
|
||||
type: Number,
|
||||
default () {
|
||||
return 9
|
||||
}
|
||||
},
|
||||
// 上传类型
|
||||
filetype: {
|
||||
type: String,
|
||||
default () {
|
||||
return 'picture'
|
||||
}
|
||||
},
|
||||
// 图片样式
|
||||
imgclass: {
|
||||
type: String,
|
||||
default () {
|
||||
return ''
|
||||
}
|
||||
},
|
||||
// 是否有权限
|
||||
imgauth: {
|
||||
type: Boolean,
|
||||
default () {
|
||||
return true
|
||||
}
|
||||
},
|
||||
// 备注信息
|
||||
text: {
|
||||
type: String,
|
||||
default () {
|
||||
return ''
|
||||
}
|
||||
},
|
||||
// 默认背景图
|
||||
bgimg: {
|
||||
type: String,
|
||||
default () {
|
||||
return ''
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
imgTypeList: ['md', 'lg'],
|
||||
}
|
||||
},
|
||||
computed: mapState({
|
||||
primaryColor: state => state.config.configInfo.primaryColor,
|
||||
subColor: state => state.config.configInfo.subColor,
|
||||
}),
|
||||
methods: {
|
||||
previewImage(current, urls) {
|
||||
let res_urls = [];
|
||||
urls = this.$util.deepCopy(urls);
|
||||
urls.forEach((item, index) => {
|
||||
res_urls.push(item.path)
|
||||
})
|
||||
uni.previewImage({
|
||||
current: current.path,
|
||||
urls: res_urls,
|
||||
})
|
||||
},
|
||||
async toDel(index) {
|
||||
let fileName = this.filetype == 'picture' ? '图片' : '视频'
|
||||
let [res_del, {
|
||||
confirm
|
||||
}] = await uni.showModal({
|
||||
content: `请确认是否要删除${fileName}`,
|
||||
})
|
||||
if (!confirm) return;
|
||||
this.imagelist.splice(index, 1);
|
||||
this.$emit('del', {
|
||||
imgtype: this.imgtype,
|
||||
imagelist: this.imagelist
|
||||
});
|
||||
},
|
||||
async chooseImage() {
|
||||
let {
|
||||
imgtype,
|
||||
imgsize,
|
||||
filetype
|
||||
} = this;
|
||||
let imagelist = this.$util.deepCopy(this.imagelist)
|
||||
let is_upload_img = filetype == 'picture'
|
||||
let chooseModel = is_upload_img ? 'chooseImage' : 'chooseVideo'
|
||||
let param = {
|
||||
count: imgsize - imagelist.length * 1,
|
||||
}
|
||||
if (is_upload_img) {
|
||||
param.sizeType = ['compressed']
|
||||
}
|
||||
let [res_upload, res_info] = await uni[chooseModel](param)
|
||||
if (res_upload) return
|
||||
let {
|
||||
size = 0,
|
||||
tempFiles,
|
||||
tempFilePath = ''
|
||||
} = res_info
|
||||
if (filetype == 'video' && size / 1024 / 1024 > 100) {
|
||||
this.$util.showToast({
|
||||
title: `上传视频大小超过限制100M`
|
||||
})
|
||||
return
|
||||
}
|
||||
let filePath = [];
|
||||
// 格式化图片参数
|
||||
this.$util.showLoading({
|
||||
title: "上传中"
|
||||
});
|
||||
if (is_upload_img) {
|
||||
for (let i = 0; i < tempFiles.length; i++) {
|
||||
let {
|
||||
attachment_path: path
|
||||
} = await this.$api.base.uploadFile({
|
||||
filePath: tempFiles[i].path,
|
||||
filetype
|
||||
})
|
||||
if (imgsize > 1) {
|
||||
imagelist.push({
|
||||
path
|
||||
})
|
||||
} else {
|
||||
imagelist = [{
|
||||
path
|
||||
}]
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let path = await this.$api.base.uploadVideo({
|
||||
filePath: tempFilePath,
|
||||
filetype
|
||||
})
|
||||
console.log(path, "=====video path");
|
||||
imagelist.push({
|
||||
path
|
||||
})
|
||||
}
|
||||
this.$util.hideAll()
|
||||
this.$emit('upload', {
|
||||
imgtype,
|
||||
imagelist
|
||||
});
|
||||
},
|
||||
onPlay(e) {},
|
||||
onPause(e) {},
|
||||
onEnded(e) {},
|
||||
onTimeUpdate(e) {},
|
||||
onWaiting(e) {},
|
||||
onProgress(e) {},
|
||||
onLoadedMetaData(e) {},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.item-child {
|
||||
width: 200rpx;
|
||||
height: 200rpx;
|
||||
background: #fff;
|
||||
margin: 20rpx 0;
|
||||
}
|
||||
|
||||
.border {
|
||||
border: 1rpx dashed #ccc;
|
||||
transform: rotateZ(360deg);
|
||||
}
|
||||
|
||||
.item-child.bg-img {
|
||||
top: 0;
|
||||
margin: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.margin {
|
||||
margin: 20rpx 20rpx 0 0;
|
||||
}
|
||||
|
||||
.item-child:nth-child(3n) {
|
||||
margin-right: 0rpx;
|
||||
}
|
||||
|
||||
.item-child.sm {
|
||||
width: 140rpx;
|
||||
height: 140rpx;
|
||||
}
|
||||
|
||||
.item-child.mini {
|
||||
width: 196rpx;
|
||||
height: 196rpx;
|
||||
}
|
||||
|
||||
.item-child.md {
|
||||
width: 294rpx;
|
||||
height: 202rpx;
|
||||
margin-bottom: 20rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.item-child.lg {
|
||||
width: 690rpx;
|
||||
height: 400rpx;
|
||||
}
|
||||
|
||||
.upload-img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.upload-item {
|
||||
|
||||
.upload-icon {
|
||||
// width: 80rpx;
|
||||
// height: 76rpx;
|
||||
// background: #FFFFFF;
|
||||
|
||||
.iconfont {
|
||||
font-size: 70rpx;
|
||||
display: block;
|
||||
// color: #BBBBBB;
|
||||
}
|
||||
}
|
||||
|
||||
.cur-imgsize {
|
||||
line-height: 1.1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.upload-item.margin {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.guanbi {
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
background: rgba(0, 0, 0, 0.2);
|
||||
border-radius: 0 10rpx 0 0;
|
||||
top: 0rpx;
|
||||
right: 0rpx;
|
||||
z-index: 1;
|
||||
|
||||
.iconfont {
|
||||
font-size: 28rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.guanbi.lg {
|
||||
width: 50rpx;
|
||||
height: 50rpx;
|
||||
|
||||
.iconfont {
|
||||
font-size: 38rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
1
uniapp/uni-app/components/w-picker/areadata/areadata.js
Normal file
1
uniapp/uni-app/components/w-picker/areadata/areadata.js
Normal file
File diff suppressed because one or more lines are too long
742
uniapp/uni-app/components/w-picker/date-picker.vue
Normal file
742
uniapp/uni-app/components/w-picker/date-picker.vue
Normal file
@@ -0,0 +1,742 @@
|
||||
<template>
|
||||
<view class="w-picker-view">
|
||||
<picker-view v-if="fields=='year'" class="d-picker-view" :indicator-style="itemHeight" :value="pickVal" @change="handlerChange">
|
||||
<picker-view-column>
|
||||
<view class="w-picker-item" v-for="(item,index) in range.years" :key="index">{{item}}年</view>
|
||||
</picker-view-column>
|
||||
</picker-view>
|
||||
<picker-view v-if="fields=='month'" class="d-picker-view" :indicator-style="itemHeight" :value="pickVal" @change="handlerChange">
|
||||
<picker-view-column>
|
||||
<view class="w-picker-item" v-for="(item,index) in range.years" :key="index">{{item}}年</view>
|
||||
</picker-view-column>
|
||||
<picker-view-column>
|
||||
<view class="w-picker-item" v-for="(item,index) in range.months" :key="index">{{item}}月</view>
|
||||
</picker-view-column>
|
||||
</picker-view>
|
||||
<picker-view v-if="fields=='day'" class="d-picker-view" :indicator-style="itemHeight" :value="pickVal" @change="handlerChange">
|
||||
<picker-view-column>
|
||||
<view class="w-picker-item" v-for="(item,index) in range.years" :key="index">{{item}}年</view>
|
||||
</picker-view-column>
|
||||
<picker-view-column>
|
||||
<view class="w-picker-item" v-for="(item,index) in range.months" :key="index">{{item}}月</view>
|
||||
</picker-view-column>
|
||||
<picker-view-column>
|
||||
<view class="w-picker-item" v-for="(item,index) in range.days" :key="index">{{item}}日</view>
|
||||
</picker-view-column>
|
||||
</picker-view>
|
||||
<picker-view v-if="fields=='hour'" class="d-picker-view" :indicator-style="itemHeight" :value="pickVal" @change="handlerChange">
|
||||
<picker-view-column>
|
||||
<view class="w-picker-item" v-for="(item,index) in range.years" :key="index">{{item}}年</view>
|
||||
</picker-view-column>
|
||||
<picker-view-column>
|
||||
<view class="w-picker-item" v-for="(item,index) in range.months" :key="index">{{item}}月</view>
|
||||
</picker-view-column>
|
||||
<picker-view-column>
|
||||
<view class="w-picker-item" v-for="(item,index) in range.days" :key="index">{{item}}日</view>
|
||||
</picker-view-column>
|
||||
<picker-view-column>
|
||||
<view class="w-picker-item" v-for="(item,index) in range.hours" :key="index">{{item}}时</view>
|
||||
</picker-view-column>
|
||||
</picker-view>
|
||||
<picker-view v-if="fields=='minute'" class="d-picker-view" :indicator-style="itemHeight" :value="pickVal" @change="handlerChange">
|
||||
<picker-view-column>
|
||||
<view class="w-picker-item" v-for="(item,index) in range.years" :key="index">{{item}}年</view>
|
||||
</picker-view-column>
|
||||
<picker-view-column>
|
||||
<view class="w-picker-item" v-for="(item,index) in range.months" :key="index">{{item}}月</view>
|
||||
</picker-view-column>
|
||||
<picker-view-column>
|
||||
<view class="w-picker-item" v-for="(item,index) in range.days" :key="index">{{item}}日</view>
|
||||
</picker-view-column>
|
||||
<picker-view-column>
|
||||
<view class="w-picker-item" v-for="(item,index) in range.hours" :key="index">{{item}}时</view>
|
||||
</picker-view-column>
|
||||
<picker-view-column>
|
||||
<view class="w-picker-item" v-for="(item,index) in range.minutes" :key="index">{{item}}分</view>
|
||||
</picker-view-column>
|
||||
</picker-view>
|
||||
<picker-view v-if="fields=='second'" class="d-picker-view" :indicator-style="itemHeight" :value="pickVal" @change="handlerChange">
|
||||
<picker-view-column>
|
||||
<view class="w-picker-item" v-for="(item,index) in range.years" :key="index">{{item}}年</view>
|
||||
</picker-view-column>
|
||||
<picker-view-column>
|
||||
<view class="w-picker-item" v-for="(item,index) in range.months" :key="index">{{item}}月</view>
|
||||
</picker-view-column>
|
||||
<picker-view-column>
|
||||
<view class="w-picker-item" v-for="(item,index) in range.days" :key="index">{{item}}日</view>
|
||||
</picker-view-column>
|
||||
<picker-view-column>
|
||||
<view class="w-picker-item" v-for="(item,index) in range.hours" :key="index">{{item}}时</view>
|
||||
</picker-view-column>
|
||||
<picker-view-column>
|
||||
<view class="w-picker-item" v-for="(item,index) in range.minutes" :key="index">{{item}}分</view>
|
||||
</picker-view-column>
|
||||
<picker-view-column>
|
||||
<view class="w-picker-item" v-for="(item,index) in range.seconds" :key="index">{{item}}秒</view>
|
||||
</picker-view-column>
|
||||
</picker-view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
pickVal:[],
|
||||
range:{
|
||||
years:[],
|
||||
months:[],
|
||||
days:[],
|
||||
hours:[],
|
||||
minutes:[],
|
||||
seconds:[]
|
||||
},
|
||||
checkObj:{}
|
||||
};
|
||||
},
|
||||
props:{
|
||||
itemHeight:{
|
||||
type:String,
|
||||
default:"44px"
|
||||
},
|
||||
startYear:{
|
||||
type:[String,Number],
|
||||
default:""
|
||||
},
|
||||
endYear:{
|
||||
type:[String,Number],
|
||||
default:""
|
||||
},
|
||||
value:{
|
||||
type:[String,Array,Number],
|
||||
default:""
|
||||
},
|
||||
current:{//是否默认选中当前日期
|
||||
type:Boolean,
|
||||
default:false
|
||||
},
|
||||
disabledAfter:{//是否禁用当前之后的日期
|
||||
type:Boolean,
|
||||
default:false
|
||||
},
|
||||
fields:{
|
||||
type:String,
|
||||
default:"day"
|
||||
}
|
||||
},
|
||||
watch:{
|
||||
fields(val){
|
||||
this.initData();
|
||||
},
|
||||
value(val){
|
||||
this.initData();
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.initData();
|
||||
},
|
||||
methods:{
|
||||
formatNum(n){
|
||||
return (Number(n)<10?'0'+Number(n):Number(n)+'');
|
||||
},
|
||||
checkValue(value){
|
||||
let strReg,example
|
||||
switch(this.fields){
|
||||
case "year":
|
||||
strReg=/^\d{4}$/;
|
||||
example="2019";
|
||||
break;
|
||||
case "month":
|
||||
strReg=/^\d{4}-\d{2}$/;
|
||||
example="2019-02";
|
||||
break;
|
||||
case "day":
|
||||
strReg=/^\d{4}-\d{2}-\d{2}$/;
|
||||
example="2019-02-01";
|
||||
break;
|
||||
case "hour":
|
||||
strReg=/^\d{4}-\d{2}-\d{2} \d{2}(:\d{2}){1,2}?$/;
|
||||
example="2019-02-01 18:00:00或2019-02-01 18";
|
||||
break;
|
||||
case "minute":
|
||||
strReg=/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}(:\d{2}){0,1}?$/;
|
||||
example="2019-02-01 18:06:00或2019-02-01 18:06";
|
||||
break;
|
||||
case "second":
|
||||
strReg=/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/;
|
||||
example="2019-02-01 18:06:01";
|
||||
break;
|
||||
}
|
||||
if(!strReg.test(value)){
|
||||
console.log(new Error("请传入与mode、fields匹配的value值,例value="+example+""))
|
||||
}
|
||||
return strReg.test(value);
|
||||
},
|
||||
resetData(year,month,day,hour,minute){
|
||||
let curDate=this.getCurrenDate();
|
||||
let curFlag=this.current;
|
||||
let curYear=curDate.curYear;
|
||||
let curMonth=curDate.curMonth;
|
||||
let curDay=curDate.curDay;
|
||||
let curHour=curDate.curHour;
|
||||
let curMinute=curDate.curMinute;
|
||||
let curSecond=curDate.curSecond;
|
||||
let months=[],days=[],hours=[],minutes=[],seconds=[];
|
||||
let disabledAfter=this.disabledAfter;
|
||||
let monthsLen=disabledAfter?(year*1<curYear?12:curMonth):12;
|
||||
let totalDays=new Date(year,month,0).getDate();//计算当月有几天;
|
||||
let daysLen=disabledAfter?((year*1<curYear||month*1<curMonth)?totalDays:curDay):totalDays;
|
||||
let hoursLen=disabledAfter?((year*1<curYear||month*1<curMonth||day*1<curDay)?24:curHour+1):24;
|
||||
let minutesLen=disabledAfter?((year*1<curYear||month*1<curMonth||day*1<curDay||hour*1<curHour)?60:curMinute+1):60;
|
||||
let secondsLen=disabledAfter?((year*1<curYear||month*1<curMonth||day*1<curDay||hour*1<curHour||minute*1<curMinute)?60:curSecond+1):60;
|
||||
for(let month=1;month<=monthsLen;month++){
|
||||
months.push(this.formatNum(month));
|
||||
};
|
||||
for(let day=1;day<=daysLen;day++){
|
||||
days.push(this.formatNum(day));
|
||||
}
|
||||
for(let hour=0;hour<hoursLen;hour++){
|
||||
hours.push(this.formatNum(hour));
|
||||
}
|
||||
for(let minute=0;minute<minutesLen;minute++){
|
||||
minutes.push(this.formatNum(minute));
|
||||
}
|
||||
for(let second=0;second<secondsLen;second++){
|
||||
seconds.push(this.formatNum(second));
|
||||
}
|
||||
return{
|
||||
months,
|
||||
days,
|
||||
hours,
|
||||
minutes,
|
||||
seconds
|
||||
}
|
||||
},
|
||||
isLeapYear (Year) {
|
||||
if (((Year % 4)==0) && ((Year % 100)!=0) || ((Year % 400)==0)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
getData(dVal){
|
||||
//用来处理初始化数据
|
||||
let curFlag=this.current;
|
||||
let disabledAfter=this.disabledAfter;
|
||||
let fields=this.fields;
|
||||
let curDate=this.getCurrenDate();
|
||||
let curYear=curDate.curYear;
|
||||
let curMonthdays=curDate.curMonthdays;
|
||||
let curMonth=curDate.curMonth;
|
||||
let curDay=curDate.curDay;
|
||||
let curHour=curDate.curHour;
|
||||
let curMinute=curDate.curMinute;
|
||||
let curSecond=curDate.curSecond;
|
||||
let defaultDate=this.getDefaultDate();
|
||||
let startYear=this.getStartDate().getFullYear();
|
||||
let endYear=this.getEndDate().getFullYear();
|
||||
//颗粒度,禁用当前之后日期仅对year,month,day,hour生效;分钟秒禁用没有意义,
|
||||
let years=[],months=[],days=[],hours=[],minutes=[],seconds=[];
|
||||
let year=dVal[0]*1;
|
||||
let month=dVal[1]*1;
|
||||
let day=dVal[2]*1;
|
||||
let hour=dVal[3]*1;
|
||||
let minute=dVal[4]*1;
|
||||
let monthsLen=disabledAfter?(year<curYear?12:curDate.curMonth):12;
|
||||
let daysLen=disabledAfter?((year<curYear||month<curMonth)?defaultDate.defaultDays:curDay):(curFlag?curMonthdays:defaultDate.defaultDays);
|
||||
let hoursLen=disabledAfter?((year<curYear||month<curMonth||day<curDay)?24:curHour+1):24;
|
||||
let minutesLen=disabledAfter?((year<curYear||month<curMonth||day<curDay||hour<curHour)?60:curMinute+1):60;
|
||||
let secondsLen=disabledAfter?((year<curYear||month<curMonth||day<curDay||hour<curHour||minute<curMinute)?60:curSecond+1):60;
|
||||
for(let year=startYear;year<=(disabledAfter?curYear:endYear);year++){
|
||||
years.push(year.toString())
|
||||
}
|
||||
for(let month=1;month<=monthsLen;month++){
|
||||
months.push(this.formatNum(month));
|
||||
}
|
||||
for(let day=1;day<=daysLen;day++){
|
||||
days.push(this.formatNum(day));
|
||||
}
|
||||
for(let hour=0;hour<hoursLen;hour++){
|
||||
hours.push(this.formatNum(hour));
|
||||
}
|
||||
for(let minute=0;minute<minutesLen;minute++){
|
||||
minutes.push(this.formatNum(minute));
|
||||
}
|
||||
// for(let second=0;second<(disabledAfter?curDate.curSecond+1:60);second++){
|
||||
// seconds.push(this.formatNum(second));
|
||||
// }
|
||||
for(let second=0;second<60;second++){
|
||||
seconds.push(this.formatNum(second));
|
||||
}
|
||||
return {
|
||||
years,
|
||||
months,
|
||||
days,
|
||||
hours,
|
||||
minutes,
|
||||
seconds
|
||||
}
|
||||
},
|
||||
getCurrenDate(){
|
||||
let curDate=new Date();
|
||||
let curYear=curDate.getFullYear();
|
||||
let curMonth=curDate.getMonth()+1;
|
||||
let curMonthdays=new Date(curYear,curMonth,0).getDate();
|
||||
let curDay=curDate.getDate();
|
||||
let curHour=curDate.getHours();
|
||||
let curMinute=curDate.getMinutes();
|
||||
let curSecond=curDate.getSeconds();
|
||||
return{
|
||||
curDate,
|
||||
curYear,
|
||||
curMonth,
|
||||
curMonthdays,
|
||||
curDay,
|
||||
curHour,
|
||||
curMinute,
|
||||
curSecond
|
||||
}
|
||||
},
|
||||
getDefaultDate(){
|
||||
let value=this.value;
|
||||
let reg=/-/g;
|
||||
let defaultDate=value?new Date(value.replace(reg,"/")):new Date();
|
||||
let defaultYear=defaultDate.getFullYear();
|
||||
let defaultMonth=defaultDate.getMonth()+1;
|
||||
let defaultDay=defaultDate.getDate();
|
||||
let defaultDays=new Date(defaultYear,defaultMonth,0).getDate()*1;
|
||||
return{
|
||||
defaultDate,
|
||||
defaultYear,
|
||||
defaultMonth,
|
||||
defaultDay,
|
||||
defaultDays
|
||||
}
|
||||
},
|
||||
getStartDate(){
|
||||
let start=this.startYear;
|
||||
let startDate="";
|
||||
let reg=/-/g;
|
||||
if(start){
|
||||
startDate=new Date(start+"/01/01");
|
||||
}else{
|
||||
startDate=new Date("1970/01/01");
|
||||
}
|
||||
return startDate;
|
||||
},
|
||||
getEndDate(){
|
||||
let end=this.endYear;
|
||||
let reg=/-/g;
|
||||
let endDate="";
|
||||
if(end){
|
||||
endDate=new Date(end+"/12/01");
|
||||
}else{
|
||||
endDate=new Date();
|
||||
}
|
||||
return endDate;
|
||||
},
|
||||
getDval(){
|
||||
let value=this.value;
|
||||
let fields=this.fields;
|
||||
let dVal=null;
|
||||
let aDate=new Date();
|
||||
let year=this.formatNum(aDate.getFullYear());
|
||||
let month=this.formatNum(aDate.getMonth()+1);
|
||||
let day=this.formatNum(aDate.getDate());
|
||||
let hour=this.formatNum(aDate.getHours());
|
||||
let minute=this.formatNum(aDate.getMinutes());
|
||||
let second=this.formatNum(aDate.getSeconds());
|
||||
if(value){
|
||||
let flag=this.checkValue(value);
|
||||
if(!flag){
|
||||
dVal=[year,month,day,hour,minute,second]
|
||||
}else{
|
||||
switch(this.fields){
|
||||
case "year":
|
||||
dVal=value?[value]:[];
|
||||
break;
|
||||
case "month":
|
||||
dVal=value?value.split("-"):[];
|
||||
break;
|
||||
case "day":
|
||||
dVal=value?value.split("-"):[];
|
||||
break;
|
||||
case "hour":
|
||||
dVal=[...value.split(" ")[0].split("-"),...value.split(" ")[1].split(":")];
|
||||
break;
|
||||
case "minute":
|
||||
dVal=value?[...value.split(" ")[0].split("-"),...value.split(" ")[1].split(":")]:[];
|
||||
break;
|
||||
case "second":
|
||||
dVal=[...value.split(" ")[0].split("-"),...value.split(" ")[1].split(":")];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
dVal=[year,month,day,hour,minute,second]
|
||||
}
|
||||
return dVal;
|
||||
},
|
||||
initData(){
|
||||
let startDate,endDate,startYear,endYear,startMonth,endMonth,startDay,endDay;
|
||||
let years=[],months=[],days=[],hours=[],minutes=[],seconds=[];
|
||||
let dVal=[],pickVal=[];
|
||||
let value=this.value;
|
||||
let reg=/-/g;
|
||||
let range={};
|
||||
let result="",full="",year,month,day,hour,minute,second,obj={};
|
||||
let defaultDate=this.getDefaultDate();
|
||||
let defaultYear=defaultDate.defaultYear;
|
||||
let defaultMonth=defaultDate.defaultMonth;
|
||||
let defaultDay=defaultDate.defaultDay;
|
||||
let defaultDays=defaultDate.defaultDays;
|
||||
let curFlag=this.current;
|
||||
let disabledAfter=this.disabledAfter;
|
||||
let curDate=this.getCurrenDate();
|
||||
let curYear=curDate.curYear;
|
||||
let curMonth=curDate.curMonth;
|
||||
let curMonthdays=curDate.curMonthdays;
|
||||
let curDay=curDate.curDay;
|
||||
let curHour=curDate.curHour;
|
||||
let curMinute=curDate.curMinute;
|
||||
let curSecond=curDate.curSecond;
|
||||
let dateData=[];
|
||||
dVal=this.getDval();
|
||||
|
||||
startDate=this.getStartDate();
|
||||
endDate=this.getEndDate();
|
||||
startYear=startDate.getFullYear();
|
||||
startMonth=startDate.getMonth();
|
||||
startDay=startDate.getDate();
|
||||
endYear=endDate.getFullYear();
|
||||
endMonth=endDate.getMonth();
|
||||
endDay=endDate.getDate();
|
||||
dateData=this.getData(dVal);
|
||||
years=dateData.years;
|
||||
months=dateData.months;
|
||||
days=dateData.days;
|
||||
hours=dateData.hours;
|
||||
minutes=dateData.minutes;
|
||||
seconds=dateData.seconds;
|
||||
switch(this.fields){
|
||||
case "year":
|
||||
pickVal=disabledAfter?[
|
||||
dVal[0]&&years.indexOf(dVal[0])!=-1?years.indexOf(dVal[0]):0
|
||||
]:(curFlag?[
|
||||
years.indexOf(curYear+'')
|
||||
]:[
|
||||
dVal[0]&&years.indexOf(dVal[0])!=-1?years.indexOf(dVal[0]):0
|
||||
]);
|
||||
range={years};
|
||||
year=dVal[0]?dVal[0]:years[0];
|
||||
result=full=`${year}`;
|
||||
obj={
|
||||
year
|
||||
}
|
||||
break;
|
||||
case "month":
|
||||
pickVal=disabledAfter?[
|
||||
dVal[0]&&years.indexOf(dVal[0])!=-1?years.indexOf(dVal[0]):0,
|
||||
dVal[1]&&months.indexOf(dVal[1])!=-1?months.indexOf(dVal[1]):0
|
||||
]:(curFlag?[
|
||||
years.indexOf(curYear+''),
|
||||
months.indexOf(this.formatNum(curMonth))
|
||||
]:[
|
||||
dVal[0]&&years.indexOf(dVal[0])!=-1?years.indexOf(dVal[0]):0,
|
||||
dVal[1]&&months.indexOf(dVal[1])!=-1?months.indexOf(dVal[1]):0
|
||||
]);
|
||||
range={years,months};
|
||||
year=dVal[0]?dVal[0]:years[0];
|
||||
month=dVal[1]?dVal[1]:months[0];
|
||||
result=full=`${year+'-'+month}`;
|
||||
obj={
|
||||
year,
|
||||
month
|
||||
}
|
||||
break;
|
||||
case "day":
|
||||
pickVal=disabledAfter?[
|
||||
dVal[0]&&years.indexOf(dVal[0])!=-1?years.indexOf(dVal[0]):0,
|
||||
dVal[1]&&months.indexOf(dVal[1])!=-1?months.indexOf(dVal[1]):0,
|
||||
dVal[2]&&days.indexOf(dVal[2])!=-1?days.indexOf(dVal[2]):0
|
||||
]:(curFlag?[
|
||||
years.indexOf(curYear+''),
|
||||
months.indexOf(this.formatNum(curMonth)),
|
||||
days.indexOf(this.formatNum(curDay)),
|
||||
]:[
|
||||
dVal[0]&&years.indexOf(dVal[0])!=-1?years.indexOf(dVal[0]):0,
|
||||
dVal[1]&&months.indexOf(dVal[1])!=-1?months.indexOf(dVal[1]):0,
|
||||
dVal[2]&&days.indexOf(dVal[2])!=-1?days.indexOf(dVal[2]):0
|
||||
]);
|
||||
range={years,months,days};
|
||||
year=dVal[0]?dVal[0]:years[0];
|
||||
month=dVal[1]?dVal[1]:months[0];
|
||||
day=dVal[2]?dVal[2]:days[0];
|
||||
result=full=`${year+'-'+month+'-'+day}`;
|
||||
obj={
|
||||
year,
|
||||
month,
|
||||
day
|
||||
}
|
||||
break;
|
||||
case "hour":
|
||||
pickVal=disabledAfter?[
|
||||
dVal[0]&&years.indexOf(dVal[0])!=-1?years.indexOf(dVal[0]):0,
|
||||
dVal[1]&&months.indexOf(dVal[1])!=-1?months.indexOf(dVal[1]):0,
|
||||
dVal[2]&&days.indexOf(dVal[2])!=-1?days.indexOf(dVal[2]):0,
|
||||
dVal[3]&&hours.indexOf(dVal[3])!=-1?hours.indexOf(dVal[3]):0
|
||||
]:(curFlag?[
|
||||
years.indexOf(curYear+''),
|
||||
months.indexOf(this.formatNum(curMonth)),
|
||||
days.indexOf(this.formatNum(curDay)),
|
||||
hours.indexOf(this.formatNum(curHour)),
|
||||
]:[
|
||||
dVal[0]&&years.indexOf(dVal[0])!=-1?years.indexOf(dVal[0]):0,
|
||||
dVal[1]&&months.indexOf(dVal[1])!=-1?months.indexOf(dVal[1]):0,
|
||||
dVal[2]&&days.indexOf(dVal[2])!=-1?days.indexOf(dVal[2]):0,
|
||||
dVal[3]&&hours.indexOf(dVal[3])!=-1?hours.indexOf(dVal[3]):0
|
||||
]);
|
||||
range={years,months,days,hours};
|
||||
year=dVal[0]?dVal[0]:years[0];
|
||||
month=dVal[1]?dVal[1]:months[0];
|
||||
day=dVal[2]?dVal[2]:days[0];
|
||||
hour=dVal[3]?dVal[3]:hours[0];
|
||||
result=`${year+'-'+month+'-'+day+' '+hour}`;
|
||||
full=`${year+'-'+month+'-'+day+' '+hour+':00:00'}`;
|
||||
obj={
|
||||
year,
|
||||
month,
|
||||
day,
|
||||
hour
|
||||
}
|
||||
break;
|
||||
case "minute":
|
||||
pickVal=disabledAfter?[
|
||||
dVal[0]&&years.indexOf(dVal[0])!=-1?years.indexOf(dVal[0]):0,
|
||||
dVal[1]&&months.indexOf(dVal[1])!=-1?months.indexOf(dVal[1]):0,
|
||||
dVal[2]&&days.indexOf(dVal[2])!=-1?days.indexOf(dVal[2]):0,
|
||||
dVal[3]&&hours.indexOf(dVal[3])!=-1?hours.indexOf(dVal[3]):0,
|
||||
dVal[4]&&minutes.indexOf(dVal[4])!=-1?minutes.indexOf(dVal[4]):0
|
||||
]:(curFlag?[
|
||||
years.indexOf(curYear+''),
|
||||
months.indexOf(this.formatNum(curMonth)),
|
||||
days.indexOf(this.formatNum(curDay)),
|
||||
hours.indexOf(this.formatNum(curHour)),
|
||||
minutes.indexOf(this.formatNum(curMinute)),
|
||||
]:[
|
||||
dVal[0]&&years.indexOf(dVal[0])!=-1?years.indexOf(dVal[0]):0,
|
||||
dVal[1]&&months.indexOf(dVal[1])!=-1?months.indexOf(dVal[1]):0,
|
||||
dVal[2]&&days.indexOf(dVal[2])!=-1?days.indexOf(dVal[2]):0,
|
||||
dVal[3]&&hours.indexOf(dVal[3])!=-1?hours.indexOf(dVal[3]):0,
|
||||
dVal[4]&&minutes.indexOf(dVal[4])!=-1?minutes.indexOf(dVal[4]):0
|
||||
]);
|
||||
range={years,months,days,hours,minutes};
|
||||
year=dVal[0]?dVal[0]:years[0];
|
||||
month=dVal[1]?dVal[1]:months[0];
|
||||
day=dVal[2]?dVal[2]:days[0];
|
||||
hour=dVal[3]?dVal[3]:hours[0];
|
||||
minute=dVal[4]?dVal[4]:minutes[0];
|
||||
full=`${year+'-'+month+'-'+day+' '+hour+':'+minute+':00'}`;
|
||||
result=`${year+'-'+month+'-'+day+' '+hour+':'+minute}`;
|
||||
obj={
|
||||
year,
|
||||
month,
|
||||
day,
|
||||
hour,
|
||||
minute
|
||||
}
|
||||
break;
|
||||
case "second":
|
||||
pickVal=disabledAfter?[
|
||||
dVal[0]&&years.indexOf(dVal[0])!=-1?years.indexOf(dVal[0]):0,
|
||||
dVal[1]&&months.indexOf(dVal[1])!=-1?months.indexOf(dVal[1]):0,
|
||||
dVal[2]&&days.indexOf(dVal[2])!=-1?days.indexOf(dVal[2]):0,
|
||||
dVal[3]&&hours.indexOf(dVal[3])!=-1?hours.indexOf(dVal[3]):0,
|
||||
dVal[4]&&minutes.indexOf(dVal[4])!=-1?minutes.indexOf(dVal[4]):0,
|
||||
dVal[5]&&seconds.indexOf(dVal[5])!=-1?seconds.indexOf(dVal[5]):0
|
||||
]:(curFlag?[
|
||||
years.indexOf(curYear+''),
|
||||
months.indexOf(this.formatNum(curMonth)),
|
||||
days.indexOf(this.formatNum(curDay)),
|
||||
hours.indexOf(this.formatNum(curHour)),
|
||||
minutes.indexOf(this.formatNum(curMinute)),
|
||||
seconds.indexOf(this.formatNum(curSecond)),
|
||||
]:[
|
||||
dVal[0]&&years.indexOf(dVal[0])!=-1?years.indexOf(dVal[0]):0,
|
||||
dVal[1]&&months.indexOf(dVal[1])!=-1?months.indexOf(dVal[1]):0,
|
||||
dVal[2]&&days.indexOf(dVal[2])!=-1?days.indexOf(dVal[2]):0,
|
||||
dVal[3]&&hours.indexOf(dVal[3])!=-1?hours.indexOf(dVal[3]):0,
|
||||
dVal[4]&&minutes.indexOf(dVal[4])!=-1?minutes.indexOf(dVal[4]):0,
|
||||
dVal[5]&&seconds.indexOf(dVal[5])!=-1?seconds.indexOf(dVal[5]):0
|
||||
]);
|
||||
range={years,months,days,hours,minutes,seconds};
|
||||
year=dVal[0]?dVal[0]:years[0];
|
||||
month=dVal[1]?dVal[1]:months[0];
|
||||
day=dVal[2]?dVal[2]:days[0];
|
||||
hour=dVal[3]?dVal[3]:hours[0];
|
||||
minute=dVal[4]?dVal[4]:minutes[0];
|
||||
second=dVal[5]?dVal[5]:seconds[0];
|
||||
result=full=`${year+'-'+month+'-'+day+' '+hour+':'+minute+':'+second}`;
|
||||
obj={
|
||||
year,
|
||||
month,
|
||||
day,
|
||||
hour,
|
||||
minute,
|
||||
second
|
||||
}
|
||||
break;
|
||||
default:
|
||||
range={years,months,days};
|
||||
break;
|
||||
}
|
||||
this.range=range;
|
||||
this.checkObj=obj;
|
||||
this.$emit("change",{
|
||||
result:result,
|
||||
value:full,
|
||||
obj:obj
|
||||
});
|
||||
this.$nextTick(()=>{
|
||||
this.pickVal=pickVal;
|
||||
})
|
||||
},
|
||||
handlerChange(e){
|
||||
let arr=[...e.detail.value];
|
||||
let data=this.range;
|
||||
let year="",month="",day="",hour="",minute="",second="";
|
||||
let result="",full="",obj={};
|
||||
let months=null,days=null,hours=null,minutes=null,seconds=null;
|
||||
let disabledAfter=this.disabledAfter;
|
||||
let leapYear=false,resetData={};
|
||||
year=(arr[0]||arr[0]==0)?data.years[arr[0]]||data.years[data.years.length-1]:"";
|
||||
month=(arr[1]||arr[1]==0)?data.months[arr[1]]||data.months[data.months.length-1]:"";
|
||||
day=(arr[2]||arr[2]==0)?data.days[arr[2]]||data.days[data.days.length-1]:"";
|
||||
hour=(arr[3]||arr[3]==0)?data.hours[arr[3]]||data.hours[data.hours.length-1]:"";
|
||||
minute=(arr[4]||arr[4]==0)?data.minutes[arr[4]]||data.minutes[data.minutes.length-1]:"";
|
||||
second=(arr[5]||arr[5]==0)?data.seconds[arr[5]]||data.seconds[data.seconds.length-1]:"";
|
||||
resetData=this.resetData(year,month,day,hour,minute);//重新拉取当前日期数据;
|
||||
leapYear=this.isLeapYear(year);//判断是否为闰年;
|
||||
switch(this.fields){
|
||||
case "year":
|
||||
result=full=`${year}`;
|
||||
obj={
|
||||
year
|
||||
};
|
||||
break;
|
||||
case "month":
|
||||
result=full=`${year+'-'+month}`;
|
||||
if(this.disabledAfter)months=resetData.months;
|
||||
if(months)this.range.months=months;
|
||||
obj={
|
||||
year,
|
||||
month
|
||||
}
|
||||
break;
|
||||
case "day":
|
||||
result=full=`${year+'-'+month+'-'+day}`;
|
||||
if(this.disabledAfter){
|
||||
months=resetData.months;
|
||||
days=resetData.days;
|
||||
}else{
|
||||
if(leapYear||(month!=this.checkObj.month)||month==2){
|
||||
days=resetData.days;
|
||||
}
|
||||
}
|
||||
if(months)this.range.months=months;
|
||||
if(days)this.range.days=days;
|
||||
obj={
|
||||
year,
|
||||
month,
|
||||
day
|
||||
}
|
||||
break;
|
||||
case "hour":
|
||||
result=`${year+'-'+month+'-'+day+' '+hour}`;
|
||||
full=`${year+'-'+month+'-'+day+' '+hour+':00:00'}`;
|
||||
if(this.disabledAfter){
|
||||
months=resetData.months;
|
||||
days=resetData.days;
|
||||
hours=resetData.hours;
|
||||
}else{
|
||||
if(leapYear||(month!=this.checkObj.month)||month==2){
|
||||
days=resetData.days;
|
||||
}
|
||||
}
|
||||
if(months)this.range.months=months;
|
||||
if(days)this.range.days=days;
|
||||
if(hours)this.range.hours=hours;
|
||||
obj={
|
||||
year,
|
||||
month,
|
||||
day,
|
||||
hour
|
||||
}
|
||||
break;
|
||||
case "minute":
|
||||
full=`${year+'-'+month+'-'+day+' '+hour+':'+minute+':00'}`;
|
||||
result=`${year+'-'+month+'-'+day+' '+hour+':'+minute}`;
|
||||
if(this.disabledAfter){
|
||||
months=resetData.months;
|
||||
days=resetData.days;
|
||||
hours=resetData.hours;
|
||||
minutes=resetData.minutes;
|
||||
}else{
|
||||
if(leapYear||(month!=this.checkObj.month)||month==2){
|
||||
days=resetData.days;
|
||||
}
|
||||
}
|
||||
if(months)this.range.months=months;
|
||||
if(days)this.range.days=days;
|
||||
if(hours)this.range.hours=hours;
|
||||
if(minutes)this.range.minutes=minutes;
|
||||
obj={
|
||||
year,
|
||||
month,
|
||||
day,
|
||||
hour,
|
||||
minute
|
||||
};
|
||||
break;
|
||||
case "second":
|
||||
result=full=`${year+'-'+month+'-'+day+' '+hour+':'+minute+':'+second}`;
|
||||
if(this.disabledAfter){
|
||||
months=resetData.months;
|
||||
days=resetData.days;
|
||||
hours=resetData.hours;
|
||||
minutes=resetData.minutes;
|
||||
//seconds=resetData.seconds;
|
||||
}else{
|
||||
if(leapYear||(month!=this.checkObj.month)||month==2){
|
||||
days=resetData.days;
|
||||
}
|
||||
}
|
||||
if(months)this.range.months=months;
|
||||
if(days)this.range.days=days;
|
||||
if(hours)this.range.hours=hours;
|
||||
if(minutes)this.range.minutes=minutes;
|
||||
//if(seconds)this.range.seconds=seconds;
|
||||
obj={
|
||||
year,
|
||||
month,
|
||||
day,
|
||||
hour,
|
||||
minute,
|
||||
second
|
||||
}
|
||||
break;
|
||||
}
|
||||
this.checkObj=obj;
|
||||
this.$emit("change",{
|
||||
result:result,
|
||||
value:full,
|
||||
obj:obj
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import "./w-picker.css";
|
||||
</style>
|
||||
345
uniapp/uni-app/components/w-picker/half-picker.vue
Normal file
345
uniapp/uni-app/components/w-picker/half-picker.vue
Normal file
@@ -0,0 +1,345 @@
|
||||
<template>
|
||||
<view class="w-picker-view">
|
||||
<picker-view class="d-picker-view" :indicator-style="itemHeight" :value="pickVal" @change="handlerChange">
|
||||
<picker-view-column>
|
||||
<view class="w-picker-item" v-for="(item,index) in range.years" :key="index">{{item}}年</view>
|
||||
</picker-view-column>
|
||||
<picker-view-column>
|
||||
<view class="w-picker-item" v-for="(item,index) in range.months" :key="index">{{item}}月</view>
|
||||
</picker-view-column>
|
||||
<picker-view-column>
|
||||
<view class="w-picker-item" v-for="(item,index) in range.days" :key="index">{{item}}日</view>
|
||||
</picker-view-column>
|
||||
<picker-view-column>
|
||||
<view class="w-picker-item" v-for="(item,index) in range.sections" :key="index">{{item}}</view>
|
||||
</picker-view-column>
|
||||
</picker-view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
pickVal:[],
|
||||
range:{},
|
||||
checkObj:{}
|
||||
};
|
||||
},
|
||||
props:{
|
||||
itemHeight:{
|
||||
type:String,
|
||||
default:"44px"
|
||||
},
|
||||
startYear:{
|
||||
type:String,
|
||||
default:""
|
||||
},
|
||||
endYear:{
|
||||
type:String,
|
||||
default:""
|
||||
},
|
||||
value:{
|
||||
type:[String,Array,Number],
|
||||
default:""
|
||||
},
|
||||
current:{//是否默认选中当前日期
|
||||
type:Boolean,
|
||||
default:false
|
||||
},
|
||||
disabledAfter:{//是否禁用当前之后的日期
|
||||
type:Boolean,
|
||||
default:false
|
||||
}
|
||||
},
|
||||
watch:{
|
||||
value(val){
|
||||
this.initData();
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.initData();
|
||||
},
|
||||
methods:{
|
||||
formatNum(n){
|
||||
return (Number(n)<10?'0'+Number(n):Number(n)+'');
|
||||
},
|
||||
checkValue(value){
|
||||
let strReg=/^\d{4}-\d{2}-\d{2} [\u4e00-\u9fa5]{2}$/,example;
|
||||
if(!strReg.test(value)){
|
||||
console.log(new Error("请传入与mode、fields匹配的value值,例value="+example+""))
|
||||
}
|
||||
return strReg.test(value);
|
||||
},
|
||||
resetData(year,month,day){
|
||||
let curDate=this.getCurrenDate();
|
||||
let curFlag=this.current;
|
||||
let curYear=curDate.curYear;
|
||||
let curMonth=curDate.curMonth;
|
||||
let curDay=curDate.curDay;
|
||||
let curHour=curDate.curHour;
|
||||
let months=[],days=[],sections=[];
|
||||
let disabledAfter=this.disabledAfter;
|
||||
let monthsLen=disabledAfter?(year*1<curYear?12:curMonth):12;
|
||||
let totalDays=new Date(year,month,0).getDate();//计算当月有几天;
|
||||
let daysLen=disabledAfter?((year*1<curYear||month*1<curMonth)?totalDays:curDay):totalDays;
|
||||
let sectionFlag=disabledAfter?((year*1<curYear||month*1<curMonth||day*1<curDay)==true?false:true):(curHour>12==true?true:false);
|
||||
sections=["上午","下午"];
|
||||
for(let month=1;month<=monthsLen;month++){
|
||||
months.push(this.formatNum(month));
|
||||
};
|
||||
for(let day=1;day<=daysLen;day++){
|
||||
days.push(this.formatNum(day));
|
||||
}
|
||||
if(sectionFlag){
|
||||
sections=["上午"];
|
||||
}
|
||||
return{
|
||||
months,
|
||||
days,
|
||||
sections
|
||||
}
|
||||
},
|
||||
getData(dVal){
|
||||
//用来处理初始化数据
|
||||
let curFlag=this.current;
|
||||
let disabledAfter=this.disabledAfter;
|
||||
let curDate=this.getCurrenDate();
|
||||
let curYear=curDate.curYear;
|
||||
let curMonthdays=curDate.curMonthdays;
|
||||
let curMonth=curDate.curMonth;
|
||||
let curDay=curDate.curDay;
|
||||
let curHour=curDate.curHour;
|
||||
let defaultDate=this.getDefaultDate();
|
||||
let startYear=this.getStartDate().getFullYear();
|
||||
let endYear=this.getEndDate().getFullYear();
|
||||
let years=[],months=[],days=[],sections=[];
|
||||
let year=dVal[0]*1;
|
||||
let month=dVal[1]*1;
|
||||
let day=dVal[2]*1;
|
||||
let monthsLen=disabledAfter?(year<curYear?12:curDate.curMonth):12;
|
||||
let daysLen=disabledAfter?((year<curYear||month<curMonth)?defaultDate.defaultDays:curDay):(curFlag?curMonthdays:defaultDate.defaultDays);
|
||||
let sectionFlag=disabledAfter?((year*1<curYear||month*1<curMonth||day*1<curDay)==true?false:true):(curHour>12==true?true:false);
|
||||
for(let year=startYear;year<=(disabledAfter?curYear:endYear);year++){
|
||||
years.push(year.toString())
|
||||
}
|
||||
for(let month=1;month<=monthsLen;month++){
|
||||
months.push(this.formatNum(month));
|
||||
}
|
||||
for(let day=1;day<=daysLen;day++){
|
||||
days.push(this.formatNum(day));
|
||||
}
|
||||
if(sectionFlag){
|
||||
sections=["下午"];
|
||||
}else{
|
||||
sections=["上午","下午"];
|
||||
}
|
||||
return {
|
||||
years,
|
||||
months,
|
||||
days,
|
||||
sections
|
||||
}
|
||||
},
|
||||
getCurrenDate(){
|
||||
let curDate=new Date();
|
||||
let curYear=curDate.getFullYear();
|
||||
let curMonth=curDate.getMonth()+1;
|
||||
let curMonthdays=new Date(curYear,curMonth,0).getDate();
|
||||
let curDay=curDate.getDate();
|
||||
let curHour=curDate.getHours();
|
||||
let curSection="上午";
|
||||
if(curHour>=12){
|
||||
curSection="下午";
|
||||
}
|
||||
return{
|
||||
curDate,
|
||||
curYear,
|
||||
curMonth,
|
||||
curMonthdays,
|
||||
curDay,
|
||||
curHour,
|
||||
curSection
|
||||
}
|
||||
},
|
||||
getDefaultDate(){
|
||||
let value=this.value;
|
||||
let reg=/-/g;
|
||||
let defaultDate=value?new Date(value.split(" ")[0].replace(reg,"/")):new Date();
|
||||
let defaultYear=defaultDate.getFullYear();
|
||||
let defaultMonth=defaultDate.getMonth()+1;
|
||||
let defaultDay=defaultDate.getDate();
|
||||
let defaultDays=new Date(defaultYear,defaultMonth,0).getDate()*1;
|
||||
return{
|
||||
defaultDate,
|
||||
defaultYear,
|
||||
defaultMonth,
|
||||
defaultDay,
|
||||
defaultDays
|
||||
}
|
||||
},
|
||||
getStartDate(){
|
||||
let start=this.startYear;
|
||||
let startDate="";
|
||||
let reg=/-/g;
|
||||
if(start){
|
||||
startDate=new Date(start+"/01/01");
|
||||
}else{
|
||||
startDate=new Date("1970/01/01");
|
||||
}
|
||||
return startDate;
|
||||
},
|
||||
getEndDate(){
|
||||
let end=this.endYear;
|
||||
let reg=/-/g;
|
||||
let endDate="";
|
||||
if(end){
|
||||
endDate=new Date(end+"/12/31");
|
||||
}else{
|
||||
endDate=new Date();
|
||||
}
|
||||
return endDate;
|
||||
},
|
||||
getDval(){
|
||||
let value=this.value;
|
||||
let dVal=null;
|
||||
let aDate=new Date();
|
||||
let year=this.formatNum(aDate.getFullYear());
|
||||
let month=this.formatNum(aDate.getMonth()+1);
|
||||
let day=this.formatNum(aDate.getDate());
|
||||
let hour=aDate.getHours();
|
||||
let section="上午";
|
||||
if(hour>=12)section="下午";
|
||||
if(value){
|
||||
let flag=this.checkValue(value);
|
||||
if(!flag){
|
||||
dVal=[year,month,day,section]
|
||||
}else{
|
||||
let v=value.split(" ");
|
||||
dVal=[...v[0].split("-"),v[1]];
|
||||
}
|
||||
}else{
|
||||
dVal=[year,month,day,section]
|
||||
}
|
||||
return dVal;
|
||||
},
|
||||
initData(){
|
||||
let startDate,endDate,startYear,endYear,startMonth,endMonth,startDay,endDay;
|
||||
let years=[],months=[],days=[],sections=[];
|
||||
let dVal=[],pickVal=[];
|
||||
let value=this.value;
|
||||
let reg=/-/g;
|
||||
let range={};
|
||||
let result="",full="",year,month,day,section,obj={};
|
||||
let defaultDate=this.getDefaultDate();
|
||||
let defaultYear=defaultDate.defaultYear;
|
||||
let defaultMonth=defaultDate.defaultMonth;
|
||||
let defaultDay=defaultDate.defaultDay;
|
||||
let defaultDays=defaultDate.defaultDays;
|
||||
let curFlag=this.current;
|
||||
let disabledAfter=this.disabledAfter;
|
||||
let curDate=this.getCurrenDate();
|
||||
let curYear=curDate.curYear;
|
||||
let curMonth=curDate.curMonth;
|
||||
let curMonthdays=curDate.curMonthdays;
|
||||
let curDay=curDate.curDay;
|
||||
let curSection=curDate.curSection;
|
||||
let dateData=[];
|
||||
dVal=this.getDval();
|
||||
startDate=this.getStartDate();
|
||||
endDate=this.getEndDate();
|
||||
startYear=startDate.getFullYear();
|
||||
startMonth=startDate.getMonth();
|
||||
startDay=startDate.getDate();
|
||||
endYear=endDate.getFullYear();
|
||||
endMonth=endDate.getMonth();
|
||||
endDay=endDate.getDate();
|
||||
dateData=this.getData(dVal);
|
||||
years=dateData.years;
|
||||
months=dateData.months;
|
||||
days=dateData.days;
|
||||
sections=dateData.sections;
|
||||
pickVal=disabledAfter?[
|
||||
dVal[0]&&years.indexOf(dVal[0])!=-1?years.indexOf(dVal[0]):0,
|
||||
dVal[1]&&months.indexOf(dVal[1])!=-1?months.indexOf(dVal[1]):0,
|
||||
dVal[2]&&days.indexOf(dVal[2])!=-1?days.indexOf(dVal[2]):0,
|
||||
dVal[3]&§ions.indexOf(dVal[3])!=-1?sections.indexOf(dVal[3]):0
|
||||
]:(curFlag?[
|
||||
years.indexOf(curYear+''),
|
||||
months.indexOf(this.formatNum(curMonth)),
|
||||
days.indexOf(this.formatNum(curDay)),
|
||||
sections.indexOf(curSection),
|
||||
]:[
|
||||
dVal[0]&&years.indexOf(dVal[0])!=-1?years.indexOf(dVal[0]):0,
|
||||
dVal[1]&&months.indexOf(dVal[1])!=-1?months.indexOf(dVal[1]):0,
|
||||
dVal[2]&&days.indexOf(dVal[2])!=-1?days.indexOf(dVal[2]):0,
|
||||
dVal[3]&§ions.indexOf(dVal[3])!=-1?sections.indexOf(dVal[3]):0
|
||||
]);
|
||||
range={years,months,days,sections};
|
||||
year=dVal[0]?dVal[0]:years[0];
|
||||
month=dVal[1]?dVal[1]:months[0];
|
||||
day=dVal[2]?dVal[2]:days[0];
|
||||
section=dVal[3]?dVal[3]:sections[0];
|
||||
result=full=`${year+'-'+month+'-'+day+' '+section}`;
|
||||
obj={
|
||||
year,
|
||||
month,
|
||||
day,
|
||||
section
|
||||
}
|
||||
this.range=range;
|
||||
this.checkObj=obj;
|
||||
this.$nextTick(()=>{
|
||||
this.pickVal=pickVal;
|
||||
});
|
||||
this.$emit("change",{
|
||||
result:result,
|
||||
value:full,
|
||||
obj:obj
|
||||
})
|
||||
},
|
||||
handlerChange(e){
|
||||
let arr=[...e.detail.value];
|
||||
let data=this.range;
|
||||
let year="",month="",day="",section="";
|
||||
let result="",full="",obj={};
|
||||
let months=null,days=null,sections=null;
|
||||
let disabledAfter=this.disabledAfter;
|
||||
year=(arr[0]||arr[0]==0)?data.years[arr[0]]||data.years[data.years.length-1]:"";
|
||||
month=(arr[1]||arr[1]==0)?data.months[arr[1]]||data.months[data.months.length-1]:"";
|
||||
day=(arr[2]||arr[2]==0)?data.days[arr[2]]||data.days[data.days.length-1]:"";
|
||||
section=(arr[3]||arr[3]==0)?data.sections[arr[3]]||data.sections[data.sections.length-1]:"";
|
||||
result=full=`${year+'-'+month+'-'+day+' '+section}`;
|
||||
let resetData=this.resetData(year,month,day);
|
||||
if(this.disabledAfter){
|
||||
months=resetData.months;
|
||||
days=resetData.days;
|
||||
sections=resetData.sections;
|
||||
}else{
|
||||
if(year%4==0||(month!=this.checkObj.month)){
|
||||
days=resetData.days;
|
||||
}
|
||||
}
|
||||
if(months)this.range.months=months;
|
||||
if(days)this.range.days=days;
|
||||
if(sections)this.range.sections=sections;
|
||||
obj={
|
||||
year,
|
||||
month,
|
||||
day,
|
||||
section
|
||||
}
|
||||
this.checkObj=obj;
|
||||
this.$emit("change",{
|
||||
result:result,
|
||||
value:full,
|
||||
obj:obj
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import "./w-picker.css";
|
||||
</style>
|
||||
274
uniapp/uni-app/components/w-picker/linkage-picker.vue
Normal file
274
uniapp/uni-app/components/w-picker/linkage-picker.vue
Normal file
@@ -0,0 +1,274 @@
|
||||
<template>
|
||||
<view class="w-picker-view">
|
||||
<picker-view class="d-picker-view" :indicator-style="itemHeight" :value="pickVal" @change="handlerChange">
|
||||
<picker-view-column v-for="(group,gIndex) in range" :key="gIndex">
|
||||
<view class="w-picker-item" v-for="(item,index) in group" :key="index">{{item[nodeKey]}}</view>
|
||||
</picker-view-column>
|
||||
</picker-view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
pickVal:[],
|
||||
range:[],
|
||||
checkObj:{}
|
||||
};
|
||||
},
|
||||
props:{
|
||||
itemHeight:{
|
||||
type:String,
|
||||
default:"44px"
|
||||
},
|
||||
value:{
|
||||
type:[Array,String],
|
||||
default:""
|
||||
},
|
||||
defaultType:{
|
||||
type:String,
|
||||
default:"label"
|
||||
},
|
||||
options:{
|
||||
type:Array,
|
||||
default(){
|
||||
return []
|
||||
}
|
||||
},
|
||||
defaultProps:{
|
||||
type:Object,
|
||||
default(){
|
||||
return{
|
||||
lable:"label",
|
||||
value:"value",
|
||||
children:"children"
|
||||
}
|
||||
}
|
||||
},
|
||||
level:{
|
||||
//多级联动层级,表示几级联动
|
||||
type:[Number,String],
|
||||
default:2
|
||||
}
|
||||
},
|
||||
computed:{
|
||||
nodeKey(){
|
||||
return this.defaultProps.label;
|
||||
},
|
||||
nodeVal(){
|
||||
return this.defaultProps.value;
|
||||
},
|
||||
nodeChild(){
|
||||
return this.defaultProps.children;
|
||||
}
|
||||
},
|
||||
watch:{
|
||||
value(val){
|
||||
if(this.options.length!=0){
|
||||
this.initData();
|
||||
}
|
||||
},
|
||||
options(val){
|
||||
this.initData();
|
||||
}
|
||||
},
|
||||
created() {
|
||||
if(this.options.length!=0){
|
||||
this.initData();
|
||||
}
|
||||
},
|
||||
methods:{
|
||||
getData(){
|
||||
//用来处理初始化数据
|
||||
let options=this.options;
|
||||
let col1={},col2={},col3={},col4={};
|
||||
let arr1=options,arr2=[],arr3=[],arr4=[];
|
||||
let col1Index=0,col2Index=0,col3Index=0,col4Index=0;
|
||||
let a1="",a2="",a3="",a4="";
|
||||
let dVal=[],obj={};
|
||||
let value=this.value;
|
||||
let data=[];
|
||||
a1=value[0];
|
||||
a2=value[1];
|
||||
if(this.level>2){
|
||||
a3=value[2];
|
||||
}
|
||||
if(this.level>3){
|
||||
a4=value[3];
|
||||
};
|
||||
/*第1列*/
|
||||
col1Index=arr1.findIndex((v)=>{
|
||||
return v[this.defaultType]==a1
|
||||
});
|
||||
col1Index=value?(col1Index!=-1?col1Index:0):0;
|
||||
col1=arr1[col1Index];
|
||||
|
||||
/*第2列*/
|
||||
arr2=arr1[col1Index][this.nodeChild];
|
||||
col2Index=arr2.findIndex((v)=>{
|
||||
return v[this.defaultType]==a2
|
||||
});
|
||||
col2Index=value?(col2Index!=-1?col2Index:0):0;
|
||||
col2=arr2[col2Index];
|
||||
|
||||
/*第3列*/
|
||||
if(this.level>2){
|
||||
arr3=arr2[col2Index][this.nodeChild];
|
||||
col3Index=arr3.findIndex((v)=>{
|
||||
return v[this.defaultType]==a3;
|
||||
});
|
||||
col3Index=value?(col3Index!=-1?col3Index:0):0;
|
||||
col3=arr3[col3Index];
|
||||
};
|
||||
|
||||
|
||||
/*第4列*/
|
||||
if(this.level>3){
|
||||
arr4=arr3[col4Index][this.nodeChild];
|
||||
col4Index=arr4.findIndex((v)=>{
|
||||
return v[this.defaultType]==a4;
|
||||
});
|
||||
col4Index=value?(col4Index!=-1?col4Index:0):0;
|
||||
col4=arr4[col4Index];
|
||||
};
|
||||
switch(this.level*1){
|
||||
case 2:
|
||||
dVal=[col1Index,col2Index];
|
||||
obj={
|
||||
col1,
|
||||
col2
|
||||
}
|
||||
data=[arr1,arr2];
|
||||
break;
|
||||
case 3:
|
||||
dVal=[col1Index,col2Index,col3Index];
|
||||
obj={
|
||||
col1,
|
||||
col2,
|
||||
col3
|
||||
}
|
||||
data=[arr1,arr2,arr3];
|
||||
break;
|
||||
case 4:
|
||||
dVal=[col1Index,col2Index,col3Index,col4Index];
|
||||
obj={
|
||||
col1,
|
||||
col2,
|
||||
col3,
|
||||
col4
|
||||
}
|
||||
data=[arr1,arr2,arr3,arr4];
|
||||
break
|
||||
}
|
||||
return {
|
||||
data,
|
||||
dVal,
|
||||
obj
|
||||
}
|
||||
},
|
||||
initData(){
|
||||
let dataData=this.getData();
|
||||
let data=dataData.data;
|
||||
let arr1=data[0];
|
||||
let arr2=data[1];
|
||||
let arr3=data[2]||[];
|
||||
let arr4=data[3]||[];
|
||||
let obj=dataData.obj;
|
||||
let col1=obj.col1,col2=obj.col2,col3=obj.col3||{},col4=obj.col4||{};
|
||||
let result="",value=[];
|
||||
let range=[];
|
||||
switch(this.level){
|
||||
case 2:
|
||||
value=[col1[this.nodeVal],col2[this.nodeVal]];
|
||||
result=`${col1[this.nodeKey]+col2[this.nodeKey]}`;
|
||||
range=[arr1,arr2];
|
||||
break;
|
||||
case 3:
|
||||
value=[col1[this.nodeVal],col2[this.nodeVal],col3[this.nodeVal]];
|
||||
result=`${col1[this.nodeKey]+col2[this.nodeKey]+col3[this.nodeKey]}`;
|
||||
range=[arr1,arr2,arr3];
|
||||
break;
|
||||
case 4:
|
||||
value=[col1[this.nodeVal],col2[this.nodeVal],col3[this.nodeVal],col4[this.nodeVal]];
|
||||
result=`${col1[this.nodeKey]+col2[this.nodeKey]+col3[this.nodeKey]+col4[this.nodeKey]}`;
|
||||
range=[arr1,arr2,arr3,arr4];
|
||||
break;
|
||||
}
|
||||
this.range=range;
|
||||
this.checkObj=obj;
|
||||
this.$nextTick(()=>{
|
||||
this.pickVal=dataData.dVal;
|
||||
});
|
||||
this.$emit("change",{
|
||||
result:result,
|
||||
value:value,
|
||||
obj:obj
|
||||
})
|
||||
},
|
||||
handlerChange(e){
|
||||
let arr=[...e.detail.value];
|
||||
let col1Index=arr[0],col2Index=arr[1],col3Index=arr[2]||0,col4Index=arr[3]||0;
|
||||
let arr1=[],arr2=[],arr3=[],arr4=[];
|
||||
let col1,col2,col3,col4,obj={};
|
||||
let result="",value=[];
|
||||
arr1=this.options;
|
||||
arr2=(arr1[col1Index]&&arr1[col1Index][this.nodeChild])||arr1[arr1.length-1][this.nodeChild]||[];
|
||||
col1=arr1[col1Index]||arr1[arr1.length-1]||{};
|
||||
col2=arr2[col2Index]||arr2[arr2.length-1]||{};
|
||||
if(this.level>2){
|
||||
arr3=(arr2[col2Index]&&arr2[col2Index][this.nodeChild])||arr2[arr2.length-1][this.nodeChild];
|
||||
col3=arr3[col3Index]||arr3[arr3.length-1]||{};
|
||||
}
|
||||
if(this.level>3){
|
||||
arr4=(arr3[col3Index]&&arr3[col3Index][this.nodeChild])||arr3[arr3.length-1][this.nodeChild]||[];
|
||||
col4=arr4[col4Index]||arr4[arr4.length-1]||{};
|
||||
}
|
||||
switch(this.level){
|
||||
case 2:
|
||||
obj={
|
||||
col1,
|
||||
col2
|
||||
}
|
||||
this.range=[arr1,arr2];
|
||||
result=`${(col1[this.nodeKey]||'')+(col2[this.nodeKey]||'')}`;
|
||||
value=[col1[this.nodeVal]||'',col2[this.nodeVal]||''];
|
||||
break;
|
||||
case 3:
|
||||
obj={
|
||||
col1,
|
||||
col2,
|
||||
col3
|
||||
}
|
||||
this.range=[arr1,arr2,arr3];
|
||||
result=`${(col1[this.nodeKey]||'')+(col2[this.nodeKey]||'')+(col3[this.nodeKey]||'')}`;
|
||||
value=[col1[this.nodeVal]||'',col2[this.nodeVal]||'',col3[this.nodeVal]||''];
|
||||
break;
|
||||
case 4:
|
||||
obj={
|
||||
col1,
|
||||
col2,
|
||||
col3,
|
||||
col4
|
||||
}
|
||||
this.range=[arr1,arr2,arr3,arr4];
|
||||
result=`${(col1[this.nodeKey]||'')+(col2[this.nodeKey]||'')+(col3[this.nodeKey]||'')+(col4[this.nodeKey]||'')}`;
|
||||
value=[col1[this.nodeVal]||'',col2[this.nodeVal]||'',col3[this.nodeVal]||'',col4[this.nodeVal]||''];
|
||||
break;
|
||||
}
|
||||
this.checkObj=obj;
|
||||
this.pickVal=arr;
|
||||
this.$emit("change",{
|
||||
result:result,
|
||||
value:value,
|
||||
obj:obj
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import "./w-picker.css";
|
||||
</style>
|
||||
|
||||
344
uniapp/uni-app/components/w-picker/range-picker.vue
Normal file
344
uniapp/uni-app/components/w-picker/range-picker.vue
Normal file
@@ -0,0 +1,344 @@
|
||||
<template>
|
||||
<view class="w-picker-view">
|
||||
<picker-view class="d-picker-view" :indicator-style="itemHeight" :value="pickVal" @change="handlerChange">
|
||||
<picker-view-column class="w-picker-flex2">
|
||||
<view class="w-picker-item" v-for="(item,index) in range.fyears" :key="index">{{item}}年</view>
|
||||
</picker-view-column>
|
||||
<picker-view-column class="w-picker-flex2">
|
||||
<view class="w-picker-item" v-for="(item,index) in range.fmonths" :key="index">{{item}}月</view>
|
||||
</picker-view-column>
|
||||
<picker-view-column class="w-picker-flex2">
|
||||
<view class="w-picker-item" v-for="(item,index) in range.fdays" :key="index">{{item}}日</view>
|
||||
</picker-view-column>
|
||||
<picker-view-column class="w-picker-flex1">
|
||||
<view class="w-picker-item">-</view>
|
||||
</picker-view-column>
|
||||
<picker-view-column class="w-picker-flex2">
|
||||
<view class="w-picker-item" v-for="(item,index) in range.tyears" :key="index">{{item}}年</view>
|
||||
</picker-view-column>
|
||||
<picker-view-column class="w-picker-flex2">
|
||||
<view class="w-picker-item" v-for="(item,index) in range.tmonths" :key="index">{{item}}月</view>
|
||||
</picker-view-column>
|
||||
<picker-view-column class="w-picker-flex2">
|
||||
<view class="w-picker-item" v-for="(item,index) in range.tdays" :key="index">{{item}}日</view>
|
||||
</picker-view-column>
|
||||
</picker-view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
pickVal:[],
|
||||
range:{},
|
||||
checkObj:{}
|
||||
};
|
||||
},
|
||||
props:{
|
||||
itemHeight:{
|
||||
type:String,
|
||||
default:"44px"
|
||||
},
|
||||
value:{
|
||||
type:[String,Array],
|
||||
default(){
|
||||
return []
|
||||
}
|
||||
},
|
||||
current:{//是否默认选中当前日期
|
||||
type:Boolean,
|
||||
default:false
|
||||
},
|
||||
startYear:{
|
||||
type:[String,Number],
|
||||
default:1970
|
||||
},
|
||||
endYear:{
|
||||
type:[String,Number],
|
||||
default:new Date().getFullYear()
|
||||
}
|
||||
},
|
||||
watch:{
|
||||
value(val){
|
||||
this.initData();
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.initData();
|
||||
},
|
||||
methods:{
|
||||
formatNum(n){
|
||||
return (Number(n)<10?'0'+Number(n):Number(n)+'');
|
||||
},
|
||||
checkValue(value){
|
||||
let strReg=/^\d{4}-\d{2}-\d{2}$/,example="2020-04-03";
|
||||
if(!strReg.test(value[0])||!strReg.test(value[1])){
|
||||
console.log(new Error("请传入与mode匹配的value值,例["+example+","+example+"]"))
|
||||
}
|
||||
return strReg.test(value[0])&&strReg.test(value[1]);
|
||||
},
|
||||
resetToData(fmonth,fday,tyear,tmonth){
|
||||
let range=this.range;
|
||||
let tmonths=[],tdays=[];
|
||||
let yearFlag=tyear!=range.tyears[0];
|
||||
let monthFlag=tyear!=range.tyears[0]||tmonth!=range.tmonths[0];
|
||||
let ttotal=new Date(tyear,tmonth,0).getDate();
|
||||
for(let i=yearFlag?1:fmonth*1;i<=12;i++){
|
||||
tmonths.push(this.formatNum(i))
|
||||
}
|
||||
for(let i=monthFlag?1:fday*1;i<=ttotal;i++){
|
||||
tdays.push(this.formatNum(i))
|
||||
}
|
||||
return{
|
||||
tmonths,
|
||||
tdays
|
||||
}
|
||||
},
|
||||
resetData(fyear,fmonth,fday,tyear,tmonth){
|
||||
let fyears=[],fmonths=[],fdays=[],tyears=[],tmonths=[],tdays=[];
|
||||
let startYear=this.startYear;
|
||||
let endYear=this.endYear;
|
||||
let ftotal=new Date(fyear,fmonth,0).getDate();
|
||||
let ttotal=new Date(tyear,tmonth,0).getDate();
|
||||
for(let i=startYear*1;i<=endYear;i++){
|
||||
fyears.push(this.formatNum(i))
|
||||
}
|
||||
for(let i=1;i<=12;i++){
|
||||
fmonths.push(this.formatNum(i))
|
||||
}
|
||||
for(let i=1;i<=ftotal;i++){
|
||||
fdays.push(this.formatNum(i))
|
||||
}
|
||||
for(let i=fyear*1;i<=endYear;i++){
|
||||
tyears.push(this.formatNum(i))
|
||||
}
|
||||
for(let i=fmonth*1;i<=12;i++){
|
||||
tmonths.push(this.formatNum(i))
|
||||
}
|
||||
for(let i=fday*1;i<=ttotal;i++){
|
||||
tdays.push(this.formatNum(i))
|
||||
}
|
||||
return {
|
||||
fyears,
|
||||
fmonths,
|
||||
fdays,
|
||||
tyears,
|
||||
tmonths,
|
||||
tdays
|
||||
}
|
||||
},
|
||||
getData(dVal){
|
||||
let start=this.startYear*1;
|
||||
let end=this.endYear*1;
|
||||
let value=dVal;
|
||||
let flag=this.current;
|
||||
let aToday=new Date();
|
||||
let tYear,tMonth,tDay,tHours,tMinutes,tSeconds,pickVal=[];
|
||||
let initstartDate=new Date(start.toString());
|
||||
let endDate=new Date(end.toString());
|
||||
if(start>end){
|
||||
initstartDate=new Date(end.toString());
|
||||
endDate=new Date(start.toString());
|
||||
};
|
||||
let startYear=initstartDate.getFullYear();
|
||||
let startMonth=initstartDate.getMonth()+1;
|
||||
let endYear=endDate.getFullYear();
|
||||
let fyears=[],fmonths=[],fdays=[],tyears=[],tmonths=[],tdays=[],returnArr=[],startDVal=[],endDVal=[];
|
||||
let curMonth=flag?value[1]*1:(startDVal[1]*1+1);
|
||||
let curMonth1=flag?value[5][1]*1:(value[5]*1+1);
|
||||
let totalDays=new Date(value[0],value[1],0).getDate();
|
||||
let totalDays1=new Date(value[4],value[5],0).getDate();
|
||||
for(let s=startYear;s<=endYear;s++){
|
||||
fyears.push(this.formatNum(s));
|
||||
};
|
||||
for(let m=1;m<=12;m++){
|
||||
fmonths.push(this.formatNum(m));
|
||||
};
|
||||
for(let d=1;d<=totalDays;d++){
|
||||
fdays.push(this.formatNum(d));
|
||||
};
|
||||
for(let s=value[0]*1;s<=endYear;s++){
|
||||
tyears.push(this.formatNum(s));
|
||||
};
|
||||
|
||||
if(value[4]*1>value[0]*1){
|
||||
for(let m=1;m<=12;m++){
|
||||
tmonths.push(this.formatNum(m));
|
||||
};
|
||||
for(let d=1;d<=totalDays1;d++){
|
||||
tdays.push(this.formatNum(d));
|
||||
};
|
||||
}else{
|
||||
for(let m=value[1]*1;m<=12;m++){
|
||||
tmonths.push(this.formatNum(m));
|
||||
};
|
||||
for(let d=value[2]*1;d<=totalDays1;d++){
|
||||
tdays.push(this.formatNum(d));
|
||||
};
|
||||
};
|
||||
|
||||
pickVal=[
|
||||
fyears.indexOf(value[0])==-1?0:fyears.indexOf(value[0]),
|
||||
fmonths.indexOf(value[1])==-1?0:fmonths.indexOf(value[1]),
|
||||
fdays.indexOf(value[2])==-1?0:fdays.indexOf(value[2]),
|
||||
0,
|
||||
tyears.indexOf(value[4])==-1?0:tyears.indexOf(value[4]),
|
||||
tmonths.indexOf(value[5])==-1?0:tmonths.indexOf(value[5]),
|
||||
tdays.indexOf(value[6])==-1?0:tdays.indexOf(value[6])
|
||||
];
|
||||
return {
|
||||
fyears,
|
||||
fmonths,
|
||||
fdays,
|
||||
tyears,
|
||||
tmonths,
|
||||
tdays,
|
||||
pickVal
|
||||
}
|
||||
},
|
||||
getDval(){
|
||||
let value=this.value;
|
||||
let fields=this.fields;
|
||||
let dVal=null;
|
||||
let aDate=new Date();
|
||||
let fyear=this.formatNum(aDate.getFullYear());
|
||||
let fmonth=this.formatNum(aDate.getMonth()+1);
|
||||
let fday=this.formatNum(aDate.getDate());
|
||||
let tyear=this.formatNum(aDate.getFullYear());
|
||||
let tmonth=this.formatNum(aDate.getMonth()+1);
|
||||
let tday=this.formatNum(aDate.getDate());
|
||||
if(value&&value.length>0){
|
||||
let flag=this.checkValue(value);
|
||||
if(!flag){
|
||||
dVal=[fyear,fmonth,fday,"-",tyear,tmonth,tday]
|
||||
}else{
|
||||
dVal=[...value[0].split("-"),"-",...value[1].split("-")];
|
||||
}
|
||||
}else{
|
||||
dVal=[fyear,fmonth,fday,"-",tyear,tmonth,tday]
|
||||
}
|
||||
return dVal;
|
||||
},
|
||||
initData(){
|
||||
let range=[],pickVal=[];
|
||||
let result="",full="",obj={};
|
||||
let dVal=this.getDval();
|
||||
let dateData=this.getData(dVal);
|
||||
let fyears=[],fmonths=[],fdays=[],tyears=[],tmonths=[],tdays=[];
|
||||
let fyear,fmonth,fday,tyear,tmonth,tday;
|
||||
pickVal=dateData.pickVal;
|
||||
fyears=dateData.fyears;
|
||||
fmonths=dateData.fmonths;
|
||||
fdays=dateData.fdays;
|
||||
tyears=dateData.tyears;
|
||||
tmonths=dateData.tmonths;
|
||||
tdays=dateData.tdays;
|
||||
range={
|
||||
fyears,
|
||||
fmonths,
|
||||
fdays,
|
||||
tyears,
|
||||
tmonths,
|
||||
tdays,
|
||||
}
|
||||
fyear=range.fyears[pickVal[0]];
|
||||
fmonth=range.fmonths[pickVal[1]];
|
||||
fday=range.fdays[pickVal[2]];
|
||||
tyear=range.tyears[pickVal[4]];
|
||||
tmonth=range.tmonths[pickVal[5]];
|
||||
tday=range.tdays[pickVal[6]];
|
||||
obj={
|
||||
fyear,
|
||||
fmonth,
|
||||
fday,
|
||||
tyear,
|
||||
tmonth,
|
||||
tday
|
||||
}
|
||||
result=`${fyear+'-'+fmonth+'-'+fday+'至'+tyear+'-'+tmonth+'-'+tday}`;
|
||||
this.range=range;
|
||||
this.checkObj=obj;
|
||||
this.$nextTick(()=>{
|
||||
this.pickVal=pickVal;
|
||||
});
|
||||
this.$emit("change",{
|
||||
result:result,
|
||||
value:result.split("至"),
|
||||
obj:obj
|
||||
})
|
||||
},
|
||||
handlerChange(e){
|
||||
let arr=[...e.detail.value];
|
||||
let result="",full="",obj={};
|
||||
let year="",month="",day="",hour="",minute="",second="",note=[],province,city,area;
|
||||
let checkObj=this.checkObj;
|
||||
let days=[],months=[],endYears=[],endMonths=[],endDays=[],startDays=[];
|
||||
let mode=this.mode;
|
||||
let col1,col2,col3,d,a,h,m;
|
||||
let xDate=new Date().getTime();
|
||||
let range=this.range;
|
||||
let fyear=range.fyears[arr[0]]||range.fyears[range.fyears.length-1];
|
||||
let fmonth=range.fmonths[arr[1]]||range.fmonths[range.fmonths.length-1];
|
||||
let fday=range.fdays[arr[2]]||range.fdays[range.fdays.length-1];
|
||||
let tyear=range.tyears[arr[4]]||range.tyears[range.tyears.length-1];
|
||||
let tmonth=range.tmonths[arr[5]]||range.tmonths[range.tmonths.length-1];
|
||||
let tday=range.tdays[arr[6]]||range.tdays[range.tdays.length-1];
|
||||
let resetData=this.resetData(fyear,fmonth,fday,tyear,tmonth);
|
||||
if(fyear!=checkObj.fyear||fmonth!=checkObj.fmonth||fday!=checkObj.fday){
|
||||
arr[4]=0;
|
||||
arr[5]=0;
|
||||
arr[6]=0;
|
||||
range.tyears=resetData.tyears;
|
||||
range.tmonths=resetData.tmonths;
|
||||
range.tdays=resetData.tdays;
|
||||
tyear=range.tyears[0];
|
||||
checkObj.tyears=range.tyears[0];
|
||||
tmonth=range.tmonths[0];
|
||||
checkObj.tmonths=range.tmonths[0];
|
||||
tday=range.tdays[0];
|
||||
checkObj.tdays=range.tdays[0];
|
||||
}
|
||||
if(fyear!=checkObj.fyear||fmonth!=checkObj.fmonth){
|
||||
range.fdays=resetData.fdays;
|
||||
};
|
||||
if(tyear!=checkObj.tyear){
|
||||
arr[5]=0;
|
||||
arr[6]=0;
|
||||
let toData=this.resetToData(fmonth,fday,tyear,tmonth);
|
||||
range.tmonths=toData.tmonths;
|
||||
range.tdays=toData.tdays;
|
||||
tmonth=range.tmonths[0];
|
||||
checkObj.tmonths=range.tmonths[0];
|
||||
tday=range.tdays[0];
|
||||
checkObj.tdays=range.tdays[0];
|
||||
};
|
||||
if(tmonth!=checkObj.tmonth){
|
||||
arr[6]=0;
|
||||
let toData=this.resetToData(fmonth,fday,tyear,tmonth);
|
||||
range.tdays=toData.tdays;
|
||||
tday=range.tdays[0];
|
||||
checkObj.tdays=range.tdays[0];
|
||||
};
|
||||
result=`${fyear+'-'+fmonth+'-'+fday+'至'+tyear+'-'+tmonth+'-'+tday}`;
|
||||
obj={
|
||||
fyear,fmonth,fday,tyear,tmonth,tday
|
||||
}
|
||||
this.checkObj=obj;
|
||||
this.$nextTick(()=>{
|
||||
this.pickVal=arr;
|
||||
})
|
||||
this.$emit("change",{
|
||||
result:result,
|
||||
value:result.split("至"),
|
||||
obj:obj
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import "./w-picker.css";
|
||||
</style>
|
||||
183
uniapp/uni-app/components/w-picker/region-picker.vue
Normal file
183
uniapp/uni-app/components/w-picker/region-picker.vue
Normal file
@@ -0,0 +1,183 @@
|
||||
<template>
|
||||
<view class="w-picker-view">
|
||||
<picker-view class="d-picker-view" :indicator-style="itemHeight" :value="pickVal" @change="handlerChange">
|
||||
<picker-view-column>
|
||||
<view class="w-picker-item" v-for="(item,index) in range.provinces" :key="index">{{item.label}}</view>
|
||||
</picker-view-column>
|
||||
<picker-view-column>
|
||||
<view class="w-picker-item" v-for="(item,index) in range.citys" :key="index">{{item.label}}</view>
|
||||
</picker-view-column>
|
||||
<picker-view-column v-if="!hideArea">
|
||||
<view class="w-picker-item" v-for="(item,index) in range.areas" :key="index">{{item.label}}</view>
|
||||
</picker-view-column>
|
||||
</picker-view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import areaData from "./areadata/areadata.js"
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
pickVal:[],
|
||||
range:{
|
||||
provinces:[],
|
||||
citys:[],
|
||||
areas:[]
|
||||
},
|
||||
checkObj:{}
|
||||
};
|
||||
},
|
||||
props:{
|
||||
itemHeight:{
|
||||
type:String,
|
||||
default:"44px"
|
||||
},
|
||||
value:{
|
||||
type:[Array,String],
|
||||
default:""
|
||||
},
|
||||
defaultType:{
|
||||
type:String,
|
||||
default:"label"
|
||||
},
|
||||
hideArea:{
|
||||
type:Boolean,
|
||||
default:false
|
||||
}
|
||||
},
|
||||
watch:{
|
||||
value(val){
|
||||
this.initData();
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.initData();
|
||||
},
|
||||
methods:{
|
||||
getData(){
|
||||
//用来处理初始化数据
|
||||
let provinces=areaData;
|
||||
let dVal=[];
|
||||
let value=this.value;
|
||||
let a1=value[0];//默认值省
|
||||
let a2=value[1];//默认值市
|
||||
let a3=value[2];//默认值区、县
|
||||
let province,city,area;
|
||||
let provinceIndex=provinces.findIndex((v)=>{
|
||||
return v[this.defaultType]==a1
|
||||
});
|
||||
provinceIndex=value?(provinceIndex!=-1?provinceIndex:0):0;
|
||||
let citys=provinces[provinceIndex].children;
|
||||
let cityIndex=citys.findIndex((v)=>{
|
||||
return v[this.defaultType]==a2
|
||||
});
|
||||
cityIndex=value?(cityIndex!=-1?cityIndex:0):0;
|
||||
let areas=citys[cityIndex].children;
|
||||
let areaIndex=areas.findIndex((v)=>{
|
||||
return v[this.defaultType]==a3;
|
||||
});
|
||||
areaIndex=value?(areaIndex!=-1?areaIndex:0):0;
|
||||
dVal=this.hideArea?[provinceIndex,cityIndex]:[provinceIndex,cityIndex,areaIndex];
|
||||
province=provinces[provinceIndex];
|
||||
city=citys[cityIndex];
|
||||
area=areas[areaIndex];
|
||||
let obj=this.hideArea?{
|
||||
province,
|
||||
city
|
||||
}:{
|
||||
province,
|
||||
city,
|
||||
area
|
||||
}
|
||||
return this.hideArea?{
|
||||
provinces,
|
||||
citys,
|
||||
dVal,
|
||||
obj
|
||||
}:{
|
||||
provinces,
|
||||
citys,
|
||||
areas,
|
||||
dVal,
|
||||
obj
|
||||
}
|
||||
},
|
||||
initData(){
|
||||
let dataData=this.getData();
|
||||
let provinces=dataData.provinces;
|
||||
let citys=dataData.citys;
|
||||
let areas=this.hideArea?[]:dataData.areas;
|
||||
let obj=dataData.obj;
|
||||
let province=obj.province,city=obj.city,area=this.hideArea?{}:obj.area;
|
||||
let value=this.hideArea?[province.value,city.value]:[province.value,city.value,area.value];
|
||||
let result=this.hideArea?`${province.label+city.label}`:`${province.label+city.label+area.label}`;
|
||||
this.range=this.hideArea?{
|
||||
provinces,
|
||||
citys,
|
||||
}:{
|
||||
provinces,
|
||||
citys,
|
||||
areas
|
||||
};
|
||||
this.checkObj=obj;
|
||||
this.$nextTick(()=>{
|
||||
this.pickVal=dataData.dVal;
|
||||
});
|
||||
this.$emit("change",{
|
||||
result:result,
|
||||
value:value,
|
||||
obj:obj
|
||||
})
|
||||
},
|
||||
handlerChange(e){
|
||||
let arr=[...e.detail.value];
|
||||
let provinceIndex=arr[0],cityIndex=arr[1],areaIndex=this.hideArea?0:arr[2];
|
||||
let provinces=areaData;
|
||||
let citys=(provinces[provinceIndex]&&provinces[provinceIndex].children)||provinces[provinces.length-1].children||[];
|
||||
let areas=this.hideArea?[]:((citys[cityIndex]&&citys[cityIndex].children)||citys[citys.length-1].children||[]);
|
||||
let province=provinces[provinceIndex]||provinces[provinces.length-1],
|
||||
city=citys[cityIndex]||[citys.length-1],
|
||||
area=this.hideArea?{}:(areas[areaIndex]||[areas.length-1]);
|
||||
let obj=this.hideArea?{
|
||||
province,
|
||||
city
|
||||
}:{
|
||||
province,
|
||||
city,
|
||||
area
|
||||
}
|
||||
if(this.checkObj.province.label!=province.label){
|
||||
//当省更新的时候需要刷新市、区县的数据;
|
||||
this.range.citys=citys;
|
||||
if(!this.hideArea){
|
||||
this.range.areas=areas;
|
||||
}
|
||||
|
||||
}
|
||||
if(this.checkObj.city.label!=city.label){
|
||||
//当市更新的时候需要刷新区县的数据;
|
||||
if(!this.hideArea){
|
||||
this.range.areas=areas;
|
||||
}
|
||||
}
|
||||
this.checkObj=obj;
|
||||
this.$nextTick(()=>{
|
||||
this.pickVal=arr;
|
||||
})
|
||||
let result=this.hideArea?`${province.label+city.label}`:`${province.label+city.label+area.label}`;
|
||||
let value=this.hideArea?[province.value,city.value]:[province.value,city.value,area.value];
|
||||
this.$emit("change",{
|
||||
result:result,
|
||||
value:value,
|
||||
obj:obj
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import "./w-picker.css";
|
||||
</style>
|
||||
|
||||
129
uniapp/uni-app/components/w-picker/selector-picker.vue
Normal file
129
uniapp/uni-app/components/w-picker/selector-picker.vue
Normal file
@@ -0,0 +1,129 @@
|
||||
<template>
|
||||
<view class="w-picker-view">
|
||||
<picker-view class="d-picker-view" :indicator-style="itemHeight" :value="pickVal" @change="handlerChange">
|
||||
<picker-view-column>
|
||||
<view class="w-picker-item" v-for="(item,index) in range" :key="index">{{item[nodeKey]}}</view>
|
||||
</picker-view-column>
|
||||
</picker-view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props:{
|
||||
itemHeight:{
|
||||
type:String,
|
||||
default:"44px"
|
||||
},
|
||||
options:{
|
||||
type:[Array,Object],
|
||||
default(){
|
||||
return []
|
||||
}
|
||||
},
|
||||
value:{
|
||||
type:String,
|
||||
default:""
|
||||
},
|
||||
defaultType:{
|
||||
type:String,
|
||||
default:"label"
|
||||
},
|
||||
defaultProps:{
|
||||
type:Object,
|
||||
default(){
|
||||
return{
|
||||
label:"label",
|
||||
value:"value"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
pickVal:[]
|
||||
};
|
||||
},
|
||||
computed:{
|
||||
nodeKey(){
|
||||
return this.defaultProps.label;
|
||||
},
|
||||
nodeValue(){
|
||||
return this.defaultProps.value;
|
||||
},
|
||||
range(){
|
||||
return this.options
|
||||
}
|
||||
},
|
||||
watch:{
|
||||
value(val){
|
||||
if(this.options.length!=0){
|
||||
this.initData();
|
||||
}
|
||||
},
|
||||
options(val){
|
||||
this.initData();
|
||||
}
|
||||
},
|
||||
created() {
|
||||
if(this.options.length!=0){
|
||||
this.initData();
|
||||
}
|
||||
},
|
||||
methods:{
|
||||
initData(){
|
||||
let dVal=this.value||"";
|
||||
let data=this.range;
|
||||
let pickVal=[0];
|
||||
let cur=null;
|
||||
let label="";
|
||||
let value,idx;
|
||||
if(this.defaultType==this.nodeValue){
|
||||
value=data.find((v)=>v[this.nodeValue]==dVal);
|
||||
idx=data.findIndex((v)=>v[this.nodeValue]==dVal);
|
||||
}else{
|
||||
value=data.find((v)=>v[this.nodeKey]==dVal);
|
||||
idx=data.findIndex((v)=>v[this.nodeKey]==dVal);
|
||||
}
|
||||
pickVal=[idx!=-1?idx:0];
|
||||
this.$nextTick(()=>{
|
||||
this.pickVal=pickVal;
|
||||
});
|
||||
if(this.defaultType==this.nodeValue){
|
||||
this.$emit("change",{
|
||||
result:value?value[this.nodeKey]:data[0][this.nodeKey],
|
||||
value:dVal||data[0][this.nodeKey],
|
||||
obj:value?value:data[0]
|
||||
})
|
||||
}else{
|
||||
this.$emit("change",{
|
||||
result:dVal||data[0][this.nodeKey],
|
||||
value:value?value[this.nodeValue]:data[0][this.nodeValue],
|
||||
obj:value?value:data[0]
|
||||
})
|
||||
}
|
||||
|
||||
},
|
||||
handlerChange(e){
|
||||
let arr=[...e.detail.value];
|
||||
let pickVal=[arr[0]||0];
|
||||
let data=this.range;
|
||||
let cur=data[arr[0]];
|
||||
let label="";
|
||||
let value="";
|
||||
this.$nextTick(()=>{
|
||||
this.pickVal=pickVal;
|
||||
});
|
||||
this.$emit("change",{
|
||||
result:cur[this.nodeKey],
|
||||
value:cur[this.nodeValue],
|
||||
obj:cur
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import "./w-picker.css";
|
||||
</style>
|
||||
250
uniapp/uni-app/components/w-picker/shortterm-picker.vue
Normal file
250
uniapp/uni-app/components/w-picker/shortterm-picker.vue
Normal file
@@ -0,0 +1,250 @@
|
||||
<template>
|
||||
<view class="w-picker-view">
|
||||
<picker-view class="d-picker-view" :indicator-style="itemHeight" :value="pickVal" @change="handlerChange">
|
||||
<picker-view-column>
|
||||
<view class="w-picker-item" v-for="(item,index) in range.dates" :key="index">{{item.label}}</view>
|
||||
</picker-view-column>
|
||||
<picker-view-column>
|
||||
<view class="w-picker-item" v-for="(item,index) in range.hours" :key="index">{{item.label}}时</view>
|
||||
</picker-view-column>
|
||||
<picker-view-column>
|
||||
<view class="w-picker-item" v-for="(item,index) in range.minutes" :key="index">{{item.label}}分</view>
|
||||
</picker-view-column>
|
||||
</picker-view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
pickVal:[],
|
||||
range:{},
|
||||
checkObj:{}
|
||||
};
|
||||
},
|
||||
props:{
|
||||
itemHeight:{
|
||||
type:String,
|
||||
default:"44px"
|
||||
},
|
||||
value:{
|
||||
type:[String,Array,Number],
|
||||
default:""
|
||||
},
|
||||
current:{//是否默认选中当前日期
|
||||
type:Boolean,
|
||||
default:false
|
||||
},
|
||||
expand:{
|
||||
type:[Number,String],
|
||||
default:30
|
||||
}
|
||||
},
|
||||
watch:{
|
||||
value(val){
|
||||
this.initData();
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.initData();
|
||||
},
|
||||
methods:{
|
||||
formatNum(n){
|
||||
return (Number(n)<10?'0'+Number(n):Number(n)+'');
|
||||
},
|
||||
checkValue(value){
|
||||
let strReg=/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}(:\d{2})?$/,example="2019-12-12 18:05:00或者2019-12-12 18:05";
|
||||
if(!strReg.test(value)){
|
||||
console.log(new Error("请传入与mode、fields匹配的value值,例value="+example+""))
|
||||
}
|
||||
return strReg.test(value);
|
||||
},
|
||||
resetData(year,month,day){
|
||||
let curDate=this.getCurrenDate();
|
||||
let curFlag=this.current;
|
||||
let curYear=curDate.curYear;
|
||||
let curMonth=curDate.curMonth;
|
||||
let curDay=curDate.curDay;
|
||||
let curHour=curDate.curHour;
|
||||
let months=[],days=[],sections=[];
|
||||
let disabledAfter=this.disabledAfter;
|
||||
let monthsLen=disabledAfter?(year*1<curYear?12:curMonth):12;
|
||||
let totalDays=new Date(year,month,0).getDate();//计算当月有几天;
|
||||
for(let month=1;month<=monthsLen;month++){
|
||||
months.push(this.formatNum(month));
|
||||
};
|
||||
for(let day=1;day<=daysLen;day++){
|
||||
days.push(this.formatNum(day));
|
||||
}
|
||||
return{
|
||||
months,
|
||||
days,
|
||||
sections
|
||||
}
|
||||
},
|
||||
getData(dVal){
|
||||
//用来处理初始化数据
|
||||
let curFlag=this.current;
|
||||
let disabledAfter=this.disabledAfter;
|
||||
let dates=[],hours=[],minutes=[];
|
||||
let curDate=new Date();
|
||||
let curYear=curDate.getFullYear();
|
||||
let curMonth=curDate.getMonth();
|
||||
let curDay=curDate.getDate();
|
||||
let aDate=new Date(curYear,curMonth,curDay);
|
||||
for(let i=0;i<this.expand*1;i++){
|
||||
aDate=new Date(curYear,curMonth,curDay+i);
|
||||
let year=aDate.getFullYear();
|
||||
let month=aDate.getMonth()+1;
|
||||
let day=aDate.getDate();
|
||||
let label=year+"-"+this.formatNum(month)+"-"+this.formatNum(day);
|
||||
switch(i){
|
||||
case 0:
|
||||
label="今天";
|
||||
break;
|
||||
case 1:
|
||||
label="明天";
|
||||
break;
|
||||
case 2:
|
||||
label="后天";
|
||||
break
|
||||
}
|
||||
dates.push({
|
||||
label:label,
|
||||
value:year+"-"+this.formatNum(month)+"-"+this.formatNum(day)
|
||||
})
|
||||
};
|
||||
for(let i=0;i<24;i++){
|
||||
hours.push({
|
||||
label:this.formatNum(i),
|
||||
value:this.formatNum(i)
|
||||
})
|
||||
}
|
||||
for(let i=0;i<60;i++){
|
||||
minutes.push({
|
||||
label:this.formatNum(i),
|
||||
value:this.formatNum(i)
|
||||
})
|
||||
}
|
||||
return {
|
||||
dates,
|
||||
hours,
|
||||
minutes
|
||||
}
|
||||
},
|
||||
getDefaultDate(){
|
||||
let value=this.value;
|
||||
let reg=/-/g;
|
||||
let defaultDate=value?new Date(value.replace(reg,"/")):new Date();
|
||||
let defaultYear=defaultDate.getFullYear();
|
||||
let defaultMonth=defaultDate.getMonth()+1;
|
||||
let defaultDay=defaultDate.getDate();
|
||||
let defaultDays=new Date(defaultYear,defaultMonth,0).getDate()*1;
|
||||
return{
|
||||
defaultDate,
|
||||
defaultYear,
|
||||
defaultMonth,
|
||||
defaultDay,
|
||||
defaultDays
|
||||
}
|
||||
},
|
||||
getDval(){
|
||||
let value=this.value;
|
||||
let dVal=null;
|
||||
let aDate=new Date();
|
||||
let year=this.formatNum(aDate.getFullYear());
|
||||
let month=this.formatNum(aDate.getMonth()+1);
|
||||
let day=this.formatNum(aDate.getDate());
|
||||
let date=this.formatNum(year)+"-"+this.formatNum(month)+"-"+this.formatNum(day);
|
||||
let hour=aDate.getHours();
|
||||
let minute=aDate.getMinutes();
|
||||
if(value){
|
||||
let flag=this.checkValue(value);
|
||||
if(!flag){
|
||||
dVal=[date,hour,minute]
|
||||
}else{
|
||||
let v=value.split(" ");
|
||||
dVal=[v[0],...v[1].split(":")];
|
||||
}
|
||||
}else{
|
||||
dVal=[date,hour,minute]
|
||||
}
|
||||
return dVal;
|
||||
},
|
||||
initData(){
|
||||
let startDate,endDate,startYear,endYear,startMonth,endMonth,startDay,endDay;
|
||||
let dates=[],hours=[],minutes=[];
|
||||
let dVal=[],pickVal=[];
|
||||
let value=this.value;
|
||||
let reg=/-/g;
|
||||
let range={};
|
||||
let result="",full="",date,hour,minute,obj={};
|
||||
let defaultDate=this.getDefaultDate();
|
||||
let defaultYear=defaultDate.defaultYear;
|
||||
let defaultMonth=defaultDate.defaultMonth;
|
||||
let defaultDay=defaultDate.defaultDay;
|
||||
let defaultDays=defaultDate.defaultDays;
|
||||
let curFlag=this.current;
|
||||
let disabledAfter=this.disabledAfter;
|
||||
let dateData=[];
|
||||
dVal=this.getDval();
|
||||
dateData=this.getData(dVal);
|
||||
dates=dateData.dates;
|
||||
hours=dateData.hours;
|
||||
minutes=dateData.minutes;
|
||||
pickVal=[
|
||||
dates.findIndex(n => n.value == dVal[0])!=-1?dates.findIndex(n => n.value == dVal[0]):0,
|
||||
hours.findIndex(n => n.value == dVal[1])!=-1?hours.findIndex(n => n.value == dVal[1]):0,
|
||||
minutes.findIndex(n => n.value == dVal[2])!=-1?minutes.findIndex(n => n.value == dVal[2]):0,
|
||||
];
|
||||
range={dates,hours,minutes};
|
||||
date=dVal[0]?dVal[0]:dates[0].label;
|
||||
hour=dVal[1]?dVal[1]:hours[0].label;
|
||||
minute=dVal[2]?dVal[2]:minutes[0].label;
|
||||
result=full=`${date+' '+hour+':'+minute}`;
|
||||
obj={
|
||||
date,
|
||||
hour,
|
||||
minute
|
||||
}
|
||||
this.range=range;
|
||||
this.checkObj=obj;
|
||||
this.$nextTick(()=>{
|
||||
this.pickVal=pickVal;
|
||||
});
|
||||
this.$emit("change",{
|
||||
result:result,
|
||||
value:full,
|
||||
obj:obj
|
||||
})
|
||||
},
|
||||
handlerChange(e){
|
||||
let arr=[...e.detail.value];
|
||||
let data=this.range;
|
||||
let date="",hour="",minute="";
|
||||
let result="",full="",obj={};
|
||||
let disabledAfter=this.disabledAfter;
|
||||
date=(arr[0]||arr[0]==0)?data.dates[arr[0]]||data.dates[data.dates.length-1]:"";
|
||||
hour=(arr[1]||arr[1]==0)?data.hours[arr[1]]||data.hours[data.hours.length-1]:"";
|
||||
minute=(arr[2]||arr[2]==0)?data.minutes[arr[2]]||data.minutes[data.minutes.length-1]:"";
|
||||
result=full=`${date.label+' '+hour.label+':'+minute.label+':00'}`;
|
||||
obj={
|
||||
date,
|
||||
hour,
|
||||
minute
|
||||
}
|
||||
this.checkObj=obj;
|
||||
this.$emit("change",{
|
||||
result:result,
|
||||
value:full,
|
||||
obj:obj
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import "./w-picker.css";
|
||||
</style>
|
||||
218
uniapp/uni-app/components/w-picker/time-picker.vue
Normal file
218
uniapp/uni-app/components/w-picker/time-picker.vue
Normal file
@@ -0,0 +1,218 @@
|
||||
<template>
|
||||
<view class="w-picker-view">
|
||||
<picker-view class="d-picker-view" :indicator-style="itemHeight" :value="pickVal" @change="handlerChange">
|
||||
<picker-view-column>
|
||||
<view class="w-picker-item" v-for="(item,index) in range.hours" :key="index">{{item}}时</view>
|
||||
</picker-view-column>
|
||||
<picker-view-column>
|
||||
<view class="w-picker-item" v-for="(item,index) in range.minutes" :key="index">{{item}}分</view>
|
||||
</picker-view-column>
|
||||
<picker-view-column v-if="second">
|
||||
<view class="w-picker-item" v-for="(item,index) in range.seconds" :key="index">{{item}}秒</view>
|
||||
</picker-view-column>
|
||||
</picker-view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
pickVal:[],
|
||||
range:{},
|
||||
checkObj:{}
|
||||
};
|
||||
},
|
||||
props:{
|
||||
itemHeight:{
|
||||
type:String,
|
||||
default:"44px"
|
||||
},
|
||||
value:{
|
||||
type:[String,Array,Number],
|
||||
default:""
|
||||
},
|
||||
current:{//是否默认选中当前日期
|
||||
type:Boolean,
|
||||
default:false
|
||||
},
|
||||
second:{
|
||||
type:Boolean,
|
||||
default:true
|
||||
}
|
||||
},
|
||||
watch:{
|
||||
value(val){
|
||||
this.initData();
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.initData();
|
||||
},
|
||||
methods:{
|
||||
formatNum(n){
|
||||
return (Number(n)<10?'0'+Number(n):Number(n)+'');
|
||||
},
|
||||
checkValue(value){
|
||||
let strReg=/^\d{2}:\d{2}:\d{2}$/,example="18:00:05";
|
||||
if(!strReg.test(value)){
|
||||
console.log(new Error("请传入与mode、fields匹配的value值,例value="+example+""))
|
||||
}
|
||||
return strReg.test(value);
|
||||
},
|
||||
resetData(year,month,day,hour,minute){
|
||||
let curDate=this.getCurrenDate();
|
||||
let curFlag=this.current;
|
||||
let curHour=curDate.curHour;
|
||||
let curMinute=curDate.curMinute;
|
||||
let curSecond=curDate.curSecond;
|
||||
for(let hour=0;hour<24;hour++){
|
||||
hours.push(this.formatNum(hour));
|
||||
}
|
||||
for(let minute=0;minute<60;minute++){
|
||||
minutes.push(this.formatNum(minute));
|
||||
}
|
||||
for(let second=0;second<60;second++){
|
||||
seconds.push(this.formatNum(second));
|
||||
}
|
||||
return{
|
||||
hours,
|
||||
minutes,
|
||||
seconds
|
||||
}
|
||||
},
|
||||
getData(curDate){
|
||||
//用来处理初始化数据
|
||||
let hours=[],minutes=[],seconds=[];
|
||||
let curFlag=this.current;
|
||||
let disabledAfter=this.disabledAfter;
|
||||
let fields=this.fields;
|
||||
let curHour=curDate.curHour;
|
||||
let curMinute=curDate.curMinute;
|
||||
let curSecond=curDate.curSecond;
|
||||
for(let hour=0;hour<24;hour++){
|
||||
hours.push(this.formatNum(hour));
|
||||
}
|
||||
for(let minute=0;minute<60;minute++){
|
||||
minutes.push(this.formatNum(minute));
|
||||
}
|
||||
for(let second=0;second<60;second++){
|
||||
seconds.push(this.formatNum(second));
|
||||
}
|
||||
return this.second?{
|
||||
hours,
|
||||
minutes,
|
||||
seconds
|
||||
}:{
|
||||
hours,
|
||||
minutes
|
||||
}
|
||||
},
|
||||
getCurrenDate(){
|
||||
let curDate=new Date();
|
||||
let curHour=curDate.getHours();
|
||||
let curMinute=curDate.getMinutes();
|
||||
let curSecond=curDate.getSeconds();
|
||||
return this.second?{
|
||||
curHour,
|
||||
curMinute,
|
||||
curSecond
|
||||
}:{
|
||||
curHour,
|
||||
curMinute,
|
||||
}
|
||||
},
|
||||
getDval(){
|
||||
let value=this.value;
|
||||
let fields=this.fields;
|
||||
let dVal=null;
|
||||
let aDate=new Date();
|
||||
let hour=this.formatNum(aDate.getHours());
|
||||
let minute=this.formatNum(aDate.getMinutes());
|
||||
let second=this.formatNum(aDate.getSeconds());
|
||||
if(value){
|
||||
let flag=this.checkValue(value);
|
||||
if(!flag){
|
||||
dVal=[hour,minute,second]
|
||||
}else{
|
||||
dVal=value?value.split(":"):[];
|
||||
}
|
||||
}else{
|
||||
dVal=this.second?[hour,minute,second]:[hour,minute]
|
||||
}
|
||||
return dVal;
|
||||
},
|
||||
initData(){
|
||||
let curDate=this.getCurrenDate();
|
||||
let dateData=this.getData(curDate);
|
||||
let pickVal=[],obj={},full="",result="",hour="",minute="",second="";
|
||||
let dVal=this.getDval();
|
||||
let curFlag=this.current;
|
||||
let disabledAfter=this.disabledAfter;
|
||||
let hours=dateData.hours;
|
||||
let minutes=dateData.minutes;
|
||||
let seconds=dateData.seconds;
|
||||
let defaultArr=this.second?[
|
||||
dVal[0]&&hours.indexOf(dVal[0])!=-1?hours.indexOf(dVal[0]):0,
|
||||
dVal[1]&&minutes.indexOf(dVal[1])!=-1?minutes.indexOf(dVal[1]):0,
|
||||
dVal[2]&&seconds.indexOf(dVal[2])!=-1?seconds.indexOf(dVal[2]):0
|
||||
]:[
|
||||
dVal[0]&&hours.indexOf(dVal[0])!=-1?hours.indexOf(dVal[0]):0,
|
||||
dVal[1]&&minutes.indexOf(dVal[1])!=-1?minutes.indexOf(dVal[1]):0
|
||||
];
|
||||
pickVal=disabledAfter?defaultArr:(curFlag?(this.second?[
|
||||
hours.indexOf(this.formatNum(curDate.curHour)),
|
||||
minutes.indexOf(this.formatNum(curDate.curMinute)),
|
||||
seconds.indexOf(this.formatNum(curDate.curSecond)),
|
||||
]:[
|
||||
hours.indexOf(this.formatNum(curDate.curHour)),
|
||||
minutes.indexOf(this.formatNum(curDate.curMinute))
|
||||
]):defaultArr);
|
||||
this.range=dateData;
|
||||
this.checkObj=obj;
|
||||
hour=dVal[0]?dVal[0]:hours[0];
|
||||
minute=dVal[1]?dVal[1]:minutes[0];
|
||||
if(this.second)second=dVal[2]?dVal[0]:seconds[0];
|
||||
result=this.second?`${hour+':'+minute+':'+second}`:`${hour+':'+minute}`;
|
||||
full=this.second?`${hour+':'+minute+':'+second}`:`${hour+':'+minute+':00'}`;
|
||||
this.$nextTick(()=>{
|
||||
this.pickVal=pickVal;
|
||||
});
|
||||
this.$emit("change",{
|
||||
result:result,
|
||||
value:full,
|
||||
obj:obj
|
||||
})
|
||||
},
|
||||
handlerChange(e){
|
||||
let arr=[...e.detail.value];
|
||||
let data=this.range;
|
||||
let hour="",minute="",second="",result="",full="",obj={};
|
||||
hour=(arr[0]||arr[0]==0)?data.hours[arr[0]]||data.hours[data.hours.length-1]:"";
|
||||
minute=(arr[1]||arr[1]==0)?data.minutes[arr[1]]||data.minutes[data.minutes.length-1]:"";
|
||||
if(this.second)second=(arr[2]||arr[2]==0)?data.seconds[arr[2]]||data.seconds[data.seconds.length-1]:"";
|
||||
obj=this.second?{
|
||||
hour,
|
||||
minute,
|
||||
second
|
||||
}:{
|
||||
hour,
|
||||
minute
|
||||
};
|
||||
this.checkObj=obj;
|
||||
result=this.second?`${hour+':'+minute+':'+second}`:`${hour+':'+minute}`;
|
||||
full=this.second?`${hour+':'+minute+':'+second}`:`${hour+':'+minute+':00'}`;
|
||||
this.$emit("change",{
|
||||
result:result,
|
||||
value:full,
|
||||
obj:obj
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import "./w-picker.css";
|
||||
</style>
|
||||
|
||||
26
uniapp/uni-app/components/w-picker/w-picker.css
Normal file
26
uniapp/uni-app/components/w-picker/w-picker.css
Normal file
@@ -0,0 +1,26 @@
|
||||
.w-picker-flex2{
|
||||
flex:2;
|
||||
}
|
||||
.w-picker-flex1{
|
||||
flex:1;
|
||||
}
|
||||
.w-picker-view {
|
||||
width: 100%;
|
||||
height: 476upx;
|
||||
overflow: hidden;
|
||||
background-color: rgba(255, 255, 255, 1);
|
||||
z-index: 666;
|
||||
}
|
||||
.d-picker-view{
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.w-picker-item {
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
height: 88upx;
|
||||
line-height: 88upx;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
font-size: 30upx;
|
||||
}
|
||||
340
uniapp/uni-app/components/w-picker/w-picker.vue
Normal file
340
uniapp/uni-app/components/w-picker/w-picker.vue
Normal file
@@ -0,0 +1,340 @@
|
||||
<template name="w-picker">
|
||||
<view class="w-picker" :key="createKey" :data-key="createKey">
|
||||
<view class="mask" :class="{'visible':visible}" @tap="onCancel" @touchmove.stop.prevent catchtouchmove="true"></view>
|
||||
<view class="w-picker-cnt" :class="{'visible':visible}">
|
||||
<view class="w-picker-header" @touchmove.stop.prevent catchtouchmove="true">
|
||||
<text @tap.stop.prevent="onCancel">取消</text>
|
||||
<slot></slot>
|
||||
<text :style="{'color':themeColor}" @tap.stop.prevent="pickerConfirm">确定</text>
|
||||
</view>
|
||||
<date-picker
|
||||
v-if="mode=='date'"
|
||||
class="w-picker-wrapper"
|
||||
:startYear="startYear"
|
||||
:endYear="endYear"
|
||||
:value="value"
|
||||
:fields="fields"
|
||||
:item-height="itemHeight"
|
||||
:current="current"
|
||||
:disabled-after="disabledAfter"
|
||||
@change="handlerChange"
|
||||
@touchstart="touchStart"
|
||||
@touchend="touchEnd">
|
||||
</date-picker>
|
||||
|
||||
<range-picker
|
||||
v-if="mode=='range'"
|
||||
class="w-picker-wrapper"
|
||||
:startYear="startYear"
|
||||
:endYear="endYear"
|
||||
:value="value"
|
||||
:item-height="itemHeight"
|
||||
:current="current"
|
||||
@change="handlerChange"
|
||||
@touchstart="touchStart"
|
||||
@touchend="touchEnd">
|
||||
</range-picker>
|
||||
|
||||
<half-picker
|
||||
v-if="mode=='half'"
|
||||
class="w-picker-wrapper"
|
||||
:startYear="startYear"
|
||||
:endYear="endYear"
|
||||
:value="value"
|
||||
:item-height="itemHeight"
|
||||
:current="current"
|
||||
:disabled-after="disabledAfter"
|
||||
@change="handlerChange"
|
||||
@touchstart="touchStart"
|
||||
@touchend="touchEnd">
|
||||
</half-picker>
|
||||
|
||||
<shortterm-picker
|
||||
v-if="mode=='shortTerm'"
|
||||
class="w-picker-wrapper"
|
||||
:startYear="startYear"
|
||||
:endYear="endYear"
|
||||
:value="value"
|
||||
:item-height="itemHeight"
|
||||
:current="current"
|
||||
expand="60"
|
||||
:disabled-after="disabledAfter"
|
||||
@change="handlerChange"
|
||||
@touchstart="touchStart"
|
||||
@touchend="touchEnd">
|
||||
</shortterm-picker>
|
||||
|
||||
<time-picker
|
||||
v-if="mode=='time'"
|
||||
class="w-picker-wrapper"
|
||||
:value="value"
|
||||
:item-height="itemHeight"
|
||||
:current="current"
|
||||
:disabled-after="disabledAfter"
|
||||
:second="second"
|
||||
@change="handlerChange"
|
||||
@touchstart="touchStart"
|
||||
@touchend="touchEnd">
|
||||
</time-picker>
|
||||
|
||||
<selector-picker
|
||||
v-if="mode=='selector'"
|
||||
class="w-picker-wrapper"
|
||||
:value="value"
|
||||
:item-height="itemHeight"
|
||||
:options="options"
|
||||
:default-type="defaultType"
|
||||
:default-props="defaultProps"
|
||||
@change="handlerChange"
|
||||
@touchstart="touchStart"
|
||||
@touchend="touchEnd">
|
||||
</selector-picker>
|
||||
|
||||
<region-picker
|
||||
v-if="mode=='region'"
|
||||
class="w-picker-wrapper"
|
||||
:value="value"
|
||||
:hide-area="hideArea"
|
||||
:default-type="defaultType"
|
||||
:item-height="itemHeight"
|
||||
@change="handlerChange"
|
||||
@touchstart="touchStart"
|
||||
@touchend="touchEnd">
|
||||
</region-picker>
|
||||
|
||||
<linkage-picker
|
||||
v-if="mode=='linkage'"
|
||||
class="w-picker-wrapper"
|
||||
:value="value"
|
||||
:options="options"
|
||||
:level="level"
|
||||
:default-type="defaultType"
|
||||
:default-props="defaultProps"
|
||||
:item-height="itemHeight"
|
||||
@change="handlerChange"
|
||||
@touchstart="touchStart"
|
||||
@touchend="touchEnd">
|
||||
</linkage-picker>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import datePicker from "./date-picker.vue"
|
||||
import rangePicker from "./range-picker.vue"
|
||||
import halfPicker from "./half-picker.vue"
|
||||
import shorttermPicker from "./shortterm-picker.vue"
|
||||
import timePicker from "./time-picker.vue"
|
||||
import selectorPicker from "./selector-picker.vue"
|
||||
import regionPicker from "./region-picker.vue"
|
||||
import linkagePicker from "./linkage-picker.vue"
|
||||
export default {
|
||||
name:"w-picker",
|
||||
components:{
|
||||
datePicker,
|
||||
rangePicker,
|
||||
halfPicker,
|
||||
timePicker,
|
||||
selectorPicker,
|
||||
shorttermPicker,
|
||||
regionPicker,
|
||||
linkagePicker
|
||||
},
|
||||
props:{
|
||||
mode:{
|
||||
type:String,
|
||||
default:"date"
|
||||
},
|
||||
value:{//默认值
|
||||
type:[String,Array,Number],
|
||||
default:""
|
||||
},
|
||||
current:{//是否默认显示当前时间,如果是,传的默认值将失效
|
||||
type:Boolean,
|
||||
default:false
|
||||
},
|
||||
themeColor:{//确认按钮主题颜色
|
||||
type:String,
|
||||
default:"#f5a200"
|
||||
},
|
||||
fields:{//日期颗粒度:year、month、day、hour、minute、second
|
||||
type:String,
|
||||
default:"date"
|
||||
},
|
||||
disabledAfter:{//是否禁用当前之后的日期
|
||||
type:Boolean,
|
||||
default:false
|
||||
},
|
||||
second:{//time-picker是否显示秒
|
||||
type:Boolean,
|
||||
default:true
|
||||
},
|
||||
options:{//selector,region数据源
|
||||
type:[Array,Object],
|
||||
default(){
|
||||
return []
|
||||
}
|
||||
},
|
||||
defaultProps:{//selector,linkagle字段转换配置
|
||||
type:Object,
|
||||
default(){
|
||||
return{
|
||||
label:"label",
|
||||
value:"value",
|
||||
children:"children"
|
||||
}
|
||||
}
|
||||
},
|
||||
defaultType:{
|
||||
type:String,
|
||||
default:"label"
|
||||
},
|
||||
hideArea:{//mode=region时,是否隐藏区县列
|
||||
type:Boolean,
|
||||
default:false
|
||||
},
|
||||
level:{
|
||||
//多级联动层级,表示几级联动,区间2-4;
|
||||
type:[Number,String],
|
||||
default:2
|
||||
},
|
||||
timeout:{//是否开启点击延迟,当快速滚动 还没有滚动完毕点击关闭时得到的值是不准确的
|
||||
type:Boolean,
|
||||
default:false
|
||||
},
|
||||
expand:{//mode=shortterm 默认往后拓展天数
|
||||
type:[Number,String],
|
||||
default:30
|
||||
},
|
||||
startYear:{
|
||||
type:[String,Number],
|
||||
default:1970
|
||||
},
|
||||
endYear:{
|
||||
type:[String,Number],
|
||||
default:new Date().getFullYear()
|
||||
},
|
||||
visible:{
|
||||
type:Boolean,
|
||||
default:false
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.createKey=Math.random()*1000;
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
itemHeight:`height: ${uni.upx2px(88)}px;`,
|
||||
result:{},
|
||||
confirmFlag:true
|
||||
};
|
||||
},
|
||||
methods:{
|
||||
touchStart(){
|
||||
if(this.timeout){
|
||||
this.confirmFlag=false;
|
||||
}
|
||||
},
|
||||
touchEnd(){
|
||||
if(this.timeout){
|
||||
setTimeout(()=>{
|
||||
this.confirmFlag=true;
|
||||
},500)
|
||||
}
|
||||
},
|
||||
handlerChange(res){
|
||||
let _this=this;
|
||||
this.result={...res};
|
||||
},
|
||||
show(){
|
||||
this.$emit("update:visible",true);
|
||||
},
|
||||
hide(){
|
||||
this.$emit("update:visible",false);
|
||||
},
|
||||
onCancel(res){
|
||||
this.$emit("update:visible",false);
|
||||
this.$emit("cancel");
|
||||
},
|
||||
pickerConfirm(){
|
||||
if(!this.confirmFlag){
|
||||
return;
|
||||
};
|
||||
this.$emit("confirm",this.result);
|
||||
this.$emit("update:visible",false);
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.w-picker-item {
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
height: 88upx;
|
||||
line-height: 88upx;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
font-size: 30upx;
|
||||
}
|
||||
.w-picker{
|
||||
z-index: 888;
|
||||
.mask {
|
||||
position: fixed;
|
||||
z-index: 1000;
|
||||
top: 0;
|
||||
right: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0, 0, 0, 0.6);
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
.mask.visible{
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
}
|
||||
.w-picker-cnt {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
transition: all 0.3s ease;
|
||||
transform: translateY(100%);
|
||||
z-index: 3000;
|
||||
background-color: #fff;
|
||||
}
|
||||
.w-picker-cnt.visible {
|
||||
transform: translateY(0);
|
||||
}
|
||||
.w-picker-header{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0 30upx;
|
||||
height: 88upx;
|
||||
background-color: #fff;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
font-size: 32upx;
|
||||
justify-content: space-between;
|
||||
border-bottom: solid 1px #eee;
|
||||
.w-picker-btn{
|
||||
font-size: 30upx;
|
||||
}
|
||||
}
|
||||
|
||||
.w-picker-hd:after {
|
||||
content: ' ';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
height: 1px;
|
||||
border-bottom: 1px solid #e5e5e5;
|
||||
color: #e5e5e5;
|
||||
transform-origin: 0 100%;
|
||||
transform: scaleY(0.5);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user