初始化项目
This commit is contained in:
commit
bf8dc07cb7
|
@ -0,0 +1,5 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<buildpath>
|
||||||
|
<buildpathentry kind="src" path=""/>
|
||||||
|
<buildpathentry kind="con" path="org.eclipse.php.core.LANGUAGE"/>
|
||||||
|
</buildpath>
|
|
@ -0,0 +1 @@
|
||||||
|
/unpackage/
|
|
@ -0,0 +1,20 @@
|
||||||
|
{ // launch.json 配置了启动调试时相关设置,configurations下节点名称可为 app-plus/h5/mp-weixin/mp-baidu/mp-alipay/mp-qq/mp-toutiao/mp-360/
|
||||||
|
// launchtype项可配置值为local或remote, local代表前端连本地云函数,remote代表前端连云端云函数
|
||||||
|
"version": "0.0",
|
||||||
|
"configurations": [{
|
||||||
|
"app-plus" :
|
||||||
|
{
|
||||||
|
"launchtype" : "local"
|
||||||
|
},
|
||||||
|
"default" :
|
||||||
|
{
|
||||||
|
"launchtype" : "local"
|
||||||
|
},
|
||||||
|
"mp-weixin" :
|
||||||
|
{
|
||||||
|
"launchtype" : "local"
|
||||||
|
},
|
||||||
|
"type" : "uniCloud"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
# 默认忽略的文件
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# 基于编辑器的 HTTP 客户端请求
|
||||||
|
/httpRequests/
|
|
@ -0,0 +1,12 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="cn.fjdmy.uniapp.UniappProjectDataService">
|
||||||
|
<option name="basePath" value="$PROJECT_DIR$" />
|
||||||
|
<option name="generalBasePath" value="$PROJECT_DIR$" />
|
||||||
|
<option name="manifestPath" value="$PROJECT_DIR$/manifest.json" />
|
||||||
|
<option name="pagesPath" value="$PROJECT_DIR$/pages.json" />
|
||||||
|
<option name="scanNum" value="1" />
|
||||||
|
<option name="type" value="store" />
|
||||||
|
<option name="uniapp" value="true" />
|
||||||
|
</component>
|
||||||
|
</project>
|
|
@ -0,0 +1,12 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="WEB_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager">
|
||||||
|
<content url="file://$MODULE_DIR$">
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/temp" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/tmp" />
|
||||||
|
</content>
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
|
@ -0,0 +1,8 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/dengLan_home_mpWeixin.iml" filepath="$PROJECT_DIR$/.idea/dengLan_home_mpWeixin.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
|
@ -0,0 +1,22 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<projectDescription>
|
||||||
|
<name>djh5</name>
|
||||||
|
<comment></comment>
|
||||||
|
<projects>
|
||||||
|
</projects>
|
||||||
|
<buildSpec>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.wst.validation.validationbuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.dltk.core.scriptbuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
</buildSpec>
|
||||||
|
<natures>
|
||||||
|
<nature>org.eclipse.php.core.PHPNature</nature>
|
||||||
|
</natures>
|
||||||
|
</projectDescription>
|
|
@ -0,0 +1,3 @@
|
||||||
|
eclipse.preferences.version=1
|
||||||
|
include_path=0;/djh5
|
||||||
|
use_asp_tags_as_php=false
|
|
@ -0,0 +1,381 @@
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
mapState,
|
||||||
|
mapActions,
|
||||||
|
mapMutations
|
||||||
|
} from "vuex"
|
||||||
|
import $api from "@/api/index.js"
|
||||||
|
import $store from "@/store/index.js"
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
timer: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async mounted() {
|
||||||
|
// #ifdef H5
|
||||||
|
if (typeof window.entryUrl === 'undefined' || window.entryUrl === '') {
|
||||||
|
window.entryUrl = window.location.href.split('#')[0]
|
||||||
|
}
|
||||||
|
if (window.location.href.indexOf('?#') < 0) {
|
||||||
|
window.location.href = window.location.href.replace("#", "?#");
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
console.log('App mounted')
|
||||||
|
},
|
||||||
|
async onLaunch() {
|
||||||
|
let configInfo = uni.getStorageSync('configInfo') || ''
|
||||||
|
if (configInfo) {
|
||||||
|
$store.commit('updateConfigItem', {
|
||||||
|
key: 'configInfo',
|
||||||
|
val: configInfo
|
||||||
|
})
|
||||||
|
}
|
||||||
|
let isGzhLogin = uni.getStorageSync('isGzhLogin') || false
|
||||||
|
$store.commit('updateUserItem', {
|
||||||
|
key: 'isGzhLogin',
|
||||||
|
val: isGzhLogin
|
||||||
|
})
|
||||||
|
console.log('isGzhLogin',isGzhLogin)
|
||||||
|
let arr = ['autograph', 'userInfo', 'location', 'appLogin', 'loginType']
|
||||||
|
|
||||||
|
arr.map(key => {
|
||||||
|
let val = uni.getStorageSync(key) || ''
|
||||||
|
// #ifdef H5
|
||||||
|
val = isGzhLogin ? val : ''
|
||||||
|
// #endif
|
||||||
|
$store.commit('updateUserItem', {
|
||||||
|
key,
|
||||||
|
val
|
||||||
|
})
|
||||||
|
// #ifdef APP-PLUS
|
||||||
|
if (key == 'userInfo') {
|
||||||
|
$store.commit('updateUserItem', {
|
||||||
|
key: 'isShowLogin',
|
||||||
|
val: val && val.id ? false : true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
})
|
||||||
|
let {
|
||||||
|
commonOptions
|
||||||
|
} = this
|
||||||
|
let {
|
||||||
|
coach_id = 0
|
||||||
|
} = commonOptions
|
||||||
|
if (coach_id) {
|
||||||
|
commonOptions.coach_id = 0
|
||||||
|
$store.commit('updateUserItem', {
|
||||||
|
key: 'commonOptions',
|
||||||
|
val: commonOptions
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.initIndex()
|
||||||
|
console.log('App onLaunch')
|
||||||
|
},
|
||||||
|
async onShow() {
|
||||||
|
if (this.timer) {
|
||||||
|
clearInterval(this.timer)
|
||||||
|
}
|
||||||
|
let {
|
||||||
|
coach_position = 0
|
||||||
|
} = this.userInfo
|
||||||
|
let {
|
||||||
|
id: coachId = 0,
|
||||||
|
status = 0
|
||||||
|
} = this.coachInfo
|
||||||
|
if (coach_position == 1) {
|
||||||
|
if (!coachId) {
|
||||||
|
await this.getCoachInfo()
|
||||||
|
}
|
||||||
|
$store.commit('updateUserItem', {
|
||||||
|
key: 'locationChange',
|
||||||
|
val: true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
uni.onNetworkStatusChange((res) => {
|
||||||
|
let {
|
||||||
|
isConnected
|
||||||
|
} = res
|
||||||
|
if (isConnected) return
|
||||||
|
let methodArr = ['updateServiceItem', 'updateTechnicianItem']
|
||||||
|
methodArr.map(item => {
|
||||||
|
$store.commit(item, {
|
||||||
|
key: 'pageActive',
|
||||||
|
val: false
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
async onHide() {
|
||||||
|
console.log('App Hide')
|
||||||
|
let {
|
||||||
|
coach_position = 0
|
||||||
|
} = this.userInfo
|
||||||
|
let {
|
||||||
|
status = 0
|
||||||
|
} = this.coachInfo
|
||||||
|
if (!coach_position || status != 2) return
|
||||||
|
$store.commit('updateUserItem', {
|
||||||
|
key: 'locationChange',
|
||||||
|
val: false
|
||||||
|
})
|
||||||
|
// #ifdef H5
|
||||||
|
if (this.$jweixin.isWechat()) {
|
||||||
|
await this.$jweixin.wxReady2();
|
||||||
|
this.toHidePage()
|
||||||
|
this.timer = setInterval(() => {
|
||||||
|
this.toHidePage()
|
||||||
|
}, 60000)
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
},
|
||||||
|
onUnload() {
|
||||||
|
uni.offLocationChange((res) => {
|
||||||
|
console.log("====offLocationChange onUnload", res)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
locationChange(newVal, oldVal) {
|
||||||
|
if (newVal) {
|
||||||
|
uni.startLocationUpdate({
|
||||||
|
complete: msg => console.log(`startLocationUpdate API complete`, msg)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
uni.stopLocationUpdate({
|
||||||
|
complete: msg => console.log(`stopLocationUpdate API complete`, msg)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'configInfo.attendant_name'(newVal, oldVal) {
|
||||||
|
if (newVal) {
|
||||||
|
this.mergeLocaleMessage()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
computed: mapState({
|
||||||
|
configInfo: state => state.config.configInfo,
|
||||||
|
old_attendant_name: state => state.config.old_attendant_name,
|
||||||
|
commonOptions: state => state.user.commonOptions,
|
||||||
|
locationChange: state => state.user.locationChange,
|
||||||
|
locationChangeUnix: state => state.user.locationChangeUnix,
|
||||||
|
userInfo: state => state.user.userInfo,
|
||||||
|
coachInfo: state => state.user.coachInfo,
|
||||||
|
}),
|
||||||
|
methods: {
|
||||||
|
...mapActions(['getConfigInfo', 'getUserInfo', 'getCoachInfo']),
|
||||||
|
async initIndex() {
|
||||||
|
|
||||||
|
let that = this
|
||||||
|
let {
|
||||||
|
coach_position = 0
|
||||||
|
} = that.userInfo
|
||||||
|
uni.onLocationChange((res) => {
|
||||||
|
console.log("====onLocationChange", res)
|
||||||
|
let {
|
||||||
|
latitude: lat,
|
||||||
|
longitude: lng
|
||||||
|
} = res
|
||||||
|
that.toChangeLocation({
|
||||||
|
lat,
|
||||||
|
lng
|
||||||
|
})
|
||||||
|
})
|
||||||
|
if (coach_position == 1) {
|
||||||
|
let {
|
||||||
|
id: coachId = 0
|
||||||
|
} = that.coachInfo
|
||||||
|
if (!coachId) {
|
||||||
|
await that.getCoachInfo()
|
||||||
|
}
|
||||||
|
$store.commit('updateUserItem', {
|
||||||
|
key: 'locationChange',
|
||||||
|
val: true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
let {
|
||||||
|
primaryColor = '',
|
||||||
|
plugAuth = {},
|
||||||
|
tabBar = []
|
||||||
|
} = that.configInfo
|
||||||
|
let mineInd = tabBar.findIndex(item => {
|
||||||
|
return item.id == 5
|
||||||
|
})
|
||||||
|
console.log(mineInd, "======mineInd")
|
||||||
|
// if ((primaryColor && plugAuth.length > 0) || mineInd != -1) return
|
||||||
|
await that.getConfigInfo()
|
||||||
|
},
|
||||||
|
async mergeLocaleMessage() {
|
||||||
|
let zh = JSON.parse(JSON.stringify(this.$i18n.messages.zh))
|
||||||
|
let {
|
||||||
|
attendant_name: name,
|
||||||
|
} = this.configInfo
|
||||||
|
let oldName = this.old_attendant_name
|
||||||
|
let reg = new RegExp(oldName, 'g')
|
||||||
|
for (let i in zh.action) {
|
||||||
|
if (zh.action[i].includes(oldName)) {
|
||||||
|
zh.action[i] = zh.action[i].replace(reg, name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.$i18n.mergeLocaleMessage('zh', zh)
|
||||||
|
$store.commit('updateConfigItem', {
|
||||||
|
key: 'old_attendant_name',
|
||||||
|
val: name
|
||||||
|
})
|
||||||
|
// console.log(this.$t('action.attendantName'), this.$i18n.messages.zh, "=====");
|
||||||
|
},
|
||||||
|
async toHidePage() {
|
||||||
|
let {
|
||||||
|
latitude: lat,
|
||||||
|
longitude: lng
|
||||||
|
} = await this.$jweixin.getWxLocation()
|
||||||
|
if (lat && lng) {
|
||||||
|
let val = this.$util.DateToUnix(this.$util.formatTime(new Date(), 'YY-M-D h:m:s'))
|
||||||
|
$store.commit('updateUserItem', {
|
||||||
|
key: 'locationChangeUnix',
|
||||||
|
val
|
||||||
|
})
|
||||||
|
this.toChangeLocation({
|
||||||
|
lat,
|
||||||
|
lng
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async toChangeLocation(param) {
|
||||||
|
let {
|
||||||
|
lat,
|
||||||
|
lng
|
||||||
|
} = param
|
||||||
|
let {
|
||||||
|
id = 0,
|
||||||
|
coach_position = 0
|
||||||
|
} = this.userInfo
|
||||||
|
let {
|
||||||
|
lat: coach_lat,
|
||||||
|
lng: coach_lng,
|
||||||
|
status = 0
|
||||||
|
} = this.coachInfo
|
||||||
|
let {
|
||||||
|
locationChangeUnix
|
||||||
|
} = this
|
||||||
|
let curUnix = this.$util.DateToUnix(this.$util.formatTime(new Date(), 'YY-M-D h:m:s'))
|
||||||
|
let second = 3
|
||||||
|
// #ifdef APP-PLUS
|
||||||
|
second = 1
|
||||||
|
// #endif
|
||||||
|
// console.log(curUnix, locationChangeUnix, curUnix - locationChangeUnix,
|
||||||
|
// "=====curUnix - locationChangeUnix")
|
||||||
|
let isMin = curUnix - locationChangeUnix <= second || curUnix - locationChangeUnix >= 60
|
||||||
|
let isSame = coach_lat * 1 == lat && coach_lng * 1 == lng
|
||||||
|
// console.log(lat, lng, coach_position, isMin, isSame, "=====lat, lng, coach_position, isMin")
|
||||||
|
if (!coach_position || status != 2 || !isMin || isSame) return
|
||||||
|
|
||||||
|
let val = this.$util.DateToUnix(this.$util.formatTime(new Date(), 'YY-M-D h:m:s'))
|
||||||
|
$store.commit('updateUserItem', {
|
||||||
|
key: 'locationChangeUnix',
|
||||||
|
val
|
||||||
|
})
|
||||||
|
|
||||||
|
let key = `${lat},${lng}`
|
||||||
|
try {
|
||||||
|
let data = await this.$api.base.getMapInfo({
|
||||||
|
location: key
|
||||||
|
})
|
||||||
|
let {
|
||||||
|
status,
|
||||||
|
result
|
||||||
|
} = JSON.parse(data)
|
||||||
|
if (status == 0) {
|
||||||
|
let {
|
||||||
|
address
|
||||||
|
} = result
|
||||||
|
console.log("toChangeLocation==>", `${lat}-${lng}-${address}`)
|
||||||
|
await this.$api.technician.coachUpdate({
|
||||||
|
lat,
|
||||||
|
lng,
|
||||||
|
address
|
||||||
|
})
|
||||||
|
await this.getCoachInfo()
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.log('=====getMapInfo catch')
|
||||||
|
uni.stopLocationUpdate({
|
||||||
|
complete: msg => console.log(`stopLocationUpdate API complete`, msg)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
@import "/styles/index.wxss";
|
||||||
|
|
||||||
|
/* #ifdef H5 */
|
||||||
|
uni-page-head {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* #endif */
|
||||||
|
|
||||||
|
page {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #222;
|
||||||
|
line-height: 1.5;
|
||||||
|
background: #F6F6F6;
|
||||||
|
font-family: -apple-system-font, Helvetica Neue, Helvetica, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
// font-family: PingFangSC-Medium, PingFang SC, -apple-system-font, Helvetica Neue, Helvetica, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
input::-webkit-input-placeholder {
|
||||||
|
/* WebKit browsers */
|
||||||
|
color: #A9A9A9;
|
||||||
|
}
|
||||||
|
|
||||||
|
input:-moz-placeholder {
|
||||||
|
/* Mozilla Firefox 4 to 18 */
|
||||||
|
color: #A9A9A9;
|
||||||
|
}
|
||||||
|
|
||||||
|
input::-moz-placeholder {
|
||||||
|
/* Mozilla Firefox 19+ */
|
||||||
|
color: #A9A9A9;
|
||||||
|
}
|
||||||
|
|
||||||
|
input:-ms-input-placeholder {
|
||||||
|
/* Internet Explorer 10+ */
|
||||||
|
color: #A9A9A9;
|
||||||
|
}
|
||||||
|
|
||||||
|
view {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
image {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.h5-image {
|
||||||
|
background-position: center center;
|
||||||
|
background-size: cover;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*隐藏滚动条*/
|
||||||
|
::-webkit-scrollbar {
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* #ifdef MP-BAIDU */
|
||||||
|
.swan-button.swan-button-radius-ios {
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* #endif */
|
||||||
|
</style>
|
|
@ -0,0 +1,135 @@
|
||||||
|
<template>
|
||||||
|
<view class="agent-account pd-lg" v-if="isLoad">
|
||||||
|
|
||||||
|
<view class="pt-md pb-md c-title text-bold" style="font-size:34rpx">账号信息</view>
|
||||||
|
|
||||||
|
<view class="flex-warp pb-lg">
|
||||||
|
<view class="f-paragraph">账号名称</view>
|
||||||
|
<view class="f-desc">{{detail.username}}</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-warp pb-lg">
|
||||||
|
<view class="f-paragraph">账号密码</view>
|
||||||
|
<view class="f-desc">{{detail.passwd_text | handlePassWord}}</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-warp pb-lg">
|
||||||
|
<view class="f-paragraph">真实姓名</view>
|
||||||
|
<view class="f-desc">{{detail.agent_name}}</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-warp pt-lg pb-lg b-1px-t">
|
||||||
|
<view class="f-paragraph">当前等级</view>
|
||||||
|
<view class="f-desc">{{cityType[detail.city_type]}}代理({{detail.city_name}})</view>
|
||||||
|
</view>
|
||||||
|
<!-- 省/市 查下级;区县查上级 -->
|
||||||
|
<view class="flex-warp pb-lg" v-if="detail.city_type != 3">
|
||||||
|
<view class="f-paragraph">关联上级代理</view>
|
||||||
|
<view class="f-desc">
|
||||||
|
{{detail.top_data && detail.top_data.hasOwnProperty('username')?detail.top_data.username:'-'}}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-warp pb-lg" v-if="detail.city_type != 2">
|
||||||
|
<view class="f-paragraph">关联下级代理</view>
|
||||||
|
<view class="f-desc">
|
||||||
|
<block v-if="detail.sub_data.length==0">-</block>
|
||||||
|
<view class="mb-sm" v-for="(item,index) in detail.sub_data" :key="index">{{item.agent_name}}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
mapState,
|
||||||
|
mapMutations
|
||||||
|
} from "vuex"
|
||||||
|
export default {
|
||||||
|
components: {},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
isLoad: false,
|
||||||
|
detail: {},
|
||||||
|
cityType: {
|
||||||
|
1: '城市',
|
||||||
|
2: '区县',
|
||||||
|
3: '省'
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
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,
|
||||||
|
}),
|
||||||
|
onLoad() {
|
||||||
|
this.initIndex()
|
||||||
|
},
|
||||||
|
onPullDownRefresh() {
|
||||||
|
// #ifndef APP-PLUS
|
||||||
|
uni.showNavigationBarLoading()
|
||||||
|
// #endif
|
||||||
|
this.initRefresh();
|
||||||
|
uni.stopPullDownRefresh()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
...mapMutations([]),
|
||||||
|
async initIndex(refresh = false) {
|
||||||
|
// #ifdef H5
|
||||||
|
if (!refresh && this.$jweixin.isWechat()) {
|
||||||
|
await this.$jweixin.initJssdk();
|
||||||
|
this.$jweixin.wxReady(() => {
|
||||||
|
this.$jweixin.hideOptionMenu()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
this.$util.showLoading()
|
||||||
|
this.detail = await this.$api.agent.adminInfoData()
|
||||||
|
this.$util.setNavigationBarColor({
|
||||||
|
bg: this.primaryColor
|
||||||
|
})
|
||||||
|
this.isLoad = true
|
||||||
|
this.$util.hideAll()
|
||||||
|
},
|
||||||
|
initRefresh() {
|
||||||
|
this.initIndex(true)
|
||||||
|
},
|
||||||
|
toJump(key, index) {
|
||||||
|
let {
|
||||||
|
url
|
||||||
|
} = this[key][index]
|
||||||
|
this.$util.goUrl({
|
||||||
|
url
|
||||||
|
})
|
||||||
|
},
|
||||||
|
},
|
||||||
|
filters: {
|
||||||
|
handlePassWord(val) {
|
||||||
|
let len = val.length
|
||||||
|
let text = val.substring(0, len > 6 ? 3 : 1) + '***'
|
||||||
|
text += val.substring(len == 6 ? len - 2 : len - 3, len)
|
||||||
|
return text
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
page {
|
||||||
|
background: #fff
|
||||||
|
}
|
||||||
|
|
||||||
|
.agent-account {
|
||||||
|
|
||||||
|
.f-paragraph {
|
||||||
|
width: 200rpx;
|
||||||
|
color: #4A4A4A;
|
||||||
|
}
|
||||||
|
|
||||||
|
.f-desc {
|
||||||
|
width: 490rpx;
|
||||||
|
color: #777777;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,315 @@
|
||||||
|
<template>
|
||||||
|
<view class="apply-pages" v-if="isLoad">
|
||||||
|
|
||||||
|
<view class="page-height" v-if="mineInfo.is_admin">
|
||||||
|
<abnor percent="150%" @confirm="$util.goUrl({url:`/agent/pages/index?agent=1`,openType: `reLaunch`})"
|
||||||
|
title="您已经是代理商了" :tip="[{ text: '快去管理订单吧', color: 0 }]" :button="[{ text: '去管理', type: 'confirm' }]"
|
||||||
|
image="https://lbqny.migugu.com/admin/public/apply_suc.jpg"></abnor>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<block v-else>
|
||||||
|
|
||||||
|
<view class="apply-info-box rel" :style="{background:primaryColor}">
|
||||||
|
<image class="bg-1 abs" src="https://lbqny.migugu.com/admin/anmo/apply/bg-4.png">
|
||||||
|
</image>
|
||||||
|
<image class="bg-2 abs" src="https://lbqny.migugu.com/admin/anmo/apply/bg-3.png">
|
||||||
|
</image>
|
||||||
|
<image class="join-us abs" src="https://lbqny.migugu.com/admin/anmo/apply/join-us-1.png">
|
||||||
|
</image>
|
||||||
|
<view class="join-us pd-lg abs" style="z-index: 3;">
|
||||||
|
<view style="height:90rpx"></view>
|
||||||
|
<view class="f-title c-title text-bold">您的姓名</view>
|
||||||
|
<input v-model="form.user_name" type="text"
|
||||||
|
class="item-input fill-base f-mini-title c-title mt-sm pl-lg pr-lg radius-10" maxlength="20"
|
||||||
|
placeholder-class="c-caption" :placeholder="rule[0].errorMsg"
|
||||||
|
:style="{borderColor:primaryColor}" />
|
||||||
|
<view class="mt-md f-title c-title text-bold">代理类型</view>
|
||||||
|
<view class="flex-y-center mt-sm">
|
||||||
|
<view @tap.stop="form.city_type = item.id" class="flex-y-center f-mini-title c-title"
|
||||||
|
:class="[{'mr-lg pr-lg':index!=2}]"
|
||||||
|
:style="{color:form.city_type == item.id ? primaryColor:''}"
|
||||||
|
v-for="(item,index) in cityList" :key="index"><i class="iconfont mr-sm"
|
||||||
|
:class="[{'icon-xuanze':form.city_type != item.id},{'icon-radio-fill':form.city_type == item.id}]"></i>{{item.title}}代理
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="mt-md f-title c-title text-bold">手机号</view>
|
||||||
|
<view class="item-input fill-base f-mini-title c-title mt-sm pl-lg pr-lg radius-10"
|
||||||
|
style="height:auto;min-height:82rpx" :style="{borderColor:primaryColor}">
|
||||||
|
<input v-model="form.phone" type="text" maxlength="20" placeholder-class="c-caption"
|
||||||
|
:placeholder="rule[1].errorMsg" style="margin-top: 15rpx;" />
|
||||||
|
<view class="flex-between" v-if="configInfo.short_code_status">
|
||||||
|
<input v-model="form.short_code" type="text" maxlength="6" placeholder-class="c-caption"
|
||||||
|
placeholder="请输入验证码" :style="{borderColor:primaryColor}" />
|
||||||
|
<view @tap.stop="toSend" :style="{color:primaryColor}">
|
||||||
|
{{authTime>0?`重新获取(${authTime}s)`:'获取验证码'}}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="mt-md f-title c-title text-bold">申请加入的区域</view>
|
||||||
|
<input v-model="form.city" type="text"
|
||||||
|
class="item-input fill-base f-mini-title c-title mt-sm pl-lg pr-lg radius-10" maxlength="50"
|
||||||
|
placeholder-class="c-caption" :placeholder="rule[2].errorMsg"
|
||||||
|
:style="{borderColor:primaryColor}" />
|
||||||
|
</view>
|
||||||
|
<image @tap.stop="submit" class="submit abs"
|
||||||
|
src="https://lbqny.migugu.com/admin/anmo/apply/submit-1.png">
|
||||||
|
</image>
|
||||||
|
</view>
|
||||||
|
</block>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
mapState,
|
||||||
|
mapActions,
|
||||||
|
mapMutations
|
||||||
|
} from "vuex"
|
||||||
|
export default {
|
||||||
|
components: {},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
isLoad: false,
|
||||||
|
options: {},
|
||||||
|
authTime: 0,
|
||||||
|
timer: null,
|
||||||
|
cityList: [{
|
||||||
|
id: 3,
|
||||||
|
title: '省'
|
||||||
|
}, {
|
||||||
|
id: 1,
|
||||||
|
title: '城市'
|
||||||
|
}, {
|
||||||
|
id: 2,
|
||||||
|
title: '区县'
|
||||||
|
}],
|
||||||
|
form: {
|
||||||
|
user_name: '', //姓名
|
||||||
|
city_type: 3,
|
||||||
|
phone: '', //手机号
|
||||||
|
short_code: '',
|
||||||
|
city: ''
|
||||||
|
},
|
||||||
|
rule: [{
|
||||||
|
name: "user_name",
|
||||||
|
checkType: "isNotNull",
|
||||||
|
errorMsg: "输入您的姓名",
|
||||||
|
regType: 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "phone",
|
||||||
|
checkType: "isMobile",
|
||||||
|
errorMsg: "输入手机号"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "city",
|
||||||
|
checkType: "isNotNull",
|
||||||
|
errorMsg: "请输入您想代理的区域"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
lockTap: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: mapState({
|
||||||
|
primaryColor: state => state.config.configInfo.primaryColor,
|
||||||
|
subColor: state => state.config.configInfo.subColor,
|
||||||
|
configInfo: state => state.config.configInfo,
|
||||||
|
mineInfo: state => state.user.mineInfo,
|
||||||
|
}),
|
||||||
|
async onLoad(options) {
|
||||||
|
this.options = options
|
||||||
|
this.$util.showLoading()
|
||||||
|
await this.initIndex()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
...mapActions(['getConfigInfo', 'getMineInfo']),
|
||||||
|
...mapMutations(['updateUserItem']),
|
||||||
|
async initIndex(refresh = false) {
|
||||||
|
// #ifdef H5
|
||||||
|
if (!refresh && this.$jweixin.isWechat()) {
|
||||||
|
await this.$jweixin.initJssdk();
|
||||||
|
this.$jweixin.wxReady(() => {
|
||||||
|
this.$jweixin.hideOptionMenu()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
if (!this.configInfo.id || !this.configInfo.hasOwnProperty(
|
||||||
|
'plugAuth') || (this.configInfo.hasOwnProperty(
|
||||||
|
'plugAuth') && !this.configInfo.plugAuth.hasOwnProperty(
|
||||||
|
'store')) || refresh) {
|
||||||
|
await this.getConfigInfo()
|
||||||
|
}
|
||||||
|
await this.getMineInfo()
|
||||||
|
let {
|
||||||
|
is_admin = 0
|
||||||
|
} = this.mineInfo
|
||||||
|
uni.setNavigationBarTitle({
|
||||||
|
title: is_admin ? '' : '招商加盟'
|
||||||
|
})
|
||||||
|
this.$util.setNavigationBarColor({
|
||||||
|
bg: this.primaryColor
|
||||||
|
})
|
||||||
|
this.$util.hideAll()
|
||||||
|
this.isLoad = true
|
||||||
|
},
|
||||||
|
initRefresh() {
|
||||||
|
this.initIndex(true)
|
||||||
|
},
|
||||||
|
// 发送验证码
|
||||||
|
async toSend() {
|
||||||
|
let {
|
||||||
|
authTime
|
||||||
|
} = this
|
||||||
|
if (authTime) return
|
||||||
|
let {
|
||||||
|
phone = ''
|
||||||
|
} = this.form
|
||||||
|
if (phone == null || !/^(1[0-9]{10})$/.test(phone)) {
|
||||||
|
this.$util.showToast({
|
||||||
|
title: phone == null ? `请输入手机号` : `${phone} 手机号无效`
|
||||||
|
});
|
||||||
|
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) {
|
||||||
|
clearInterval(this.timer)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
time--
|
||||||
|
this.authTime = time
|
||||||
|
}, 1000)
|
||||||
|
} catch (e) {
|
||||||
|
setTimeout(() => {
|
||||||
|
this.lockTap = false
|
||||||
|
this.$util.hideAll()
|
||||||
|
}, 2000)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
//表单验证
|
||||||
|
validate(param) {
|
||||||
|
let validate = new this.$util.Validate();
|
||||||
|
this.rule.map(item => {
|
||||||
|
let {
|
||||||
|
name,
|
||||||
|
} = item
|
||||||
|
validate.add(param[name], item);
|
||||||
|
})
|
||||||
|
let message = validate.start();
|
||||||
|
return message;
|
||||||
|
},
|
||||||
|
async submit() {
|
||||||
|
let param = this.$util.deepCopy(this.form)
|
||||||
|
let msg = this.validate(param);
|
||||||
|
if (msg) {
|
||||||
|
this.$util.showToast({
|
||||||
|
title: msg
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let {
|
||||||
|
short_code_status
|
||||||
|
} = this.configInfo
|
||||||
|
if (short_code_status && (param.short_code == null || param.short_code.length != 6)) {
|
||||||
|
this.$util.showToast({
|
||||||
|
title: `请输入6位数短信验证码`
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!short_code_status) {
|
||||||
|
delete param.short_code
|
||||||
|
}
|
||||||
|
if (this.lockTap) return
|
||||||
|
this.lockTap = true
|
||||||
|
this.$util.showLoading()
|
||||||
|
try {
|
||||||
|
await this.$api.agent.agentApply(param)
|
||||||
|
this.$util.hideAll()
|
||||||
|
this.$util.showToast({
|
||||||
|
title: `提交成功,即将跳转个人中心`,
|
||||||
|
})
|
||||||
|
if (this.timer) {
|
||||||
|
clearInterval(this.timer)
|
||||||
|
}
|
||||||
|
setTimeout(() => {
|
||||||
|
if (getCurrentPages().length > 1) {
|
||||||
|
this.$util.back()
|
||||||
|
}
|
||||||
|
this.$util.goUrl({
|
||||||
|
url: '/pages/mine',
|
||||||
|
openType: `reLaunch`
|
||||||
|
})
|
||||||
|
}, 2000)
|
||||||
|
} catch (e) {
|
||||||
|
setTimeout(() => {
|
||||||
|
this.lockTap = false
|
||||||
|
this.$util.hideAll()
|
||||||
|
}, 2000)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.apply-info-box {
|
||||||
|
width: 100%;
|
||||||
|
height: 1632rpx;
|
||||||
|
|
||||||
|
.bg-1 {
|
||||||
|
width: 750rpx;
|
||||||
|
height: 1632rpx;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-2 {
|
||||||
|
width: 750rpx;
|
||||||
|
height: 575rpx;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
z-index: 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.join-us {
|
||||||
|
width: 671rpx;
|
||||||
|
height: 890rpx;
|
||||||
|
top: 482rpx;
|
||||||
|
left: 44rpx;
|
||||||
|
z-index: 2;
|
||||||
|
|
||||||
|
.item-input {
|
||||||
|
height: 74rpx;
|
||||||
|
border: 4rpx solid #069F5E;
|
||||||
|
|
||||||
|
.flex-between {
|
||||||
|
height: 74rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-input.text {
|
||||||
|
height: 82rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.submit {
|
||||||
|
width: 662rpx;
|
||||||
|
height: 93rpx;
|
||||||
|
top: 1400rpx;
|
||||||
|
left: 47rpx;
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,576 @@
|
||||||
|
<template>
|
||||||
|
<view class="agent-income-commission" v-if="isLoad">
|
||||||
|
|
||||||
|
|
||||||
|
<fixed @height="initFixHeight" zIndex="997">
|
||||||
|
<view class="record-search-info fill-body pt-md pl-md c-base">
|
||||||
|
<view class="record-info radius-32" :style="{background:primaryColor}">
|
||||||
|
<view class="search-item flex-between ml-lg mr-lg f-desc b-1px-b">
|
||||||
|
<view>查询时间</view>
|
||||||
|
<view @tap.stop="toShowTimePopup($event)" class="flex-y-center">
|
||||||
|
{{ prev_time | handleTimeText(1) }}<i class="iconfont icon-right"></i>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="search-item flex-between ml-lg mr-lg f-desc">
|
||||||
|
<view>入账状态</view>
|
||||||
|
<view @tap.stop="$refs.show_status_item.open()" class="flex-y-center">
|
||||||
|
{{typeList[typeIndex].title}}<i class="iconfont icon-right"></i>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</fixed>
|
||||||
|
|
||||||
|
<block v-for="(item,index) in list.data" :key="index">
|
||||||
|
<view @tap.stop="toShowTimePopup($event,item.month)" class="count-item fill-body pl-md pr-md"
|
||||||
|
v-if="prev_time.activeIndex==0 && (index==0 || (index>0&&item.month!=list.data[index-1].month))">
|
||||||
|
<veiw class="title flex-y-center">
|
||||||
|
<view class="f-title c-title text-bold">{{item.month}}</view>
|
||||||
|
<i class="iconfont iconxia"></i>
|
||||||
|
</veiw>
|
||||||
|
<view class="f-caption c-caption">获得总提成¥{{item.total_cash}}({{cityType[item.my_city_type]}}代理)
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view @tap.stop="toShowTimePopup($event,item.month)" class="count-item fill-body pl-md pr-md"
|
||||||
|
v-if="prev_time.activeIndex==1 && index==0">
|
||||||
|
<veiw class="title flex-y-center">
|
||||||
|
<view class="f-title c-title text-bold">{{prev_time | handleTimeText(2)}}</view>
|
||||||
|
<i class="iconfont iconxia"></i>
|
||||||
|
</veiw>
|
||||||
|
<view class="f-caption c-caption">获得总提成¥{{item.total_cash}}({{cityType[item.my_city_type]}}代理)
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="list-item ml-md mr-md fill-base radius-16" :class="[{'mt-md':index!==0}]">
|
||||||
|
<view class="flex-between pt-lg pb-lg ml-lg mr-lg b-1px-b">
|
||||||
|
<view class="flex-y-center f-caption c-caption">{{$t('action.attendantName')}}
|
||||||
|
<view class="f-paragraph c-title text-bold ml-md max-380 ellipsis">
|
||||||
|
{{item.coach_info.coach_name}}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="f-paragraph text-bold" :style="{color:item.status==1?subColor:primaryColor}">
|
||||||
|
{{statusType[item.have_tx]}}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="pd-lg f-caption">
|
||||||
|
<view class="flex-warp">
|
||||||
|
<view class="item-text c-paragraph">创建时间: </view>
|
||||||
|
<view class="c-title">{{item.create_time}}</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-warp mt-md">
|
||||||
|
<view class="item-text c-paragraph">服务时间: </view>
|
||||||
|
<view class="c-title">{{item.start_time}}</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-warp mt-md">
|
||||||
|
<view class="item-text c-paragraph">项目: </view>
|
||||||
|
<view class="c-title" style="max-width:410rpx">
|
||||||
|
<view :class="[{'mt-md':aindex!=0}]" v-for="(aitem,aindex) in item.order_goods"
|
||||||
|
:key="aindex">
|
||||||
|
{{aitem.goods_name}}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-warp mt-md">
|
||||||
|
<view class="item-text c-paragraph">订单实际支付价格: </view>
|
||||||
|
<view class="flex-y-center c-title">
|
||||||
|
<view class="mr-sm">¥{{item.pay_price}}</view>
|
||||||
|
<block v-if="item.true_car_price*1>0">(含车费¥{{item.true_car_price}})</block>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-warp mt-lg pt-md">
|
||||||
|
<view class="item-text c-paragraph">{{$t('action.attendantName')}}分成: </view>
|
||||||
|
<view class="c-title" :style="{color:primaryColor}">¥{{item.coach_cash}}</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-warp mt-md" v-for="(aitem,aindex) in item.admin_cash_list" :key="aindex">
|
||||||
|
<view class="item-text c-paragraph">{{cityType[aitem.city_type]}}代理分成: </view>
|
||||||
|
<view class="c-title" :style="{color:primaryColor}">¥{{aitem.cash}}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
</block>
|
||||||
|
|
||||||
|
<load-more :noMore="list.current_page>=list.last_page&&list.data.length>0" :loading="loading" v-if="loading">
|
||||||
|
</load-more>
|
||||||
|
<abnor v-if="!loading&&list.data.length<=0&&list.current_page==1"></abnor>
|
||||||
|
|
||||||
|
<view class="space-footer"></view>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<uni-popup ref="show_choose_time" type="bottom">
|
||||||
|
<view class="popup-choose-time fill-base">
|
||||||
|
<view class="pl-lg pr-lg">
|
||||||
|
<view class="flex-between b-1px-b">
|
||||||
|
<tab @change="handerTabChange" :list="tabList" :activeIndex="activeIndex*1"
|
||||||
|
:activeColor="primaryColor" height="100rpx"></tab>
|
||||||
|
<i @tap.stop="toClose" class="iconfont icon-close"></i>
|
||||||
|
</view>
|
||||||
|
<view class="flex-center mt-md pt-lg pb-lg">
|
||||||
|
<view class="flex-1 flex-y-baseline">
|
||||||
|
<view class="f-paragraph c-title text-bold">{{activeIndex==0?'选择月份':'自定义时间'}}</view>
|
||||||
|
<view class="f-caption c-warning ml-sm" v-if="activeIndex==1">最长可查找时间跨度一年的交易</view>
|
||||||
|
</view>
|
||||||
|
<view class="f-paragraph" @tap.stop="toReset" style="color: #5A677E;"
|
||||||
|
v-if="(activeIndex==0&&check_time.month) || (activeIndex==1&&(check_time.start_time || check_time.end_time))">
|
||||||
|
清除</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-center pb-lg" v-if="activeIndex==0">
|
||||||
|
<view @tap.stop="toShowTime('month')" class="item-child flex-center flex-column">
|
||||||
|
<view>开始月份</view>
|
||||||
|
<view class="mt-sm" :style="{color:check_time.month ? primaryColor : '#999'}">
|
||||||
|
{{check_time.month || '选择月份'}}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-center pb-lg" v-if="activeIndex==1">
|
||||||
|
<view @tap.stop="toShowTime('start_time')" class="item-child flex-center flex-column">
|
||||||
|
<view>开始时间</view>
|
||||||
|
<view class="mt-sm" :style="{color:check_time.start_time ? primaryColor : '#999'}">
|
||||||
|
{{check_time.start_time || '选择时间'}}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view @tap.stop="toShowTime('end_time')" class="item-child flex-center flex-column b-1px-l">
|
||||||
|
<view>结束时间</view>
|
||||||
|
<view class="mt-sm" :style="{color:check_time.end_time ? primaryColor : '#999'}">
|
||||||
|
{{check_time.end_time || '选择时间'}}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-center flex-column fill-body">
|
||||||
|
<view class="space-lg"></view>
|
||||||
|
<view @tap.stop="toConfirm" class="confirm-btn flex-center f-title c-base radius-16"
|
||||||
|
:style="{background: primaryColor}">确定</view>
|
||||||
|
<view class="space-lg"></view>
|
||||||
|
<view class="space-safe"></view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</uni-popup>
|
||||||
|
|
||||||
|
<w-picker mode="date" :startYear="startYear*1-10" :endYear="startYear"
|
||||||
|
:value="activeIndex == 0 ?curMonth:curDay" :current="false" :fields="activeIndex == 0 ?'month':'day'"
|
||||||
|
@confirm="onConfirm($event)" :disabled-after="false" ref="day" :themeColor="primaryColor"
|
||||||
|
:visible.sync="showDate">
|
||||||
|
</w-picker>
|
||||||
|
|
||||||
|
<uni-popup type="bottom" ref="show_status_item" :custom="true">
|
||||||
|
<view class="popup-status pd-lg fill-base">
|
||||||
|
<view @tap.stop="handerTypeChange(index)" class="flex-center f-paragraph mb-lg"
|
||||||
|
:class="[{'mt-lg':index==0}]" :style="{color:typeIndex==index?primaryColor:''}"
|
||||||
|
v-for="(item,index) in typeList" :key="index">
|
||||||
|
{{item.title}}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</uni-popup>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
mapState,
|
||||||
|
mapMutations
|
||||||
|
} from "vuex"
|
||||||
|
import $util from "@/utils/index.js"
|
||||||
|
import wPicker from "@/components/w-picker/w-picker.vue";
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
wPicker
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
isLoad: false,
|
||||||
|
popupHeight: '',
|
||||||
|
curDay: '',
|
||||||
|
curMonth: '',
|
||||||
|
startYear: '',
|
||||||
|
showKey: '',
|
||||||
|
showDate: false,
|
||||||
|
time_text: '',
|
||||||
|
prev_time: {
|
||||||
|
activeIndex: 0,
|
||||||
|
month: '',
|
||||||
|
start_time: '',
|
||||||
|
end_time: ''
|
||||||
|
},
|
||||||
|
check_time: {
|
||||||
|
activeIndex: 0,
|
||||||
|
month: '',
|
||||||
|
start_time: '',
|
||||||
|
end_time: ''
|
||||||
|
},
|
||||||
|
activeIndex: 0,
|
||||||
|
tabList: [{
|
||||||
|
id: 1,
|
||||||
|
title: '月份选择'
|
||||||
|
}, {
|
||||||
|
id: 2,
|
||||||
|
title: '自定义时间'
|
||||||
|
}],
|
||||||
|
typeIndex: 0,
|
||||||
|
typeList: [{
|
||||||
|
title: '全部',
|
||||||
|
id: -1
|
||||||
|
}, {
|
||||||
|
title: '未到账',
|
||||||
|
id: 0,
|
||||||
|
}, {
|
||||||
|
title: '已到账',
|
||||||
|
id: 1
|
||||||
|
}],
|
||||||
|
statusType: {
|
||||||
|
0: '未到账',
|
||||||
|
1: '已到账'
|
||||||
|
},
|
||||||
|
cityType: ['', '城市', '区县', '省'],
|
||||||
|
param: {
|
||||||
|
page: 1,
|
||||||
|
start_time: '',
|
||||||
|
end_time: ''
|
||||||
|
},
|
||||||
|
list: {
|
||||||
|
data: []
|
||||||
|
},
|
||||||
|
loading: true,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: mapState({
|
||||||
|
primaryColor: state => state.config.configInfo.primaryColor,
|
||||||
|
subColor: state => state.config.configInfo.subColor,
|
||||||
|
}),
|
||||||
|
async onLoad() {
|
||||||
|
this.$util.showLoading()
|
||||||
|
let cur_time = new Date(Math.ceil(new Date().getTime()))
|
||||||
|
this.curDay = this.$util.formatTime(cur_time, 'YY-M-D')
|
||||||
|
this.curMonth = this.$util.formatTime(cur_time, 'YY-M')
|
||||||
|
this.startYear = this.$util.formatTime(cur_time, 'YY')
|
||||||
|
await this.initIndex()
|
||||||
|
this.isLoad = true
|
||||||
|
},
|
||||||
|
onPullDownRefresh() {
|
||||||
|
// #ifndef APP-PLUS
|
||||||
|
uni.showNavigationBarLoading()
|
||||||
|
// #endif
|
||||||
|
this.initRefresh();
|
||||||
|
uni.stopPullDownRefresh()
|
||||||
|
},
|
||||||
|
onReachBottom() {
|
||||||
|
if (this.list.current_page >= this.list.last_page || this.loading) return;
|
||||||
|
this.param.page = this.param.page + 1;
|
||||||
|
this.loading = true;
|
||||||
|
this.getList();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
...mapMutations([]),
|
||||||
|
async initIndex(refresh = false) {
|
||||||
|
// #ifdef H5
|
||||||
|
if (!refresh && this.$jweixin.isWechat()) {
|
||||||
|
await this.$jweixin.initJssdk();
|
||||||
|
this.$jweixin.wxReady(() => {
|
||||||
|
this.$jweixin.hideOptionMenu()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
await this.getList()
|
||||||
|
this.$util.setNavigationBarColor({
|
||||||
|
bg: this.primaryColor
|
||||||
|
})
|
||||||
|
},
|
||||||
|
initRefresh() {
|
||||||
|
this.param.page = 1
|
||||||
|
this.initIndex(true)
|
||||||
|
},
|
||||||
|
async getList(page) {
|
||||||
|
if (page) {
|
||||||
|
this.param.page = 1
|
||||||
|
this.list.data = []
|
||||||
|
uni.pageScrollTo({
|
||||||
|
scrollTop: 0
|
||||||
|
})
|
||||||
|
}
|
||||||
|
let {
|
||||||
|
list: oldList,
|
||||||
|
param,
|
||||||
|
activeIndex,
|
||||||
|
typeIndex,
|
||||||
|
typeList
|
||||||
|
} = this
|
||||||
|
let {
|
||||||
|
id
|
||||||
|
} = typeList[typeIndex]
|
||||||
|
if (id != -1) {
|
||||||
|
param.have_tx = id
|
||||||
|
}
|
||||||
|
let {
|
||||||
|
month,
|
||||||
|
start_time,
|
||||||
|
end_time
|
||||||
|
} = this.$util.deepCopy(this.check_time)
|
||||||
|
if (activeIndex == 0) {
|
||||||
|
param.month = month ? this.$util.DateToUnix(`${month}-01`) : ''
|
||||||
|
}
|
||||||
|
if (activeIndex == 1) {
|
||||||
|
param.start_time = start_time && end_time ? this.$util.DateToUnix(start_time) : ''
|
||||||
|
param.end_time = start_time && end_time ? this.$util.DateToUnix(end_time) + 24 * 3600 - 1 : ''
|
||||||
|
}
|
||||||
|
let newList = await this.$api.agent.commList(param);
|
||||||
|
if (this.param.page == 1) {
|
||||||
|
this.list = newList
|
||||||
|
} else {
|
||||||
|
newList.data = oldList.data.concat(newList.data)
|
||||||
|
this.list = newList
|
||||||
|
}
|
||||||
|
this.loading = false
|
||||||
|
this.$util.hideAll()
|
||||||
|
},
|
||||||
|
initFixHeight(val) {
|
||||||
|
this.popupHeight = val
|
||||||
|
},
|
||||||
|
handerTabChange(index) {
|
||||||
|
this.activeIndex = index
|
||||||
|
this.check_time.activeIndex = index
|
||||||
|
},
|
||||||
|
handerTypeChange(index) {
|
||||||
|
this.typeIndex = index
|
||||||
|
this.getList(1)
|
||||||
|
this.$refs.show_status_item.close()
|
||||||
|
},
|
||||||
|
toChangeType(index) {
|
||||||
|
this.active = index
|
||||||
|
},
|
||||||
|
toShowTimePopup(e, month = 0) {
|
||||||
|
this.check_time = this.$util.deepCopy(this.prev_time)
|
||||||
|
if (month && month != 0) {
|
||||||
|
this.activeIndex = 0
|
||||||
|
this.curMonth = month
|
||||||
|
this.check_time.month = month
|
||||||
|
}
|
||||||
|
this.activeIndex = this.check_time.activeIndex
|
||||||
|
this.$refs.show_choose_time.open()
|
||||||
|
},
|
||||||
|
toReset() {
|
||||||
|
let {
|
||||||
|
activeIndex
|
||||||
|
} = this
|
||||||
|
if (activeIndex == 0) {
|
||||||
|
this.check_time.month = ''
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.check_time.start_time = ''
|
||||||
|
this.check_time.end_time = ''
|
||||||
|
this.getList(1)
|
||||||
|
},
|
||||||
|
async toClose() {
|
||||||
|
let {
|
||||||
|
activeIndex
|
||||||
|
} = this
|
||||||
|
let {
|
||||||
|
month,
|
||||||
|
start_time,
|
||||||
|
end_time
|
||||||
|
} = this.check_time
|
||||||
|
|
||||||
|
if ((activeIndex == 0 && !month) || (activeIndex == 1 && (!start_time || !end_time))) {
|
||||||
|
if (activeIndex == 1 && (!start_time || !end_time)) {
|
||||||
|
this.activeIndex = 0
|
||||||
|
this.check_time.activeIndex = 0
|
||||||
|
this.check_time.month = ''
|
||||||
|
}
|
||||||
|
this.prev_time = this.$util.deepCopy(this.check_time)
|
||||||
|
}
|
||||||
|
if ((activeIndex == 0 && month) || (activeIndex == 1 && (start_time && end_time))) {
|
||||||
|
this.check_time = this.$util.deepCopy(this.prev_time)
|
||||||
|
}
|
||||||
|
this.$refs.show_choose_time.close()
|
||||||
|
this.getList(1)
|
||||||
|
},
|
||||||
|
toShowTime(key) {
|
||||||
|
let {
|
||||||
|
activeIndex
|
||||||
|
} = this
|
||||||
|
if (activeIndex == 1 && key == 'end_time' && !this.check_time.start_time) {
|
||||||
|
this.$util.showToast({
|
||||||
|
title: `请选择开始时间`
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let showTime = this.check_time[key]
|
||||||
|
if (showTime) {
|
||||||
|
if (key == 'month') {
|
||||||
|
this.curMonth = showTime
|
||||||
|
} else {
|
||||||
|
this.curDay = showTime
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.showKey = key
|
||||||
|
this.showDate = true
|
||||||
|
},
|
||||||
|
async onConfirm(val) {
|
||||||
|
let {
|
||||||
|
start_time,
|
||||||
|
end_time
|
||||||
|
} = this.check_time
|
||||||
|
let {
|
||||||
|
showKey,
|
||||||
|
activeIndex = 0
|
||||||
|
} = this
|
||||||
|
let show_unit = this.$util.DateToUnix(showKey == 'month' ? `${val.result}-01` : val.result)
|
||||||
|
let start_unit = start_time ? this.$util.DateToUnix(start_time) : 0
|
||||||
|
let end_unit = end_time ? this.$util.DateToUnix(end_time) : 0
|
||||||
|
let cur_month = this.$util.formatTime(new Date(Math.ceil(new Date().getTime())), 'YY-M-D')
|
||||||
|
let cur_unit = this.$util.DateToUnix(cur_month) + 1
|
||||||
|
|
||||||
|
let msgType = {
|
||||||
|
month: '开始月份',
|
||||||
|
start_time: '开始时间',
|
||||||
|
end_time: '结束时间',
|
||||||
|
}
|
||||||
|
|
||||||
|
if (show_unit > cur_unit) {
|
||||||
|
this.$util.showToast({
|
||||||
|
title: `${msgType[showKey]}不能选择未来时间哦`
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (activeIndex == 1 && ((showKey == 'start_time' && end_unit && end_unit < this.$util.DateToUnix(val
|
||||||
|
.result)) ||
|
||||||
|
(showKey == 'end_time' && start_unit && start_unit > this.$util.DateToUnix(val.result)))) {
|
||||||
|
this.$util.showToast({
|
||||||
|
title: `结束时间不能小于开始时间`
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.check_time[showKey] = val.result
|
||||||
|
},
|
||||||
|
async toConfirm() {
|
||||||
|
let {
|
||||||
|
month = '',
|
||||||
|
start_time = '',
|
||||||
|
end_time = ''
|
||||||
|
} = this.check_time
|
||||||
|
let {
|
||||||
|
activeIndex = 0
|
||||||
|
} = this
|
||||||
|
let start_unit = this.$util.DateToUnix(start_time) * 1000
|
||||||
|
let end_unit = this.$util.DateToUnix(end_time) * 1000
|
||||||
|
|
||||||
|
if (activeIndex == 0 && !month) {
|
||||||
|
this.$util.showToast({
|
||||||
|
title: `请选择开始月份`
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (activeIndex == 1 && (!start_time || !end_time || (end_unit -
|
||||||
|
start_unit > 365 * 24 * 3600 * 1000))) {
|
||||||
|
this.$util.showToast({
|
||||||
|
title: !start_time ? `请选择开始时间` : !end_time ? `请选择结束时间` : `查询时间跨度最长为一年哦`
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.check_time.activeIndex = activeIndex
|
||||||
|
this.prev_time = this.$util.deepCopy(this.check_time)
|
||||||
|
this.$refs.show_choose_time.close()
|
||||||
|
if (activeIndex == 1) {
|
||||||
|
await this.getCount()
|
||||||
|
}
|
||||||
|
this.getList(1)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
filters: {
|
||||||
|
handleTimeText(val, type) {
|
||||||
|
let text = '请选择'
|
||||||
|
let {
|
||||||
|
activeIndex,
|
||||||
|
month,
|
||||||
|
start_time,
|
||||||
|
end_time
|
||||||
|
} = val
|
||||||
|
if (activeIndex == 0 && month) {
|
||||||
|
text = $util.formatTime($util.DateToUnix(`${month}-01`) * 1000, 'YY年M月')
|
||||||
|
}
|
||||||
|
let formatType = type == 1 ? 'YY.M.D' : 'YY年M月D日'
|
||||||
|
if (activeIndex == 1 && start_time && end_time) {
|
||||||
|
text = $util.formatTime($util.DateToUnix(start_time) * 1000, formatType) + ' - ' +
|
||||||
|
$util.formatTime($util.DateToUnix(end_time) * 1000, formatType)
|
||||||
|
}
|
||||||
|
return text
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.agent-income-commission {
|
||||||
|
|
||||||
|
.record-search-info {
|
||||||
|
width: 750rpx;
|
||||||
|
// height: 200rpx;
|
||||||
|
|
||||||
|
.record-info {
|
||||||
|
width: 710rpx;
|
||||||
|
|
||||||
|
.search-item {
|
||||||
|
height: 100rpx;
|
||||||
|
|
||||||
|
.text {
|
||||||
|
color: #3D2C1B;
|
||||||
|
}
|
||||||
|
|
||||||
|
.iconfont {
|
||||||
|
font-size: 26rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.count-item {
|
||||||
|
height: 120rpx;
|
||||||
|
|
||||||
|
.title {
|
||||||
|
padding-top: 18rpx;
|
||||||
|
|
||||||
|
.iconfont {
|
||||||
|
font-size: 16rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.list-item {
|
||||||
|
.item-text {
|
||||||
|
width: 240rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-choose-time {
|
||||||
|
width: 750rpx;
|
||||||
|
border-radius: 30rpx 30rpx 0 0;
|
||||||
|
|
||||||
|
.icon-close {
|
||||||
|
color: #A8AEB8;
|
||||||
|
font-size: 40rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-child {
|
||||||
|
width: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.confirm-btn {
|
||||||
|
width: 670rpx;
|
||||||
|
height: 100rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-status {
|
||||||
|
width: 750rpx;
|
||||||
|
height: 360rpx;
|
||||||
|
border-radius: 30rpx 30rpx 0 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,653 @@
|
||||||
|
<template>
|
||||||
|
<view class="agent-index" v-if="isLoad">
|
||||||
|
<block v-if="options.agent">
|
||||||
|
<view class="mine-count-list c-base pd-lg radius-16" :style="{background:primaryColor}">
|
||||||
|
<view class="flex-between">
|
||||||
|
<view>
|
||||||
|
<view class="text flex-center f-caption">可提现(元)</view>
|
||||||
|
<view class="f-sm-title">{{detail.cash}} </view>
|
||||||
|
</view>
|
||||||
|
<view @tap.stop="$util.goUrl({url:`/user/pages/cash-out?type=agent`})"
|
||||||
|
class="cash-out-btn fill-base flex-center f-desc text-bold radius"
|
||||||
|
:style="{color: primaryColor}">
|
||||||
|
我要提现
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="count-data-list flex-x-center mt-lg pt-lg b-1px-t">
|
||||||
|
<view class="list-item flex-center flex-column">
|
||||||
|
<view class="f-sm-title">{{detail.total_cash}}</view>
|
||||||
|
<view class="text f-caption c-caption">总金额 (元)</view>
|
||||||
|
</view>
|
||||||
|
<view class="list-item flex-center flex-column">
|
||||||
|
<view class="f-sm-title">{{detail.unrecorded_cash}}</view>
|
||||||
|
<view @tap.stop="$refs.show_rule_item.open()" class="text flex-center f-caption c-caption">未入账
|
||||||
|
(元)<i class="iconfont iconshuyi_shuoming ml-sm"></i></view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view @tap.stop="$util.goUrl({url:`/user/pages/distribution/bind-technician`})"
|
||||||
|
class="mine-menu-list share flex-center fill-base radius-16">
|
||||||
|
<view class="icon-info flex-center">
|
||||||
|
<i class="iconfont iconjishi1" :style="{color:primaryColor}"></i>
|
||||||
|
</view>
|
||||||
|
<view class="flex-1">
|
||||||
|
<view class="f-mini-title c-title text-bold">绑定{{$t('action.attendantName')}}</view>
|
||||||
|
<view class="f-desc c-caption mt-sm ellipsis">整合自己的{{$t('action.attendantName')}}资源,获取分润</view>
|
||||||
|
</view>
|
||||||
|
<view class="share-btn flex-center f-desc c-base text-bold" :style="{background:primaryColor}">邀请Ta
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view @tap.stop="$util.goUrl({url:`/agent/pages/poster/salesman`})"
|
||||||
|
class="mine-menu-list share flex-center fill-base radius-16" v-if="detail.salesman_auth">
|
||||||
|
<view class="icon-info flex-center">
|
||||||
|
<i class="iconfont iconbangdingyewuyuan" :style="{color:primaryColor}"></i>
|
||||||
|
</view>
|
||||||
|
<view class="flex-1">
|
||||||
|
<view class="f-mini-title c-title text-bold">绑定业务员</view>
|
||||||
|
<view class="f-desc c-caption mt-sm ellipsis">招揽人才,为自己拓宽渠道</view>
|
||||||
|
</view>
|
||||||
|
<view class="share-btn flex-center f-desc c-base text-bold" :style="{background:primaryColor}">邀请Ta
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view @tap.stop="$util.goUrl({url:`/agent/pages/poster/channel`})"
|
||||||
|
class="mine-menu-list share flex-center fill-base radius-16" v-if="detail.channel_auth">
|
||||||
|
<view class="icon-info flex-center">
|
||||||
|
<i class="iconfont iconbangdingqudaoshang" :style="{color:primaryColor}"></i>
|
||||||
|
</view>
|
||||||
|
<view class="flex-1">
|
||||||
|
<view class="f-mini-title c-title text-bold">绑定渠道商</view>
|
||||||
|
<view class="f-desc c-caption mt-sm ellipsis">直招渠道,获利更多</view>
|
||||||
|
</view>
|
||||||
|
<view class="share-btn flex-center f-desc c-base text-bold" :style="{background:primaryColor}">邀请Ta
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</block>
|
||||||
|
|
||||||
|
<view class="mine-menu-list fill-base radius-16">
|
||||||
|
<view class="menu-title flex-between pl-lg pr-sm">
|
||||||
|
<view class="f-paragraph c-title text-bold">智能助手</view>
|
||||||
|
</view>
|
||||||
|
<view @tap.stop="goOrder(index)" class="notice-info flex-center pl-lg pr-md pb-lg"
|
||||||
|
v-for="(item,index) in detail.notice" :key="index">
|
||||||
|
<view class="title flex-center f-icontext c-base mr-md"
|
||||||
|
:style="{background:item.type==1?primaryColor: item.type==2?'#FFA229':'#E82F21'}">
|
||||||
|
{{noticeType[item.type].title}}
|
||||||
|
</view>
|
||||||
|
<view class="flex-1 flex-between f-desc">
|
||||||
|
<view class="c-title">{{item.id ? noticeType[item.type].text : '暂无数据'}}</view>
|
||||||
|
<view class="flex-y-center c-caption" v-if="item.id">点击查看<i class="iconfont icon-right"></i></view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="mine-menu-list box-shadow fill-base radius-16" v-if="detail.node.includes('shopOrder')">
|
||||||
|
<view class="menu-title flex-between pl-lg pr-sm">
|
||||||
|
<view class="f-paragraph c-title text-bold">订单管理</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-warp pb-lg">
|
||||||
|
<view @tap.stop="toJump('shopOrder', index)"
|
||||||
|
class="item-child flex-center flex-column f-caption c-title" v-for="(item, index) in shopOrder"
|
||||||
|
:key="index">
|
||||||
|
<view class="item-img rel flex-center radius">
|
||||||
|
<view class="abs dot-unread-number flex-center"
|
||||||
|
:style="{width: item.number>99 ? '44rpx': item.number > 9 ? '34rpx' :'',right: item.number>99 ? '-32rpx': item.number > 9 ? '-22rpx' :'-12rpx'}"
|
||||||
|
v-if="item.number > 0">
|
||||||
|
{{item.number < 100 ? item.number : '99+'}}
|
||||||
|
</view>
|
||||||
|
<view class="item-img radius abs" :style="{background:primaryColor}"></view>
|
||||||
|
<i class="iconfont c-title" :class="item.icon" :style="{color:primaryColor}"></i>
|
||||||
|
</view>
|
||||||
|
<view class="mt-sm">{{ item.text }}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="mine-menu-list box-shadow fill-base radius-16" v-if="detail.node.includes('shopBellOrder')">
|
||||||
|
<view class="menu-title flex-between pl-lg pr-sm">
|
||||||
|
<view class="f-paragraph c-title text-bold">加钟管理</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-warp pb-lg">
|
||||||
|
<view @tap.stop="toJump('shopBellOrder', index)"
|
||||||
|
class="item-child flex-center flex-column f-caption c-title" v-for="(item, index) in shopBellOrder"
|
||||||
|
:key="index">
|
||||||
|
<view class="item-img rel flex-center radius">
|
||||||
|
<view class="abs dot-unread-number flex-center"
|
||||||
|
:style="{width: item.number>99 ? '44rpx': item.number > 9 ? '34rpx' :'',right: item.number>99 ? '-32rpx': item.number > 9 ? '-22rpx' :'-12rpx'}"
|
||||||
|
v-if="item.number > 0">
|
||||||
|
{{item.number < 100 ? item.number : '99+'}}
|
||||||
|
</view>
|
||||||
|
<view class="item-img radius abs" :style="{background:primaryColor}"></view>
|
||||||
|
<image mode="heightFix" class="icon-img" :src="item.icon"></image>
|
||||||
|
</view>
|
||||||
|
<view class="mt-sm">{{ item.text }}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="mine-menu-list box-shadow fill-base radius-16" v-if="detail.node.includes('shopRefuseOrder')">
|
||||||
|
<view class="menu-title flex-between pl-lg pr-sm">
|
||||||
|
<view class="f-paragraph c-title text-bold">拒单管理</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-warp pb-lg">
|
||||||
|
<view @tap.stop="toJump('shopRefuseOrder', index)"
|
||||||
|
class="item-child flex-center flex-column f-caption c-title"
|
||||||
|
v-for="(item, index) in shopRefuseOrder" :key="index">
|
||||||
|
<view class="item-img rel flex-center radius">
|
||||||
|
<view class="abs dot-unread-number flex-center"
|
||||||
|
:style="{width: item.number>99 ? '44rpx': item.number > 9 ? '34rpx' :'',right: item.number>99 ? '-32rpx': item.number > 9 ? '-22rpx' :'-12rpx'}"
|
||||||
|
v-if="item.number > 0">
|
||||||
|
{{item.number < 100 ? item.number : '99+'}}
|
||||||
|
</view>
|
||||||
|
<view class="item-img radius abs" :style="{background:primaryColor}"></view>
|
||||||
|
<i class="iconfont c-title" :class="item.icon" :style="{color:primaryColor}"></i>
|
||||||
|
</view>
|
||||||
|
<view class="mt-sm">{{ item.text }}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="mine-menu-list box-shadow fill-base radius-16" v-if="detail.node.includes('shopRefund')">
|
||||||
|
<view class="menu-title flex-between pl-lg pr-sm">
|
||||||
|
<view class="f-paragraph c-title text-bold">服务退款</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-warp pb-lg">
|
||||||
|
<view @tap.stop="toJump('shopRefund', index)"
|
||||||
|
class="item-child flex-center flex-column f-caption c-title" v-for="(item, index) in shopRefund"
|
||||||
|
:key="index">
|
||||||
|
<view class="item-img rel flex-center radius">
|
||||||
|
<view class="abs dot-unread-number flex-center"
|
||||||
|
:style="{width: item.number>99 ? '44rpx': item.number > 9 ? '34rpx' :'',right: item.number>99 ? '-32rpx': item.number > 9 ? '-22rpx' :'-12rpx'}"
|
||||||
|
v-if="item.number > 0">
|
||||||
|
{{item.number < 100 ? item.number : '99+'}}
|
||||||
|
</view>
|
||||||
|
<view class="item-img radius abs" :style="{background:primaryColor}"></view>
|
||||||
|
<i class="iconfont c-title" :class="item.icon" :style="{color:primaryColor}"></i>
|
||||||
|
</view>
|
||||||
|
<view class="mt-sm">{{ item.text }}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="mine-menu-list box-shadow fill-base radius-16" v-if="detail.node.includes('shopBellRefund')">
|
||||||
|
<view class="menu-title flex-between pl-lg pr-sm">
|
||||||
|
<view class="f-paragraph c-title text-bold">加钟退款</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-warp pb-lg">
|
||||||
|
<view @tap.stop="toJump('shopBellRefund', index)"
|
||||||
|
class="item-child flex-center flex-column f-caption c-title" v-for="(item, index) in shopBellRefund"
|
||||||
|
:key="index">
|
||||||
|
<view class="item-img rel flex-center radius">
|
||||||
|
<view class="abs dot-unread-number flex-center"
|
||||||
|
:style="{width: item.number>99 ? '44rpx': item.number > 9 ? '34rpx' :'',right: item.number>99 ? '-32rpx': item.number > 9 ? '-22rpx' :'-12rpx'}"
|
||||||
|
v-if="item.number > 0">
|
||||||
|
{{item.number < 100 ? item.number : '99+'}}
|
||||||
|
</view>
|
||||||
|
<view class="item-img radius abs" :style="{background:primaryColor}"></view>
|
||||||
|
<image mode="heightFix" class="icon-img" :src="item.icon"></image>
|
||||||
|
</view>
|
||||||
|
<view class="mt-sm">{{ item.text }}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
|
||||||
|
<view class="mine-menu-list fill-base radius-16" v-if="options.agent">
|
||||||
|
<view class="menu-title flex-between pl-lg pr-sm">
|
||||||
|
<view class="f-paragraph c-title text-bold">其他功能</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-warp pb-sm">
|
||||||
|
<view @tap.stop="toJump('toolList', index)" class="item-child flex-center flex-column f-caption c-title"
|
||||||
|
style="width: 25%;margin:10rpx 0 20rpx 0" v-for="(item, index) in toolList" :key="index">
|
||||||
|
<i class="iconfont c-title" :class="item.icon" :style="{color:primaryColor}"></i>
|
||||||
|
<view class="mt-sm">{{ item.text }}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="space-footer"></view>
|
||||||
|
|
||||||
|
|
||||||
|
<uni-popup ref="show_rule_item" type="center" :maskClick="false">
|
||||||
|
<view class="common-popup-content fill-base pd-lg radius-34">
|
||||||
|
<view class="title">未入账</view>
|
||||||
|
<view class="f-desc c-title mt-lg">
|
||||||
|
平台未到账的服务订单金额
|
||||||
|
</view>
|
||||||
|
<view class="button">
|
||||||
|
<view @tap.stop="$refs.show_rule_item.close()" class="item-child c-base"
|
||||||
|
:style="{background: primaryColor,color:'#fff'}">知道了</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</uni-popup>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
mapState,
|
||||||
|
mapMutations
|
||||||
|
} from "vuex"
|
||||||
|
import tabbar from "@/components/tabbar.vue"
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
tabbar
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
isLoad: false,
|
||||||
|
options: {},
|
||||||
|
detail: {},
|
||||||
|
noticeType: {
|
||||||
|
1: {
|
||||||
|
title: '订单通知',
|
||||||
|
text: '您有新的订单来啦!'
|
||||||
|
},
|
||||||
|
2: {
|
||||||
|
title: '退款通知',
|
||||||
|
text: '您有新的客户退款通知!'
|
||||||
|
},
|
||||||
|
3: {
|
||||||
|
title: '拒单通知',
|
||||||
|
text: '有' + this.$t('action.attendantName') + '拒单, 请尽快处理!'
|
||||||
|
},
|
||||||
|
},
|
||||||
|
shopOrder: [{
|
||||||
|
icon: 'icondaifuwu4',
|
||||||
|
text: '待服务',
|
||||||
|
url: '/agent/pages/order/list?tab=1',
|
||||||
|
key: 2,
|
||||||
|
number: 0
|
||||||
|
}, {
|
||||||
|
icon: 'iconjishijiedan1',
|
||||||
|
text: this.$t('action.attendantName') + '接单',
|
||||||
|
url: '/agent/pages/order/list?tab=2',
|
||||||
|
key: 3,
|
||||||
|
number: 0
|
||||||
|
}, {
|
||||||
|
icon: 'iconjishichufa1',
|
||||||
|
text: this.$t('action.attendantName') + '出发',
|
||||||
|
url: '/agent/pages/order/list?tab=3',
|
||||||
|
key: 4,
|
||||||
|
number: 0
|
||||||
|
}, {
|
||||||
|
icon: 'iconjishidaoda1',
|
||||||
|
text: this.$t('action.attendantName') + '到达',
|
||||||
|
url: '/agent/pages/order/list?tab=4',
|
||||||
|
key: 5,
|
||||||
|
number: 0
|
||||||
|
}, {
|
||||||
|
icon: 'iconanmo2',
|
||||||
|
text: '服务中',
|
||||||
|
url: '/agent/pages/order/list?tab=5',
|
||||||
|
key: 6,
|
||||||
|
number: 0
|
||||||
|
}, {
|
||||||
|
icon: 'iconyiwancheng',
|
||||||
|
text: '已完成',
|
||||||
|
url: '/agent/pages/order/list?tab=6'
|
||||||
|
}],
|
||||||
|
shopBellOrder: [{
|
||||||
|
icon: 'https://lbqny.migugu.com/admin/anmo/menu/daifuwu.png',
|
||||||
|
text: '待服务',
|
||||||
|
url: '/agent/pages/order/list?bell=1&tab=1',
|
||||||
|
key: 2,
|
||||||
|
number: 0
|
||||||
|
}, {
|
||||||
|
icon: 'https://lbqny.migugu.com/admin/anmo/menu/jiedan.png',
|
||||||
|
text: this.$t('action.attendantName') + '接单',
|
||||||
|
url: '/agent/pages/order/list?bell=1&tab=2',
|
||||||
|
key: 3,
|
||||||
|
number: 0
|
||||||
|
}, {
|
||||||
|
icon: 'https://lbqny.migugu.com/admin/anmo/menu/fuwuzhong.png',
|
||||||
|
text: '服务中',
|
||||||
|
url: '/agent/pages/order/list?bell=1&tab=3',
|
||||||
|
key: 6,
|
||||||
|
number: 0
|
||||||
|
}, {
|
||||||
|
icon: 'https://lbqny.migugu.com/admin/anmo/menu/wancheng.png',
|
||||||
|
text: '已完成',
|
||||||
|
url: '/agent/pages/order/list?bell=1&tab=4',
|
||||||
|
}],
|
||||||
|
shopRefuseOrder: [{
|
||||||
|
icon: 'icondaizhuandan',
|
||||||
|
text: '待转单',
|
||||||
|
url: '/agent/pages/order/list?tab=8',
|
||||||
|
key: 8,
|
||||||
|
number: 0
|
||||||
|
}],
|
||||||
|
shopRefund: [{
|
||||||
|
icon: 'iconshenqingzhong',
|
||||||
|
text: '申请中',
|
||||||
|
url: '/agent/pages/refund/list?tab=1',
|
||||||
|
key: 1,
|
||||||
|
number: 0
|
||||||
|
}, {
|
||||||
|
icon: 'icontongyituikuan',
|
||||||
|
text: '同意退款',
|
||||||
|
url: '/agent/pages/refund/list?tab=2',
|
||||||
|
key: 2,
|
||||||
|
number: 0
|
||||||
|
}, {
|
||||||
|
icon: 'iconjujuetuikuan',
|
||||||
|
text: '拒绝退款',
|
||||||
|
url: '/agent/pages/refund/list?tab=3',
|
||||||
|
key: 3,
|
||||||
|
number: 0
|
||||||
|
}],
|
||||||
|
shopBellRefund: [{
|
||||||
|
icon: 'https://lbqny.migugu.com/admin/anmo/menu/shenqingzhong.png',
|
||||||
|
text: '申请中',
|
||||||
|
url: '/agent/pages/refund/list?bell=1&tab=1',
|
||||||
|
key: 1,
|
||||||
|
number: 0
|
||||||
|
}, {
|
||||||
|
icon: 'https://lbqny.migugu.com/admin/anmo/menu/tongyi.png',
|
||||||
|
text: '同意退款',
|
||||||
|
url: '/agent/pages/refund/list?bell=1&tab=2',
|
||||||
|
key: 2,
|
||||||
|
number: 0
|
||||||
|
}, {
|
||||||
|
icon: 'https://lbqny.migugu.com/admin/anmo/menu/jujue.png',
|
||||||
|
text: '拒绝退款',
|
||||||
|
url: '/agent/pages/refund/list?bell=1&tab=3',
|
||||||
|
key: 3,
|
||||||
|
number: 0
|
||||||
|
}],
|
||||||
|
toolList: [{
|
||||||
|
icon: 'iconzhanghaoshezhi',
|
||||||
|
text: '账号设置',
|
||||||
|
url: '/agent/pages/account'
|
||||||
|
}, {
|
||||||
|
icon: 'iconshenqingjishi3',
|
||||||
|
text: this.$t('action.attendantName') + '管理',
|
||||||
|
url: '/agent/pages/technician/list'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: 'iconyongjinxinxi1',
|
||||||
|
text: '佣金信息',
|
||||||
|
url: '/agent/pages/income/commission'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: 'icontixianshenqing1',
|
||||||
|
text: '提现申请',
|
||||||
|
url: '/user/pages/distribution/record?type=5'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
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,
|
||||||
|
haveOperItem: state => state.technician.haveOperItem,
|
||||||
|
}),
|
||||||
|
onLoad(options) {
|
||||||
|
let {
|
||||||
|
agent = 0
|
||||||
|
} = options
|
||||||
|
options.agent = agent * 1
|
||||||
|
this.options = options
|
||||||
|
uni.setNavigationBarTitle({
|
||||||
|
title: agent == 1 ? '代理商端' : '管理员端'
|
||||||
|
})
|
||||||
|
this.initIndex()
|
||||||
|
},
|
||||||
|
onShow() {
|
||||||
|
if (!this.haveOperItem) return
|
||||||
|
this.initRefresh()
|
||||||
|
},
|
||||||
|
onPullDownRefresh() {
|
||||||
|
// #ifndef APP-PLUS
|
||||||
|
uni.showNavigationBarLoading()
|
||||||
|
// #endif
|
||||||
|
this.initRefresh();
|
||||||
|
uni.stopPullDownRefresh()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
...mapMutations(['updateTechnicianItem']),
|
||||||
|
async initIndex(refresh = false) {
|
||||||
|
// #ifdef H5
|
||||||
|
if (!refresh && this.$jweixin.isWechat()) {
|
||||||
|
await this.$jweixin.initJssdk();
|
||||||
|
this.$jweixin.wxReady(() => {
|
||||||
|
this.$jweixin.hideOptionMenu()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
this.$util.setNavigationBarColor({
|
||||||
|
bg: this.primaryColor
|
||||||
|
})
|
||||||
|
this.$util.showLoading()
|
||||||
|
this.updateTechnicianItem({
|
||||||
|
key: 'haveOperItem',
|
||||||
|
val: false
|
||||||
|
})
|
||||||
|
let {
|
||||||
|
agent
|
||||||
|
} = this.options
|
||||||
|
let methodKey = agent ? 'agent' : 'admin'
|
||||||
|
let data = await this.$api[methodKey].index()
|
||||||
|
if (agent) {
|
||||||
|
data.node = ['shopOrder', 'shopBellOrder', 'shopRefuseOrder', 'shopRefund', 'shopBellRefund']
|
||||||
|
}
|
||||||
|
let {
|
||||||
|
notice
|
||||||
|
} = data
|
||||||
|
let {
|
||||||
|
order_id,
|
||||||
|
refund_id,
|
||||||
|
refuse_id
|
||||||
|
} = notice
|
||||||
|
if (order_id && order_id.length == 0) {
|
||||||
|
order_id = {
|
||||||
|
type: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (refund_id && refund_id.length == 0) {
|
||||||
|
refund_id = {
|
||||||
|
type: 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (refuse_id && refuse_id.length == 0) {
|
||||||
|
refuse_id = {
|
||||||
|
type: 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let arr = []
|
||||||
|
if (data.node.includes('shopOrder') || data.node.includes('shopOrder')) {
|
||||||
|
arr.push(order_id)
|
||||||
|
}
|
||||||
|
if (data.node.includes('shopRefund') || data.node.includes('shopBellRefund')) {
|
||||||
|
arr.push(refund_id)
|
||||||
|
}
|
||||||
|
if (data.node.includes('shopRefuseOrder')) {
|
||||||
|
arr.push(refuse_id)
|
||||||
|
}
|
||||||
|
data.notice = arr
|
||||||
|
this.shopOrder.map(item => {
|
||||||
|
if (item.key) {
|
||||||
|
item.number = data.order_count[item.key]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this.shopBellOrder.map(item => {
|
||||||
|
if (item.key) {
|
||||||
|
item.number = data.add_count[item.key]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this.shopRefuseOrder.map(item => {
|
||||||
|
if (item.key) {
|
||||||
|
item.number = data.refuse_order[item.key]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this.shopRefund.map(item => {
|
||||||
|
if (item.key) {
|
||||||
|
item.number = data.refund_count[item.key]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this.shopBellRefund.map(item => {
|
||||||
|
if (item.key) {
|
||||||
|
item.number = data.add_refund_count[item.key]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this.detail = data
|
||||||
|
this.isLoad = true
|
||||||
|
this.$util.hideAll()
|
||||||
|
},
|
||||||
|
initRefresh() {
|
||||||
|
this.initIndex(true)
|
||||||
|
},
|
||||||
|
toJump(key, index) {
|
||||||
|
let {
|
||||||
|
url
|
||||||
|
} = this[key][index]
|
||||||
|
let {
|
||||||
|
agent
|
||||||
|
} = this.options
|
||||||
|
let joinKey = url.includes('?') ? '&' : '?'
|
||||||
|
url += `${joinKey}agent=${agent}`
|
||||||
|
this.$util.goUrl({
|
||||||
|
url
|
||||||
|
})
|
||||||
|
},
|
||||||
|
async goOrder(index) {
|
||||||
|
let {
|
||||||
|
id = 0,
|
||||||
|
order_id = 0,
|
||||||
|
type
|
||||||
|
} = this.detail.notice[index]
|
||||||
|
if (!order_id) return
|
||||||
|
let {
|
||||||
|
agent
|
||||||
|
} = this.options
|
||||||
|
let methodKey = agent ? 'agent' : 'admin'
|
||||||
|
await this.$api[methodKey].noticeUpdate({
|
||||||
|
id,
|
||||||
|
have_look: 1
|
||||||
|
})
|
||||||
|
this.initRefresh()
|
||||||
|
let page = type == 2 ? 'refund' : 'order'
|
||||||
|
let url = `/agent/pages/${page}/detail?id=${order_id}&agent=${agent}`
|
||||||
|
this.$util.goUrl({
|
||||||
|
url
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.agent-index {
|
||||||
|
|
||||||
|
.mine-count-list {
|
||||||
|
width: 710rpx;
|
||||||
|
height: 295rpx;
|
||||||
|
margin: 20rpx 20rpx 0 20rpx;
|
||||||
|
|
||||||
|
.text {
|
||||||
|
color: rgba(255, 255, 255, 0.6)
|
||||||
|
}
|
||||||
|
|
||||||
|
.cash-out-btn {
|
||||||
|
width: 180rpx;
|
||||||
|
height: 70rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.count-data-list {
|
||||||
|
.list-item {
|
||||||
|
width: 50%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.dot-unread-number {
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
width: 24rpx;
|
||||||
|
height: 24rpx;
|
||||||
|
line-height: 24rpx;
|
||||||
|
text-align: center;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 18rpx;
|
||||||
|
border-radius: 24rpx;
|
||||||
|
background-color: #F1381F;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 我的订单/其他
|
||||||
|
.mine-menu-list {
|
||||||
|
margin: 20rpx 20rpx 0 20rpx;
|
||||||
|
|
||||||
|
.menu-title {
|
||||||
|
height: 90rpx;
|
||||||
|
color: #434343;
|
||||||
|
|
||||||
|
.iconfont {
|
||||||
|
font-size: 24rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-info {
|
||||||
|
width: 80rpx;
|
||||||
|
height: 80rpx;
|
||||||
|
background: #FFFFFF;
|
||||||
|
box-shadow: 0 3rpx 31rpx -2rpx rgba(217, 224, 219, 0.5);
|
||||||
|
border-radius: 29rpx;
|
||||||
|
margin-right: 16rpx;
|
||||||
|
|
||||||
|
.iconfont {
|
||||||
|
font-size: 48rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.share-btn {
|
||||||
|
width: 130rpx;
|
||||||
|
height: 52rpx;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notice-info {
|
||||||
|
.title {
|
||||||
|
width: 100rpx;
|
||||||
|
height: 34rpx;
|
||||||
|
border-radius: 4rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.iconfont {
|
||||||
|
font-size: 20rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-child {
|
||||||
|
width: 25%;
|
||||||
|
margin: 10rpx 0;
|
||||||
|
|
||||||
|
.iconfont {
|
||||||
|
font-size: 52rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-img {
|
||||||
|
width: 60rpx;
|
||||||
|
height: 60rpx;
|
||||||
|
|
||||||
|
.iconfont {
|
||||||
|
font-size: 36rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-img {
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
opacity: 0.1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-img {
|
||||||
|
height: 32rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mine-menu-list.share {
|
||||||
|
padding: 30rpx 30rpx 30rpx 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,508 @@
|
||||||
|
<template>
|
||||||
|
<view class="order-pages" v-if="isLoad">
|
||||||
|
<fixed @height="initFixHeight" :initHeight="transferForm.coach_type">
|
||||||
|
<view class="fill-base pd-lg">
|
||||||
|
<view class="flex-between">
|
||||||
|
<view class="f-title c-title text-bold">转派订单</view>
|
||||||
|
<view class="flex-center">
|
||||||
|
<view @tap.stop="toChangeItem('coach_type',item.id)"
|
||||||
|
class="flex-center service-type-item c-caption" :class="[{'ml-lg':index!=0}]"
|
||||||
|
:style="{background:transferForm.coach_type == item.id ? primaryColor:'',color:transferForm.coach_type == item.id ? '#fff':''}"
|
||||||
|
v-for="(item,index) in tabList" :key="index">
|
||||||
|
{{item.title}}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="fill-base flex-center mt-lg pt-lg b-1px-t" v-if="transferForm.coach_type == 1">
|
||||||
|
<view class="flex-1">
|
||||||
|
<search @input="toSearch" type="input" :padding="0" :radius="30" height="70rpx"
|
||||||
|
:placeholder="placeholder">
|
||||||
|
</search>
|
||||||
|
</view>
|
||||||
|
<view @tap.stop="$refs.show_transfer_item.open()" class="flex-y-center pl-lg">筛选<i
|
||||||
|
class="iconfont iconshaixuanxia-1 c-caption"></i></view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</fixed>
|
||||||
|
|
||||||
|
|
||||||
|
<block v-if="transferForm.coach_type == 1">
|
||||||
|
|
||||||
|
<view @tap.stop="toChangeItem('coach_id',index)"
|
||||||
|
class="list-item fill-base pt-lg pb-lg pl-md pr-lg flex-center mt-md ml-md mr-md radius-16"
|
||||||
|
v-for="(item,index) in list.data" :key="index">
|
||||||
|
<i class="iconfont mr-md"
|
||||||
|
:class="[{'icon-xuanze':transferForm.coach_id!=item.id},{'icon-radio-fill':transferForm.coach_id==item.id}]"
|
||||||
|
:style="{color:transferForm.coach_id==item.id?primaryColor:''}"></i>
|
||||||
|
<view class="flex-1 flex-warp">
|
||||||
|
<image class="avatar radius" :src="item.work_img"></image>
|
||||||
|
<view class="flex-1 ml-md">
|
||||||
|
<view class="flex-between">
|
||||||
|
<view class="f-title c-title text-bold max-200 ellipsis">{{item.coach_name}}</view>
|
||||||
|
<view class="can-service-btn flex-center f-icontext rel" :style="{color:primaryColor}">
|
||||||
|
<view class="bg abs" :style="{background:primaryColor}"></view>
|
||||||
|
最早可约:{{item.near_time}}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="f-desc" style="color:#4D4D4D">
|
||||||
|
所属代理商:{{item.admin_info.username}}({{cityType[item.admin_info.city_type]}}代理)</view>
|
||||||
|
<view class="flex-between f-caption c-caption mt-sm">
|
||||||
|
<view>电话:{{item.mobile}}</view>
|
||||||
|
<view class="flex-y-center"><i class="iconfont iconjuli1"></i>{{item.distance}}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<load-more :noMore="list.current_page>=list.last_page&&list.data.length>0" :loading="loading"
|
||||||
|
v-if="loading">
|
||||||
|
</load-more>
|
||||||
|
<abnor v-if="!loading&&list.data.length<=0&&list.current_page==1"></abnor>
|
||||||
|
|
||||||
|
</block>
|
||||||
|
<block v-if="transferForm.coach_type == 2">
|
||||||
|
|
||||||
|
<view class="pd-lg f-mini-title c-title fill-base b-1px-t">
|
||||||
|
<view class="text-bold flex-y-center pb-lg"><i
|
||||||
|
class="iconfont icon-required c-warning"></i>线下{{$t('action.attendantName')}}</view>
|
||||||
|
<input v-model="transferForm.coach_name" type="text" class="item-input pl-lg pr-lg radius-16"
|
||||||
|
maxlength="15" :placeholder="rule[0].errorMsg" placeholder-class="color:#C7C7C7" />
|
||||||
|
<view class="text-bold flex-y-center pt-lg pb-lg"><i class="iconfont icon-required c-warning"></i>联系电话
|
||||||
|
</view>
|
||||||
|
<input v-model="transferForm.mobile" type="text" class="item-input pl-lg pr-lg radius-16" maxlength="11"
|
||||||
|
:placeholder="rule[1].errorMsg" placeholder-class="color:#C7C7C7" />
|
||||||
|
<view class="text-bold pt-lg pb-lg">转派备注 </view>
|
||||||
|
<textarea v-model="transferForm.text" class="item-textarea pd-lg radius-16"
|
||||||
|
placeholder-class="color:#C7C7C7" maxlength="400" placeholder="若订单有其他特殊情况可单独备注在此处" />
|
||||||
|
<view @tap.stop="toChooseAgent" class="flex-between pt-lg pb-lg">
|
||||||
|
<view class="text-bold">关联代理商</view>
|
||||||
|
<view class="flex-y-center" :class="[{'c-caption':!transferForm.admin_id}]">
|
||||||
|
<view class="max-400 ellipsis">{{transferForm.admin_id | handleAdminName(base_agent)}}</view>
|
||||||
|
<i class="iconfont icongengduo"></i>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-center f-caption c-caption pt-lg">
|
||||||
|
不关联代理商则默认是平台的{{$t('action.attendantName')}}</view>
|
||||||
|
</block>
|
||||||
|
|
||||||
|
|
||||||
|
<view class="space-max-footer"></view>
|
||||||
|
|
||||||
|
<fix-bottom-button @confirm="toConfirm" :text="[{text:'确定',type:'confirm'}]" bgColor="#fff">
|
||||||
|
</fix-bottom-button>
|
||||||
|
|
||||||
|
|
||||||
|
<uni-popup type="top" ref="show_transfer_item" :top="`${popupHeight+1}px`" :custom="true">
|
||||||
|
<view class="popup-transfer-type pd-lg fill-base">
|
||||||
|
<view @tap.stop="toChangeItem('type',item.id)" class="f-paragraph mb-lg" :class="[{'mt-lg':index==0}]"
|
||||||
|
:style="{color:param.type==item.id?primaryColor:''}" v-for="(item,index) in transfreTypeList"
|
||||||
|
:key="index">
|
||||||
|
{{item.title}}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</uni-popup>
|
||||||
|
|
||||||
|
<uni-popup ref="choose_item" type="bottom" :custom="true">
|
||||||
|
<view @touchmove.stop.prevent class="common-popup-content fill-base"
|
||||||
|
style="width: 100%;border-radius: 34rpx 34rpx 0 0;">
|
||||||
|
<view class="flex-center f-title c-title text-bold pb-lg">选择代理商</view>
|
||||||
|
<scroll-view scroll-y style="width: 100%;max-height:50vh">
|
||||||
|
<view @tap.stop="toChangeItem('chooseInd',index)" class="flex-center pt-sm pb-sm"
|
||||||
|
:style="{color:chooseInd == index ? primaryColor: ''}" v-for="(item,index) in base_agent"
|
||||||
|
:key="index">
|
||||||
|
<view class="f-title flex-1 pr-lg">
|
||||||
|
{{item.agent_name}}
|
||||||
|
</view>
|
||||||
|
<i class="iconfont c-caption"
|
||||||
|
:class="[{'icon-xuanze':chooseInd != index},{'icon-radio-fill':chooseInd == index}]"
|
||||||
|
style="font-size: 40rpx;" :style="{color:chooseInd == index ? primaryColor: ''}"></i>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
|
||||||
|
<view class="button">
|
||||||
|
<view @tap.stop="$refs.choose_item.close()" class="item-child">
|
||||||
|
取消
|
||||||
|
</view>
|
||||||
|
<view @tap.stop="toConfirmCheck" class="item-child"
|
||||||
|
:style="{background: primaryColor,color:'#fff'}">
|
||||||
|
确定
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="space-safe"></view>
|
||||||
|
</block>
|
||||||
|
</view>
|
||||||
|
</uni-popup>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
mapState,
|
||||||
|
mapActions,
|
||||||
|
mapMutations
|
||||||
|
} from "vuex"
|
||||||
|
export default {
|
||||||
|
components: {},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
isLoad: false,
|
||||||
|
options: {},
|
||||||
|
placeholder: '请输入' + this.$t('action.attendantName') + '名称',
|
||||||
|
tabList: [{
|
||||||
|
id: 1,
|
||||||
|
title: '更换' + this.$t('action.attendantName')
|
||||||
|
}, {
|
||||||
|
id: 2,
|
||||||
|
title: '委派' + this.$t('action.attendantName')
|
||||||
|
}],
|
||||||
|
transfreTypeList: [{
|
||||||
|
id: 1,
|
||||||
|
title: '距离最近'
|
||||||
|
}, {
|
||||||
|
id: 2,
|
||||||
|
title: '最早可预约'
|
||||||
|
}],
|
||||||
|
cityType: ['', '城市', '区县', '省'],
|
||||||
|
param: {
|
||||||
|
page: 1,
|
||||||
|
coach_name: '',
|
||||||
|
type: 1
|
||||||
|
},
|
||||||
|
list: {
|
||||||
|
data: []
|
||||||
|
},
|
||||||
|
loading: true,
|
||||||
|
index: -1,
|
||||||
|
lockTap: false,
|
||||||
|
popupHeight: '',
|
||||||
|
popupInfo: {},
|
||||||
|
base_agent: [],
|
||||||
|
chooseInd: -1,
|
||||||
|
transferForm: {
|
||||||
|
order_id: '',
|
||||||
|
coach_type: 1,
|
||||||
|
coach_id: '',
|
||||||
|
coach_name: '',
|
||||||
|
near_time: '',
|
||||||
|
mobile: '',
|
||||||
|
text: '',
|
||||||
|
admin_id: ''
|
||||||
|
},
|
||||||
|
rule: [{
|
||||||
|
name: "coach_name",
|
||||||
|
checkType: "isNotNull",
|
||||||
|
errorMsg: "请输入" + this.$t('action.attendantName') + "姓名",
|
||||||
|
regType: 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "mobile",
|
||||||
|
checkType: "isMobile",
|
||||||
|
errorMsg: "请输入联系电话"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: mapState({
|
||||||
|
primaryColor: state => state.config.configInfo.primaryColor,
|
||||||
|
subColor: state => state.config.configInfo.subColor,
|
||||||
|
configInfo: state => state.config.configInfo,
|
||||||
|
userInfo: state => state.user.userInfo,
|
||||||
|
}),
|
||||||
|
onLoad(options) {
|
||||||
|
let {
|
||||||
|
id,
|
||||||
|
agent = 0
|
||||||
|
} = options
|
||||||
|
options.agent = agent * 1
|
||||||
|
this.options = options
|
||||||
|
this.transferForm.order_id = id
|
||||||
|
this.initIndex()
|
||||||
|
},
|
||||||
|
onPullDownRefresh() {
|
||||||
|
// #ifndef APP-PLUS
|
||||||
|
uni.showNavigationBarLoading()
|
||||||
|
// #endif
|
||||||
|
this.initRefresh()
|
||||||
|
uni.stopPullDownRefresh()
|
||||||
|
},
|
||||||
|
onReachBottom() {
|
||||||
|
if (this.list.current_page >= this.list.last_page || this.loading) return;
|
||||||
|
this.param.page = this.param.page + 1;
|
||||||
|
this.loading = true;
|
||||||
|
this.getList();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
...mapActions(['getConfigInfo']),
|
||||||
|
...mapMutations(['updateTechnicianItem']),
|
||||||
|
async initIndex(refresh = false) {
|
||||||
|
// #ifdef H5
|
||||||
|
if (!refresh && this.$jweixin.isWechat()) {
|
||||||
|
await this.$jweixin.initJssdk();
|
||||||
|
this.$jweixin.wxReady(() => {
|
||||||
|
this.$jweixin.hideOptionMenu()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
if (!this.configInfo.id || refresh) {
|
||||||
|
await this.getConfigInfo()
|
||||||
|
}
|
||||||
|
await Promise.all([this.getBaseInfo(), this.getList()])
|
||||||
|
this.isLoad = true
|
||||||
|
this.$util.setNavigationBarColor({
|
||||||
|
bg: this.primaryColor
|
||||||
|
})
|
||||||
|
},
|
||||||
|
initRefresh() {
|
||||||
|
this.param.page = 1
|
||||||
|
this.initIndex(true)
|
||||||
|
},
|
||||||
|
async getBaseInfo() {
|
||||||
|
let {
|
||||||
|
agent = 0
|
||||||
|
} = this.options
|
||||||
|
let methodKey = agent ? 'agent' : 'admin'
|
||||||
|
this.base_agent = await this.$api[methodKey].adminSelect()
|
||||||
|
},
|
||||||
|
toSearch(val) {
|
||||||
|
this.param.page = 1
|
||||||
|
this.param.coach_name = val
|
||||||
|
this.transferForm.coach_id = ''
|
||||||
|
this.getList()
|
||||||
|
},
|
||||||
|
async getList() {
|
||||||
|
let {
|
||||||
|
list: oldList,
|
||||||
|
param,
|
||||||
|
} = this
|
||||||
|
let {
|
||||||
|
id,
|
||||||
|
agent = 0
|
||||||
|
} = this.options
|
||||||
|
param.order_id = id
|
||||||
|
let methodKey = agent ? 'agent' : 'admin'
|
||||||
|
let newList = await this.$api[methodKey].orderChangeCoachList(param)
|
||||||
|
|
||||||
|
if (this.param.page == 1) {
|
||||||
|
this.list = newList
|
||||||
|
} else {
|
||||||
|
newList.data = oldList.data.concat(newList.data)
|
||||||
|
this.list = newList
|
||||||
|
}
|
||||||
|
this.loading = false
|
||||||
|
this.$util.hideAll()
|
||||||
|
},
|
||||||
|
initFixHeight(val) {
|
||||||
|
this.popupHeight = val
|
||||||
|
},
|
||||||
|
toChangeItem(key, val) {
|
||||||
|
switch (key) {
|
||||||
|
case 'type':
|
||||||
|
this.transferForm.coach_id = ''
|
||||||
|
this.param[key] = val
|
||||||
|
this.param.page = 1
|
||||||
|
this.getList()
|
||||||
|
this.$refs.show_transfer_item.close()
|
||||||
|
break
|
||||||
|
case 'coach_type':
|
||||||
|
let data = Object.assign({}, this.transferForm, {
|
||||||
|
coach_type: val,
|
||||||
|
coach_id: '',
|
||||||
|
coach_name: '',
|
||||||
|
near_time: '',
|
||||||
|
mobile: '',
|
||||||
|
text: '',
|
||||||
|
admin_id: ''
|
||||||
|
})
|
||||||
|
this.transferForm = data
|
||||||
|
break
|
||||||
|
case 'coach_id':
|
||||||
|
let {
|
||||||
|
id, near_time
|
||||||
|
} = this.list.data[val]
|
||||||
|
this.transferForm[key] = id
|
||||||
|
this.transferForm.near_time = near_time
|
||||||
|
break
|
||||||
|
case 'chooseInd':
|
||||||
|
this[key] = val
|
||||||
|
break
|
||||||
|
}
|
||||||
|
},
|
||||||
|
toChooseAgent() {
|
||||||
|
let {
|
||||||
|
admin_id = 0
|
||||||
|
} = this.transferForm
|
||||||
|
let ind = this.base_agent.findIndex(item => {
|
||||||
|
return item.id == admin_id
|
||||||
|
})
|
||||||
|
this.chooseInd = ind
|
||||||
|
this.$refs.choose_item.open()
|
||||||
|
},
|
||||||
|
toConfirmCheck() {
|
||||||
|
let {
|
||||||
|
id
|
||||||
|
} = this.base_agent[this.chooseInd]
|
||||||
|
this.transferForm.admin_id = id
|
||||||
|
this.$refs.choose_item.close()
|
||||||
|
},
|
||||||
|
//表单验证
|
||||||
|
validate(param) {
|
||||||
|
let validate = new this.$util.Validate();
|
||||||
|
this.rule.map(item => {
|
||||||
|
let {
|
||||||
|
name,
|
||||||
|
} = item
|
||||||
|
validate.add(param[name], item);
|
||||||
|
})
|
||||||
|
let message = validate.start();
|
||||||
|
return message;
|
||||||
|
},
|
||||||
|
async toConfirm() {
|
||||||
|
let param = this.$util.deepCopy(this.transferForm)
|
||||||
|
let {
|
||||||
|
coach_type: ctype = 1,
|
||||||
|
coach_id = 0
|
||||||
|
} = param
|
||||||
|
if (ctype === 1) {
|
||||||
|
if (!coach_id) {
|
||||||
|
this.$util.showToast({
|
||||||
|
title: `请选择` + this.$t('action.attendantName')
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
delete param.coach_name
|
||||||
|
delete param.mobile
|
||||||
|
delete param.text
|
||||||
|
delete param.admin_id
|
||||||
|
} else {
|
||||||
|
param.coach_id = 0
|
||||||
|
let msg = this.validate(param);
|
||||||
|
if (msg) {
|
||||||
|
this.$util.showToast({
|
||||||
|
title: msg
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
delete param.near_time
|
||||||
|
}
|
||||||
|
delete param.coach_type
|
||||||
|
param.text = param.text ? param.text.substring(0, 400) : ''
|
||||||
|
if (this.lockTap) return
|
||||||
|
let {
|
||||||
|
agent
|
||||||
|
} = this.options
|
||||||
|
let methodKey = agent ? 'agent' : 'admin'
|
||||||
|
try {
|
||||||
|
await this.$api[methodKey].orderChangeCoach(param)
|
||||||
|
this.$util.showToast({
|
||||||
|
title: '操作成功'
|
||||||
|
})
|
||||||
|
this.lockTap = false;
|
||||||
|
this.$util.hideAll()
|
||||||
|
this.updateTechnicianItem({
|
||||||
|
key: 'haveOperItem',
|
||||||
|
val: true
|
||||||
|
})
|
||||||
|
this.$util.back()
|
||||||
|
this.$util.goUrl({
|
||||||
|
url: 1,
|
||||||
|
openType: `navigateBack`
|
||||||
|
})
|
||||||
|
} catch (e) {
|
||||||
|
setTimeout(() => {
|
||||||
|
this.lockTap = false
|
||||||
|
this.$util.hideAll()
|
||||||
|
}, 2000)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 订单详情
|
||||||
|
goDetail(index) {
|
||||||
|
let {
|
||||||
|
id
|
||||||
|
} = this.list.data[index]
|
||||||
|
let {
|
||||||
|
agent
|
||||||
|
} = this.options
|
||||||
|
let url = `/agent/pages/order/detail?id=${id}&agent=${agent}`
|
||||||
|
this.$util.goUrl({
|
||||||
|
url
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
filters: {
|
||||||
|
handleAdminName(val, data) {
|
||||||
|
let text = '请选择代理商'
|
||||||
|
if (val) {
|
||||||
|
let arr = data.filter(item => {
|
||||||
|
return item.id == val
|
||||||
|
})
|
||||||
|
text = arr[0].agent_name
|
||||||
|
}
|
||||||
|
return text
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.order-pages {
|
||||||
|
.iconshaixuanxia-1 {
|
||||||
|
font-size: 20rpx;
|
||||||
|
transform: scale(0.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
.popup-transfer-type {
|
||||||
|
width: 100%;
|
||||||
|
height: 234rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-item {
|
||||||
|
|
||||||
|
.icon-xuanze,
|
||||||
|
.icon-radio-fill {
|
||||||
|
font-size: 38rpx;
|
||||||
|
color: '#BEC3CE'
|
||||||
|
}
|
||||||
|
|
||||||
|
.avatar {
|
||||||
|
width: 124rpx;
|
||||||
|
height: 124rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.can-service-btn {
|
||||||
|
height: 32rpx;
|
||||||
|
padding: 0 6rpx 0 6rpx;
|
||||||
|
|
||||||
|
.bg {
|
||||||
|
opacity: 0.1;
|
||||||
|
border-radius: 5rpx;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.item-input {
|
||||||
|
height: 110rpx;
|
||||||
|
background: #F9FAF9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-textarea {
|
||||||
|
width: 630rpx;
|
||||||
|
height: 300rpx;
|
||||||
|
background: #F9FAF9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icongengduo {
|
||||||
|
color: #5A677E;
|
||||||
|
font-size: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,549 @@
|
||||||
|
<template>
|
||||||
|
<view class="order-pages" v-if="detail.id">
|
||||||
|
<view class="item-child pd-lg fill-base f-paragraph c-base" :style="{background:primaryColor}">
|
||||||
|
<view class="text-bold">{{statusType[detail.pay_type]}}</view>
|
||||||
|
<view class="f-caption mt-sm" v-if="detail.pay_type == 1 && detail.end_time > 0">请在<min-countdown
|
||||||
|
:targetTime="over_time_text" @callback="countEnd"></min-countdown>内完成支付,逾期未支付,订单将自动取消</view>
|
||||||
|
<view class="space-lg"></view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- // pay_type 1待支付,2待服务,3技-师接单,4技-师出发,5技-师到达,6服务中,7服务完成,8待评价 -->
|
||||||
|
<view
|
||||||
|
class="menu-list flex-warp rel ml-lg mr-lg pt-lg pb-lg pl-md pr-md fill-base f-paragraph c-caption radius-16"
|
||||||
|
:class="[{'add-bell':detail.is_add || detail.store_id}]">
|
||||||
|
<view class="menu-line abs b-1px-b"></view>
|
||||||
|
<block v-for="(item,index) in lineList" :key="index">
|
||||||
|
<view class="item-child flex-center flex-column f-icontext c-paragraph"
|
||||||
|
:style="{color:detail.pay_type > item.pay_type -1?primaryColor:''}" v-if="item.icon">
|
||||||
|
<view class="item-img fill-base flex-center mb-sm radius"
|
||||||
|
:style="{borderColor:detail.pay_type > item.pay_type -1?primaryColor:''}">
|
||||||
|
<i class="iconfont" :class="item.icon"></i>
|
||||||
|
</view>
|
||||||
|
<view class="ellipsis" style="max-width:100%">{{item.title}}</view>
|
||||||
|
</view>
|
||||||
|
</block>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
|
||||||
|
<view class="item-child mt-md ml-lg mr-lg pd-lg fill-base radius-16">
|
||||||
|
<view class="flex-between pb-lg">
|
||||||
|
<view class="f-paragraph c-title max-380 ellipsis">服务内容</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-center" :class="[{'mb-lg':aindex != detail.order_goods.length -1}]"
|
||||||
|
v-for="(aitem,aindex) in detail.order_goods" :key="aindex">
|
||||||
|
<!-- #ifdef H5 -->
|
||||||
|
<view class="avatar lg radius-16">
|
||||||
|
<view class="h5-image avatar lg radius-16"
|
||||||
|
:style="{ backgroundImage : `url('${aitem.goods_cover}')`}">
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<!-- #endif -->
|
||||||
|
<!-- #ifndef H5 -->
|
||||||
|
<image mode="aspectFill" class="avatar lg radius-16" :src="aitem.goods_cover"></image>
|
||||||
|
<!-- #endif -->
|
||||||
|
<view class="flex-1 ml-md">
|
||||||
|
<view class="flex-between">
|
||||||
|
<view class="f-mini-title c-title text-bold max-380 ellipsis">
|
||||||
|
{{aitem.goods_name}}
|
||||||
|
</view>
|
||||||
|
<view class="c-paragraph">x{{aitem.num}}</view>
|
||||||
|
</view>
|
||||||
|
<view class="f-caption c-caption" v-if="aitem.material_price*1>0">物料费:¥{{aitem.material_price}}
|
||||||
|
</view>
|
||||||
|
<view class="flex-between mt-md">
|
||||||
|
<view class="f-caption" style="color:#777">服务时长 {{aitem.time_long}}分钟</view>
|
||||||
|
<view class="f-caption c-warning" v-if="aitem.refund_num>0">已退x{{aitem.refund_num}}</view>
|
||||||
|
</view>
|
||||||
|
<view class="f-paragraph c-warning text-bold mt-sm">¥{{aitem.price}}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="store-info mt-md ml-lg mr-lg pd-lg fill-base radius-16" v-if="detail.store_id">
|
||||||
|
<view class="f-mini-title c-title text-bold pb-md">
|
||||||
|
{{detail.store_info.title}}
|
||||||
|
</view>
|
||||||
|
<view class="flex-between">
|
||||||
|
<view class="flex-y-center" style="color: #303030;">
|
||||||
|
<i class="iconfont icondizhi1 mr-sm"></i>
|
||||||
|
<view class="c-title flex-1 mr-md">
|
||||||
|
<span>{{detail.store_info.address || `暂未设置门店地址`}}</span>
|
||||||
|
<span @tap.stop="$util.goUrl({url:detail.store_info.address,openType:'copy'})"
|
||||||
|
class="copy-btn span f-icontext radius-5 ml-sm"
|
||||||
|
:style="{color:primaryColor,borderColor:primaryColor}"
|
||||||
|
v-if="detail.store_info.address">复制</span>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-center">
|
||||||
|
<view @tap.stop="$util.goUrl({url:detail.store_info.phone,openType:'call'})"
|
||||||
|
class="item-icon rel flex-center radius-16">
|
||||||
|
<view class="item-icon radius-16 abs" :style="{background:primaryColor}"></view>
|
||||||
|
<i class="iconfont icondadianhua_1" :style="{color:primaryColor}"></i>
|
||||||
|
</view>
|
||||||
|
<view @tap.stop="toMap('store_info')" class="item-icon rel flex-center radius-16 ml-md"
|
||||||
|
v-if="detail.store_info.address">
|
||||||
|
<view class="item-icon radius-16 abs" :style="{background:primaryColor}"></view>
|
||||||
|
<i class="iconfont icondizhi_1" :style="{color:primaryColor}"></i>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
|
||||||
|
<view class="order-agent-info store-info mt-md ml-lg mr-lg pd-lg fill-base f-paragraph radius-16">
|
||||||
|
<view class="flex-center">
|
||||||
|
<image mode="aspectFill" class="coach-img radius" :src="detail.coach_info.work_img"></image>
|
||||||
|
<view class="flex-1 ml-lg f-title text-bold ellipsis" style="max-width: 506rpx;">
|
||||||
|
{{detail.coach_info ? detail.coach_info.coach_name : ''}}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-center mt-lg">
|
||||||
|
<view class="title">下单人</view>
|
||||||
|
<view class="text flex-1 ellipsis">{{detail.address_info.user_name}}</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-center mt-lg">
|
||||||
|
<view class="title">联系方式</view>
|
||||||
|
<view class="text flex-1 flex-between">
|
||||||
|
<view>
|
||||||
|
{{detail.address_info.mobile.substring(0,3)}}****{{detail.address_info.mobile.substring(7,11)}}
|
||||||
|
</view>
|
||||||
|
<view @tap.stop="toTel" class="item-icon rel flex-center radius-16">
|
||||||
|
<view class="item-icon radius-16 abs" :style="{background:primaryColor}"></view>
|
||||||
|
<i class="iconfont icondadianhua_1" :style="{color:primaryColor}"></i>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-warp mt-lg" v-if="!detail.store_id">
|
||||||
|
<view class="title">服务地址</view>
|
||||||
|
<view class="text flex-1 flex-between">
|
||||||
|
<view style="max-width: 350rpx;">
|
||||||
|
<span>{{`${detail.address_info.address}${detail.address_info.address_info}`}}</span>
|
||||||
|
<span @tap="toCopy" class="copy-btn fill radius-5 f-icontext ml-sm">复制</span>
|
||||||
|
</view>
|
||||||
|
<view @tap.stop="toMap('address_info')" class="item-icon rel flex-center radius-16">
|
||||||
|
<view class="item-icon radius-16 abs" :style="{background:primaryColor}"></view>
|
||||||
|
<i class="iconfont icondizhi_1" :style="{color:primaryColor}"></i>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="mt-lg" v-if="detail.text">
|
||||||
|
<view class="title">订单备注</view>
|
||||||
|
<view class="text mt-sm">{{detail.text}}</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-center mt-lg pt-lg b-1px-t">
|
||||||
|
<view class="title">下单时间</view>
|
||||||
|
<view class="text flex-1">{{detail.create_time}}</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-center mt-lg">
|
||||||
|
<view class="title">服务时间</view>
|
||||||
|
<view class="text flex-1">{{detail.start_time}}</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-center mt-lg">
|
||||||
|
<view class="title">服务时长</view>
|
||||||
|
<view class="text flex-1">{{detail.time_long}}分钟</view>
|
||||||
|
</view>
|
||||||
|
<block v-if="!detail.is_add && !detail.store_id">
|
||||||
|
<view class="flex-center mt-lg">
|
||||||
|
<view class="title">车费详情</view>
|
||||||
|
<view class="text flex-1 flex-y-center">{{carType[detail.car_type]}}
|
||||||
|
<view class="ml-md" v-if="detail.car_type == 1">全程{{detail.distance}}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-center mt-lg" v-if="detail.car_type == 1">
|
||||||
|
<view class="title">出行费用</view>
|
||||||
|
<view class="text flex-1">出租车 ¥{{detail.car_price}}</view>
|
||||||
|
</view>
|
||||||
|
</block>
|
||||||
|
<view class="flex-center mt-lg">
|
||||||
|
<view class="title">服务项目费用</view>
|
||||||
|
<view class="text flex-1">¥{{detail.init_service_price}}</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-center mt-lg" v-if="detail.discount*1 > 0">
|
||||||
|
<view class="title">卡券优惠</view>
|
||||||
|
<view class="text flex-1">-¥{{detail.discount}}</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-center mt-lg">
|
||||||
|
<view class="title">支付方式</view>
|
||||||
|
<view class="text flex-1">{{payType[detail.pay_model]}}</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-between mt-lg pt-lg b-1px-t">
|
||||||
|
<view class="title"></view>
|
||||||
|
<view class="flex-y-baseline f-paragraph c-black text-bold">总计:<view class="c-warning">
|
||||||
|
¥{{detail.pay_price}}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="mt-md ml-lg mr-lg pd-lg fill-base radius-16">
|
||||||
|
<view class="flex-y-center pb-lg f-mini-title c-title flex-warp b-1px-b">
|
||||||
|
<view class="flex-between text-bold">订单编号:</view>
|
||||||
|
<view class="flex-between flex-1 ">
|
||||||
|
<view class="text-bold max-350 ellipsis">{{detail.order_code}}</view>
|
||||||
|
<view class="copy-btn flex-center radius-5 f-icontext"
|
||||||
|
@tap.stop="$util.goUrl({openType:'copy',url:detail.order_code})"
|
||||||
|
:style="{borderColor:primaryColor ,color:primaryColor}">复制</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="space-lg"></view>
|
||||||
|
<timeline :list="lineList" :info="detail"></timeline>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="space-max-footer"></view>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<fix-bottom-button
|
||||||
|
@cancel="$util.goUrl({url:`/agent/pages/order/change?id=${options.id}&agent=${options.agent}`})"
|
||||||
|
@confirm="toConfirm"
|
||||||
|
:text="detail.is_add && detail.pay_type != 8 ? [{text:$t( `action.${ technicianStatusOperType[ detail.pay_type === 3 && (detail.is_add || detail.store_id) ? 5 : detail.pay_type ] }` ),type:'confirm'}] : [{text:$t('action.transferOrder'),type:'cancel'},{text:$t( `action.${ technicianStatusOperType[ detail.pay_type === 3 && (detail.is_add || detail.store_id) ? 5 : detail.pay_type == 8 ? -1 : detail.pay_type ] }` ),type:'confirm'}]"
|
||||||
|
bgColor="#fff" :classType="2" v-if="[2, 3, 4, 5, 6, 8].includes(detail.pay_type)">
|
||||||
|
</fix-bottom-button>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<uni-popup ref="change_item" type="center" :custom="true">
|
||||||
|
<view class="common-popup-content fill-base pd-lg radius-34">
|
||||||
|
<view class="title">温馨提示</view>
|
||||||
|
<view class="desc">
|
||||||
|
你确认要操作{{$t(`action.${technicianStatusOperType[popupInfo.type]}`)}}吗?
|
||||||
|
</view>
|
||||||
|
<view class="f-caption c-warning" v-if="popupInfo.type == -1">退款金额:¥{{popupInfo.refund_price}}</view>
|
||||||
|
<view class="button">
|
||||||
|
<view @tap.stop="$refs.change_item.close()" class="item-child">取消</view>
|
||||||
|
<view @tap.stop="confirmChangeOrder" class="item-child c-base"
|
||||||
|
:style="{background: primaryColor,color:'#fff'}">确定</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</uni-popup>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
mapState,
|
||||||
|
mapActions,
|
||||||
|
mapMutations
|
||||||
|
} from "vuex"
|
||||||
|
import timeline from '@/components/timeline.vue'
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
timeline
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
options: {},
|
||||||
|
statusType: {
|
||||||
|
'-1': '已取消',
|
||||||
|
1: '待支付',
|
||||||
|
2: '待服务',
|
||||||
|
3: this.$t('action.attendantName') + '接单',
|
||||||
|
4: this.$t('action.attendantName') + '出发',
|
||||||
|
5: this.$t('action.attendantName') + '到达',
|
||||||
|
6: '服务中',
|
||||||
|
7: '已完成',
|
||||||
|
8: '待转单'
|
||||||
|
},
|
||||||
|
technicianStatusOperType: {
|
||||||
|
'-1': 'agreeRefund',
|
||||||
|
2: 'orderTaking',
|
||||||
|
3: 'setOut',
|
||||||
|
4: 'arrive',
|
||||||
|
5: 'startService',
|
||||||
|
6: 'serviceCompletion'
|
||||||
|
},
|
||||||
|
carType: {
|
||||||
|
0: '公交/地铁',
|
||||||
|
1: '出租车'
|
||||||
|
},
|
||||||
|
payType: {
|
||||||
|
1: '微信支付',
|
||||||
|
2: '余额支付',
|
||||||
|
3: '支付宝支付'
|
||||||
|
},
|
||||||
|
lineList: [],
|
||||||
|
base_service: [{
|
||||||
|
pay_type: 3,
|
||||||
|
title: this.$t('action.attendantName') + '接单',
|
||||||
|
time: 'receiving_time',
|
||||||
|
icon: 'iconjishijiedan'
|
||||||
|
}, {
|
||||||
|
pay_type: 4,
|
||||||
|
title: this.$t('action.attendantName') + '出发',
|
||||||
|
time: 'serout_time',
|
||||||
|
icon: 'iconjishichufa'
|
||||||
|
}, {
|
||||||
|
pay_type: 5,
|
||||||
|
title: this.$t('action.attendantName') + '到达',
|
||||||
|
time: 'arrive_time',
|
||||||
|
icon: 'iconjishidaoda'
|
||||||
|
}, {
|
||||||
|
pay_type: 6,
|
||||||
|
title: '开始服务',
|
||||||
|
time: 'start_service_time',
|
||||||
|
icon: 'iconjishifuwu'
|
||||||
|
}, {
|
||||||
|
pay_type: 7,
|
||||||
|
title: '服务完成',
|
||||||
|
time: 'order_end_time',
|
||||||
|
icon: 'iconjishiwancheng'
|
||||||
|
}, {
|
||||||
|
pay_type: 7,
|
||||||
|
title: '签字确认',
|
||||||
|
time: 'sign_time',
|
||||||
|
icon: ''
|
||||||
|
}],
|
||||||
|
base_bell: [{
|
||||||
|
pay_type: 3,
|
||||||
|
title: this.$t('action.attendantName') + '接单',
|
||||||
|
time: 'receiving_time',
|
||||||
|
icon: 'iconjishijiedan'
|
||||||
|
}, {
|
||||||
|
pay_type: 6,
|
||||||
|
title: '开始服务',
|
||||||
|
time: 'start_service_time',
|
||||||
|
icon: 'iconjishifuwu'
|
||||||
|
}, {
|
||||||
|
pay_type: 7,
|
||||||
|
title: '服务完成',
|
||||||
|
time: 'order_end_time',
|
||||||
|
icon: 'iconjishiwancheng'
|
||||||
|
}],
|
||||||
|
detail: {
|
||||||
|
pay_type: 0
|
||||||
|
},
|
||||||
|
check_label: [],
|
||||||
|
coach_refund_text: '',
|
||||||
|
lockTap: false,
|
||||||
|
popupInfo: {
|
||||||
|
title: '',
|
||||||
|
type: '',
|
||||||
|
param: {},
|
||||||
|
imgs: [],
|
||||||
|
location: {
|
||||||
|
lat: 0,
|
||||||
|
lng: 0,
|
||||||
|
address: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: mapState({
|
||||||
|
primaryColor: state => state.config.configInfo.primaryColor,
|
||||||
|
subColor: state => state.config.configInfo.subColor,
|
||||||
|
configInfo: state => state.config.configInfo,
|
||||||
|
userInfo: state => state.user.userInfo,
|
||||||
|
haveOperItem: state => state.technician.haveOperItem,
|
||||||
|
over_time_text() {
|
||||||
|
return new Date().getTime() + this.detail.end_time * 1000
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
onLoad(options) {
|
||||||
|
let {
|
||||||
|
agent = 0
|
||||||
|
} = options
|
||||||
|
options.agent = agent * 1
|
||||||
|
this.options = options
|
||||||
|
this.initIndex()
|
||||||
|
},
|
||||||
|
onShow() {
|
||||||
|
if (!this.haveOperItem) return
|
||||||
|
this.$util.back()
|
||||||
|
this.updateTechnicianItem({
|
||||||
|
key: 'haveOperItem',
|
||||||
|
val: false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
...mapActions(['getConfigInfo', 'getCoachInfo']),
|
||||||
|
...mapMutations(['updateTechnicianItem']),
|
||||||
|
async initIndex(refresh = false) {
|
||||||
|
// #ifdef H5
|
||||||
|
if (!refresh && this.$jweixin.isWechat()) {
|
||||||
|
await this.$jweixin.initJssdk();
|
||||||
|
this.$jweixin.wxReady(() => {
|
||||||
|
this.$jweixin.hideOptionMenu()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
if (!this.configInfo.id || refresh) {
|
||||||
|
await this.getConfigInfo()
|
||||||
|
}
|
||||||
|
let {
|
||||||
|
id,
|
||||||
|
agent
|
||||||
|
} = this.options
|
||||||
|
let methodKey = agent ? 'agent' : 'admin'
|
||||||
|
let data = await this.$api[methodKey].orderInfo({
|
||||||
|
id
|
||||||
|
})
|
||||||
|
this.$util.setNavigationBarColor({
|
||||||
|
bg: this.primaryColor
|
||||||
|
})
|
||||||
|
data.is_balance = data.balance * 1 > 0 ? 1 : 0
|
||||||
|
let {
|
||||||
|
pay_type,
|
||||||
|
time_long,
|
||||||
|
start_service_time,
|
||||||
|
is_add = 0,
|
||||||
|
store_id = 0
|
||||||
|
} = data
|
||||||
|
let lineList = this.$util.deepCopy(is_add || store_id ? this.base_bell : this.base_service)
|
||||||
|
if (store_id) {
|
||||||
|
lineList.push({
|
||||||
|
pay_type: 7,
|
||||||
|
title: '签字确认',
|
||||||
|
time: 'sign_time',
|
||||||
|
icon: ''
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.lineList = lineList
|
||||||
|
this.detail = data
|
||||||
|
},
|
||||||
|
initRefresh() {
|
||||||
|
this.initIndex(true)
|
||||||
|
},
|
||||||
|
countEnd() {
|
||||||
|
this.$util.log("倒计时完了")
|
||||||
|
setTimeout(() => {
|
||||||
|
this.initRefresh()
|
||||||
|
this.$util.back()
|
||||||
|
}, 1000)
|
||||||
|
},
|
||||||
|
// type: -1拒绝接单,3确定接单,4已出发,5已到达,6开始服务,7服务完成
|
||||||
|
async toConfirm() {
|
||||||
|
let {
|
||||||
|
id: order_id,
|
||||||
|
pay_type,
|
||||||
|
is_add = 0,
|
||||||
|
store_id = 0,
|
||||||
|
true_car_price,
|
||||||
|
true_service_price
|
||||||
|
} = this.detail
|
||||||
|
let type = pay_type === 3 && (is_add || store_id) ?
|
||||||
|
5 :
|
||||||
|
pay_type
|
||||||
|
let refund_price = (true_car_price * 1 + true_service_price * 1).toFixed(2)
|
||||||
|
this.popupInfo = {
|
||||||
|
order_id,
|
||||||
|
type: pay_type == 8 ? -1 : type,
|
||||||
|
refund_price
|
||||||
|
}
|
||||||
|
this.$refs.change_item.open()
|
||||||
|
},
|
||||||
|
async confirmChangeOrder() {
|
||||||
|
let param = this.$util.deepCopy(this.popupInfo)
|
||||||
|
param.type = param.type + 1
|
||||||
|
let {
|
||||||
|
type
|
||||||
|
} = param
|
||||||
|
delete param.index
|
||||||
|
let msg = {
|
||||||
|
'-1': '退款成功',
|
||||||
|
3: '接单成功',
|
||||||
|
4: '已成功出发',
|
||||||
|
5: '已成功到达',
|
||||||
|
6: '已开始服务',
|
||||||
|
7: '服务已完成'
|
||||||
|
}
|
||||||
|
let {
|
||||||
|
activeIndex
|
||||||
|
} = this
|
||||||
|
if (this.lockTap) return;
|
||||||
|
this.lockTap = true;
|
||||||
|
this.$util.showLoading()
|
||||||
|
let {
|
||||||
|
agent
|
||||||
|
} = this.options
|
||||||
|
let methodKey = agent ? 'agent' : 'admin'
|
||||||
|
try {
|
||||||
|
await this.$api[methodKey].adminUpdateOrder(param)
|
||||||
|
this.$refs.change_item.close()
|
||||||
|
this.$util.showToast({
|
||||||
|
title: msg[type]
|
||||||
|
})
|
||||||
|
this.lockTap = false;
|
||||||
|
this.updateTechnicianItem({
|
||||||
|
key: 'haveOperItem',
|
||||||
|
val: true
|
||||||
|
})
|
||||||
|
this.initRefresh()
|
||||||
|
this.$util.back()
|
||||||
|
} catch (e) {
|
||||||
|
setTimeout(() => {
|
||||||
|
this.lockTap = false
|
||||||
|
this.$util.hideAll()
|
||||||
|
}, 2000)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 咨询
|
||||||
|
async toTel() {
|
||||||
|
let {
|
||||||
|
id: order_id,
|
||||||
|
pay_type
|
||||||
|
} = this.detail
|
||||||
|
let {
|
||||||
|
agent
|
||||||
|
} = this.options
|
||||||
|
let methodKey = agent ? 'agent' : 'admin'
|
||||||
|
if ([2, 3, 4, 5, 6].includes(pay_type)) {
|
||||||
|
let url = await this.$api[methodKey].getVirtualPhone({
|
||||||
|
order_id
|
||||||
|
})
|
||||||
|
this.$util.goUrl({
|
||||||
|
url,
|
||||||
|
openType: `call`
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
let msg = pay_type == 7 ? '服务结束' : '服务取消'
|
||||||
|
this.$util.showToast({
|
||||||
|
title: `${msg}不能联系客户哦`
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 复制定位
|
||||||
|
toCopy() {
|
||||||
|
let {
|
||||||
|
address,
|
||||||
|
address_info
|
||||||
|
} = this.detail.address_info
|
||||||
|
let url = `${address}${address_info}`
|
||||||
|
this.$util.goUrl({
|
||||||
|
url,
|
||||||
|
openType: 'copy'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 查看定位
|
||||||
|
async toMap(key) {
|
||||||
|
let {
|
||||||
|
address,
|
||||||
|
address_info = '',
|
||||||
|
lat,
|
||||||
|
lng
|
||||||
|
} = this.detail[key]
|
||||||
|
await this.$util.checkAuth({
|
||||||
|
type: 'userLocation'
|
||||||
|
})
|
||||||
|
await uni.getLocation({
|
||||||
|
type: 'gcj02',
|
||||||
|
})
|
||||||
|
await uni.openLocation({
|
||||||
|
latitude: lat * 1,
|
||||||
|
longitude: lng * 1,
|
||||||
|
name: address_info ? `${address} ${address_info}` : address,
|
||||||
|
scale: 28
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.avatar.coath {
|
||||||
|
width: 94rpx;
|
||||||
|
height: 94rpx;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,401 @@
|
||||||
|
<template>
|
||||||
|
<view class="order-pages" v-if="isLoad">
|
||||||
|
<fixed>
|
||||||
|
<view class="fill-base pt-lg pl-md pr-md pb-md">
|
||||||
|
<search @input="toSearch" type="input" :padding="0" :radius="30" height="70rpx"
|
||||||
|
placeholder="请输入系统订单号查询">
|
||||||
|
</search>
|
||||||
|
</view>
|
||||||
|
<tab @change="handerTabChange" :list="tabList" :activeIndex="activeIndex*1" :activeColor="primaryColor"
|
||||||
|
height="100rpx" v-if="options.tab != 8"></tab>
|
||||||
|
<view class="b-1px-b"></view>
|
||||||
|
</fixed>
|
||||||
|
|
||||||
|
<view @tap.stop="goDetail(index)" class="item-child mt-md ml-lg mr-lg pd-lg fill-base radius-16 rel"
|
||||||
|
v-for="(item,index) in list.data" :key="index">
|
||||||
|
<view v-if="item.is_add">
|
||||||
|
<view class="bell-tag flex-center f-icontext c-base abs" :style="{background:primaryColor}">加钟服务
|
||||||
|
</view>
|
||||||
|
<view class="space-md"></view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-between pb-lg b-1px-b">
|
||||||
|
<view class="f-paragraph c-title max-450 ellipsis">订单号:{{item.order_code}}</view>
|
||||||
|
<view class="f-caption text-bold"
|
||||||
|
:style="{color:item.pay_type==2?primaryColor: [3,4,5].includes(item.pay_type)?subColor: item.pay_type == 6 ? '#11C95E' : '#333'}">
|
||||||
|
{{statusType[item.pay_type]}}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-center mb-lg" :class="[{'mt-lg':aindex==0}]" v-for="(aitem,aindex) in item.order_goods"
|
||||||
|
:key="aindex">
|
||||||
|
<!-- #ifdef H5 -->
|
||||||
|
<view class="avatar lg radius-16">
|
||||||
|
<view class="h5-image avatar lg radius-16"
|
||||||
|
:style="{ backgroundImage : `url('${aitem.goods_cover}')`}">
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<!-- #endif -->
|
||||||
|
<!-- #ifndef H5 -->
|
||||||
|
<image mode="aspectFill" class="avatar lg radius-16" :src="aitem.goods_cover"></image>
|
||||||
|
<!-- #endif -->
|
||||||
|
|
||||||
|
<view class="flex-1 ml-md">
|
||||||
|
<view class="flex-between">
|
||||||
|
<view class="f-mini-title c-title text-bold max-380 ellipsis">
|
||||||
|
{{aitem.goods_name}}
|
||||||
|
</view>
|
||||||
|
<view class="c-paragraph">x{{aitem.num}}</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-between mt-md">
|
||||||
|
<view class="f-caption c-caption ellipsis"
|
||||||
|
:class="[{'max-300':aitem.refund_num>0},{'max-450':aitem.refund_num==0}]">
|
||||||
|
服务{{$t('action.attendantName')}}:{{item.coach_info?item.coach_info.coach_name:'-'}}</view>
|
||||||
|
<view class="f-caption c-warning" v-if="aitem.refund_num>0">已退x{{aitem.refund_num}}</view>
|
||||||
|
</view>
|
||||||
|
<view class="f-caption c-caption" style="margin-top: 5rpx;">服务时间:{{item.start_time}}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-between pt-lg b-1px-t">
|
||||||
|
<view class="flex-y-center f-desc c-title">总计:
|
||||||
|
<view class="f-paragraph text-bold">¥{{item.pay_price}}</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-warp">
|
||||||
|
<!-- // pay_type 2待接单,3接单,4出发,5到达,6服务中,7服务完成 -->
|
||||||
|
<block v-if="[2, 3, 4, 5, 6, 8].includes(item.pay_type)">
|
||||||
|
<button
|
||||||
|
@tap.stop="$util.goUrl({url:`/agent/pages/order/change?id=${item.id}&agent=${options.agent}`})"
|
||||||
|
class="clear-btn order" style="margin-left: 0;" v-if="!options.bell">转单</button>
|
||||||
|
<button @tap.stop="toConfirm(index)" class="clear-btn order"
|
||||||
|
:style="{color:'#fff',background:primaryColor,borderColor:primaryColor}">{{ $t( `action.${ technicianStatusOperType[ item.pay_type === 3 && (item.is_add || item.store_id) ? 5 : item.pay_type == 8 ? -1 : item.pay_type ] }` ) }}</button>
|
||||||
|
</block>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<load-more :noMore="list.current_page>=list.last_page&&list.data.length>0" :loading="loading" v-if="loading">
|
||||||
|
</load-more>
|
||||||
|
<abnor v-if="!loading&&list.data.length<=0&&list.current_page==1"></abnor>
|
||||||
|
|
||||||
|
<view class="space-footer"></view>
|
||||||
|
|
||||||
|
<uni-popup ref="change_item" type="center" :custom="true">
|
||||||
|
<view class="common-popup-content fill-base pd-lg radius-34">
|
||||||
|
<view class="title">温馨提示</view>
|
||||||
|
<view class="desc">
|
||||||
|
你确认要操作{{$t(`action.${technicianStatusOperType[popupInfo.type]}`)}}吗?
|
||||||
|
</view>
|
||||||
|
<view class="f-caption c-warning" v-if="popupInfo.type == -1">退款金额:¥{{popupInfo.refund_price}}</view>
|
||||||
|
<view class="button">
|
||||||
|
<view @tap.stop="$refs.change_item.close()" class="item-child">取消</view>
|
||||||
|
<view @tap.stop="confirmChangeOrder" class="item-child c-base"
|
||||||
|
:style="{background: primaryColor,color:'#fff'}">确定</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</uni-popup>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
mapState,
|
||||||
|
mapActions,
|
||||||
|
mapMutations
|
||||||
|
} from "vuex"
|
||||||
|
export default {
|
||||||
|
components: {},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
isLoad: false,
|
||||||
|
options: {},
|
||||||
|
activeIndex: 0,
|
||||||
|
tabList: [],
|
||||||
|
tabOrderList: [{
|
||||||
|
title: '全部',
|
||||||
|
id: 0
|
||||||
|
}, {
|
||||||
|
title: '待服务',
|
||||||
|
id: 2,
|
||||||
|
number: 0
|
||||||
|
}, {
|
||||||
|
title: this.$t('action.attendantName') + '接单',
|
||||||
|
id: 3,
|
||||||
|
number: 0
|
||||||
|
}, {
|
||||||
|
title: this.$t('action.attendantName') + '出发',
|
||||||
|
id: 4,
|
||||||
|
number: 0
|
||||||
|
}, {
|
||||||
|
title: this.$t('action.attendantName') + '到达',
|
||||||
|
id: 5,
|
||||||
|
number: 0
|
||||||
|
}, {
|
||||||
|
title: '服务中',
|
||||||
|
id: 6,
|
||||||
|
number: 0
|
||||||
|
}, {
|
||||||
|
title: '已完成',
|
||||||
|
id: 7,
|
||||||
|
number: 0
|
||||||
|
}],
|
||||||
|
tabBellList: [{
|
||||||
|
title: '全部',
|
||||||
|
id: 0
|
||||||
|
}, {
|
||||||
|
title: '待服务',
|
||||||
|
id: 2,
|
||||||
|
number: 0
|
||||||
|
}, {
|
||||||
|
title: this.$t('action.attendantName') + '接单',
|
||||||
|
id: 3,
|
||||||
|
number: 0
|
||||||
|
}, {
|
||||||
|
title: '服务中',
|
||||||
|
id: 6,
|
||||||
|
number: 0
|
||||||
|
}, {
|
||||||
|
title: '已完成',
|
||||||
|
id: 7,
|
||||||
|
number: 0
|
||||||
|
}],
|
||||||
|
statusType: {
|
||||||
|
'-1': '已取消',
|
||||||
|
1: '待支付',
|
||||||
|
2: '待服务',
|
||||||
|
3: this.$t('action.attendantName') + '接单',
|
||||||
|
4: this.$t('action.attendantName') + '出发',
|
||||||
|
5: this.$t('action.attendantName') + '到达',
|
||||||
|
6: '服务中',
|
||||||
|
7: '已完成',
|
||||||
|
8: '待转单'
|
||||||
|
},
|
||||||
|
technicianStatusOperType: {
|
||||||
|
'-1': 'agreeRefund',
|
||||||
|
2: 'orderTaking',
|
||||||
|
3: 'setOut',
|
||||||
|
4: 'arrive',
|
||||||
|
5: 'startService',
|
||||||
|
6: 'serviceCompletion',
|
||||||
|
8: 'transferOrder'
|
||||||
|
},
|
||||||
|
param: {
|
||||||
|
page: 1,
|
||||||
|
pay_type: 0,
|
||||||
|
order_code: ''
|
||||||
|
},
|
||||||
|
list: {
|
||||||
|
data: []
|
||||||
|
},
|
||||||
|
loading: true,
|
||||||
|
index: -1,
|
||||||
|
lockTap: false,
|
||||||
|
popupInfo: {
|
||||||
|
title: '',
|
||||||
|
index: '',
|
||||||
|
type: '',
|
||||||
|
param: {},
|
||||||
|
imgs: [],
|
||||||
|
location: {
|
||||||
|
lat: 0,
|
||||||
|
lng: 0,
|
||||||
|
address: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: mapState({
|
||||||
|
primaryColor: state => state.config.configInfo.primaryColor,
|
||||||
|
subColor: state => state.config.configInfo.subColor,
|
||||||
|
configInfo: state => state.config.configInfo,
|
||||||
|
userInfo: state => state.user.userInfo,
|
||||||
|
}),
|
||||||
|
onLoad(options) {
|
||||||
|
let {
|
||||||
|
agent = 0,
|
||||||
|
bell = 0,
|
||||||
|
tab = 0,
|
||||||
|
} = options
|
||||||
|
options.agent = agent * 1
|
||||||
|
options.bell = bell * 1
|
||||||
|
this.options = options
|
||||||
|
uni.setNavigationBarTitle({
|
||||||
|
title: tab == 8 ? '拒单管理' : bell == 1 ? '加钟管理' : '订单管理'
|
||||||
|
})
|
||||||
|
this.tabList = tab == 8 ? [] : bell == 1 ? this.tabBellList : this.tabOrderList
|
||||||
|
this.activeIndex = tab
|
||||||
|
this.initIndex()
|
||||||
|
},
|
||||||
|
onPullDownRefresh() {
|
||||||
|
// #ifndef APP-PLUS
|
||||||
|
uni.showNavigationBarLoading()
|
||||||
|
// #endif
|
||||||
|
this.initRefresh();
|
||||||
|
uni.stopPullDownRefresh()
|
||||||
|
},
|
||||||
|
onReachBottom() {
|
||||||
|
if (this.list.current_page >= this.list.last_page || this.loading) return;
|
||||||
|
this.param.page = this.param.page + 1;
|
||||||
|
this.loading = true;
|
||||||
|
this.getList();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
...mapActions(['getConfigInfo']),
|
||||||
|
...mapMutations(['updateTechnicianItem']),
|
||||||
|
async initIndex(refresh = false) {
|
||||||
|
// #ifdef H5
|
||||||
|
if (!refresh && this.$jweixin.isWechat()) {
|
||||||
|
await this.$jweixin.initJssdk();
|
||||||
|
this.$jweixin.wxReady(() => {
|
||||||
|
this.$jweixin.hideOptionMenu()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
if (!this.configInfo.id || refresh) {
|
||||||
|
await this.getConfigInfo()
|
||||||
|
}
|
||||||
|
await this.getList()
|
||||||
|
this.isLoad = true
|
||||||
|
this.$util.setNavigationBarColor({
|
||||||
|
bg: this.primaryColor
|
||||||
|
})
|
||||||
|
},
|
||||||
|
initRefresh() {
|
||||||
|
this.param.page = 1
|
||||||
|
this.initIndex(true)
|
||||||
|
},
|
||||||
|
toSearch(val) {
|
||||||
|
this.param.page = 1
|
||||||
|
this.param.order_code = val
|
||||||
|
this.getList()
|
||||||
|
},
|
||||||
|
async getList(flag = false) {
|
||||||
|
let {
|
||||||
|
list: oldList,
|
||||||
|
param,
|
||||||
|
tabList,
|
||||||
|
activeIndex,
|
||||||
|
} = this
|
||||||
|
let {
|
||||||
|
tab = 0,
|
||||||
|
bell = 0,
|
||||||
|
agent = 0
|
||||||
|
} = this.options
|
||||||
|
let methodKey = agent ? 'agent' : 'admin'
|
||||||
|
param.pay_type = tab == 8 ? 8 : tabList[activeIndex].id
|
||||||
|
if (tab != 8) {
|
||||||
|
param.is_add = bell
|
||||||
|
}
|
||||||
|
let newList = await this.$api[methodKey].orderList(param)
|
||||||
|
|
||||||
|
if (!flag) {
|
||||||
|
if (this.param.page == 1) {
|
||||||
|
this.list = newList
|
||||||
|
} else {
|
||||||
|
newList.data = oldList.data.concat(newList.data)
|
||||||
|
this.list = newList
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.loading = false
|
||||||
|
this.$util.hideAll()
|
||||||
|
},
|
||||||
|
handerTabChange(index) {
|
||||||
|
this.activeIndex = index;
|
||||||
|
this.$util.showLoading()
|
||||||
|
this.param.page = 1;
|
||||||
|
this.getList()
|
||||||
|
},
|
||||||
|
// type: -1拒绝接单,3确定接单,4已出发,5已到达,6开始服务,7服务完成
|
||||||
|
async toConfirm(index) {
|
||||||
|
let {
|
||||||
|
id: order_id,
|
||||||
|
pay_type,
|
||||||
|
true_car_price,
|
||||||
|
true_service_price,
|
||||||
|
is_add = 0,
|
||||||
|
store_id = 0
|
||||||
|
} = this.list.data[index]
|
||||||
|
let type = pay_type === 3 && (is_add || store_id) ?
|
||||||
|
5 :
|
||||||
|
pay_type
|
||||||
|
let refund_price = (true_car_price * 1 + true_service_price * 1).toFixed(2)
|
||||||
|
this.popupInfo = {
|
||||||
|
index,
|
||||||
|
order_id,
|
||||||
|
type: pay_type == 8 ? -1 : type,
|
||||||
|
refund_price
|
||||||
|
}
|
||||||
|
this.$refs.change_item.open()
|
||||||
|
},
|
||||||
|
async confirmChangeOrder() {
|
||||||
|
let param = this.$util.deepCopy(this.popupInfo)
|
||||||
|
param.type = param.type + 1
|
||||||
|
let {
|
||||||
|
index,
|
||||||
|
type
|
||||||
|
} = param
|
||||||
|
delete param.index
|
||||||
|
delete param.refund_price
|
||||||
|
let msg = {
|
||||||
|
'-1': '退款成功',
|
||||||
|
3: '接单成功',
|
||||||
|
4: '已成功出发',
|
||||||
|
5: '已成功到达',
|
||||||
|
6: '已开始服务',
|
||||||
|
7: '服务已完成'
|
||||||
|
}
|
||||||
|
let {
|
||||||
|
activeIndex
|
||||||
|
} = this
|
||||||
|
if (this.lockTap) return;
|
||||||
|
this.lockTap = true;
|
||||||
|
this.$util.showLoading()
|
||||||
|
let {
|
||||||
|
agent
|
||||||
|
} = this.options
|
||||||
|
let methodKey = agent ? 'agent' : 'admin'
|
||||||
|
try {
|
||||||
|
await this.$api[methodKey].adminUpdateOrder(param)
|
||||||
|
this.$refs.change_item.close()
|
||||||
|
this.$util.showToast({
|
||||||
|
title: msg[type]
|
||||||
|
})
|
||||||
|
if (activeIndex == 0) {
|
||||||
|
this.list.data[index].pay_type = type
|
||||||
|
} else {
|
||||||
|
this.list.data.splice(index, 1)
|
||||||
|
}
|
||||||
|
this.lockTap = false;
|
||||||
|
this.$util.hideAll()
|
||||||
|
this.updateTechnicianItem({
|
||||||
|
key: 'haveOperItem',
|
||||||
|
val: true
|
||||||
|
})
|
||||||
|
if (activeIndex == 0) return
|
||||||
|
await this.getList(true)
|
||||||
|
} catch (e) {
|
||||||
|
setTimeout(() => {
|
||||||
|
this.lockTap = false
|
||||||
|
this.$util.hideAll()
|
||||||
|
}, 2000)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 订单详情
|
||||||
|
goDetail(index) {
|
||||||
|
let {
|
||||||
|
id
|
||||||
|
} = this.list.data[index]
|
||||||
|
let {
|
||||||
|
agent
|
||||||
|
} = this.options
|
||||||
|
let url = `/agent/pages/order/detail?id=${id}&agent=${agent}`
|
||||||
|
this.$util.goUrl({
|
||||||
|
url
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
</style>
|
|
@ -0,0 +1,237 @@
|
||||||
|
<template>
|
||||||
|
<view>
|
||||||
|
<view class="hideCanvasView">
|
||||||
|
<l-painter class="hideCanvas" ref="painter" useCORS />
|
||||||
|
</view>
|
||||||
|
<block v-if="src">
|
||||||
|
<image :src="src" class="code-img" @tap="previewImage"></image>
|
||||||
|
<view class="space-max-footer"></view>
|
||||||
|
<fix-bottom-button @confirm="toPreviewSave" :text="[{text: confirmText,type:'confirm'}]" bgColor="#fff"
|
||||||
|
:classType="2">
|
||||||
|
</fix-bottom-button>
|
||||||
|
</block>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
mapState,
|
||||||
|
mapActions
|
||||||
|
} from 'vuex';
|
||||||
|
export default {
|
||||||
|
components: {},
|
||||||
|
props: {
|
||||||
|
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
options: {},
|
||||||
|
// #ifdef H5
|
||||||
|
confirmText: '长按上图保存图片',
|
||||||
|
// #endif
|
||||||
|
// #ifndef H5
|
||||||
|
confirmText: '保存图片至相册',
|
||||||
|
// #endif
|
||||||
|
src: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: mapState({
|
||||||
|
primaryColor: state => state.config.configInfo.primaryColor,
|
||||||
|
configInfo: state => state.config.configInfo,
|
||||||
|
userInfo: state => state.user.userInfo,
|
||||||
|
}),
|
||||||
|
async onLoad(options) {
|
||||||
|
this.options = options
|
||||||
|
// #ifdef H5
|
||||||
|
if (this.$jweixin.isWechat()) {
|
||||||
|
await this.$jweixin.initJssdk();
|
||||||
|
this.$jweixin.wxReady(() => {
|
||||||
|
this.$jweixin.hideOptionMenu()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
this.$util.showLoading()
|
||||||
|
await this.getConfigInfo()
|
||||||
|
this.$util.setNavigationBarColor({
|
||||||
|
bg: this.primaryColor
|
||||||
|
})
|
||||||
|
let that = this
|
||||||
|
setTimeout(() => {
|
||||||
|
that.renderToCanvas()
|
||||||
|
}, 1000)
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
...mapActions(['getConfigInfo']),
|
||||||
|
async renderToCanvas() {
|
||||||
|
let that = this;
|
||||||
|
let {
|
||||||
|
type = 0
|
||||||
|
} = that.options
|
||||||
|
|
||||||
|
let qr_code = type == 1 ? await this.$api.salesman.salesmanQr() : await this.$api.agent.agentInviteQr({
|
||||||
|
type: 1
|
||||||
|
})
|
||||||
|
|
||||||
|
let {
|
||||||
|
channel_poster = ''
|
||||||
|
} = this.configInfo
|
||||||
|
|
||||||
|
let cover = channel_poster || 'https://lbqny.migugu.com/admin/anmo/mine/channel-share.png'
|
||||||
|
|
||||||
|
let {
|
||||||
|
nickName,
|
||||||
|
avatarUrl
|
||||||
|
} = this.userInfo
|
||||||
|
let qr_radius = '0rpx'
|
||||||
|
// #ifdef MP-WEIXIN
|
||||||
|
qr_radius = '97rpx'
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
let poster = {
|
||||||
|
css: {
|
||||||
|
width: '750rpx',
|
||||||
|
height: '1280rpx',
|
||||||
|
},
|
||||||
|
views: [{
|
||||||
|
type: 'image',
|
||||||
|
src: cover,
|
||||||
|
css: {
|
||||||
|
width: '750rpx',
|
||||||
|
height: '1140rpx',
|
||||||
|
objectFit: "cover",
|
||||||
|
top: '0rpx',
|
||||||
|
left: '0rpx',
|
||||||
|
position: 'absolute'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'view',
|
||||||
|
css: {
|
||||||
|
background: '#fff',
|
||||||
|
width: '750rpx',
|
||||||
|
height: '140rpx',
|
||||||
|
bottom: '0rpx',
|
||||||
|
left: '0rpx',
|
||||||
|
position: 'absolute'
|
||||||
|
},
|
||||||
|
views: [{
|
||||||
|
type: 'image',
|
||||||
|
src: avatarUrl,
|
||||||
|
css: {
|
||||||
|
position: 'absolute',
|
||||||
|
width: '94rpx',
|
||||||
|
height: '94rpx',
|
||||||
|
objectFit: 'cover',
|
||||||
|
borderRadius: '50rpx',
|
||||||
|
bottom: '23rpx',
|
||||||
|
left: '20rpx'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'text',
|
||||||
|
text: nickName,
|
||||||
|
css: {
|
||||||
|
position: 'absolute',
|
||||||
|
bottom: '70rpx',
|
||||||
|
left: '130rpx',
|
||||||
|
width: '350rpx',
|
||||||
|
fontSize: '32rpx',
|
||||||
|
fontWeight: '400',
|
||||||
|
color: '#000'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'text',
|
||||||
|
text: '邀请您成为TA的渠道商,扫描二维码立即加入吧!',
|
||||||
|
css: {
|
||||||
|
position: 'absolute',
|
||||||
|
bottom: '25rpx',
|
||||||
|
left: '130rpx',
|
||||||
|
width: '750rpx',
|
||||||
|
fontSize: '26rpx',
|
||||||
|
color: '#999999',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'image',
|
||||||
|
src: qr_code,
|
||||||
|
css: {
|
||||||
|
position: 'absolute',
|
||||||
|
width: '200rpx',
|
||||||
|
height: '200rpx',
|
||||||
|
bottom: '337rpx',
|
||||||
|
left: '53rpx',
|
||||||
|
background: '#ffffff',
|
||||||
|
borderRadius: qr_radius
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'text',
|
||||||
|
text: '扫一扫',
|
||||||
|
css: {
|
||||||
|
position: 'absolute',
|
||||||
|
bottom: '290rpx',
|
||||||
|
left: '53rpx',
|
||||||
|
width: '200rpx',
|
||||||
|
fontSize: '26rpx',
|
||||||
|
color: '#999999',
|
||||||
|
textAlign: 'center'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
]
|
||||||
|
}
|
||||||
|
// 渲染
|
||||||
|
this.$refs.painter.render(poster);
|
||||||
|
// 生成图片
|
||||||
|
this.$refs.painter.canvasToTempFilePathSync({
|
||||||
|
fileType: "jpg",
|
||||||
|
quality: 1,
|
||||||
|
success: (res) => {
|
||||||
|
that.$util.hideAll()
|
||||||
|
this.src = res.tempFilePath
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
},
|
||||||
|
previewImage() {
|
||||||
|
let finalPath = this.src;
|
||||||
|
uni.previewImage({
|
||||||
|
current: finalPath,
|
||||||
|
urls: [finalPath]
|
||||||
|
})
|
||||||
|
},
|
||||||
|
async saveImage() {
|
||||||
|
await this.$util.checkAuth({
|
||||||
|
type: "writePhotosAlbum"
|
||||||
|
});
|
||||||
|
let filePath = this.src;
|
||||||
|
let [err, success] = await uni.saveImageToPhotosAlbum({
|
||||||
|
filePath
|
||||||
|
})
|
||||||
|
if (err) return;
|
||||||
|
uni.showToast({
|
||||||
|
icon: 'none',
|
||||||
|
title: '保存成功'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
toPreviewSave() {
|
||||||
|
// #ifdef H5
|
||||||
|
this.previewImage()
|
||||||
|
// #endif
|
||||||
|
// #ifndef H5
|
||||||
|
this.saveImage()
|
||||||
|
// #endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.code-img {
|
||||||
|
width: 750rpx;
|
||||||
|
height: 1280rpx;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,218 @@
|
||||||
|
<template>
|
||||||
|
<view>
|
||||||
|
<view class="hideCanvasView">
|
||||||
|
<l-painter class="hideCanvas" ref="painter" useCORS />
|
||||||
|
</view>
|
||||||
|
<block v-if="src">
|
||||||
|
<image :src="src" class="code-img" @tap="previewImage"></image>
|
||||||
|
<view class="space-max-footer"></view>
|
||||||
|
<fix-bottom-button @confirm="toPreviewSave" :text="[{text: confirmText,type:'confirm'}]" bgColor="#fff"
|
||||||
|
:classType="2">
|
||||||
|
</fix-bottom-button>
|
||||||
|
</block>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
mapState,
|
||||||
|
mapActions
|
||||||
|
} from 'vuex';
|
||||||
|
export default {
|
||||||
|
components: {},
|
||||||
|
props: {
|
||||||
|
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
// #ifdef H5
|
||||||
|
confirmText: '长按上图保存图片',
|
||||||
|
// #endif
|
||||||
|
// #ifndef H5
|
||||||
|
confirmText: '保存图片至相册',
|
||||||
|
// #endif
|
||||||
|
src: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: mapState({
|
||||||
|
primaryColor: state => state.config.configInfo.primaryColor,
|
||||||
|
configInfo: state => state.config.configInfo,
|
||||||
|
userInfo: state => state.user.userInfo,
|
||||||
|
}),
|
||||||
|
async onLoad(options) {
|
||||||
|
// #ifdef H5
|
||||||
|
if (this.$jweixin.isWechat()) {
|
||||||
|
await this.$jweixin.initJssdk();
|
||||||
|
this.$jweixin.wxReady(() => {
|
||||||
|
this.$jweixin.hideOptionMenu()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
this.$util.showLoading()
|
||||||
|
await this.getConfigInfo()
|
||||||
|
this.$util.setNavigationBarColor({
|
||||||
|
bg: this.primaryColor
|
||||||
|
})
|
||||||
|
let that = this
|
||||||
|
setTimeout(() => {
|
||||||
|
that.renderToCanvas()
|
||||||
|
}, 1000)
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
...mapActions(['getConfigInfo']),
|
||||||
|
async renderToCanvas() {
|
||||||
|
let that = this;
|
||||||
|
let qr_code = await this.$api.agent.agentInviteQr({
|
||||||
|
type: 2
|
||||||
|
})
|
||||||
|
|
||||||
|
let {
|
||||||
|
salesman_poster = ''
|
||||||
|
} = this.configInfo
|
||||||
|
|
||||||
|
let cover = salesman_poster || 'https://lbqny.migugu.com/admin/anmo/mine/salesman-share.png'
|
||||||
|
|
||||||
|
let {
|
||||||
|
nickName,
|
||||||
|
avatarUrl
|
||||||
|
} = this.userInfo
|
||||||
|
let qr_radius = '0rpx'
|
||||||
|
// #ifdef MP-WEIXIN
|
||||||
|
qr_radius = '145rpx'
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
let poster = {
|
||||||
|
css: {
|
||||||
|
width: '750rpx',
|
||||||
|
height: '1280rpx',
|
||||||
|
},
|
||||||
|
views: [{
|
||||||
|
type: 'image',
|
||||||
|
src: cover,
|
||||||
|
css: {
|
||||||
|
width: '750rpx',
|
||||||
|
height: '1140rpx',
|
||||||
|
objectFit: "cover",
|
||||||
|
top: '0rpx',
|
||||||
|
left: '0rpx',
|
||||||
|
position: 'absolute'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'view',
|
||||||
|
css: {
|
||||||
|
background: '#fff',
|
||||||
|
width: '750rpx',
|
||||||
|
height: '140rpx',
|
||||||
|
bottom: '0rpx',
|
||||||
|
left: '0rpx',
|
||||||
|
position: 'absolute'
|
||||||
|
},
|
||||||
|
views: [{
|
||||||
|
type: 'image',
|
||||||
|
src: avatarUrl,
|
||||||
|
css: {
|
||||||
|
position: 'absolute',
|
||||||
|
width: '94rpx',
|
||||||
|
height: '94rpx',
|
||||||
|
objectFit: "cover",
|
||||||
|
borderRadius: '50rpx',
|
||||||
|
bottom: '23rpx',
|
||||||
|
left: '20rpx'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'text',
|
||||||
|
text: nickName,
|
||||||
|
css: {
|
||||||
|
position: 'absolute',
|
||||||
|
bottom: '70rpx',
|
||||||
|
left: '130rpx',
|
||||||
|
width: '350rpx',
|
||||||
|
fontSize: '32rpx',
|
||||||
|
fontWeight: '400',
|
||||||
|
color: '#000'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'text',
|
||||||
|
text: '邀请您成为TA的业务员,扫描二维码立即加入吧!',
|
||||||
|
css: {
|
||||||
|
position: 'absolute',
|
||||||
|
bottom: '25rpx',
|
||||||
|
left: '130rpx',
|
||||||
|
width: '750rpx',
|
||||||
|
fontSize: '26rpx',
|
||||||
|
color: '#999999',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'image',
|
||||||
|
src: qr_code,
|
||||||
|
css: {
|
||||||
|
position: 'absolute',
|
||||||
|
width: '290rpx',
|
||||||
|
height: '290rpx',
|
||||||
|
bottom: '366rpx',
|
||||||
|
left: '228rpx',
|
||||||
|
background: '#ffffff',
|
||||||
|
borderRadius: qr_radius
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
]
|
||||||
|
}
|
||||||
|
// 渲染
|
||||||
|
this.$refs.painter.render(poster);
|
||||||
|
// 生成图片
|
||||||
|
this.$refs.painter.canvasToTempFilePathSync({
|
||||||
|
fileType: "jpg",
|
||||||
|
quality: 1,
|
||||||
|
success: (res) => {
|
||||||
|
that.$util.hideAll()
|
||||||
|
this.src = res.tempFilePath
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
},
|
||||||
|
previewImage() {
|
||||||
|
let finalPath = this.src;
|
||||||
|
uni.previewImage({
|
||||||
|
current: finalPath,
|
||||||
|
urls: [finalPath]
|
||||||
|
})
|
||||||
|
},
|
||||||
|
async saveImage() {
|
||||||
|
await this.$util.checkAuth({
|
||||||
|
type: "writePhotosAlbum"
|
||||||
|
});
|
||||||
|
let filePath = this.src;
|
||||||
|
let [err, success] = await uni.saveImageToPhotosAlbum({
|
||||||
|
filePath
|
||||||
|
})
|
||||||
|
if (err) return;
|
||||||
|
uni.showToast({
|
||||||
|
icon: 'none',
|
||||||
|
title: '保存成功'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
toPreviewSave() {
|
||||||
|
// #ifdef H5
|
||||||
|
this.previewImage()
|
||||||
|
// #endif
|
||||||
|
// #ifndef H5
|
||||||
|
this.saveImage()
|
||||||
|
// #endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.code-img {
|
||||||
|
width: 750rpx;
|
||||||
|
height: 1280rpx;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,415 @@
|
||||||
|
<template>
|
||||||
|
<view class="order-pages" v-if="detail.id">
|
||||||
|
|
||||||
|
<view class="item-child flex-center pd-lg fill-base f-paragraph c-base" style="height:200rpx"
|
||||||
|
:style="{background:primaryColor}">
|
||||||
|
<view class="flex-1 flex-y-baseline f-md-title">{{statusType[detail.status]}}
|
||||||
|
<view class="f-desc ml-md" v-if="detail.status == 2">退款金额¥{{detail.refund_price}}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="item-child mt-md ml-lg mr-lg pd-lg fill-base radius-16">
|
||||||
|
<view class="flex-between pb-lg">
|
||||||
|
<view class="f-paragraph c-title max-380 ellipsis">服务内容</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-center" :class="[{'mb-lg':aindex != detail.order_goods.length -1}]"
|
||||||
|
v-for="(aitem,aindex) in detail.order_goods" :key="aindex">
|
||||||
|
<!-- #ifdef H5 -->
|
||||||
|
<view class="avatar lg radius-16">
|
||||||
|
<view class="h5-image avatar lg radius-16"
|
||||||
|
:style="{ backgroundImage : `url('${aitem.goods_cover}')`}">
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<!-- #endif -->
|
||||||
|
<!-- #ifndef H5 -->
|
||||||
|
<image mode="aspectFill" class="avatar lg radius-16" :src="aitem.goods_cover"></image>
|
||||||
|
<!-- #endif -->
|
||||||
|
<view class="flex-1 ml-md">
|
||||||
|
<view class="flex-between">
|
||||||
|
<view class="f-mini-title c-title text-bold max-380 ellipsis">
|
||||||
|
{{aitem.goods_name}}
|
||||||
|
</view>
|
||||||
|
<view class="c-paragraph">x{{aitem.num}}</view>
|
||||||
|
</view>
|
||||||
|
<view class="f-caption c-caption" v-if="aitem.material_price*1>0">物料费:¥{{aitem.material_price}}
|
||||||
|
</view>
|
||||||
|
<view class="f-caption mt-md" style="color:#777">服务时长 {{aitem.time_long}}分钟</view>
|
||||||
|
<view class="f-paragraph c-warning text-bold mt-sm">¥{{aitem.goods_price}}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="store-info mt-md ml-lg mr-lg pd-lg fill-base radius-16" v-if="detail.store_id">
|
||||||
|
<view class="f-mini-title c-title text-bold pb-md">
|
||||||
|
{{detail.store_info.title}}
|
||||||
|
</view>
|
||||||
|
<view class="flex-between">
|
||||||
|
<view class="flex-y-center" style="color: #303030;">
|
||||||
|
<i class="iconfont icondizhi1 mr-sm"></i>
|
||||||
|
<view class="c-title flex-1 mr-md">
|
||||||
|
<span>{{detail.store_info.address || `暂未设置门店地址`}}</span>
|
||||||
|
<span @tap.stop="$util.goUrl({url:detail.store_info.address,openType:'copy'})"
|
||||||
|
class="copy-btn span radius-5 f-icontext ml-sm"
|
||||||
|
:style="{color:primaryColor,borderColor:primaryColor}"
|
||||||
|
v-if="detail.store_info.address">复制</span>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-center">
|
||||||
|
<view @tap.stop="$util.goUrl({url:detail.store_info.phone,openType:'call'})"
|
||||||
|
class="item-icon rel flex-center radius-16">
|
||||||
|
<view class="item-icon radius-16 abs" :style="{background:primaryColor}"></view>
|
||||||
|
<i class="iconfont icondadianhua_1" :style="{color:primaryColor}"></i>
|
||||||
|
</view>
|
||||||
|
<view @tap.stop="toMap('store_info')" class="item-icon rel flex-center radius-16 ml-md"
|
||||||
|
v-if="detail.store_info.address">
|
||||||
|
<view class="item-icon radius-16 abs" :style="{background:primaryColor}"></view>
|
||||||
|
<i class="iconfont icondizhi_1" :style="{color:primaryColor}"></i>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
|
||||||
|
<view class="order-agent-info store-info mt-md ml-lg mr-lg pd-lg fill-base f-paragraph radius-16">
|
||||||
|
<view class="flex-between">
|
||||||
|
<image mode="aspectFill" class="coach-img radius" :src="detail.coach_info.work_img"></image>
|
||||||
|
<view class="f-title text-bold max-450 ellipsis">
|
||||||
|
{{detail.coach_info ? detail.coach_info.coach_name : ''}}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-center mt-lg">
|
||||||
|
<view class="title">下单人</view>
|
||||||
|
<view class="text flex-1 ellipsis">{{detail.address_info.user_name}}</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-center mt-lg">
|
||||||
|
<view class="title">联系方式</view>
|
||||||
|
<view class="text flex-1 flex-between">
|
||||||
|
<view>
|
||||||
|
{{detail.address_info.mobile.substring(0,3)}}****{{detail.address_info.mobile.substring(7,11)}}
|
||||||
|
</view>
|
||||||
|
<view @tap.stop="toTel" class="item-icon rel flex-center radius-16">
|
||||||
|
<view class="item-icon radius-16 abs" :style="{background:primaryColor}"></view>
|
||||||
|
<i class="iconfont icondadianhua_1" :style="{color:primaryColor}"></i>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-warp mt-lg" v-if="!detail.store_id">
|
||||||
|
<view class="title">服务地址</view>
|
||||||
|
<view class="text flex-1 flex-between">
|
||||||
|
<view style="max-width: 350rpx;">
|
||||||
|
<span>{{`${detail.address_info.address}${detail.address_info.address_info}`}}</span>
|
||||||
|
<span @tap="toCopy" class="copy-btn fill radius-5 f-icontext ml-sm">复制</span>
|
||||||
|
</view>
|
||||||
|
<view @tap.stop="toMap('address_info')" class="item-icon rel flex-center radius-16">
|
||||||
|
<view class="item-icon radius-16 abs" :style="{background:primaryColor}"></view>
|
||||||
|
<i class="iconfont icondizhi_1" :style="{color:primaryColor}"></i>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-between mt-lg pt-lg b-1px-t">
|
||||||
|
<view class="title"></view>
|
||||||
|
<view class="flex-y-baseline f-paragraph c-black text-bold">总计:<view class="c-warning">
|
||||||
|
¥{{detail.apply_price}}</view>
|
||||||
|
<view class="flex-y-center ml-md" v-if="detail.car_price*1>0">含车费:
|
||||||
|
<view class="f-icontext">¥</view>{{detail.car_price}}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
|
||||||
|
<view class="order-agent-info mt-md ml-lg mr-lg pd-lg fill-base radius-16">
|
||||||
|
<view class="flex-center">
|
||||||
|
<view class="title">退款单号</view>
|
||||||
|
<view class="text flex-1">
|
||||||
|
<view class="flex-between">
|
||||||
|
<view class="max-350 ellipsis">{{detail.order_code}}</view>
|
||||||
|
<view @tap="$util.goUrl( {url:`${detail.order_code}`,openType:'copy'})"
|
||||||
|
class="copy-btn flex-center radius-5 f-icontext"
|
||||||
|
:style="{color:primaryColor,borderColor:primaryColor}">
|
||||||
|
复制</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-center mt-lg" v-if="detail.out_refund_no">
|
||||||
|
<view class="title">微信退款单号</view>
|
||||||
|
<view class="text flex-1">
|
||||||
|
<view class="flex-between">
|
||||||
|
<view class="max-350 ellipsis">{{detail.out_refund_no}}</view>
|
||||||
|
<view @tap="$util.goUrl( {url:`${detail.out_refund_no}`,openType:'copy'})"
|
||||||
|
class="copy-btn flex-center radius-5 f-icontext"
|
||||||
|
:style="{color:primaryColor,borderColor:primaryColor}">复制</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-center mt-lg">
|
||||||
|
<view class="title">提交日期</view>
|
||||||
|
<view class="text flex-1 ellipsis">{{detail.create_time}}</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-center mt-lg" v-if="detail.status != 1">
|
||||||
|
<view class="title">审核日期</view>
|
||||||
|
<view class="text flex-1 ellipsis">{{detail.refund_time}}</view>
|
||||||
|
</view>
|
||||||
|
<view class="mt-lg">
|
||||||
|
<view class="title">退款原因</view>
|
||||||
|
<view class="text mt-sm">{{detail.text}}</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-column" v-if="detail.imgs && detail.imgs.length > 0">
|
||||||
|
<view class="title">上传图片</view>
|
||||||
|
<view class="flex-warp">
|
||||||
|
<block v-for="(item,index) in detail.imgs" :key="index">
|
||||||
|
<image @tap.top="previewImage(item,detail.imgs)" class="refund-img mt-md mr-md radius-10"
|
||||||
|
:src="item" />
|
||||||
|
</block>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="space-max-footer"></view>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<fix-bottom-button @cancel="toConfirm(3)" @confirm="toConfirm(2)"
|
||||||
|
:text="[{text:'拒绝退款',type:'cancel'},{text:'同意退款',type:'confirm'}]" bgColor="#fff" :classType="2"
|
||||||
|
v-if="detail.status==1">
|
||||||
|
</fix-bottom-button>
|
||||||
|
|
||||||
|
|
||||||
|
<uni-popup ref="change_item" type="center" :custom="true">
|
||||||
|
<view class="common-popup-content fill-base pd-lg radius-34">
|
||||||
|
<view class="title">温馨提示</view>
|
||||||
|
<view class="desc">
|
||||||
|
你确认要操作{{statusType[popupInfo.type]}}吗?
|
||||||
|
</view>
|
||||||
|
<view class="mt-lg" v-if="popupInfo.type == 2">
|
||||||
|
<input v-model="popupInfo.price" type="digit"
|
||||||
|
class="input flex-y-center pl-lg pr-lg f-sm-title c-title radius-16"
|
||||||
|
placeholder-class="c-placeholder" placeholder="请输入退款金额" />
|
||||||
|
<view class="f-desc c-caption mt-md">
|
||||||
|
<view class="flex-y-center">实际可退款金额<view class="ml-sm c-warning">¥{{popupInfo.apply_price}}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view>退款金额不能大于可退款金额</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="button">
|
||||||
|
<view @tap.stop="$refs.change_item.close()" class="item-child">取消</view>
|
||||||
|
<view @tap.stop="confirmChangeOrder" class="item-child c-base"
|
||||||
|
:style="{background: primaryColor,color:'#fff'}">确定</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</uni-popup>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
mapState,
|
||||||
|
mapActions,
|
||||||
|
mapMutations
|
||||||
|
} from "vuex"
|
||||||
|
export default {
|
||||||
|
components: {},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
options: {},
|
||||||
|
carType: {
|
||||||
|
0: '公交/地铁',
|
||||||
|
1: '出租车'
|
||||||
|
},
|
||||||
|
payType: {
|
||||||
|
1: '微信支付',
|
||||||
|
2: '余额支付',
|
||||||
|
3: '支付宝支付'
|
||||||
|
},
|
||||||
|
statusType: {
|
||||||
|
1: '退款申请中',
|
||||||
|
2: '同意退款',
|
||||||
|
3: '拒绝退款',
|
||||||
|
},
|
||||||
|
detail: {
|
||||||
|
pay_type: 0
|
||||||
|
},
|
||||||
|
lockTap: false,
|
||||||
|
popupInfo: {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: mapState({
|
||||||
|
primaryColor: state => state.config.configInfo.primaryColor,
|
||||||
|
subColor: state => state.config.configInfo.subColor,
|
||||||
|
configInfo: state => state.config.configInfo,
|
||||||
|
userInfo: state => state.user.userInfo,
|
||||||
|
over_time_text() {
|
||||||
|
return new Date().getTime() + this.detail.end_time * 1000
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
onLoad(options) {
|
||||||
|
let {
|
||||||
|
agent = 0
|
||||||
|
} = options
|
||||||
|
options.agent = agent * 1
|
||||||
|
this.options = options
|
||||||
|
this.initIndex()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
...mapActions(['getConfigInfo', 'getCoachInfo']),
|
||||||
|
...mapMutations(['updateTechnicianItem']),
|
||||||
|
async initIndex(refresh = false) {
|
||||||
|
// #ifdef H5
|
||||||
|
if (!refresh && this.$jweixin.isWechat()) {
|
||||||
|
await this.$jweixin.initJssdk();
|
||||||
|
this.$jweixin.wxReady(() => {
|
||||||
|
this.$jweixin.hideOptionMenu()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
if (!this.configInfo.id || refresh) {
|
||||||
|
await this.getConfigInfo()
|
||||||
|
}
|
||||||
|
let {
|
||||||
|
id,
|
||||||
|
agent
|
||||||
|
} = this.options
|
||||||
|
let methodKey = agent ? 'agent' : 'admin'
|
||||||
|
let data = await this.$api[methodKey].refundOrderInfo({
|
||||||
|
id
|
||||||
|
})
|
||||||
|
this.$util.setNavigationBarColor({
|
||||||
|
bg: this.primaryColor
|
||||||
|
})
|
||||||
|
data.is_balance = data.balance * 1 > 0 ? 1 : 0
|
||||||
|
this.detail = data
|
||||||
|
},
|
||||||
|
initRefresh() {
|
||||||
|
this.initIndex(true)
|
||||||
|
},
|
||||||
|
// type: 2同意退款;3拒绝退款
|
||||||
|
async toConfirm(type) {
|
||||||
|
let {
|
||||||
|
id,
|
||||||
|
apply_price
|
||||||
|
} = this.detail
|
||||||
|
this.popupInfo = {
|
||||||
|
id,
|
||||||
|
type,
|
||||||
|
apply_price,
|
||||||
|
price: type == 2 ? apply_price : '',
|
||||||
|
text: ''
|
||||||
|
}
|
||||||
|
this.$refs.change_item.open()
|
||||||
|
},
|
||||||
|
async confirmChangeOrder() {
|
||||||
|
let {
|
||||||
|
type,
|
||||||
|
price,
|
||||||
|
apply_price
|
||||||
|
} = this.popupInfo
|
||||||
|
let param = this.$util.pick(this.popupInfo, ['id', 'price', 'text'])
|
||||||
|
let reg = /^(([0-9][0-9]*)|(([0]\.\d{1,2}|[1-9][0-9]*\.\d{1,2})))$/
|
||||||
|
if (type == 2 && (!price || !reg.test(price) || price * 1 > apply_price * 1)) {
|
||||||
|
this.$util.showToast({
|
||||||
|
title: !price ? '请输入退款金额' : !reg.test(price) ? '请输入正确的退款金额,最多保留2位小数' : '退款金额不能大于可退款金额'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (this.lockTap) return;
|
||||||
|
this.lockTap = true;
|
||||||
|
this.$util.showLoading()
|
||||||
|
let {
|
||||||
|
agent
|
||||||
|
} = this.options
|
||||||
|
let methodKey = agent ? 'agent' : 'admin'
|
||||||
|
let methodModel = type == 2 ? 'passRefund' : 'noPassRefund'
|
||||||
|
try {
|
||||||
|
await this.$api[methodKey][methodModel](param)
|
||||||
|
this.$refs.change_item.close()
|
||||||
|
this.$util.showToast({
|
||||||
|
title: '操作成功'
|
||||||
|
})
|
||||||
|
this.lockTap = false;
|
||||||
|
this.updateTechnicianItem({
|
||||||
|
key: 'haveOperItem',
|
||||||
|
val: true
|
||||||
|
})
|
||||||
|
this.initRefresh()
|
||||||
|
this.$util.back()
|
||||||
|
} catch (e) {
|
||||||
|
setTimeout(() => {
|
||||||
|
this.lockTap = false
|
||||||
|
this.$util.hideAll()
|
||||||
|
}, 2000)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 咨询
|
||||||
|
async toTel() {
|
||||||
|
let {
|
||||||
|
id: order_id,
|
||||||
|
pay_type
|
||||||
|
} = this.detail
|
||||||
|
let {
|
||||||
|
agent
|
||||||
|
} = this.options
|
||||||
|
let methodKey = agent ? 'agent' : 'admin'
|
||||||
|
if ([2, 3, 4, 5, 6].includes(pay_type)) {
|
||||||
|
let url = await this.$api[methodKey].getVirtualPhone({
|
||||||
|
order_id
|
||||||
|
})
|
||||||
|
this.$util.goUrl({
|
||||||
|
url,
|
||||||
|
openType: `call`
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
let msg = pay_type == 7 ? '服务结束' : '服务取消'
|
||||||
|
this.$util.showToast({
|
||||||
|
title: `${msg}不能联系客户哦`
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 复制定位
|
||||||
|
toCopy() {
|
||||||
|
let {
|
||||||
|
address,
|
||||||
|
address_info
|
||||||
|
} = this.detail.address_info
|
||||||
|
let url = `${address}${address_info}`
|
||||||
|
this.$util.goUrl({
|
||||||
|
url,
|
||||||
|
openType: 'copy'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 查看定位
|
||||||
|
async toMap(key) {
|
||||||
|
let {
|
||||||
|
address,
|
||||||
|
address_info = '',
|
||||||
|
lat,
|
||||||
|
lng
|
||||||
|
} = this.detail[key]
|
||||||
|
await this.$util.checkAuth({
|
||||||
|
type: 'userLocation'
|
||||||
|
})
|
||||||
|
await uni.getLocation({
|
||||||
|
type: 'gcj02',
|
||||||
|
})
|
||||||
|
await uni.openLocation({
|
||||||
|
latitude: lat * 1,
|
||||||
|
longitude: lng * 1,
|
||||||
|
name: address_info ? `${address} ${address_info}` : address,
|
||||||
|
scale: 28
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.avatar.coath {
|
||||||
|
width: 94rpx;
|
||||||
|
height: 94rpx;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,330 @@
|
||||||
|
<template>
|
||||||
|
<view class="order-pages">
|
||||||
|
<fixed>
|
||||||
|
<view class="fill-base pt-lg pl-md pr-md pb-md">
|
||||||
|
<search @input="toSearch" type="input" :padding="0" :radius="30" height="70rpx"
|
||||||
|
placeholder="请输入系统订单号查询">
|
||||||
|
</search>
|
||||||
|
</view>
|
||||||
|
<tab @change="handerTabChange" :list="tabList" :activeIndex="activeIndex*1" :activeColor="primaryColor"
|
||||||
|
width="25%" height="100rpx"></tab>
|
||||||
|
<view class="b-1px-b"></view>
|
||||||
|
</fixed>
|
||||||
|
|
||||||
|
<view @tap.stop="goDetail(index)" class="item-child mt-md ml-lg mr-lg pd-lg fill-base radius-16"
|
||||||
|
v-for="(item,index) in list.data" :key="index">
|
||||||
|
<view class="flex-between pb-lg b-1px-b">
|
||||||
|
<view class="f-paragraph c-title max-450 ellipsis">订单号:{{item.order_code}}</view>
|
||||||
|
<view class="f-caption text-bold"
|
||||||
|
:style="{color:item.status==1?subColor: item.status == 2 ? '#11C95E' : '#333'}">
|
||||||
|
{{statusType[item.status]}}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-center mb-lg" :class="[{'mt-lg':aindex==0}]" v-for="(aitem,aindex) in item.order_goods"
|
||||||
|
:key="aindex">
|
||||||
|
<!-- #ifdef H5 -->
|
||||||
|
<view class="avatar lg radius-16">
|
||||||
|
<view class="h5-image avatar lg radius-16"
|
||||||
|
:style="{ backgroundImage : `url('${aitem.goods_cover}')`}">
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<!-- #endif -->
|
||||||
|
<!-- #ifndef H5 -->
|
||||||
|
<image mode="aspectFill" class="avatar lg radius-16" :src="aitem.goods_cover"></image>
|
||||||
|
<!-- #endif -->
|
||||||
|
|
||||||
|
<view class="flex-1 ml-md">
|
||||||
|
<view class="flex-between">
|
||||||
|
<view class="f-mini-title c-title text-bold max-380 ellipsis">
|
||||||
|
{{aitem.goods_name}}
|
||||||
|
</view>
|
||||||
|
<view class="c-paragraph">x{{aitem.num}}</view>
|
||||||
|
</view>
|
||||||
|
<view class="mt-md f-caption c-caption max-450 ellipsis">
|
||||||
|
服务{{$t('action.attendantName')}}:{{item.coach_info?item.coach_info.coach_name:'-'}}</view>
|
||||||
|
<view class="f-caption c-caption" style="margin-top: 5rpx;">服务时间:{{item.start_time}}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-between pt-lg b-1px-t">
|
||||||
|
<view class="flex-y-center f-desc c-title">总计:
|
||||||
|
<view class="f-paragraph text-bold">¥{{item.apply_price}}</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-warp">
|
||||||
|
<!-- 退款申请中 -->
|
||||||
|
<block v-if="item.status == 1">
|
||||||
|
<button @tap.stop="toConfirm(index,3)" class="clear-btn order"
|
||||||
|
style="margin-left: 0;">拒绝退款</button>
|
||||||
|
<button @tap.stop="toConfirm(index,2)" class="clear-btn order"
|
||||||
|
:style="{color:'#fff',background:primaryColor,border:`1rpx solid ${primaryColor}`}">同意退款</button>
|
||||||
|
</block>
|
||||||
|
<!-- 同意/拒绝退款 -->
|
||||||
|
<view v-else>
|
||||||
|
<button class="clear-btn order"
|
||||||
|
:style="{color:'#fff',background:primaryColor,border:`1rpx solid ${primaryColor}`}">查看详情</button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<load-more :noMore="list.current_page>=list.last_page&&list.data.length>0" :loading="loading" v-if="loading">
|
||||||
|
</load-more>
|
||||||
|
<abnor v-if="!loading&&list.data.length<=0&&list.current_page==1"></abnor>
|
||||||
|
|
||||||
|
<view class="space-footer"></view>
|
||||||
|
|
||||||
|
<uni-popup ref="change_item" type="center" :custom="true">
|
||||||
|
<view class="common-popup-content fill-base pd-lg radius-34">
|
||||||
|
<view class="title">温馨提示</view>
|
||||||
|
<view class="desc">
|
||||||
|
你确认要操作{{statusType[popupInfo.type]}}吗?
|
||||||
|
</view>
|
||||||
|
<view class="mt-lg" v-if="popupInfo.type == 2">
|
||||||
|
<input v-model="popupInfo.price" type="digit"
|
||||||
|
class="input flex-y-center pl-lg pr-lg f-sm-title c-title radius-16"
|
||||||
|
placeholder-class="c-placeholder" placeholder="请输入退款金额" />
|
||||||
|
<view class="f-desc c-caption mt-md">
|
||||||
|
<view class="flex-y-center">实际可退款金额<view class="ml-sm c-warning">¥{{popupInfo.apply_price}}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view>退款金额不能大于可退款金额</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="button">
|
||||||
|
<view @tap.stop="$refs.change_item.close()" class="item-child">取消</view>
|
||||||
|
<view @tap.stop="confirmChangeOrder" class="item-child c-base"
|
||||||
|
:style="{background: primaryColor,color:'#fff'}">确定</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</uni-popup>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
mapState,
|
||||||
|
mapMutations
|
||||||
|
} from "vuex"
|
||||||
|
export default {
|
||||||
|
components: {},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
options: {},
|
||||||
|
activeIndex: 0,
|
||||||
|
tabList: [{
|
||||||
|
title: '全部',
|
||||||
|
id: 0
|
||||||
|
}, {
|
||||||
|
title: '退款申请中',
|
||||||
|
id: 1,
|
||||||
|
}, {
|
||||||
|
title: '同意退款',
|
||||||
|
id: 2
|
||||||
|
}, {
|
||||||
|
title: '拒绝退款',
|
||||||
|
id: 3
|
||||||
|
}],
|
||||||
|
statusType: {
|
||||||
|
1: '退款申请中',
|
||||||
|
2: '同意退款',
|
||||||
|
3: '拒绝退款',
|
||||||
|
},
|
||||||
|
param: {
|
||||||
|
page: 1,
|
||||||
|
},
|
||||||
|
list: {
|
||||||
|
data: []
|
||||||
|
},
|
||||||
|
loading: true,
|
||||||
|
popupInfo: {},
|
||||||
|
lockTap: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: mapState({
|
||||||
|
primaryColor: state => state.config.configInfo.primaryColor,
|
||||||
|
subColor: state => state.config.configInfo.subColor,
|
||||||
|
configInfo: state => state.config.configInfo,
|
||||||
|
userInfo: state => state.user.userInfo,
|
||||||
|
}),
|
||||||
|
onLoad(options) {
|
||||||
|
let {
|
||||||
|
agent = 0,
|
||||||
|
bell = 0,
|
||||||
|
tab = 0
|
||||||
|
} = options
|
||||||
|
options.agent = agent * 1
|
||||||
|
this.options = options
|
||||||
|
this.activeIndex = tab
|
||||||
|
uni.setNavigationBarTitle({
|
||||||
|
title: bell == 1 ? '加钟退款' : '服务退款'
|
||||||
|
})
|
||||||
|
this.initIndex()
|
||||||
|
},
|
||||||
|
onPullDownRefresh() {
|
||||||
|
// #ifndef APP-PLUS
|
||||||
|
uni.showNavigationBarLoading()
|
||||||
|
// #endif
|
||||||
|
this.initRefresh();
|
||||||
|
uni.stopPullDownRefresh()
|
||||||
|
},
|
||||||
|
onReachBottom() {
|
||||||
|
if (this.list.current_page >= this.list.last_page || this.loading) return;
|
||||||
|
this.param.page = this.param.page + 1;
|
||||||
|
this.loading = true;
|
||||||
|
this.getList();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
...mapMutations(['updateTechnicianItem']),
|
||||||
|
async initIndex(refresh = false) {
|
||||||
|
// #ifdef H5
|
||||||
|
if (!refresh && this.$jweixin.isWechat()) {
|
||||||
|
await this.$jweixin.initJssdk();
|
||||||
|
this.$jweixin.wxReady(() => {
|
||||||
|
this.$jweixin.hideOptionMenu()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
await this.getList()
|
||||||
|
this.$util.setNavigationBarColor({
|
||||||
|
bg: this.primaryColor
|
||||||
|
})
|
||||||
|
},
|
||||||
|
initRefresh() {
|
||||||
|
this.param.page = 1
|
||||||
|
this.initIndex(true)
|
||||||
|
},
|
||||||
|
toSearch(val) {
|
||||||
|
this.param.page = 1
|
||||||
|
this.param.order_code = val
|
||||||
|
this.getList()
|
||||||
|
},
|
||||||
|
async getList() {
|
||||||
|
let {
|
||||||
|
list: oldList,
|
||||||
|
param,
|
||||||
|
tabList,
|
||||||
|
activeIndex
|
||||||
|
} = this
|
||||||
|
param.status = tabList[activeIndex].id
|
||||||
|
let {
|
||||||
|
bell = 0,
|
||||||
|
agent
|
||||||
|
} = this.options
|
||||||
|
param.is_add = bell
|
||||||
|
let methodKey = agent ? 'agent' : 'admin'
|
||||||
|
let newList = await this.$api[methodKey].refundOrderList(param);
|
||||||
|
|
||||||
|
if (this.param.page == 1) {
|
||||||
|
this.list = newList
|
||||||
|
} else {
|
||||||
|
newList.data = oldList.data.concat(newList.data)
|
||||||
|
this.list = newList
|
||||||
|
}
|
||||||
|
this.loading = false
|
||||||
|
this.$util.hideAll()
|
||||||
|
},
|
||||||
|
handerTabChange(index) {
|
||||||
|
this.activeIndex = index;
|
||||||
|
this.$util.showLoading()
|
||||||
|
this.param.page = 1;
|
||||||
|
this.getList()
|
||||||
|
},
|
||||||
|
// type: 2同意退款;3拒绝退款
|
||||||
|
async toConfirm(index, type) {
|
||||||
|
let {
|
||||||
|
id,
|
||||||
|
apply_price
|
||||||
|
} = this.list.data[index]
|
||||||
|
this.popupInfo = {
|
||||||
|
index,
|
||||||
|
id,
|
||||||
|
type,
|
||||||
|
apply_price,
|
||||||
|
price: type == 2 ? apply_price : '',
|
||||||
|
text: ''
|
||||||
|
}
|
||||||
|
this.$refs.change_item.open()
|
||||||
|
},
|
||||||
|
async confirmChangeOrder() {
|
||||||
|
let {
|
||||||
|
type,
|
||||||
|
index,
|
||||||
|
price,
|
||||||
|
apply_price
|
||||||
|
} = this.popupInfo
|
||||||
|
let param = this.$util.pick(this.popupInfo, ['id', 'price', 'text'])
|
||||||
|
let reg = /^(([0-9][0-9]*)|(([0]\.\d{1,2}|[1-9][0-9]*\.\d{1,2})))$/
|
||||||
|
if (type == 2 && (!price || !reg.test(price) || price * 1 > apply_price * 1)) {
|
||||||
|
this.$util.showToast({
|
||||||
|
title: !price ? '请输入退款金额' : !reg.test(price) ? '请输入正确的退款金额,最多保留2位小数' : '退款金额不能大于可退款金额'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let {
|
||||||
|
activeIndex
|
||||||
|
} = this
|
||||||
|
if (this.lockTap) return;
|
||||||
|
this.lockTap = true;
|
||||||
|
this.$util.showLoading()
|
||||||
|
let {
|
||||||
|
agent
|
||||||
|
} = this.options
|
||||||
|
let methodKey = agent ? 'agent' : 'admin'
|
||||||
|
let methodModel = type == 2 ? 'passRefund' : 'noPassRefund'
|
||||||
|
try {
|
||||||
|
await this.$api[methodKey][methodModel](param)
|
||||||
|
this.$refs.change_item.close()
|
||||||
|
this.$util.showToast({
|
||||||
|
title: '操作成功'
|
||||||
|
})
|
||||||
|
if (activeIndex == 0) {
|
||||||
|
this.list.data[index].status = type
|
||||||
|
} else {
|
||||||
|
this.list.data.splice(index, 1)
|
||||||
|
}
|
||||||
|
this.lockTap = false;
|
||||||
|
this.$util.hideAll()
|
||||||
|
this.updateTechnicianItem({
|
||||||
|
key: 'haveOperItem',
|
||||||
|
val: true
|
||||||
|
})
|
||||||
|
if (activeIndex == 0) return
|
||||||
|
await this.getList(true)
|
||||||
|
} catch (e) {
|
||||||
|
setTimeout(() => {
|
||||||
|
this.lockTap = false
|
||||||
|
this.$util.hideAll()
|
||||||
|
}, 2000)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 订单详情
|
||||||
|
goDetail(index) {
|
||||||
|
let {
|
||||||
|
id
|
||||||
|
} = this.list.data[index]
|
||||||
|
let {
|
||||||
|
agent
|
||||||
|
} = this.options
|
||||||
|
let url = `/agent/pages/refund/detail?id=${id}&agent=${agent}`
|
||||||
|
this.$util.goUrl({
|
||||||
|
url
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 平台
|
||||||
|
toTel() {
|
||||||
|
let {
|
||||||
|
mobile: url
|
||||||
|
} = this.configInfo
|
||||||
|
this.$util.goUrl({
|
||||||
|
url,
|
||||||
|
openType: `call`
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
</style>
|
|
@ -0,0 +1,775 @@
|
||||||
|
<template>
|
||||||
|
<view class="apply-pages" v-if="isLoad">
|
||||||
|
<view class="apply-form">
|
||||||
|
<view class="fill-base radius-16">
|
||||||
|
<view @tap.stop="toChooseUser" class="flex-between pl-lg pr-lg b-1px-b">
|
||||||
|
<view class="item-text">关联用户</view>
|
||||||
|
<view class="item-input text">
|
||||||
|
<view class="flex-between">
|
||||||
|
{{form.user_id ? form.nickName :'请选择'}}
|
||||||
|
<i class="iconfont icon-right ml-sm" style="font-size: 28rpx;"></i>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-between pl-lg pr-lg b-1px-b">
|
||||||
|
<view class="item-text flex-y-center"><i class="iconfont icon-required c-warning"></i>姓名</view>
|
||||||
|
<input v-model="form.coach_name" type="text" class="item-input flex-1" maxlength="20"
|
||||||
|
:placeholder="rule[0].errorMsg" />
|
||||||
|
</view>
|
||||||
|
<view class="flex-between pl-lg pr-lg b-1px-b">
|
||||||
|
<view class="item-text flex-y-center"><i class="iconfont icon-required c-warning"></i>性别</view>
|
||||||
|
<view class="item-input flex-1 flex-y-center">
|
||||||
|
<view @tap.stop="form.sex = index" class="flex-y-center" :class="[{'mr-lg':index==0}]"
|
||||||
|
:style="{color:form.sex == index ? primaryColor:''}" v-for="(item,index) in ['男','女']"
|
||||||
|
:key="index"><i class="iconfont icon-xuanze mr-sm"
|
||||||
|
:class="[{'icon-xuanze-fill':form.sex == index}]"></i>{{item}}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-between ml-lg mr-lg b-1px-b">
|
||||||
|
<view class="item-text flex-y-center"><i class="iconfont icon-required c-warning"></i>生日</view>
|
||||||
|
<view class="item-input text flex-1">
|
||||||
|
<picker @change="pickerChange($event,'birthday')" mode="date" :end="endYear"
|
||||||
|
:value="form.birthday">
|
||||||
|
<view class="flex-between">
|
||||||
|
{{form.birthday||'请选择'}}
|
||||||
|
<i class="iconfont icon-right ml-sm" style="font-size: 28rpx;"></i>
|
||||||
|
</view>
|
||||||
|
</picker>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-between pl-lg pr-lg b-1px-b">
|
||||||
|
<view class="item-text flex-y-center"><i class="iconfont icon-required c-warning"></i>手机号</view>
|
||||||
|
<input v-model="form.mobile" type="text" class="item-input flex-1"
|
||||||
|
:placeholder="rule[2].errorMsg" />
|
||||||
|
</view>
|
||||||
|
<view class="flex-between pl-lg pr-lg b-1px-b">
|
||||||
|
<view class="item-text flex-y-center"><i class="iconfont icon-required c-warning"></i>从业年份</view>
|
||||||
|
<input v-model="form.work_time" type="number" class="item-input flex-1"
|
||||||
|
:placeholder="rule[3].errorMsg" />
|
||||||
|
</view>
|
||||||
|
<view class="flex-between pl-lg pr-lg b-1px-b">
|
||||||
|
<view class="item-text flex-y-center" style="width:230rpx"><i
|
||||||
|
class="iconfont icon-required c-warning"></i>意向工作城市</view>
|
||||||
|
<view class="item-input text">
|
||||||
|
<picker @change="pickerChange($event,'city')" :value="cityIndex" :range="cityList"
|
||||||
|
range-key="title">
|
||||||
|
<view class="flex-between">
|
||||||
|
{{cityIndex!=-1?cityList[cityIndex].title:'请选择'}}
|
||||||
|
<i class="iconfont icon-right ml-sm" style="font-size: 28rpx;"></i>
|
||||||
|
</view>
|
||||||
|
</picker>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-between pl-lg pr-lg b-1px-b" v-if="configInfo.plugAuth.store && storeList.length>0">
|
||||||
|
<view class="item-text">挂靠门店</view>
|
||||||
|
<view class="item-input text">
|
||||||
|
<picker @change="pickerChange($event,'store')" :value="storeIndex" :range="storeList"
|
||||||
|
range-key="title">
|
||||||
|
<view class="flex-between">
|
||||||
|
<view class="max-400 ellipsis">{{storeIndex!=-1?storeList[storeIndex].title:'请选择'}}
|
||||||
|
</view>
|
||||||
|
<i class="iconfont icon-right ml-sm" style="font-size: 28rpx;"></i>
|
||||||
|
</view>
|
||||||
|
</picker>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-between pl-lg pr-lg">
|
||||||
|
<view class="item-text flex-y-center"><i class="iconfont icon-required c-warning"></i>所在地址</view>
|
||||||
|
<view class="item-input text flex-1">
|
||||||
|
<view @tap.stop="toChooseLocation" class="flex-between">
|
||||||
|
<view>{{form.address || `点击右边图标设置`}}</view>
|
||||||
|
<i class="iconfont iconjuli ml-sm" :style="{color: primaryColor}"></i>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="fill-base mt-md radius-16">
|
||||||
|
<view class="flex-between pl-lg pr-lg">
|
||||||
|
<view class="item-text flex-y-center" style="width:auto"><i
|
||||||
|
class="iconfont icon-required c-warning"></i>{{$t('action.attendantName')}}简介</view>
|
||||||
|
<input :disabled="true" type="text" class="item-input flex-1" />
|
||||||
|
</view>
|
||||||
|
<textarea v-model="form.text" class="item-textarea pd-lg" maxlength="300"
|
||||||
|
:placeholder="'输入'+$t('action.attendantName')+'简介'" />
|
||||||
|
<view class="text-right pb-lg pr-lg">
|
||||||
|
{{form.text.length>300?300:form.text.length}}/300
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="fill-base mt-md radius-16">
|
||||||
|
<view class="flex-between pl-lg pr-lg">
|
||||||
|
<view class="item-text flex-y-center"><i class="iconfont icon-required c-warning"></i>身份证号</view>
|
||||||
|
<input v-model="form.id_code" type="text" class="item-input flex-1"
|
||||||
|
:placeholder="rule[7].errorMsg" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="fill-base mt-md radius-16">
|
||||||
|
<view class="flex-between pl-lg pr-lg">
|
||||||
|
<view class="item-text flex-y-center"><i class="iconfont icon-required c-warning"></i>身份证照片</view>
|
||||||
|
<view class="item-input flex-1">图片大小不超过10M</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-between pl-lg pr-lg pb-md">
|
||||||
|
<upload @upload="imgUpload" :imagelist="form.id_card" imgtype="id_card" imgclass="md" text="身份证人像面"
|
||||||
|
:imgsize="1"></upload>
|
||||||
|
<upload @upload="imgUpload" :imagelist="form.id_card_fan" imgtype="id_card_fan" imgclass="md"
|
||||||
|
text="身份证国徽面" :imgsize="1"></upload>
|
||||||
|
</view>
|
||||||
|
<view class="flex-between pl-lg pr-lg pb-md">
|
||||||
|
<upload @upload="imgUpload" :imagelist="form.id_card_people" imgtype="id_card_people" imgclass="md"
|
||||||
|
text="手持身份证照片" :imgsize="1"></upload>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="fill-base mt-md radius-16">
|
||||||
|
<view class="flex-between pl-lg pr-lg">
|
||||||
|
<view class="item-text flex-y-center"><i class="iconfont icon-required c-warning"></i>资格证书</view>
|
||||||
|
<view class="item-input flex-1">图片大小不超过10M</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-between pl-lg pr-lg pb-md">
|
||||||
|
<upload @upload="imgUpload" @del="imgUpload" :imagelist="form.license" imgtype="license" text="上传图片"
|
||||||
|
:imgsize="15">
|
||||||
|
</upload>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="fill-base mt-md radius-16">
|
||||||
|
<view class="flex-between pl-lg pr-lg">
|
||||||
|
<view class="item-text flex-y-center"><i class="iconfont icon-required c-warning"></i>工作形象照</view>
|
||||||
|
<view class="item-input flex-1">图片建议尺寸: 750 * 750,大小不超过10M</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-between pl-lg pr-lg pb-md">
|
||||||
|
<upload @upload="imgUpload" :imagelist="form.work_img" imgtype="work_img" text="上传图片" :imgsize="1">
|
||||||
|
</upload>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="fill-base mt-md radius-16">
|
||||||
|
<view class="flex-between pl-lg pr-lg">
|
||||||
|
<view class="item-text flex-y-center"><i class="iconfont icon-required c-warning"></i>个人生活照</view>
|
||||||
|
<view class="item-input flex-1">图片建议尺寸: 750 * n,大小不超过10M</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-between pl-lg pr-lg pb-md">
|
||||||
|
<upload @upload="imgUpload" @del="imgUpload" :imagelist="form.self_img" filetype="picture"
|
||||||
|
imgtype="self_img" text="上传图片" :imgsize="9">
|
||||||
|
</upload>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="fill-base mt-md radius-16">
|
||||||
|
<view class="flex-between pl-lg pr-lg">
|
||||||
|
<view class="item-text">个人视频介绍</view>
|
||||||
|
<view class="item-input flex-1">视频大小不超过50M</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-between pl-lg pr-lg pb-md">
|
||||||
|
<upload @upload="imgUpload" @del="imgUpload" :imagelist="form.video" filetype="video"
|
||||||
|
imgtype="video" text="上传视频" :imgsize="1">
|
||||||
|
</upload>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="fill-base mt-md radius-16">
|
||||||
|
<view class="flex-between pl-lg pr-lg b-1px-b">
|
||||||
|
<view class="item-text flex-y-center"><i class="iconfont icon-required c-warning"></i>虚拟订单</view>
|
||||||
|
<input v-model="form.order_num" type="number" class="item-input flex-1"
|
||||||
|
:placeholder="rule[14].errorMsg" />
|
||||||
|
</view>
|
||||||
|
<view class="flex-between pl-lg pr-lg b-1px-b">
|
||||||
|
<view class="item-text flex-y-center"><i class="iconfont icon-required c-warning"></i>是否接单</view>
|
||||||
|
<view class="item-input flex-1 flex-y-center">
|
||||||
|
<view @tap.stop="toSetItem(index)" class="flex-y-center" :class="[{'mr-lg':item.id==1}]"
|
||||||
|
:style="{color:form.is_work == item.id ? primaryColor:''}" v-for="(item,index) in workList"
|
||||||
|
:key="index"><i class="iconfont mr-sm"
|
||||||
|
:class="[{'icon-xuanze':form.is_work != item.id},{'icon-radio-fill':form.is_work == item.id}]"></i>{{item.title}}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-between pd-lg" v-if="form.is_work===1">
|
||||||
|
<view @tap.stop="toShowTime('start_time')" class="item-time flex-center flex-column">
|
||||||
|
<view>开始时间</view>
|
||||||
|
<view class="mt-sm" :style="{color:form.start_time ? primaryColor : '#999'}">
|
||||||
|
{{form.start_time || '选择时间'}}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view @tap.stop="toShowTime('end_time')" class="item-time flex-center flex-column b-1px-l">
|
||||||
|
<view>结束时间</view>
|
||||||
|
<view class="mt-sm" :style="{color:form.end_time ? primaryColor : '#999'}">
|
||||||
|
{{form | handleStartEndTime(toDay)}}{{form.end_time || '选择时间'}}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- TODO 合同 -->
|
||||||
|
<view @tap.stop="toFddSign" class="fill-base mt-md radius-16"
|
||||||
|
v-if="fdd_agreement && fdd_agreement.hasOwnProperty('viewpdf_url')">
|
||||||
|
<view class="flex-between pl-lg pr-lg b-1px-b">
|
||||||
|
<view class="item-text">电子签约</view>
|
||||||
|
<view class="item-input flex-1" :style="{color:primaryColor}">
|
||||||
|
查看签约合同
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="space-max-footer"></view>
|
||||||
|
|
||||||
|
<fix-bottom-button @confirm="submit" :text="[{text:'确定提交',type:'confirm',isAuth:true}]" bgColor="#fff">
|
||||||
|
</fix-bottom-button>
|
||||||
|
|
||||||
|
|
||||||
|
<w-picker :visible.sync="showTime" mode="time" :value="toDayTime" :current="false" :second="false"
|
||||||
|
:themeColor="primaryColor" @confirm="onConfirm" ref="time"></w-picker>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import $util from "@/utils/index.js"
|
||||||
|
import wPicker from "@/components/w-picker/w-picker.vue";
|
||||||
|
import {
|
||||||
|
mapState,
|
||||||
|
mapActions,
|
||||||
|
mapMutations
|
||||||
|
} from "vuex"
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
wPicker
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
isLoad: false,
|
||||||
|
options: {},
|
||||||
|
cityList: [],
|
||||||
|
cityIndex: -1,
|
||||||
|
storeList: [],
|
||||||
|
storeIndex: -1,
|
||||||
|
toDay: '',
|
||||||
|
toDayTime: '',
|
||||||
|
showKey: '',
|
||||||
|
showTime: false,
|
||||||
|
workList: [{
|
||||||
|
id: 1,
|
||||||
|
title: '接单'
|
||||||
|
}, {
|
||||||
|
id: 0,
|
||||||
|
title: '休息'
|
||||||
|
}],
|
||||||
|
fdd_agreement: {},
|
||||||
|
form: {
|
||||||
|
id: 0,
|
||||||
|
user_id: '',
|
||||||
|
nickName: '',
|
||||||
|
coach_name: '', //姓名
|
||||||
|
mobile: '', //手机号
|
||||||
|
sex: 0, //性别
|
||||||
|
birthday: '',
|
||||||
|
work_time: '', //从业年份
|
||||||
|
city_id: '', // 城市id
|
||||||
|
store_id: '', // 门店id
|
||||||
|
lng: '',
|
||||||
|
lat: '',
|
||||||
|
address: '', //详细地址
|
||||||
|
text: '', //备注
|
||||||
|
id_code: '', //身份证号
|
||||||
|
id_card: [], //身份证
|
||||||
|
id_card_fan: [], // 身份证反面
|
||||||
|
id_card_people: [], //手持身份证
|
||||||
|
license: [], //资格证书
|
||||||
|
work_img: [], // 工作照
|
||||||
|
self_img: [], // 生活照
|
||||||
|
city_id: '', // 城市 id
|
||||||
|
video: [],
|
||||||
|
order_num: 0,
|
||||||
|
is_work: 1,
|
||||||
|
start_time: '00:00',
|
||||||
|
end_time: '23:59'
|
||||||
|
},
|
||||||
|
rule: [{
|
||||||
|
name: "coach_name",
|
||||||
|
checkType: "isNotNull",
|
||||||
|
errorMsg: "输入您的姓名",
|
||||||
|
regType: 2
|
||||||
|
}, {
|
||||||
|
name: "birthday",
|
||||||
|
checkType: "isNotNull",
|
||||||
|
errorMsg: "请选择您的生日",
|
||||||
|
regType: 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "mobile",
|
||||||
|
checkType: "isMobile",
|
||||||
|
errorMsg: "输入手机号"
|
||||||
|
}, {
|
||||||
|
name: "work_time",
|
||||||
|
checkType: "isNotNull",
|
||||||
|
errorMsg: "请输入从业年份,例如:5"
|
||||||
|
}, {
|
||||||
|
name: "city_id",
|
||||||
|
checkType: "isNotNull",
|
||||||
|
errorMsg: "请选择意向工作城市"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "address",
|
||||||
|
checkType: "isNotNull",
|
||||||
|
errorMsg: "请选择所在地址"
|
||||||
|
}, {
|
||||||
|
name: "text",
|
||||||
|
checkType: "isNotNull",
|
||||||
|
errorMsg: "请输入" + this.$t('action.attendantName') + "简介",
|
||||||
|
regType: 2
|
||||||
|
}, {
|
||||||
|
name: "id_code",
|
||||||
|
checkType: "isIdCard",
|
||||||
|
errorMsg: "输入您的身份证号码"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "id_card",
|
||||||
|
checkType: "isNotNull",
|
||||||
|
errorMsg: "请上传身份证人像面"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "id_card_fan",
|
||||||
|
checkType: "isNotNull",
|
||||||
|
errorMsg: "请上传身份证国徽面"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "id_card_people",
|
||||||
|
checkType: "isNotNull",
|
||||||
|
errorMsg: "请上传手持身份证照片"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "license",
|
||||||
|
checkType: "isNotNull",
|
||||||
|
errorMsg: "请上传资格证书"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "work_img",
|
||||||
|
checkType: "isNotNull",
|
||||||
|
errorMsg: "请上传工作形象照"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "self_img",
|
||||||
|
checkType: "isNotNull",
|
||||||
|
errorMsg: "请上传个人生活照"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "order_num",
|
||||||
|
checkType: "isNumber",
|
||||||
|
errorMsg: "请输入虚拟订单量",
|
||||||
|
regType: 2
|
||||||
|
},
|
||||||
|
],
|
||||||
|
have_user_id: false,
|
||||||
|
lockTap: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: mapState({
|
||||||
|
primaryColor: state => state.config.configInfo.primaryColor,
|
||||||
|
subColor: state => state.config.configInfo.subColor,
|
||||||
|
configInfo: state => state.config.configInfo,
|
||||||
|
userInfo: state => state.user.userInfo,
|
||||||
|
location: state => state.user.location,
|
||||||
|
}),
|
||||||
|
async onLoad(options) {
|
||||||
|
let {
|
||||||
|
id = 0
|
||||||
|
} = options
|
||||||
|
this.options = options
|
||||||
|
this.$util.showLoading()
|
||||||
|
await this.initIndex()
|
||||||
|
let {
|
||||||
|
coach_status
|
||||||
|
} = this
|
||||||
|
|
||||||
|
uni.setNavigationBarTitle({
|
||||||
|
title: id ? '编辑' : '新增' + this.$t(
|
||||||
|
'action.attendantName')
|
||||||
|
})
|
||||||
|
this.isLoad = true
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
...mapActions(['getConfigInfo', 'getUserInfo']),
|
||||||
|
...mapMutations(['updateUserItem']),
|
||||||
|
async initIndex(refresh = false) {
|
||||||
|
// #ifdef H5
|
||||||
|
if (!refresh && this.$jweixin.isWechat()) {
|
||||||
|
await this.$jweixin.initJssdk();
|
||||||
|
this.$jweixin.wxReady(() => {
|
||||||
|
this.$jweixin.hideOptionMenu()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
if (!this.configInfo.id || !this.configInfo.hasOwnProperty(
|
||||||
|
'plugAuth') || (this.configInfo.hasOwnProperty(
|
||||||
|
'plugAuth') && !this.configInfo.plugAuth.hasOwnProperty(
|
||||||
|
'store')) || refresh) {
|
||||||
|
await this.getConfigInfo()
|
||||||
|
}
|
||||||
|
this.$util.setNavigationBarColor({
|
||||||
|
bg: this.primaryColor
|
||||||
|
})
|
||||||
|
let cur_time = new Date(Math.ceil(new Date().getTime()))
|
||||||
|
this.toDay = this.$util.formatTime(cur_time, 'YY-M-D')
|
||||||
|
this.toDayTime = this.$util.formatTime(cur_time, 'h:m')
|
||||||
|
await Promise.all([this.getCityList(), this.getStoreList()])
|
||||||
|
let {
|
||||||
|
id = 0
|
||||||
|
} = this.options
|
||||||
|
if (!id) {
|
||||||
|
this.$util.hideAll()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let data = await this.$api.agent.coachInfo({
|
||||||
|
id
|
||||||
|
})
|
||||||
|
data.id_card = data.id_card.map(item => {
|
||||||
|
return {
|
||||||
|
path: item
|
||||||
|
}
|
||||||
|
})
|
||||||
|
data.id_card_fan = [data.id_card[1]]
|
||||||
|
data.id_card_people = [data.id_card[2]]
|
||||||
|
data.id_card.splice(1, 3)
|
||||||
|
data.license = data.license.map(item => {
|
||||||
|
return {
|
||||||
|
path: item
|
||||||
|
}
|
||||||
|
})
|
||||||
|
data.work_img = [{
|
||||||
|
path: data.work_img
|
||||||
|
}]
|
||||||
|
data.self_img = data.self_img.map(item => {
|
||||||
|
return {
|
||||||
|
path: item
|
||||||
|
}
|
||||||
|
})
|
||||||
|
data.video = data.video && data.video.length > 0 ? [{
|
||||||
|
path: data.video
|
||||||
|
}] : []
|
||||||
|
this.cityIndex = this.cityList.findIndex(item => {
|
||||||
|
return item.id == data.city_id
|
||||||
|
})
|
||||||
|
this.storeIndex = this.storeList.findIndex(item => {
|
||||||
|
return item.id == data.store_id
|
||||||
|
})
|
||||||
|
data.birthday = data.birthday ? this.$util.formatTime(data.birthday * 1000, 'YY-M-D') : ''
|
||||||
|
for (let key in this.form) {
|
||||||
|
this.form[key] = data[key]
|
||||||
|
}
|
||||||
|
this.have_user_id = data.id && data.user_id
|
||||||
|
this.fdd_agreement = data.fdd_agreement
|
||||||
|
this.$util.hideAll()
|
||||||
|
},
|
||||||
|
initRefresh() {
|
||||||
|
this.initIndex(true)
|
||||||
|
},
|
||||||
|
async getStoreList() {
|
||||||
|
let {
|
||||||
|
store = false
|
||||||
|
} = this.configInfo.plugAuth
|
||||||
|
if (store) {
|
||||||
|
let data = await this.$api.agent.storeSelect()
|
||||||
|
data.unshift({
|
||||||
|
id: 0,
|
||||||
|
title: '不挂靠门店'
|
||||||
|
})
|
||||||
|
this.storeList = data
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async getCityList() {
|
||||||
|
let {
|
||||||
|
location
|
||||||
|
} = this
|
||||||
|
if (!location.lat) {
|
||||||
|
// #ifdef H5
|
||||||
|
if (this.$jweixin.isWechat()) {
|
||||||
|
this.$util.showLoading()
|
||||||
|
// await this.$jweixin.initJssdk();
|
||||||
|
await this.$jweixin.wxReady2();
|
||||||
|
let {
|
||||||
|
latitude: lat = 0,
|
||||||
|
longitude: lng = 0
|
||||||
|
} = await this.$jweixin.getWxLocation()
|
||||||
|
location = {
|
||||||
|
lng,
|
||||||
|
lat,
|
||||||
|
address: '定位失败',
|
||||||
|
province: '',
|
||||||
|
city: '',
|
||||||
|
district: ''
|
||||||
|
}
|
||||||
|
if (lat && lng) {
|
||||||
|
let key = `${lat},${lng}`
|
||||||
|
let data = await this.$api.base.getMapInfo({
|
||||||
|
location: key
|
||||||
|
})
|
||||||
|
let {
|
||||||
|
status,
|
||||||
|
result
|
||||||
|
} = JSON.parse(data)
|
||||||
|
if (status == 0) {
|
||||||
|
let {
|
||||||
|
address,
|
||||||
|
address_component
|
||||||
|
} = result
|
||||||
|
let {
|
||||||
|
province,
|
||||||
|
city,
|
||||||
|
district
|
||||||
|
} = address_component
|
||||||
|
location = {
|
||||||
|
lng,
|
||||||
|
lat,
|
||||||
|
address,
|
||||||
|
province,
|
||||||
|
city,
|
||||||
|
district
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
// #ifndef H5
|
||||||
|
location = await this.$util.getBmapLocation()
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
this.updateUserItem({
|
||||||
|
key: 'location',
|
||||||
|
val: location
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
let {
|
||||||
|
lng = 0,
|
||||||
|
lat = 0
|
||||||
|
} = location
|
||||||
|
if (lat && lng) {
|
||||||
|
let city = await this.$api.base.getCity({
|
||||||
|
lng,
|
||||||
|
lat
|
||||||
|
})
|
||||||
|
this.$util.hideAll()
|
||||||
|
this.cityList = city
|
||||||
|
this.cityIndex = city.length > 0 ? 0 : -1
|
||||||
|
this.form.city_id = city.length > 0 ? city[0].id : ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async toFddSign() {
|
||||||
|
this.updateUserItem({
|
||||||
|
key: 'fddExtsign',
|
||||||
|
val: ''
|
||||||
|
})
|
||||||
|
let {
|
||||||
|
viewpdf_url = ''
|
||||||
|
} = this.fdd_agreement
|
||||||
|
this.updateUserItem({
|
||||||
|
key: 'fddExtsign',
|
||||||
|
val: viewpdf_url
|
||||||
|
})
|
||||||
|
this.$util.goUrl({
|
||||||
|
url: `/user/pages/common/web?url=fddExtsign`
|
||||||
|
})
|
||||||
|
},
|
||||||
|
pickerChange(e, key) {
|
||||||
|
let ind = e.target.value
|
||||||
|
if (key === 'birthday') {
|
||||||
|
let unix = this.$util.DateToUnix(ind)
|
||||||
|
if (unix > new Date(Math.ceil(new Date().getTime())) / 1000) {
|
||||||
|
this.$util.showToast({
|
||||||
|
title: `不能选择未来时间哦`
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.form[key] = ind
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this[`${key}Index`] = ind
|
||||||
|
this.form[`${key}_id`] = this[`${key}List`][ind].id
|
||||||
|
},
|
||||||
|
imgUpload(e) {
|
||||||
|
let {
|
||||||
|
imagelist,
|
||||||
|
imgtype
|
||||||
|
} = e;
|
||||||
|
this.form[imgtype] = imagelist;
|
||||||
|
},
|
||||||
|
toSetItem(index) {
|
||||||
|
let {
|
||||||
|
id
|
||||||
|
} = this.workList[index]
|
||||||
|
this.form.is_work = id
|
||||||
|
},
|
||||||
|
toShowTime(key) {
|
||||||
|
this.showKey = key
|
||||||
|
this.showTime = true
|
||||||
|
},
|
||||||
|
onConfirm(val) {
|
||||||
|
this.form[this.showKey] = val.result;
|
||||||
|
},
|
||||||
|
// 选择地区
|
||||||
|
async toChooseLocation(e) {
|
||||||
|
await this.$util.checkAuth({
|
||||||
|
type: 'userLocation'
|
||||||
|
})
|
||||||
|
let {
|
||||||
|
lat: locaLat = '',
|
||||||
|
lng: locaLng = ''
|
||||||
|
} = this.location
|
||||||
|
let {
|
||||||
|
id = 0,
|
||||||
|
lat: addrLat,
|
||||||
|
lng: addrLng
|
||||||
|
} = this.form
|
||||||
|
|
||||||
|
if (id) {
|
||||||
|
locaLat = addrLat
|
||||||
|
locaLng = addrLng
|
||||||
|
}
|
||||||
|
|
||||||
|
let param = {}
|
||||||
|
if (!locaLat && !locaLng) {
|
||||||
|
// #ifdef H5
|
||||||
|
if (this.$jweixin.isWechat()) {
|
||||||
|
this.$util.showLoading()
|
||||||
|
await this.$jweixin.wxReady2();
|
||||||
|
let {
|
||||||
|
latitude,
|
||||||
|
longitude
|
||||||
|
} = await this.$jweixin.getWxLocation()
|
||||||
|
locaLat = latitude
|
||||||
|
locaLng = longitude
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
// #ifdef APP-PLUS
|
||||||
|
let location = await this.$util.getBmapLocation()
|
||||||
|
locaLat = location.lat
|
||||||
|
locaLng = location.lng
|
||||||
|
// #endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// #ifndef MP-WEIXIN
|
||||||
|
param = {
|
||||||
|
latitude: locaLat,
|
||||||
|
longitude: locaLng
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
let [, {
|
||||||
|
address = '',
|
||||||
|
longitude,
|
||||||
|
latitude
|
||||||
|
}] = await uni.chooseLocation(param);
|
||||||
|
if (!address) return
|
||||||
|
this.form.address = address
|
||||||
|
this.form.lng = longitude
|
||||||
|
this.form.lat = latitude
|
||||||
|
},
|
||||||
|
toChooseUser() {
|
||||||
|
let {
|
||||||
|
have_user_id
|
||||||
|
} = this
|
||||||
|
if (have_user_id) return
|
||||||
|
this.$util.goUrl({
|
||||||
|
url: `/agent/pages/technician/user`
|
||||||
|
})
|
||||||
|
},
|
||||||
|
//表单验证
|
||||||
|
validate(param) {
|
||||||
|
let validate = new this.$util.Validate();
|
||||||
|
this.rule.map(item => {
|
||||||
|
let {
|
||||||
|
name,
|
||||||
|
} = item
|
||||||
|
validate.add(param[name], item);
|
||||||
|
})
|
||||||
|
let message = validate.start();
|
||||||
|
return message;
|
||||||
|
},
|
||||||
|
async submit() {
|
||||||
|
let param = this.$util.deepCopy(this.form)
|
||||||
|
let arr = ['id_card', 'id_card_fan', 'id_card_people', 'work_img', 'video']
|
||||||
|
arr.map(item => {
|
||||||
|
param[item] = param[item].length > 0 ? param[item][0].path : ''
|
||||||
|
})
|
||||||
|
param.license = param.license.map(item => {
|
||||||
|
return item.path
|
||||||
|
})
|
||||||
|
param.self_img = param.self_img.map(item => {
|
||||||
|
return item.path
|
||||||
|
})
|
||||||
|
let msg = this.validate(param);
|
||||||
|
if (msg) {
|
||||||
|
this.$util.showToast({
|
||||||
|
title: msg
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let {
|
||||||
|
is_work: work = 0,
|
||||||
|
start_time: start,
|
||||||
|
end_time: end
|
||||||
|
} = param
|
||||||
|
if (work && (!start || !end)) {
|
||||||
|
this.$util.showToast({
|
||||||
|
title: !start ? '请选择开始时间' : '请选择结束时间'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
param.birthday = this.$util.DateToUnix(param.birthday)
|
||||||
|
param.id_card = [param.id_card, param.id_card_fan, param.id_card_people]
|
||||||
|
delete param.id_card_fan
|
||||||
|
delete param.id_card_people
|
||||||
|
delete param.nickName
|
||||||
|
if (param.id) {
|
||||||
|
delete param.admin_id
|
||||||
|
}
|
||||||
|
if (this.lockTap) return
|
||||||
|
this.lockTap = true
|
||||||
|
this.$util.showLoading()
|
||||||
|
try {
|
||||||
|
let {
|
||||||
|
is_edit = 0
|
||||||
|
} = this.options
|
||||||
|
let methodModel = param.id ? 'coachDataUpdate' : 'coachApply'
|
||||||
|
await this.$api.agent[methodModel](param)
|
||||||
|
this.$util.hideAll()
|
||||||
|
this.$util.showToast({
|
||||||
|
title: `提交成功`
|
||||||
|
})
|
||||||
|
setTimeout(() => {
|
||||||
|
this.$util.back()
|
||||||
|
this.$util.goUrl({
|
||||||
|
url: 1,
|
||||||
|
openType: `navigateBack`
|
||||||
|
})
|
||||||
|
}, 2000)
|
||||||
|
} catch (e) {
|
||||||
|
setTimeout(() => {
|
||||||
|
this.lockTap = false
|
||||||
|
this.$util.hideAll()
|
||||||
|
}, 2000)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
filters: {
|
||||||
|
handleStartEndTime(val, toDay) {
|
||||||
|
let text = ''
|
||||||
|
let {
|
||||||
|
start_time,
|
||||||
|
end_time
|
||||||
|
} = val
|
||||||
|
let start = `${toDay} ${start_time}`
|
||||||
|
let end = `${toDay} ${end_time}`
|
||||||
|
if (start_time && end_time && $util.DateToUnix(start) >= $util.DateToUnix(end)) {
|
||||||
|
text = '次日'
|
||||||
|
}
|
||||||
|
return text
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.item-time {
|
||||||
|
width: 50%;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,284 @@
|
||||||
|
<template>
|
||||||
|
<view class="agent-technician-list" v-if="isLoad">
|
||||||
|
<fixed>
|
||||||
|
<view class="search-info fill-base pt-lg pb-md">
|
||||||
|
<view class="flex-center pl-lg pr-lg pb-md">
|
||||||
|
<view @tap.stop="$util.goUrl({url:`/agent/pages/technician/apply`})"
|
||||||
|
class="dynamic-btn flex-center f-caption mr-lg radius"
|
||||||
|
:style="{color:primaryColor,border:`1rpx solid ${primaryColor}`}">
|
||||||
|
<i class="iconfont icon-jia-bold"></i>
|
||||||
|
添加
|
||||||
|
</view>
|
||||||
|
<view class="flex-1">
|
||||||
|
<search @input="toSearch" type="input" :padding="0" :radius="30" backgroundColor="#F0F0F0"
|
||||||
|
:placeholder="placeholder">
|
||||||
|
</search>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view style="padding-right:30rpx">
|
||||||
|
<tab @change="handerTabChange" :isLine="true" :list="tabList" :activeIndex="activeIndex*1"
|
||||||
|
color="#9D9D9D" :activeColor="primaryColor" :width="100/tabList.length + '%'" height="100rpx"
|
||||||
|
:numberType="2"></tab>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
</fixed>
|
||||||
|
<view @tap.stop="goDetail(index)" class="list-item fill-base flex-warp mt-md ml-md mr-md pd-lg radius-16"
|
||||||
|
v-for="(item,index) in list.data" :key="index">
|
||||||
|
<view>
|
||||||
|
<view class="avatar rel">
|
||||||
|
<!-- #ifdef H5 -->
|
||||||
|
<view class="avatar radius">
|
||||||
|
<view class="h5-image avatar radius" :style="{ backgroundImage : `url('${item.work_img}')`}">
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<!-- #endif -->
|
||||||
|
<!-- #ifndef H5 -->
|
||||||
|
<image mode="aspectFill" class="avatar radius" :src="item.work_img">
|
||||||
|
</image>
|
||||||
|
<!-- #endif -->
|
||||||
|
</view>
|
||||||
|
<view class="flex-center">
|
||||||
|
<view class="item-tag flex-center f-icontext c-base radius-20"
|
||||||
|
:class="[{'have-user':item.auth_status}]">
|
||||||
|
{{authStatusType[item.auth_status]}}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="flex-1 ml-md">
|
||||||
|
<view class="flex-between">
|
||||||
|
<view class="f-icontext c-paragraph">ID:{{item.id}}</view>
|
||||||
|
<view class="f-paragraph"
|
||||||
|
:style="{color:item.is_update==1?primaryColor:item.status==4?subColor:item.status==3?'#E82F21':'#999999'}">
|
||||||
|
{{statusType[item.status]}}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-y-center pb-lg b-1px-b">
|
||||||
|
<view class="f-paragraph c-black text-bold max-400 ellipsis">{{item.coach_name}}</view>
|
||||||
|
<view class="status-btn flex-center f-icontext ml-md"
|
||||||
|
:style="{color:item.admin_add==1?primaryColor:subColor,border:`1rpx solid ${item.admin_add==1?primaryColor:subColor}`}">
|
||||||
|
{{item.admin_add==1?'平台':'用户'}}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="f-icontext c-paragraph mt-md">{{item.mobile}}</view>
|
||||||
|
<view class="f-icontext c-paragraph mt-sm">
|
||||||
|
所属代理商:{{item.admin_name || '-'}}{{item.admin_id?` (${cityType[item.city_type]})`:''}}</view>
|
||||||
|
<view class="f-icontext c-paragraph mt-sm">申请时间:{{item.create_time}}</view>
|
||||||
|
<view class="flex-between mt-md" v-if="!item.is_update">
|
||||||
|
<view></view>
|
||||||
|
<view class="edit-btn flex-center f-desc radius"
|
||||||
|
:style="{color:primaryColor,border:`1rpx solid ${primaryColor}`}">编辑</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<load-more :noMore="list.current_page>=list.last_page&&list.data.length>0" :loading="loading" v-if="loading">
|
||||||
|
</load-more>
|
||||||
|
<abnor v-if="!loading&&list.data.length<=0&&list.current_page==1"></abnor>
|
||||||
|
<view class="space-footer"></view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
mapState,
|
||||||
|
mapActions,
|
||||||
|
mapMutations
|
||||||
|
} from "vuex"
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
options: {},
|
||||||
|
placeholder: '请输入' + this.$t('action.attendantName') + '姓名/手机号',
|
||||||
|
tabList: [{
|
||||||
|
id: 0,
|
||||||
|
title: '全部',
|
||||||
|
number: 0
|
||||||
|
}, {
|
||||||
|
id: 1,
|
||||||
|
title: '申请中',
|
||||||
|
number: 0
|
||||||
|
}, {
|
||||||
|
id: 2,
|
||||||
|
title: '已授权',
|
||||||
|
number: 0
|
||||||
|
}, {
|
||||||
|
id: 3,
|
||||||
|
title: '已驳回',
|
||||||
|
number: 0
|
||||||
|
}, {
|
||||||
|
id: 4,
|
||||||
|
title: '重新审核',
|
||||||
|
number: 0
|
||||||
|
}],
|
||||||
|
activeIndex: 0,
|
||||||
|
authStatusType: {
|
||||||
|
0: '未认证',
|
||||||
|
1: '认证中',
|
||||||
|
2: '已认证',
|
||||||
|
3: '认证失败'
|
||||||
|
},
|
||||||
|
statusType: {
|
||||||
|
1: '申请中',
|
||||||
|
2: '已授权',
|
||||||
|
3: '取消授权',
|
||||||
|
4: '已驳回'
|
||||||
|
},
|
||||||
|
cityType: {
|
||||||
|
1: '城市',
|
||||||
|
2: '区县',
|
||||||
|
3: '省'
|
||||||
|
},
|
||||||
|
loading: true,
|
||||||
|
isLoad: false,
|
||||||
|
param: {
|
||||||
|
page: 1,
|
||||||
|
limit: 10,
|
||||||
|
status: 0
|
||||||
|
},
|
||||||
|
list: {
|
||||||
|
data: []
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: mapState({
|
||||||
|
primaryColor: state => state.config.configInfo.primaryColor,
|
||||||
|
subColor: state => state.config.configInfo.subColor,
|
||||||
|
configInfo: state => state.config.configInfo,
|
||||||
|
userInfo: state => state.user.userInfo,
|
||||||
|
}),
|
||||||
|
onLoad(options) {
|
||||||
|
this.options = options
|
||||||
|
uni.setNavigationBarTitle({
|
||||||
|
title: this.$t('action.attendantName') + '管理'
|
||||||
|
})
|
||||||
|
this.initIndex()
|
||||||
|
},
|
||||||
|
onPullDownRefresh() {
|
||||||
|
// #ifndef APP-PLUS
|
||||||
|
uni.showNavigationBarLoading()
|
||||||
|
// #endif
|
||||||
|
this.initRefresh();
|
||||||
|
uni.stopPullDownRefresh()
|
||||||
|
},
|
||||||
|
onReachBottom() {
|
||||||
|
if (this.list.current_page >= this.list.last_page || this.loading) return;
|
||||||
|
this.param.page = this.param.page + 1;
|
||||||
|
this.loading = true;
|
||||||
|
this.getList();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async initIndex(refresh = false) {
|
||||||
|
// #ifdef H5
|
||||||
|
if (!refresh && this.$jweixin.isWechat()) {
|
||||||
|
await this.$jweixin.initJssdk();
|
||||||
|
this.$jweixin.wxReady(() => {
|
||||||
|
this.$jweixin.hideOptionMenu()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
this.$util.setNavigationBarColor({
|
||||||
|
bg: this.primaryColor
|
||||||
|
})
|
||||||
|
this.getList();
|
||||||
|
},
|
||||||
|
handerTabChange(index) {
|
||||||
|
this.activeIndex = index
|
||||||
|
this.param.status = index
|
||||||
|
this.getList();
|
||||||
|
},
|
||||||
|
initRefresh() {
|
||||||
|
this.param.page = 1
|
||||||
|
this.initIndex(true)
|
||||||
|
},
|
||||||
|
toSearch(val) {
|
||||||
|
this.param.page = 1
|
||||||
|
this.param.name = val
|
||||||
|
this.getList()
|
||||||
|
},
|
||||||
|
async getList() {
|
||||||
|
this.$util.showLoading()
|
||||||
|
let {
|
||||||
|
list: oldList,
|
||||||
|
param
|
||||||
|
} = this
|
||||||
|
let newList = await this.$api.agent.coachList(param)
|
||||||
|
if (this.param.page == 1) {
|
||||||
|
this.list = newList
|
||||||
|
} else {
|
||||||
|
newList.data = oldList.data.concat(newList.data)
|
||||||
|
this.list = newList
|
||||||
|
}
|
||||||
|
this.tabList[1].number = newList.ing
|
||||||
|
this.isLoad = true
|
||||||
|
this.loading = false
|
||||||
|
this.$util.hideAll()
|
||||||
|
},
|
||||||
|
goDetail(index) {
|
||||||
|
let {
|
||||||
|
id,
|
||||||
|
is_update
|
||||||
|
} = this.list.data[index]
|
||||||
|
if (is_update) return
|
||||||
|
this.$util.goUrl({
|
||||||
|
url: `/agent/pages/technician/apply?id=${id}`
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.agent-technician-list {
|
||||||
|
.search-info {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.dynamic-btn {
|
||||||
|
width: 134rpx;
|
||||||
|
height: 56rpx;
|
||||||
|
transform: rotateZ(360deg);
|
||||||
|
|
||||||
|
.iconfont {
|
||||||
|
font-size: 24rpx;
|
||||||
|
margin-right: 6rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-item {
|
||||||
|
.avatar {
|
||||||
|
width: 124rpx;
|
||||||
|
height: 124rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-tag {
|
||||||
|
width: 100rpx;
|
||||||
|
height: 32rpx;
|
||||||
|
color: #4A4A4A;
|
||||||
|
background: #D8D8D8;
|
||||||
|
margin-top: 19rpx;
|
||||||
|
margin-bottom: 6rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.have-user {
|
||||||
|
color: #EBDDB1;
|
||||||
|
background: linear-gradient(270deg, #4C545A 0%, #282B34 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-btn {
|
||||||
|
width: 60rpx;
|
||||||
|
height: 32rpx;
|
||||||
|
border-radius: 5rpx;
|
||||||
|
transform: rotateZ(360deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.edit-btn {
|
||||||
|
width: 120rpx;
|
||||||
|
height: 50rpx;
|
||||||
|
transform: rotateZ(360deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,167 @@
|
||||||
|
<template>
|
||||||
|
<view>
|
||||||
|
<fixed>
|
||||||
|
<search @input="toSearch" type="input" :padding="30" :radius="0" placeholder="请输入用户昵称/手机号查找">
|
||||||
|
</search>
|
||||||
|
</fixed>
|
||||||
|
<view @tap.stop="toChangeItem(index)"
|
||||||
|
class="list-item fill-base pt-lg pb-lg pl-md pr-lg flex-center mt-md ml-md mr-md radius-16"
|
||||||
|
v-for="(item,index) in list.data" :key="index">
|
||||||
|
<i class="iconfont mr-md"
|
||||||
|
:class="[{'icon-xuanze':check_user.id!=item.id},{'icon-radio-fill':check_user.id==item.id}]"
|
||||||
|
:style="{color:check_user.id==item.id?primaryColor:''}"></i>
|
||||||
|
<view class="flex-1 flex-center">
|
||||||
|
<image mode="aspectFill" class="avatar radius" :src="item.avatarUrl"></image>
|
||||||
|
<view class="flex-1 ml-md">
|
||||||
|
<view class="f-paragraph c-title text-bold ellipsis">{{item.nickName}}</view>
|
||||||
|
<view class="phone" v-if="item.phone">{{item.phone}}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<load-more :noMore="list.current_page>=list.last_page&&list.data.length>0" :loading="loading" v-if="loading">
|
||||||
|
</load-more>
|
||||||
|
<abnor v-if="!loading&&list.data.length<=0&&list.current_page==1"></abnor>
|
||||||
|
<view class="space-max-footer"></view>
|
||||||
|
<fix-bottom-button @confirm="toConfirm" :text="[{text:'确定',type:'confirm'}]" bgColor="#fff">
|
||||||
|
</fix-bottom-button>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
mapState,
|
||||||
|
mapActions,
|
||||||
|
mapMutations
|
||||||
|
} from "vuex"
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
loading: true,
|
||||||
|
isLoad: false,
|
||||||
|
param: {
|
||||||
|
page: 1,
|
||||||
|
limit: 10,
|
||||||
|
status: 0
|
||||||
|
},
|
||||||
|
list: {
|
||||||
|
data: []
|
||||||
|
},
|
||||||
|
check_user: {}
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: mapState({
|
||||||
|
primaryColor: state => state.config.configInfo.primaryColor,
|
||||||
|
subColor: state => state.config.configInfo.subColor,
|
||||||
|
configInfo: state => state.config.configInfo,
|
||||||
|
userInfo: state => state.user.userInfo,
|
||||||
|
}),
|
||||||
|
onLoad() {
|
||||||
|
let {
|
||||||
|
user_id,
|
||||||
|
nickName
|
||||||
|
} = this.$util.getPage(-1).form
|
||||||
|
this.check_user = {
|
||||||
|
id: user_id,
|
||||||
|
nickName
|
||||||
|
}
|
||||||
|
this.initIndex()
|
||||||
|
},
|
||||||
|
onPullDownRefresh() {
|
||||||
|
// #ifndef APP-PLUS
|
||||||
|
uni.showNavigationBarLoading()
|
||||||
|
// #endif
|
||||||
|
this.initRefresh();
|
||||||
|
uni.stopPullDownRefresh()
|
||||||
|
},
|
||||||
|
onReachBottom() {
|
||||||
|
if (this.list.current_page >= this.list.last_page || this.loading) return;
|
||||||
|
this.param.page = this.param.page + 1;
|
||||||
|
this.loading = true;
|
||||||
|
this.getList();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async initIndex(refresh = false) {
|
||||||
|
// #ifdef H5
|
||||||
|
if (!refresh && this.$jweixin.isWechat()) {
|
||||||
|
await this.$jweixin.initJssdk();
|
||||||
|
this.$jweixin.wxReady(() => {
|
||||||
|
this.$jweixin.hideOptionMenu()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
this.$util.setNavigationBarColor({
|
||||||
|
bg: this.primaryColor
|
||||||
|
})
|
||||||
|
this.getList();
|
||||||
|
},
|
||||||
|
handerTabChange(index) {
|
||||||
|
this.activeIndex = index
|
||||||
|
this.param.status = index
|
||||||
|
this.getList();
|
||||||
|
},
|
||||||
|
toSearch(val) {
|
||||||
|
this.param.page = 1
|
||||||
|
this.param.nickName = val
|
||||||
|
this.check_user = {}
|
||||||
|
this.getList()
|
||||||
|
},
|
||||||
|
initRefresh() {
|
||||||
|
this.param.page = 1
|
||||||
|
this.initIndex(true)
|
||||||
|
},
|
||||||
|
async getList() {
|
||||||
|
this.$util.showLoading()
|
||||||
|
let {
|
||||||
|
list: oldList,
|
||||||
|
param
|
||||||
|
} = this
|
||||||
|
let newList = await this.$api.agent.coachUserList(param)
|
||||||
|
if (this.param.page == 1) {
|
||||||
|
this.list = newList
|
||||||
|
} else {
|
||||||
|
newList.data = oldList.data.concat(newList.data)
|
||||||
|
this.list = newList
|
||||||
|
}
|
||||||
|
this.isLoad = true
|
||||||
|
this.loading = false
|
||||||
|
this.$util.hideAll()
|
||||||
|
},
|
||||||
|
toChangeItem(index) {
|
||||||
|
this.check_user = this.list.data[index]
|
||||||
|
},
|
||||||
|
toConfirm() {
|
||||||
|
let {
|
||||||
|
id,
|
||||||
|
nickName
|
||||||
|
} = this.check_user
|
||||||
|
if (!id) {
|
||||||
|
this.$util.showToast({
|
||||||
|
title: `请选择用户`
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.$util.getPage(-1).form.user_id = id
|
||||||
|
this.$util.getPage(-1).form.nickName = nickName || `用户${id}`
|
||||||
|
this.$util.goUrl({
|
||||||
|
url: 1,
|
||||||
|
openType: `navigateBack`
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.list-item {
|
||||||
|
.avatar {
|
||||||
|
width: 72rpx;
|
||||||
|
height: 72rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.phone {
|
||||||
|
font-size: 25rpx;
|
||||||
|
color: #ADADAD;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,38 @@
|
||||||
|
{
|
||||||
|
"version" : "1.1.2",
|
||||||
|
"prompt" : "template",
|
||||||
|
"title" : "服务协议和隐私政策",
|
||||||
|
"message" : " 请你务必审慎阅读、充分理解“服务协议”和“隐私政策”各条款,包括但不限于:为了更好的向你提供服务,我们需要收集你的设备标识、操作日志等信息用于分析、优化应用性能。<br/><br/> 因本产品首页需根据用户定位信息来推荐附近的热门店铺,因此进入APP首页将会弹出获取定位授权。<br/><br/> 你可阅读<a href=\"https://tianjin.tianjinhualong.cn/information.html\">《服务协议》</a>和<a href=\"https://tianjin.tianjinhualong.cn/protocol.html\">《隐私政策》</a>了解详细信息。如果你同意,请点击下面按钮开始接受我们的服务。",
|
||||||
|
"buttonAccept" : "同意并接受",
|
||||||
|
"buttonRefuse" : "暂不同意",
|
||||||
|
"hrefLoader" : "system|default",
|
||||||
|
"backToExit" : "true",
|
||||||
|
"second" : {
|
||||||
|
"title" : "确认提示",
|
||||||
|
"message" : " 进入应用前,你需先同意<a href=\"https://tianjin.tianjinhualong.cn/information.html\">《服务协议》</a>和<a href=\"https://tianjin.tianjinhualong.cn/protocol.html\">《隐私政策》</a>,否则将退出应用。",
|
||||||
|
"buttonAccept" : "同意并继续",
|
||||||
|
"buttonRefuse" : "退出应用"
|
||||||
|
},
|
||||||
|
"disagreeMode" : {
|
||||||
|
"support" : false,
|
||||||
|
"loadNativePlugins" : false,
|
||||||
|
"visitorEntry" : false,
|
||||||
|
"showAlways" : false
|
||||||
|
},
|
||||||
|
"styles" : {
|
||||||
|
"backgroundColor" : "#ffffff",
|
||||||
|
"borderRadius" : "15px",
|
||||||
|
"title" : {
|
||||||
|
"color" : "#000000"
|
||||||
|
},
|
||||||
|
"buttonAccept" : {
|
||||||
|
"color" : "#F3A664"
|
||||||
|
},
|
||||||
|
"buttonRefuse" : {
|
||||||
|
"color" : "#009254"
|
||||||
|
},
|
||||||
|
"buttonVisitor" : {
|
||||||
|
"color" : "#6A5ACD"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
const files = require.context('./modules', false, /\.js$/)
|
||||||
|
const modules = {}
|
||||||
|
files.keys().forEach(key => {
|
||||||
|
modules[key.replace(/(\.\/|\.js)/g, '')] = files(key).default
|
||||||
|
})
|
||||||
|
|
||||||
|
export default{
|
||||||
|
...modules
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
import {
|
||||||
|
req
|
||||||
|
} from '../../utils/req.js';
|
||||||
|
export default {
|
||||||
|
// 首页
|
||||||
|
index(param) {
|
||||||
|
return req.get("mobilenode/app/IndexAdminOrder/index", param)
|
||||||
|
},
|
||||||
|
// 拨打客户电话
|
||||||
|
getVirtualPhone(param) {
|
||||||
|
return req.post("mobilenode/app/IndexAdminOrder/getVirtualPhone", param)
|
||||||
|
},
|
||||||
|
// 编辑通知状态
|
||||||
|
noticeUpdate(param) {
|
||||||
|
return req.post("mobilenode/app/IndexAdminOrder/noticeUpdate", param)
|
||||||
|
},
|
||||||
|
// 订单列表
|
||||||
|
orderList(param) {
|
||||||
|
return req.get("mobilenode/app/IndexAdminOrder/orderList", param)
|
||||||
|
},
|
||||||
|
// 订单详情
|
||||||
|
orderInfo(param) {
|
||||||
|
return req.get("mobilenode/app/IndexAdminOrder/orderInfo", param)
|
||||||
|
},
|
||||||
|
// 修改订单状态
|
||||||
|
adminUpdateOrder(param) {
|
||||||
|
return req.post("mobilenode/app/IndexAdminOrder/adminUpdateOrder", param)
|
||||||
|
},
|
||||||
|
// 退款列表
|
||||||
|
refundOrderList(param) {
|
||||||
|
return req.get("mobilenode/app/IndexAdminOrder/refundOrderList", param)
|
||||||
|
},
|
||||||
|
// 退款详情
|
||||||
|
refundOrderInfo(param) {
|
||||||
|
return req.get("mobilenode/app/IndexAdminOrder/refundOrderInfo", param)
|
||||||
|
},
|
||||||
|
// 同意退款
|
||||||
|
passRefund(param) {
|
||||||
|
return req.post("mobilenode/app/IndexAdminOrder/passRefund", param)
|
||||||
|
},
|
||||||
|
// 拒绝退款
|
||||||
|
noPassRefund(param) {
|
||||||
|
return req.post("mobilenode/app/IndexAdminOrder/noPassRefund", param)
|
||||||
|
},
|
||||||
|
// 代理商列表
|
||||||
|
adminSelect(param) {
|
||||||
|
return req.get("mobilenode/app/IndexAdminOrder/adminSelect", param)
|
||||||
|
},
|
||||||
|
// 更换技-师
|
||||||
|
orderChangeCoach(param) {
|
||||||
|
return req.post("mobilenode/app/IndexAdminOrder/orderChangeCoach", param)
|
||||||
|
},
|
||||||
|
// 转派技-师列表
|
||||||
|
orderChangeCoachList(param) {
|
||||||
|
return req.get("mobilenode/app/IndexAdminOrder/orderChangeCoachList", param)
|
||||||
|
},
|
||||||
|
}
|
|
@ -0,0 +1,109 @@
|
||||||
|
import {
|
||||||
|
req
|
||||||
|
} from '../../utils/req.js';
|
||||||
|
export default {
|
||||||
|
// 合作加盟
|
||||||
|
agentApply(param) {
|
||||||
|
return req.post("massage/app/IndexUser/agentApply", param)
|
||||||
|
},
|
||||||
|
//代理商详情
|
||||||
|
agentInfo(param) {
|
||||||
|
return req.get("massage/app/Index/agentInfo", param)
|
||||||
|
},
|
||||||
|
// 首页
|
||||||
|
index(param) {
|
||||||
|
return req.get("mobilenode/app/IndexAgentOrder/index", param)
|
||||||
|
},
|
||||||
|
// 邀请海报
|
||||||
|
agentInviteQr(param) {
|
||||||
|
return req.get("mobilenode/app/IndexAgentOrder/agentInviteQr", param)
|
||||||
|
},
|
||||||
|
//申请提现
|
||||||
|
applyWallet(param) {
|
||||||
|
return req.post("mobilenode/app/IndexAgentOrder/applyWallet", param)
|
||||||
|
},
|
||||||
|
//提现记录
|
||||||
|
walletList(param) {
|
||||||
|
return req.get("mobilenode/app/IndexAgentOrder/walletList", param)
|
||||||
|
},
|
||||||
|
//账号设置
|
||||||
|
adminInfoData(param) {
|
||||||
|
return req.get("mobilenode/app/IndexAgentOrder/adminInfoData", param)
|
||||||
|
},
|
||||||
|
// 门店下拉列表
|
||||||
|
storeSelect(param) {
|
||||||
|
return req.get("mobilenode/app/IndexAgentOrder/storeSelect", param)
|
||||||
|
},
|
||||||
|
//技-师列表
|
||||||
|
coachList(param) {
|
||||||
|
return req.get("mobilenode/app/IndexAgentOrder/coachList", param)
|
||||||
|
},
|
||||||
|
//技-师详情
|
||||||
|
coachInfo(param) {
|
||||||
|
return req.get("mobilenode/app/IndexAgentOrder/coachInfo", param)
|
||||||
|
},
|
||||||
|
//新增技-师
|
||||||
|
coachApply(param) {
|
||||||
|
return req.post("mobilenode/app/IndexAgentOrder/coachApply", param)
|
||||||
|
},
|
||||||
|
//编辑技-师
|
||||||
|
coachDataUpdate(param) {
|
||||||
|
return req.post("mobilenode/app/IndexAgentOrder/coachDataUpdate", param)
|
||||||
|
},
|
||||||
|
//技-师关联用户
|
||||||
|
coachUserList(param) {
|
||||||
|
return req.get("mobilenode/app/IndexAgentOrder/coachUserList", param)
|
||||||
|
},
|
||||||
|
//佣金列表
|
||||||
|
commList(param) {
|
||||||
|
return req.get("mobilenode/app/IndexAgentOrder/commList", param)
|
||||||
|
},
|
||||||
|
// 拨打客户电话
|
||||||
|
getVirtualPhone(param) {
|
||||||
|
return req.post("mobilenode/app/IndexAgentOrder/getVirtualPhone", param)
|
||||||
|
},
|
||||||
|
// 编辑通知状态
|
||||||
|
noticeUpdate(param) {
|
||||||
|
return req.post("mobilenode/app/IndexAgentOrder/noticeUpdate", param)
|
||||||
|
},
|
||||||
|
// 订单列表
|
||||||
|
orderList(param) {
|
||||||
|
return req.get("mobilenode/app/IndexAgentOrder/orderList", param)
|
||||||
|
},
|
||||||
|
// 订单详情
|
||||||
|
orderInfo(param) {
|
||||||
|
return req.get("mobilenode/app/IndexAgentOrder/orderInfo", param)
|
||||||
|
},
|
||||||
|
// 修改订单状态
|
||||||
|
adminUpdateOrder(param) {
|
||||||
|
return req.post("mobilenode/app/IndexAgentOrder/adminUpdateOrder", param)
|
||||||
|
},
|
||||||
|
// 退款列表
|
||||||
|
refundOrderList(param) {
|
||||||
|
return req.get("mobilenode/app/IndexAgentOrder/refundOrderList", param)
|
||||||
|
},
|
||||||
|
// 退款详情
|
||||||
|
refundOrderInfo(param) {
|
||||||
|
return req.get("mobilenode/app/IndexAgentOrder/refundOrderInfo", param)
|
||||||
|
},
|
||||||
|
// 同意退款
|
||||||
|
passRefund(param) {
|
||||||
|
return req.post("mobilenode/app/IndexAgentOrder/passRefund", param)
|
||||||
|
},
|
||||||
|
// 拒绝退款
|
||||||
|
noPassRefund(param) {
|
||||||
|
return req.post("mobilenode/app/IndexAgentOrder/noPassRefund", param)
|
||||||
|
},
|
||||||
|
// 代理商下拉列表
|
||||||
|
adminSelect(param) {
|
||||||
|
return req.get("mobilenode/app/IndexAgentOrder/adminSelect", param)
|
||||||
|
},
|
||||||
|
// 更换技-师
|
||||||
|
orderChangeCoach(param) {
|
||||||
|
return req.post("mobilenode/app/IndexAgentOrder/orderChangeCoach", param)
|
||||||
|
},
|
||||||
|
// 转派技-师列表
|
||||||
|
orderChangeCoachList(param) {
|
||||||
|
return req.get("mobilenode/app/IndexAgentOrder/orderChangeCoachList", param)
|
||||||
|
},
|
||||||
|
}
|
|
@ -0,0 +1,65 @@
|
||||||
|
import {
|
||||||
|
req,
|
||||||
|
uploadFile
|
||||||
|
} from '../../utils/req.js';
|
||||||
|
export default {
|
||||||
|
// 小程序登录
|
||||||
|
login(param) {
|
||||||
|
return req.post("index/login", param)
|
||||||
|
},
|
||||||
|
// 公众号登录
|
||||||
|
webLogin(param) {
|
||||||
|
return req.post("index/webLogin", param)
|
||||||
|
},
|
||||||
|
// app微信登录
|
||||||
|
appLogin(param) {
|
||||||
|
return req.post("index/appLogin", param)
|
||||||
|
},
|
||||||
|
// app苹果登录
|
||||||
|
iosLogin(param) {
|
||||||
|
return req.post("index/iosLogin", param)
|
||||||
|
},
|
||||||
|
// app登录配置
|
||||||
|
getConfig(param) {
|
||||||
|
return req.get("index/getConfig", param)
|
||||||
|
},
|
||||||
|
// 获取配置
|
||||||
|
getWebConfig(param) {
|
||||||
|
return req.get("index/getWebConfig", param)
|
||||||
|
},
|
||||||
|
// 系统配置
|
||||||
|
configInfo(param) {
|
||||||
|
return req.get("massage/app/Index/configInfo", param)
|
||||||
|
},
|
||||||
|
// 获取地图定位
|
||||||
|
getMapInfo(param) {
|
||||||
|
return req.get("massage/app/Index/getMapInfo", param)
|
||||||
|
},
|
||||||
|
// 解析二维码
|
||||||
|
getWxCodeData(param) {
|
||||||
|
return req.get("card/app/getWxCodeData", param)
|
||||||
|
},
|
||||||
|
// base64ToImg
|
||||||
|
base64ToImg(param) {
|
||||||
|
return req.get("massage/app/IndexUser/base64ToImg", param)
|
||||||
|
},
|
||||||
|
// 上传文件
|
||||||
|
uploadFile(param) {
|
||||||
|
return uploadFile("admin/app/wx/uploadFile", param)
|
||||||
|
},
|
||||||
|
uploadFiles(querys, fn) {
|
||||||
|
return req.post('admin/admin/file/uploadFiles', querys, fn)
|
||||||
|
},
|
||||||
|
// 上传视频
|
||||||
|
uploadVideo(param) {
|
||||||
|
return uploadFile("admin/app/wx/uploadVideo", param)
|
||||||
|
},
|
||||||
|
// 获取城市
|
||||||
|
getCity(param) {
|
||||||
|
return req.get("massage/app/Index/getCity", param)
|
||||||
|
},
|
||||||
|
// 获取插件授权
|
||||||
|
plugAuth(param) {
|
||||||
|
return req.get("massage/app/Index/plugAuth", param)
|
||||||
|
},
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
import {
|
||||||
|
req
|
||||||
|
} from '../../utils/req.js';
|
||||||
|
export default {
|
||||||
|
// 渠道商下拉
|
||||||
|
channelCateSelect(param) {
|
||||||
|
return req.get("massage/app/IndexUser/channelCateSelect", param)
|
||||||
|
},
|
||||||
|
// 申请渠道商
|
||||||
|
applyChannel(param) {
|
||||||
|
return req.post("massage/app/IndexUser/applyChannel", param)
|
||||||
|
},
|
||||||
|
// 渠道商信息
|
||||||
|
channelInfo(param) {
|
||||||
|
return req.get("massage/app/IndexUser/channelInfo", param)
|
||||||
|
},
|
||||||
|
// 渠道商首页
|
||||||
|
index(param) {
|
||||||
|
return req.get("massage/app/IndexChannel/index", param)
|
||||||
|
},
|
||||||
|
// 渠道商二维码
|
||||||
|
channelQr(param) {
|
||||||
|
return req.get("massage/app/IndexChannel/channelQr", param)
|
||||||
|
},
|
||||||
|
// 订单列表
|
||||||
|
orderList(param) {
|
||||||
|
return req.get("massage/app/IndexChannel/orderList", param)
|
||||||
|
},
|
||||||
|
//申请提现
|
||||||
|
applyWallet(param) {
|
||||||
|
return req.post("massage/app/IndexChannel/applyWallet", param)
|
||||||
|
},
|
||||||
|
//提现记录
|
||||||
|
walletList(param) {
|
||||||
|
return req.get("massage/app/IndexChannel/walletList", param)
|
||||||
|
},
|
||||||
|
}
|
|
@ -0,0 +1,82 @@
|
||||||
|
import {
|
||||||
|
req
|
||||||
|
} from '../../utils/req.js';
|
||||||
|
export default {
|
||||||
|
// 动态列表
|
||||||
|
dynamicList(param) {
|
||||||
|
return req.get("dynamic/app/IndexDynamicList/dynamicList", param)
|
||||||
|
},
|
||||||
|
// 获取关注技-师的最新动态数量
|
||||||
|
getFollowData(param) {
|
||||||
|
return req.get("dynamic/app/IndexDynamicList/getFollowData", param)
|
||||||
|
},
|
||||||
|
// 关注技-师动态列表
|
||||||
|
followDynamicList(param) {
|
||||||
|
return req.get("dynamic/app/IndexDynamicList/followDynamicList", param)
|
||||||
|
},
|
||||||
|
// 动态详情
|
||||||
|
dynamicInfo(param) {
|
||||||
|
return req.get("dynamic/app/IndexDynamicList/dynamicInfo", param)
|
||||||
|
},
|
||||||
|
// 点赞或者取消点赞
|
||||||
|
thumbsAddOrCancek(param) {
|
||||||
|
return req.post("dynamic/app/IndexDynamicList/thumbsAddOrCancek", param)
|
||||||
|
},
|
||||||
|
// 我的关注
|
||||||
|
followCoachList(param) {
|
||||||
|
return req.get("dynamic/app/IndexDynamicList/followCoachList", param)
|
||||||
|
},
|
||||||
|
// 关注或者取消关注
|
||||||
|
followAddOrCancek(param) {
|
||||||
|
return req.post("dynamic/app/IndexDynamicList/followAddOrCancek", param)
|
||||||
|
},
|
||||||
|
// 评论列表
|
||||||
|
commentList(param) {
|
||||||
|
return req.get("dynamic/app/IndexDynamicList/commentList", param)
|
||||||
|
},
|
||||||
|
// 新增评论
|
||||||
|
commentAdd(param) {
|
||||||
|
return req.post("dynamic/app/IndexDynamicList/commentAdd", param)
|
||||||
|
},
|
||||||
|
// 删除评论
|
||||||
|
commentDel(param) {
|
||||||
|
return req.post("dynamic/app/IndexDynamicList/commentDel", param)
|
||||||
|
},
|
||||||
|
// --------- 技-师端
|
||||||
|
// 动态列表
|
||||||
|
coachDynamicList(param) {
|
||||||
|
return req.get("dynamic/app/IndexDynamicCoach/dynamicList", param)
|
||||||
|
},
|
||||||
|
// 动态详情
|
||||||
|
coachDynamicInfo(param) {
|
||||||
|
return req.get("dynamic/app/IndexDynamicCoach/dynamicInfo", param)
|
||||||
|
},
|
||||||
|
// 关注点赞消息详情
|
||||||
|
dynamicData(param) {
|
||||||
|
return req.get("dynamic/app/IndexDynamicCoach/dynamicData", param)
|
||||||
|
},
|
||||||
|
// 发布动态
|
||||||
|
dynamicAdd(param) {
|
||||||
|
return req.post("dynamic/app/IndexDynamicCoach/dynamicAdd", param)
|
||||||
|
},
|
||||||
|
// 编辑动态
|
||||||
|
dynamicUpdate(param) {
|
||||||
|
return req.post("dynamic/app/IndexDynamicCoach/dynamicUpdate", param)
|
||||||
|
},
|
||||||
|
// 删除动态
|
||||||
|
dynamicDel(param) {
|
||||||
|
return req.post("dynamic/app/IndexDynamicCoach/dynamicDel", param)
|
||||||
|
},
|
||||||
|
// 收获的赞
|
||||||
|
thumbsList(param) {
|
||||||
|
return req.get("dynamic/app/IndexDynamicCoach/thumbsList", param)
|
||||||
|
},
|
||||||
|
// 新增关注
|
||||||
|
followList(param) {
|
||||||
|
return req.get("dynamic/app/IndexDynamicCoach/followList", param)
|
||||||
|
},
|
||||||
|
// 收获的评论
|
||||||
|
coachCommentList(param) {
|
||||||
|
return req.get("dynamic/app/IndexDynamicCoach/commentList", param)
|
||||||
|
},
|
||||||
|
}
|
|
@ -0,0 +1,177 @@
|
||||||
|
import {
|
||||||
|
req
|
||||||
|
} from '../../utils/req.js';
|
||||||
|
export default {
|
||||||
|
// 个人中心页面
|
||||||
|
index(param) {
|
||||||
|
return req.get("massage/app/IndexUser/index", param)
|
||||||
|
},
|
||||||
|
//技师端显示隐藏
|
||||||
|
isShowwx(param) {
|
||||||
|
return req.get("massage/CallBack/is_showwx", param)
|
||||||
|
},
|
||||||
|
// 认证技-师
|
||||||
|
attestationCoach(param) {
|
||||||
|
return req.post("massage/app/IndexUser/attestationCoach", param)
|
||||||
|
},
|
||||||
|
//申请分销商
|
||||||
|
applyReseller(param) {
|
||||||
|
return req.post("massage/app/IndexUser/applyReseller", param)
|
||||||
|
},
|
||||||
|
//分销商详情
|
||||||
|
resellerInfo(param) {
|
||||||
|
return req.get("massage/app/IndexUser/resellerInfo", param)
|
||||||
|
},
|
||||||
|
//我的收益
|
||||||
|
capCashInfo(param) {
|
||||||
|
return req.get("massage/app/IndexUser/userCashInfo", param)
|
||||||
|
},
|
||||||
|
//申请提现
|
||||||
|
applyWallet(param) {
|
||||||
|
return req.post("massage/app/IndexUser/applyWallet", param)
|
||||||
|
},
|
||||||
|
//提现记录
|
||||||
|
walletList(param) {
|
||||||
|
return req.get("massage/app/IndexUser/walletList", param)
|
||||||
|
},
|
||||||
|
//合伙人首页
|
||||||
|
partnerIndex(param) {
|
||||||
|
return req.get("massage/app/IndexReseller/partnerIndex", param)
|
||||||
|
},
|
||||||
|
//邀请的技-师
|
||||||
|
partnerCoachList(param) {
|
||||||
|
return req.get("massage/app/IndexReseller/partnerCoachList", param)
|
||||||
|
},
|
||||||
|
//我的团队
|
||||||
|
myTeam(param) {
|
||||||
|
return req.get("massage/app/IndexUser/myTeam", param)
|
||||||
|
},
|
||||||
|
//邀请用户
|
||||||
|
userCommQr(param) {
|
||||||
|
return req.get("massage/app/IndexUser/userCommQr", param)
|
||||||
|
},
|
||||||
|
//代理商绑定技-师
|
||||||
|
adminCoachQr(param) {
|
||||||
|
return req.get("massage/app/IndexUser/adminCoachQr", param)
|
||||||
|
},
|
||||||
|
//邀请技-师
|
||||||
|
resellerInvCoachQr(param) {
|
||||||
|
return req.get("massage/app/IndexReseller/resellerInvCoachQr", param)
|
||||||
|
},
|
||||||
|
//选择代理商
|
||||||
|
adminList(param) {
|
||||||
|
return req.get("massage/app/IndexReseller/adminList", param)
|
||||||
|
},
|
||||||
|
// 获取默认地址
|
||||||
|
getDefultAddress(param) {
|
||||||
|
return req.get("massage/app/IndexUser/getDefultAddress", param)
|
||||||
|
},
|
||||||
|
// 地址列表
|
||||||
|
addressList(param) {
|
||||||
|
return req.get("massage/app/IndexUser/addressList", param)
|
||||||
|
},
|
||||||
|
// 地址详情
|
||||||
|
addressInfo(param) {
|
||||||
|
return req.get("massage/app/IndexUser/addressInfo", param)
|
||||||
|
},
|
||||||
|
// 新增地址
|
||||||
|
addressAdd(param) {
|
||||||
|
return req.post("massage/app/IndexUser/addressAdd", param)
|
||||||
|
},
|
||||||
|
// 修改地址
|
||||||
|
addressUpdate(param) {
|
||||||
|
return req.post("massage/app/IndexUser/addressUpdate", param)
|
||||||
|
},
|
||||||
|
// 删除地址
|
||||||
|
addressDel(param) {
|
||||||
|
return req.post("massage/app/IndexUser/addressDel", param)
|
||||||
|
},
|
||||||
|
// 收藏技-师
|
||||||
|
coachCollectList(param) {
|
||||||
|
return req.get("massage/app/IndexUser/coachCollectList", param)
|
||||||
|
},
|
||||||
|
// 新增收藏
|
||||||
|
addCollect(param) {
|
||||||
|
return req.post("massage/app/IndexUser/addCollect", param)
|
||||||
|
},
|
||||||
|
// 删除收藏
|
||||||
|
delCollect(param) {
|
||||||
|
return req.post("massage/app/IndexUser/delCollect", param)
|
||||||
|
},
|
||||||
|
//卡券列表
|
||||||
|
userCouponList(param) {
|
||||||
|
return req.get("massage/app/IndexUser/userCouponList", param)
|
||||||
|
},
|
||||||
|
//删除卡券
|
||||||
|
couponDel(param) {
|
||||||
|
return req.post("massage/app/IndexUser/couponDel", param)
|
||||||
|
},
|
||||||
|
//卡券活动
|
||||||
|
couponAtvInfo(param) {
|
||||||
|
return req.post("massage/app/IndexUser/couponAtvInfo", param)
|
||||||
|
},
|
||||||
|
//卡券二维码
|
||||||
|
atvQr(param) {
|
||||||
|
return req.post("massage/app/IndexUser/atvQr", param)
|
||||||
|
},
|
||||||
|
//技-师分享储值套餐
|
||||||
|
coachBalanceQr(param) {
|
||||||
|
return req.get("massage/app/IndexCoach/coachBalanceQr", param)
|
||||||
|
},
|
||||||
|
//选择技-师
|
||||||
|
coachList(param) {
|
||||||
|
return req.get("massage/app/IndexBalance/coachList", param)
|
||||||
|
},
|
||||||
|
//储值充值卡列表
|
||||||
|
cardList(param) {
|
||||||
|
return req.get("massage/app/IndexBalance/cardList", param)
|
||||||
|
},
|
||||||
|
//充值余额(card_id)
|
||||||
|
payBalanceOrder(param) {
|
||||||
|
return req.post("massage/app/IndexBalance/payBalanceOrder", param)
|
||||||
|
},
|
||||||
|
//充值订单列表(时间筛选 start_time,end_time)
|
||||||
|
balaceOrder(param) {
|
||||||
|
return req.get("massage/app/IndexBalance/balaceOrder", param)
|
||||||
|
},
|
||||||
|
//消费明细
|
||||||
|
payWater(param) {
|
||||||
|
return req.get("massage/app/IndexBalance/payWater", param)
|
||||||
|
},
|
||||||
|
//佣金明细
|
||||||
|
commList(param) {
|
||||||
|
return req.get("massage/app/IndexUser/commList", param)
|
||||||
|
},
|
||||||
|
// 提交反馈
|
||||||
|
addFeedback(param) {
|
||||||
|
return req.post("massage/app/IndexCoach/addFeedback", param)
|
||||||
|
},
|
||||||
|
// 反馈记录
|
||||||
|
listFeedback(param) {
|
||||||
|
return req.get("massage/app/IndexCoach/listFeedback", param)
|
||||||
|
},
|
||||||
|
// 反馈详情
|
||||||
|
feedbackInfo(param) {
|
||||||
|
return req.get("massage/app/IndexCoach/feedbackInfo", param)
|
||||||
|
},
|
||||||
|
// 屏蔽列表
|
||||||
|
shieldCoachList(param) {
|
||||||
|
return req.get("massage/app/IndexUser/shieldCoachList", param)
|
||||||
|
},
|
||||||
|
// 新增屏蔽
|
||||||
|
shieldCoachAdd(param) {
|
||||||
|
return req.post("massage/app/IndexUser/shieldCoachAdd", param)
|
||||||
|
},
|
||||||
|
// 删除屏蔽
|
||||||
|
shieldCoachDel(param) {
|
||||||
|
return req.post("massage/app/IndexUser/shieldCoachDel", param)
|
||||||
|
},
|
||||||
|
// 绑定支付宝账号
|
||||||
|
bindAlipayNumber(param) {
|
||||||
|
return req.post("massage/app/IndexUser/bindAlipayNumber", param)
|
||||||
|
},
|
||||||
|
// 获取门店数据
|
||||||
|
getStoreSelect(param) {
|
||||||
|
return req.get("massage/app/IndexUser/getStoreSelect", param)
|
||||||
|
},
|
||||||
|
}
|
|
@ -0,0 +1,133 @@
|
||||||
|
import {
|
||||||
|
req
|
||||||
|
} from '../../utils/req.js';
|
||||||
|
export default {
|
||||||
|
// 购物车
|
||||||
|
carInfo(param) {
|
||||||
|
return req.get("massage/app/Index/carInfo", param)
|
||||||
|
},
|
||||||
|
// 加入购物车
|
||||||
|
addCar(param) {
|
||||||
|
return req.post("massage/app/Index/addCar", param)
|
||||||
|
},
|
||||||
|
// 删除购物车数量
|
||||||
|
delCar(param) {
|
||||||
|
return req.post("massage/app/Index/delCar", param)
|
||||||
|
},
|
||||||
|
//清空购物车
|
||||||
|
delSomeCar(param) {
|
||||||
|
return req.post("massage/app/IndexGoods/delSomeCar", param)
|
||||||
|
},
|
||||||
|
//选择购物车商品
|
||||||
|
carUpdate(param) {
|
||||||
|
return req.post("massage/app/IndexGoods/carUpdate", param)
|
||||||
|
},
|
||||||
|
//获取是否能选择 公交/地铁
|
||||||
|
getIsBus(param) {
|
||||||
|
return req.get("massage/app/IndexOrder/getIsBus", param)
|
||||||
|
},
|
||||||
|
//下单选择时间
|
||||||
|
dayText(param) {
|
||||||
|
return req.get("massage/app/IndexOrder/dayText", param)
|
||||||
|
},
|
||||||
|
//下单选择时间(coach_id,day)
|
||||||
|
timeText(param) {
|
||||||
|
return req.get("massage/app/IndexOrder/timeText", param)
|
||||||
|
},
|
||||||
|
//获取升级订单信息
|
||||||
|
upOrderInfo(param) {
|
||||||
|
return req.post("massage/app/IndexOrder/upOrderInfo", param)
|
||||||
|
},
|
||||||
|
//升级服务下单
|
||||||
|
upOrderGoods(param) {
|
||||||
|
return req.post("massage/app/IndexOrder/upOrderGoods", param)
|
||||||
|
},
|
||||||
|
//校验加钟订单是否可下单
|
||||||
|
checkAddOrder(param) {
|
||||||
|
return req.post("massage/app/IndexOrder/checkAddOrder", param)
|
||||||
|
},
|
||||||
|
//获取下单信息(coach_id,有卡券就传 coupon_id)
|
||||||
|
payOrderInfo(param) {
|
||||||
|
return req.get("massage/app/IndexOrder/payOrderInfo", param)
|
||||||
|
},
|
||||||
|
//下单
|
||||||
|
payOrder(param) {
|
||||||
|
return req.post("massage/app/IndexOrder/payOrder", param)
|
||||||
|
},
|
||||||
|
//可用卡券
|
||||||
|
couponList(param) {
|
||||||
|
return req.get("massage/app/IndexOrder/couponList", param)
|
||||||
|
},
|
||||||
|
//订单列表
|
||||||
|
orderList(param) {
|
||||||
|
return req.get("massage/app/IndexOrder/orderList", param)
|
||||||
|
},
|
||||||
|
//根据主订单查询加钟订单列表
|
||||||
|
getAddClockOrder(param) {
|
||||||
|
return req.get("massage/app/IndexOrder/getAddClockOrder", param)
|
||||||
|
},
|
||||||
|
//订单详情
|
||||||
|
orderInfo(param) {
|
||||||
|
return req.get("massage/app/IndexOrder/orderInfo", param)
|
||||||
|
},
|
||||||
|
// 技师已到达
|
||||||
|
userSureArrivalOrder(param) {
|
||||||
|
return req.post("massage/app/IndexOrder/userSureArrival", param)
|
||||||
|
},
|
||||||
|
// 升级订单记录
|
||||||
|
orderUpRecord(param) {
|
||||||
|
return req.get("massage/app/IndexOrder/orderUpRecord", param)
|
||||||
|
},
|
||||||
|
// 拨打技-师电话
|
||||||
|
getVirtualPhone(param) {
|
||||||
|
return req.get("massage/app/IndexUser/getVirtualPhone", param)
|
||||||
|
},
|
||||||
|
//刷新二维码
|
||||||
|
refreshQr(param) {
|
||||||
|
return req.post("massage/app/IndexOrder/refreshQr", param)
|
||||||
|
},
|
||||||
|
//取消订单
|
||||||
|
cancelOrder(param) {
|
||||||
|
return req.post("massage/app/IndexOrder/cancelOrder", param)
|
||||||
|
},
|
||||||
|
//删除订单
|
||||||
|
delOrder(param) {
|
||||||
|
return req.post("massage/app/IndexOrder/delOrder", param)
|
||||||
|
},
|
||||||
|
//确认完成订单
|
||||||
|
userSignOrder(param) {
|
||||||
|
return req.post("massage/app/IndexOrder/userSignOrder", param)
|
||||||
|
},
|
||||||
|
//重新支付
|
||||||
|
rePayOrder(param) {
|
||||||
|
return req.post("massage/app/IndexOrder/rePayOrder", param)
|
||||||
|
},
|
||||||
|
//申请退款
|
||||||
|
applyOrder(param) {
|
||||||
|
return req.post("massage/app/IndexOrder/applyOrder", param)
|
||||||
|
},
|
||||||
|
//再来一单
|
||||||
|
onceMoreOrder(param) {
|
||||||
|
return req.post("massage/app/Index/onceMoreOrder", param)
|
||||||
|
},
|
||||||
|
//添加评价(order_id,text,star)
|
||||||
|
addComment(param) {
|
||||||
|
return req.post("massage/app/IndexOrder/addComment", param)
|
||||||
|
},
|
||||||
|
//标签列表
|
||||||
|
lableList(param) {
|
||||||
|
return req.get("massage/app/IndexOrder/lableList", param)
|
||||||
|
},
|
||||||
|
//我的售后
|
||||||
|
refundOrderList(param) {
|
||||||
|
return req.get("massage/app/IndexOrder/refundOrderList", param)
|
||||||
|
},
|
||||||
|
//售后详情
|
||||||
|
refundOrderInfo(param) {
|
||||||
|
return req.get("massage/app/IndexOrder/refundOrderInfo", param)
|
||||||
|
},
|
||||||
|
//取消退款
|
||||||
|
cancelRefundOrder(param) {
|
||||||
|
return req.post("massage/app/IndexOrder/cancelRefundOrder", param)
|
||||||
|
},
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
import {
|
||||||
|
req
|
||||||
|
} from '../../utils/req.js';
|
||||||
|
export default {
|
||||||
|
// 申请业务员
|
||||||
|
applySalesman(param) {
|
||||||
|
return req.post("massage/app/IndexUser/applySalesman", param)
|
||||||
|
},
|
||||||
|
// 业务员信息
|
||||||
|
salesmanInfo(param) {
|
||||||
|
return req.get("massage/app/IndexUser/salesmanInfo", param)
|
||||||
|
},
|
||||||
|
// 业务员首页
|
||||||
|
index(param) {
|
||||||
|
return req.get("massage/app/IndexSalesman/index", param)
|
||||||
|
},
|
||||||
|
// 业务员二维码
|
||||||
|
salesmanQr(param) {
|
||||||
|
return req.get("massage/app/IndexSalesman/salesmanQr", param)
|
||||||
|
},
|
||||||
|
// 申请提现
|
||||||
|
applyWallet(param) {
|
||||||
|
return req.post("massage/app/IndexSalesman/applyWallet", param)
|
||||||
|
},
|
||||||
|
// 提现记录
|
||||||
|
walletList(param) {
|
||||||
|
return req.get("massage/app/IndexSalesman/walletList", param)
|
||||||
|
},
|
||||||
|
// 渠道明细
|
||||||
|
salesmanChannelCash(param) {
|
||||||
|
return req.get("massage/app/IndexSalesman/salesmanChannelCash", param)
|
||||||
|
},
|
||||||
|
// 业务员渠道商明细详情
|
||||||
|
salesmanChannelOrderList(param) {
|
||||||
|
return req.get("massage/app/IndexSalesman/salesmanChannelOrderList", param)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,65 @@
|
||||||
|
import {
|
||||||
|
req
|
||||||
|
} from '../../utils/req.js';
|
||||||
|
export default {
|
||||||
|
// 首页轮播图
|
||||||
|
index(param) {
|
||||||
|
return req.get("massage/app/Index/index", param)
|
||||||
|
},
|
||||||
|
//文章详情
|
||||||
|
articleInfo(param) {
|
||||||
|
return req.get("massage/app/IndexArticle/articleInfo", param)
|
||||||
|
},
|
||||||
|
//文章详情-提交表单
|
||||||
|
subArticleForm(param) {
|
||||||
|
return req.post("massage/app/IndexArticle/subArticleForm", param)
|
||||||
|
},
|
||||||
|
// 服务分类列表
|
||||||
|
serviceCateList(param) {
|
||||||
|
return req.get("massage/app/Index/serviceCateList", param)
|
||||||
|
},
|
||||||
|
// 服务列表
|
||||||
|
serviceList(param) {
|
||||||
|
return req.get("massage/app/Index/serviceList", param)
|
||||||
|
},
|
||||||
|
// 服务详情
|
||||||
|
serviceInfo(param) {
|
||||||
|
return req.get("massage/app/Index/serviceInfo", param)
|
||||||
|
},
|
||||||
|
// 地图找人
|
||||||
|
mapCoachList(param) {
|
||||||
|
return req.get("map/app/Index/coachList", param)
|
||||||
|
},
|
||||||
|
// 服务技-师列表无筛选项(ser_id,服务id,lat,lng)
|
||||||
|
typeServiceCoachList(param) {
|
||||||
|
return req.get("massage/app/Index/typeServiceCoachList", param)
|
||||||
|
},
|
||||||
|
// 服务技-师列表(ser_id,服务id,lat,lng,type)
|
||||||
|
serviceCoachList(param) {
|
||||||
|
return req.get("massage/app/Index/serviceCoachList", param)
|
||||||
|
},
|
||||||
|
// 技-师服务列表(coach_id)
|
||||||
|
coachServiceList(param) {
|
||||||
|
return req.get("massage/app/Index/coachServiceList", param)
|
||||||
|
},
|
||||||
|
// 技-师评价
|
||||||
|
commentList(param) {
|
||||||
|
return req.get("massage/app/Index/commentList", param)
|
||||||
|
},
|
||||||
|
// 技-师信息
|
||||||
|
coachInfo(param) {
|
||||||
|
return req.get("massage/app/Index/coachInfo", param)
|
||||||
|
},
|
||||||
|
//优惠券列表
|
||||||
|
couponList(param) {
|
||||||
|
return req.get("massage/app/Index/couponList", param)
|
||||||
|
},
|
||||||
|
//领取优惠券
|
||||||
|
userGetCoupon(param) {
|
||||||
|
return req.post("massage/app/Index/userGetCoupon", param)
|
||||||
|
},
|
||||||
|
//获取可升级的服务
|
||||||
|
getUpOrderGoods(param) {
|
||||||
|
return req.get("massage/app/IndexOrder/getUpOrderGoods", param)
|
||||||
|
},
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
import {
|
||||||
|
req
|
||||||
|
} from '../../utils/req.js';
|
||||||
|
export default {
|
||||||
|
// 门店列表
|
||||||
|
storeList(param) {
|
||||||
|
return req.get("store/app/IndexStore/storeList", param)
|
||||||
|
},
|
||||||
|
// 门店详情
|
||||||
|
storeInfo(param) {
|
||||||
|
return req.get("store/app/IndexStore/storeInfo", param)
|
||||||
|
},
|
||||||
|
// 门店服务列表
|
||||||
|
storeServiceList(param) {
|
||||||
|
return req.get("store/app/IndexStore/storeServiceList", param)
|
||||||
|
},
|
||||||
|
// 门店评价列表
|
||||||
|
commentList(param) {
|
||||||
|
return req.get("store/app/IndexStore/commentList", param)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,185 @@
|
||||||
|
import {
|
||||||
|
req
|
||||||
|
} from '../../utils/req.js';
|
||||||
|
export default {
|
||||||
|
// 申请技-师
|
||||||
|
coachApply(param) {
|
||||||
|
return req.post("massage/app/IndexUser/coachApply", param)
|
||||||
|
},
|
||||||
|
// 获取是否开启合同
|
||||||
|
getFddStatus(param) {
|
||||||
|
return req.get("massage/app/IndexCoach/getFddStatus", param)
|
||||||
|
},
|
||||||
|
// 获取是否已签合同
|
||||||
|
getFddRecord(param) {
|
||||||
|
return req.get("massage/app/IndexCoach/getFddRecord", param)
|
||||||
|
},
|
||||||
|
// 获取发大大实名认证地址
|
||||||
|
getPersonVerifyUrl(param) {
|
||||||
|
return req.get("massage/app/IndexCoach/getPersonVerifyUrl", param)
|
||||||
|
},
|
||||||
|
// 获取用户实名注册信息
|
||||||
|
getAttestationInfo(param) {
|
||||||
|
return req.get("massage/app/IndexCoach/getAttestationInfo", param)
|
||||||
|
},
|
||||||
|
// 签署合同
|
||||||
|
Extsign(param) {
|
||||||
|
return req.post("massage/app/IndexCoach/Extsign", param)
|
||||||
|
},
|
||||||
|
// 技-师信息
|
||||||
|
coachInfo(param) {
|
||||||
|
return req.get("massage/app/IndexUser/coachInfo", param)
|
||||||
|
},
|
||||||
|
// 编辑技-师
|
||||||
|
coachUpdate(param) {
|
||||||
|
return req.post("massage/app/IndexCoach/coachUpdate", param)
|
||||||
|
},
|
||||||
|
// 编辑技-师
|
||||||
|
coachUpdateV2(param) {
|
||||||
|
return req.post("massage/app/IndexCoach/coachUpdateV2", param)
|
||||||
|
},
|
||||||
|
// 技-师等级
|
||||||
|
coachLevel(param) {
|
||||||
|
return req.get("massage/app/IndexCoach/coachLevel", param)
|
||||||
|
},
|
||||||
|
// 技-师首页
|
||||||
|
coachIndex(param) {
|
||||||
|
return req.get("massage/app/IndexCoach/coachIndex", param)
|
||||||
|
},
|
||||||
|
// 技-师报警
|
||||||
|
police(param) {
|
||||||
|
return req.post("massage/app/IndexCoach/police", param)
|
||||||
|
},
|
||||||
|
// 订单列表
|
||||||
|
orderList(param) {
|
||||||
|
return req.get("massage/app/IndexCoach/orderList", param)
|
||||||
|
},
|
||||||
|
// 订单详情
|
||||||
|
orderInfo(param) {
|
||||||
|
return req.get("massage/app/IndexCoach/orderInfo", param)
|
||||||
|
},
|
||||||
|
// 修改订单状态(type,order_id)
|
||||||
|
updateOrder(param) {
|
||||||
|
return req.post("massage/app/IndexCoach/updateOrder", param)
|
||||||
|
},
|
||||||
|
// 客户爽约
|
||||||
|
breakThePromiseOrder(param) {
|
||||||
|
return req.post("massage/app/IndexCoach/breakThePromise", param)
|
||||||
|
},
|
||||||
|
// 拨打客户电话
|
||||||
|
getVirtualPhone(param) {
|
||||||
|
return req.post("massage/app/IndexCoach/getVirtualPhone", param)
|
||||||
|
},
|
||||||
|
//佣金信息
|
||||||
|
capCashInfo(param) {
|
||||||
|
return req.get("massage/app/IndexCoach/capCashInfo", param)
|
||||||
|
},
|
||||||
|
//佣金信息(车费)
|
||||||
|
capCashInfoCar(param) {
|
||||||
|
return req.get("massage/app/IndexCoach/capCashInfoCar", param)
|
||||||
|
},
|
||||||
|
//申请提现 (apply_price,text,type:1服务费提现,2车费提现)
|
||||||
|
applyWallet(param) {
|
||||||
|
return req.post("massage/app/IndexCoach/applyWallet", param)
|
||||||
|
},
|
||||||
|
//提现记录
|
||||||
|
capCashList(param) {
|
||||||
|
return req.get("massage/app/IndexCoach/capCashList", param)
|
||||||
|
},
|
||||||
|
//时间管理回显
|
||||||
|
timeConfig(param) {
|
||||||
|
return req.get("massage/app/IndexCoach/timeConfig", param)
|
||||||
|
},
|
||||||
|
//时间管理设置
|
||||||
|
setTimeConfig(param) {
|
||||||
|
return req.post("massage/app/IndexCoach/timeConfig", param)
|
||||||
|
},
|
||||||
|
//根据接单时间获取时间节点
|
||||||
|
getTime(param) {
|
||||||
|
return req.get("massage/app/IndexCoach/getTime", param)
|
||||||
|
},
|
||||||
|
//根据接单时间获取时间节点
|
||||||
|
getOrderNum(param) {
|
||||||
|
return req.get("massage/app/IndexCoach/getOrderNum", param)
|
||||||
|
},
|
||||||
|
//物料商城-商品列表
|
||||||
|
goodsList(param) {
|
||||||
|
return req.get("massage/app/IndexCoach/goodsList", param)
|
||||||
|
},
|
||||||
|
//物料商城-分类列表
|
||||||
|
carteList(param) {
|
||||||
|
return req.get("massage/app/IndexCoach/carteList", param)
|
||||||
|
},
|
||||||
|
//物料商城-商品详情
|
||||||
|
goodsInfo(param) {
|
||||||
|
return req.get("massage/app/IndexCoach/goodsInfo", param)
|
||||||
|
},
|
||||||
|
//车费明细列表
|
||||||
|
carMoneyList(param) {
|
||||||
|
return req.get("massage/app/IndexCoach/carMoneyList", param)
|
||||||
|
},
|
||||||
|
//差评申诉 订单列表
|
||||||
|
appealOrder(param) {
|
||||||
|
return req.get("massage/app/IndexCoach/appealOrder", param)
|
||||||
|
},
|
||||||
|
//差评申诉 提交申诉
|
||||||
|
addAppeal(param) {
|
||||||
|
return req.post("massage/app/IndexCoach/addAppeal", param)
|
||||||
|
},
|
||||||
|
//差评申诉 申诉记录列表
|
||||||
|
appealList(param) {
|
||||||
|
return req.get("massage/app/IndexCoach/appealList", param)
|
||||||
|
},
|
||||||
|
//标签列表
|
||||||
|
labelList(param) {
|
||||||
|
return req.get("massage/app/IndexCoach/labelList", param)
|
||||||
|
},
|
||||||
|
//添加用户评价
|
||||||
|
userLabelAdd(param) {
|
||||||
|
return req.post("massage/app/IndexCoach/userLabelAdd", param)
|
||||||
|
},
|
||||||
|
//获取用户当前标签
|
||||||
|
userLabelList(param) {
|
||||||
|
return req.get("massage/app/IndexCoach/userLabelList", param)
|
||||||
|
},
|
||||||
|
//储值返佣列表
|
||||||
|
balanceCommissionList(param) {
|
||||||
|
return req.get("massage/app/IndexCoach/balanceCommissionList", param)
|
||||||
|
},
|
||||||
|
//储值返佣金额统计
|
||||||
|
balanceCommissionData(param) {
|
||||||
|
return req.get("massage/app/IndexCoach/balanceCommissionData", param)
|
||||||
|
},
|
||||||
|
//分成明细
|
||||||
|
coachCommissionList(param) {
|
||||||
|
return req.get("massage/app/IndexCoach/coachCommissionList", param)
|
||||||
|
},
|
||||||
|
//分成明细金额统计
|
||||||
|
coachCommissionData(param) {
|
||||||
|
return req.get("massage/app/IndexCoach/coachCommissionData", param)
|
||||||
|
},
|
||||||
|
//收益详情
|
||||||
|
coachCommissionInfo(param) {
|
||||||
|
return req.get("massage/app/IndexCoach/coachCommissionInfo", param)
|
||||||
|
},
|
||||||
|
//拉黑用户
|
||||||
|
shieldUserAdd(param) {
|
||||||
|
return req.post("massage/app/IndexCoach/shieldUserAdd", param)
|
||||||
|
},
|
||||||
|
//移除拉黑用户
|
||||||
|
shieldUserDel(param) {
|
||||||
|
return req.post("massage/app/IndexCoach/shieldUserDel", param)
|
||||||
|
},
|
||||||
|
//拉黑用户列表
|
||||||
|
shieldCoachList(param) {
|
||||||
|
return req.get("massage/app/IndexCoach/shieldCoachList", param)
|
||||||
|
},
|
||||||
|
// 订单服务录音
|
||||||
|
recordingAdd(param) {
|
||||||
|
return req.post("recording/app/Recording/recordingAdd", param)
|
||||||
|
},
|
||||||
|
// 修改技师白天夜间免费出行距离
|
||||||
|
updateCoachRidingForfree(param) {
|
||||||
|
return req.post("massage/app/IndexCoach/updateCoachRidingForfree", param)
|
||||||
|
},
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
import {
|
||||||
|
req
|
||||||
|
} from '../../utils/req.js';
|
||||||
|
export default {
|
||||||
|
// 用户信息
|
||||||
|
userInfo(param) {
|
||||||
|
return req.get("massage/app/IndexUser/userInfo", param)
|
||||||
|
},
|
||||||
|
// 更新用户信息
|
||||||
|
userUpdate(param) {
|
||||||
|
return req.post("massage/app/IndexUser/userUpdate", param)
|
||||||
|
},
|
||||||
|
// 绑定渠道商
|
||||||
|
bindChannel(param) {
|
||||||
|
return req.post("massage/app/IndexUser/bindChannel", param)
|
||||||
|
},
|
||||||
|
// 注销用户
|
||||||
|
delUserInfo(param) {
|
||||||
|
return req.post("/massage/app/IndexUser/delUserInfo", param)
|
||||||
|
},
|
||||||
|
// 获取手机号
|
||||||
|
reportPhone(param) {
|
||||||
|
return req.post("massage/app/IndexUser/reportPhone", param)
|
||||||
|
},
|
||||||
|
// 验证码
|
||||||
|
sendShortMsg(param) {
|
||||||
|
return req.post("massage/app/IndexUser/sendShortMsg", param)
|
||||||
|
},
|
||||||
|
// 绑定手机号
|
||||||
|
bindUserPhone(param) {
|
||||||
|
return req.post("massage/app/IndexUser/bindUserPhone", param)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,322 @@
|
||||||
|
<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: 'confirm'
|
||||||
|
}],
|
||||||
|
tip: []
|
||||||
|
},
|
||||||
|
'DATA': {
|
||||||
|
image: '/static/img/qs_dingdan.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-car.png',
|
||||||
|
title: '购物车还是空的哦~',
|
||||||
|
button: [{
|
||||||
|
text: '去逛逛',
|
||||||
|
type: 'confirm'
|
||||||
|
}],
|
||||||
|
button: [],
|
||||||
|
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',
|
||||||
|
title: '你还没有可用的卡券哦',
|
||||||
|
button: [],
|
||||||
|
tip: []
|
||||||
|
},
|
||||||
|
'REDUCTION': {
|
||||||
|
image: 'https://lbqny.migugu.com/admin/reduction/nodata.png',
|
||||||
|
title: '您当前没有满减券,请向工作人员索取',
|
||||||
|
button: [],
|
||||||
|
tip: []
|
||||||
|
},
|
||||||
|
'MYTEAM': {
|
||||||
|
image: 'https://lbqny.migugu.com/admin/public/no-coupon.png',
|
||||||
|
title: '没有更多了',
|
||||||
|
button: [],
|
||||||
|
tip: []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
import {
|
||||||
|
mapState,
|
||||||
|
mapActions,
|
||||||
|
} 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;
|
||||||
|
if (Types[type]) {
|
||||||
|
this.pimage = this.image || Types[type].image;
|
||||||
|
this.ptitle = this.title || Types[type].title;
|
||||||
|
this.pbutton = this.button && this.button.length > 0 ? this.button : Types[type].button;
|
||||||
|
this.ptip = this.tip && 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: 520rpx;
|
||||||
|
height: 400rpx;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.abnor-text {
|
||||||
|
margin-top: 30rpx;
|
||||||
|
color: #333;
|
||||||
|
font-size: 32rpx;
|
||||||
|
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>
|
|
@ -0,0 +1,542 @@
|
||||||
|
<template>
|
||||||
|
<view style="width:100%">
|
||||||
|
<block v-if="needAuth">
|
||||||
|
<view @tap.stop="toShowAuth">
|
||||||
|
<slot></slot>
|
||||||
|
</view>
|
||||||
|
</block>
|
||||||
|
<block v-else>
|
||||||
|
<view @tap.stop="go(1)">
|
||||||
|
<slot></slot>
|
||||||
|
</view>
|
||||||
|
</block>
|
||||||
|
|
||||||
|
<uni-popup ref="show_auth_item" :maskClick="false">
|
||||||
|
<view @tap.stop.prevent class="auth-box fill-base flex-column flex-center text-center radius-26">
|
||||||
|
<view class="space-md"></view>
|
||||||
|
<block v-if="pType == 'phone'">
|
||||||
|
<image mode="aspectFill" class="auth-img" :src="`https://lbqny.migugu.com/admin/public/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 === 'phone'">
|
||||||
|
<button open-type="getPhoneNumber" hover-class="btn-hover" @getphonenumber="authPhone"
|
||||||
|
class="clear-btn flex-center auth-btn" :style="{background: `linear-gradient(68deg, ${primaryColor}, ${subColor})`,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="{background: `linear-gradient(68deg, ${primaryColor}, ${subColor})`,color:'white'}">
|
||||||
|
{{btn_text||contentList[pType][1]}}
|
||||||
|
</button>
|
||||||
|
</block>
|
||||||
|
<view @tap.stop="go(pType == 'phone' && !userInfo.phone ? 2 : 1)" class="f-caption c-caption mt-md"
|
||||||
|
v-if="!pMust">{{pType=='userInfo'?'暂不授权':'暂不登录'}}</view>
|
||||||
|
<view class="space-md"></view>
|
||||||
|
</view>
|
||||||
|
</uni-popup>
|
||||||
|
|
||||||
|
|
||||||
|
<uni-popup ref="show_info_item" :maskClick="false">
|
||||||
|
<view @tap.stop.prevent 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-between" style="width:100%">
|
||||||
|
<view class="flex-y-center c-title">
|
||||||
|
<view class="c-warning">*</view>昵称
|
||||||
|
</view>
|
||||||
|
<!-- #ifdef MP-WEIXIN -->
|
||||||
|
<input v-model="infoForm.nickName" type="nickname" maxlength="15"
|
||||||
|
class="f-mini-title c-title text-right" style="width:80%" placeholder-class="c-placeholder"
|
||||||
|
:placeholder="infoRule[0].errorMsg" />
|
||||||
|
<!-- #endif -->
|
||||||
|
<!-- #ifndef MP-WEIXIN -->
|
||||||
|
<input v-model="infoForm.nickName" type="text" maxlength="15"
|
||||||
|
class="f-mini-title c-title text-right" style="width:80%" placeholder-class="c-placeholder"
|
||||||
|
:placeholder="infoRule[0].errorMsg" />
|
||||||
|
<!-- #endif -->
|
||||||
|
</view>
|
||||||
|
<view class="flex-between mt-md pt-md b-1px-t" style="width:100%">
|
||||||
|
<view class="flex-y-center c-title">
|
||||||
|
<view class="c-warning">*</view>头像
|
||||||
|
</view>
|
||||||
|
<!-- #ifdef MP-WEIXIN -->
|
||||||
|
<button open-type="chooseAvatar" @chooseavatar="onChooseAvatar">
|
||||||
|
<image mode="aspectFill" class="avatar radius" :src="infoForm.avatarUrl || '/static/mine/default_user.png'"></image>
|
||||||
|
</button>
|
||||||
|
<!-- #endif -->
|
||||||
|
<!-- #ifndef MP-WEIXIN -->
|
||||||
|
<image @tap.stop="toChooseImg" mode="aspectFill" class="avatar radius" :src="infoForm.avatarUrl">
|
||||||
|
</image>
|
||||||
|
<!-- #endif -->
|
||||||
|
</view>
|
||||||
|
<view class="button">
|
||||||
|
<view @tap.stop="$refs.show_info_item.close()" class="item-child">
|
||||||
|
取消
|
||||||
|
</view>
|
||||||
|
<view @tap.stop="submit('info')" class="item-child"
|
||||||
|
:style="{background: primaryColor,color:'#fff'}">
|
||||||
|
确定
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</uni-popup>
|
||||||
|
|
||||||
|
<uni-popup ref="show_phone_item" :maskClick="false">
|
||||||
|
<view @tap.stop.prevent 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="subRule[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="subRule[1].errorMsg" />
|
||||||
|
</view>
|
||||||
|
<view class="button">
|
||||||
|
<view @tap.stop="go(3)" class="item-child">
|
||||||
|
取消
|
||||||
|
</view>
|
||||||
|
<view @tap.stop="submit('sub')" 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 ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
haveGo: {
|
||||||
|
type: Boolean,
|
||||||
|
default () {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
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: ''
|
||||||
|
},
|
||||||
|
subRule: [{
|
||||||
|
name: "phone",
|
||||||
|
checkType: "isMobile",
|
||||||
|
errorMsg: "请输入手机号",
|
||||||
|
regText: "手机号"
|
||||||
|
}, {
|
||||||
|
name: "short_code",
|
||||||
|
checkType: "isNotNull",
|
||||||
|
errorMsg: "请输入短信验证码"
|
||||||
|
}],
|
||||||
|
infoForm: {
|
||||||
|
nickName: '',
|
||||||
|
avatarUrl: ''
|
||||||
|
},
|
||||||
|
infoRule: [{
|
||||||
|
name: "nickName",
|
||||||
|
checkType: "isNotNull",
|
||||||
|
errorMsg: "请输入用户昵称",
|
||||||
|
regType: 2
|
||||||
|
}, {
|
||||||
|
name: "avatarUrl",
|
||||||
|
checkType: "isNotNull",
|
||||||
|
errorMsg: "请上传用户头像"
|
||||||
|
}],
|
||||||
|
lockTap: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
...mapActions(['getUserInfo', 'getMineInfo', 'getAuthUserProfile', 'getAuthPhone', ]),
|
||||||
|
...mapMutations(['updateConfigItem', 'updateUserItem']),
|
||||||
|
init() {
|
||||||
|
let {
|
||||||
|
type,
|
||||||
|
must,
|
||||||
|
showAuth
|
||||||
|
} = this
|
||||||
|
this.$set(this, 'pType', type)
|
||||||
|
this.$set(this, 'pMust', must)
|
||||||
|
if (!showAuth) return
|
||||||
|
let refs_key = type === 'userInfo' ? 'show_info_item' : 'show_auth_item'
|
||||||
|
this.$refs[refs_key].open()
|
||||||
|
},
|
||||||
|
toShowAuth() {
|
||||||
|
let {
|
||||||
|
id: uid = 0,
|
||||||
|
phone = '',
|
||||||
|
} = this.userInfo
|
||||||
|
if (!uid) {
|
||||||
|
this.updateUserItem({
|
||||||
|
key: 'loginPage',
|
||||||
|
val: `/pages/mine?type=1`
|
||||||
|
})
|
||||||
|
this.$util.goUrl({
|
||||||
|
url: `/pages/login`
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.infoForm = this.$util.pick(this.userInfo, ['nickName',
|
||||||
|
'avatarUrl'
|
||||||
|
])
|
||||||
|
let type = !phone ? 'phone' : 'userInfo'
|
||||||
|
this.$set(this, 'pType', type)
|
||||||
|
let refs_key = 'show_info_item'
|
||||||
|
if (!phone) {
|
||||||
|
// #ifdef MP-WEIXIN
|
||||||
|
refs_key = 'show_auth_item'
|
||||||
|
// #endif
|
||||||
|
// #ifndef MP-WEIXIN
|
||||||
|
if (this.haveGo) {
|
||||||
|
refs_key = 'show_phone_item'
|
||||||
|
let {
|
||||||
|
short_code_status = 0
|
||||||
|
} = this.configInfo
|
||||||
|
if (!short_code_status) {
|
||||||
|
this.go(1)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
}
|
||||||
|
this.$refs[refs_key].open()
|
||||||
|
},
|
||||||
|
// 授权手机号
|
||||||
|
async authPhone(e) {
|
||||||
|
let {
|
||||||
|
pMust
|
||||||
|
} = this
|
||||||
|
let phone = await this.getAuthPhone({
|
||||||
|
e,
|
||||||
|
})
|
||||||
|
if (!phone) {
|
||||||
|
this.go(pMust ? 2 : 1)
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
let {
|
||||||
|
nickName = '',
|
||||||
|
} = this.userInfo
|
||||||
|
if (nickName) {
|
||||||
|
this.go(1)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.$set(this, 'pType', 'userInfo')
|
||||||
|
this.$set(this, 'pMust', this.userMust)
|
||||||
|
if (!this.pMust) return
|
||||||
|
this.$refs.show_info_item.open()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
go(type = 1) {
|
||||||
|
this.lockTap = false
|
||||||
|
this.$emit(type == 1 ? 'go' : 'hide')
|
||||||
|
let refs_key = type == 3 ? 'show_phone_item' : type == 4 ? 'show_info_item' : 'show_auth_item'
|
||||||
|
let {
|
||||||
|
id: uid = 0
|
||||||
|
} = this.userInfo
|
||||||
|
if (uid) {
|
||||||
|
this.$refs[refs_key].close();
|
||||||
|
}
|
||||||
|
if (type != 3) return
|
||||||
|
this.toResetItem('sub')
|
||||||
|
},
|
||||||
|
// 重置数据
|
||||||
|
toResetItem(type) {
|
||||||
|
if (type == 'sub') {
|
||||||
|
this.timer && clearTimeout(this.timer)
|
||||||
|
this.authTime = 0
|
||||||
|
this.subForm = {
|
||||||
|
phone: '',
|
||||||
|
short_code: ''
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.infoForm = this.$util.pick(this.userInfo, ['nickName',
|
||||||
|
'avatarUrl'
|
||||||
|
])
|
||||||
|
},
|
||||||
|
//表单验证
|
||||||
|
validate(param, ruleType, is_send = false) {
|
||||||
|
let validate = new this.$util.Validate();
|
||||||
|
this[`${ruleType}Rule`].map(item => {
|
||||||
|
let {
|
||||||
|
name,
|
||||||
|
} = item
|
||||||
|
if (ruleType == 'sub' && 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
|
||||||
|
}, 'sub', 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) {
|
||||||
|
clearInterval(this.timer)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
time--
|
||||||
|
this.authTime = time
|
||||||
|
}, 1000)
|
||||||
|
} catch (e) {
|
||||||
|
setTimeout(() => {
|
||||||
|
this.lockTap = false
|
||||||
|
this.$util.hideAll()
|
||||||
|
}, 2000)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 获取头像
|
||||||
|
onChooseAvatar(e) {
|
||||||
|
let {
|
||||||
|
avatarUrl
|
||||||
|
} = e.detail
|
||||||
|
this.infoForm.avatarUrl = avatarUrl
|
||||||
|
},
|
||||||
|
async toChooseImg() {
|
||||||
|
let param = {
|
||||||
|
count: 1,
|
||||||
|
sizeType: ['compressed'],
|
||||||
|
sourceType: ['album'],
|
||||||
|
}
|
||||||
|
let [res_upload, res_info] = await uni.chooseImage(param)
|
||||||
|
if (res_upload) return
|
||||||
|
let {
|
||||||
|
size = 0,
|
||||||
|
tempFiles,
|
||||||
|
tempFilePath = ''
|
||||||
|
} = res_info
|
||||||
|
// 格式化图片参数
|
||||||
|
this.$util.showLoading({
|
||||||
|
title: "上传中"
|
||||||
|
})
|
||||||
|
let {
|
||||||
|
attachment_path: path
|
||||||
|
} = await this.$api.base.uploadFile({
|
||||||
|
filePath: tempFiles[0].path,
|
||||||
|
formData: {
|
||||||
|
type: 'picture'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this.infoForm.avatarUrl = path
|
||||||
|
this.$util.hideAll()
|
||||||
|
},
|
||||||
|
// sub 授权手机号,info 用户信息
|
||||||
|
async submit(formType) {
|
||||||
|
let param = this.$util.deepCopy(this[`${formType}Form`])
|
||||||
|
let msg = this.validate(param, formType);
|
||||||
|
if (msg) {
|
||||||
|
this.$util.showToast({
|
||||||
|
title: msg
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (formType == 'sub' && param.short_code.length != 6) {
|
||||||
|
this.$util.showToast({
|
||||||
|
title: `请输入6位数短信验证码`
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (formType == 'info' && (param.avatarUrl.includes('wxfile://') || param.avatarUrl.includes(
|
||||||
|
'//tmp/'))) {
|
||||||
|
let {
|
||||||
|
attachment_path: path
|
||||||
|
} = await this.$api.base.uploadFile({
|
||||||
|
filePath: param.avatarUrl,
|
||||||
|
formData: {
|
||||||
|
type: 'picture'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
param.avatarUrl = path
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.lockTap) return
|
||||||
|
this.lockTap = true
|
||||||
|
this.$util.showLoading()
|
||||||
|
let methodModel = formType == 'sub' ? 'bindUserPhone' : 'userUpdate'
|
||||||
|
let refs_key = formType == 'sub' ? 'show_phone_item' : 'show_info_item'
|
||||||
|
try {
|
||||||
|
await this.$api.user[methodModel](param)
|
||||||
|
this.$util.hideAll()
|
||||||
|
this.lockTap = false
|
||||||
|
this.$refs[refs_key].close()
|
||||||
|
this.toResetItem(formType)
|
||||||
|
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: 30rpx;
|
||||||
|
|
||||||
|
.auth-img {
|
||||||
|
width: 322rpx;
|
||||||
|
height: 341rpx;
|
||||||
|
/* background: #f4f6f8; */
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-btn {
|
||||||
|
width: 367rpx;
|
||||||
|
height: 90rpx;
|
||||||
|
border-radius: 90rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth-info {
|
||||||
|
width: 80rpx;
|
||||||
|
height: 80rpx;
|
||||||
|
background: #f4f6f8;
|
||||||
|
border-radius: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.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>
|
|
@ -0,0 +1,285 @@
|
||||||
|
<template>
|
||||||
|
<!-- 轮播图广告 -->
|
||||||
|
<!-- :current="activeIndex" -->
|
||||||
|
<view class='swiper-box' :style='{margin:`0 ${margin}rpx`}' v-if="showSwiper">
|
||||||
|
<swiper class="swiper-ad fill-base" :indicator-dots="false" :autoplay="playVideo ? false : 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:height+'rpx'}" easing-function="linear">
|
||||||
|
<swiper-item v-for="(item,index) in list" :key="index" :style="{borderRadius:borderRadius+'rpx'}">
|
||||||
|
<view class='img-box' @tap.stop='changeItem(item)'>
|
||||||
|
<block v-if="item.jump_type == 'video'">
|
||||||
|
<block v-if="!playVideo">
|
||||||
|
<view @tap.stop="playCurrent" class="play-video-info flex-center c-base abs">
|
||||||
|
<view class="play-video flex-center c-base radius">
|
||||||
|
<i class="iconfont icon-play-video"></i>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<image mode="aspectFill" :src='item.img' class="swiper-ad__img radius-16"
|
||||||
|
:style="{borderRadius:borderRadius+'rpx'}" />
|
||||||
|
</block>
|
||||||
|
<view class="video-box" v-if="playVideo">
|
||||||
|
<video :id="`video_id`" class="my-video" object-fit="contain" :loop="false"
|
||||||
|
enable-play-gesture :enable-progress-gesture="false" :src="item.jump_url"
|
||||||
|
:autoplay="playVideo" @play="onPlay" @pause="onPause" @ended="onEnded"
|
||||||
|
@timeupdate="onTimeUpdate" @waiting="onWaiting" @progress="onProgress"
|
||||||
|
@loadedmetadata="onLoadedMetaData"></video>
|
||||||
|
</view>
|
||||||
|
</block>
|
||||||
|
<image mode="aspectFill" :src='item.img || item' class="swiper-ad__img"
|
||||||
|
:style="{borderRadius:borderRadius+'rpx'}" v-else />
|
||||||
|
</view>
|
||||||
|
</swiper-item>
|
||||||
|
</swiper>
|
||||||
|
<view class='numbers' v-if="list.length>1&&indicatorType=='number' && !playVideo"
|
||||||
|
: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,bottom:`${dotBottom}rpx`}">
|
||||||
|
<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 []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
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
|
||||||
|
}
|
||||||
|
},
|
||||||
|
dotBottom: {
|
||||||
|
type: Number,
|
||||||
|
default () {
|
||||||
|
return 20
|
||||||
|
}
|
||||||
|
},
|
||||||
|
margin: {
|
||||||
|
type: Number,
|
||||||
|
default () {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
borderRadius: {
|
||||||
|
type: Number,
|
||||||
|
default () {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.videoContexts = uni.createVideoContext(`video_id`, this)
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
showSwiper: true,
|
||||||
|
activeIndex: 0,
|
||||||
|
videoContexts: {},
|
||||||
|
playVideo: false,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
list(newlist, oldlist) {
|
||||||
|
this.activeIndex = 0
|
||||||
|
this.showSwiper = false;
|
||||||
|
setTimeout(() => {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.showSwiper = true
|
||||||
|
});
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: mapState({
|
||||||
|
configInfo: state => state.config.configInfo,
|
||||||
|
commonOptions: state => state.user.commonOptions,
|
||||||
|
}),
|
||||||
|
methods: {
|
||||||
|
handerChange: function(e) {
|
||||||
|
let {
|
||||||
|
current
|
||||||
|
} = e.detail
|
||||||
|
this.activeIndex = current
|
||||||
|
let ind = this.list.findIndex(item => {
|
||||||
|
return item.jump_type == 'video'
|
||||||
|
})
|
||||||
|
if (ind == -1) return
|
||||||
|
if (current == ind + 1 || current == this.list.length - 1) {
|
||||||
|
this.videoContexts.pause()
|
||||||
|
this.playVideo = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
changeItem(item) {
|
||||||
|
let {
|
||||||
|
jump_type = ''
|
||||||
|
} = item
|
||||||
|
if (jump_type == 'video') return
|
||||||
|
this.$emit("change", item)
|
||||||
|
},
|
||||||
|
playCurrent() {
|
||||||
|
this.videoContexts.play()
|
||||||
|
this.playVideo = true
|
||||||
|
},
|
||||||
|
onPlay(e) {},
|
||||||
|
onPause(e) {},
|
||||||
|
onEnded(e) {},
|
||||||
|
onError(e) {},
|
||||||
|
onTimeUpdate(e) {},
|
||||||
|
onWaiting(e) {},
|
||||||
|
onProgress(e) {},
|
||||||
|
onLoadedMetaData(e) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.swiper-box {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.img-box {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
.swiper-ad__img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.play-video-info {
|
||||||
|
top: 0rpx;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
z-index: 9;
|
||||||
|
|
||||||
|
.play-video {
|
||||||
|
width: 66rpx;
|
||||||
|
height: 66rpx;
|
||||||
|
background: rgba(2, 2, 2, 0.5);
|
||||||
|
|
||||||
|
.iconfont {
|
||||||
|
font-size: 28rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-box {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
.my-video {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.dots {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 20rpx;
|
||||||
|
text-align: right;
|
||||||
|
width: 100%;
|
||||||
|
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(-70rpx);
|
||||||
|
padding: 0 15rpx;
|
||||||
|
|
||||||
|
.number {
|
||||||
|
display: inline-block;
|
||||||
|
width: 66rpx;
|
||||||
|
line-height: 40rpx;
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #fff;
|
||||||
|
text-align: center;
|
||||||
|
border-radius: 33rpx;
|
||||||
|
background: rgba(0, 0, 0, 0.4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,337 @@
|
||||||
|
<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" class="column-img radius" :src="item.cover" v-if="item.cover"></image>
|
||||||
|
<view v-else class="column-no-img"
|
||||||
|
:style="{background:item.icon?primaryColor:colorList[index%4],borderRadius:'50%',margin:'0rpx auto'}">
|
||||||
|
<i class="iconfont" :class="item.icon" v-if="item.icon"></i>
|
||||||
|
<view v-else>{{getFirstText(item.title)}}</view>
|
||||||
|
</view>
|
||||||
|
<view class='column-text'>{{item.title}}</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,width:index==current?'20rpx':'8rpx'}">
|
||||||
|
</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" 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>
|
||||||
|
import {
|
||||||
|
mapState,
|
||||||
|
mapActions,
|
||||||
|
mapMutations
|
||||||
|
} from "vuex"
|
||||||
|
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"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapState({
|
||||||
|
primaryColor: state => state.config.configInfo.primaryColor,
|
||||||
|
subColor: state => state.config.configInfo.subColor,
|
||||||
|
}),
|
||||||
|
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: 94rpx;
|
||||||
|
height: 94rpx;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.column-no-img {
|
||||||
|
width: 94rpx;
|
||||||
|
height: 94rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 36rpx;
|
||||||
|
color: #fff;
|
||||||
|
|
||||||
|
.iconfont {
|
||||||
|
font-size: 58rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.column-text {
|
||||||
|
margin-top: 10rpx;
|
||||||
|
text-align: center;
|
||||||
|
color: #484848;
|
||||||
|
width: 100%;
|
||||||
|
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: 94rpx;
|
||||||
|
height: 94rpx;
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.column-text {
|
||||||
|
margin-top: 10rpx;
|
||||||
|
text-align: center;
|
||||||
|
color: #484848;
|
||||||
|
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: 8rpx;
|
||||||
|
width: 8rpx;
|
||||||
|
background: #E5E5E5;
|
||||||
|
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>
|
|
@ -0,0 +1,161 @@
|
||||||
|
<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" class="image" :class="imgSize" :src="info.image" v-if="info.image"></image>
|
||||||
|
<view class="name" 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 = {
|
||||||
|
'REFUSE_ORDER': {
|
||||||
|
title: '拒绝接单',
|
||||||
|
desc: '请确认是否拒绝接单',
|
||||||
|
text: '确认拒绝'
|
||||||
|
},
|
||||||
|
'CANCEL_ORDER': {
|
||||||
|
title: '取消订单',
|
||||||
|
desc: '请确认是否取消订单,取消后将无法恢复',
|
||||||
|
text: '确认取消'
|
||||||
|
},
|
||||||
|
'DELETE_ORDER': {
|
||||||
|
title: '删除订单',
|
||||||
|
desc: '请确认是否删除订单,删除后将无法恢复',
|
||||||
|
text: '确认删除'
|
||||||
|
},
|
||||||
|
'CANCEL_REFUND_ORDER': {
|
||||||
|
title: '取消退款',
|
||||||
|
desc: '请确认是否取消退款',
|
||||||
|
text: '确认取消'
|
||||||
|
},
|
||||||
|
'NO_PASS_REFUND': {
|
||||||
|
title: '拒绝退款',
|
||||||
|
desc: '请确认是否拒绝退款',
|
||||||
|
text: '确认拒绝'
|
||||||
|
},
|
||||||
|
'HX_CODE': {
|
||||||
|
title: '核销码',
|
||||||
|
desc: '请出示二维码给核销人员',
|
||||||
|
},
|
||||||
|
'HX_ORDER': {
|
||||||
|
title: '核销订单',
|
||||||
|
desc: '请确认是否核销订单',
|
||||||
|
text: '确认核销'
|
||||||
|
},
|
||||||
|
}
|
||||||
|
import {
|
||||||
|
mapState,
|
||||||
|
mapMutations
|
||||||
|
} 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 ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
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 (!Types[type].text) return
|
||||||
|
this.pbutton[1].title = 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>
|
|
@ -0,0 +1,98 @@
|
||||||
|
<template>
|
||||||
|
<view class="content" :style="{background: bgColor}">
|
||||||
|
<block v-for="(item,index) in text" :key="index">
|
||||||
|
<!-- 无间隔的按钮 -->
|
||||||
|
<auth @tap.stop.prevent :needAuth="item.isAuth && (userInfo && (!userInfo.phone || !userInfo.nickName))"
|
||||||
|
:must="true" :type="!userInfo.phone ? 'phone' : 'userInfo'" @go="confirm(item)" :style="{
|
||||||
|
width:(100/ text.length)+ '%'}" v-if="classType === 1">
|
||||||
|
<view class="bottom-view" :style="{
|
||||||
|
margin:text.length==1?'0 30rpx':index==0?'0 0 0 30rpx':'0 30rpx 0 0',
|
||||||
|
borderRadius:text.length==1?'88rpx':index==0?'88rpx 0 0 88rpx':'0 88rpx 88rpx 0',
|
||||||
|
background: item.type == 'confirm'? `linear-gradient(68deg, ${primaryColor}, ${subColor})` : subColor}">
|
||||||
|
{{ item.text }}
|
||||||
|
</view>
|
||||||
|
</auth>
|
||||||
|
<!-- 有间隔的圆弧形按钮 -->
|
||||||
|
<auth @tap.stop.prevent :needAuth="item.isAuth && (userInfo && (!userInfo.phone || !userInfo.nickName))"
|
||||||
|
:must="true" :type="!userInfo.phone ? 'phone' : 'userInfo'" @go="confirm(item)" :style="{
|
||||||
|
width:text.length==2 ? index==0 ? '390rpx' : '360rpx' : (100/ text.length) + '%'}" v-if="classType === 2">
|
||||||
|
<view class="bottom-view" :style="{
|
||||||
|
margin:text.length==1?'0 30rpx':index==0?'0 30rpx 0 30rpx':'0 30rpx 0 0',
|
||||||
|
borderRadius:'88rpx',
|
||||||
|
background: item.type == 'confirm'? `linear-gradient(68deg, ${primaryColor}, ${subColor})` : '',
|
||||||
|
color: item.type === 'confirm' ? '#fff' : '#000',
|
||||||
|
transform: 'rotateZ(360deg)',
|
||||||
|
border: item.type == 'confirm'? `1rpx solid ${primaryColor}` : '1rpx solid #C7C7C7'}">
|
||||||
|
{{ item.text }}
|
||||||
|
</view>
|
||||||
|
</auth>
|
||||||
|
</block>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
mapState,
|
||||||
|
mapMutations
|
||||||
|
} from "vuex"
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
text: {
|
||||||
|
type: Array,
|
||||||
|
default () {
|
||||||
|
return [{
|
||||||
|
text: '保存',
|
||||||
|
type: 'confirm'
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
bgColor: {
|
||||||
|
type: String,
|
||||||
|
default () {
|
||||||
|
return '#F8F8F8'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
classType: {
|
||||||
|
type: Number,
|
||||||
|
default () {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: mapState({
|
||||||
|
primaryColor: state => state.config.configInfo.primaryColor,
|
||||||
|
subColor: state => state.config.configInfo.subColor,
|
||||||
|
userInfo: state => state.user.userInfo,
|
||||||
|
}),
|
||||||
|
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>
|
|
@ -0,0 +1,86 @@
|
||||||
|
<template>
|
||||||
|
<view>
|
||||||
|
<view class="ui-fixed" :class="{'fixed-top':position=='top','fixed-bottom':position=='bottom'}"
|
||||||
|
:style="{top:position=='top'?`${top}px`:`` , zIndex: zIndex}">
|
||||||
|
<slot></slot>
|
||||||
|
</view>
|
||||||
|
<view :style="{height:height+'px'}" v-if="position=='top'"></view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'fixed',
|
||||||
|
props: {
|
||||||
|
position: {
|
||||||
|
type: [String],
|
||||||
|
default () {
|
||||||
|
return 'top'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
top: {
|
||||||
|
type: [Number],
|
||||||
|
default () {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
zIndex: {
|
||||||
|
type: [Number],
|
||||||
|
default () {
|
||||||
|
return 999
|
||||||
|
}
|
||||||
|
},
|
||||||
|
initHeight: {
|
||||||
|
type: String || Number,
|
||||||
|
default () {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
height: uni.getSystemInfoSync().windowWidth * 100 / 750
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
setTimeout(() => {
|
||||||
|
this.setHeight();
|
||||||
|
}, 100)
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
initHeight(newVal, oldval) {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.setHeight()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
setHeight() {
|
||||||
|
var _this = this;
|
||||||
|
var query = uni.createSelectorQuery().in(_this);
|
||||||
|
query.select('.ui-fixed').boundingClientRect(function(res) {
|
||||||
|
_this.height = res.height;
|
||||||
|
_this.$emit('height', res.height)
|
||||||
|
}).exec();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.ui-fixed {
|
||||||
|
position: fixed;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
z-index: 999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fixed-top {
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fixed-bottom {
|
||||||
|
bottom: 0;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -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"]);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
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"]);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,617 @@
|
||||||
|
<!--
|
||||||
|
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;
|
||||||
|
const cache = getApp().parserCache = {};
|
||||||
|
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>
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,441 @@
|
||||||
|
/*
|
||||||
|
将 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()
|
||||||
|
};
|
|
@ -0,0 +1,252 @@
|
||||||
|
/* 配置文件 */
|
||||||
|
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) {
|
||||||
|
let default_style = "max-width: 100% !important;display:block;"
|
||||||
|
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':
|
||||||
|
if (node.name === 'span') {
|
||||||
|
default_style = 'white-space:normal;'
|
||||||
|
}
|
||||||
|
if (node.name === 'p' && (!node.attrs.style || !node.attrs.style.includes('margin-top:'))) {
|
||||||
|
default_style += 'margin-top:10px;'
|
||||||
|
}
|
||||||
|
if (node.attrs.style) {
|
||||||
|
node.attrs.style = node.attrs.style.includes('width:') ? default_style : node.attrs.style +
|
||||||
|
`;${default_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'
|
||||||
|
}
|
||||||
|
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
|
||||||
|
}
|
|
@ -0,0 +1,407 @@
|
||||||
|
<!--
|
||||||
|
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;word-break:normal">
|
||||||
|
<block v-for="(item, index) in nodes" v-bind:key="index">
|
||||||
|
<!-- {{item.name}} {{item}} -->
|
||||||
|
<!--#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;word-break:normal" :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="'word-break:normal;'+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>
|
|
@ -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: #999;
|
||||||
|
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>
|
|
@ -0,0 +1,112 @@
|
||||||
|
<template>
|
||||||
|
<view>
|
||||||
|
<view class="login-info pd-lg flex-center rel" :style="{bottom:`${configInfo.tabbarHeight}px`}" v-if="pShow">
|
||||||
|
<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 {
|
||||||
|
pShow: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
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']),
|
||||||
|
init() {
|
||||||
|
let {
|
||||||
|
isShowLogin
|
||||||
|
} = this
|
||||||
|
this.$set(this, 'pShow', isShowLogin)
|
||||||
|
},
|
||||||
|
toClose() {
|
||||||
|
this.updateUserItem({
|
||||||
|
key: 'isShowLogin',
|
||||||
|
val: false
|
||||||
|
})
|
||||||
|
this.$set(this, 'pShow', false)
|
||||||
|
},
|
||||||
|
toLogin() {
|
||||||
|
let pages = getCurrentPages();
|
||||||
|
let {
|
||||||
|
route
|
||||||
|
} = pages[pages.length - 1]
|
||||||
|
this.updateUserItem({
|
||||||
|
key: 'loginPage',
|
||||||
|
val: `/${route}`
|
||||||
|
})
|
||||||
|
this.$util.goUrl({
|
||||||
|
url: `/pages/login`
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.login-info {
|
||||||
|
position: fixed;
|
||||||
|
left: 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>
|
|
@ -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>
|
|
@ -0,0 +1,176 @@
|
||||||
|
<template>
|
||||||
|
<view>
|
||||||
|
<view class="min-countdown" :class="countdownClass">
|
||||||
|
<rich-text :nodes="time" v-if="type == 1"></rich-text>
|
||||||
|
<view class="flex-y-center" :style="{color:primaryColor}" v-if="type == 2">
|
||||||
|
<view class="count-tag flex-center">{{time.d}}</view>天<view class="count-tag flex-center">{{time.h}}
|
||||||
|
</view>时
|
||||||
|
<view class="count-tag flex-center">{{time.m}}</view>分<view class="count-tag flex-center">{{time.s}}
|
||||||
|
</view>秒
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
mapState,
|
||||||
|
mapActions,
|
||||||
|
mapMutations
|
||||||
|
} 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}秒'
|
||||||
|
},
|
||||||
|
countdownClass: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
bgColor: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
isPlay: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
time: '00:00:00',
|
||||||
|
audioBg: {},
|
||||||
|
playBg: false,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async mounted() {
|
||||||
|
this.getTime()
|
||||||
|
if (this.isPlay && !this.configInfo.id) {
|
||||||
|
await this.getConfigInfo()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: mapState({
|
||||||
|
primaryColor: state => state.config.configInfo.primaryColor,
|
||||||
|
subColor: state => state.config.configInfo.subColor,
|
||||||
|
configInfo: state => state.config.configInfo,
|
||||||
|
isHaveAudio: state => state.user.isHaveAudio,
|
||||||
|
}),
|
||||||
|
methods: {
|
||||||
|
...mapActions(['getConfigInfo', 'toPlayAudio']),
|
||||||
|
...mapMutations(['updateUserItem']),
|
||||||
|
initIndex() {
|
||||||
|
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.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.initIndex()
|
||||||
|
if (this.isPlay && gapTime == 60 * 5) {
|
||||||
|
this.toPlayAudio({
|
||||||
|
key: 'countdown_voice'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (this.isPlay && gapTime == 0) {
|
||||||
|
this.toPlayAudio({
|
||||||
|
key: 'service_end_recording'
|
||||||
|
})
|
||||||
|
this.$emit('end')
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.$emit('callback')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async toInitPlay() {
|
||||||
|
if (!this.configInfo.id) {
|
||||||
|
await this.getConfigInfo()
|
||||||
|
}
|
||||||
|
console.log("======toInitPlay")
|
||||||
|
|
||||||
|
let {
|
||||||
|
countdown_voice
|
||||||
|
} = this.configInfo
|
||||||
|
this.audioBg = uni.createInnerAudioContext();
|
||||||
|
this.audioBg.src = countdown_voice
|
||||||
|
this.audioBg.obeyMuteSwitch = false
|
||||||
|
this.updateUserItem({
|
||||||
|
key: 'isHaveAudio',
|
||||||
|
val: true
|
||||||
|
})
|
||||||
|
console.log(this.audioBg, "=======this.audioBg")
|
||||||
|
|
||||||
|
this.audioBg.onPlay(() => {
|
||||||
|
console.log('onPlay')
|
||||||
|
this.playBg = true
|
||||||
|
})
|
||||||
|
this.audioBg.onStop(() => {
|
||||||
|
console.log('onStop')
|
||||||
|
this.playBg = false
|
||||||
|
})
|
||||||
|
this.audioBg.onError(() => {
|
||||||
|
console.log('onError')
|
||||||
|
this.playBg = false
|
||||||
|
this.audioBg.destroy()
|
||||||
|
})
|
||||||
|
this.audioBg.onEnded(() => {
|
||||||
|
console.log('onEnded')
|
||||||
|
this.playBg = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
toPlay() {
|
||||||
|
console.log("=====toPlay", this.playBg, this.audioBg)
|
||||||
|
if (this.playBg) {
|
||||||
|
this.audioBg.stop()
|
||||||
|
}
|
||||||
|
this.audioBg.play()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.min-countdown {
|
||||||
|
display: inline-flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.count-tag {
|
||||||
|
width: 56rpx;
|
||||||
|
height: 56rpx;
|
||||||
|
margin: 0 10rpx;
|
||||||
|
background: linear-gradient(0deg, #F7D9AD 0%, #FBEACB 100%);
|
||||||
|
border-radius: 8rpx;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,207 @@
|
||||||
|
<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:searchStyleObj[searchStyle],background:frontColor,justifyContent:textAlign,height:height}'>
|
||||||
|
<block v-if="type=='text'">
|
||||||
|
<image src='https://lbqny.migugu.com/admin/public/search.png' class="search-icon"></image>
|
||||||
|
<view class='ml-md placeholder'>{{placeholder}}</view>
|
||||||
|
</block>
|
||||||
|
<block v-if="type=='input'">
|
||||||
|
<view class="flex-y-center flex-1">
|
||||||
|
<image src='https://lbqny.migugu.com/admin/public/search.png' class="search-icon"></image>
|
||||||
|
<input type='text' class="flex-1 ml-md mr-md f-paragraph c-title" :disabled="disabled"
|
||||||
|
:placeholder='placeholder' placeholder-class='f-paragraph c-caption' 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="confirmSearch">搜索</view>
|
||||||
|
</block>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
mapState,
|
||||||
|
mapMutations
|
||||||
|
} 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
|
||||||
|
}
|
||||||
|
},
|
||||||
|
height: {
|
||||||
|
type: String,
|
||||||
|
default () {
|
||||||
|
return '64rpx'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
backgroundColor: {
|
||||||
|
type: String,
|
||||||
|
default () {
|
||||||
|
return '#fff'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
frontColor: {
|
||||||
|
type: String,
|
||||||
|
default () {
|
||||||
|
return '#f4f6f8'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
autofocus: {
|
||||||
|
type: Boolean,
|
||||||
|
default () {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
disabled: {
|
||||||
|
type: Boolean,
|
||||||
|
default () {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
focus: {
|
||||||
|
type: Boolean,
|
||||||
|
default () {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
keyword: {
|
||||||
|
type: String,
|
||||||
|
default () {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
confirmSearch: {
|
||||||
|
type: Boolean,
|
||||||
|
default () {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
searchStyleObj: {
|
||||||
|
square: '0rpx',
|
||||||
|
radius: '10rpx',
|
||||||
|
circle: '30rpx'
|
||||||
|
},
|
||||||
|
text: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
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%;
|
||||||
|
background: #ffffff;
|
||||||
|
border-radius: 30rpx;
|
||||||
|
padding: 0 0 0 25rpx;
|
||||||
|
line-height: 1;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #888;
|
||||||
|
}
|
||||||
|
|
||||||
|
.placeholder {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-item-btn {
|
||||||
|
width: 110rpx;
|
||||||
|
height: 64rpx;
|
||||||
|
font-size: 26rpx;
|
||||||
|
font-weight: 400;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-btn {
|
||||||
|
padding: 0 20rpx 0 40rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-icon {
|
||||||
|
width: 30rpx;
|
||||||
|
height: 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.flex-1 {
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-md {
|
||||||
|
width: 40rpx;
|
||||||
|
height: 40rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ml-md {
|
||||||
|
margin-left: 16rpx;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,180 @@
|
||||||
|
<template>
|
||||||
|
<view class="service-list-item">
|
||||||
|
<view @tap.stop="goDetail" class="list-item flex-warp">
|
||||||
|
<!-- #ifdef H5 -->
|
||||||
|
<view class="cover radius-16">
|
||||||
|
<view class="h5-image cover radius-16" :style="{ backgroundImage : `url('${info.cover}')`}">
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<!-- #endif -->
|
||||||
|
<!-- #ifndef H5 -->
|
||||||
|
<image mode="aspectFill" lazy-load class="cover radius-16" :src="info.cover"></image>
|
||||||
|
<!-- #endif -->
|
||||||
|
<view class="flex-1 ml-md" :style="{maxWidth:maxWidth}">
|
||||||
|
<view class="flex-between">
|
||||||
|
<view class="f-title c-title text-bold max-270 ellipsis">{{ info.title }}</view>
|
||||||
|
<view class="f-caption c-caption">超{{ info.total_sale }}人选择</view>
|
||||||
|
</view>
|
||||||
|
<view class="f-caption c-caption mt-sm mb-sm ellipsis" style="height: 36rpx;">{{ info.sub_title || '' }}
|
||||||
|
</view>
|
||||||
|
<view class="f-caption c-caption" v-if="info.material_price*1>0">物料费:¥{{info.material_price}}</view>
|
||||||
|
<view class="flex-between">
|
||||||
|
<view class="flex-y-center f-desc c-caption max-350 ellipsis">
|
||||||
|
<view class="flex-y-baseline f-icontext c-orange text-bold mr-sm">
|
||||||
|
<b class="f-caption c-orange">¥</b>
|
||||||
|
<view class="f-md-title">
|
||||||
|
{{ info.price }}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="text-delete" v-if="info.init_price">¥{{ info.init_price }}</view>
|
||||||
|
<view class="servefc ml-md">
|
||||||
|
<i class="iconfont icon-shijian" :style="{ color: primaryColor }"></i>
|
||||||
|
<span class="f-caption c-title ml-sm">{{ info.time_long }}分钟</span>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<auth @tap.stop.prevent :needAuth="userInfo && (!userInfo.phone || !userInfo.nickName)" :must="true"
|
||||||
|
:type="!userInfo.phone ? 'phone' : 'userInfo'" @go="toChoose" style="width:190rpx">
|
||||||
|
<view class="flex-between">
|
||||||
|
<view></view>
|
||||||
|
<view class="item-btn flex-center f-caption c-base" :style="{background: `linear-gradient(68deg, ${primaryColor}, ${subColor})`}">
|
||||||
|
{{ from == 'technician-info' ? `立即预约` : `选择${$t('action.attendantName')}`}}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</auth>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
mapState,
|
||||||
|
mapMutations
|
||||||
|
} from "vuex"
|
||||||
|
export default {
|
||||||
|
components: {},
|
||||||
|
props: {
|
||||||
|
from: {
|
||||||
|
type: String,
|
||||||
|
default () {
|
||||||
|
return 'list'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
sid: {
|
||||||
|
type: Number,
|
||||||
|
default () {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
info: {
|
||||||
|
type: Object,
|
||||||
|
default () {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
maxWidth: {
|
||||||
|
type: String,
|
||||||
|
default () {
|
||||||
|
return '490rpx'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
textType: {
|
||||||
|
1: '可服务',
|
||||||
|
2: '服务中',
|
||||||
|
3: '可预约',
|
||||||
|
4: '不可预约'
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: mapState({
|
||||||
|
primaryColor: state => state.config.configInfo.primaryColor,
|
||||||
|
subColor: state => state.config.configInfo.subColor,
|
||||||
|
userInfo: state => state.user.userInfo,
|
||||||
|
}),
|
||||||
|
methods: {
|
||||||
|
// 详情
|
||||||
|
goDetail() {
|
||||||
|
let {
|
||||||
|
id
|
||||||
|
} = this.info
|
||||||
|
let {
|
||||||
|
sid: store_id = 0
|
||||||
|
} = this
|
||||||
|
let url = `/user/pages/detail?id=${id}&store_id=${store_id}`
|
||||||
|
this.$util.goUrl({
|
||||||
|
url
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 选择技-师
|
||||||
|
toChoose() {
|
||||||
|
let {
|
||||||
|
from
|
||||||
|
} = this
|
||||||
|
if (from == 'technician-info') {
|
||||||
|
this.$emit('order')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let {
|
||||||
|
id
|
||||||
|
} = this.info
|
||||||
|
let {
|
||||||
|
sid: store_id = 0
|
||||||
|
} = this
|
||||||
|
let url = `/user/pages/choose-technician?id=${id}&store_id=${store_id}`
|
||||||
|
this.$util.goUrl({
|
||||||
|
url
|
||||||
|
})
|
||||||
|
},
|
||||||
|
toEmit(key) {
|
||||||
|
this.$emit(key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.service-list-item {
|
||||||
|
.list-item {
|
||||||
|
.cover {
|
||||||
|
width: 180rpx;
|
||||||
|
height: 180rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.time-long {
|
||||||
|
min-width: 72rpx;
|
||||||
|
height: 30rpx;
|
||||||
|
padding: 0 5rpx;
|
||||||
|
background: linear-gradient(270deg, #4C545A 0%, #282B34 100%);
|
||||||
|
border-radius: 4rpx;
|
||||||
|
font-size: 20rpx;
|
||||||
|
color: #FFEEB9;
|
||||||
|
margin-right: 16rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.f-icontext {
|
||||||
|
font-size: 18rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-delete {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #B9B9B9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-btn {
|
||||||
|
min-width: 150rpx;
|
||||||
|
height: 52rpx;
|
||||||
|
padding: 0 10rpx;
|
||||||
|
border-radius: 100rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.servefc{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,233 @@
|
||||||
|
<template>
|
||||||
|
<view class="rel">
|
||||||
|
<view class="abs" style="z-index: 99;" :style="{top:statusBarHeight + 'px'}">
|
||||||
|
<!-- #ifdef MP-WEIXIN -->
|
||||||
|
<view @tap.stop="goBack" class="flex-center circle home-return-btn" v-if="!isShare"
|
||||||
|
:class="[{'back-user-ios': configInfo.isIos},{'back-user-android': !configInfo.isIos}]">
|
||||||
|
<view class="iconfont icon-left c-base text-bold" style="font-size: 40rpx;"></view>
|
||||||
|
</view>
|
||||||
|
<!-- #endif -->
|
||||||
|
<!-- #ifdef H5 -->
|
||||||
|
<view @tap="$util.goUrl({url:`/pages/service`,openType:`reLaunch`})"
|
||||||
|
:class="[{'back-user-ios': configInfo.isIos},{'back-user-android': !configInfo.isIos}]" v-if="isShare">
|
||||||
|
<view class="iconshouye iconfont"></view>
|
||||||
|
<view class="back-user_text">回到首页</view>
|
||||||
|
</view>
|
||||||
|
<!-- #endif -->
|
||||||
|
</view>
|
||||||
|
<view class='banner'>
|
||||||
|
<swiper class='banner-swiper' :style="{background: playVideo && !detail.video_vid ? '#000':'#f4f6f8'}"
|
||||||
|
@change='handerSwiperChange' @transition="swiperTransition" :autoplay="playVideo ? false : true"
|
||||||
|
:current="current">
|
||||||
|
<swiper-item v-for="(item,index) in detail.images" :key="index" @tap='handerBannerClick(index)'>
|
||||||
|
<block v-if="index == 0 && detail.video_url">
|
||||||
|
<block v-if="!playVideo">
|
||||||
|
<view @tap.stop="playCurrent"
|
||||||
|
class="banner-swiper c-base iconfont icontushucxuanzebofangtiaozhuan abs flex-center"
|
||||||
|
style="top: 0rpx;font-size: 80rpx;z-index: 9;"></view>
|
||||||
|
<image mode="aspectFill" class='banner-img' :src='item'></image>
|
||||||
|
</block>
|
||||||
|
<!-- #ifdef MP-WEIXIN -->
|
||||||
|
<txv-video :vid="detail.video_vid" :playerid="detail.video_vid" width="100%" height="100%"
|
||||||
|
:controls="true" :autoplay="true" :isHiddenStop="true" v-if="playVideo && detail.video_vid">
|
||||||
|
</txv-video>
|
||||||
|
<!-- #endif -->
|
||||||
|
<view class="video-box" v-if="playVideo && !detail.video_vid">
|
||||||
|
<video :id="`video_id`" class="my-video" :loop="false" enable-play-gesture
|
||||||
|
:enable-progress-gesture="false" :src="detail.video_url" :autoplay="playVideo"
|
||||||
|
@play="onPlay" @pause="onPause" @ended="onEnded" @timeupdate="onTimeUpdate"
|
||||||
|
@waiting="onWaiting" @progress="onProgress" @loadedmetadata="onLoadedMetaData"></video>
|
||||||
|
</view>
|
||||||
|
</block>
|
||||||
|
<image mode="aspectFill" class='banner-img' :src='item' v-else></image>
|
||||||
|
</swiper-item>
|
||||||
|
</swiper>
|
||||||
|
<view class='banner-tagitem banner-tagitem_count' v-if="!playVideo && detail.images.length">
|
||||||
|
{{current+1}}/{{detail.images.length}}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
mapState
|
||||||
|
} from "vuex"
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
detail: {
|
||||||
|
type: Object,
|
||||||
|
default () {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
isShare: {
|
||||||
|
type: Boolean,
|
||||||
|
default () {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setCurrent: {
|
||||||
|
type: Number,
|
||||||
|
default () {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
'detail.images'(newValue, oldValue) {
|
||||||
|
this.current = 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
statusBarHeight: uni.getSystemInfoSync().statusBarHeight,
|
||||||
|
videoContexts: {},
|
||||||
|
playVideo: false,
|
||||||
|
current: 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: mapState({
|
||||||
|
primaryColor: state => state.config.configInfo.primaryColor,
|
||||||
|
subColor: state => state.config.configInfo.subColor,
|
||||||
|
configInfo: state => state.config.configInfo,
|
||||||
|
userInfo: state => state.user.userInfo,
|
||||||
|
}),
|
||||||
|
created() {
|
||||||
|
this.videoContexts = uni.createVideoContext(`video_id`, this)
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handerSwiperChange(e) {
|
||||||
|
let {
|
||||||
|
current,
|
||||||
|
} = e.detail
|
||||||
|
this.current = current;
|
||||||
|
this.videoContexts.pause()
|
||||||
|
this.playVideo = false;
|
||||||
|
},
|
||||||
|
swiperTransition(e) {
|
||||||
|
// // #ifdef H5
|
||||||
|
// if(this.playVideo && this.current == 0 && e.detail.dx < 30){
|
||||||
|
// this.current = 1
|
||||||
|
// this.videoContexts.pause()
|
||||||
|
// this.playVideo = false;
|
||||||
|
// console.log(e,"======swiperTransition")
|
||||||
|
// }
|
||||||
|
// // #endif
|
||||||
|
},
|
||||||
|
playCurrent() {
|
||||||
|
this.videoContexts.play()
|
||||||
|
this.playVideo = true
|
||||||
|
},
|
||||||
|
onPlay(e) {},
|
||||||
|
onPause(e) {},
|
||||||
|
onEnded(e) {},
|
||||||
|
onError(e) {},
|
||||||
|
onTimeUpdate(e) {},
|
||||||
|
onWaiting(e) {},
|
||||||
|
onProgress(e) {},
|
||||||
|
onLoadedMetaData(e) {},
|
||||||
|
handerBannerClick(index) {
|
||||||
|
let {
|
||||||
|
image_url: url,
|
||||||
|
video_url = ''
|
||||||
|
} = this.detail
|
||||||
|
if (index == 0 && video_url) {
|
||||||
|
this.playVideo = true;
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!url) return
|
||||||
|
this.$util.goUrl({
|
||||||
|
openType: 'web', //this.configInfo.methodObj[jump_type],
|
||||||
|
url
|
||||||
|
})
|
||||||
|
},
|
||||||
|
goBack() {
|
||||||
|
uni.navigateBack({
|
||||||
|
delta: 1
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.home-return-btn {
|
||||||
|
margin-top: 10rpx;
|
||||||
|
margin-left: 24rpx;
|
||||||
|
width: 60rpx;
|
||||||
|
height: 60rpx;
|
||||||
|
border: none;
|
||||||
|
background-color: rgba(0, 0, 0, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-box {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: 500rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.my-video {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 80%;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 120rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner-swiper {
|
||||||
|
width: 750rpx;
|
||||||
|
height: 564rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner-img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner-taglist {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 32rpx;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner-tagitem {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 90rpx;
|
||||||
|
height: 42rpx;
|
||||||
|
border-radius: 21rpx;
|
||||||
|
background: rgba(255, 255, 255, 0.8);
|
||||||
|
color: #2b2b2b;
|
||||||
|
font-size: 22rpx;
|
||||||
|
margin-left: 32rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner-tagitem:nth-child(1) {
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner-tagitem_count {
|
||||||
|
background: rgba(0, 0, 0, 0.5);
|
||||||
|
color: #fff;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 32rpx;
|
||||||
|
right: 32rpx;
|
||||||
|
z-index: 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
.banner-tagitem_active {
|
||||||
|
background: #19c865;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,210 @@
|
||||||
|
<template>
|
||||||
|
<view>
|
||||||
|
<scroll-view scroll-x class='tab-list' :scroll-into-view="'tab'+(activeIndex-1)" :scroll-with-animation="true"
|
||||||
|
:style="{background: bgColor,fontSize: fontSize}">
|
||||||
|
<view class='tab-item rel' v-for="(item,index) in list" :key="index" @tap='handerTabChange(index)'
|
||||||
|
data-index="index" :id="'tab'+index"
|
||||||
|
:style='{width,height,lineHeight:height,color:index==activeIndex?activeColor:color}'>
|
||||||
|
<view class="flex-y-baseline flex-x-center rel">
|
||||||
|
<view class="rel" v-if="item.number">
|
||||||
|
{{item.title || item}}
|
||||||
|
<view v-if="numberType == 1" class="item-msg c-base abs"
|
||||||
|
:style="{width: item.number<10 ? '30rpx' :item.number<100 ? '40rpx' : '50rpx',right:item.number<10 ? '-34rpx' :item.number<100 ? '-44rpx' : '-54rpx' }">
|
||||||
|
{{item.number < 100 ? item.number : '99+'}}
|
||||||
|
</view>
|
||||||
|
<view class="tab-label c-base abs"
|
||||||
|
:style="{width: item.number<10 ? '24rpx' :item.number<100 ? '36rpx': '48rpx',right:item.number<10 ? '-14rpx' :item.number<100 ? '-26rpx' : '-38rpx'}"
|
||||||
|
v-if="numberType == 2">
|
||||||
|
{{item.number < 100 ? item.number : '99+'}}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<block v-else>{{item.title || item}}</block>
|
||||||
|
<block v-if="item.is_sign == 1">
|
||||||
|
<view class="tab-item-sanjao abs" :style="{right: item.title.length == 3 ? '-20rpx' : ''}">
|
||||||
|
<view class="up iconfont icon-up-fill rel"
|
||||||
|
:style="{color:index==activeIndex && item.sign == 1?activeColor:'#ccc',}"></view>
|
||||||
|
<view class="down iconfont icon-down-fill rel"
|
||||||
|
:style="{color:index==activeIndex && item.sign == 0?activeColor:'#ccc',}"></view>
|
||||||
|
</view>
|
||||||
|
</block>
|
||||||
|
</view>
|
||||||
|
<view class="abs line" :class="[lineClass]" :style="{background: activeColor}"
|
||||||
|
v-if="isLine && index==activeIndex && !item.is_sign">
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'tab',
|
||||||
|
props: {
|
||||||
|
list: {
|
||||||
|
type: Array,
|
||||||
|
default () {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
activeIndex: {
|
||||||
|
type: Number,
|
||||||
|
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 '100rpx'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
isLine: {
|
||||||
|
type: Boolean,
|
||||||
|
default () {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
lineClass: {
|
||||||
|
type: String,
|
||||||
|
default () {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
msgRight: {
|
||||||
|
type: String,
|
||||||
|
default () {
|
||||||
|
return '5rpx'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fontSize: {
|
||||||
|
type: String,
|
||||||
|
default () {
|
||||||
|
return '30rpx'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
numberType: {
|
||||||
|
type: Number,
|
||||||
|
default () {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handerTabChange(index) {
|
||||||
|
this.$emit('change', index);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.tab-list {
|
||||||
|
white-space: nowrap;
|
||||||
|
background: #fff;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.tab-item {
|
||||||
|
display: inline-block;
|
||||||
|
text-align: center;
|
||||||
|
padding: 0 20rpx;
|
||||||
|
border-color: #fff;
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
.tab-label {
|
||||||
|
width: 24rpx;
|
||||||
|
height: 24rpx;
|
||||||
|
font-size: 18rpx;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 24rpx;
|
||||||
|
border-radius: 24rpx;
|
||||||
|
background: #F1381F;
|
||||||
|
top: 12rpx;
|
||||||
|
right: -14rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-msg {
|
||||||
|
width: 30rpx;
|
||||||
|
height: 30rpx;
|
||||||
|
font-size: 20rpx;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 30rpx;
|
||||||
|
border-radius: 15rpx 15rpx 15rpx 0;
|
||||||
|
background: #f12c20;
|
||||||
|
top: 10rpx;
|
||||||
|
right: -34rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-item-sanjao {
|
||||||
|
top: 18rpx;
|
||||||
|
right: -6rpx;
|
||||||
|
width: 30rpx;
|
||||||
|
height: 50rpx;
|
||||||
|
transform: scale(0.6);
|
||||||
|
|
||||||
|
.iconfont {
|
||||||
|
font-size: 28rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.up {
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.down {
|
||||||
|
bottom: 10rpx;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.line {
|
||||||
|
width: 80rpx;
|
||||||
|
height: 6rpx;
|
||||||
|
border-radius: 6rpx;
|
||||||
|
left: 50%;
|
||||||
|
bottom: 0rpx;
|
||||||
|
margin-left: -40rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.line.sm {
|
||||||
|
width: 60rpx;
|
||||||
|
height: 6rpx;
|
||||||
|
border-radius: 6rpx;
|
||||||
|
left: 50%;
|
||||||
|
bottom: 0rpx;
|
||||||
|
margin-left: -30rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,117 @@
|
||||||
|
<template>
|
||||||
|
<view class="custom-tabbar fix flex-center fill-base b-1px-t">
|
||||||
|
<view @tap.stop="changeTab(item)" class="flex-center flex-column mt-sm"
|
||||||
|
:style="{width: (100/configInfo.tabBar.length) + '%',color:cur == item.id ? primaryColor : '#666'}"
|
||||||
|
v-for="(item,index) in configInfo.tabBar" :key="index">
|
||||||
|
<i class="iconfont" :class="cur == item.id ? item.selected_img : item.default_img"></i>
|
||||||
|
<image class="" :src="cur == item.id ? item.selected_img : item.default_img" style="width:45rpx;height:45rpx;"></image>
|
||||||
|
<view class="text">{{item.name}}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
mapState,
|
||||||
|
mapActions,
|
||||||
|
mapMutations
|
||||||
|
} from "vuex"
|
||||||
|
export default {
|
||||||
|
components: {},
|
||||||
|
props: {
|
||||||
|
cur: {
|
||||||
|
type: Number,
|
||||||
|
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,
|
||||||
|
userPageType: state => state.user.userPageType,
|
||||||
|
activeIndex: state => state.order.activeIndex,
|
||||||
|
}),
|
||||||
|
async mounted() {
|
||||||
|
let that = this;
|
||||||
|
let sysheight = uni.getSystemInfoSync().windowHeight
|
||||||
|
let {
|
||||||
|
navBarHeight
|
||||||
|
} = that.configInfo
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
const query = uni.createSelectorQuery().in(that);
|
||||||
|
query.select('.custom-tabbar').boundingClientRect(data => {
|
||||||
|
let curSysHeight = sysheight - data.height - navBarHeight
|
||||||
|
let configInfo = that.$util.deepCopy(this.configInfo)
|
||||||
|
configInfo.curSysHeight = curSysHeight
|
||||||
|
configInfo.tabbarHeight = data.height
|
||||||
|
that.updateConfigItem({
|
||||||
|
key: 'configInfo',
|
||||||
|
val: configInfo
|
||||||
|
})
|
||||||
|
}).exec();
|
||||||
|
}, 600)
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
...mapActions(['getConfigInfo']),
|
||||||
|
...mapMutations(['updateConfigItem']),
|
||||||
|
// 点击跳转
|
||||||
|
async changeTab(item) {
|
||||||
|
if (!item.id) {
|
||||||
|
await this.getConfigInfo()
|
||||||
|
let arr = this.configInfo.tabBar.filter(aitem => {
|
||||||
|
return aitem.name == item.name
|
||||||
|
})
|
||||||
|
item = arr[0]
|
||||||
|
}
|
||||||
|
let {
|
||||||
|
id: index
|
||||||
|
} = item
|
||||||
|
let {
|
||||||
|
activeIndex,
|
||||||
|
cur,
|
||||||
|
userPageType
|
||||||
|
} = this
|
||||||
|
let page = {
|
||||||
|
1: `/pages/service`,
|
||||||
|
2: `/pages/technician`,
|
||||||
|
3: `/pages/dynamic`,
|
||||||
|
4: `/pages/order?tab=${activeIndex}`,
|
||||||
|
5: `/pages/mine?type=${userPageType}`,
|
||||||
|
6: `/pages/shopstore`,
|
||||||
|
7: `/pages/map`
|
||||||
|
}
|
||||||
|
if (index == cur) return
|
||||||
|
this.$util.goUrl({
|
||||||
|
url: page[index],
|
||||||
|
openType: `reLaunch`
|
||||||
|
})
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</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);
|
||||||
|
|
||||||
|
.iconfont {
|
||||||
|
font-size: 40rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text {
|
||||||
|
font-size: 22rpx;
|
||||||
|
margin-top: 5rpx;
|
||||||
|
height: 32rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,306 @@
|
||||||
|
<template>
|
||||||
|
<view class="technician-list-item">
|
||||||
|
|
||||||
|
<view class="list-item flex-center pd-lg fill-base radius-16 rel">
|
||||||
|
<image mode="aspectFill" class="king-img abs" src="https://lbqny.migugu.com/admin/anmo/mine/king.gif"
|
||||||
|
v-if="info.coach_type_status==1">
|
||||||
|
</image>
|
||||||
|
<view class="flex-center flex-column">
|
||||||
|
<view class="item-img rel">
|
||||||
|
<!-- #ifdef H5 -->
|
||||||
|
<view class="item-img radius">
|
||||||
|
<view @tap.stop="toPreviewImage('work_img')" class="h5-image item-img radius"
|
||||||
|
:style="{ backgroundImage : `url('${info.work_img}')`}">
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view @tap.stop="info.coach_type_status==1?toPreviewImage('work_img'):''" class="h5-image abs"
|
||||||
|
:class="[`${imgType[info.coach_type_status]}-img`]"
|
||||||
|
:style="{ backgroundImage : info.coach_type_status === 3? `url('https://lbqny.migugu.com/admin/anmo/mine/${imgType[info.coach_type_status]}.png')` : `url('https://lbqny.migugu.com/admin/anmo/mine/${imgType[info.coach_type_status]}.gif')`}"
|
||||||
|
v-if="info.coach_type_status">
|
||||||
|
</view>
|
||||||
|
<!-- #endif -->
|
||||||
|
<!-- #ifndef H5 -->
|
||||||
|
<image @tap.stop="toPreviewImage('work_img')" mode="aspectFill" class="item-img radius"
|
||||||
|
:src="info.work_img">
|
||||||
|
</image>
|
||||||
|
<image @tap.stop="info.coach_type_status==1?toPreviewImage('work_img'):''" class="abs"
|
||||||
|
:class="[`${imgType[info.coach_type_status]}-img`]"
|
||||||
|
:src=" info.coach_type_status === 3 ? `https://lbqny.migugu.com/admin/anmo/mine/${imgType[info.coach_type_status]}.png` : `https://lbqny.migugu.com/admin/anmo/mine/${imgType[info.coach_type_status]}.gif`"
|
||||||
|
v-if="info.coach_type_status">
|
||||||
|
</image>
|
||||||
|
<!-- #endif -->
|
||||||
|
</view>
|
||||||
|
<view class="item-tag flex-center f-icontext c-base radius-20"
|
||||||
|
:style="{background: info.text_type === 1 ? service_btn_color : info.text_type == 3?primaryColor: info.text_type==4?'#e1493b':'',color:info.text_type === 1 ? service_font_color :[3,4].includes(info.text_type) ? '#fff' : ''}">
|
||||||
|
{{textType[info.text_type]}}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-1 ml-md max-510">
|
||||||
|
<view class="flex-between">
|
||||||
|
<view @tap.stop="goInfo">
|
||||||
|
<view class="flex-y-center f-title c-title">
|
||||||
|
<view class="text-bold max-200 ellipsis">{{info.coach_name}}</view>
|
||||||
|
<view @tap.stop="toPreviewImage('self_img')"
|
||||||
|
class="more-img flex-center ml-sm f-icontext ml-lg"
|
||||||
|
:style="{color:primaryColor,border:`1rpx solid ${primaryColor}`}">生活照</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-y-center f-icontext mt-sm">
|
||||||
|
<view class="flex-y-center"><i class="iconfont iconyduixingxingshixin icon-font-color"></i>
|
||||||
|
<view class="star-text">{{info.star}}</view>
|
||||||
|
</view>
|
||||||
|
<view class="order-num">
|
||||||
|
已服务 {{info.order_num > 9999 ? '9999+' : info.order_num}}单</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-y-center f-icontext mt-sm mb-sm">
|
||||||
|
<view class="flex-center">
|
||||||
|
<i class="iconfont iconjuli" :style="{color:primaryColor}"></i>
|
||||||
|
<view class="f-desc c-title ml-sm">{{info.distance}}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="can-service-btn f-caption c-base radius-10"
|
||||||
|
:style="{border:`2rpx solid ${primaryColor}`}" v-if="info.near_time">
|
||||||
|
<view class="text"
|
||||||
|
:style="{background: `linear-gradient(68deg, ${primaryColor}, ${subColor})`}">最早可约</view>
|
||||||
|
<view class="time" :style="{color:primaryColor}">{{'时间'+info.near_time+''}}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-between">
|
||||||
|
<view class="flex-y-center f-desc c-caption">
|
||||||
|
<view @tap.stop="goInfo" class="flex-y-center">
|
||||||
|
<block v-if="from!='collect' && plugAuth.store && info.store && info.store.id">
|
||||||
|
<i class="iconfont iconshangjia_1 c-caption mr-sm"></i>
|
||||||
|
商家
|
||||||
|
</block>
|
||||||
|
<block v-else-if="from!='collect' && info.admin_id && info.admin_name && merchantAuth">
|
||||||
|
<i class="iconfont iconshangjia_1 c-caption mr-sm"></i>
|
||||||
|
{{info.admin_name}}
|
||||||
|
</block>
|
||||||
|
<block v-else>
|
||||||
|
<i class="iconfont iconxiangqing c-caption mr-sm"></i>
|
||||||
|
详情
|
||||||
|
</block>
|
||||||
|
</view>
|
||||||
|
<view @tap.stop="toEmit('comment')" class="flex-y-center ml-lg"><i
|
||||||
|
class="iconfont iconpinglun mr-sm"></i>{{info.comment_num > 9999 ? '9999+':info.comment_num}}
|
||||||
|
</view>
|
||||||
|
<view @tap.stop="toEmit('collect')" class="flex-y-center ml-lg"><i class="iconfont mr-sm"
|
||||||
|
:class="[{'iconshoucang1':!info.is_collect},{'iconshoucang2':info.is_collect}]"
|
||||||
|
:style="{color:info.is_collect ? primaryColor :''}"></i>{{info.collect_num > 9999 ? '9999+':info.collect_num}}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<auth @tap.stop.prevent :needAuth="userInfo && (!userInfo.phone || !userInfo.nickName)" :must="true"
|
||||||
|
:type="!userInfo.phone ? 'phone' : 'userInfo'" @go="toEmit('order')" style="width:130rpx;">
|
||||||
|
<view class="item-btn flex-center f-desc c-base"
|
||||||
|
:style="{background: `linear-gradient(68deg, ${primaryColor}, ${subColor})`}">
|
||||||
|
预约TA
|
||||||
|
</view>
|
||||||
|
</auth>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
mapState,
|
||||||
|
mapMutations
|
||||||
|
} from "vuex"
|
||||||
|
export default {
|
||||||
|
components: {},
|
||||||
|
props: {
|
||||||
|
from: {
|
||||||
|
type: String,
|
||||||
|
default () {
|
||||||
|
return 'list'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
info: {
|
||||||
|
type: Object,
|
||||||
|
default () {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
imgType: {
|
||||||
|
1: 'top',
|
||||||
|
2: 'hot',
|
||||||
|
3: 'new'
|
||||||
|
},
|
||||||
|
textType: {
|
||||||
|
1: '可服务',
|
||||||
|
2: '服务中',
|
||||||
|
3: '可预约',
|
||||||
|
4: '不可预约'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: mapState({
|
||||||
|
primaryColor: state => state.config.configInfo.primaryColor,
|
||||||
|
subColor: state => state.config.configInfo.subColor,
|
||||||
|
plugAuth: state => state.config.configInfo.plugAuth,
|
||||||
|
merchantAuth: state => state.config.merchantAuth,
|
||||||
|
service_btn_color: state => state.config.configInfo.service_btn_color,
|
||||||
|
service_font_color: state => state.config.configInfo.service_font_color,
|
||||||
|
userInfo: state => state.user.userInfo,
|
||||||
|
}),
|
||||||
|
methods: {
|
||||||
|
toPreviewImage(key) {
|
||||||
|
let urls = this.info[key]
|
||||||
|
if (key == 'work_img') {
|
||||||
|
urls = [urls]
|
||||||
|
}
|
||||||
|
this.$util.previewImage({
|
||||||
|
current: urls[0],
|
||||||
|
urls
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 技-师详情
|
||||||
|
goInfo() {
|
||||||
|
let {
|
||||||
|
id,
|
||||||
|
store = {},
|
||||||
|
admin_id = 0,
|
||||||
|
admin_name
|
||||||
|
} = this.info
|
||||||
|
let {
|
||||||
|
from,
|
||||||
|
plugAuth = {},
|
||||||
|
merchantAuth = 0
|
||||||
|
} = this
|
||||||
|
this.$util.goUrl({
|
||||||
|
url: from != 'collect' && plugAuth.store && store && store.id ?
|
||||||
|
`/shopstore/pages/detail?id=${store.id}` : from != 'collect' && merchantAuth && admin_id &&
|
||||||
|
admin_name ? `/user/pages/merchant-info?id=${admin_id}` :
|
||||||
|
`/user/pages/technician-info?id=${id}`
|
||||||
|
})
|
||||||
|
},
|
||||||
|
toEmit(key) {
|
||||||
|
this.$emit(key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.technician-list-item {
|
||||||
|
|
||||||
|
.list-item {
|
||||||
|
.top-tag {
|
||||||
|
width: 40rpx;
|
||||||
|
height: 30rpx;
|
||||||
|
color: #B75E1D;
|
||||||
|
background: linear-gradient(90deg, #DFB885 0%, #FCE0AD 100%);
|
||||||
|
border-radius: 8rpx 0 8rpx 0;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-img {
|
||||||
|
width: 124rpx;
|
||||||
|
height: 124rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.king-img {
|
||||||
|
width: 90rpx;
|
||||||
|
height: 90rpx;
|
||||||
|
top: 110rpx;
|
||||||
|
left: -15rpx;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.top-img {
|
||||||
|
width: 146rpx;
|
||||||
|
height: 140rpx;
|
||||||
|
top: -7rpx;
|
||||||
|
left: -11rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hot-img {
|
||||||
|
width: 75rpx;
|
||||||
|
height: 51rpx;
|
||||||
|
top: 77rpx;
|
||||||
|
left: 25rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.new-img {
|
||||||
|
width: 38rpx;
|
||||||
|
height: 52rpx;
|
||||||
|
top: 83rpx;
|
||||||
|
left: 78rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-tag {
|
||||||
|
width: 100rpx;
|
||||||
|
height: 32rpx;
|
||||||
|
color: #000;
|
||||||
|
background: rgba(216, 216, 216, 0.3);
|
||||||
|
margin-top: 19rpx;
|
||||||
|
margin-bottom: 6rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.more-img {
|
||||||
|
width: 94rpx;
|
||||||
|
height: 33rpx;
|
||||||
|
border-radius: 3px;
|
||||||
|
transform: rotateZ(1turn);
|
||||||
|
}
|
||||||
|
|
||||||
|
.can-service-btn {
|
||||||
|
height: 80rpx;
|
||||||
|
margin-bottom: 30rpx;
|
||||||
|
width: 130rpx;
|
||||||
|
|
||||||
|
.bg {
|
||||||
|
width: 64rpx;
|
||||||
|
height: 28rpx;
|
||||||
|
opacity: 0.1;
|
||||||
|
border-radius: 3rpx;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text {
|
||||||
|
height: 40rpx;
|
||||||
|
line-height: 40rpx;
|
||||||
|
text-align: center;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.time {
|
||||||
|
height: 40rpx;
|
||||||
|
line-height: 40rpx;
|
||||||
|
text-align: center;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.iconyduixingxingshixin {
|
||||||
|
font-size: 28rpx;
|
||||||
|
background-image: -webkit-linear-gradient(270deg, #FAD961 0%, #F76B1C 100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.star-text {
|
||||||
|
color: #FF9519;
|
||||||
|
margin-left: 6rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.order-num {
|
||||||
|
color: #4D4D4D;
|
||||||
|
margin-left: 16rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-btn {
|
||||||
|
width: 130rpx;
|
||||||
|
height: 52rpx;
|
||||||
|
border-radius: 100rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,331 @@
|
||||||
|
<template>
|
||||||
|
<view class="technician-list-popup">
|
||||||
|
<uni-popup ref="technician_item" type="bottom" style="height: 600px;">
|
||||||
|
<view class="technician-popup fill-base">
|
||||||
|
<view class="pd-lg rel"
|
||||||
|
:class="[{'flex-center': from=='technician-info'&&showType == 'message' || showType == 'technician'},{'flex-warp': showType == 'message'}]">
|
||||||
|
<image mode="aspectFill" class="item-avatar radius" :src="info.work_img"></image>
|
||||||
|
<i @tap.stop="$refs.technician_item.close()" class="iconfont icon-close abs"></i>
|
||||||
|
<view class="flex-1 ml-md">
|
||||||
|
<view class="flex-between">
|
||||||
|
<view class="flex-y-baseline f-caption c-caption">
|
||||||
|
<view class="f-title c-title text-bold mr-sm max-350 ellipsis">
|
||||||
|
{{info.coach_name}}
|
||||||
|
</view>从业{{info.work_time}}年
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<scroll-view scroll-y @touchmove.stop.prevent class="technician-text f-caption c-caption mt-sm"
|
||||||
|
v-if="from != 'technician-info' && showType == 'message'">
|
||||||
|
{{info.text}}
|
||||||
|
</scroll-view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="space-sm fill-body"></view>
|
||||||
|
<scroll-view scroll-y @touchmove.stop.prevent class="list-content">
|
||||||
|
<block v-if="showType == 'technician'">
|
||||||
|
<view class="list-item flex-center pd-lg fill-base radius-16" :class="[{'b-1px-t':index != 0}]"
|
||||||
|
v-for="(item,index) in serviceList" :key="index">
|
||||||
|
<image @tap.stop="goDetail(index)" mode="aspectFill" class="avatar lg radius-16"
|
||||||
|
:src="item.cover"></image>
|
||||||
|
<view class="flex-1 ml-md">
|
||||||
|
<view @tap.stop="goDetail(index)" class="f-sm-title c-title text-bold max-510 ellipsis">
|
||||||
|
{{item.title}}
|
||||||
|
</view>
|
||||||
|
<view class="f-caption c-caption mt-sm mb-sm ellipsis">超{{item.total_sale}}人选择</view>
|
||||||
|
<view class="flex-between">
|
||||||
|
<view class="flex-y-baseline flex-1">
|
||||||
|
<view class="flex-y-baseline f-icontext c-orange text-bold mr-sm">
|
||||||
|
<b class="f-paragraph c-orange">¥</b>
|
||||||
|
<view class="f-big-title">
|
||||||
|
{{item.price}}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="text-delete mr-sm c-caption f-desc" v-if="item.init_price">
|
||||||
|
¥{{item.init_price}}</view>
|
||||||
|
<view class="flex-y-baseline flex-1 c-caption f-desc">
|
||||||
|
<i class="iconfont icon-shijian mr-sm" :style="{ color: primaryColor }"></i>
|
||||||
|
{{item.time_long}}分钟
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-warp">
|
||||||
|
<block v-if="item.car_num">
|
||||||
|
<button @tap.stop="changeNum(-1,index)" class="reduce"
|
||||||
|
:style="{borderColor:primaryColor,color:primaryColor}"><i
|
||||||
|
class="iconfont icon-jian-bold"></i></button>
|
||||||
|
<button class="addreduce clear-btn">{{item.car_num || 0}}</button>
|
||||||
|
</block>
|
||||||
|
<button @tap.stop="changeNum(1,index)" class="add"
|
||||||
|
:style="{background:primaryColor,borderColor:primaryColor}"><i
|
||||||
|
class="iconfont icon-jia-bold"></i></button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</block>
|
||||||
|
<block v-if="showType == 'message'">
|
||||||
|
<view class="list-message flex-warp pd-lg" :class="[{'b-1px-t':index!=0}]"
|
||||||
|
v-for="(item,index) in commentList.data" :key="index">
|
||||||
|
<image mode="aspectFill" class="item-avatar radius" :src="item.avatarUrl"></image>
|
||||||
|
<view class="flex-1 ml-md">
|
||||||
|
<view class="flex-between">
|
||||||
|
<view class="flex-y-center">
|
||||||
|
<view class="f-paragraph c-title mr-md">{{item.nickName}}</view>
|
||||||
|
<view class="flex-warp">
|
||||||
|
<i class="iconfont iconyduixingxingshixin icon-font-color"
|
||||||
|
:style="{backgroundImage: aindex< item.star?`-webkit-linear-gradient(270deg, #FAD961 0%, #F76B1C 100%)`:`-webkit-linear-gradient(270deg, #f4f6f8 0%, #ccc 100%)`}"
|
||||||
|
v-for="(aitem,aindex) in 5" :key="aindex"></i>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="f-icontext c-caption">{{item.create_time}}</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-warp mt-sm">
|
||||||
|
<view class="pt-sm pb-sm pl-md pr-md mt-sm mr-sm radius fill-body f-caption c-desc"
|
||||||
|
v-for="(item,index) in item.lable_text" :key="index">{{item}}</view>
|
||||||
|
</view>
|
||||||
|
<view class="f-caption c-caption mt-md">
|
||||||
|
<text decode="emsp" style="word-break:break-all;">{{item.text}}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</block>
|
||||||
|
</scroll-view>
|
||||||
|
<view style="margin: 0 100rpx;"
|
||||||
|
v-if="!loading&&((showType == 'technician' && serviceList&&serviceList.length<=0) || (showType == 'message' && commentList && commentList.data &&commentList.data.length<=0))">
|
||||||
|
<abnor></abnor>
|
||||||
|
</view>
|
||||||
|
<block v-if="showType == 'message' && commentList.last_page > 1">
|
||||||
|
<view class="space-lg b-1px-t"></view>
|
||||||
|
<view
|
||||||
|
@tap.stop="$refs.technician_item.close(),$util.goUrl({url:`/user/pages/comment?id=${info.id}`})"
|
||||||
|
class="more-btn flex-center f-paragraph c-base radius"
|
||||||
|
style="width:300rpx;height: 80rpx;margin:0 auto" :style="{background:primaryColor}">查看更多
|
||||||
|
</view>
|
||||||
|
<view class="space-lg"></view>
|
||||||
|
</block>
|
||||||
|
<view class="flex-between pd-lg b-1px-t" v-if="showType == 'technician' && car_info.car_count > 0">
|
||||||
|
<view class="flex-center">合计:<view class="f-title c-warning text-bold ml-sm">¥{{car_info.car_price}}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view @tap.stop="toOrder" class="order-btn flex-center f-desc c-base radius"
|
||||||
|
:style="{background: `linear-gradient(68deg, ${primaryColor}, ${subColor})`}">提交订单
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="space-safe"></view>
|
||||||
|
<view style="height: 98rpx;"></view>
|
||||||
|
</view>
|
||||||
|
</uni-popup>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
mapState,
|
||||||
|
mapActions,
|
||||||
|
mapMutations
|
||||||
|
} from "vuex"
|
||||||
|
export default {
|
||||||
|
components: {},
|
||||||
|
props: {
|
||||||
|
from: {
|
||||||
|
type: String,
|
||||||
|
default () {
|
||||||
|
return 'list'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
sid: {
|
||||||
|
type: Number,
|
||||||
|
default () {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
info: {},
|
||||||
|
showType: '',
|
||||||
|
car_info: {},
|
||||||
|
serviceList: [],
|
||||||
|
commentList: [],
|
||||||
|
loading: true,
|
||||||
|
lockTap: false,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: mapState({
|
||||||
|
primaryColor: state => state.config.configInfo.primaryColor,
|
||||||
|
subColor: state => state.config.configInfo.subColor,
|
||||||
|
plugAuth: state => state.config.configInfo.plugAuth,
|
||||||
|
userInfo: state => state.user.userInfo,
|
||||||
|
}),
|
||||||
|
methods: {
|
||||||
|
...mapActions([]),
|
||||||
|
async toShowPopup(info, key) {
|
||||||
|
this.info = info
|
||||||
|
this.showType = key
|
||||||
|
if (key == 'technician') {
|
||||||
|
let {
|
||||||
|
is_work = 0,
|
||||||
|
} = this.info
|
||||||
|
if (!is_work) return
|
||||||
|
this.serviceList = []
|
||||||
|
await this.getServiceList()
|
||||||
|
} else {
|
||||||
|
await this.getCommentList()
|
||||||
|
}
|
||||||
|
this.$refs.technician_item.open()
|
||||||
|
},
|
||||||
|
async getCommentList() {
|
||||||
|
let {
|
||||||
|
id: coach_id
|
||||||
|
} = this.info
|
||||||
|
let param = {
|
||||||
|
coach_id,
|
||||||
|
page: 1,
|
||||||
|
}
|
||||||
|
this.commentList = await this.$api.service.commentList(param)
|
||||||
|
this.loading = false
|
||||||
|
},
|
||||||
|
async getServiceList(flag = false) {
|
||||||
|
let {
|
||||||
|
id: coach_id
|
||||||
|
} = this.info
|
||||||
|
let {
|
||||||
|
data,
|
||||||
|
car_count,
|
||||||
|
car_price
|
||||||
|
} = await this.$api.service.coachServiceList({
|
||||||
|
coach_id
|
||||||
|
})
|
||||||
|
if (!flag) {
|
||||||
|
this.serviceList = data
|
||||||
|
}
|
||||||
|
this.car_info = {
|
||||||
|
car_count,
|
||||||
|
car_price
|
||||||
|
}
|
||||||
|
this.loading = false
|
||||||
|
},
|
||||||
|
// 服务详情
|
||||||
|
goDetail(index) {
|
||||||
|
let {
|
||||||
|
id
|
||||||
|
} = this.serviceList[index]
|
||||||
|
let {
|
||||||
|
sid: store_id = 0
|
||||||
|
} = this
|
||||||
|
let url = `/user/pages/detail?id=${id}&store_id=${store_id}`
|
||||||
|
this.$util.goUrl({
|
||||||
|
url
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 加/减数量
|
||||||
|
async changeNum(mol, serInd) {
|
||||||
|
let {
|
||||||
|
id: coach_id
|
||||||
|
} = this.info
|
||||||
|
let {
|
||||||
|
id: service_id,
|
||||||
|
car_num = 0,
|
||||||
|
car_id = 0
|
||||||
|
} = this.serviceList[serInd]
|
||||||
|
if (this.lockTap) return;
|
||||||
|
this.lockTap = true;
|
||||||
|
let methodModel = mol > 0 ? 'addCar' : 'delCar'
|
||||||
|
let param = mol > 0 ? {
|
||||||
|
service_id,
|
||||||
|
coach_id,
|
||||||
|
num: 1
|
||||||
|
} : {
|
||||||
|
id: car_id,
|
||||||
|
num: 1
|
||||||
|
}
|
||||||
|
if (methodModel == 'delCar' && !param.id) {
|
||||||
|
this.lockTap = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
let add_car_id = await this.$api.order[methodModel](param)
|
||||||
|
this.serviceList[serInd].car_num = car_num + mol
|
||||||
|
if (add_car_id && mol > 0 && !car_id) {
|
||||||
|
this.serviceList[serInd].car_id = add_car_id
|
||||||
|
}
|
||||||
|
if (this.serviceList[serInd].car_num < 1) {
|
||||||
|
this.serviceList[serInd].car_id = 0
|
||||||
|
}
|
||||||
|
await this.getServiceList(true)
|
||||||
|
this.lockTap = false
|
||||||
|
} catch (e) {
|
||||||
|
this.lockTap = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 下单
|
||||||
|
toOrder() {
|
||||||
|
if (this.car_info.car_count < 1) {
|
||||||
|
this.$util.showToast({
|
||||||
|
title: `请选择服务`
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let {
|
||||||
|
id
|
||||||
|
} = this.info
|
||||||
|
this.$refs.technician_item.close()
|
||||||
|
this.$util.goUrl({
|
||||||
|
url: `/user/pages/order?id=${id}`
|
||||||
|
})
|
||||||
|
},
|
||||||
|
toEmit(key) {
|
||||||
|
this.$emit(key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.technician-list-popup {
|
||||||
|
|
||||||
|
.technician-popup {
|
||||||
|
border-radius: 20rpx 20rpx 0 0;
|
||||||
|
|
||||||
|
.item-avatar {
|
||||||
|
width: 88rpx;
|
||||||
|
height: 88rpx;
|
||||||
|
background: #f4f6f8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-close {
|
||||||
|
font-size: 50rpx;
|
||||||
|
top: 30rpx;
|
||||||
|
right: 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.technician-text {
|
||||||
|
max-height: 150rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-content {
|
||||||
|
max-height: 50vh;
|
||||||
|
|
||||||
|
.list-message {
|
||||||
|
.item-avatar {
|
||||||
|
width: 52rpx;
|
||||||
|
height: 52rpx;
|
||||||
|
background: #f4f6f8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.iconyduixingxingshixin {
|
||||||
|
font-size: 28rpx;
|
||||||
|
margin-right: 5rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.order-btn {
|
||||||
|
width: 200rpx;
|
||||||
|
height: 72rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,87 @@
|
||||||
|
### 使用组件
|
||||||
|
|
||||||
|
```html
|
||||||
|
<time-picker-popup ref="TimePickerPopupRef" :value="value" @confirm="confirm"></time-picker-popup>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 引入组件
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
import TimePickerPopup from '@/components/time-picker-popup/time-picker-popup.vue';
|
||||||
|
```
|
||||||
|
|
||||||
|
### 注册组件
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
export default {
|
||||||
|
components: { TimePickerPopup },
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
value: ['00', '00', '00', '00']
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onReady() {
|
||||||
|
this.open();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
confirm(data) {
|
||||||
|
uni.showToast({
|
||||||
|
title: `${data[0]}:${data[1]}-${data[2]}:${data[3]}`
|
||||||
|
})
|
||||||
|
},
|
||||||
|
open() {
|
||||||
|
this.$refs.TimePickerPopupRef.open();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 参数
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// 当前选中的值
|
||||||
|
value: {
|
||||||
|
type: Array,
|
||||||
|
default: () => (['00', '00', '00', '00'])
|
||||||
|
},
|
||||||
|
// 标题
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
default: '时间'
|
||||||
|
},
|
||||||
|
// 取消按钮文字
|
||||||
|
cancelText: {
|
||||||
|
type: String,
|
||||||
|
default: '取消'
|
||||||
|
},
|
||||||
|
// 取消按钮颜色
|
||||||
|
canceColor: {
|
||||||
|
type: String,
|
||||||
|
default: '#666666'
|
||||||
|
},
|
||||||
|
// 确定按钮文字
|
||||||
|
confirmText: {
|
||||||
|
type: String,
|
||||||
|
default: '确定'
|
||||||
|
},
|
||||||
|
// 确定按钮颜色
|
||||||
|
confirmColor: {
|
||||||
|
type: String,
|
||||||
|
default: '#2bb781'
|
||||||
|
},
|
||||||
|
// 分割符
|
||||||
|
segmentation: {
|
||||||
|
type: String,
|
||||||
|
default: '-'
|
||||||
|
},
|
||||||
|
// 设置选择器中间选中框的类名 注意页面或组件的style中写了scoped时,需要在类名前写/deep/
|
||||||
|
indicatorClass: {
|
||||||
|
type: String,
|
||||||
|
default: 'picker-view__indicator'
|
||||||
|
},
|
||||||
|
// 设置选择器中间选中框的样式
|
||||||
|
indicatorStyle: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
```
|
|
@ -0,0 +1,163 @@
|
||||||
|
<template>
|
||||||
|
<!-- 时间选择器弹窗 -->
|
||||||
|
<uni-popup ref="popup" type="bottom" :safe-area="false">
|
||||||
|
<view class="custom-picker">
|
||||||
|
<view class="custom-picker__header">
|
||||||
|
<view class="cancel" :style="{ color: canceColor }" @tap="onCancel">{{ cancelText }}</view>
|
||||||
|
<view class="title">{{ title }}</view>
|
||||||
|
<view class="confirm" :style="{ color: confirmColor }" @tap="onConfirm">{{ confirmText }}</view>
|
||||||
|
</view>
|
||||||
|
<picker-view :indicator-class="indicatorClass" :indicator-style="indicatorStyle" class="picker-view"
|
||||||
|
:value="value" @change="bindChange" @pickstart="pickstart" @pickend="pickend">
|
||||||
|
<picker-view-column>
|
||||||
|
<view class="picker-view__item" v-for="(item,index) in rangeList[0]" :key="index">{{item}}</view>
|
||||||
|
</picker-view-column>
|
||||||
|
<picker-view-column>
|
||||||
|
<view class="picker-view__item" v-for="(item,index) in rangeList[1]" :key="index">{{item}}</view>
|
||||||
|
</picker-view-column>
|
||||||
|
<!-- <view class="picker-view__segmentation">{{ segmentation }}</view> -->
|
||||||
|
<picker-view-column>
|
||||||
|
<view class="picker-view__item" v-for="(item,index) in rangeList[2]" :key="index">{{item}}</view>
|
||||||
|
</picker-view-column>
|
||||||
|
<picker-view-column>
|
||||||
|
<view class="picker-view__item" v-for="(item,index) in rangeList[3]" :key="index">{{item}}</view>
|
||||||
|
</picker-view-column>
|
||||||
|
</picker-view>
|
||||||
|
</view>
|
||||||
|
</uni-popup>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import utils from './utils.js'
|
||||||
|
export default {
|
||||||
|
name: 'TimePickerPopup',
|
||||||
|
props: utils.props,
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
rangeList: utils.range,
|
||||||
|
pickerValue: [0, 0, 0, 0],
|
||||||
|
isScoll: false, // 是否正在滚动
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
/**
|
||||||
|
* 开启弹窗
|
||||||
|
*/
|
||||||
|
open() {
|
||||||
|
// 判断是否传入props -> value
|
||||||
|
if (Array.isArray(this.value) && this.value.length) {
|
||||||
|
this.pickerValue = this.value.map((item, index) => this.rangeList[index].findIndex(child =>
|
||||||
|
child == this.value[index]));
|
||||||
|
console.log(this.pickerValue)
|
||||||
|
|
||||||
|
} else {
|
||||||
|
this.pickerValue = [0, 0, 0, 0];
|
||||||
|
}
|
||||||
|
this.$refs.popup.open();
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 关闭弹窗
|
||||||
|
*/
|
||||||
|
close() {
|
||||||
|
this.$refs.popup.close();
|
||||||
|
// 重置选中数据
|
||||||
|
this.pickerValue = [0, 0, 0, 0];
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 点击确定
|
||||||
|
*/
|
||||||
|
onConfirm() {
|
||||||
|
if (!this.isScoll) {
|
||||||
|
let data = this.value || ['00', '00', '00', '00'];
|
||||||
|
if (this.pickerValue && this.pickerValue.length) {
|
||||||
|
data = this.pickerValue.map((item, index) => String(this.rangeList[index][Number(item)]));
|
||||||
|
}
|
||||||
|
this.$emit('confirm', data);
|
||||||
|
this.close();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 点击取消
|
||||||
|
*/
|
||||||
|
onCancel() {
|
||||||
|
this.close();
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 滚动开始
|
||||||
|
*/
|
||||||
|
pickstart() {
|
||||||
|
this.isScoll = true;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 滚动结束
|
||||||
|
*/
|
||||||
|
pickend() {
|
||||||
|
this.isScoll = false;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 选择器改变
|
||||||
|
* @param {Object} e
|
||||||
|
*/
|
||||||
|
bindChange(e) {
|
||||||
|
this.pickerValue = e.detail.value;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.custom-picker {
|
||||||
|
width: 100%;
|
||||||
|
height: 620rpx;
|
||||||
|
background-color: #fff;
|
||||||
|
padding-bottom: 0;
|
||||||
|
padding-bottom: constant(safe-area-inset-bottom);
|
||||||
|
padding-bottom: env(safe-area-inset-bottom);
|
||||||
|
position: relative;
|
||||||
|
z-index: 999;
|
||||||
|
|
||||||
|
&__header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
padding: 30rpx 40rpx;
|
||||||
|
|
||||||
|
.cancel {
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-size: 32rpx;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.confirm {
|
||||||
|
color: #2bb781;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.picker-view {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
margin-top: 20rpx;
|
||||||
|
|
||||||
|
&__item {
|
||||||
|
line-height: 100rpx;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/deep/ &__indicator {
|
||||||
|
height: 100rpx;
|
||||||
|
color: #2bb781;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__segmentation {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,69 @@
|
||||||
|
// 组件props
|
||||||
|
const props = {
|
||||||
|
// 当前选中的值
|
||||||
|
value: {
|
||||||
|
type: Array,
|
||||||
|
default: () => (['00', '00', '00', '00'])
|
||||||
|
},
|
||||||
|
// 标题
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
default: '时间'
|
||||||
|
},
|
||||||
|
// 取消按钮文字
|
||||||
|
cancelText: {
|
||||||
|
type: String,
|
||||||
|
default: '取消'
|
||||||
|
},
|
||||||
|
// 取消按钮颜色
|
||||||
|
canceColor: {
|
||||||
|
type: String,
|
||||||
|
default: '#666666'
|
||||||
|
},
|
||||||
|
// 确定按钮文字
|
||||||
|
confirmText: {
|
||||||
|
type: String,
|
||||||
|
default: '确定'
|
||||||
|
},
|
||||||
|
// 确定按钮颜色
|
||||||
|
confirmColor: {
|
||||||
|
type: String,
|
||||||
|
default: '#2bb781'
|
||||||
|
},
|
||||||
|
// 分割符
|
||||||
|
segmentation: {
|
||||||
|
type: String,
|
||||||
|
default: '-'
|
||||||
|
},
|
||||||
|
// 设置选择器中间选中框的类名 注意页面或组件的style中写了scoped时,需要在类名前写/deep/
|
||||||
|
indicatorClass: {
|
||||||
|
type: String,
|
||||||
|
default: 'picker-view__indicator'
|
||||||
|
},
|
||||||
|
// 设置选择器中间选中框的样式
|
||||||
|
indicatorStyle: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// 滚动数据
|
||||||
|
let range = [
|
||||||
|
[],
|
||||||
|
[],
|
||||||
|
[],
|
||||||
|
[]
|
||||||
|
];
|
||||||
|
for (let i = 0; i < 24; i++) {
|
||||||
|
range[0].push(i >= 10 ? String(i) : `0${i}`);
|
||||||
|
range[2].push(i >= 10 ? String(i) : `0${i}`);
|
||||||
|
}
|
||||||
|
for (let i = 0; i < 60; i++) {
|
||||||
|
range[1].push(i >= 10 ? String(i) : `0${i}`);
|
||||||
|
range[3].push(i >= 10 ? String(i) : `0${i}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props,
|
||||||
|
range
|
||||||
|
}
|
|
@ -0,0 +1,210 @@
|
||||||
|
<template>
|
||||||
|
<view>
|
||||||
|
<view class='record-box fill-base'>
|
||||||
|
<view class='record-item rel ml-sm b-1px-l' :style="{padding:index==list.length -1?'0 0 0 30rpx':''}"
|
||||||
|
v-for="(item,index) in list" :key="index">
|
||||||
|
|
||||||
|
<text class="item-tag abs" :class="[{'cur':info.pay_type > item.pay_type -1 && info.pay_type != 8}]"
|
||||||
|
:style="{border:`2rpx solid ${primaryColor}`,background: info.pay_type > item.pay_type -1 && info.pay_type != 8 ? primaryColor : ''}"></text>
|
||||||
|
|
||||||
|
<view class='c-title'>
|
||||||
|
<view class="item-text f-paragraph flex-y-baseline">
|
||||||
|
{{item.title}}
|
||||||
|
<view class="ml-md f-caption c-caption"
|
||||||
|
:style="{color:item.title == '签字确认' && !info.sign_img ? '' : info.pay_type > item.pay_type -1 && info.pay_type != 8 ? primaryColor : ''}">
|
||||||
|
{{item.title == '签字确认' && !info.sign_img ? '暂未签字确认' : info.pay_type > item.pay_type -1 && info.pay_type != 8? '' : '状态未开始' }}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="c-caption" v-if="info.pay_type > item.pay_type*1-1 && info[item.time]">
|
||||||
|
{{info[item.time]}}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<block v-if="item.pay_type == 4 && !info.is_add && info.pay_type > 3">
|
||||||
|
<view @tap.stop="toMap('serout')" class="flex-y-center mt-md f-caption c-title"
|
||||||
|
v-if="info.serout_address">
|
||||||
|
<i class="iconfont iconjuli mr-sm" :style="{color:primaryColor}"></i>{{info.serout_address}}
|
||||||
|
</view>
|
||||||
|
</block>
|
||||||
|
<block
|
||||||
|
v-if="item.pay_type == 5 && !info.is_add && info.pay_type > 4 && (info.arrive_img || info.arr_address)">
|
||||||
|
<block v-if="info.arrive_img">
|
||||||
|
<!-- #ifdef H5 -->
|
||||||
|
<view @tap.stop="toPreviewImage('arrive_img')" class="item-img mt-md radius-5"
|
||||||
|
v-if="info.arrive_img">
|
||||||
|
<view class="h5-image item-img mt-md radius-5"
|
||||||
|
:style="{ backgroundImage : `url('${info.arrive_img}')`}">
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<!-- #endif -->
|
||||||
|
<!-- #ifndef H5 -->
|
||||||
|
<image @tap.stop="toPreviewImage('arrive_img')" mode="widthFix" class="item-img mt-md radius-5"
|
||||||
|
:src="info.arrive_img" v-if="info.arrive_img">
|
||||||
|
</image>
|
||||||
|
<!-- #endif -->
|
||||||
|
</block>
|
||||||
|
<view @tap.stop="toMap('arr')" class="flex-y-center mt-md f-caption c-title"
|
||||||
|
v-if="info.arr_address">
|
||||||
|
<i class="iconfont iconjuli mr-sm" :style="{color:primaryColor}"></i>{{info.arr_address}}
|
||||||
|
</view>
|
||||||
|
</block>
|
||||||
|
<block v-if="item.title== '服务完成' && info.pay_type == 7 && (info.end_img || info.end_address)">
|
||||||
|
<block v-if="info.end_img">
|
||||||
|
<!-- #ifdef H5 -->
|
||||||
|
<view @tap.stop="toPreviewImage('end_img')" class="item-img mt-md radius-5">
|
||||||
|
<view class="h5-image item-img mt-md radius-5"
|
||||||
|
:style="{ backgroundImage : `url('${info.end_img}')`}">
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<!-- #endif -->
|
||||||
|
<!-- #ifndef H5 -->
|
||||||
|
<image @tap.stop="toPreviewImage('end_img')" mode="widthFix" class="item-img mt-md radius-5"
|
||||||
|
:src="info.end_img">
|
||||||
|
</image>
|
||||||
|
<!-- #endif -->
|
||||||
|
</block>
|
||||||
|
<view @tap.stop="toMap('end')" class="flex-y-center mt-md f-caption c-title"
|
||||||
|
v-if="info.end_address">
|
||||||
|
<i class="iconfont iconjuli mr-sm" :style="{color:primaryColor}"></i>{{info.end_address}}
|
||||||
|
</view>
|
||||||
|
</block>
|
||||||
|
<block v-if="item.title== '签字确认' && info.pay_type == 7">
|
||||||
|
<block v-if="info.sign_img">
|
||||||
|
<!-- #ifdef H5 -->
|
||||||
|
<view @tap.stop="toPreviewImage('sign_img')" class="item-img mt-md radius-5">
|
||||||
|
<view class="h5-image item-img mt-md radius-5"
|
||||||
|
:style="{ backgroundImage : `url('${info.sign_img}')`}">
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<!-- #endif -->
|
||||||
|
<!-- #ifndef H5 -->
|
||||||
|
<image @tap.stop="toPreviewImage('sign_img')" mode="widthFix" class="item-img mt-md radius-5"
|
||||||
|
:src="info.sign_img">
|
||||||
|
</image>
|
||||||
|
<!-- #endif -->
|
||||||
|
</block>
|
||||||
|
<view class="flex-between" v-if="type==1 && !info.is_add && !info.sign_img">
|
||||||
|
<view @tap.stop="toSign" class="item-btn flex-center mt-md c-base radius"
|
||||||
|
:style="{background:primaryColor}">
|
||||||
|
签字确认
|
||||||
|
</view>
|
||||||
|
<view></view>
|
||||||
|
</view>
|
||||||
|
</block>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
mapState
|
||||||
|
} from "vuex"
|
||||||
|
export default {
|
||||||
|
name: 'timeline',
|
||||||
|
props: {
|
||||||
|
list: {
|
||||||
|
type: Array,
|
||||||
|
default () {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
info: {
|
||||||
|
type: Object,
|
||||||
|
default () {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
type: {
|
||||||
|
type: Number,
|
||||||
|
default () {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: mapState({
|
||||||
|
primaryColor: state => state.config.configInfo.primaryColor,
|
||||||
|
subColor: state => state.config.configInfo.subColor,
|
||||||
|
}),
|
||||||
|
methods: {
|
||||||
|
toPreviewImage(key) {
|
||||||
|
let curent = this.info[key]
|
||||||
|
this.$util.previewImage({
|
||||||
|
curent,
|
||||||
|
urls: [curent]
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// 查看定位
|
||||||
|
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
|
||||||
|
})
|
||||||
|
},
|
||||||
|
toSign() {
|
||||||
|
let {
|
||||||
|
id
|
||||||
|
} = this.info
|
||||||
|
let url = `/user/pages/order/sign?id=${id}`
|
||||||
|
this.$util.goUrl({
|
||||||
|
url
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.record-item {
|
||||||
|
padding: 0 0 30rpx 30rpx;
|
||||||
|
|
||||||
|
.item-tag {
|
||||||
|
width: 14px;
|
||||||
|
height: 14px;
|
||||||
|
display: block;
|
||||||
|
background: #fff;
|
||||||
|
border-radius: 50%;
|
||||||
|
top: 0;
|
||||||
|
left: -7px;
|
||||||
|
transform: rotateZ(360deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-text {
|
||||||
|
line-height: 34rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-img {
|
||||||
|
width: 180rpx;
|
||||||
|
min-height: 118rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-btn {
|
||||||
|
width: 160rpx;
|
||||||
|
height: 64rpx;
|
||||||
|
background: #EEEEEE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.record-item.b-1px-l::before {
|
||||||
|
border-left: 2px solid #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.record-item:last-child {
|
||||||
|
padding-bottom: 0;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,247 @@
|
||||||
|
<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">
|
||||||
|
<view v-if="title.length" class="uni-navbar-container-title">{{title}}</view>
|
||||||
|
<!-- 标题插槽 -->
|
||||||
|
<slot></slot>
|
||||||
|
</view>
|
||||||
|
<view class="uni-navbar-header-btns right" @tap="onClickRight">
|
||||||
|
<view v-if="rightText.length" 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: ''
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 左侧按钮图标
|
||||||
|
*/
|
||||||
|
leftIcon: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 左侧按钮文本
|
||||||
|
*/
|
||||||
|
leftText: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 右侧按钮文本
|
||||||
|
*/
|
||||||
|
rightText: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 是否固定在顶部
|
||||||
|
*/
|
||||||
|
fixed: {
|
||||||
|
type: [Boolean, String],
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 按钮图标和文字颜色
|
||||||
|
*/
|
||||||
|
color: {
|
||||||
|
type: String,
|
||||||
|
default: '#000000'
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 背景颜色
|
||||||
|
*/
|
||||||
|
backgroundColor: {
|
||||||
|
type: String,
|
||||||
|
default: '#FFFFFF'
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 是否仅有左侧
|
||||||
|
*/
|
||||||
|
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 == 'iconshouye11') {
|
||||||
|
this.$util.goUrl({
|
||||||
|
url: `/pages/service`,
|
||||||
|
openType: 'reLaunch'
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
this.$emit('clickLeft')
|
||||||
|
this.$emit('click-left')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 右侧按钮点击事件
|
||||||
|
*/
|
||||||
|
onClickRight() {
|
||||||
|
this.$emit('clickRight')
|
||||||
|
this.$emit('click-right')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.uni-navbar {
|
||||||
|
display: block;
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
/* background-color: #FFFFFF; */
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-navbar-shadow {
|
||||||
|
box-shadow: 0 1px 6px #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-navbar.uni-navbar-fixed {
|
||||||
|
position: fixed;
|
||||||
|
z-index: 9999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.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: 16px;
|
||||||
|
/* #endif */
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-navbar-header-btns {
|
||||||
|
display: inline-flex;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
flex-shrink: 0;
|
||||||
|
width: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-navbar-header-btns.left {
|
||||||
|
padding-left: 30rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.iconfont {
|
||||||
|
font-size: 36rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-navbar-header-btns.right {
|
||||||
|
padding-right: 30rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.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;
|
||||||
|
text-align: center;
|
||||||
|
/* #ifndef H5 */
|
||||||
|
padding-right: 30px;
|
||||||
|
/* #endif */
|
||||||
|
max-width: 360rpx;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,209 @@
|
||||||
|
<template>
|
||||||
|
<view v-if="showPopup" class="uni-popup" :style="{top: top,zIndex: zIndex}">
|
||||||
|
<view @click="close(true)" :class="[ani, animation ? 'ani' : '', !custom ? 'uni-custom' : '']"
|
||||||
|
class="uni-popup__mask" :style="{zIndex: zIndex}" />
|
||||||
|
<view @click="close(true)" :class="[type, ani, animation ? 'ani' : '', !custom ? 'uni-custom' : '']"
|
||||||
|
class="uni-popup__wrapper" :style="{zIndex: zIndex+1,left: type!='center'?left:''}">
|
||||||
|
<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
|
||||||
|
},
|
||||||
|
top: {
|
||||||
|
type: String,
|
||||||
|
default: '0rpx'
|
||||||
|
},
|
||||||
|
left: {
|
||||||
|
type: String,
|
||||||
|
default: '0rpx'
|
||||||
|
},
|
||||||
|
zIndex: {
|
||||||
|
type: [Number],
|
||||||
|
default () {
|
||||||
|
return 998
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
ani: '',
|
||||||
|
showPopup: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
show(newValue) {
|
||||||
|
if (newValue) {
|
||||||
|
this.open()
|
||||||
|
} else {
|
||||||
|
this.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {},
|
||||||
|
methods: {
|
||||||
|
clear() {
|
||||||
|
this.$emit('clear', {
|
||||||
|
show: false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
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;
|
||||||
|
overflow: hidden
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-popup__mask {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
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;
|
||||||
|
box-sizing: border-box
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-popup__wrapper.ani {
|
||||||
|
transition: all .3s
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-popup__wrapper.top {
|
||||||
|
top: 0;
|
||||||
|
width: 100%;
|
||||||
|
transform: translateY(-100%)
|
||||||
|
}
|
||||||
|
|
||||||
|
.uni-popup__wrapper.bottom {
|
||||||
|
bottom: 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>
|
|
@ -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>
|
|
@ -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>
|
|
@ -0,0 +1,353 @@
|
||||||
|
<template>
|
||||||
|
<view
|
||||||
|
:class="[{'flex-warp':!imgclass || imgclass =='mini'},{'flex-center flex-column':imgclass && imgclass != 'mini'}]">
|
||||||
|
<block v-for="(item,index) in imagelist" :key="index">
|
||||||
|
<view class="rel item-child radius-16" :class="[imgclass,{'margin': imgsize > 1}]"
|
||||||
|
:style="{border:imgclass=='apply'?`4rpx solid ${primaryColor}`:''}">
|
||||||
|
<!-- #ifdef H5 -->
|
||||||
|
<view class="upload-img radius-16" v-if="filetype == 'picture'">
|
||||||
|
<view @tap.stop="previewImage(item,imagelist)" class="h5-image upload-img radius-16"
|
||||||
|
:style="{ backgroundImage : `url('${item.path}')`}">
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<!-- #endif -->
|
||||||
|
<!-- #ifndef H5 -->
|
||||||
|
<image mode="aspectFill" @tap.stop="previewImage(item,imagelist)" class="upload-img radius-16"
|
||||||
|
:src="item.path" v-if="filetype == 'picture'"></image>
|
||||||
|
<!-- #endif -->
|
||||||
|
|
||||||
|
<video :id="`video_${index}`" class="upload-video rel 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'">
|
||||||
|
<cover-view @tap="toDel(index)" class="item-delete abs flex-center f-icontext c-base"
|
||||||
|
:style="{background:primaryColor}">
|
||||||
|
删除
|
||||||
|
</cover-view>
|
||||||
|
</video>
|
||||||
|
|
||||||
|
<block v-if="filetype == 'picture'">
|
||||||
|
<view @tap="toDel(index)" class="guanbi abs flex-center" :class="[imgclass]" style="z-index: 1;"
|
||||||
|
v-if="imgsize>1"><i class="iconfont icon-add rotate-45 c-base"></i></view>
|
||||||
|
<view @tap="chooseImage" class="flex-center flex-column item-child upload-item radius-16 abs"
|
||||||
|
:class="[imgclass]" style="top:0;margin-top:0;background:rgba(0,0,0,0.5);" v-else>
|
||||||
|
<view class="upload-icon flex-center c-title radius-10">
|
||||||
|
<i class="iconfont icon-camera"></i>
|
||||||
|
</view>
|
||||||
|
<view class="f-caption c-base mt-sm">重新上传</view>
|
||||||
|
</view>
|
||||||
|
</block>
|
||||||
|
</view>
|
||||||
|
</block>
|
||||||
|
<view @tap="chooseImage" class="radius-16 flex-center flex-column item-child upload-item fill-body radius-16"
|
||||||
|
:class="[imgclass,{'margin': imgsize > 1}]"
|
||||||
|
:style="{border:imgclass=='apply'?`4rpx solid ${primaryColor}`:''}" v-if="imagelist.length < imgsize">
|
||||||
|
<view class="upload-icon flex-center c-title radius-10">
|
||||||
|
<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>
|
||||||
|
</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 ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 备注信息
|
||||||
|
text: {
|
||||||
|
type: String,
|
||||||
|
default () {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 视频大小限制
|
||||||
|
videoSize: {
|
||||||
|
type: Number,
|
||||||
|
default () {
|
||||||
|
return 50
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 上传类型
|
||||||
|
sourceType: {
|
||||||
|
type: Number,
|
||||||
|
default () {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: mapState({
|
||||||
|
primaryColor: state => state.config.configInfo.primaryColor,
|
||||||
|
subColor: state => state.config.configInfo.subColor,
|
||||||
|
userInfo: state => state.user.userInfo
|
||||||
|
}),
|
||||||
|
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,
|
||||||
|
videoSize,
|
||||||
|
sourceType
|
||||||
|
} = this;
|
||||||
|
let imagelist = this.$util.deepCopy(this.imagelist)
|
||||||
|
let is_upload_img = filetype == 'picture'
|
||||||
|
let chooseModel = is_upload_img ? 'chooseImage' : 'chooseVideo'
|
||||||
|
let count = 1
|
||||||
|
// #ifndef H5
|
||||||
|
count = imgsize == 1 ? 1 : imgsize - imagelist.length * 1
|
||||||
|
// #endif
|
||||||
|
let param = {
|
||||||
|
count
|
||||||
|
}
|
||||||
|
if (is_upload_img) {
|
||||||
|
param.sizeType = ['compressed']
|
||||||
|
}
|
||||||
|
param.sourceType = sourceType == 1 ? ['camera', 'album'] : ['camera']
|
||||||
|
let [res_upload, res_info] = await uni[chooseModel](param)
|
||||||
|
if (res_upload) return
|
||||||
|
let {
|
||||||
|
size = 0,
|
||||||
|
tempFiles,
|
||||||
|
tempFilePath = ''
|
||||||
|
} = res_info
|
||||||
|
console.log(is_upload_img, size, size / 1024 / 1024, "=====size")
|
||||||
|
if (filetype == 'video' && size / 1024 / 1024 > videoSize) {
|
||||||
|
this.$util.showToast({
|
||||||
|
title: `上传视频大小超过限制${videoSize}M`
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let filePath = [];
|
||||||
|
// 格式化图片参数
|
||||||
|
this.$util.showLoading({
|
||||||
|
title: "上传中"
|
||||||
|
});
|
||||||
|
console.log("======tempFiles==tempFilePath", tempFiles, tempFilePath)
|
||||||
|
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,
|
||||||
|
formData: {
|
||||||
|
type: this.filetype
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (imgsize > 1) {
|
||||||
|
imagelist.push({
|
||||||
|
path
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
imagelist = [{
|
||||||
|
path
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let {
|
||||||
|
attachment_path: path
|
||||||
|
} = await this.$api.base.uploadFile({
|
||||||
|
filePath: tempFilePath,
|
||||||
|
formData: {
|
||||||
|
type: this.filetype
|
||||||
|
}
|
||||||
|
})
|
||||||
|
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: 216rpx;
|
||||||
|
height: 216rpx;
|
||||||
|
background: #F7F7F7;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.margin {
|
||||||
|
margin: 0 21rpx 21rpx 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-child:nth-child(3n) {
|
||||||
|
margin-right: 0rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-child.sm {
|
||||||
|
width: 140rpx;
|
||||||
|
height: 140rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-child.apply {
|
||||||
|
width: 176rpx;
|
||||||
|
height: 176rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-child.mini {
|
||||||
|
width: 196rpx;
|
||||||
|
height: 196rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-child.md {
|
||||||
|
width: 335rpx;
|
||||||
|
height: 210rpx;
|
||||||
|
margin: 0rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-child.lg {
|
||||||
|
width: 686rpx;
|
||||||
|
height: 400rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-img,
|
||||||
|
.upload-video {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.upload-video {
|
||||||
|
.item-delete {
|
||||||
|
width: 60rpx;
|
||||||
|
height: 32rpx;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-item {
|
||||||
|
|
||||||
|
.upload-icon {
|
||||||
|
width: 80rpx;
|
||||||
|
height: 76rpx;
|
||||||
|
background: #FFFFFF;
|
||||||
|
|
||||||
|
.iconfont {
|
||||||
|
font-size: 40rpx;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cur-imgsize {
|
||||||
|
line-height: 1.1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload-item.margin {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-child.apply {
|
||||||
|
.upload-item {
|
||||||
|
width: 168rpx;
|
||||||
|
height: 168rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.guanbi {
|
||||||
|
width: 32rpx;
|
||||||
|
height: 32rpx;
|
||||||
|
background: rgba(0, 0, 0, 0.2);
|
||||||
|
border-radius: 0 15rpx 0 0;
|
||||||
|
top: 0rpx;
|
||||||
|
right: 0rpx;
|
||||||
|
z-index: 1;
|
||||||
|
|
||||||
|
.iconfont {
|
||||||
|
font-size: 28rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.guanbi.lg {
|
||||||
|
width: 50rpx;
|
||||||
|
height: 50rpx;
|
||||||
|
|
||||||
|
.iconfont {
|
||||||
|
font-size: 38rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
File diff suppressed because one or more lines are too long
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
|
@ -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>
|
|
@ -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>
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -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>
|
|
@ -0,0 +1,183 @@
|
||||||
|
<template>
|
||||||
|
<view class="wf-list-container">
|
||||||
|
<view id="wf-list" class="wf-list" v-for="(list,listIndex) of viewList" :key="listIndex">
|
||||||
|
<view @tap="goDetail(listIndex,index)" :data-id="item.id" class="wf-item-child rel"
|
||||||
|
v-for="(item,index) of list.list" :key="index">
|
||||||
|
<view class="examin-btn flex-center f-icontext c-base radius abs"
|
||||||
|
:style="{background:item.status==1?'#FC8218':'#FF6262'}" v-if="path==2&& item.status!=2">
|
||||||
|
{{item.status==1?'审核中':'已驳回'}}
|
||||||
|
</view>
|
||||||
|
<image mode="widthFix" class="cover" :id="'id'+item.id" @load="handleViewRender"
|
||||||
|
@error="handleViewRender" :src="item.cover"></image>
|
||||||
|
<view class="play-video-info flex-center c-base abs" v-if="item.type == 2">
|
||||||
|
<view class="play-video flex-center c-base radius">
|
||||||
|
<i class="iconfont icon-play-video"></i>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="wf-item">
|
||||||
|
<view class="f-desc c-black text-bold">{{item.title}}</view>
|
||||||
|
<view class="flex-between mt-sm">
|
||||||
|
<view class="flex-center">
|
||||||
|
<image mode="aspectFill" class="avatar" :src="item.work_img"></image>
|
||||||
|
<view class="coach f-caption c-desc ellipsis">{{item.coach_name}}</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-y-baseline f-caption c-desc"> <i class="iconfont iconjuli"
|
||||||
|
:style="{color:primaryColor}"></i>
|
||||||
|
{{item.distance}}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
mapState,
|
||||||
|
mapActions
|
||||||
|
} from 'vuex';
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
list: {
|
||||||
|
type: Array, //实际请求获取的列表数据
|
||||||
|
},
|
||||||
|
path: {
|
||||||
|
type: String || Number, //跳转页面类型 1用户端;2技-师端
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
viewList: [{
|
||||||
|
list: []
|
||||||
|
}, {
|
||||||
|
list: []
|
||||||
|
}],
|
||||||
|
//展示到视图的列表数据
|
||||||
|
everyNum: 2
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
if (this.list.length) {
|
||||||
|
this.init()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: mapState({
|
||||||
|
primaryColor: state => state.config.configInfo.primaryColor,
|
||||||
|
subColor: state => state.config.configInfo.subColor,
|
||||||
|
have: state => state.config.configInfo.subColor,
|
||||||
|
}),
|
||||||
|
methods: {
|
||||||
|
...mapActions(),
|
||||||
|
init() {
|
||||||
|
this.viewList = [{
|
||||||
|
list: []
|
||||||
|
}, {
|
||||||
|
list: []
|
||||||
|
}];
|
||||||
|
setTimeout(() => {
|
||||||
|
this.handleViewRender(0, 0)
|
||||||
|
}, 600)
|
||||||
|
},
|
||||||
|
handleViewRender(x, y) {
|
||||||
|
const index = this.viewList.reduce((total, current) => total + current.list.length, 0)
|
||||||
|
if (index > this.list.length - 1) {
|
||||||
|
// 加载完成触发事件并返回加载过的图片数
|
||||||
|
this.$emit('finishLoad', index)
|
||||||
|
return
|
||||||
|
};
|
||||||
|
const query = uni.createSelectorQuery().in(this);
|
||||||
|
let listFlag = 0;
|
||||||
|
query.selectAll('#wf-list').boundingClientRect(data => {
|
||||||
|
listFlag = data[0].bottom - data[1].bottom <= 0 ? 0 : 1;
|
||||||
|
this.viewList[listFlag].list.push(this.list[index])
|
||||||
|
}).exec()
|
||||||
|
},
|
||||||
|
async goDetail(a, b) {
|
||||||
|
let {
|
||||||
|
id
|
||||||
|
} = this.viewList[a].list[b]
|
||||||
|
let {
|
||||||
|
path
|
||||||
|
} = this
|
||||||
|
let page_url = path == 1 ? `` : `technician/`
|
||||||
|
let url = `/dynamic/pages/${page_url}detail?id=${id}`
|
||||||
|
this.$util.goUrl({
|
||||||
|
url,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.wf-list-container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: flex-start;
|
||||||
|
padding: 0 20rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wf-list {
|
||||||
|
width: calc(50% - 10rpx);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wf-item-child {
|
||||||
|
background: white;
|
||||||
|
margin-bottom: 20rpx;
|
||||||
|
border-radius: 16rpx;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
.examin-btn {
|
||||||
|
top: 20rpx;
|
||||||
|
left: 15rpx;
|
||||||
|
width: 89rpx;
|
||||||
|
height: 37rpx;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.play-video-info {
|
||||||
|
top: 0rpx;
|
||||||
|
width: 100%;
|
||||||
|
height: calc(100% - 128rpx);
|
||||||
|
z-index: 9;
|
||||||
|
|
||||||
|
.play-video {
|
||||||
|
width: 66rpx;
|
||||||
|
height: 66rpx;
|
||||||
|
background: rgba(2, 2, 2, 0.5);
|
||||||
|
|
||||||
|
.iconfont {
|
||||||
|
font-size: 28rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.cover {
|
||||||
|
width: 100%;
|
||||||
|
height: 100rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wf-item {
|
||||||
|
padding: 20rpx;
|
||||||
|
|
||||||
|
.avatar {
|
||||||
|
width: 40rpx;
|
||||||
|
height: 40rpx;
|
||||||
|
border-radius: 40rpx;
|
||||||
|
margin-right: 6rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.coach {
|
||||||
|
max-width: 100rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.iconfont {
|
||||||
|
font-size: 24rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,280 @@
|
||||||
|
<template>
|
||||||
|
<view class="xt__verify-code">
|
||||||
|
<!-- 输入框 -->
|
||||||
|
<input id="xt__input" :value="code" class="xt__input" :focus="isFocus" :password="isPassword" :type="inputType"
|
||||||
|
:maxlength="itemSize" @input="input" @focus="inputFocus" @blur="inputBlur" />
|
||||||
|
|
||||||
|
<!-- 光标 -->
|
||||||
|
<view id="xt__cursor" v-if="cursorVisible && type !== 'middle'" class="xt__cursor"
|
||||||
|
:style="{ left: codeCursorLeft[code.length] + 'px', height: cursorHeight + 'px', backgroundColor: cursorColor }">
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 输入框 - 组 -->
|
||||||
|
<view id="xt__input-ground" class="xt__input-ground">
|
||||||
|
<template v-for="(item, index) in itemSize">
|
||||||
|
<view :key="index"
|
||||||
|
:style="{ borderColor: code.length === index && cursorVisible ? boxActiveColor : boxNormalColor }"
|
||||||
|
:class="['xt__box', `xt__box-${type + ''}`, `xt__box::after`]">
|
||||||
|
<view :style="{ borderColor: boxActiveColor }" class="xt__middle-line"
|
||||||
|
v-if="type === 'middle' && !code[index]"></view>
|
||||||
|
<text class="xt__code-text">{{ code[index] | codeFormat(isPassword) }}</text>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
/**
|
||||||
|
* @description 输入验证码组件
|
||||||
|
* @property {string} type = [box|middle|bottom] - 显示类型 默认:box -eg:bottom
|
||||||
|
* @property {string} inputType = [text|number] - 输入框类型 默认:number -eg:number
|
||||||
|
* @property {number} size = [1|2|3|4|5|6] - 支持的验证码数量 默认:6 -eg:6
|
||||||
|
* @property {boolean} isFocus - 是否立即聚焦 默认:true
|
||||||
|
* @property {boolean} isPassword - 是否以密码形式显示 默认false -eg:false
|
||||||
|
* @property {string} cursorColor - 光标颜色 默认:#cccccc
|
||||||
|
* @property {string} boxNormalColor - 光标未聚焦到的框的颜色 默认:#f7f7f7
|
||||||
|
* @property {string} boxActiveColor - 光标聚焦到的框的颜色 默认:#009254
|
||||||
|
* @event {Function(data)} confirm - 输入完成
|
||||||
|
*/
|
||||||
|
export default {
|
||||||
|
name: 'xt-verify-code',
|
||||||
|
props: {
|
||||||
|
value: {
|
||||||
|
type: String,
|
||||||
|
default: () => ''
|
||||||
|
},
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
default: () => 'box'
|
||||||
|
},
|
||||||
|
inputType: {
|
||||||
|
type: String,
|
||||||
|
default: () => 'number'
|
||||||
|
},
|
||||||
|
size: {
|
||||||
|
type: Number,
|
||||||
|
default: () => 6
|
||||||
|
},
|
||||||
|
isFocus: {
|
||||||
|
type: Boolean,
|
||||||
|
default: () => true
|
||||||
|
},
|
||||||
|
isPassword: {
|
||||||
|
type: Boolean,
|
||||||
|
default: () => false
|
||||||
|
},
|
||||||
|
cursorColor: {
|
||||||
|
type: String,
|
||||||
|
default: () => '#cccccc'
|
||||||
|
},
|
||||||
|
boxNormalColor: {
|
||||||
|
type: String,
|
||||||
|
default: () => '#f7f7f7'
|
||||||
|
},
|
||||||
|
boxActiveColor: {
|
||||||
|
type: String,
|
||||||
|
default: () => '#009254'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
model: {
|
||||||
|
prop: 'value',
|
||||||
|
event: 'input'
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
cursorVisible: false,
|
||||||
|
cursorHeight: 35,
|
||||||
|
code: '', // 输入的验证码
|
||||||
|
codeCursorLeft: [], // 向左移动的距离数组,
|
||||||
|
itemSize: 6
|
||||||
|
};
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.cursorVisible = this.isFocus;
|
||||||
|
this.validatorSize();
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.init();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
validatorSize() {
|
||||||
|
if (this.size <= 6 && this.size > 0) {
|
||||||
|
this.itemSize = Math.floor(this.size);
|
||||||
|
} else {
|
||||||
|
this.itemSize = 6;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* @description 初始化
|
||||||
|
*/
|
||||||
|
init() {
|
||||||
|
this.getCodeCursorLeft();
|
||||||
|
this.setCursorHeight();
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* @description 获取元素节点
|
||||||
|
* @param {string} elm - 节点的id、class 相当于 document.querySelect的参数 -eg: #id
|
||||||
|
* @param {string} type = [single|array] - 单个元素获取多个元素 默认是单个元素
|
||||||
|
* @param {Function} callback - 回调函数
|
||||||
|
*/
|
||||||
|
getElement(elm, type = 'single', callback) {
|
||||||
|
uni
|
||||||
|
.createSelectorQuery()
|
||||||
|
.in(this)[type === 'array' ? 'selectAll' : 'select'](elm)
|
||||||
|
.boundingClientRect()
|
||||||
|
.exec(data => {
|
||||||
|
callback(data[0]);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* @description 计算光标的高度
|
||||||
|
*/
|
||||||
|
setCursorHeight() {
|
||||||
|
this.getElement('.xt__box', 'single', boxElm => {
|
||||||
|
this.cursorHeight = boxElm.height * 0.6;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* @description 获取光标在每一个box的left位置
|
||||||
|
*/
|
||||||
|
getCodeCursorLeft() {
|
||||||
|
// 获取父级框的位置信息
|
||||||
|
this.getElement('#xt__input-ground', 'single', parentElm => {
|
||||||
|
const parentLeft = parentElm.left;
|
||||||
|
// 获取各个box信息
|
||||||
|
this.getElement('.xt__box', 'array', elms => {
|
||||||
|
this.codeCursorLeft = [];
|
||||||
|
elms.forEach(elm => {
|
||||||
|
this.codeCursorLeft.push(elm.left - parentLeft + elm.width / 2);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// 输入框输入变化的回调
|
||||||
|
input(e) {
|
||||||
|
const value = e.detail.value;
|
||||||
|
this.cursorVisible = value.length !== this.itemSize;
|
||||||
|
this.$emit('input', value);
|
||||||
|
this.inputSuccess(value);
|
||||||
|
},
|
||||||
|
// 输入完成回调
|
||||||
|
inputSuccess(value) {
|
||||||
|
if (value.length === this.itemSize) {
|
||||||
|
this.$emit('confirm', value);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 输入聚焦
|
||||||
|
inputFocus() {
|
||||||
|
this.cursorVisible = this.code.length !== this.itemSize;
|
||||||
|
},
|
||||||
|
// 输入失去焦点
|
||||||
|
inputBlur() {
|
||||||
|
this.cursorVisible = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
value(val) {
|
||||||
|
this.code = val;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
filters: {
|
||||||
|
codeFormat(val, isPassword) {
|
||||||
|
let value = '';
|
||||||
|
if (val) {
|
||||||
|
value = isPassword ? '*' : val;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.xt__verify-code {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
.xt__input {
|
||||||
|
height: 100%;
|
||||||
|
width: 200%;
|
||||||
|
position: absolute;
|
||||||
|
left: -100%;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.xt__cursor {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
display: inline-block;
|
||||||
|
width: 2px;
|
||||||
|
animation-name: cursor;
|
||||||
|
animation-duration: 0.8s;
|
||||||
|
animation-iteration-count: infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.xt__input-ground {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
.xt__box {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
width: 88rpx;
|
||||||
|
height: 100rpx;
|
||||||
|
background: #F7F7F7;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
margin-left: 20rpx;
|
||||||
|
|
||||||
|
&-bottom {
|
||||||
|
border-bottom: 1rpx solid #009254;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-box {
|
||||||
|
border: 1rpx solid #009254;
|
||||||
|
}
|
||||||
|
|
||||||
|
&-middle {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.xt__middle-line {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
width: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
border-bottom-width: 2px;
|
||||||
|
border-bottom-style: solid;
|
||||||
|
}
|
||||||
|
|
||||||
|
.xt__code-text {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
font-size: 58rpx;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.xt__box:nth-child(1){
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes cursor {
|
||||||
|
0% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,206 @@
|
||||||
|
<template>
|
||||||
|
<view class="dynamic-follow">
|
||||||
|
<view @tap.stop="goDetail(index)"
|
||||||
|
class="list-item flex-center fill-base mt-md ml-md mr-md pd-lg radius-16 box-shadow"
|
||||||
|
v-for="(item,index) in list.data" :key="index">
|
||||||
|
<image mode="aspectFill" class="avatar radius" :src="item.work_img"></image>
|
||||||
|
<view class="flex-1 ml-md">
|
||||||
|
<view class="flex-between">
|
||||||
|
<view class="f-title c-black text-bold ellipsis" style="max-width: 150rpx;">{{item.coach_name}}
|
||||||
|
</view>
|
||||||
|
<view class="flex-y-baseline f-desc c-black"> <i class="iconfont iconjuli"
|
||||||
|
:style="{color:primaryColor}"></i>
|
||||||
|
{{item.distance}}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-y-baseline">
|
||||||
|
<view class="text flex-y-center f-desc">已接单<view class="ml-sm" :style="{color:primaryColor}">
|
||||||
|
{{item.order_num}}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="flex-y-center f-caption c-caption ml-md"> 粉丝数 <view class="c-title ml-sm">
|
||||||
|
{{item.fans_num}}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<load-more :noMore="list.current_page>=list.last_page&&list.data.length>0" :loading="loading" v-if="loading">
|
||||||
|
</load-more>
|
||||||
|
<abnor v-if="!loading&&list.data.length<=0&&list.current_page==1"></abnor>
|
||||||
|
<view class="space-footer"></view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
mapState,
|
||||||
|
mapActions,
|
||||||
|
mapMutations
|
||||||
|
} from "vuex"
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
loading: true,
|
||||||
|
param: {
|
||||||
|
page: 1
|
||||||
|
},
|
||||||
|
list: {
|
||||||
|
data: []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: mapState({
|
||||||
|
primaryColor: state => state.config.configInfo.primaryColor,
|
||||||
|
subColor: state => state.config.configInfo.subColor,
|
||||||
|
userInfo: state => state.user.userInfo,
|
||||||
|
location: state => state.user.location,
|
||||||
|
}),
|
||||||
|
onLoad() {
|
||||||
|
this.$util.setNavigationBarColor({
|
||||||
|
bg: this.primaryColor
|
||||||
|
})
|
||||||
|
this.$util.showLoading()
|
||||||
|
this.initIndex()
|
||||||
|
},
|
||||||
|
onPullDownRefresh() {
|
||||||
|
// #ifndef APP-PLUS
|
||||||
|
uni.showNavigationBarLoading()
|
||||||
|
// #endif
|
||||||
|
this.initRefresh();
|
||||||
|
uni.stopPullDownRefresh()
|
||||||
|
},
|
||||||
|
onReachBottom() {
|
||||||
|
if (this.list.current_page >= this.list.last_page || this.loading) return;
|
||||||
|
this.param.page = this.param.page + 1;
|
||||||
|
this.loading = true;
|
||||||
|
this.getList();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
...mapMutations(['updateUserItem']),
|
||||||
|
async initIndex(refresh = false) {
|
||||||
|
// #ifdef H5
|
||||||
|
if (!refresh && this.$jweixin.isWechat()) {
|
||||||
|
await this.$jweixin.initJssdk();
|
||||||
|
this.$jweixin.wxReady(() => {
|
||||||
|
this.$jweixin.hideOptionMenu()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
this.getList();
|
||||||
|
},
|
||||||
|
handerTabChange(index) {
|
||||||
|
this.activeIndex = index
|
||||||
|
this.param.status = index
|
||||||
|
this.getList();
|
||||||
|
},
|
||||||
|
initRefresh() {
|
||||||
|
this.param.page = 1
|
||||||
|
this.initIndex(true)
|
||||||
|
},
|
||||||
|
async getList() {
|
||||||
|
let {
|
||||||
|
list: oldList,
|
||||||
|
param,
|
||||||
|
location
|
||||||
|
} = this
|
||||||
|
if (!location.lat) {
|
||||||
|
// #ifdef H5
|
||||||
|
if (this.$jweixin.isWechat()) {
|
||||||
|
this.$util.showLoading()
|
||||||
|
// await this.$jweixin.initJssdk();
|
||||||
|
await this.$jweixin.wxReady2();
|
||||||
|
let {
|
||||||
|
latitude: lat = 0,
|
||||||
|
longitude: lng = 0
|
||||||
|
} = await this.$jweixin.getWxLocation()
|
||||||
|
location = {
|
||||||
|
lng,
|
||||||
|
lat,
|
||||||
|
address: '定位失败',
|
||||||
|
province: '',
|
||||||
|
city: '',
|
||||||
|
district: ''
|
||||||
|
}
|
||||||
|
if (lat && lng) {
|
||||||
|
let key = `${lat},${lng}`
|
||||||
|
let data = await this.$api.base.getMapInfo({
|
||||||
|
location: key
|
||||||
|
})
|
||||||
|
let {
|
||||||
|
status,
|
||||||
|
result
|
||||||
|
} = JSON.parse(data)
|
||||||
|
if (status == 0) {
|
||||||
|
let {
|
||||||
|
address,
|
||||||
|
address_component
|
||||||
|
} = result
|
||||||
|
let {
|
||||||
|
province,
|
||||||
|
city,
|
||||||
|
district
|
||||||
|
} = address_component
|
||||||
|
location = {
|
||||||
|
lng,
|
||||||
|
lat,
|
||||||
|
address,
|
||||||
|
province,
|
||||||
|
city,
|
||||||
|
district
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
// #ifndef H5
|
||||||
|
location = await this.$util.getBmapLocation()
|
||||||
|
// #endif
|
||||||
|
this.updateUserItem({
|
||||||
|
key: 'location',
|
||||||
|
val: location
|
||||||
|
})
|
||||||
|
}
|
||||||
|
let {
|
||||||
|
lat = 0, lng = 0
|
||||||
|
} = location
|
||||||
|
param.lat = lat
|
||||||
|
param.lng = lng
|
||||||
|
|
||||||
|
let newList = await this.$api.dynamic.followCoachList(param)
|
||||||
|
if (this.param.page == 1) {
|
||||||
|
this.list = newList
|
||||||
|
} else {
|
||||||
|
newList.data = oldList.data.concat(newList.data)
|
||||||
|
this.list = newList
|
||||||
|
}
|
||||||
|
this.loading = false
|
||||||
|
this.$util.hideAll()
|
||||||
|
},
|
||||||
|
goDetail(index) {
|
||||||
|
let {
|
||||||
|
coach_id
|
||||||
|
} = this.list.data[index]
|
||||||
|
this.$util.goUrl({
|
||||||
|
url: `/user/pages/technician-info?id=${coach_id}`
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.dynamic-follow {
|
||||||
|
.list-item {
|
||||||
|
.avatar {
|
||||||
|
width: 124rpx;
|
||||||
|
height: 124rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text {
|
||||||
|
color: #4D4D4D;
|
||||||
|
margin-top: 6rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,194 @@
|
||||||
|
<template>
|
||||||
|
<view class="dynamic-technician-comment">
|
||||||
|
<view @longpress="toDel(index)" class="list-item flex-warp ml-lg mr-lg pt-lg pb-lg"
|
||||||
|
:class="[{'b-1px-t':index!==0}]" v-for="(item,index) in list.data" :key="index">
|
||||||
|
<image mode="aspectFill" class="avatar radius" :src="item.avatarUrl"></image>
|
||||||
|
<view class="flex-1 ml-md">
|
||||||
|
<view class="flex-between">
|
||||||
|
<view>
|
||||||
|
<view class="flex-y-center f-paragraph c-title text-bold">
|
||||||
|
<view class="max-400 ellipsis">{{item.nickName}}</view>
|
||||||
|
<view class="examine-btn flex-center f-icontext ml-md radius" v-if="item.status==1">审核中
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="text flex-y-center f-caption">评论了你的动态<view class="ml-md">{{item.friend_time}}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<image mode="aspectFill" class="cover radius-16" :src="item.cover"></image>
|
||||||
|
</view>
|
||||||
|
<view class="comment f-paragraph mt-md"> {{item.text}} </view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<load-more :noMore="list.current_page>=list.last_page&&list.data.length>0" :loading="loading" v-if="loading">
|
||||||
|
</load-more>
|
||||||
|
<abnor v-if="!loading&&list.data.length<=0&&list.current_page==1"></abnor>
|
||||||
|
<view class="space-footer"></view>
|
||||||
|
<common-popup @confirm="confirmDel" ref="del_item" type="DELETE_ORDER" title="删除评论" desc="请确认是否删除评论,删除后将无法恢复"
|
||||||
|
:info="popupInfo"></common-popup>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
mapState,
|
||||||
|
mapActions,
|
||||||
|
mapMutations
|
||||||
|
} from "vuex"
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
loading: true,
|
||||||
|
param: {
|
||||||
|
page: 1
|
||||||
|
},
|
||||||
|
list: {
|
||||||
|
data: []
|
||||||
|
},
|
||||||
|
popupInfo: {},
|
||||||
|
lockTap: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: mapState({
|
||||||
|
primaryColor: state => state.config.configInfo.primaryColor,
|
||||||
|
subColor: state => state.config.configInfo.subColor,
|
||||||
|
configInfo: state => state.config.configInfo,
|
||||||
|
userInfo: state => state.user.userInfo,
|
||||||
|
}),
|
||||||
|
onLoad() {
|
||||||
|
this.$util.setNavigationBarColor({
|
||||||
|
bg: this.primaryColor
|
||||||
|
})
|
||||||
|
this.initIndex()
|
||||||
|
},
|
||||||
|
onPullDownRefresh() {
|
||||||
|
// #ifndef APP-PLUS
|
||||||
|
uni.showNavigationBarLoading()
|
||||||
|
// #endif
|
||||||
|
this.initRefresh();
|
||||||
|
uni.stopPullDownRefresh()
|
||||||
|
},
|
||||||
|
onReachBottom() {
|
||||||
|
if (this.list.current_page >= this.list.last_page || this.loading) return;
|
||||||
|
this.param.page = this.param.page + 1;
|
||||||
|
this.loading = true;
|
||||||
|
this.getList();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async initIndex(refresh = false) {
|
||||||
|
// #ifdef H5
|
||||||
|
if (!refresh && this.$jweixin.isWechat()) {
|
||||||
|
await this.$jweixin.initJssdk();
|
||||||
|
this.$jweixin.wxReady(() => {
|
||||||
|
this.$jweixin.hideOptionMenu()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
this.getList();
|
||||||
|
},
|
||||||
|
handerTabChange(index) {
|
||||||
|
this.activeIndex = index
|
||||||
|
this.param.status = index
|
||||||
|
this.getList();
|
||||||
|
},
|
||||||
|
initRefresh() {
|
||||||
|
this.param.page = 1
|
||||||
|
this.initIndex(true)
|
||||||
|
},
|
||||||
|
async getList() {
|
||||||
|
this.$util.showLoading()
|
||||||
|
let {
|
||||||
|
list: oldList,
|
||||||
|
param
|
||||||
|
} = this
|
||||||
|
let newList = await this.$api.dynamic.coachCommentList(param)
|
||||||
|
if (this.param.page == 1) {
|
||||||
|
this.list = newList
|
||||||
|
} else {
|
||||||
|
newList.data = oldList.data.concat(newList.data)
|
||||||
|
this.list = newList
|
||||||
|
}
|
||||||
|
this.loading = false
|
||||||
|
this.$util.hideAll()
|
||||||
|
},
|
||||||
|
toDel(index) {
|
||||||
|
let {
|
||||||
|
id,
|
||||||
|
cover: image
|
||||||
|
} = this.list.data[index]
|
||||||
|
this.popupInfo = {
|
||||||
|
id,
|
||||||
|
name: ``,
|
||||||
|
image,
|
||||||
|
index,
|
||||||
|
}
|
||||||
|
this.$refs.del_item.open()
|
||||||
|
},
|
||||||
|
// 确认:删除评论
|
||||||
|
async confirmDel() {
|
||||||
|
let {
|
||||||
|
id,
|
||||||
|
index,
|
||||||
|
} = this.popupInfo
|
||||||
|
if (this.lockTap) return
|
||||||
|
this.lockTap = true
|
||||||
|
this.$util.showLoading()
|
||||||
|
try {
|
||||||
|
await this.$api.dynamic.commentDel({
|
||||||
|
id
|
||||||
|
})
|
||||||
|
this.lockTap = false
|
||||||
|
this.$util.hideAll()
|
||||||
|
this.list.data.splice(index, 1)
|
||||||
|
this.$util.showToast({
|
||||||
|
title: `删除成功`
|
||||||
|
})
|
||||||
|
this.$refs.del_item.close()
|
||||||
|
} catch (e) {
|
||||||
|
setTimeout(() => {
|
||||||
|
this.lockTap = false
|
||||||
|
this.$util.hideAll()
|
||||||
|
}, 2000)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
page {
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dynamic-technician-comment {
|
||||||
|
.list-item {
|
||||||
|
.avatar {
|
||||||
|
width: 72rpx;
|
||||||
|
height: 72rpx;
|
||||||
|
margin-top: 16rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cover {
|
||||||
|
width: 107rpx;
|
||||||
|
height: 107rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text {
|
||||||
|
color: #ADADAD;
|
||||||
|
margin-top: 6rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.comment {
|
||||||
|
color: #3A3A3A;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.examine-btn {
|
||||||
|
width: 82rpx;
|
||||||
|
height: 34rpx;
|
||||||
|
color: #F96246;
|
||||||
|
background: rgba(249, 98, 70, 0.1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,273 @@
|
||||||
|
<template>
|
||||||
|
<view class="dynamic-technician-add">
|
||||||
|
<view class="pd-lg">
|
||||||
|
<view class="pb-md" :class="[{'flex-warp': subForm.type == 2 }]">
|
||||||
|
<view class="mr-md" v-if="subForm.type == 2">
|
||||||
|
<upload @upload="imgUpload" @del="imgUpload" :imagelist="subForm.cover" filetype="picture"
|
||||||
|
imgtype="cover" text="上传封面" :imgsize="1">
|
||||||
|
</upload>
|
||||||
|
</view>
|
||||||
|
<upload @upload="imgUpload" @del="imgUpload" :imagelist="subForm.imgs"
|
||||||
|
:filetype="subForm.type == 1 ? 'picture' : 'video'" imgtype="imgs"
|
||||||
|
:text="subForm.type == 1 ? '上传图片' : '上传视频'" :imgsize="subForm.type == 1 ? 9 : 1">
|
||||||
|
</upload>
|
||||||
|
</view>
|
||||||
|
<view class="space-md"></view>
|
||||||
|
<input v-model="subForm.title" class="f-mini-title c-title" type="text" placeholder="填写标题有更多赞哟~"
|
||||||
|
placeholder-class="f-mini-title c-caption" maxlength="10" />
|
||||||
|
<view class="space-lg b-1px-b"></view>
|
||||||
|
<view class="space-lg"></view>
|
||||||
|
<textarea v-model="subForm.text" class="textarea f-desc c-title" maxlength="400"
|
||||||
|
placeholder="还有更多的想法也一起写到正文吧~" placeholder-class="f-desc c-caption"></textarea>
|
||||||
|
</view>
|
||||||
|
<view @tap.stop="toChooseLocation" class="pt-lg pl-lg pr-md flex-center f-desc">
|
||||||
|
<i class="iconfont icon-dingwei"></i>
|
||||||
|
<view class="flex-1 ml-sm mr-lg c-title ellipsis-2">
|
||||||
|
{{subForm.lat ? subForm.address : '添加地点'}}
|
||||||
|
</view>
|
||||||
|
<i class="iconfont icongengduo"></i>
|
||||||
|
</view>
|
||||||
|
<view class="space-max-footer"></view>
|
||||||
|
<fix-bottom-button @confirm="submit" :text="[{text:subForm.id?'编辑动态':'发布动态',type:'confirm'}]" bgColor="#fff">
|
||||||
|
</fix-bottom-button>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
mapState,
|
||||||
|
mapActions,
|
||||||
|
mapMutations
|
||||||
|
} from "vuex"
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
options: {},
|
||||||
|
subForm: {
|
||||||
|
id: 0,
|
||||||
|
cover: [],
|
||||||
|
imgs: [],
|
||||||
|
type: 1,
|
||||||
|
title: '',
|
||||||
|
text: '',
|
||||||
|
lat: '',
|
||||||
|
lng: '',
|
||||||
|
address: ''
|
||||||
|
},
|
||||||
|
rule: [{
|
||||||
|
name: "cover",
|
||||||
|
checkType: "isNotNull",
|
||||||
|
errorMsg: "请上传封面图"
|
||||||
|
}, {
|
||||||
|
name: "imgs",
|
||||||
|
checkType: "isNotNull",
|
||||||
|
errorMsg: ""
|
||||||
|
}, {
|
||||||
|
name: "title",
|
||||||
|
checkType: "isNotNull",
|
||||||
|
errorMsg: "请输入标题",
|
||||||
|
regType: 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "text",
|
||||||
|
checkType: "isNotNull",
|
||||||
|
errorMsg: "请输入正文内容",
|
||||||
|
regType: 2
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "address",
|
||||||
|
checkType: "isNotNull",
|
||||||
|
errorMsg: "请选择定位地点"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
lockTap: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: mapState({
|
||||||
|
primaryColor: state => state.config.configInfo.primaryColor,
|
||||||
|
subColor: state => state.config.configInfo.subColor,
|
||||||
|
configInfo: state => state.config.configInfo,
|
||||||
|
userInfo: state => state.user.userInfo,
|
||||||
|
location: state => state.user.location,
|
||||||
|
haveShieldOper: state => state.user.haveShieldOper,
|
||||||
|
}),
|
||||||
|
onLoad(options) {
|
||||||
|
let {
|
||||||
|
type
|
||||||
|
} = options
|
||||||
|
type = type * 1
|
||||||
|
this.options = options
|
||||||
|
this.subForm.type = type
|
||||||
|
this.rule[1].errorMsg = type == 1 ? '请上传图片' : '请上传视频'
|
||||||
|
this.initIndex()
|
||||||
|
this.$util.setNavigationBarColor({
|
||||||
|
bg: this.primaryColor
|
||||||
|
})
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
...mapMutations(['updateUserItem']),
|
||||||
|
async initIndex() {
|
||||||
|
let {
|
||||||
|
id = 0
|
||||||
|
} = this.options
|
||||||
|
if (!id) return
|
||||||
|
let data = await this.$api.dynamic.coachDynamicInfo({
|
||||||
|
id
|
||||||
|
})
|
||||||
|
data.cover = [{
|
||||||
|
path: data.cover
|
||||||
|
}]
|
||||||
|
data.imgs = data.imgs.map(item => {
|
||||||
|
return {
|
||||||
|
path: item
|
||||||
|
}
|
||||||
|
})
|
||||||
|
for (let key in this.subForm) {
|
||||||
|
this.subForm[key] = data[key]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
imgUpload(e) {
|
||||||
|
let {
|
||||||
|
imagelist,
|
||||||
|
imgtype
|
||||||
|
} = e;
|
||||||
|
this.subForm[imgtype] = imagelist;
|
||||||
|
},
|
||||||
|
// 选择地区
|
||||||
|
async toChooseLocation(e) {
|
||||||
|
await this.$util.checkAuth({
|
||||||
|
type: 'userLocation'
|
||||||
|
})
|
||||||
|
let {
|
||||||
|
lat: locaLat = '',
|
||||||
|
lng: locaLng = ''
|
||||||
|
} = this.location
|
||||||
|
let {
|
||||||
|
id = 0,
|
||||||
|
lat: addrLat,
|
||||||
|
lng: addrLng
|
||||||
|
} = this.subForm
|
||||||
|
|
||||||
|
if (id) {
|
||||||
|
locaLat = addrLat
|
||||||
|
locaLng = addrLng
|
||||||
|
}
|
||||||
|
|
||||||
|
let param = {}
|
||||||
|
if (!locaLat && !locaLng) {
|
||||||
|
// #ifdef H5
|
||||||
|
if (this.$jweixin.isWechat()) {
|
||||||
|
this.$util.showLoading()
|
||||||
|
await this.$jweixin.wxReady2();
|
||||||
|
let {
|
||||||
|
latitude,
|
||||||
|
longitude
|
||||||
|
} = await this.$jweixin.getWxLocation()
|
||||||
|
locaLat = latitude
|
||||||
|
locaLng = longitude
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
// #ifdef APP-PLUS
|
||||||
|
let location = await this.$util.getBmapLocation()
|
||||||
|
locaLat = location.lat
|
||||||
|
locaLng = location.lng
|
||||||
|
// #endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// #ifndef MP-WEIXIN
|
||||||
|
param = {
|
||||||
|
latitude: locaLat,
|
||||||
|
longitude: locaLng
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
let [, {
|
||||||
|
address = '',
|
||||||
|
longitude: lng,
|
||||||
|
latitude: lat,
|
||||||
|
}] = await uni.chooseLocation(param);
|
||||||
|
if (!lng) return
|
||||||
|
this.subForm.address = address
|
||||||
|
this.subForm.lat = lat
|
||||||
|
this.subForm.lng = lng
|
||||||
|
},
|
||||||
|
//表单验证
|
||||||
|
validate(param) {
|
||||||
|
let validate = new this.$util.Validate();
|
||||||
|
this.rule.map(item => {
|
||||||
|
let {
|
||||||
|
name,
|
||||||
|
} = item
|
||||||
|
validate.add(param[name], item);
|
||||||
|
})
|
||||||
|
let message = validate.start();
|
||||||
|
return message;
|
||||||
|
},
|
||||||
|
async submit() {
|
||||||
|
let subForm = this.$util.deepCopy(this.subForm)
|
||||||
|
subForm.imgs = subForm.imgs && subForm.imgs.length > 0 ? subForm.imgs.map(item => {
|
||||||
|
return item.path
|
||||||
|
}) : []
|
||||||
|
let url = subForm.type == 1 ? subForm.imgs.length > 0 ? subForm.imgs[0] : '' : subForm.cover && subForm
|
||||||
|
.cover.length > 0 ? subForm.cover[0].path : ''
|
||||||
|
subForm.cover = url
|
||||||
|
let msg = this.validate(subForm);
|
||||||
|
if (msg) {
|
||||||
|
this.$util.showToast({
|
||||||
|
title: msg
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (this.lockTap) return
|
||||||
|
this.lockTap = true
|
||||||
|
this.$util.showLoading()
|
||||||
|
try {
|
||||||
|
let methodModel = subForm.id ? 'dynamicUpdate' : 'dynamicAdd'
|
||||||
|
let {
|
||||||
|
status = 1
|
||||||
|
} = await this.$api.dynamic[methodModel](subForm)
|
||||||
|
this.$util.hideAll()
|
||||||
|
this.$util.showToast({
|
||||||
|
title: status == 1 ? '正在审核中' : subForm.id ? `编辑成功` : `发布成功`
|
||||||
|
})
|
||||||
|
this.updateUserItem({
|
||||||
|
key: 'haveShieldOper',
|
||||||
|
val: 1
|
||||||
|
})
|
||||||
|
setTimeout(() => {
|
||||||
|
this.$util.back()
|
||||||
|
this.$util.goUrl({
|
||||||
|
url: 1,
|
||||||
|
openType: `navigateBack`
|
||||||
|
})
|
||||||
|
}, 2000)
|
||||||
|
} catch (e) {
|
||||||
|
setTimeout(() => {
|
||||||
|
this.lockTap = false
|
||||||
|
this.$util.hideAll()
|
||||||
|
}, 2000)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
page {
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dynamic-technician-add {
|
||||||
|
.icon-dingwei {
|
||||||
|
font-size: 28rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icongengduo {
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #9B9B9B;
|
||||||
|
}
|
||||||
|
|
||||||
|
.textarea {
|
||||||
|
width: 690rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,130 @@
|
||||||
|
<template>
|
||||||
|
<view class="dynamic-technician-follow">
|
||||||
|
<view class="list-item flex-center ml-lg mr-lg pt-lg pb-lg" :class="[{'b-1px-t':index!==0}]"
|
||||||
|
v-for="(item,index) in list.data" :key="index">
|
||||||
|
<image mode="aspectFill" class="avatar radius" :src="item.avatarUrl"></image>
|
||||||
|
<view class="flex-1 flex-between ml-md">
|
||||||
|
<view>
|
||||||
|
<view class="f-paragraph c-title text-bold max-470 ellipsis">{{item.nickName}}</view>
|
||||||
|
<view class="text f-caption">开始关注了你</view>
|
||||||
|
</view>
|
||||||
|
<view class="time f-icontext">{{item.friend_time}}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<load-more :noMore="list.current_page>=list.last_page&&list.data.length>0" :loading="loading" v-if="loading">
|
||||||
|
</load-more>
|
||||||
|
<abnor v-if="!loading&&list.data.length<=0&&list.current_page==1"></abnor>
|
||||||
|
<view class="space-footer"></view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
mapState,
|
||||||
|
mapActions,
|
||||||
|
mapMutations
|
||||||
|
} from "vuex"
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
loading: true,
|
||||||
|
param: {
|
||||||
|
page: 1
|
||||||
|
},
|
||||||
|
list: {
|
||||||
|
data: []
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: mapState({
|
||||||
|
primaryColor: state => state.config.configInfo.primaryColor,
|
||||||
|
subColor: state => state.config.configInfo.subColor,
|
||||||
|
configInfo: state => state.config.configInfo,
|
||||||
|
userInfo: state => state.user.userInfo,
|
||||||
|
}),
|
||||||
|
onLoad() {
|
||||||
|
this.$util.setNavigationBarColor({
|
||||||
|
bg: this.primaryColor
|
||||||
|
})
|
||||||
|
this.initIndex()
|
||||||
|
},
|
||||||
|
onPullDownRefresh() {
|
||||||
|
// #ifndef APP-PLUS
|
||||||
|
uni.showNavigationBarLoading()
|
||||||
|
// #endif
|
||||||
|
this.initRefresh();
|
||||||
|
uni.stopPullDownRefresh()
|
||||||
|
},
|
||||||
|
onReachBottom() {
|
||||||
|
if (this.list.current_page >= this.list.last_page || this.loading) return;
|
||||||
|
this.param.page = this.param.page + 1;
|
||||||
|
this.loading = true;
|
||||||
|
this.getList();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async initIndex(refresh = false) {
|
||||||
|
// #ifdef H5
|
||||||
|
if (!refresh && this.$jweixin.isWechat()) {
|
||||||
|
await this.$jweixin.initJssdk();
|
||||||
|
this.$jweixin.wxReady(() => {
|
||||||
|
this.$jweixin.hideOptionMenu()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
this.getList();
|
||||||
|
},
|
||||||
|
handerTabChange(index) {
|
||||||
|
this.activeIndex = index
|
||||||
|
this.param.status = index
|
||||||
|
this.getList();
|
||||||
|
},
|
||||||
|
|
||||||
|
initRefresh() {
|
||||||
|
this.param.page = 1
|
||||||
|
this.initIndex(true)
|
||||||
|
},
|
||||||
|
async getList() {
|
||||||
|
this.$util.showLoading()
|
||||||
|
let {
|
||||||
|
list: oldList,
|
||||||
|
param
|
||||||
|
} = this
|
||||||
|
let newList = await this.$api.dynamic.followList(param)
|
||||||
|
if (this.param.page == 1) {
|
||||||
|
this.list = newList
|
||||||
|
} else {
|
||||||
|
newList.data = oldList.data.concat(newList.data)
|
||||||
|
this.list = newList
|
||||||
|
}
|
||||||
|
this.loading = false
|
||||||
|
this.$util.hideAll()
|
||||||
|
},
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
page {
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dynamic-technician-follow {
|
||||||
|
.list-item {
|
||||||
|
.avatar {
|
||||||
|
width: 72rpx;
|
||||||
|
height: 72rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text {
|
||||||
|
color: #ADADAD;
|
||||||
|
margin-top: 6rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.time {
|
||||||
|
color: #9B9B9B;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,341 @@
|
||||||
|
<template>
|
||||||
|
<view class="dynamic-technician-list" v-if="isLoad">
|
||||||
|
<fixed>
|
||||||
|
<view class="fill-body">
|
||||||
|
<view class="count-list flex-center fill-base">
|
||||||
|
<view @tap.stop="$util.goUrl({url:`/dynamic/pages/technician/thumbs`})"
|
||||||
|
class="count-item flex-center flex-column f-caption c-title">
|
||||||
|
<view class="tag thumbs flex-center rel">
|
||||||
|
<i class="iconfont icon-shoucang-fill"></i>
|
||||||
|
<view class="count-tag flex-center f-icontext c-base abs"
|
||||||
|
:style="{width: count.thumbs_num < 10 ? '26rpx':'50rpx',right:count.thumbs_num < 10 ? '-13rpx':'-38rpx'}"
|
||||||
|
v-if="count.thumbs_num">
|
||||||
|
{{count.thumbs_num < 100 ? count.thumbs_num : '99+'}}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="mt-md">收获的赞</view>
|
||||||
|
</view>
|
||||||
|
<view @tap.stop="$util.goUrl({url:`/dynamic/pages/technician/follow`})"
|
||||||
|
class="count-item flex-center flex-column f-caption c-title">
|
||||||
|
<view class="tag follow flex-center rel">
|
||||||
|
<i class="iconfont iconxinzengguanzhu"></i>
|
||||||
|
<view class="count-tag flex-center f-icontext c-base abs"
|
||||||
|
:style="{width: count.follow_num < 10 ? '26rpx':'50rpx',right:count.follow_num < 10 ? '-13rpx':'-38rpx'}"
|
||||||
|
v-if="count.follow_num">
|
||||||
|
{{count.follow_num < 100 ? count.follow_num : '99+'}}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="mt-md">新增关注</view>
|
||||||
|
</view>
|
||||||
|
<view @tap.stop="$util.goUrl({url:`/dynamic/pages/technician/comment`})"
|
||||||
|
class="count-item flex-center flex-column f-caption c-title">
|
||||||
|
<view class="tag comment flex-center rel">
|
||||||
|
<i class="iconfont iconshouhuodepinglun"></i>
|
||||||
|
<view class="count-tag flex-center f-icontext c-base abs"
|
||||||
|
:style="{width: count.comment_num < 10 ? '26rpx':'50rpx',right:count.comment_num < 10 ? '-13rpx':'-38rpx'}"
|
||||||
|
v-if="count.comment_num">
|
||||||
|
{{count.comment_num < 100 ? count.comment_num : '99+'}}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="mt-md">收获的评论</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="rel">
|
||||||
|
<view class="flex-between pd-lg">
|
||||||
|
<view class="f-title text-bold">我的发布</view>
|
||||||
|
<view @tap.stop="toChangeItem(-1)" class="flex-y-center f-desc">
|
||||||
|
{{statusList[statusInd].title}}<i class="iconfont c-desc ml-sm"
|
||||||
|
:class="[{'iconshaixuanxia-1':showSort},{'iconshaixuanshang-1':!showSort}]"
|
||||||
|
style="font-size: 20rpx"></i>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<view class="dynamic-sort pt-md pb-md f-desc abs" v-if="showSort">
|
||||||
|
<view @tap.stop="toChangeItem(index)" class="sort-item flex-center"
|
||||||
|
:style="{color:statusInd == index ? primaryColor : ''}" v-for="(item,index) in statusList"
|
||||||
|
:key="index">
|
||||||
|
{{item.title}}
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</fixed>
|
||||||
|
|
||||||
|
<wfalls-flow :list="list.data" :path="2" ref="wfalls" v-if="list.data.length > 0"></wfalls-flow>
|
||||||
|
<load-more :noMore="list.current_page>=list.last_page&&list.data.length>0" :loading="loading" v-if="loading">
|
||||||
|
</load-more>
|
||||||
|
<abnor v-if="!loading&&list.data.length<=0&&list.current_page==1"></abnor>
|
||||||
|
<view class="space-footer"></view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
mapState,
|
||||||
|
mapActions,
|
||||||
|
mapMutations
|
||||||
|
} from "vuex"
|
||||||
|
import wfallsFlow from "@/components/wfalls-flow.vue"
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
wfallsFlow
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
isLoad: false,
|
||||||
|
statusList: [{
|
||||||
|
id: 0,
|
||||||
|
title: '全部'
|
||||||
|
}, {
|
||||||
|
id: 1,
|
||||||
|
title: '审核中'
|
||||||
|
}, {
|
||||||
|
id: 2,
|
||||||
|
title: '审核通过'
|
||||||
|
}, {
|
||||||
|
id: 3,
|
||||||
|
title: '已驳回'
|
||||||
|
}],
|
||||||
|
statusInd: 0,
|
||||||
|
showSort: false,
|
||||||
|
loading: true,
|
||||||
|
param: {
|
||||||
|
page: 1,
|
||||||
|
limit: 10,
|
||||||
|
status: 0
|
||||||
|
},
|
||||||
|
list: {
|
||||||
|
data: []
|
||||||
|
},
|
||||||
|
count: {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: mapState({
|
||||||
|
primaryColor: state => state.config.configInfo.primaryColor,
|
||||||
|
subColor: state => state.config.configInfo.subColor,
|
||||||
|
configInfo: state => state.config.configInfo,
|
||||||
|
userInfo: state => state.user.userInfo,
|
||||||
|
location: state => state.user.location,
|
||||||
|
haveShieldOper: state => state.user.haveShieldOper,
|
||||||
|
}),
|
||||||
|
onLoad() {
|
||||||
|
this.$util.setNavigationBarColor({
|
||||||
|
bg: this.primaryColor
|
||||||
|
})
|
||||||
|
this.$util.showLoading()
|
||||||
|
this.initIndex()
|
||||||
|
},
|
||||||
|
async onShow() {
|
||||||
|
if (this.haveShieldOper == 1) {
|
||||||
|
await this.initRefresh()
|
||||||
|
this.updateUserItem({
|
||||||
|
key: 'haveShieldOper',
|
||||||
|
val: 0
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
this.getDynamicData()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async onPullDownRefresh() {
|
||||||
|
// #ifndef APP-PLUS
|
||||||
|
uni.showNavigationBarLoading()
|
||||||
|
// #endif
|
||||||
|
await this.initRefresh();
|
||||||
|
uni.stopPullDownRefresh()
|
||||||
|
},
|
||||||
|
async onReachBottom() {
|
||||||
|
if (this.list.current_page >= this.list.last_page || this.loading) return;
|
||||||
|
this.param.page = this.param.page + 1;
|
||||||
|
this.loading = true;
|
||||||
|
await this.getList();
|
||||||
|
setTimeout(() => {
|
||||||
|
this.$refs.wfalls.handleViewRender();
|
||||||
|
}, 0)
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
...mapMutations(['updateUserItem']),
|
||||||
|
async initIndex(refresh = false) {
|
||||||
|
// #ifdef H5
|
||||||
|
if (!refresh && this.$jweixin.isWechat()) {
|
||||||
|
await this.$jweixin.initJssdk();
|
||||||
|
this.$jweixin.wxReady(() => {
|
||||||
|
this.$jweixin.hideOptionMenu()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
if (refresh) {
|
||||||
|
await Promise.all([this.getDynamicData(), this.getList(1)])
|
||||||
|
} else {
|
||||||
|
await this.getList(1)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async initRefresh() {
|
||||||
|
await this.initIndex(true)
|
||||||
|
},
|
||||||
|
async getDynamicData() {
|
||||||
|
this.count = await this.$api.dynamic.dynamicData()
|
||||||
|
},
|
||||||
|
async getList(flag) {
|
||||||
|
if (flag) {
|
||||||
|
this.showSort = false
|
||||||
|
this.param.page = 1
|
||||||
|
this.list.data = []
|
||||||
|
}
|
||||||
|
let {
|
||||||
|
location
|
||||||
|
} = this
|
||||||
|
if (!location.lat) {
|
||||||
|
// #ifdef H5
|
||||||
|
if (this.$jweixin.isWechat()) {
|
||||||
|
this.$util.showLoading()
|
||||||
|
// await this.$jweixin.initJssdk();
|
||||||
|
await this.$jweixin.wxReady2();
|
||||||
|
let {
|
||||||
|
latitude: lat = 0,
|
||||||
|
longitude: lng = 0
|
||||||
|
} = await this.$jweixin.getWxLocation()
|
||||||
|
location = {
|
||||||
|
lng,
|
||||||
|
lat,
|
||||||
|
address: '定位失败',
|
||||||
|
province: '',
|
||||||
|
city: '',
|
||||||
|
district: ''
|
||||||
|
}
|
||||||
|
if (lat && lng) {
|
||||||
|
let key = `${lat},${lng}`
|
||||||
|
let data = await this.$api.base.getMapInfo({
|
||||||
|
location: key
|
||||||
|
})
|
||||||
|
let {
|
||||||
|
status,
|
||||||
|
result
|
||||||
|
} = JSON.parse(data)
|
||||||
|
if (status == 0) {
|
||||||
|
let {
|
||||||
|
address,
|
||||||
|
address_component
|
||||||
|
} = result
|
||||||
|
let {
|
||||||
|
province,
|
||||||
|
city,
|
||||||
|
district
|
||||||
|
} = address_component
|
||||||
|
location = {
|
||||||
|
lng,
|
||||||
|
lat,
|
||||||
|
address,
|
||||||
|
province,
|
||||||
|
city,
|
||||||
|
district
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
// #ifndef H5
|
||||||
|
location = await this.$util.getBmapLocation()
|
||||||
|
// #endif
|
||||||
|
this.updateUserItem({
|
||||||
|
key: 'location',
|
||||||
|
val: location
|
||||||
|
})
|
||||||
|
}
|
||||||
|
let {
|
||||||
|
lat = 0, lng = 0
|
||||||
|
} = location
|
||||||
|
|
||||||
|
let {
|
||||||
|
list: oldList,
|
||||||
|
param,
|
||||||
|
statusList,
|
||||||
|
statusInd
|
||||||
|
} = this
|
||||||
|
param.lat = lat
|
||||||
|
param.lng = lng
|
||||||
|
param.status = statusList[statusInd].id
|
||||||
|
let newList = await this.$api.dynamic.coachDynamicList(param)
|
||||||
|
if (this.param.page == 1) {
|
||||||
|
this.list = newList
|
||||||
|
} else {
|
||||||
|
newList.data = oldList.data.concat(newList.data)
|
||||||
|
this.list = newList
|
||||||
|
}
|
||||||
|
this.isLoad = true
|
||||||
|
this.loading = false
|
||||||
|
this.$util.hideAll()
|
||||||
|
},
|
||||||
|
toChangeItem(index) {
|
||||||
|
if (index == -1) {
|
||||||
|
this.showSort = !this.showSort
|
||||||
|
} else {
|
||||||
|
this.statusInd = index
|
||||||
|
this.showSort = false
|
||||||
|
this.initRefresh()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.dynamic-technician-list {
|
||||||
|
.count-list {
|
||||||
|
width: 750rpx;
|
||||||
|
height: 204rpx;
|
||||||
|
|
||||||
|
.count-item {
|
||||||
|
width: 33.33%;
|
||||||
|
|
||||||
|
.tag {
|
||||||
|
width: 85rpx;
|
||||||
|
height: 85rpx;
|
||||||
|
border-radius: 29rpx;
|
||||||
|
|
||||||
|
.iconfont {
|
||||||
|
font-size: 44rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.count-tag {
|
||||||
|
top: 0;
|
||||||
|
right: -13rpx;
|
||||||
|
width: 26rpx;
|
||||||
|
height: 26rpx;
|
||||||
|
background: #E82F21;
|
||||||
|
border-radius: 26rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.thumbs {
|
||||||
|
color: #ff6262;
|
||||||
|
background: #FFEFEF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.follow {
|
||||||
|
color: #FC8218;
|
||||||
|
background: #FEF6E7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.comment {
|
||||||
|
color: #44A860;
|
||||||
|
background: #ECF6EF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.dynamic-sort {
|
||||||
|
top: 80rpx;
|
||||||
|
right: 32rpx;
|
||||||
|
width: 145rpx;
|
||||||
|
background: #FEFFFE;
|
||||||
|
box-shadow: 0 14rpx 20rpx 0 rgba(132, 132, 132, 0.08);
|
||||||
|
border-radius: 4rpx;
|
||||||
|
border: 1rpx solid #EFEFEF;
|
||||||
|
transform: rotateZ(360deg);
|
||||||
|
z-index: 1;
|
||||||
|
|
||||||
|
.sort-item {
|
||||||
|
padding: 15rpx 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,126 @@
|
||||||
|
<template>
|
||||||
|
<view class="dynamic-technician-thumbs">
|
||||||
|
<view class="list-item flex-center ml-lg mr-lg pt-lg pb-lg" :class="[{'b-1px-t':index!==0}]"
|
||||||
|
v-for="(item,index) in list.data" :key="index">
|
||||||
|
<image mode="aspectFill" class="avatar radius" :src="item.avatarUrl"></image>
|
||||||
|
<view class="flex-1 flex-between ml-md">
|
||||||
|
<view>
|
||||||
|
<view class="f-paragraph c-title text-bold max-470 ellipsis">{{item.nickName}}</view>
|
||||||
|
<view class="text flex-y-center f-caption">赞了你的动态<view class="ml-md">{{item.friend_time}}</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<image mode="aspectFill" class="cover radius-16" :src="item.cover"></image>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<load-more :noMore="list.current_page>=list.last_page&&list.data.length>0" :loading="loading" v-if="loading">
|
||||||
|
</load-more>
|
||||||
|
<abnor v-if="!loading&&list.data.length<=0&&list.current_page==1"></abnor>
|
||||||
|
<view class="space-footer"></view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
mapState,
|
||||||
|
mapActions,
|
||||||
|
mapMutations
|
||||||
|
} from "vuex"
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
loading: true,
|
||||||
|
param: {
|
||||||
|
page: 1
|
||||||
|
},
|
||||||
|
list: {
|
||||||
|
data: []
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: mapState({
|
||||||
|
primaryColor: state => state.config.configInfo.primaryColor,
|
||||||
|
subColor: state => state.config.configInfo.subColor,
|
||||||
|
configInfo: state => state.config.configInfo,
|
||||||
|
userInfo: state => state.user.userInfo,
|
||||||
|
}),
|
||||||
|
onLoad() {
|
||||||
|
this.$util.setNavigationBarColor({
|
||||||
|
bg: this.primaryColor
|
||||||
|
})
|
||||||
|
this.initIndex()
|
||||||
|
},
|
||||||
|
onPullDownRefresh() {
|
||||||
|
// #ifndef APP-PLUS
|
||||||
|
uni.showNavigationBarLoading()
|
||||||
|
// #endif
|
||||||
|
this.initRefresh();
|
||||||
|
uni.stopPullDownRefresh()
|
||||||
|
},
|
||||||
|
onReachBottom() {
|
||||||
|
if (this.list.current_page >= this.list.last_page || this.loading) return;
|
||||||
|
this.param.page = this.param.page + 1;
|
||||||
|
this.loading = true;
|
||||||
|
this.getList();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async initIndex(refresh = false) {
|
||||||
|
// #ifdef H5
|
||||||
|
if (!refresh && this.$jweixin.isWechat()) {
|
||||||
|
await this.$jweixin.initJssdk();
|
||||||
|
this.$jweixin.wxReady(() => {
|
||||||
|
this.$jweixin.hideOptionMenu()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
this.getList();
|
||||||
|
},
|
||||||
|
initRefresh() {
|
||||||
|
this.param.page = 1
|
||||||
|
this.initIndex(true)
|
||||||
|
},
|
||||||
|
async getList() {
|
||||||
|
this.$util.showLoading()
|
||||||
|
let {
|
||||||
|
list: oldList,
|
||||||
|
param
|
||||||
|
} = this
|
||||||
|
let newList = await this.$api.dynamic.thumbsList(param)
|
||||||
|
if (this.param.page == 1) {
|
||||||
|
this.list = newList
|
||||||
|
} else {
|
||||||
|
newList.data = oldList.data.concat(newList.data)
|
||||||
|
this.list = newList
|
||||||
|
}
|
||||||
|
this.loading = false
|
||||||
|
this.$util.hideAll()
|
||||||
|
},
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
page {
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dynamic-technician-thumbs {
|
||||||
|
.list-item {
|
||||||
|
.avatar {
|
||||||
|
width: 72rpx;
|
||||||
|
height: 72rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cover {
|
||||||
|
width: 107rpx;
|
||||||
|
height: 107rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text {
|
||||||
|
color: #ADADAD;
|
||||||
|
margin-top: 6rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -0,0 +1,30 @@
|
||||||
|
# jweixin-module
|
||||||
|
|
||||||
|
微信JS-SDK
|
||||||
|
|
||||||
|
## 安装
|
||||||
|
|
||||||
|
### NPM
|
||||||
|
|
||||||
|
```shell
|
||||||
|
npm install jweixin-module --save
|
||||||
|
```
|
||||||
|
|
||||||
|
### UMD
|
||||||
|
|
||||||
|
```http
|
||||||
|
https://unpkg.com/jweixin-module/out/index.js
|
||||||
|
```
|
||||||
|
|
||||||
|
## 使用
|
||||||
|
|
||||||
|
```js
|
||||||
|
var jweixin = require('jweixin-module')
|
||||||
|
jweixin.ready(function(){
|
||||||
|
// TODO
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
## 完整API
|
||||||
|
|
||||||
|
>[微信JS-SDK说明文档](https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115)
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,53 @@
|
||||||
|
{
|
||||||
|
"_from": "jweixin-module",
|
||||||
|
"_id": "jweixin-module@1.6.0",
|
||||||
|
"_inBundle": false,
|
||||||
|
"_integrity": "sha512-dGk9cf+ipipHmtzYmKZs5B2toX+p4hLyllGLF6xuC8t+B05oYxd8fYoaRz0T30U2n3RUv8a4iwvjhA+OcYz52w==",
|
||||||
|
"_location": "/jweixin-module",
|
||||||
|
"_phantomChildren": {},
|
||||||
|
"_requested": {
|
||||||
|
"type": "tag",
|
||||||
|
"registry": true,
|
||||||
|
"raw": "jweixin-module",
|
||||||
|
"name": "jweixin-module",
|
||||||
|
"escapedName": "jweixin-module",
|
||||||
|
"rawSpec": "",
|
||||||
|
"saveSpec": null,
|
||||||
|
"fetchSpec": "latest"
|
||||||
|
},
|
||||||
|
"_requiredBy": [
|
||||||
|
"#USER"
|
||||||
|
],
|
||||||
|
"_resolved": "https://registry.npmjs.org/jweixin-module/-/jweixin-module-1.6.0.tgz",
|
||||||
|
"_shasum": "4a7ea614083e3c9c3f49e2fdc2bb882cfa58dfcd",
|
||||||
|
"_spec": "jweixin-module",
|
||||||
|
"_where": "D:\\node-v12.12.0",
|
||||||
|
"author": {
|
||||||
|
"name": "Shengqiang Guo"
|
||||||
|
},
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/zhetengbiji/jweixin-module/issues"
|
||||||
|
},
|
||||||
|
"bundleDependencies": false,
|
||||||
|
"deprecated": false,
|
||||||
|
"description": "微信JS-SDK",
|
||||||
|
"devDependencies": {},
|
||||||
|
"homepage": "https://github.com/zhetengbiji/jweixin-module#readme",
|
||||||
|
"keywords": [
|
||||||
|
"wxjssdk",
|
||||||
|
"weixin",
|
||||||
|
"jweixin",
|
||||||
|
"wechat",
|
||||||
|
"jssdk",
|
||||||
|
"wx"
|
||||||
|
],
|
||||||
|
"license": "ISC",
|
||||||
|
"main": "lib/index.js",
|
||||||
|
"name": "jweixin-module",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/zhetengbiji/jweixin-module.git"
|
||||||
|
},
|
||||||
|
"scripts": {},
|
||||||
|
"version": "1.6.0"
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
import zhCnLocale from './lang/zh-CN';
|
||||||
|
import enUsLocale from './lang/en-US';
|
||||||
|
import VueI18n from 'vue-i18n';
|
||||||
|
import Vue from 'vue';
|
||||||
|
Vue.use(VueI18n);
|
||||||
|
const i18n = new VueI18n({
|
||||||
|
locale: 'zh',
|
||||||
|
messages: {
|
||||||
|
'en': enUsLocale,
|
||||||
|
'zh': zhCnLocale
|
||||||
|
}
|
||||||
|
})
|
||||||
|
export default i18n
|
|
@ -0,0 +1,5 @@
|
||||||
|
export default {
|
||||||
|
action: {
|
||||||
|
attendantName: 'technician'
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
export default {
|
||||||
|
action: {
|
||||||
|
attendantName: '技师',
|
||||||
|
agreeRefund: '立即退款',
|
||||||
|
transferOrder: '转单',
|
||||||
|
orderTaking: '技师接单',
|
||||||
|
setOut: '技师出发',
|
||||||
|
arrive: '技师到达',
|
||||||
|
startService: '开始服务',
|
||||||
|
serviceCompletion: '服务完成',
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue