Commit cc6b6400 by 莫晓莉

Initial commit

parents
<script>
export default {
onLaunch: function() {
console.log('App Launch')
},
onShow: function() {
//查看有没有登录
// let token = uni.getStorageSync('token');
// if(!token){
// uni.reLaunch({
// url:'pages/login/login',
// })
// }
console.log('App Show');
},
onHide: function() {
console.log('App Hide')
},
// globalData:{
// tabBar: {
// "color": "#999999",
// "selectedColor": "#2e7dfe",
// "borderStyle": "white",
// "backgroundColor": "#ffffff",
// "list": [{
// "pagePath": "pages/index/index",
// "iconPath": "static/ic_icon-01.png",
// "selectedIconPath": "static/ic_icon-05.png",
// "text": "首页"
// },
// {
// "pagePath": "pages/project/project",
// "iconPath": "static/ic_icon-02.png",
// "selectedIconPath": "static/ic_icon-06.png",
// "text": "服务项目"
// },
// {
// "pagePath": "pages/staff/staff",
// "iconPath": "static/ic_icon-03.png",
// "selectedIconPath": "static/ic_icon-07.png",
// "text": "残疾人员"
// },
// {
// "pagePath": "pages/center/center",
// "iconPath": "static/ic_icon-04.png",
// "selectedIconPath": "static/ic_icon-08.png",
// "text": "个人中心"
// }
// ]
// }
// }
}
</script>
<style>
/*每个页面公共css */
@import "./components/iconfont.css";
@import "./components/style.css";
/* -------------残联start------------------ */
@import './common/common.css';
/* page{
padding-bottom:250upx;
} */
/* page {
min-height: 100%;
display: flex;
font-size: 16px;
flex:1;
}
page {
width: 100%;
height: 100%;
display: block;
}
swan-template {
width: 100%;
min-height: 100%;
display: flex;
}
custom-component {
width: 100%;
min-height: 100%;
display: flex;
}
page {
min-height: 100vh;
}
m-input {
width: 100%;
display: flex;
flex: 1;
}
.content {
display: flex;
flex: 1;
flex-direction: column;
background-color: #efeff4;
padding: 10px;
} */
/* .input-group {
background-color: #ffffff;
margin-top: 20px;
position: relative;
}
.input-group::before {
position: absolute;
right: 0;
top: 0;
left: 0;
height: 1px;
content: '';
-webkit-transform: scaleY(.5);
transform: scaleY(.5);
background-color: #c8c7cc;
}
.input-group::after {
position: absolute;
right: 0;
bottom: 0;
left: 0;
height: 1px;
content: '';
-webkit-transform: scaleY(.5);
transform: scaleY(.5);
background-color: #c8c7cc;
}
.input-row {
display: flex;
flex-direction: row;
position: relative;
font-size: 18px;
line-height: 40px;
}
.input-row .title {
width: 100px;
padding-left: 15px;
}
.input-row.border::after {
position: absolute;
right: 0;
bottom: 0;
left: 8px;
height: 1px;
content: '';
-webkit-transform: scaleY(.5);
transform: scaleY(.5);
background-color: #c8c7cc;
}
.btn-row {
margin-top: 25px;
padding: 10px;
}
button.primary {
background-color: #0faeff;
} */
/* 空 */
page {
min-height: 100%;
display: flex;
font-size: 16px;
flex:1;
}
.empty-v{
padding:250upx 0 0 0;text-align: center;color:#bcbcbc;
}
.empty-v .empty-icon{
display:block;width:100upx;height:100upx;margin:15upx auto;
}
.content {
display: flex;
flex: 1;
flex-direction: column;
background-color: #efeff4;
padding: 10px;
}
/* -------------残联end-------------------- */
</style>
// import request from "@/utils/request"
import request from "../utils/request"
//登录
export const login = (data) => {
return request('login', data)
}
//注册
export const register = (data) => {
return request('register', data)
}
//获取验证码
export const sendCode = (data) => {
return request('sendCode', data)
}
//获取用户信息
export const getUserByToken = (data) => {
return request('getUserByToken', data)
}
//获取项目类型
export const getProjectTypeList = (data) => {
return request('getProjectTypeList', data)
}
//申请服务
export const applyProject = (data) => {
return request('applyProject', data)
}
//意见反馈
export const satisfactionEvaluation = (data) => {
return request('satisfactionEvaluation', data,'POST')
}
//获取已审批的项目
export const getApplyProject = (data) => {
return request('getApplyProject', data)
}
//获取历史反馈
export const getSatisfactionEvaluation = (data) => {
return request('getSatisfactionEvaluation', data)
}
page{
display: flex;
flex-direction: column;
width:100%;
}
.flex{
/*display: flex;兼容写法开始*/
display: -webkit-box; /* 老版本语法: Safari, iOS, Android browser, older WebKit browsers. */
display: -moz-box; /* 老版本语法: Firefox (buggy) */
display: -ms-flexbox; /* 混合版本语法: IE 10 */
display: -webkit-flex; /* 新版本语法: Chrome 21+ */
display: flex; /* 新版本语法: Opera 12.1, Firefox 22+ */
/*display: flex;兼容写法结束*/
}
.flex-ac{
/*align-items兼容写法开始*/
-webkit-align-items:center;
-ms-flex-align:center;
align-items:center;
-webkit-box-align:center;
/*align-items兼容写法开始*/
}
.flex-jc{
-webkit-box-pack: center;
-ms-flex-pack: center;
-webkit-justify-content: center;
justify-content: center;
}
.flex-dc{
-webkit-box-orient: vertical;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
}
.flex-jb{
/*justify-content:space-between;兼容写法开始*/
-webkit-box-pack:justify;
-webkit-justify-content:space-between;
-ms-flex-pack:justify;
justify-content:space-between;
/*align-items兼容写法开始*/
}
.flex-col-b{
/*display: flex;兼容写法开始*/
display: -webkit-box; /* 老版本语法: Safari, iOS, Android browser, older WebKit browsers. */
display: -moz-box; /* 老版本语法: Firefox (buggy) */
display: -ms-flexbox; /* 混合版本语法: IE 10 */
display: -webkit-flex; /* 新版本语法: Chrome 21+ */
display: flex; /* 新版本语法: Opera 12.1, Firefox 22+ */
/*display: flex;兼容写法结束*/
-webkit-box-orient: vertical;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
/*justify-content:space-between;兼容写法开始*/
-webkit-box-pack:justify;
-webkit-justify-content:space-between;
-ms-flex-pack:justify;
justify-content:space-between;
/*align-items兼容写法开始*/
}
.flex-a-c{
/*display: flex;兼容写法开始*/
display: -webkit-box; /* 老版本语法: Safari, iOS, Android browser, older WebKit browsers. */
display: -moz-box; /* 老版本语法: Firefox (buggy) */
display: -ms-flexbox; /* 混合版本语法: IE 10 */
display: -webkit-flex; /* 新版本语法: Chrome 21+ */
display: flex; /* 新版本语法: Opera 12.1, Firefox 22+ */
/*display: flex;兼容写法结束*/
/*align-items兼容写法开始*/
-webkit-align-items:center;
-ms-flex-align:center;
align-items:center;
-webkit-box-align:center;
/*align-items兼容写法开始*/
}
.flex-ac-jc{
/*display: flex;兼容写法开始*/
display: -webkit-box; /* 老版本语法: Safari, iOS, Android browser, older WebKit browsers. */
display: -moz-box; /* 老版本语法: Firefox (buggy) */
display: -ms-flexbox; /* 混合版本语法: IE 10 */
display: -webkit-flex; /* 新版本语法: Chrome 21+ */
display: flex; /* 新版本语法: Opera 12.1, Firefox 22+ */
/*display: flex;兼容写法结束*/
/*align-items兼容写法开始*/
-webkit-align-items:center;
-ms-flex-align:center;
align-items:center;
-webkit-box-align:center;
/*align-items兼容写法开始*/
-webkit-box-pack: center;
-ms-flex-pack: center;
-webkit-justify-content: center;
justify-content: center;
}
.flex-ac-jb{
/*display: flex;兼容写法开始*/
display: -webkit-box; /* 老版本语法: Safari, iOS, Android browser, older WebKit browsers. */
display: -moz-box; /* 老版本语法: Firefox (buggy) */
display: -ms-flexbox; /* 混合版本语法: IE 10 */
display: -webkit-flex; /* 新版本语法: Chrome 21+ */
display: flex; /* 新版本语法: Opera 12.1, Firefox 22+ */
/*display: flex;兼容写法结束*/
/*align-items兼容写法开始*/
-webkit-align-items:center;
-ms-flex-align:center;
align-items:center;
-webkit-box-align:center;
/*align-items兼容写法开始*/
/*justify-content:space-between;兼容写法开始*/
-webkit-box-pack:justify;
-webkit-justify-content:space-between;
-ms-flex-pack:justify;
justify-content:space-between;
/*align-items兼容
写法开始*/
}
.flex1{
-prefix-box-flex: 1;
-webkit-box-flex: 1;
-webkit-flex: 1;
-moz-box-flex: 1;
-ms-flex: 1;
flex: 1;
}
.ellipsis2{
display:-webkit-box;
-webkit-box-orient:vertical;
-webkit-line-clamp:2;
overflow:hidden;
}
.flex-wrap{
-webkit-flex-wrap: wrap;
-moz-flex-wrap: wrap;
-ms-flex-wrap: wrap;
-o-flex-wrap: wrap;
flex-wrap: wrap;
}
checkbox .wx-checkbox-input {
width: 35rpx;
height: 35rpx;
}
checkbox .wx-checkbox-input.wx-checkbox-input-checked {
border: none;
background: #38B0A5;
}
checkbox .wx-checkbox-input.wx-checkbox-input-checked::before {
border-radius: 50%;
width: 40rpx;
height: 40rpx;
line-height: 40rpx;
text-align: center;
font-size: 30rpx;
color: #fff;
}
button{
border:none;
border-radius:0;
}
button::after{
border: none;
border-radius: 0;
}
.flex-bt{
/*display: flex;兼容写法开始*/
display: -webkit-box; /* 老版本语法: Safari, iOS, Android browser, older WebKit browsers. */
display: -moz-box; /* 老版本语法: Firefox (buggy) */
display: -ms-flexbox; /* 混合版本语法: IE 10 */
display: -webkit-flex; /* 新版本语法: Chrome 21+ */
display: flex; /* 新版本语法: Opera 12.1, Firefox 22+ */
/*display: flex;兼容写法结束*/
/*justify-content:space-between;兼容写法开始*/
-webkit-box-pack:justify;
-webkit-justify-content:space-between;
-ms-flex-pack:justify;
justify-content:space-between;
/*align-items兼容*/
}
checkbox .wx-checkbox-input {
border-radius: 50%;
width: 40rpx;
height: 40rpx;
}
\ No newline at end of file
@font-face {font-family: "iconfont";
src: url('https://at.alicdn.com/iconfont.eot?t=1602294263390'); /* IE9 */
src: url('https://at.alicdn.com/iconfont.eot?t=1602294263390#iefix') format('embedded-opentype'), /* IE6-IE8 */
url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAAWUAAsAAAAACsgAAAVGAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCDbAqHaIYiATYCJAMgCxIABCAFhG0HexsnCciOkVuMOJb/F3/i4b/9aPfNzJc1bWrRMIualoqnrezpmDcqqYmVAnk1VOSHd9NeEqjgNU/rs4orsjtPIQFPLw0VZWczh07FkZnSU/ns/xwzXT4fWH7b2iU7cDQMHtCAIi+i6UTvQA4PxE/kFvEsLqTgxJy4nECncVMhl6obpeClgE2B2NaqCfDK6JUGXGhVdcWhJeI9cLXpBXobwDv3/XEE6eFFUmWw8/r9KhWU7qLjLZhlwgKfGgQI8KyYHUXGKlCI55X2h4CF+CpM5+Z3ObaAXq2k3kXdEneWO89tGG+ZmCCLau6E4dAr4lQKLhfhL09D1Li8m2LvJhp2UUWhYldCobCbRSGzm0ch2DVQSOw1U6jZa6nTgNYc0g/0EQsA8Ri4cs3Jy1OxZYlW908OT48PQnjdXNJPbz3ocMg4drtU5HTKuS6XguQlFS7z3759DJYFgCVguWDYwhe+2hYUZMtEkA8rA62B0hI6ebK1SZdvqYuAZcx/Gbfy5mwt51CdbVWnKsWczMPX4+L8KzlSDhha/txSAyJMUMv1MwLhbayBW29mHyWcropLrsC5DvyRK9LxRPruqXyPPdfp9HfYpWudyWcXsztk3baj70NZD29fE0Cqlll2zA1So8zrl1sPrw6QbTm2znT63KvgtuVe022dbrlrXOH4ILO/H5TM2TljV6LPlh2W7SrPVbvm7gCPwCmeSim3rly1LUi4fMuKMX/pss3K5fzl6T3UtrU7D/urKOuc7ZYA8mRnIVl+lnqEIJD6jZJjR+uRjZn/1raDFyXxv53xLfiZl+SVImnQ926bLqgTKwb7MxPqBUk8mTE7e925t2c+1mxXF9xXDPTqG4SiByd7jx4WiG/sokYK+cKdbb3upaLn0/pnHp2ygC1TxlKxnHixzXyoWtyvmZzgFS229hysfj0wkx/vGaNmy4591WkN2zqzDlouT/48aKj1k1AFgk1ULyiJsM0c+KgtvXxe47uzjzrSuNhNUcntozO/FRgNTxs+DhFWab2amuf4Nwbqvty+sB0e6QDdbtqpqHzeupvzIjM2I/FF/On459Ka2Ng4gFMfeaOGiZO7fh81inae4rZuwJxOzgbBMboNWCLFLJd62i9yMJB+FRyZybnEQXP5Ss+OYo5PfRThOzN+piRC0hvfe0sZgfTGzfTNnyKuF9x/XnzTV2WO3DDzQERPVV/qc1beh592AfrTvrNScYd7s/RFbGZixov4W/F3aqTp6eUAZwH+H8JeYK0ApN/of8un7cWeYhaA/zfzGawIgHSAhgKQd9BP/7w/Y+DPkcVfiAv/9eIX8Gtb+v/O99/CgeH8f6BCZ8Ff1VG8fKCirQgMbVl3qD5tVi+wFM93fExppxjgL+oe9JIpRzoXE1ojCSSNMchas8iCXYVKlzWotc5CpxU1R3cZwsBE6cCy7wiEfvsg6fUJsn53kAX7AiqjfoVaf2DQaSv8TtllPrS8CoYkWFKFd/bjWiVtoqSJ5fnSdlJtNhBMWuTwcpLp1obwtOTUfKqGNJEMxh7dPep0lqVwiqGNeDW5Gmkw0HgXQ+tIJZusYdmu/JQUquqDkpW0EXguYpAILJIKrlM/nJYSzYQy41m8wte3I6mZGRCYhp4bdjkSo5t2elyaZKkdkDVyU6ee5zK/Ww+1dCwWxddRGDQjXDW1kgwiTsN1VS/TISmxkmkGRLvkS2H9qK7y5OMrja/0BHSCU7eRIkeJKupooo0OvbcJk5qWFSotYdKYCUyZaMkjkeqK2SxtzuJRRK2F0GmN1INFNATN7bN2A+HNeB11AAAA') format('woff2'),
url('https://at.alicdn.com/iconfont.woff?t=1602294263390') format('woff'),
url('https://at.alicdn.com/iconfont.ttf?t=1602294263390') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */
url('https://at.alicdn.com/iconfont.svg?t=1602294263390#iconfont') format('svg'); /* iOS 4.1- */
}
.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-bangongdianhua:before {
content: "\e639";
}
.icon-huo:before {
content: "\e66c";
}
.icon-iconfontjiantou5:before {
content: "\e635";
}
.icon-fangdajing:before {
content: "\e610";
}
.icon-jiahao:before {
content: "\e602";
}
.icon-xiala:before {
content: "\e74e";
}
.icon-xialaicon:before {
content: "\e74f";
}
import { getColumns } from '../utils'
export const commonMixin = {
data () {
return {
indicatorStyle: `height: 34px`
}
},
created () {
this.init('init')
},
methods: {
init (changeType) {
if (this.list && this.list.length) {
const column = getColumns({
value: this.value,
list: this.list,
mode: this.mode,
props: this.props,
level: this.level
})
const { columns, value, item, index } = column
this.selectValue = value
this.selectItem = item
this.pickerColumns = columns
this.pickerValue = index
this.$emit('change', {
value: this.selectValue,
item: this.selectItem,
index: this.pickerValue,
change: changeType
})
}
}
},
watch: {
value () {
if (!this.isConfirmChange) {
this.init('value')
}
},
list () {
this.init('list')
}
}
}
<template>
<view class="lb-multi-selector lb-picker-item"
:style="{ height: height }">
<picker-view :value="pickerValue"
:indicator-style="indicatorStyle"
:style="{ height: height }"
@change="handleChange">
<picker-view-column v-for="(column, index) in pickerColumns"
:key="index">
<view v-for="(item, i) in column || []"
:class="[
'lb-picker-column',
item[props.value] === selectValue[index]
? 'lb-picker-column-active'
: ''
]"
:key="i">
<text class="lb-picker-column-label">
{{ item[props.label] || item }}
</text>
</view>
</picker-view-column>
</picker-view>
</view>
</template>
<script>
import { commonMixin } from '../mixins'
export default {
props: {
value: Array,
list: Array,
mode: String,
props: Object,
level: Number,
visible: Boolean,
height: String,
isConfirmChange: Boolean
},
mixins: [commonMixin],
data () {
return {
pickerValue: [],
pickerColumns: [],
selectValue: [],
selectItem: []
}
},
methods: {
handleChange (item) {
const pickerValue = item.detail.value
const columnIndex = pickerValue.findIndex((item, i) => item !== this.pickerValue[i])
const valueIndex = pickerValue[columnIndex]
this.setPickerChange(pickerValue, valueIndex, columnIndex)
},
setPickerChange (pickerValue, valueIndex, columnIndex) {
for (let i = 0; i < this.level; i++) {
if (i > columnIndex) {
pickerValue[i] = 0
const column =
this.pickerColumns[i - 1][valueIndex] ||
this.pickerColumns[i - 1][0]
this.$set(this.pickerColumns, i, column[this.props.children] || [])
valueIndex = 0
}
this.$set(this.pickerValue, i, pickerValue[i])
const selectItem = this.pickerColumns[i][pickerValue[i]]
if (selectItem) {
this.selectItem[i] = selectItem
this.selectValue[i] = selectItem[this.props.value]
} else {
const spliceNum = this.level - i
this.pickerValue.splice(i, spliceNum)
this.selectValue.splice(i, spliceNum)
this.selectItem.splice(i, spliceNum)
this.pickerColumns.splice(i, spliceNum)
break
}
}
this.$emit('change', {
value: this.selectValue,
item: this.selectItem,
index: this.pickerValue,
change: 'scroll'
})
}
}
}
</script>
<style lang="scss" scoped>
@import "../style/picker-item.scss";
</style>
<template>
<view class="lb-selector-picker lb-picker-item"
:style="{ height: height }">
<picker-view :value="pickerValue"
:style="{ height: height }"
:indicator-style="indicatorStyle"
@change="handleChange">
<picker-view-column>
<view v-for="(item, i) in list"
:class="[
'lb-picker-column',
(item[props.value] || item) === selectValue
? 'lb-picker-column-active'
: ''
]"
:key="i">
<text class="lb-picker-column-label">
{{ item[props.label] || item }}
</text>
</view>
</picker-view-column>
</picker-view>
</view>
</template>
<script>
import { isObject } from '../utils'
import { commonMixin } from '../mixins'
export default {
props: {
value: [String, Number],
list: Array,
mode: String,
props: Object,
visible: Boolean,
height: String,
isConfirmChange: Boolean
},
mixins: [commonMixin],
data () {
return {
pickerValue: [],
selectValue: '',
selectItem: null
}
},
methods: {
handleChange (item) {
const index = item.detail.value[0] || 0
this.selectItem = this.list[index]
this.selectValue = isObject(this.selectItem)
? this.selectItem[this.props.value]
: this.selectItem
this.pickerValue = item.detail.value
this.$emit('change', {
value: this.selectValue,
item: this.selectItem,
index: index,
change: 'scroll'
})
}
}
}
</script>
<style lang="scss" scoped>
@import "../style/picker-item.scss";
</style>
<template>
<view class="lb-selector-picker lb-picker-item"
:style="{ height: height }">
<picker-view :value="pickerValue"
:indicator-style="indicatorStyle"
:style="{ height: height }"
@change="handleChange">
<picker-view-column v-for="(column, index) in pickerColumns"
:key="index">
<view v-for="(item, i) in column || []"
:class="[
'lb-picker-column',
(item[props.value] || item) === selectValue[index]
? 'lb-picker-column-active'
: ''
]"
:key="i">
<text class="lb-picker-column-label">
{{ item[props.label] || item }}
</text>
</view>
</picker-view-column>
</picker-view>
</view>
</template>
<script>
import { isObject } from '../utils'
import { commonMixin } from '../mixins'
export default {
props: {
value: Array,
list: Array,
mode: String,
props: Object,
visible: Boolean,
height: String,
isConfirmChange: Boolean
},
mixins: [commonMixin],
data () {
return {
pickerValue: [],
pickerColumns: [],
selectValue: [],
selectItem: []
}
},
methods: {
handleChange (item) {
const pickerValue = item.detail.value
const columnIndex = pickerValue.findIndex((item, i) => item !== this.pickerValue[i])
if (columnIndex > -1) {
const valueIndex = pickerValue[columnIndex]
const columnItem = this.list[columnIndex][valueIndex]
const valueItem = isObject(columnItem)
? columnItem[this.props.value]
: columnItem
this.pickerValue = pickerValue
this.$set(this.selectValue, columnIndex, valueItem)
this.$set(this.selectItem, columnIndex, columnItem)
this.$emit('change', {
value: this.selectValue,
item: this.selectItem,
index: this.pickerValue,
change: 'scroll'
})
}
}
}
}
</script>
<style lang="scss" scoped>
@import "../style/picker-item.scss";
</style>
.lb-picker-column {
height: 34px;
/* #ifndef APP-NVUE */
display: flex;
box-sizing: border-box;
white-space: nowrap;
overflow: hidden;
/* #endif */
flex-direction: row;
align-items: center;
justify-content: center;
}
.lb-picker-column-label {
font-size: 26rpx;
text-align: center;
text-overflow: ellipsis;
transition-property: color;
transition-duration: 0.3s;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
\ No newline at end of file
.lb-picker {
position: relative;
}
.lb-picker-mask {
background-color: rgba(0, 0, 0, 0.0);
position: fixed;
top: 0;
right: 0;
left: 0;
bottom: 0;
}
.lb-picker-mask-animation {
transition-property: background-color;
transition-duration: 0.3s;
}
.lb-picker-container {
position: relative;
}
.lb-picker-container-fixed {
position: fixed;
left: 0;
right: 0;
bottom: 0;
transform: translateY(100%);
/* #ifndef APP-PLUS */
overflow: hidden;
/* #endif */
}
.lb-picker-container-animation {
transition-property: transform;
transition-duration: 0.3s;
}
.lb-picker-container-show {
transform: translateY(0);
}
.lb-picker-header {
position: relative;
height: 45px;
background-color: #fff;
/* #ifdef APP-NVUE */
border-bottom-width: 1px;
border-bottom-style: solid;
border-bottom-color: #e5e5e5;
border-top-width: 1px;
border-top-style: solid;
border-top-color: #e5e5e5;
/* #endif */
/* #ifndef APP-NVUE */
box-sizing: border-box;
display: flex;
/* #endif */
flex-direction: row;
justify-content: space-between;
flex-wrap: nowrap;
}
/* #ifndef APP-PLUS */
.lb-picker-header::before {
content: "";
position: absolute;
left: 0;
top: 0;
right: 0;
height: 1px;
clear: both;
border-bottom: 1px solid #e5e5e5;
color: #e5e5e5;
transform-origin: 0 100%;
transform: scaleY(0.5);
}
.lb-picker-header::after {
content: "";
position: absolute;
left: 0;
bottom: 0;
right: 0;
height: 1px;
clear: both;
border-bottom: 1px solid #e5e5e5;
color: #e5e5e5;
transform-origin: 0 100%;
transform: scaleY(0.5);
}
/* #endif */
.lb-picker-action {
padding-left: 14px;
padding-right: 14px;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
align-items: center;
justify-content: center;
}
.lb-picker-action-item {
text-align: center;
height: 45px;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
align-items: center;
}
.lb-picker-action-cancel-text {
font-size: 16px;
color: #999;
}
.lb-picker-action-confirm-text {
font-size: 16px;
color: #007aff;
}
.lb-picker-content {
position: relative;
background-color: #fff;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
justify-content: center;
flex-direction: column;
}
.lb-picker-loading,
.lb-picker-empty {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
justify-content: center;
align-items: center;
}
.lb-picker-empty-text {
color: #999;
font-size: 16px;
}
.lb-picker-loading-img {
width: 25px;
height: 25px;
/* #ifndef APP-NVUE */
animation: rotating 2s linear infinite;
/* #endif */
}
/* #ifndef APP-NVUE */
@keyframes rotating {
0% {
transform: rotate(0deg)
}
to {
transform: rotate(1turn)
}
}
/* #endif */
\ No newline at end of file
/**
* 判断是否是对象
*
* @export
* @param {*} val
* @returns true/false
*/
export function isObject (val) {
return Object.prototype.toString.call(val) === '[object Object]'
}
/**
* 根据value获取columns信息
*
* @export
* @param {*} { value, list, mode, props, level }
* @param {number} [type=2] 查询不到value数据返回数据类型 1空值null 2默认第一个选项
* @returns
*/
export function getColumns ({ value, list, mode, props, level }, type = 2) {
let pickerValue = []
let pickerColumns = []
let selectValue = []
let selectItem = []
let columnsInfo = null
switch (mode) {
case 'selector':
let index = list.findIndex(item => {
return isObject(item) ? item[props.value] === value : item === value
})
if (index === -1 && type === 1) {
columnsInfo = null
} else {
index = index > -1 ? index : 0
selectItem = list[index]
selectValue = isObject(selectItem)
? selectItem[props.value]
: selectItem
pickerColumns = list
pickerValue = [index]
columnsInfo = {
index: pickerValue,
value: selectValue,
item: selectItem,
columns: pickerColumns
}
}
break
case 'multiSelector':
const setPickerItems = (data = [], index = 0) => {
if (!data.length) return
const defaultValue = value || []
if (index < level) {
const value = defaultValue[index] || ''
let i = data.findIndex(item => item[props.value] === value)
if (i === -1 && type === 1) return
i = i > -1 ? i : 0
pickerValue[index] = i
pickerColumns[index] = data
if (data[i]) {
selectValue[index] = data[i][props.value]
selectItem[index] = data[i]
setPickerItems(data[i][props.children] || [], index + 1)
}
}
}
setPickerItems(list)
if (!selectValue.length && type === 1) {
columnsInfo = null
} else {
columnsInfo = {
index: pickerValue,
value: selectValue,
item: selectItem,
columns: pickerColumns
}
}
break
case 'unlinkedSelector':
list.forEach((item, i) => {
let index = item.findIndex(item => {
return isObject(item)
? item[props.value] === value[i]
: item === value[i]
})
if (index === -1 && type === 1) return
index = index > -1 ? index : 0
const columnItem = list[i][index]
const valueItem = isObject(columnItem)
? columnItem[props.value]
: columnItem
pickerValue[i] = index
selectValue[i] = valueItem
selectItem[i] = columnItem
})
pickerColumns = list
if (!selectValue.length && type === 1) {
columnsInfo = null
} else {
columnsInfo = {
index: pickerValue,
value: selectValue,
item: selectItem,
columns: pickerColumns
}
}
break
}
return columnsInfo
}
<template>
<view class="wrapper" v-show="isShowMask">
<transition name="content">
<view class="content_view" v-show="isShow">
<!-- 选中数据 -->
<view class="select_top">
<view class="select_top_item" ref="select_top_item" v-for="(item,index) in dataList" :key="index"
@click="select_top_item_click(index)">
<text class="address_value">{{item}}</text>
</view>
<view class="indicator" :style="{ left: indicatorStyleLeft + 'px' }" ref="indicator"></view>
<view class="selectbtns" @click="sure_address_choose">确认</view>
</view>
<!-- 数据列表 -->
<swiper class="swiperlist" :current="currentIndex" @change="swiperChange">
<swiper-item v-for="(swiper_item,swiper_index) in dataList" :key="swiper_index">
<view class="swiper-item">
<scroll-view class="scroll-view-item" scroll-y="true">
<view class="cu-list menu">
<view class="cu-item" v-for="(item,index) in cityAreaArray[swiper_index]" :key="index"
@click="address_item_click(swiper_index,index)">
<view class="content">
<text class="text-df" :class="selectIndexArr[swiper_index] === index?'text-blue':''">{{item.name}}</text>
</view>
</view>
</view>
</scroll-view>
</view>
</swiper-item>
</swiper>
</view>
</transition>
<view class="mask" @click="hidden" v-show="isShowMask"></view>
</view>
</template>
<script>
let self;
export default {
data() {
return {
isShow: false,
isShowMask: false,
dataList: ['请选择'],
currentIndex: 0,
cityAreaArray: [],
selectIndexArr: [],
chooseAreaArray:[],
currentObj: {},
indicatorStyleLeft: 16
};
},
props: {
pickerUrl: {
type: String,
default: '',
},
pickerSize: {
type: Number,
default: 5,
},
pid: {
type: Number,
default: parseInt(uni.getStorageSync('user').u_depart)
}
},
methods: {
//显示控件
show() {
this.isShow = true
this.isShowMask = true
},
//隐藏控件
hidden() {
setTimeout(() => {
this.isShowMask = false
this.isShow = false
}, 100);
},
//点击层级
select_top_item_click(index) {
this.currentIndex = index
},
//切换数据列表
swiperChange(event) {
this.currentIndex = event.detail.current
if(this.currentIndex <= this.chooseAreaArray.length){
this.dataList.splice(this.currentIndex)
this.dataList.splice(this.currentIndex + 1, 0, '请选择')
}
this.chooseAreaArray.splice(this.currentIndex);
},
//加载数据列表
changeIndicator(index, pid) {
this.currentIndex = index;
this.getadd(index, pid);
},
//点击选中数据列表
address_item_click(swiper_index, index) {
this.selectIndexArr.splice(swiper_index, 5, index);
this.currentObj = this.cityAreaArray[swiper_index][index];
//判断当前是否为最下一级
if (swiper_index < this.pickerSize - 1) {
this.chooseAreaArray.push(this.currentObj.id);
this.dataList.splice(swiper_index, 5, this.currentObj.name)
this.dataList.splice(swiper_index + 1, 0, '请选择')
setTimeout(() => {
this.changeIndicator(swiper_index + 1, this.currentObj.id)
}, 50);
} else { //是最下一级
if(this.chooseAreaArray.length === 4){
this.chooseAreaArray.pop()
}
this.chooseAreaArray.push(this.currentObj.id);
this.dataList.splice(swiper_index, 1, this.currentObj.name)
this.returnPicker()
}
},
sure_address_choose(){
let returnData = {
'id_arr': this.chooseAreaArray,
'current':this.currentObj
}
this.$emit("selectAddress", returnData);
this.hidden();
},
//返回数据
returnPicker() {
let returnData = {
'id_arr': this.chooseAreaArray,
'current':this.currentObj
}
this.$emit("selectAddress", returnData);
this.hidden();
},
//动态加载数据
getadd(index, pid) {
uni.request({
url: this.pickerUrl,
data: {
pid: pid
},
success: function(res) {
self.cityAreaArray.splice(index, 0, res.data.data)
if (res.data.count == 0) {
//无下一级直接返回
self.returnPicker();
}
}
});
},
},
created() {
self = this;
this.getadd(0, this.pid)
},
mounted() {}
}
</script>
<style>
.selectbtns{
font-size: 28rpx;
font-weight: bold;
min-width: 10%;
}
.cu-list{
padding: 20rpx 30rpx 30rpx 30rpx;
height: 86%;
overflow-y: auto;
}
.cu-item{
font-size: 28rpx;
line-height: 68rpx;
}
.wrapper {
z-index: 1999;
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
background: rgba(0,0,0,0.5);
}
.content_view {
z-index: 999;
background: white;
position: absolute;
height: 75%;
left: 0;
bottom: 0;
right: 0;
border-top-left-radius: 20px;
border-top-right-radius: 20px;
}
.select_top {
height: 100rpx;
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 30rpx;
font-weight: bold;
position: relative;
box-sizing: border-box;
border-bottom: #f5f5f5 1rpx solid;
}
.select_top_item {
font-size: 14px;
margin-right: 20rpx;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
min-width: 10%;
}
.indicator {
position: absolute;
width: 30px;
height: 2px;
background: $uni-color-primary;
left: 16px;
bottom: 0;
transition: left 0.5s ease;
}
.swiperlist {
height: 100%;
position: relative;
left: 0;
top: 0;
bottom: 0;
right: 0;
}
.swiper-item {
height: 100%;
}
.scroll-view-item {
height: 100%;
}
.address_item {
padding: 5px 0;
font-size: 14px;
display: flex;
align-items: center;
}
.address_item_icon {
width: 20px;
height: 20px;
margin-right: 10px;
}
.mask {
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
background: $uni-text-color-grey;
opacity: 0.7;
}
.content-enter {
transform: translateY(100%);
}
.content-enter-to {
transform: translateY(0%);
}
.content-enter-active {
transition: transform 0.5s;
}
.content-leave {
transform: translateY(0%);
}
.content-leave-to {
transform: translateY(100%);
}
.content-leave-active {
transition: transform 0.5s;
}
</style>
export default {
created() {
if (this.type === 'message') {
// 不显示遮罩
this.maskShow = false
// 获取子组件对象
this.childrenMsg = null
}
},
methods: {
customOpen() {
if (this.childrenMsg) {
this.childrenMsg.open()
}
},
customClose() {
if (this.childrenMsg) {
this.childrenMsg.close()
}
}
}
}
import message from './message.js';
// 定义 type 类型:弹出类型:top/bottom/center
const config = {
// 顶部弹出
top:'top',
// 底部弹出
bottom:'bottom',
// 居中弹出
center:'center',
// 消息提示
message:'top',
// 对话框
dialog:'center',
// 分享
share:'bottom',
}
export default {
data(){
return {
config:config
}
},
mixins: [message],
}
<template>
<view class="uni-popup-dialog">
<view class="uni-popup-main">
<view class="uni-dialog-title">
<text class="uni-dialog-title-text" :class="['uni-popup__'+dialogType]">{{title}}</text>
</view>
<view class="uni-dialog-content">
<text class="uni-dialog-content-text" v-if="mode === 'base'">{{content}}</text>
<input v-else class="uni-dialog-input" v-model="val" type="text" :placeholder="placeholder" :focus="focus" >
</view>
</view>
<view class="uni-dialog-button-group">
<view class="uni-dialog-button" @click="close">
<text class="uni-dialog-button-text">取消</text>
</view>
<view class="uni-dialog-button uni-border-left" @click="onOk">
<text class="uni-dialog-button-text uni-button-color">确定</text>
</view>
</view>
</view>
</template>
<script>
/**
* PopUp 弹出层-对话框样式
* @description 弹出层-对话框样式
* @tutorial https://ext.dcloud.net.cn/plugin?id=329
* @property {String} value input 模式下的默认值
* @property {String} placeholder input 模式下输入提示
* @property {String} type = [success|warning|info|error] 主题样式
* @value success 成功
* @value warning 提示
* @value info 消息
* @value error 错误
* @property {String} mode = [base|input] 模式、
* @value base 基础对话框
* @value input 可输入对话框
* @property {String} content 对话框内容
* @property {Boolean} beforeClose 是否拦截取消事件
* @event {Function} confirm 点击确认按钮触发
* @event {Function} close 点击取消按钮触发
*/
export default {
name: "uniPopupDialog",
props: {
value: {
type: [String, Number],
default: ''
},
placeholder: {
type: [String, Number],
default: '请输入内容'
},
/**
* 对话框主题 success/warning/info/error 默认 success
*/
type: {
type: String,
default: 'error'
},
/**
* 对话框模式 base/input
*/
mode: {
type: String,
default: 'base'
},
/**
* 对话框标题
*/
title: {
type: String,
default: '提示'
},
/**
* 对话框内容
*/
content: {
type: String,
default: ''
},
/**
* 拦截取消事件 ,如果拦截取消事件,必须监听close事件,执行 done()
*/
beforeClose: {
type: Boolean,
default: false
}
},
data() {
return {
dialogType: 'error',
focus: false,
val: ""
}
},
inject: ['popup'],
watch: {
type(val) {
this.dialogType = val
},
mode(val) {
if (val === 'input') {
this.dialogType = 'info'
}
},
value(val) {
this.val = val
}
},
created() {
// 对话框遮罩不可点击
this.popup.mkclick = false
if (this.mode === 'input') {
this.dialogType = 'info'
this.val = this.value
} else {
this.dialogType = this.type
}
},
mounted() {
this.focus = true
},
methods: {
/**
* 点击确认按钮
*/
onOk() {
this.$emit('confirm', () => {
this.popup.close()
if (this.mode === 'input') this.val = this.value
}, this.mode === 'input' ? this.val : '')
},
/**
* 点击取消按钮
*/
close() {
if (this.beforeClose) {
this.$emit('close', () => {
this.popup.close()
})
return
}
this.popup.close()
}
}
}
</script>
<style lang="scss" scoped>
.uni-popup-dialog {
width: 300px;
border-radius: 15px;
background-color: #fff;
}
.uni-dialog-title {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
justify-content: center;
padding-top: 15px;
padding-bottom: 5px;
}
.uni-dialog-title-text {
font-size: 16px;
font-weight: 500;
}
.uni-dialog-content {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
justify-content: center;
align-items: center;
padding: 5px 15px 15px 15px;
}
.uni-dialog-content-text {
font-size: 14px;
color: #6e6e6e;
}
.uni-dialog-button-group {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
border-top-color: #f5f5f5;
border-top-style: solid;
border-top-width: 1px;
}
.uni-dialog-button {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex: 1;
flex-direction: row;
justify-content: center;
align-items: center;
height: 45px;
}
.uni-border-left {
border-left-color: #f0f0f0;
border-left-style: solid;
border-left-width: 1px;
}
.uni-dialog-button-text {
font-size: 14px;
}
.uni-button-color {
color: $uni-color-primary;
}
.uni-dialog-input {
flex: 1;
font-size: 14px;
}
.uni-popup__success {
color: $uni-color-success;
}
.uni-popup__warn {
color: $uni-color-warning;
}
.uni-popup__error {
color: $uni-color-error;
}
.uni-popup__info {
color: #909399;
}
</style>
<template>
<view class="uni-popup-message" :class="'uni-popup__'+[type]">
<text class="uni-popup-message-text" :class="'uni-popup__'+[type]+'-text'">{{message}}</text>
</view>
</template>
<script>
/**
* PopUp 弹出层-消息提示
* @description 弹出层-消息提示
* @tutorial https://ext.dcloud.net.cn/plugin?id=329
* @property {String} type = [success|warning|info|error] 主题样式
* @value success 成功
* @value warning 提示
* @value info 消息
* @value error 错误
* @property {String} message 消息提示文字
* @property {String} duration 显示时间,设置为 0 则不会自动关闭
*/
export default {
name: 'UniPopupMessage',
props: {
/**
* 主题 success/warning/info/error 默认 success
*/
type: {
type: String,
default: 'success'
},
/**
* 消息文字
*/
message: {
type: String,
default: ''
},
/**
* 显示时间,设置为 0 则不会自动关闭
*/
duration: {
type: Number,
default: 3000
}
},
inject: ['popup'],
data() {
return {}
},
created() {
this.popup.childrenMsg = this
},
methods: {
open() {
if (this.duration === 0) return
clearTimeout(this.popuptimer)
this.popuptimer = setTimeout(() => {
this.popup.close()
}, this.duration)
},
close() {
clearTimeout(this.popuptimer)
}
}
}
</script>
<style lang="scss" scoped>
.uni-popup-message {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
background-color: #e1f3d8;
padding: 10px 15px;
border-color: #eee;
border-style: solid;
border-width: 1px;
}
.uni-popup-message-text {
font-size: 14px;
padding: 0;
}
.uni-popup__success {
background-color: #e1f3d8;
}
.uni-popup__success-text {
color: #67C23A;
}
.uni-popup__warn {
background-color: #faecd8;
}
.uni-popup__warn-text {
color: #E6A23C;
}
.uni-popup__error {
background-color: #fde2e2;
}
.uni-popup__error-text {
color: #F56C6C;
}
.uni-popup__info {
background-color: #F2F6FC;
}
.uni-popup__info-text {
color: #909399;
}
</style>
<template>
<view class="uni-popup-share">
<view class="uni-share-title"><text class="uni-share-title-text">{{title}}</text></view>
<view class="uni-share-content">
<view class="uni-share-content-box">
<view class="uni-share-content-item" v-for="(item,index) in bottomData" :key="index" @click.stop="select(item,index)">
<image class="uni-share-image" :src="item.icon" mode="aspectFill"></image>
<text class="uni-share-text">{{item.text}}</text>
</view>
</view>
</view>
<view class="uni-share-button-box">
<button class="uni-share-button" @click="close">取消</button>
</view>
</view>
</template>
<script>
export default {
name: 'UniPopupShare',
props: {
title: {
type: String,
default: '分享到'
}
},
inject: ['popup'],
data() {
return {
bottomData: [{
text: '微信',
icon: 'https://img-cdn-qiniu.dcloud.net.cn/uni-ui/grid-2.png',
name: 'wx'
},
{
text: '支付宝',
icon: 'https://img-cdn-qiniu.dcloud.net.cn/uni-ui/grid-8.png',
name: 'wx'
},
{
text: 'QQ',
icon: 'https://img-cdn-qiniu.dcloud.net.cn/uni-ui/gird-3.png',
name: 'qq'
},
{
text: '新浪',
icon: 'https://img-cdn-qiniu.dcloud.net.cn/uni-ui/grid-1.png',
name: 'sina'
},
{
text: '百度',
icon: 'https://img-cdn-qiniu.dcloud.net.cn/uni-ui/grid-7.png',
name: 'copy'
},
{
text: '其他',
icon: 'https://img-cdn-qiniu.dcloud.net.cn/uni-ui/grid-5.png',
name: 'more'
}
]
}
},
created() {},
methods: {
/**
* 选择内容
*/
select(item, index) {
this.$emit('select', {
item,
index
}, () => {
this.popup.close()
})
},
/**
* 关闭窗口
*/
close() {
this.popup.close()
}
}
}
</script>
<style lang="scss" scoped>
.uni-popup-share {
background-color: #fff;
}
.uni-share-title {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
align-items: center;
justify-content: center;
height: 40px;
}
.uni-share-title-text {
font-size: 14px;
color: #666;
}
.uni-share-content {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
justify-content: center;
padding-top: 10px;
}
.uni-share-content-box {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
flex-wrap: wrap;
width: 360px;
}
.uni-share-content-item {
width: 90px;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: column;
justify-content: center;
padding: 10px 0;
align-items: center;
}
.uni-share-content-item:active {
background-color: #f5f5f5;
}
.uni-share-image {
width: 30px;
height: 30px;
}
.uni-share-text {
margin-top: 10px;
font-size: 14px;
color: #3B4144;
}
.uni-share-button-box {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
padding: 10px 15px;
}
.uni-share-button {
flex: 1;
border-radius: 50px;
color: #666;
font-size: 16px;
}
.uni-share-button::after {
border-radius: 50px;
}
</style>
<template>
<view v-if="showPopup" class="uni-popup" :class="[popupstyle]" >
<uni-transition v-if="maskShow" :mode-class="['fade']" :styles="maskClass" :duration="duration" :show="showTrans"
@click="onTap" />
<uni-transition :mode-class="ani" :styles="transClass" :duration="duration" :show="showTrans" @click="onTap">
<view class="uni-popup__wrapper-box" @click.stop="clear">
<slot />
</view>
</uni-transition>
</view>
</template>
<script>
import uniTransition from '../uni-transition/uni-transition.vue'
import popup from './popup.js'
/**
* PopUp 弹出层
* @description 弹出层组件,为了解决遮罩弹层的问题
* @tutorial https://ext.dcloud.net.cn/plugin?id=329
* @property {String} type = [top|center|bottom] 弹出方式
* @value top 顶部弹出
* @value center 中间弹出
* @value bottom 底部弹出
* @value message 消息提示
* @value dialog 对话框
* @value share 底部分享示例
* @property {Boolean} animation = [ture|false] 是否开启动画
* @property {Boolean} maskClick = [ture|false] 蒙版点击是否关闭弹窗
* @event {Function} change 打开关闭弹窗触发,e={show: false}
*/
export default {
name: 'UniPopup',
components: {
uniTransition
},
props: {
// 开启动画
animation: {
type: Boolean,
default: true
},
// 弹出层类型,可选值,top: 顶部弹出层;bottom:底部弹出层;center:全屏弹出层
// message: 消息提示 ; dialog : 对话框
type: {
type: String,
default: 'center'
},
// maskClick
maskClick: {
type: Boolean,
default: true
}
},
provide() {
return {
popup: this
}
},
mixins: [popup],
watch: {
/**
* 监听type类型
*/
type: {
handler: function(newVal) {
this[this.config[newVal]]()
},
immediate: true
},
/**
* 监听遮罩是否可点击
* @param {Object} val
*/
maskClick(val) {
this.mkclick = val
}
},
data() {
return {
duration: 300,
ani: [],
showPopup: false,
showTrans: false,
maskClass: {
'position': 'fixed',
'bottom': 0,
'top': 0,
'left': 0,
'right': 0,
'backgroundColor': 'rgba(0, 0, 0, 0.4)'
},
transClass: {
'position': 'fixed',
'left': 0,
'right': 0,
},
maskShow: true,
mkclick: true,
popupstyle: 'top'
}
},
created() {
this.mkclick = this.maskClick
if (this.animation) {
this.duration = 300
} else {
this.duration = 0
}
},
methods: {
clear(e) {
// TODO nvue 取消冒泡
e.stopPropagation()
},
open() {
this.showPopup = true
this.$nextTick(() => {
new Promise(resolve => {
clearTimeout(this.timer)
this.timer = setTimeout(() => {
this.showTrans = true
// fixed by mehaotian 兼容 app 端
this.$nextTick(() => {
resolve();
})
}, 50);
}).then(res => {
// 自定义打开事件
clearTimeout(this.msgtimer)
this.msgtimer = setTimeout(() => {
this.customOpen && this.customOpen()
}, 100)
this.$emit('change', {
show: true,
type: this.type
})
})
})
},
close(type) {
this.showTrans = false
this.$nextTick(() => {
this.$emit('change', {
show: false,
type: this.type
})
clearTimeout(this.timer)
// 自定义关闭事件
this.customOpen && this.customClose()
this.timer = setTimeout(() => {
this.showPopup = false
}, 300)
})
},
onTap() {
if (!this.mkclick) return
this.close()
},
/**
* 顶部弹出样式处理
*/
top() {
this.popupstyle = 'top'
this.ani = ['slide-top']
this.transClass = {
'position': 'fixed',
'left': 0,
'right': 0,
}
},
/**
* 底部弹出样式处理
*/
bottom() {
this.popupstyle = 'bottom'
this.ani = ['slide-bottom']
this.transClass = {
'position': 'fixed',
'left': 0,
'right': 0,
'bottom': 0
}
},
/**
* 中间弹出样式处理
*/
center() {
this.popupstyle = 'center'
this.ani = ['zoom-out', 'fade']
this.transClass = {
'position': 'fixed',
/* #ifndef APP-NVUE */
'display': 'flex',
'flexDirection': 'column',
/* #endif */
'bottom': 0,
'left': 0,
'right': 0,
'top': 0,
'justifyContent': 'center',
'alignItems': 'center'
}
}
}
}
</script>
<style lang="scss" scoped>
.uni-popup {
position: fixed;
/* #ifndef APP-NVUE */
z-index: 99;
/* #endif */
top: 0;
width: 100%;
height: 100%;
}
.uni-popup__mask {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: $uni-bg-color-mask;
opacity: 0;
}
.mask-ani {
transition-property: opacity;
transition-duration: 0.2s;
}
.uni-top-mask {
opacity: 1;
}
.uni-bottom-mask {
opacity: 1;
}
.uni-center-mask {
opacity: 1;
}
.uni-popup__wrapper {
/* #ifndef APP-NVUE */
display: block;
/* #endif */
position: absolute;
}
.top {
/* #ifdef H5 */
top: var(--window-top);
/* #endif */
/* #ifndef H5 */
top: 0;
/* #endif */
}
.bottom {
bottom: 0;
}
.uni-popup__wrapper-box {
/* #ifndef APP-NVUE */
display: block;
/* #endif */
position: relative;
/* iphonex 等安全区设置,底部安全区适配 */
/* #ifndef APP-NVUE */
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
/* #endif */
}
.content-ani {
// transition: transform 0.3s;
transition-property: transform, opacity;
transition-duration: 0.2s;
}
.uni-top-content {
transform: translateY(0);
}
.uni-bottom-content {
transform: translateY(0);
}
.uni-center-content {
transform: scale(1);
opacity: 1;
}
</style>
<template>
<view class="uni-section" nvue>
<view v-if="type" class="uni-section__head">
<view :class="type" class="uni-section__head-tag" />
</view>
<view class="uni-section__content">
<text :class="{'distraction':!subTitle}" class="uni-section__content-title">{{ title }}</text>
<text v-if="subTitle" class="uni-section__content-sub">{{ subTitle }}</text>
</view>
<slot />
</view>
</template>
<script>
/**
* Section 标题栏
* @description 标题栏
* @property {String} type = [line|circle] 标题装饰类型
* @value line 竖线
* @value circle 圆形
* @property {String} title 主标题
* @property {String} subTitle 副标题
*/
export default {
name: 'UniSection',
props: {
type: {
type: String,
default: ''
},
title: {
type: String,
default: ''
},
subTitle: {
type: String,
default: ''
}
},
data() {
return {}
},
watch: {
title(newVal) {
if (uni.report && newVal !== '') {
uni.report('title', newVal)
}
}
},
methods: {
onClick() {
this.$emit('click')
}
}
}
</script>
<style lang="scss" scoped>
.uni-section {
position: relative;
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
margin-top: 10px;
flex-direction: row;
align-items: center;
padding: 0 10px;
height: 50px;
background-color: $uni-bg-color-grey;
/* #ifdef APP-NVUE */
// border-bottom-color: $uni-border-color;
// border-bottom-style: solid;
// border-bottom-width: 0.5px;
/* #endif */
font-weight: normal;
}
/* #ifndef APP-NVUE */
// .uni-section:after {
// position: absolute;
// bottom: 0;
// right: 0;
// left: 0;
// height: 1px;
// content: '';
// -webkit-transform: scaleY(.5);
// transform: scaleY(.5);
// background-color: $uni-border-color;
// }
/* #endif */
.uni-section__head {
flex-direction: row;
justify-content: center;
align-items: center;
margin-right: 10px;
}
.line {
height: 15px;
background-color: $uni-text-color-disable;
border-radius: 5px;
width: 3px;
}
.circle {
width: 8px;
height: 8px;
border-top-right-radius: 50px;
border-top-left-radius: 50px;
border-bottom-left-radius: 50px;
border-bottom-right-radius: 50px;
background-color: $uni-text-color-disable;
}
.uni-section__content {
flex-direction: column;
flex: 1;
color: $uni-text-color;
}
.uni-section__content-title {
font-size: $uni-font-size-base;
color: $uni-text-color;
}
.distraction {
flex-direction: row;
align-items: center;
}
.uni-section__content-sub {
font-size: $uni-font-size-sm;
color: $uni-text-color-grey;
}
</style>
const BindingX = uni.requireNativePlugin('bindingx');
const dom = uni.requireNativePlugin('dom');
const animation = uni.requireNativePlugin('animation');
export default {
data() {
return {}
},
watch: {
show(newVal) {
if (this.autoClose) return
if (this.stop) return
this.stop = true
if (newVal) {
this.open(newVal)
} else {
this.close()
}
},
leftOptions() {
this.getSelectorQuery()
this.init()
},
rightOptions(newVal) {
this.init()
}
},
created() {
if (this.swipeaction.children !== undefined) {
this.swipeaction.children.push(this)
}
},
mounted() {
this.box = this.getEl(this.$refs['selector-box--hock'])
this.selector = this.getEl(this.$refs['selector-content--hock']);
this.leftButton = this.getEl(this.$refs['selector-left-button--hock']);
this.rightButton = this.getEl(this.$refs['selector-right-button--hock']);
this.init()
},
beforeDestroy() {
this.swipeaction.children.forEach((item, index) => {
if (item === this) {
this.swipeaction.children.splice(index, 1)
}
})
},
methods: {
init() {
this.$nextTick(() => {
this.x = 0
this.button = {
show: false
}
setTimeout(() => {
this.getSelectorQuery()
}, 200)
})
},
onClick(index, item, position) {
this.$emit('click', {
content: item,
index,
position
})
},
touchstart(e) {
// 每次只触发一次,避免多次监听造成闪烁
if (this.stop) return
this.stop = true
if (this.autoClose) {
this.swipeaction.closeOther(this)
}
const leftWidth = this.button.left.width
const rightWidth = this.button.right.width
let expression = this.range(this.x, -rightWidth, leftWidth)
let leftExpression = this.range(this.x - leftWidth, -leftWidth, 0)
let rightExpression = this.range(this.x + rightWidth, 0, rightWidth)
this.eventpan = BindingX.bind({
anchor: this.box,
eventType: 'pan',
props: [{
element: this.selector,
property: 'transform.translateX',
expression
}, {
element: this.leftButton,
property: 'transform.translateX',
expression: leftExpression
}, {
element: this.rightButton,
property: 'transform.translateX',
expression: rightExpression
}, ]
}, (e) => {
// nope
if (e.state === 'end') {
this.x = e.deltaX + this.x;
this.isclick = true
this.bindTiming(e.deltaX)
}
});
},
touchend(e) {
if (this.isopen !== 'none' && !this.isclick) {
this.open('none')
}
},
bindTiming(x) {
const left = this.x
const leftWidth = this.button.left.width
const rightWidth = this.button.right.width
const threshold = this.threshold
if (!this.isopen || this.isopen === 'none') {
if (left > threshold) {
this.open('left')
} else if (left < -threshold) {
this.open('right')
} else {
this.open('none')
}
} else {
if ((x > -leftWidth && x < 0) || x > rightWidth) {
if ((x > -threshold && x < 0) || (x - rightWidth > threshold)) {
this.open('left')
} else {
this.open('none')
}
} else {
if ((x < threshold && x > 0) || (x + leftWidth < -threshold)) {
this.open('right')
} else {
this.open('none')
}
}
}
},
/**
* 移动范围
* @param {Object} num
* @param {Object} mix
* @param {Object} max
*/
range(num, mix, max) {
return `min(max(x+${num}, ${mix}), ${max})`
},
/**
* 开启swipe
*/
open(type) {
this.animation(type)
},
/**
* 关闭swipe
*/
close() {
this.animation('none')
},
/**
* 开启关闭动画
* @param {Object} type
*/
animation(type) {
const time = 300
const leftWidth = this.button.left.width
const rightWidth = this.button.right.width
if (this.eventpan && this.eventpan.token) {
BindingX.unbind({
token: this.eventpan.token,
eventType: 'pan'
})
}
switch (type) {
case 'left':
Promise.all([
this.move(this.selector, leftWidth),
this.move(this.leftButton, 0),
this.move(this.rightButton, rightWidth * 2)
]).then(() => {
this.setEmit(leftWidth, type)
})
break
case 'right':
Promise.all([
this.move(this.selector, -rightWidth),
this.move(this.leftButton, -leftWidth * 2),
this.move(this.rightButton, 0)
]).then(() => {
this.setEmit(-rightWidth, type)
})
break
default:
Promise.all([
this.move(this.selector, 0),
this.move(this.leftButton, -leftWidth),
this.move(this.rightButton, rightWidth)
]).then(() => {
this.setEmit(0, type)
})
}
},
setEmit(x, type) {
const leftWidth = this.button.left.width
const rightWidth = this.button.right.width
this.isopen = this.isopen || 'none'
this.stop = false
this.isclick = false
// 只有状态不一致才会返回结果
if (this.isopen !== type && this.x !== x) {
if (type === 'left' && leftWidth > 0) {
this.$emit('change', 'left')
}
if (type === 'right' && rightWidth > 0) {
this.$emit('change', 'right')
}
if (type === 'none') {
this.$emit('change', 'none')
}
}
this.x = x
this.isopen = type
},
move(ref, value) {
return new Promise((resolve, reject) => {
animation.transition(ref, {
styles: {
transform: `translateX(${value})`,
},
duration: 150, //ms
timingFunction: 'linear',
needLayout: false,
delay: 0 //ms
}, function(res) {
resolve(res)
})
})
},
/**
* 获取ref
* @param {Object} el
*/
getEl(el) {
return el.ref
},
/**
* 获取节点信息
*/
getSelectorQuery() {
Promise.all([
this.getDom('left'),
this.getDom('right'),
]).then((data) => {
let show = 'none'
if (this.autoClose) {
show = 'none'
} else {
show = this.show
}
if (show === 'none') {
// this.close()
} else {
this.open(show)
}
})
},
getDom(str) {
return new Promise((resolve, reject) => {
dom.getComponentRect(this.$refs[`selector-${str}-button--hock`], (data) => {
if (data) {
this.button[str] = data.size
resolve(data)
} else {
reject()
}
})
})
}
}
}
var MIN_DISTANCE = 10;
/**
* 监听页面内值的变化,主要用于动态开关swipe-action
* @param {Object} newValue
* @param {Object} oldValue
* @param {Object} ownerInstance
* @param {Object} instance
*/
function sizeReady(newValue, oldValue, ownerInstance, instance) {
var state = instance.getState()
var buttonPositions = JSON.parse(newValue)
if (!buttonPositions || !buttonPositions.data || buttonPositions.data.length === 0) return
state.leftWidth = buttonPositions.data[0].width
state.rightWidth = buttonPositions.data[1].width
state.threshold = instance.getDataset().threshold
if (buttonPositions.show && buttonPositions.show !== 'none') {
openState(buttonPositions.show, instance, ownerInstance)
return
}
if (state.left) {
openState('none', instance, ownerInstance)
}
resetTouchStatus(instance)
}
/**
* 开始触摸操作
* @param {Object} e
* @param {Object} ins
*/
function touchstart(e, ins) {
var instance = e.instance;
var disabled = instance.getDataset().disabled
var state = instance.getState();
// fix by mehaotian, TODO 兼容 app-vue 获取dataset为字符串 , h5 获取 为 undefined 的问题,待框架修复
disabled = (typeof(disabled) === 'string' ? JSON.parse(disabled) : disabled) || false;
if (disabled) return
// 开始触摸时移除动画类
instance.requestAnimationFrame(function(){
instance.removeClass('ani');
ins.callMethod('closeSwipe');
})
// 记录上次的位置
state.x = state.left || 0
// 计算滑动开始位置
stopTouchStart(e, ins)
}
/**
* 开始滑动操作
* @param {Object} e
* @param {Object} ownerInstance
*/
function touchmove(e, ownerInstance) {
var instance = e.instance;
var disabled = instance.getDataset().disabled
var state = instance.getState()
// fix by mehaotian, TODO 兼容 app-vue 获取dataset为字符串 , h5 获取 为 undefined 的问题,待框架修复
disabled = (typeof(disabled) === 'string' ? JSON.parse(disabled) : disabled) || false;
if (disabled) return
// 是否可以滑动页面
stopTouchMove(e);
if (state.direction !== 'horizontal') {
return;
}
if (e.preventDefault) {
// 阻止页面滚动
e.preventDefault()
}
move(state.x + state.deltaX, instance, ownerInstance)
}
/**
* 结束触摸操作
* @param {Object} e
* @param {Object} ownerInstance
*/
function touchend(e, ownerInstance) {
var instance = e.instance;
var disabled = instance.getDataset().disabled
var state = instance.getState()
// fix by mehaotian, TODO 兼容 app-vue 获取dataset为字符串 , h5 获取 为 undefined 的问题,待框架修复
disabled = (typeof(disabled) === 'string' ? JSON.parse(disabled) : disabled) || false;
if (disabled) return
// 滑动过程中触摸结束,通过阙值判断是开启还是关闭
// fixed by mehaotian 定时器解决点击按钮,touchend 触发比 click 事件时机早的问题 ,主要是 ios13
moveDirection(state.left, instance, ownerInstance)
}
/**
* 设置移动距离
* @param {Object} value
* @param {Object} instance
* @param {Object} ownerInstance
*/
function move(value, instance, ownerInstance) {
value = value || 0
var state = instance.getState()
var leftWidth = state.leftWidth
var rightWidth = state.rightWidth
// 获取可滑动范围
state.left = range(value, -rightWidth, leftWidth);
instance.requestAnimationFrame(function(){
instance.setStyle({
transform: 'translateX(' + state.left + 'px)',
'-webkit-transform': 'translateX(' + state.left + 'px)'
})
})
}
/**
* 获取范围
* @param {Object} num
* @param {Object} min
* @param {Object} max
*/
function range(num, min, max) {
return Math.min(Math.max(num, min), max);
}
/**
* 移动方向判断
* @param {Object} left
* @param {Object} value
* @param {Object} ownerInstance
* @param {Object} ins
*/
function moveDirection(left, ins, ownerInstance) {
var state = ins.getState()
var threshold = state.threshold
var position = state.position
var isopen = state.isopen || 'none'
var leftWidth = state.leftWidth
var rightWidth = state.rightWidth
if (state.deltaX === 0) {
openState('none', ins, ownerInstance)
return
}
if ((isopen === 'none' && rightWidth > 0 && -left > threshold) || (isopen !== 'none' && rightWidth > 0 && rightWidth +
left < threshold)) {
// right
openState('right', ins, ownerInstance)
} else if ((isopen === 'none' && leftWidth > 0 && left > threshold) || (isopen !== 'none' && leftWidth > 0 &&
leftWidth - left < threshold)) {
// left
openState('left', ins, ownerInstance)
} else {
// default
openState('none', ins, ownerInstance)
}
}
/**
* 开启状态
* @param {Boolean} type
* @param {Object} ins
* @param {Object} ownerInstance
*/
function openState(type, ins, ownerInstance) {
var state = ins.getState()
var position = state.position
var leftWidth = state.leftWidth
var rightWidth = state.rightWidth
var left = ''
state.isopen = state.isopen ? state.isopen : 'none'
switch (type) {
case "left":
left = leftWidth
break
case "right":
left = -rightWidth
break
default:
left = 0
}
// && !state.throttle
if (state.isopen !== type ) {
state.throttle = true
ownerInstance.callMethod('change', {
open: type
})
}
state.isopen = type
// 添加动画类
ins.requestAnimationFrame(function(){
ins.addClass('ani');
move(left, ins, ownerInstance)
})
// 设置最终移动位置,理论上只要进入到这个函数,肯定是要打开的
}
function getDirection(x, y) {
if (x > y && x > MIN_DISTANCE) {
return 'horizontal';
}
if (y > x && y > MIN_DISTANCE) {
return 'vertical';
}
return '';
}
/**
* 重置滑动状态
* @param {Object} event
*/
function resetTouchStatus(instance) {
var state = instance.getState();
state.direction = '';
state.deltaX = 0;
state.deltaY = 0;
state.offsetX = 0;
state.offsetY = 0;
}
/**
* 设置滑动开始位置
* @param {Object} event
*/
function stopTouchStart(event) {
var instance = event.instance;
var state = instance.getState();
resetTouchStatus(instance);
var touch = event.touches[0];
state.startX = touch.clientX;
state.startY = touch.clientY;
}
/**
* 滑动中,是否禁止打开
* @param {Object} event
*/
function stopTouchMove(event) {
var instance = event.instance;
var state = instance.getState();
var touch = event.touches[0];
state.deltaX = touch.clientX - state.startX;
state.deltaY = touch.clientY - state.startY;
state.offsetX = Math.abs(state.deltaX);
state.offsetY = Math.abs(state.deltaY);
state.direction = state.direction || getDirection(state.offsetX, state.offsetY);
}
module.exports = {
sizeReady: sizeReady,
touchstart: touchstart,
touchmove: touchmove,
touchend: touchend
}
export default {
data() {
return {
x: 0,
transition: false,
width: 0,
viewWidth: 0,
swipeShow: 0
}
},
watch: {
show(newVal) {
if (this.autoClose) return
if (newVal && newVal !== 'none' ) {
this.transition = true
this.open(newVal)
} else {
this.close()
}
}
},
created() {
if (this.swipeaction.children !== undefined) {
this.swipeaction.children.push(this)
}
},
beforeDestroy() {
this.swipeaction.children.forEach((item, index) => {
if (item === this) {
this.swipeaction.children.splice(index, 1)
}
})
},
mounted() {
this.isopen = false
setTimeout(() => {
this.getQuerySelect()
}, 50)
},
methods: {
appTouchStart(e) {
const {
clientX
} = e.changedTouches[0]
this.clientX = clientX
this.timestamp = new Date().getTime()
},
appTouchEnd(e, index, item, position) {
const {
clientX
} = e.changedTouches[0]
// fixed by xxxx 模拟点击事件,解决 ios 13 点击区域错位的问题
let diff = Math.abs(this.clientX - clientX)
let time = (new Date().getTime()) - this.timestamp
if (diff < 40 && time < 300) {
this.$emit('click', {
content: item,
index,
position
})
}
},
// onClick(index, item, position) {
// this.$emit('click', {
// content: item,
// index,
// position
// })
// },
/**
* 移动触发
* @param {Object} e
*/
onChange(e) {
this.moveX = e.detail.x
this.isclose = false
},
touchstart(e) {
this.transition = false
this.isclose = true
this.autoClose && this.swipeaction.closeOther(this)
},
touchmove(e) {},
touchend(e) {
// 0的位置什么都不执行
if (this.isclose && this.isopen === 'none') return
if (this.isclose && this.isopen !== 'none') {
this.transition = true
this.close()
} else {
this.move(this.moveX + this.leftWidth)
}
},
/**
* 移动
* @param {Object} moveX
*/
move(moveX) {
// 打开关闭的处理逻辑不太一样
this.transition = true
// 未打开状态
if (!this.isopen || this.isopen === 'none') {
if (moveX > this.threshold) {
this.open('left')
} else if (moveX < -this.threshold) {
this.open('right')
} else {
this.close()
}
} else {
if (moveX < 0 && moveX < this.rightWidth) {
const rightX = this.rightWidth + moveX
if (rightX < this.threshold) {
this.open('right')
} else {
this.close()
}
} else if (moveX > 0 && moveX < this.leftWidth) {
const leftX = this.leftWidth - moveX
if (leftX < this.threshold) {
this.open('left')
} else {
this.close()
}
}
}
},
/**
* 打开
*/
open(type) {
this.x = this.moveX
this.animation(type)
},
/**
* 关闭
*/
close() {
this.x = this.moveX
// TODO 解决 x 值不更新的问题,所以会多触发一次 nextTick ,待优化
this.$nextTick(() => {
this.x = -this.leftWidth
if(this.isopen!=='none'){
this.$emit('change', 'none')
}
this.isopen = 'none'
})
},
/**
* 执行结束动画
* @param {Object} type
*/
animation(type) {
this.$nextTick(() => {
if (type === 'left') {
this.x = 0
} else {
this.x = -this.rightWidth - this.leftWidth
}
if(this.isopen!==type){
this.$emit('change', type)
}
this.isopen = type
})
},
getSlide(x) {},
getQuerySelect() {
const query = uni.createSelectorQuery().in(this);
query.selectAll('.movable-view--hock').boundingClientRect(data => {
this.leftWidth = data[1].width
this.rightWidth = data[2].width
this.width = data[0].width
this.viewWidth = this.width + this.rightWidth + this.leftWidth
if (this.leftWidth === 0) {
// TODO 疑似bug ,初始化的时候如果x 是0,会导致移动位置错误,所以让元素超出一点
this.x = -0.1
} else {
this.x = -this.leftWidth
}
this.moveX = this.x
this.$nextTick(() => {
this.swipeShow = 1
})
if (!this.buttonWidth) {
this.disabledView = true
}
if (this.autoClose) return
if (this.show !== 'none') {
this.transition = true
this.open(this.shows)
}
}).exec();
}
}
}
const MIN_DISTANCE = 10;
export default {
data() {
return {
uniShow: false,
left: 0,
buttonShow: 'none',
ani: false,
moveLeft:''
}
},
watch: {
show(newVal) {
if (this.autoClose) return
this.openState(newVal)
},
left(){
this.moveLeft = `translateX(${this.left}px)`
},
buttonShow(newVal){
if (this.autoClose) return
this.openState(newVal)
},
leftOptions() {
this.init()
},
rightOptions() {
this.init()
}
},
mounted() {
// this.position = {}
if (this.swipeaction.children !== undefined) {
this.swipeaction.children.push(this)
}
this.init()
},
beforeDestoy() {
this.swipeaction.children.forEach((item, index) => {
if (item === this) {
this.swipeaction.children.splice(index, 1)
}
})
},
methods: {
init(){
clearTimeout(this.timer)
this.timer = setTimeout(() => {
this.getSelectorQuery()
}, 100)
// 移动距离
this.left = 0
this.x = 0
},
closeSwipe(e) {
if (!this.autoClose) return
this.swipeaction.closeOther(this)
},
appTouchStart(e) {
const {
clientX
} = e.changedTouches[0]
this.clientX = clientX
this.timestamp = new Date().getTime()
},
appTouchEnd(e, index, item, position) {
const {
clientX
} = e.changedTouches[0]
// fixed by xxxx 模拟点击事件,解决 ios 13 点击区域错位的问题
let diff = Math.abs(this.clientX - clientX)
let time = (new Date().getTime()) - this.timestamp
if (diff < 40 && time < 300) {
this.$emit('click', {
content: item,
index,
position
})
}
},
touchstart(e) {
if (this.disabled) return
this.ani = false
this.x = this.left || 0
this.stopTouchStart(e)
this.autoClose && this.closeSwipe()
},
touchmove(e) {
if (this.disabled) return
// 是否可以滑动页面
this.stopTouchMove(e);
if (this.direction !== 'horizontal') {
return;
}
this.move(this.x + this.deltaX)
},
touchend() {
if (this.disabled) return
this.moveDirection(this.left)
},
/**
* 设置移动距离
* @param {Object} value
*/
move(value) {
value = value || 0
const leftWidth = this.leftWidth
const rightWidth = this.rightWidth
// 获取可滑动范围
this.left = this.range(value, -rightWidth, leftWidth);
},
/**
* 获取范围
* @param {Object} num
* @param {Object} min
* @param {Object} max
*/
range(num, min, max) {
return Math.min(Math.max(num, min), max);
},
/**
* 移动方向判断
* @param {Object} left
* @param {Object} value
*/
moveDirection(left) {
const threshold = this.threshold
const isopen = this.isopen || 'none'
const leftWidth = this.leftWidth
const rightWidth = this.rightWidth
if (this.deltaX === 0) {
this.openState('none')
return
}
if ((isopen === 'none' && rightWidth > 0 && -left > threshold) || (isopen !== 'none' && rightWidth > 0 && rightWidth +
left < threshold)) {
// right
this.openState('right')
} else if ((isopen === 'none' && leftWidth > 0 && left > threshold) || (isopen !== 'none' && leftWidth > 0 &&
leftWidth - left < threshold)) {
// left
this.openState('left')
} else {
// default
this.openState('none')
}
},
/**
* 开启状态
* @param {Boolean} type
*/
openState(type) {
const leftWidth = this.leftWidth
const rightWidth = this.rightWidth
let left = ''
this.isopen = this.isopen ? this.isopen : 'none'
switch (type) {
case "left":
left = leftWidth
break
case "right":
left = -rightWidth
break
default:
left = 0
}
if (this.isopen !== type) {
this.throttle = true
this.$emit('change', type)
}
this.isopen = type
// 添加动画类
this.ani = true
this.$nextTick(() => {
this.move(left)
})
// 设置最终移动位置,理论上只要进入到这个函数,肯定是要打开的
},
close() {
this.openState('none')
},
getDirection(x, y) {
if (x > y && x > MIN_DISTANCE) {
return 'horizontal';
}
if (y > x && y > MIN_DISTANCE) {
return 'vertical';
}
return '';
},
/**
* 重置滑动状态
* @param {Object} event
*/
resetTouchStatus() {
this.direction = '';
this.deltaX = 0;
this.deltaY = 0;
this.offsetX = 0;
this.offsetY = 0;
},
/**
* 设置滑动开始位置
* @param {Object} event
*/
stopTouchStart(event) {
this.resetTouchStatus();
const touch = event.touches[0];
this.startX = touch.clientX;
this.startY = touch.clientY;
},
/**
* 滑动中,是否禁止打开
* @param {Object} event
*/
stopTouchMove(event) {
const touch = event.touches[0];
this.deltaX = touch.clientX - this.startX;
this.deltaY = touch.clientY - this.startY;
this.offsetX = Math.abs(this.deltaX);
this.offsetY = Math.abs(this.deltaY);
this.direction = this.direction || this.getDirection(this.offsetX, this.offsetY);
},
getSelectorQuery() {
const views = uni.createSelectorQuery().in(this)
views
.selectAll('.uni-swipe_button-group')
.boundingClientRect(data => {
let show = 'none'
if (this.autoClose) {
show = 'none'
} else {
show = this.show
}
this.leftWidth = data[0].width || 0
this.rightWidth = data[1].width || 0
this.buttonShow = show
})
.exec()
}
}
}
export default {
data() {
return {
position: [],
button: {},
btn: "[]"
}
},
// computed: {
// pos() {
// return JSON.stringify(this.position)
// },
// btn() {
// return JSON.stringify(this.button)
// }
// },
watch: {
button: {
handler(newVal) {
this.btn = JSON.stringify(newVal)
},
deep: true
},
show(newVal) {
if (this.autoClose) return
if (!this.button) {
this.init()
return
}
this.button.show = newVal
},
leftOptions() {
this.init()
},
rightOptions() {
this.init()
}
},
created() {
if (this.swipeaction.children !== undefined) {
this.swipeaction.children.push(this)
}
},
mounted() {
this.init()
},
beforeDestroy() {
this.swipeaction.children.forEach((item, index) => {
if (item === this) {
this.swipeaction.children.splice(index, 1)
}
})
},
methods: {
init() {
clearTimeout(this.swipetimer)
this.swipetimer = setTimeout(() => {
this.getButtonSize()
}, 50)
},
closeSwipe(e) {
if (!this.autoClose) return
this.swipeaction.closeOther(this)
},
change(e) {
this.$emit('change', e.open)
let show = this.button.show
if (show !== e.open) {
this.button.show = e.open
}
},
appTouchStart(e) {
const {
clientX
} = e.changedTouches[0]
this.clientX = clientX
this.timestamp = new Date().getTime()
},
appTouchEnd(e, index, item, position) {
const {
clientX
} = e.changedTouches[0]
// fixed by xxxx 模拟点击事件,解决 ios 13 点击区域错位的问题
let diff = Math.abs(this.clientX - clientX)
let time = (new Date().getTime()) - this.timestamp
if (diff < 40 && time < 300) {
this.$emit('click', {
content: item,
index,
position
})
}
},
getButtonSize() {
const views = uni.createSelectorQuery().in(this)
views
.selectAll('.uni-swipe_button-group')
.boundingClientRect(data => {
let show = 'none'
if (this.autoClose) {
show = 'none'
} else {
show = this.show
}
this.button = {
data,
show
}
})
.exec()
}
}
}
<template>
<!-- 在微信小程序 app vue端 h5 使用wxs 实现-->
<!-- #ifdef APP-VUE || MP-WEIXIN || H5 -->
<view class="uni-swipe">
<view
class="uni-swipe_box"
:data-threshold="threshold"
:data-disabled="disabled"
:change:prop="swipe.sizeReady"
:prop="btn"
@touchstart="swipe.touchstart"
@touchmove="swipe.touchmove"
@touchend="swipe.touchend"
>
<!-- 在微信小程序 app vue端 h5 使用wxs 实现-->
<view class="uni-swipe_button-group button-group--left">
<slot name="left">
<view
v-for="(item,index) in leftOptions"
:data-button="btn"
:key="index"
:style="{
backgroundColor: item.style && item.style.backgroundColor ? item.style.backgroundColor : '#C7C6CD',
fontSize: item.style && item.style.fontSize ? item.style.fontSize : '16px'
}"
class="uni-swipe_button button-hock"
@touchstart="appTouchStart"
@touchend="appTouchEnd($event,index,item,'left')"
><text
class="uni-swipe_button-text"
:style="{color: item.style && item.style.color ? item.style.color : '#FFFFFF',}"
>{{ item.text }}</text></view>
</slot>
</view>
<slot></slot>
<view class="uni-swipe_button-group button-group--right">
<slot name="right">
<view
v-for="(item,index) in rightOptions"
:data-button="btn"
:key="index"
:style="{
backgroundColor: item.style && item.style.backgroundColor ? item.style.backgroundColor : '#C7C6CD',
fontSize: item.style && item.style.fontSize ? item.style.fontSize : '16px'
}"
class="uni-swipe_button button-hock"
@touchstart="appTouchStart"
@touchend="appTouchEnd($event,index,item,'right')"
><text
class="uni-swipe_button-text"
:style="{color: item.style && item.style.color ? item.style.color : '#FFFFFF',}"
>{{ item.text }}</text></view>
</slot>
</view>
</view>
</view>
<!-- #endif -->
<!-- app nvue端 使用 bindingx -->
<!-- #ifdef APP-NVUE -->
<view
ref="selector-box--hock"
class="uni-swipe"
@horizontalpan="touchstart"
@touchend="touchend"
>
<view
ref='selector-left-button--hock'
class="uni-swipe_button-group button-group--left"
>
<slot name="left">
<view
v-for="(item,index) in leftOptions"
:data-button="btn"
:key="index"
:style="{
backgroundColor: item.style && item.style.backgroundColor ? item.style.backgroundColor : '#C7C6CD',
fontSize: item.style && item.style.fontSize ? item.style.fontSize : '16px'
}"
class="uni-swipe_button button-hock"
@click.stop="onClick(index,item,'left')"
><text
class="uni-swipe_button-text"
:style="{color: item.style && item.style.color ? item.style.color : '#FFFFFF',}"
>{{ item.text }}</text></view>
</slot>
</view>
<view
ref='selector-right-button--hock'
class="uni-swipe_button-group button-group--right"
>
<slot name="right">
<view
v-for="(item,index) in rightOptions"
:data-button="btn"
:key="index"
:style="{
backgroundColor: item.style && item.style.backgroundColor ? item.style.backgroundColor : '#C7C6CD',
fontSize: item.style && item.style.fontSize ? item.style.fontSize : '16px'
}"
class="uni-swipe_button button-hock"
@click.stop="onClick(index,item,'right')"
><text
class="uni-swipe_button-text"
:style="{color: item.style && item.style.color ? item.style.color : '#FFFFFF',}"
>{{ item.text }}</text></view>
</slot>
</view>
<view
ref='selector-content--hock'
class="uni-swipe_box"
>
<slot></slot>
</view>
</view>
<!-- #endif -->
<!-- 其他平台使用 js ,长列表性能可能会有影响-->
<!-- #ifdef MP-ALIPAY || MP-BAIDU || MP-TOUTIAO || MP-QQ -->
<view class="uni-swipe">
<view
class="uni-swipe_box"
@touchstart="touchstart"
@touchmove="touchmove"
@touchend="touchend"
:style="{transform:moveLeft}"
:class="{ani:ani}"
>
<view class="uni-swipe_button-group button-group--left">
<slot name="left">
<view
v-for="(item,index) in leftOptions"
:data-button="btn"
:key="index"
:style="{
backgroundColor: item.style && item.style.backgroundColor ? item.style.backgroundColor : '#C7C6CD',
fontSize: item.style && item.style.fontSize ? item.style.fontSize : '16px'
}"
class="uni-swipe_button button-hock"
@touchstart="appTouchStart"
@touchend="appTouchEnd($event,index,item,'left')"
><text
class="uni-swipe_button-text"
:style="{color: item.style && item.style.color ? item.style.color : '#FFFFFF',}"
>{{ item.text }}</text></view>
</slot>
</view>
<slot></slot>
<view class="uni-swipe_button-group button-group--right">
<slot name="right">
<view
v-for="(item,index) in rightOptions"
:data-button="btn"
:key="index"
:style="{
backgroundColor: item.style && item.style.backgroundColor ? item.style.backgroundColor : '#C7C6CD',
fontSize: item.style && item.style.fontSize ? item.style.fontSize : '16px'
}"
@touchstart="appTouchStart"
@touchend="appTouchEnd($event,index,item,'right')"
class="uni-swipe_button button-hock"
><text
class="uni-swipe_button-text"
:style="{color: item.style && item.style.color ? item.style.color : '#FFFFFF',}"
>{{ item.text }}</text></view>
</slot>
</view>
</view>
</view>
<!-- #endif -->
</template>
<script
src="./index.wxs"
module="swipe"
lang="wxs"
></script>
<script>
// #ifdef APP-VUE|| MP-WEIXIN || H5
import mpwxs from './mpwxs'
// #endif
// #ifdef APP-NVUE
import bindingx from './bindingx.js'
// #endif
// #ifndef APP-PLUS|| MP-WEIXIN || H5
import mixins from './mpother'
// #endif
/**
* SwipeActionItem 滑动操作子组件
* @description 通过滑动触发选项的容器
* @tutorial https://ext.dcloud.net.cn/plugin?id=181
* @property {Boolean} show = [left|right|none] 开启关闭组件,auto-close = false 时生效
* @property {Boolean} disabled = [true|false] 是否禁止滑动
* @property {Boolean} autoClose = [true|false] 滑动打开当前组件,是否关闭其他组件
* @property {Number} threshold 滑动缺省值
* @property {Array} leftOptions 左侧选项内容及样式
* @property {Array} rgihtOptions 右侧选项内容及样式
* @event {Function} click 点击选项按钮时触发事件,e = {content,index} ,content(点击内容)、index(下标)
* @event {Function} change 组件打开或关闭时触发,left\right\none
*/
export default {
// #ifdef APP-VUE|| MP-WEIXIN||H5
mixins: [mpwxs],
// #endif
// #ifdef APP-NVUE
mixins: [bindingx],
// #endif
// #ifndef APP-PLUS|| MP-WEIXIN || H5
mixins: [mixins],
// #endif
props: {
// 控制开关
show: {
type: String,
default: 'none'
},
// 禁用
disabled: {
type: Boolean,
default: false
},
// 是否自动关闭
autoClose: {
type: Boolean,
default: true
},
// 滑动缺省距离
threshold: {
type: Number,
default: 20
},
// 左侧按钮内容
leftOptions: {
type: Array,
default () {
return []
}
},
// 右侧按钮内容
rightOptions: {
type: Array,
default () {
return []
}
}
},
inject: ['swipeaction']
}
</script>
<style
lang="scss"
scoped
>
.uni-swipe {
position: relative;
/* #ifndef APP-NVUE */
overflow: hidden;
/* #endif */
}
.uni-swipe_box {
/* #ifndef APP-NVUE */
display: flex;
flex-shrink: 0;
/* #endif */
position: relative;
}
.uni-swipe_content {
// border: 1px red solid;
}
.uni-swipe_button-group {
/* #ifndef APP-NVUE */
box-sizing: border-box;
display: flex;
/* #endif */
flex-direction: row;
position: absolute;
top: 0;
bottom: 0;
}
.button-group--left {
left: 0;
transform: translateX(-100%)
}
.button-group--right {
right: 0;
transform: translateX(100%)
}
.uni-swipe_button {
/* #ifdef APP-NVUE */
flex: 1;
/* #endif */
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
justify-content: center;
align-items: center;
padding: 0 20px;
}
.uni-swipe_button-text {
/* #ifndef APP-NVUE */
flex-shrink: 0;
/* #endif */
font-size: 14px;
}
.ani {
transition-property: transform;
transition-duration: 0.3s;
transition-timing-function: cubic-bezier(0.165, 0.84, 0.44, 1);
}
/* #ifdef MP-ALIPAY */
.movable-area {
/* width: 100%; */
height: 45px;
}
.movable-view {
display: flex;
/* justify-content: center; */
position: relative;
flex: 1;
height: 45px;
z-index: 2;
}
.movable-view-button {
display: flex;
flex-shrink: 0;
flex-direction: row;
height: 100%;
background: #C0C0C0;
}
/* .transition {
transition: all 0.3s;
} */
.movable-view-box {
flex-shrink: 0;
height: 100%;
background-color: #fff;
}
/* #endif */
</style>
<template>
<view>
<slot></slot>
</view>
</template>
<script>
/**
* SwipeAction 滑动操作
* @description 通过滑动触发选项的容器
* @tutorial https://ext.dcloud.net.cn/plugin?id=181
*/
export default {
data() {
return {};
},
provide() {
return {
swipeaction: this
};
},
created() {
this.children = [];
},
methods: {
closeOther(vm) {
if (this.openItem && this.openItem !== vm) {
// #ifdef APP-VUE || H5 || MP-WEIXIN
this.openItem.button.show = 'none'
// #endif
// #ifndef APP-VUE || H5 || MP-WEIXIN
this.openItem.close()
// #endif
}
this.openItem = vm
}
}
};
</script>
<style></style>
<template>
<view v-if="isShow" ref="ani" class="uni-transition" :class="[ani.in]" :style="'transform:' +transform+';'+stylesObject"
@click="change">
<slot></slot>
</view>
</template>
<script>
// #ifdef APP-NVUE
const animation = uni.requireNativePlugin('animation');
// #endif
/**
* Transition 过渡动画
* @description 简单过渡动画组件
* @tutorial https://ext.dcloud.net.cn/plugin?id=985
* @property {Boolean} show = [false|true] 控制组件显示或隐藏
* @property {Array} modeClass = [fade|slide-top|slide-right|slide-bottom|slide-left|zoom-in|zoom-out] 过渡动画类型
* @value fade 渐隐渐出过渡
* @value slide-top 由上至下过渡
* @value slide-right 由右至左过渡
* @value slide-bottom 由下至上过渡
* @value slide-left 由左至右过渡
* @value zoom-in 由小到大过渡
* @value zoom-out 由大到小过渡
* @property {Number} duration 过渡动画持续时间
* @property {Object} styles 组件样式,同 css 样式,注意带’-‘连接符的属性需要使用小驼峰写法如:`backgroundColor:red`
*/
export default {
name: 'uniTransition',
props: {
show: {
type: Boolean,
default: false
},
modeClass: {
type: Array,
default () {
return []
}
},
duration: {
type: Number,
default: 300
},
styles: {
type: Object,
default () {
return {}
}
}
},
data() {
return {
isShow: false,
transform: '',
ani: { in: '',
active: ''
}
};
},
watch: {
show: {
handler(newVal) {
if (newVal) {
this.open()
} else {
this.close()
}
},
immediate: true
}
},
computed: {
stylesObject() {
let styles = {
...this.styles,
'transition-duration': this.duration / 1000 + 's'
}
let transfrom = ''
for (let i in styles) {
let line = this.toLine(i)
transfrom += line + ':' + styles[i] + ';'
}
return transfrom
}
},
created() {
// this.timer = null
// this.nextTick = (time = 50) => new Promise(resolve => {
// clearTimeout(this.timer)
// this.timer = setTimeout(resolve, time)
// return this.timer
// });
},
methods: {
change() {
this.$emit('click', {
detail: this.isShow
})
},
open() {
clearTimeout(this.timer)
this.isShow = true
this.transform = ''
this.ani.in = ''
for (let i in this.getTranfrom(false)) {
if (i === 'opacity') {
this.ani.in = 'fade-in'
} else {
this.transform += `${this.getTranfrom(false)[i]} `
}
}
this.$nextTick(() => {
setTimeout(() => {
this._animation(true)
}, 50)
})
},
close(type) {
clearTimeout(this.timer)
this._animation(false)
},
_animation(type) {
let styles = this.getTranfrom(type)
// #ifdef APP-NVUE
if(!this.$refs['ani']) return
animation.transition(this.$refs['ani'].ref, {
styles,
duration: this.duration, //ms
timingFunction: 'ease',
needLayout: false,
delay: 0 //ms
}, () => {
if (!type) {
this.isShow = false
}
this.$emit('change', {
detail: this.isShow
})
})
// #endif
// #ifndef APP-NVUE
this.transform = ''
for (let i in styles) {
if (i === 'opacity') {
this.ani.in = `fade-${type?'out':'in'}`
} else {
this.transform += `${styles[i]} `
}
}
this.timer = setTimeout(() => {
if (!type) {
this.isShow = false
}
this.$emit('change', {
detail: this.isShow
})
}, this.duration)
// #endif
},
getTranfrom(type) {
let styles = {
transform: ''
}
this.modeClass.forEach((mode) => {
switch (mode) {
case 'fade':
styles.opacity = type ? 1 : 0
break;
case 'slide-top':
styles.transform += `translateY(${type?'0':'-100%'}) `
break;
case 'slide-right':
styles.transform += `translateX(${type?'0':'100%'}) `
break;
case 'slide-bottom':
styles.transform += `translateY(${type?'0':'100%'}) `
break;
case 'slide-left':
styles.transform += `translateX(${type?'0':'-100%'}) `
break;
case 'zoom-in':
styles.transform += `scale(${type?1:0.8}) `
break;
case 'zoom-out':
styles.transform += `scale(${type?1:1.2}) `
break;
}
})
return styles
},
_modeClassArr(type) {
let mode = this.modeClass
if (typeof(mode) !== "string") {
let modestr = ''
mode.forEach((item) => {
modestr += (item + '-' + type + ',')
})
return modestr.substr(0, modestr.length - 1)
} else {
return mode + '-' + type
}
},
// getEl(el) {
// console.log(el || el.ref || null);
// return el || el.ref || null
// },
toLine(name) {
return name.replace(/([A-Z])/g, "-$1").toLowerCase();
}
}
}
</script>
<style>
.uni-transition {
transition-timing-function: ease;
transition-duration: 0.3s;
transition-property: transform, opacity;
}
.fade-in {
opacity: 0;
}
.fade-active {
opacity: 1;
}
.slide-top-in {
/* transition-property: transform, opacity; */
transform: translateY(-100%);
}
.slide-top-active {
transform: translateY(0);
/* opacity: 1; */
}
.slide-right-in {
transform: translateX(100%);
}
.slide-right-active {
transform: translateX(0);
}
.slide-bottom-in {
transform: translateY(100%);
}
.slide-bottom-active {
transform: translateY(0);
}
.slide-left-in {
transform: translateX(-100%);
}
.slide-left-active {
transform: translateX(0);
opacity: 1;
}
.zoom-in-in {
transform: scale(0.8);
}
.zoom-out-active {
transform: scale(1);
}
.zoom-out-in {
transform: scale(1.2);
}
</style>
<template>
<view>
</view>
</template>
<script>
export default {
data() {
return {
};
}
}
</script>
<style>
</style>
# swipe-action 滑动操作
### `觉得不错,给个5星好评吧`
### QQ交流群(加群持续更新) 607391225
![QQ交流群](http://qn.kemean.cn//upload/202004/14/15868301778472k7oubi6.png)
# [点击跳转-本插件示例](https://ext.dcloud.net.cn/plugin?id=2009)
# [点击跳转-5年的web前端开源的uni-app快速开发模板-下载看文档](https://ext.dcloud.net.cn/plugin?id=2009)
### 使用时不懂的请看上面链接的插件示例
### 示例代码
```
<template>
<view>
<swipe-action :options="options" :show="show"><view class="swipe_action">滑动</view></swipe-action>
<swipe-action :options="options" disabled><view class="swipe_action">禁止滑动</view></swipe-action>
<view v-for="(item, index) of 3" :key="index" class="swipe_action_list">
<swipe-action :options="options3" :index="index" @button="onButton">
<view class="swipe_action">滑动列表{{ index + 1 }}</view>
</swipe-action>
</view>
</view>
</template>
<script>
import swipeAction from '@/components/zhouWei-swipeAction';
export default {
components: {
swipeAction
},
data() {
return {
options: [
{
text: '删除',
style: {
backgroundColor: '#dd524d'
}
},
{
text: '取消',
style: {
backgroundColor: '#007aff'
}
}
],
show: true
};
},
methods: {
onButton(e) {
uni.showToast({
title: '您点击了滑动列表' + (e.index + 1) + '的第' + (e.buttonIndex + 1) + '个按钮,按钮为‘' + e.content.text + '’',
icon: 'none'
});
}
},
}
</script>
```
### 使用说明
| 名称 | 类型 | 默认值 | 描述 |
| ----------|--------------- | ------------- | -------------------|
| options | Array | [] | 查看options参数说明 |
| disabled | Boolean | false | 是否禁止滑动 |
| show | Boolean | false | 是否打开 |
| autoClose | Boolean | true | 点击后是否自动关闭 |
| index | Number | 0 | 循环的时候的索引值,通过@button传递出去 |
### options参数说明
| 名称 | 类型 | 描述 |
| ------------------------|--------------- | -------------------|
| text | String | 按钮名称 |
| style | Object | 按钮样式 |
| style.backgroundColor | String | 按钮背景颜色 |
| style.fontSize | String | 按钮字体大小 |
| style.color | String | 按钮字体颜色 |
### 事件
| 名称 | 描述 |
| -----------------| --------------------------|
| button | 左滑按钮点击事件 |
```
按钮左滑按钮点击事件返回值
{
content: "点击按钮的options参数",
index: "循环的时候的索引值",
buttonIndex: "点击按钮的索引值"
}
```
\ No newline at end of file
<template>
<view class="swipe_action_box" @touchstart="onTouchstart" @touchmove="onTouchmove" @touchcancel="onTouchcancel" @touchend="onTouchend">
<view class="swipe_action_item" :style="{ width: (screenWidth + maxWidth) + 'px', transform: 'translateX(' + translateX + 'px)', transition: 'transform ' + animationTime + 'ms cubic-bezier(.165, .84, .44, 1)' }">
<view class="swipe_action_content"><slot></slot></view>
<view class="swipe_action_btn_box" ref="swipeActionBtnBox">
<view v-for="(item,index) of options" :key="index" class="swipe_action_btn" :style="{
backgroundColor: item.style && item.style.backgroundColor ? item.style.backgroundColor : '#C7C6CD'
}" @click.stop="onBtn(index,item)">
<text :style="{
fontSize: item.style && item.style.fontSize ? item.style.fontSize : '14px',
color: item.style && item.style.color ? item.style.color : '#FFFFFF'
}">{{ item.text }}</text>
</view>
</view>
</view>
</view>
</template>
<script>
// #ifdef APP-NVUE
const dom = weex.requireModule('dom');
// #endif
export default {
props: {
/**
* 按钮内容
*/
options: {
type: Array,
default () {
return []
}
},
/**
* 禁用
*/
disabled: {
type: Boolean,
default: false
},
/**
* 变量控制开关
*/
show: {
type: Boolean,
default: false
},
/**
* 是否自动关闭
*/
autoClose: {
type: Boolean,
default: true
},
/**
* swipe-action 的索引值
*/
index: {
type: Number,
default: 0
}
},
data() {
return {
//开始触摸时间
startTime: 0,
//开始触摸距离
touchStartX: 0,
//最大距离
maxWidth: 58,
//滑动距离
translateX: 0,
animationTime: 0,
//上次的位置
currentX: 0,
screenWidth: 0
};
},
watch:{
show(val){
if(val){
this.animationTime = 350;
this.translateX = -this.maxWidth;
}else {
this.animationTime = 350;
this.translateX = 0;
}
}
},
created() {
let systemInfo = uni.getSystemInfoSync();
this.screenWidth = systemInfo.screenWidth;
},
mounted() {
const _this = this;
setTimeout(() => {
// #ifdef APP-NVUE
dom.getComponentRect(this.$refs['swipeActionBtnBox'], (data) => {
_this.maxWidth = data.size.width;
if(_this.show){
_this.animationTime = 350;
_this.translateX = -data.size.width;
}
});
// #endif
// #ifndef APP-NVUE
uni.createSelectorQuery().in(this).selectAll('.swipe_action_btn_box')
.boundingClientRect(data => {
_this.maxWidth = data[0].width;
if(_this.show){
_this.animationTime = 350;
_this.translateX = -data[0].width;
}
}).exec()
// #endif
},500);
},
//方法
methods: {
onBtn(index, item) {
this.$emit('button', {
content: item,
index: this.index,
buttonIndex: index
});
if(this.autoClose){
this.animationTime = 350;
this.translateX = 0;
}
},
// 手指触摸动作开始
onTouchstart(e) {
if(this.disabled){
return;
}
//储存手指触摸坐标,当前时间戳,当前坐标
// #ifdef APP-NVUE
this.touchStartX = e.changedTouches[0].screenX;
// #endif
// #ifndef APP-NVUE
this.touchStartX = e.changedTouches[0].clientX;
// #endif
this.startTime = new Date().getTime();
this.currentX = this.translateX;
},
// 手指触摸后移动
onTouchmove(e) {
if(this.disabled){
return;
}
//手指当前坐标
// #ifdef APP-NVUE
const clientX = e.changedTouches[0].screenX;
// #endif
// #ifndef APP-NVUE
const clientX = e.changedTouches[0].clientX;
// #endif
//计算滑动距离
const difference = this.touchStartX - clientX;
//判断左滑还是右滑
if (difference > 0) {
//计算当前已滑动距离
const leftDifference = this.currentX - Math.abs(difference);
//判断是否大于滑动的最大宽度
if (this.maxWidth < Math.abs(leftDifference)) {
this.animationTime = 0;
this.translateX = -this.maxWidth;
} else {
this.animationTime = 0;
this.translateX = leftDifference;
}
} else {
const rightDifference = this.currentX + Math.abs(difference);
if (0 < rightDifference) {
this.animationTime = 0;
this.translateX = 0;
} else {
this.animationTime = 0;
this.translateX = rightDifference;
}
}
},
// 手指触摸动作被打断,如来电提醒,弹窗
onTouchcancel(e) {
if(this.disabled){
return;
}
// #ifdef APP-NVUE
this.finallySlide(e.changedTouches[0].screenX);
// #endif
// #ifndef APP-NVUE
this.finallySlide(e.changedTouches[0].clientX);
// #endif
},
// 手指触摸动作结束
onTouchend(e) {
if(this.disabled){
return;
}
// #ifdef APP-NVUE
this.finallySlide(e.changedTouches[0].screenX);
// #endif
// #ifndef APP-NVUE
this.finallySlide(e.changedTouches[0].clientX);
// #endif
},
//最终判断滑动
finallySlide(finallyX) {
//手指离开的时间
const endTime = new Date().getTime();
//手机滑动屏幕的总花费时间
const timeDifference = endTime - this.startTime;
//手指触摸总滑动距离
const distanceDifference = this.touchStartX - finallyX;
//判断最终滑动方向
if (distanceDifference > 0) {
//判断是否滑动到左边 滑动距离超过3分之一 或者 滑动时间在300毫秒并且距离在4分之一
if (Math.abs(this.translateX) > this.maxWidth / 2 || (timeDifference < 300 && distanceDifference > this.maxWidth / 4)) {
this.animationTime = 350;
this.translateX = -this.maxWidth;
} else {
this.animationTime = 350;
this.translateX = 0;
}
} else if (distanceDifference < 0) {
//判断是否滑动到右边 滑动距离超过3分之一 或者 滑动时间在300毫秒并且距离在4分之一
if (Math.abs(this.translateX) < this.maxWidth / 2 || (timeDifference < 300 && Math.abs(distanceDifference) > this.maxWidth / 4)) {
this.animationTime = 350;
this.translateX = 0;
} else {
this.animationTime = 350;
this.translateX = -this.maxWidth;
}
}
}
}
};
</script>
<style scoped>
.swipe_action_box {
overflow: hidden;
width: 750rpx;
}
.swipe_action_item {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
}
.swipe_action_content {
width: 750rpx;
/* #ifndef APP-NVUE */
flex-shrink: 0;
/* #endif */
}
.swipe_action_btn_box {
/* #ifndef APP-NVUE */
display: flex;
flex-shrink: 0;
/* #endif */
flex-direction: row;
}
.swipe_action_btn {
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
flex-direction: row;
align-items: center;
justify-content: center;
padding: 0 30rpx;
}
</style>
<template>
<view >
<view class="bar-fixed" style="">
<view class="tab-bar" style="">
<!-- <view class="bar-item" >
<image class="bar-img" src="../static/bottombar/home.png"></image>
<text class="bar-text">首页</text>
</view> -->
<view @click="toUrl(item.pagePath)" v-for="(item,index) in tabBar.list" :key="index" class="bar-item " >
<image class="bar-img" :src="item.selected?item.selectedIconPath:item.iconPath"></image>
<text class="bar-text" :style="{'color': (item.selected? tabBar.selectedColor:'#333')}">{{item.text}}</text>
</view>
</view>
</view>
</view>
</template>
<script>
export default{
name:'footv',
props:{
tabBar: {
type: Object,
default: function(e) {
return {}
}
},
},
methods:{
toUrl(e) {
console.log("切换标签",e);
// uni.navigateTo({
// url:e
// })
uni.reLaunch({
url:e
})
},
},
}
</script>
<style>
.tab-bar{
width:100%;
display:flex;
justify-content:space-around;
background-color:#fff;
border-top:1rpx solid #eee;
}
.bar-fixed{
position:fixed;
bottom:0;
left:0;
width:100%;
}
.bar-item{
display: flex;
flex-direction: column;
font-size:25upx;
text-align: center;
padding:25upx 10upx;
color:#333;
}
.bar-img{
width:50upx;
height:50upx;
margin: 0 auto;
margin-bottom:5upx;
}
.bar-text-selected{
color:red;
}
</style>
import Vue from 'vue'
import App from './App'
import Common from './utils/common.js'
Vue.config.productionTip = false
Vue.prototype.$common = Common;
App.mpType = 'app'
const app = new Vue({
...App
})
app.$mount()
{
"appid" : "__UNI__66959D4",
"name" : "广西残联",
"description" : "广西残疾人联合会",
"versionName" : "1.0.0",
"app-plus" : {
"distribute" : {
"icons" : {
"android" : {
"hdpi" : "unpackage/res/icons/72x72.png",
"xhdpi" : "unpackage/res/icons/96x96.png",
"xxhdpi" : "unpackage/res/icons/144x144.png",
"xxxhdpi" : "unpackage/res/icons/192x192.png"
},
"ios" : {
"appstore" : "unpackage/res/icons/1024x1024.png",
"ipad" : {
"app" : "unpackage/res/icons/76x76.png",
"app@2x" : "unpackage/res/icons/152x152.png",
"notification" : "unpackage/res/icons/20x20.png",
"notification@2x" : "unpackage/res/icons/40x40.png",
"proapp@2x" : "unpackage/res/icons/167x167.png",
"settings" : "unpackage/res/icons/29x29.png",
"settings@2x" : "unpackage/res/icons/58x58.png",
"spotlight" : "unpackage/res/icons/40x40.png",
"spotlight@2x" : "unpackage/res/icons/80x80.png"
},
"iphone" : {
"app@2x" : "unpackage/res/icons/120x120.png",
"app@3x" : "unpackage/res/icons/180x180.png",
"notification@2x" : "unpackage/res/icons/40x40.png",
"notification@3x" : "unpackage/res/icons/60x60.png",
"settings@2x" : "unpackage/res/icons/58x58.png",
"settings@3x" : "unpackage/res/icons/87x87.png",
"spotlight@2x" : "unpackage/res/icons/80x80.png",
"spotlight@3x" : "unpackage/res/icons/120x120.png"
}
}
},
"sdkConfigs" : {
"ad" : {}
}
}
},
"versionCode" : 100
}
{
"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
//残联绩效自评start-----------------
{
"path" : "pages/comment/flow-btn/flow-btn",
"style" : {
"navigationBarTitleText": "广西壮族自治区残疾人联合会",
"navigationBarBackgroundColor":"#CA0000"
}
},
//残联绩效自评end-------------------
{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "残疾人家庭无障碍改造系统",
"navigationBarBackgroundColor":"#2e7dfe"
}
}, {
"path": "pages/project/product",
"style": {
"navigationBarTitleText": "产品选择",
"navigationBarBackgroundColor":"#2e7dfe"
}
},{
"path": "pages/project/projectdetails",
"style": {
"navigationBarTitleText": "个案详情",
"navigationBarBackgroundColor":"#2e7dfe"
}
}, {
"path": "pages/project/project",
"style": {
"navigationBarTitleText": "服务项目",
"navigationBarBackgroundColor":"#2e7dfe"
}
}, {
"path": "pages/project/addpeople",
"style": {
"navigationBarTitleText": "添加服务人员",
"navigationBarBackgroundColor":"#2e7dfe"
}
},
{
"path": "pages/center/centerpersonal",
"style": {
"navigationBarTitleText": "个人中心",
"navigationBarBackgroundColor":"#2e7dfe"
}
}, {
"path": "pages/staff/staff",
"style": {
"navigationBarTitleText": "残疾人员",
"navigationBarBackgroundColor":"#2e7dfe"
}
}, {
"path" : "pages/login/login",
"style" : {
"navigationBarTitleText": "残疾人家庭无障碍改造系统",
"navigationBarBackgroundColor":"#2e7dfe"
}
},{
"path": "pages/project/projectjindu",
"style": {
"navigationBarTitleText": "添加施工进度",
"navigationBarBackgroundColor":"#2e7dfe"
}
},{
"path": "pages/center/center",
"style": {
"navigationBarTitleText": "个人中心",
"navigationBarBackgroundColor":"#2e7dfe"
}
}, {
"path": "pages/center/centershuoming",
"style": {
"navigationBarTitleText": "使用说明",
"navigationBarBackgroundColor":"#2e7dfe"
}
}, {
"path": "pages/project/projectinfo",
"style": {
"navigationBarTitleText": "所有人员",
"navigationBarBackgroundColor":"#2e7dfe"
}
}, {
"path": "pages/project/projectlist",
"style": {
"navigationBarTitleText": "项目详情",
"navigationBarBackgroundColor":"#2e7dfe"
}
},
// ---------残联绩效自评start---------------------
// {
// "path" : "pages/comment/flow-btn/flow-btn",
// "style" : {
// "navigationBarTitleText": "广西壮族自治区残疾人联合会"
// }
// },
{
"path": "pages/comment/main/main",
"style": {
"navigationBarTitleText": "广西残联自评app",
"navigationBarBackgroundColor":"#CA0000"
}
},
{
"path": "pages/comment/login/login",
"style": {
"navigationBarTitleText": "登录",
"navigationBarBackgroundColor":"#CA0000"
}
},
{
"path": "pages/comment/reg/reg",
"style": {
"navigationBarTitleText": "注册",
"navigationBarBackgroundColor":"#CA0000"
}
}, {
"path": "pages/comment/user/user",
"style": {
"navigationBarTitleText": "我的",
"navigationBarBackgroundColor":"#CA0000"
}
}
,{
"path" : "pages/comment/evaluate/evaluate",
"style" : {
"navigationBarTitleText": "意见反馈",
"navigationBarBackgroundColor":"#CA0000"
}
}
,{
"path" : "pages/comment/evaluate-history/evaluate-history",
"style" : {
"navigationBarTitleText": "反馈历史",
"navigationBarBackgroundColor":"#CA0000"
}
}
,{
"path" : "pages/comment/service-apl/service-apl",
"style" : {
"navigationBarTitleText": "申请服务",
"navigationBarBackgroundColor":"#CA0000"
}
}
,{
"path" : "pages/comment/service-apl-history/service-apl-history",
"style" : {
"navigationBarTitleText": "申请记录 ",
"navigationBarBackgroundColor":"#CA0000"
}
},{
"path" : "pages/comment/flow/flow",
"style" : {
"navigationBarTitleText": "残疾人家庭无障碍改造系统",
"navigationBarBackgroundColor":"#CA0000"
}
}
//----------残联绩效自评end-----------------------
],
"globalStyle": {
"navigationBarTextStyle": "white",
"navigationBarTitleText": "残疾人家庭无障碍改造系统"
// "navigationBarBackgroundColor": "#2e7dfe"
// "backgroundColor": "#F8F8F8"
}
// "tabBar": {
// "color": "#999999",
// "selectedColor": "#2e7dfe",
// "borderStyle": "white",
// "backgroundColor": "#ffffff",
// "list": [{
// "pagePath": "pages/index/index",
// "iconPath": "static/ic_icon-01.png",
// "selectedIconPath": "static/ic_icon-05.png",
// "text": "首页"
// },
// {
// "pagePath": "pages/project/project",
// "iconPath": "static/ic_icon-02.png",
// "selectedIconPath": "static/ic_icon-06.png",
// "text": "服务项目"
// },
// {
// "pagePath": "pages/staff/staff",
// "iconPath": "static/ic_icon-03.png",
// "selectedIconPath": "static/ic_icon-07.png",
// "text": "残疾人员"
// },
// {
// "pagePath": "pages/center/center",
// "iconPath": "static/ic_icon-04.png",
// "selectedIconPath": "static/ic_icon-08.png",
// "text": "个人中心"
// }
// ]
// },
// "condition" : { //模式配置,仅开发期间生效
// "current": 0, //当前激活的模式(list 的索引项)
// "list": [
// {
// "name": "", //模式名称
// "path": "", //启动页面,必选
// "query": "" //启动参数,在页面的onLoad函数里面得到
// }
// ]
// }
}
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment