crm
This commit is contained in:
parent
61ab038c4e
commit
1b4278010e
26
App.vue
26
App.vue
@ -32,35 +32,9 @@
|
||||
main.SET_TOKEN(opt.accessToken);
|
||||
}
|
||||
})
|
||||
|
||||
onShow(() => {
|
||||
// 检查用户登录情况
|
||||
// #ifdef H5
|
||||
if (isWeixin()) {
|
||||
// H5编译的代码
|
||||
// 判断是否是微信浏览器
|
||||
//oAuth()
|
||||
//return;
|
||||
}
|
||||
// #endif
|
||||
// #ifdef MP-WEIXIN
|
||||
//wechatMiniLogin();
|
||||
// #endif
|
||||
})
|
||||
|
||||
onHide(() => {
|
||||
console.log('App Hide')
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import '~@/static/style/app.scss';
|
||||
//@import 'static/iconfont/iconfont.scss';
|
||||
//@import url('./static/style/style.less');
|
||||
@import 'static/style/yshop.css';
|
||||
|
||||
// /*每个页面公共css */
|
||||
// page {
|
||||
// background-color: #f5f5f5;
|
||||
// }
|
||||
</style>
|
13
pages.json
13
pages.json
@ -20,13 +20,6 @@
|
||||
"enablePullDownRefresh": true
|
||||
}
|
||||
|
||||
}, {
|
||||
"path": "pages/msg/index",
|
||||
"style": {
|
||||
"navigationBarTitleText": "消息",
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
|
||||
}
|
||||
],
|
||||
"subPackages": [{
|
||||
@ -363,12 +356,6 @@
|
||||
"iconPath": "static/images/tabBar/customer.png",
|
||||
"selectedIconPath": "static/images/tabBar/customer-selected.png"
|
||||
},
|
||||
//{
|
||||
// "pagePath": "pages/msg/index",
|
||||
// "text": "消息",
|
||||
// "iconPath": "static/images/tabBar/msg.png",
|
||||
// "selectedIconPath": "static/images/tabBar/msg-select.png"
|
||||
// },
|
||||
{
|
||||
"pagePath": "pages/mine/mine",
|
||||
"text": "我的",
|
||||
|
@ -17,35 +17,32 @@
|
||||
@scrolltolower="reachBottom">
|
||||
<view class="page-box">
|
||||
<block v-if="list.length > 0">
|
||||
<uv-checkbox-group>
|
||||
<view class="client" v-for="(item, index) in list" :key="index">
|
||||
<view class="top">
|
||||
<view class="left">
|
||||
<view class="store">
|
||||
<uv-checkbox disabled activeColor="#09b4f1" :checked="item.checked"
|
||||
:name="item.id">{{item.storeName}}</uv-checkbox>
|
||||
</view>
|
||||
</view>
|
||||
<view class="client" v-for="(item, index) in list" :key="index">
|
||||
<view class="top">
|
||||
<view>
|
||||
<radio activeBackgroundColor="#09b4f1" activeBorderColor="#09b4f1" color="#09b4f1" :disabled="true"
|
||||
:value="item.id" :checked="item.checked" />
|
||||
</view>
|
||||
<view class="sku-name">{{item.storeName}}</view>
|
||||
</view>
|
||||
|
||||
<view class="item">
|
||||
<view class="title uv-line-2 flex">
|
||||
<view class="mr-1">规格:{{item.sku}}</view>
|
||||
<uv-text color="#3c9cff" text="选择规格" @click="selectSku(item,index)"></uv-text>
|
||||
</view>
|
||||
<view class="title">库存:{{item.stock}}</view>
|
||||
<view class="decimal">价格:{{item.price}}</view>
|
||||
<view class="item">
|
||||
<view class="title uv-line-2 flex">
|
||||
<view class="mr-1">规格:{{item.sku}}</view>
|
||||
<uv-text color="#3c9cff" text="选择规格" @click="selectSku(item,index)"></uv-text>
|
||||
</view>
|
||||
<view class="title">库存:{{item.stock}}</view>
|
||||
<view class="decimal">价格:{{item.price}}</view>
|
||||
</view>
|
||||
|
||||
<view class="bottom">
|
||||
<view class="client_time">添加时间: {{formatDateTime(item.createTime)}}</view>
|
||||
<view class="flex">
|
||||
<view class="btn ml-1 entity" :style="{backgroundColor:item.checked?'#999':'#09b4f1'}"
|
||||
@click.stop="onSelect(item,index)">{{item.checked ? '取消':'选择'}}</view>
|
||||
</view>
|
||||
<view class="bottom">
|
||||
<view class="client_time">添加时间: {{formatDateTime(item.createTime)}}</view>
|
||||
<view class="flex">
|
||||
<view class="btn ml-1 entity" :style="{backgroundColor:item.checked?'#999':'#09b4f1'}"
|
||||
@click.stop="onSelect(item,index)">{{item.checked ? '取消':'选择'}}</view>
|
||||
</view>
|
||||
</view>
|
||||
</uv-checkbox-group>
|
||||
</view>
|
||||
<uv-load-more :status="listStatus"></uv-load-more>
|
||||
</block>
|
||||
<uv-empty text="暂无数据" v-else margin-top="50" mode="list"></uv-empty>
|
||||
@ -150,6 +147,9 @@
|
||||
storeToRefs
|
||||
} from 'pinia'
|
||||
const main = useMainStore()
|
||||
const {
|
||||
selectProductList
|
||||
} = storeToRefs(main)
|
||||
const title = ref('选择产品')
|
||||
const keyword = ref('')
|
||||
const selected = ref(false)
|
||||
@ -157,10 +157,6 @@
|
||||
const oldScrollTop = ref(0)
|
||||
const scrollTop = ref(-1)
|
||||
const skuList = ref([])
|
||||
|
||||
// search: {
|
||||
// fontSise: '18px'
|
||||
// },
|
||||
const list = ref([])
|
||||
const selectList = ref([])
|
||||
const consentShow = ref(false)
|
||||
@ -178,7 +174,6 @@
|
||||
const thisIndex = ref(0)
|
||||
|
||||
|
||||
|
||||
onReady(() => {
|
||||
uni.getSystemInfo({
|
||||
success(res) {
|
||||
@ -192,15 +187,11 @@
|
||||
})
|
||||
})
|
||||
|
||||
onLoad((e) => {
|
||||
//getBusinessList();
|
||||
})
|
||||
|
||||
onShow(() => {
|
||||
onLoad((opt) => {
|
||||
selectList.value = selectProductList.value || []
|
||||
getProductList()
|
||||
})
|
||||
|
||||
|
||||
// 选中一个
|
||||
const selectShowRef = ref()
|
||||
const onSelect = (val, i) => {
|
||||
@ -210,7 +201,6 @@
|
||||
icon: 'error',
|
||||
duration: 2000
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
list.value.forEach((item, index) => {
|
||||
@ -230,7 +220,6 @@
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const selectSku = async (val, index) => {
|
||||
@ -284,9 +273,9 @@
|
||||
})
|
||||
selectList.value.splice(index, 1)
|
||||
}
|
||||
|
||||
// 选好了
|
||||
const chosen = () => {
|
||||
// 储存
|
||||
main.SET_SELECT_PRODUCT(selectList.value)
|
||||
uni.navigateBack();
|
||||
}
|
||||
@ -301,7 +290,6 @@
|
||||
}).then(res => {
|
||||
if (res) {
|
||||
res.list.forEach((item, index) => {
|
||||
//item.create_time = this.timeFormats(item.create_time)
|
||||
item.checked = false
|
||||
// 设置默认数据
|
||||
item.nums = 1
|
||||
@ -327,12 +315,11 @@
|
||||
}
|
||||
})
|
||||
}
|
||||
// scroll 滚动记录
|
||||
|
||||
const scroll = (e) => {
|
||||
oldScrollTop.value = e.detail.scrollTop
|
||||
}
|
||||
|
||||
|
||||
// 滚动到底部
|
||||
const reachBottom = () => {
|
||||
if (lastPage.value || listStatus.value == 'loading') return;
|
||||
@ -375,16 +362,13 @@
|
||||
|
||||
.top {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
|
||||
.left {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.store {
|
||||
font-size: 28rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
.sku-name {
|
||||
font-size: 30rpx;
|
||||
margin-left: 10rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.right {
|
||||
|
@ -88,7 +88,7 @@
|
||||
</view>
|
||||
<!-- 底部按钮 -->
|
||||
<view class="bottom-btn">
|
||||
<uv-button :plain="true" @click="moreShow" customStyle="padding:0 80rpx;border:solid">更多</uv-button>
|
||||
<view class="btn more-btn" @click="moreShow">更多</view>
|
||||
<view class="btn entity ml-1" @click="onAdd">跟进</view>
|
||||
</view>
|
||||
</view>
|
||||
@ -662,11 +662,21 @@
|
||||
border-radius: 5px;
|
||||
font-size: 28rpx;
|
||||
text-align: center;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.entity {
|
||||
color: #fff;
|
||||
background-color: #09b4f1;
|
||||
z-index: 999;
|
||||
}
|
||||
|
||||
.more-btn {
|
||||
padding: 15rpx 60rpx;
|
||||
background-color: #5ecc62;
|
||||
color: #fff;
|
||||
margin-right: 12rpx;
|
||||
z-index: 999;
|
||||
}
|
||||
}
|
||||
|
||||
@ -686,6 +696,7 @@
|
||||
.grid-text {
|
||||
font-size: 28rpx;
|
||||
margin-top: 4rpx;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -70,12 +70,6 @@
|
||||
</template>
|
||||
</uv-input>
|
||||
</uv-form-item>
|
||||
<!-- <uv-form-item label="审批人:">
|
||||
<uv-input disabledColor="#ffffff" disabled v-model="form.flowAdminIdName" placeholder="请去审批流程里配置合同审批" />
|
||||
</uv-form-item> -->
|
||||
<!-- <uv-form-item label="备注:">
|
||||
<uv-textarea v-model="form.remark" :disabled="isCheck" placeholder="请输入备注"></uv-textarea>
|
||||
</uv-form-item> -->
|
||||
</uv-form>
|
||||
<!-- 产品 -->
|
||||
<view class="flex cif-title" @click="type !== 'detail' ? selectProduct() : ''">
|
||||
@ -129,8 +123,8 @@
|
||||
<view class="item-photo-list-item" style="font-size: 0; position: relative;margin-bottom: 60rpx;"
|
||||
:style="{marginRight:(index+1)%3==0?'0rpx':'20rpx'}" v-for="(item, index) in imgFiles" :key="item"
|
||||
@click="replaceImage(item, index)">
|
||||
<image v-if="!isCheck" src="@/static/greyguanbi.png" mode="aspectFit" class="item-photo-list-item-close"
|
||||
@click.stop="deleteItem(item, index)"></image>
|
||||
<image v-if="!isCheck" src="https://sys.znkjfw.com/imgs/crmimages/close.png" mode="aspectFit"
|
||||
class="item-photo-list-item-close" @click.stop="deleteItem(item, index)"></image>
|
||||
<image v-if="!isCheck" :src="item.url" mode="" style="width: 100%; height: 100%"></image>
|
||||
</view>
|
||||
<image src="http://sys.znkjfw.com/imgs/process/uploadzp.png" mode="aspectFill" class="item-photo-list-item"
|
||||
@ -144,8 +138,8 @@
|
||||
<view class="item-photo-list">
|
||||
<view class="item-photo-list-item" style="font-size: 0; position: relative;margin-bottom: 60rpx;"
|
||||
:style="{marginRight:(index+1)%3==0?'0rpx':'20rpx'}" v-for="(item, index) in pdfList" :key="item">
|
||||
<image v-if="!isCheck" src="@/static/greyguanbi.png" mode="aspectFit" class="item-photo-list-item-close"
|
||||
@click.stop="deleteFiles(item, index)"></image>
|
||||
<image v-if="!isCheck" src="https://sys.znkjfw.com/imgs/crmimages/close.png" mode="aspectFit"
|
||||
class="item-photo-list-item-close" @click.stop="deleteFiles(item, index)"></image>
|
||||
<image v-if="!isCheck" src="http://sys.znkjfw.com/imgs/process/pdfIcon.png" mode=""
|
||||
style="width: 100%; height: 100%">
|
||||
</image>
|
||||
@ -160,33 +154,8 @@
|
||||
<view class="mt-4" style="text-align: center;">
|
||||
<uv-button color="#09b4f1" @click="submit" :disabled="isCheck || submitBtn" :ripple="true">确定提交</uv-button>
|
||||
</view>
|
||||
<!-- <view class="mt-4 flex justify-end" style="text-align: center;" v-else>
|
||||
<view style="width: 25%;margin-right: 10rpx;">
|
||||
<uv-button color="#09b4f1" @click="submitCheck(1)">审核</uv-button>
|
||||
</view>
|
||||
<view style="width: 25%;">
|
||||
<uv-button type="error" @click="selectShow5()">拒绝</uv-button>
|
||||
</view>
|
||||
</view> -->
|
||||
</view>
|
||||
<uv-popup mode="bottom" round="38" ref="selectShowRef5">
|
||||
<view class="popup-content">
|
||||
<view class="popup-title">
|
||||
<view class="" style="width: 45px;">
|
||||
</view>
|
||||
<text class="">输入驳回理由</text>
|
||||
<view class="" @click="selectShowClose5" style="width: 45px;">
|
||||
<uv-icon name="close" color="#909399" size="24"></uv-icon>
|
||||
</view>
|
||||
</view>
|
||||
<view style="height: 500rpx;padding: 20rpx;">
|
||||
<uv-textarea v-model="form2.remark" placeholder="输入驳回理由"></uv-textarea>
|
||||
</view>
|
||||
<view style="padding: 20rpx;">
|
||||
<uv-button color="#09b4f1" @click="submitCheck(2)">确定</uv-button>
|
||||
</view>
|
||||
</view>
|
||||
</uv-popup>
|
||||
|
||||
<!-- 选择客户弹窗 -->
|
||||
<uv-popup mode="bottom" round="38" ref="selectShowRef">
|
||||
<view class="popup-content">
|
||||
@ -450,11 +419,6 @@
|
||||
const keyword3 = ref('')
|
||||
const businessList = ref([])
|
||||
const isCheck = ref(false)
|
||||
const form2 = ref({
|
||||
id: 0,
|
||||
agreeType: 1,
|
||||
remark: ''
|
||||
})
|
||||
|
||||
onLoad((e) => {
|
||||
type.value = e.type
|
||||
@ -862,13 +826,6 @@
|
||||
selectShowClose4()
|
||||
}
|
||||
|
||||
const selectShowRef5 = ref()
|
||||
const selectShow5 = async () => {
|
||||
unref(selectShowRef5).open()
|
||||
}
|
||||
const selectShowClose5 = () => {
|
||||
unref(selectShowRef5).close()
|
||||
}
|
||||
|
||||
//公司
|
||||
const selectShowRef6 = ref()
|
||||
@ -939,30 +896,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
const submitCheck = async (type) => {
|
||||
if (type == 2 && form2.value.remark == '') {
|
||||
uni.showToast({
|
||||
icon: 'error',
|
||||
title: '请填写驳回理由'
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
form2.value.id = contractId.value
|
||||
form2.value.type
|
||||
await check(form2.value)
|
||||
|
||||
uni.showToast({
|
||||
title: '审核成功',
|
||||
icon: 'success',
|
||||
duration: 2000
|
||||
})
|
||||
prePage().$vm.isRefresh = true
|
||||
setTimeout(() => {
|
||||
uni.navigateBack();
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
// 提交跟进
|
||||
const uForm = ref()
|
||||
const submit = () => {
|
||||
|
@ -71,8 +71,8 @@
|
||||
<view class="item-photo-list-item" style="font-size: 0; position: relative;margin-bottom: 60rpx;"
|
||||
:style="{marginRight:(index+1)%3==0?'0rpx':'20rpx'}" v-for="(item, index) in imgFiles" :key="item"
|
||||
@click="replaceImage(item, index)">
|
||||
<image v-if="!isCheck" src="@/static/greyguanbi.png" mode="aspectFit" class="item-photo-list-item-close"
|
||||
@click.stop="deleteItem(item, index)"></image>
|
||||
<image v-if="!isCheck" src="https://sys.znkjfw.com/imgs/crmimages/close.png" mode="aspectFit"
|
||||
class="item-photo-list-item-close" @click.stop="deleteItem(item, index)"></image>
|
||||
<image v-if="!isCheck" :src="item.url" mode="" style="width: 100%; height: 100%"></image>
|
||||
</view>
|
||||
<image src="http://sys.znkjfw.com/imgs/process/uploadzp.png" mode="aspectFill" class="item-photo-list-item"
|
||||
@ -86,8 +86,8 @@
|
||||
<view class="item-photo-list">
|
||||
<view class="item-photo-list-item" style="font-size: 0; position: relative;margin-bottom: 60rpx;"
|
||||
:style="{marginRight:(index+1)%3==0?'0rpx':'20rpx'}" v-for="(item, index) in pdfList" :key="item">
|
||||
<image v-if="!isCheck" src="@/static/greyguanbi.png" mode="aspectFit" class="item-photo-list-item-close"
|
||||
@click.stop="deleteFiles(item, index)"></image>
|
||||
<image v-if="!isCheck" src="https://sys.znkjfw.com/imgs/crmimages/close.png" mode="aspectFit"
|
||||
class="item-photo-list-item-close" @click.stop="deleteFiles(item, index)"></image>
|
||||
<image v-if="!isCheck" src="http://sys.znkjfw.com/imgs/process/pdfIcon.png" mode=""
|
||||
style="width: 100%; height: 100%">
|
||||
</image>
|
||||
|
@ -1,81 +0,0 @@
|
||||
<template>
|
||||
<uv-navbar :fixed="false" @leftClick="$onClickLeft" bgColor="#09b4f1">
|
||||
<template v-slot:left>
|
||||
<uv-icon name="arrow-left" size="19" color="#ffffff"></uv-icon>
|
||||
</template>
|
||||
<template v-slot:center>
|
||||
<text style="color:#ffffff">{{title}}</text>
|
||||
</template>
|
||||
</uv-navbar>
|
||||
<view class="bg-white">
|
||||
<uv-cell-group>
|
||||
<uv-cell icon="http://sys.znkjfw.com/imgs/crmimages/16.png" title="待办事项" label="待办事项消息提现" isLink
|
||||
url="/pages/components/pages/msg/wait" iconStyle="height:70rpx;width:70rpx;margin-right:10rpx">
|
||||
<template v-slot:right-icon>
|
||||
<view class="flex align-center">
|
||||
<uv-badge type="error" max="99" :value="waitCount"></uv-badge>
|
||||
<uv-icon size="30rpx" name="arrow-right"></uv-icon>
|
||||
</view>
|
||||
</template>
|
||||
</uv-cell>
|
||||
<uv-cell icon="http://sys.znkjfw.com/imgs/crmimages/15.png" title="审批管理" label="审批消息提现" isLink
|
||||
url="/pages/components/pages/msg/exam" iconStyle="height:70rpx;width:70rpx;margin-right:10rpx">
|
||||
<template v-slot:right-icon>
|
||||
<view class="flex align-center">
|
||||
<uv-badge type="error" max="99" :value="checkCount"></uv-badge>
|
||||
<uv-icon size="30rpx" name="arrow-right"></uv-icon>
|
||||
</view>
|
||||
</template>
|
||||
</uv-cell>
|
||||
<uv-cell icon="http://sys.znkjfw.com/imgs/crmimages/23.png" title="通知管理" label="系统公告通知" isLink
|
||||
url="/pages/components/pages/mine/list" iconStyle="height:70rpx;width:70rpx;margin-right:10rpx">
|
||||
<template v-slot:right-icon>
|
||||
<view class="flex align-center">
|
||||
<uv-badge type="error" max="99" :value="noticeCount"></uv-badge>
|
||||
<uv-icon size="30rpx" name="arrow-right"></uv-icon>
|
||||
</view>
|
||||
</template>
|
||||
</uv-cell>
|
||||
</uv-cell-group>
|
||||
</view>
|
||||
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
ref,
|
||||
computed
|
||||
} from 'vue'
|
||||
import {
|
||||
useMainStore
|
||||
} from '@/store/store'
|
||||
import {
|
||||
storeToRefs
|
||||
} from 'pinia'
|
||||
import {
|
||||
onLoad,
|
||||
onShow
|
||||
} from '@dcloudio/uni-app'
|
||||
const main = useMainStore()
|
||||
const {
|
||||
indexCount
|
||||
} = storeToRefs(main)
|
||||
const title = ref('消息')
|
||||
const cart = ref([])
|
||||
const uToast = ref()
|
||||
const waitCount = ref(0)
|
||||
const checkCount = ref(0)
|
||||
const noticeCount = ref(0)
|
||||
|
||||
onShow(() => {
|
||||
noticeCount.value = indexCount.value.brieCountVO?.count13 || 0
|
||||
waitCount.value = indexCount.value.followBusinessCount + indexCount.value.followCluesCount + indexCount.value
|
||||
.followCustomerCount
|
||||
checkCount.value = indexCount.value.contractCheckCount + indexCount.value.invoiceCheckCount + indexCount.value
|
||||
.receivablesCheckCount
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
</style>
|
@ -1,23 +0,0 @@
|
||||
@font-face {
|
||||
font-family: "iconfont"; /* Project id 4205200 */
|
||||
src: url('~@/static/iconfont/iconfont.woff2?t=1691643169117') format('woff2'),
|
||||
url('~@/static/iconfont/iconfont.woff?t=1691643169117') format('woff'),
|
||||
url('~@/static/iconfont/iconfont.ttf?t=1691643169117') format('truetype');
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
font-family: "iconfont" !important;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.icon-waimai-:before {
|
||||
content: "\e607";
|
||||
}
|
||||
|
||||
.icon-tangshi:before {
|
||||
content: "\e645";
|
||||
}
|
||||
|
@ -1,270 +0,0 @@
|
||||
|
||||
@font-face {
|
||||
font-family: 'iconfont-yshop';
|
||||
src: url('//at.alicdn.com/t/font_2012069_r7oux4ay0ls.eot');
|
||||
src: url('//at.alicdn.com/t/font_2012069_r7oux4ay0ls.eot?#iefix') format('embedded-opentype'),
|
||||
url('//at.alicdn.com/t/font_2012069_r7oux4ay0ls.woff2') format('woff2'),
|
||||
url('//at.alicdn.com/t/font_2012069_r7oux4ay0ls.woff') format('woff'),
|
||||
url('//at.alicdn.com/t/font_2012069_r7oux4ay0ls.ttf') format('truetype'),
|
||||
url('//at.alicdn.com/t/font_2012069_r7oux4ay0ls.svg#iconfont-yshop') format('svg');
|
||||
|
||||
}
|
||||
|
||||
.iconfont-yshop {
|
||||
font-family: 'iconfont-yshop' !important;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
color: #09b4f1;
|
||||
}
|
||||
.icon-alipay:before {
|
||||
content: '\e60a';
|
||||
}
|
||||
.icon-shop:before {
|
||||
content: '\e664';
|
||||
}
|
||||
.icon-takein:before {
|
||||
content: '\e666';
|
||||
}
|
||||
.icon-takeout:before {
|
||||
content: '\e667';
|
||||
}
|
||||
.icon-location:before {
|
||||
content: '\e633';
|
||||
}
|
||||
.icon-mobile:before {
|
||||
content: '\e602';
|
||||
}
|
||||
.icon-box:before {
|
||||
content: '\e665';
|
||||
}
|
||||
.icon-lamp:before {
|
||||
content: '\e668';
|
||||
}
|
||||
.icon-doorbell:before {
|
||||
content: '\e662';
|
||||
}
|
||||
.icon-daojishi:before {
|
||||
content: '\e625';
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'iconfont';
|
||||
src: url('//at.alicdn.com/t/font_1789197_z1gzlwq7idq.ttf?t=1589441233693') format('truetype');
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
font-family: 'iconfont' !important;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.iconshoucang:before {
|
||||
content: '\e667';
|
||||
}
|
||||
|
||||
.iconshoucangfill:before {
|
||||
content: '\e6c9';
|
||||
}
|
||||
|
||||
.iconjifen:before {
|
||||
content: '\e642';
|
||||
}
|
||||
|
||||
.iconradio-button-off:before {
|
||||
content: '\e688';
|
||||
}
|
||||
|
||||
.iconradio-button-on:before {
|
||||
content: '\e689';
|
||||
}
|
||||
|
||||
.iconhelp:before {
|
||||
content: '\e752';
|
||||
}
|
||||
|
||||
.iconwxpay:before {
|
||||
content: '\e611';
|
||||
}
|
||||
|
||||
.iconbalance:before {
|
||||
content: '\e619';
|
||||
}
|
||||
|
||||
.iconadd-select:before {
|
||||
content: '\e7b0';
|
||||
}
|
||||
|
||||
.iconsami-select:before {
|
||||
content: '\e7b1';
|
||||
}
|
||||
|
||||
.iconmap:before {
|
||||
content: '\e758';
|
||||
}
|
||||
|
||||
.iconsuccess:before {
|
||||
content: '\e767';
|
||||
}
|
||||
|
||||
.iconsuccess-fill:before {
|
||||
content: '\e78d';
|
||||
}
|
||||
|
||||
.iconiconset0136:before {
|
||||
content: '\e623';
|
||||
}
|
||||
|
||||
.iconzan:before {
|
||||
content: '\e640';
|
||||
}
|
||||
|
||||
.iconjifenqiandao:before {
|
||||
content: '\e6a6';
|
||||
}
|
||||
|
||||
.iconshouyeshouye:before {
|
||||
content: '\e606';
|
||||
}
|
||||
|
||||
.icondaohang:before {
|
||||
content: '\e641';
|
||||
}
|
||||
|
||||
.iconwodelianxikefu:before {
|
||||
content: '\e671';
|
||||
}
|
||||
|
||||
.iconwodexinyuan:before {
|
||||
content: '\e675';
|
||||
}
|
||||
|
||||
.iconphone:before {
|
||||
content: '\e6dd';
|
||||
}
|
||||
|
||||
.icondingdan:before {
|
||||
content: '\e645';
|
||||
}
|
||||
|
||||
.iconliwu:before {
|
||||
content: '\e61c';
|
||||
}
|
||||
|
||||
.iconyinpinyinliao:before {
|
||||
content: '\e60d';
|
||||
}
|
||||
|
||||
.iconyinpin:before {
|
||||
content: '\e70b';
|
||||
}
|
||||
|
||||
.iconwaimaixinxi:before {
|
||||
content: '\e685';
|
||||
}
|
||||
|
||||
.iconico:before {
|
||||
content: '\e646';
|
||||
}
|
||||
|
||||
.iconwode:before {
|
||||
content: '\e616';
|
||||
}
|
||||
|
||||
.icongengduofuwu:before {
|
||||
content: '\e607';
|
||||
}
|
||||
|
||||
.iconqucan:before {
|
||||
content: '\e625';
|
||||
}
|
||||
|
||||
.iconyou:before {
|
||||
content: '\e618';
|
||||
}
|
||||
|
||||
.iconshouhuodizhi:before {
|
||||
content: '\e666';
|
||||
}
|
||||
|
||||
.iconshangcheng:before {
|
||||
content: '\e63b';
|
||||
}
|
||||
|
||||
.iconadd:before {
|
||||
content: '\e742';
|
||||
}
|
||||
|
||||
.iconarrow-right:before {
|
||||
content: '\e743';
|
||||
}
|
||||
|
||||
.iconarrow-lift:before {
|
||||
content: '\e744';
|
||||
}
|
||||
|
||||
.iconarrow-up:before {
|
||||
content: '\e745';
|
||||
}
|
||||
|
||||
.iconclose:before {
|
||||
content: '\e747';
|
||||
}
|
||||
|
||||
.iconleftbutton:before {
|
||||
content: '\e755';
|
||||
}
|
||||
|
||||
.iconreduce:before {
|
||||
content: '\e75e';
|
||||
}
|
||||
|
||||
.iconseleted:before {
|
||||
content: '\e763';
|
||||
}
|
||||
|
||||
.iconRightbutton:before {
|
||||
content: '\e765';
|
||||
}
|
||||
|
||||
.iconleftbutton-fill:before {
|
||||
content: '\e782';
|
||||
}
|
||||
|
||||
.iconRightbutton-fill:before {
|
||||
content: '\e78a';
|
||||
}
|
||||
|
||||
.iconarrow-down:before {
|
||||
content: '\e7b2';
|
||||
}
|
||||
|
||||
.iconaixin1:before {
|
||||
content: '\e63c';
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "iconfont"; /* Project id 4205200 */
|
||||
src: url('~@/static/iconfont/iconfont.woff2') format('woff2'),
|
||||
url('~@/static/iconfont/iconfont.woff') format('woff'),
|
||||
url('~@/static/iconfont/iconfont.ttf') format('truetype');
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
font-family: "iconfont" !important;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.icon-waimai-:before {
|
||||
content: "\e607";
|
||||
}
|
||||
|
||||
.icon-tangshi:before {
|
||||
content: "\e645";
|
||||
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 2.6 KiB |
Binary file not shown.
Before Width: | Height: | Size: 2.6 KiB |
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
6
uni.scss
6
uni.scss
@ -112,9 +112,3 @@ $uv-info: #909399;
|
||||
$uv-info-dark: #767a82;
|
||||
$uv-info-disabled: #c4c6c9;
|
||||
$uv-info-light: #f4f4f5;
|
||||
|
||||
|
||||
@import '~@/static/iconfont/iconfont.scss';
|
||||
|
||||
/* uni.scss */
|
||||
// @import 'uview-ui/theme.scss';
|
||||
|
@ -1,8 +0,0 @@
|
||||
## 1.0.2(2023-07-03)
|
||||
1. 优化插槽自定义内容部分
|
||||
2. 增加backToTop方法说明
|
||||
## 1.0.1(2023-05-16)
|
||||
1. 优化组件依赖,修改后无需全局引入,组件导入即可使用
|
||||
2. 优化部分功能
|
||||
## 1.0.0(2023-05-10)
|
||||
uv-back-top 返回顶部
|
@ -1,58 +0,0 @@
|
||||
export default {
|
||||
props: {
|
||||
// 返回顶部的形状,circle-圆形,square-方形
|
||||
mode: {
|
||||
type: String,
|
||||
default: 'circle'
|
||||
},
|
||||
// 自定义图标
|
||||
icon: {
|
||||
type: String,
|
||||
default: 'arrow-upward'
|
||||
},
|
||||
// 提示文字
|
||||
text: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 返回顶部滚动时间
|
||||
duration: {
|
||||
type: [String, Number],
|
||||
default: 100
|
||||
},
|
||||
// 滚动距离
|
||||
scrollTop: {
|
||||
type: [String, Number],
|
||||
default: 0
|
||||
},
|
||||
// 距离顶部多少距离显示,单位px
|
||||
top: {
|
||||
type: [String, Number],
|
||||
default: 400
|
||||
},
|
||||
// 返回顶部按钮到底部的距离,单位px
|
||||
bottom: {
|
||||
type: [String, Number],
|
||||
default: 100
|
||||
},
|
||||
// 返回顶部按钮到右边的距离,单位px
|
||||
right: {
|
||||
type: [String, Number],
|
||||
default: 20
|
||||
},
|
||||
// 层级
|
||||
zIndex: {
|
||||
type: [String, Number],
|
||||
default: 9
|
||||
},
|
||||
// 图标的样式,对象形式
|
||||
iconStyle: {
|
||||
type: Object,
|
||||
default: () => ({
|
||||
color: '#909399',
|
||||
fontSize: '19px'
|
||||
})
|
||||
},
|
||||
...uni.$uv?.props?.backtop
|
||||
}
|
||||
}
|
@ -1,116 +0,0 @@
|
||||
<template>
|
||||
<uv-transition mode="fade" :customStyle="backTopStyle" :show="show">
|
||||
<slot>
|
||||
<view class="uv-back-top" :style="[contentStyle]" @click="backToTop">
|
||||
<uv-icon :name="icon" :custom-style="iconStyle"></uv-icon>
|
||||
<text v-if="text" class="uv-back-top__text">{{text}}</text>
|
||||
</view>
|
||||
</slot>
|
||||
</uv-transition>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import mpMixin from '@/uni_modules/uv-ui-tools/libs/mixin/mpMixin.js'
|
||||
import mixin from '@/uni_modules/uv-ui-tools/libs/mixin/mixin.js'
|
||||
import props from './props.js';
|
||||
// #ifdef APP-NVUE
|
||||
const dom = weex.requireModule('dom')
|
||||
// #endif
|
||||
/**
|
||||
* backTop 返回顶部
|
||||
* @description 本组件一个用于长页面,滑动一定距离后,出现返回顶部按钮,方便快速返回顶部的场景。
|
||||
* @tutorial https://www.uvui.cn/components/backTop.html
|
||||
* @property {String} mode 返回顶部的形状,circle-圆形,square-方形 (默认 'circle' )
|
||||
* @property {String} icon 自定义图标 (默认 'arrow-upward' ) 见官方文档示例
|
||||
* @property {String} text 提示文字
|
||||
* @property {String | Number} duration 返回顶部滚动时间 (默认 100)
|
||||
* @property {String | Number} scrollTop 滚动距离 (默认 0 )
|
||||
* @property {String | Number} top 距离顶部多少距离显示,单位px (默认 400 )
|
||||
* @property {String | Number} bottom 返回顶部按钮到底部的距离,单位px (默认 100 )
|
||||
* @property {String | Number} right 返回顶部按钮到右边的距离,单位px (默认 20 )
|
||||
* @property {String | Number} zIndex 层级 (默认 9 )
|
||||
* @property {Object<Object>} iconStyle 图标的样式,对象形式 (默认 {color: '#909399',fontSize: '19px'})
|
||||
* @property {Object} customStyle 定义需要用到的外部样式
|
||||
*
|
||||
* @example <uv-back-top :scrollTop="scrollTop"></uv-back-top>
|
||||
*/
|
||||
export default {
|
||||
name: 'uv-back-top',
|
||||
emits: ['click'],
|
||||
mixins: [mpMixin, mixin, props],
|
||||
computed: {
|
||||
backTopStyle() {
|
||||
// 动画组件样式
|
||||
const style = {
|
||||
bottom: this.$uv.addUnit(this.bottom),
|
||||
right: this.$uv.addUnit(this.right),
|
||||
width: '40px',
|
||||
height: '40px',
|
||||
position: 'fixed',
|
||||
zIndex: 10,
|
||||
}
|
||||
return style
|
||||
},
|
||||
show() {
|
||||
return this.$uv.getPx(this.scrollTop) > this.$uv.getPx(this.top)
|
||||
},
|
||||
contentStyle() {
|
||||
const style = {}
|
||||
let radius = 0
|
||||
// 是否圆形
|
||||
if (this.mode === 'circle') {
|
||||
radius = '100px'
|
||||
} else {
|
||||
radius = '4px'
|
||||
}
|
||||
// 为了兼容安卓nvue,只能这么分开写
|
||||
style.borderTopLeftRadius = radius
|
||||
style.borderTopRightRadius = radius
|
||||
style.borderBottomLeftRadius = radius
|
||||
style.borderBottomRightRadius = radius
|
||||
return this.$uv.deepMerge(style, this.$uv.addStyle(this.customStyle))
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
backToTop() {
|
||||
// #ifdef APP-NVUE
|
||||
if (!this.$parent.$refs['uv-back-top']) {
|
||||
this.$uv.error(`nvue页面需要给页面最外层元素设置"ref='uv-back-top'`)
|
||||
}
|
||||
dom.scrollToElement(this.$parent.$refs['uv-back-top'], {
|
||||
offset: 0
|
||||
})
|
||||
// #endif
|
||||
|
||||
// #ifndef APP-NVUE
|
||||
uni.pageScrollTo({
|
||||
scrollTop: 0,
|
||||
duration: this.duration
|
||||
});
|
||||
// #endif
|
||||
this.$emit('click')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '@/uni_modules/uv-ui-tools/libs/css/components.scss';
|
||||
$uv-back-top-flex: 1 !default;
|
||||
$uv-back-top-height: 100% !default;
|
||||
$uv-back-top-background-color: #E1E1E1 !default;
|
||||
$uv-back-top-tips-font-size: 12px !default;
|
||||
.uv-back-top {
|
||||
@include flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
flex: $uv-back-top-flex;
|
||||
height: $uv-back-top-height;
|
||||
justify-content: center;
|
||||
background-color: $uv-back-top-background-color;
|
||||
&__tips {
|
||||
font-size: $uv-back-top-tips-font-size;
|
||||
transform: scale(0.8);
|
||||
}
|
||||
}
|
||||
</style>
|
@ -1,89 +0,0 @@
|
||||
{
|
||||
"id": "uv-back-top",
|
||||
"displayName": "uv-back-top 返回顶部 全面兼容小程序、nvue、vue2、vue3等多端",
|
||||
"version": "1.0.2",
|
||||
"description": "返回顶部 组件一个用于长页面,滑动一定距离后,出现返回顶部按钮,方便快速返回顶部的场景。",
|
||||
"keywords": [
|
||||
"uv-back-top",
|
||||
"uvui",
|
||||
"uv-ui",
|
||||
"avatar",
|
||||
"返回顶部"
|
||||
],
|
||||
"repository": "",
|
||||
"engines": {
|
||||
"HBuilderX": "^3.1.0"
|
||||
},
|
||||
"dcloudext": {
|
||||
"type": "component-vue",
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "插件不采集任何数据",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": ""
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": [
|
||||
"uv-ui-tools",
|
||||
"uv-icon",
|
||||
"uv-transition"
|
||||
],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y"
|
||||
},
|
||||
"client": {
|
||||
"Vue": {
|
||||
"vue2": "y",
|
||||
"vue3": "y"
|
||||
},
|
||||
"App": {
|
||||
"app-vue": "y",
|
||||
"app-nvue": "y"
|
||||
},
|
||||
"H5-mobile": {
|
||||
"Safari": "y",
|
||||
"Android Browser": "y",
|
||||
"微信浏览器(Android)": "y",
|
||||
"QQ浏览器(Android)": "y"
|
||||
},
|
||||
"H5-pc": {
|
||||
"Chrome": "y",
|
||||
"IE": "y",
|
||||
"Edge": "y",
|
||||
"Firefox": "y",
|
||||
"Safari": "y"
|
||||
},
|
||||
"小程序": {
|
||||
"微信": "y",
|
||||
"阿里": "y",
|
||||
"百度": "y",
|
||||
"字节跳动": "y",
|
||||
"QQ": "y",
|
||||
"钉钉": "u",
|
||||
"快手": "u",
|
||||
"飞书": "u",
|
||||
"京东": "u"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "u",
|
||||
"联盟": "u"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
## BackTop 返回顶部
|
||||
|
||||
> **组件名:uv-back-top**
|
||||
|
||||
该组件一个用于长页面,滑动一定距离后,出现返回顶部按钮,方便快速返回顶部的场景。
|
||||
|
||||
### <a href="https://www.uvui.cn/components/backTop.html" target="_blank">查看文档</a>
|
||||
|
||||
### [完整示例项目下载 | 关注更多组件](https://ext.dcloud.net.cn/plugin?name=uv-ui)
|
||||
|
||||
#### 如使用过程中有任何问题,或者您对uv-ui有一些好的建议,欢迎加入 uv-ui 交流群:<a href="https://ext.dcloud.net.cn/plugin?id=12287" target="_blank">uv-ui</a>、<a href="https://www.uvui.cn/components/addQQGroup.html" target="_blank">官方QQ群</a>
|
@ -1,32 +0,0 @@
|
||||
## 1.0.13(2023-10-11)
|
||||
1. 优化同类问题:https://gitee.com/climblee/uv-ui/issues/I872VD
|
||||
## 1.0.12(2023-09-22)
|
||||
1. 修复change回调中v-model值不更新的BUG
|
||||
## 1.0.11(2023-09-01)
|
||||
1. 修复点击空隙处无效的问题
|
||||
2. label支持插槽下可点击
|
||||
## 1.0.10(2023-08-27)
|
||||
1. 修复label设置布尔值不生效的BUG
|
||||
## 1.0.9(2023-08-16)
|
||||
1. 解决数据多不换行的BUG
|
||||
## 1.0.8(2023-07-13)
|
||||
1. 修复 uv-checkbox设置value属性不生效的BUG
|
||||
## 1.0.7(2023-07-05)
|
||||
修复vue3模式下,动态修改v-model绑定的值无效的BUG
|
||||
## 1.0.6(2023-06-29)
|
||||
1. 增加label插槽,与radio保持一致
|
||||
2. 优化文档
|
||||
## 1.0.5(2023-06-12)
|
||||
1. 修复1.0.4改出的问题
|
||||
## 1.0.4(2023-06-08)
|
||||
1. 复选框修复全局设置不生效的BUG
|
||||
## 1.0.3(2023-06-06)
|
||||
1. uv-checkbox-group 兼容自定义样式customStyle,方便通过样式调整整体位置等;
|
||||
2. .uv-checkbox-group--row增加flex-wrap: wrap;允许换行
|
||||
## 1.0.2(2023-05-30)
|
||||
1. 修复error报错的BUG
|
||||
## 1.0.1(2023-05-16)
|
||||
1. 优化组件依赖,修改后无需全局引入,组件导入即可使用
|
||||
2. 优化部分功能
|
||||
## 1.0.0(2023-05-10)
|
||||
uv-checkbox 复选框
|
@ -1,84 +0,0 @@
|
||||
export default {
|
||||
props: {
|
||||
// 绑定的值
|
||||
value: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
modelValue: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
// 标识符
|
||||
name: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 形状,circle-圆形,square-方形
|
||||
shape: {
|
||||
type: String,
|
||||
default: 'square'
|
||||
},
|
||||
// 是否禁用全部checkbox
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 选中状态下的颜色,如设置此值,将会覆盖parent的activeColor值
|
||||
activeColor: {
|
||||
type: String,
|
||||
default: '#2979ff'
|
||||
},
|
||||
// 未选中的颜色
|
||||
inactiveColor: {
|
||||
type: String,
|
||||
default: '#c8c9cc'
|
||||
},
|
||||
// 整个组件的尺寸,默认px
|
||||
size: {
|
||||
type: [String, Number],
|
||||
default: 18
|
||||
},
|
||||
// 布局方式,row-横向,column-纵向
|
||||
placement: {
|
||||
type: String,
|
||||
default: 'row'
|
||||
},
|
||||
// label的字体大小,px单位
|
||||
labelSize: {
|
||||
type: [String, Number],
|
||||
default: 14
|
||||
},
|
||||
// label的字体颜色
|
||||
labelColor: {
|
||||
type: [String],
|
||||
default: '#303133'
|
||||
},
|
||||
// 是否禁止点击文本操作
|
||||
labelDisabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 图标颜色
|
||||
iconColor: {
|
||||
type: String,
|
||||
default: '#fff'
|
||||
},
|
||||
// 图标的大小,单位px
|
||||
iconSize: {
|
||||
type: [String, Number],
|
||||
default: 12
|
||||
},
|
||||
// 勾选图标的对齐方式,left-左边,right-右边
|
||||
iconPlacement: {
|
||||
type: String,
|
||||
default: 'left'
|
||||
},
|
||||
// 竖向配列时,是否显示下划线
|
||||
borderBottom: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
...uni.$uv?.props?.checkboxGroup
|
||||
}
|
||||
}
|
@ -1,119 +0,0 @@
|
||||
<template>
|
||||
<view
|
||||
class="uv-checkbox-group"
|
||||
:class="bemClass"
|
||||
:style="[$uv.addStyle(this.customStyle)]"
|
||||
>
|
||||
<slot></slot>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import mpMixin from '@/uni_modules/uv-ui-tools/libs/mixin/mpMixin.js'
|
||||
import mixin from '@/uni_modules/uv-ui-tools/libs/mixin/mixin.js'
|
||||
import props from './props.js';
|
||||
/**
|
||||
* checkboxGroup 复选框组
|
||||
* @description 复选框组件一般用于需要多个选择的场景,该组件功能完整,使用方便
|
||||
* @tutorial https://www.uvui.cn/components/checkbox.html
|
||||
* @property {String} name 标识符
|
||||
* @property {Array} value 绑定的值
|
||||
* @property {String} shape 形状,circle-圆形,square-方形 (默认 'square' )
|
||||
* @property {Boolean} disabled 是否禁用全部checkbox (默认 false )
|
||||
* @property {String} activeColor 选中状态下的颜色,如设置此值,将会覆盖parent的activeColor值 (默认 '#2979ff' )
|
||||
* @property {String} inactiveColor 未选中的颜色 (默认 '#c8c9cc' )
|
||||
* @property {String | Number} size 整个组件的尺寸 单位px (默认 18 )
|
||||
* @property {String} placement 布局方式,row-横向,column-纵向 (默认 'row' )
|
||||
* @property {String | Number} labelSize label的字体大小,px单位 (默认 14 )
|
||||
* @property {String} labelColor label的字体颜色 (默认 '#303133' )
|
||||
* @property {Boolean} labelDisabled 是否禁止点击文本操作 (默认 false )
|
||||
* @property {String} iconColor 图标颜色 (默认 '#ffffff' )
|
||||
* @property {String | Number} iconSize 图标的大小,单位px (默认 12 )
|
||||
* @property {String} iconPlacement 勾选图标的对齐方式,left-左边,right-右边 (默认 'left' )
|
||||
* @property {Boolean} borderBottom placement为row时,是否显示下边框 (默认 false )
|
||||
* @event {Function} change 任一个checkbox状态发生变化时触发,回调为一个对象
|
||||
* @event {Function} input 修改通过v-model绑定的值时触发,回调为一个对象
|
||||
* @example <uv-checkbox-group></uv-checkbox-group>
|
||||
*/
|
||||
export default {
|
||||
name: 'uv-checkbox-group',
|
||||
mixins: [mpMixin, mixin, props],
|
||||
computed: {
|
||||
// 这里computed的变量,都是子组件uv-checkbox需要用到的,由于头条小程序的兼容性差异,子组件无法实时监听父组件参数的变化
|
||||
// 所以需要手动通知子组件,这里返回一个parentData变量,供watch监听,在其中去通知每一个子组件重新从父组件(uv-checkbox-group)
|
||||
// 拉取父组件新的变化后的参数
|
||||
parentData() {
|
||||
let value = [];
|
||||
if(this.value.length) {
|
||||
value = this.value;
|
||||
} else if (this.modelValue.length){
|
||||
value = this.modelValue;
|
||||
}
|
||||
return [value, this.disabled, this.inactiveColor, this.activeColor, this.size, this.labelDisabled, this.shape,
|
||||
this.iconSize, this.borderBottom, this.placement, this.labelSize, this.labelColor]
|
||||
},
|
||||
bemClass() {
|
||||
// this.bem为一个computed变量,在mixin中
|
||||
return this.bem('checkbox-group', ['placement'])
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
// 当父组件需要子组件需要共享的参数发生了变化,手动通知子组件
|
||||
parentData() {
|
||||
if (this.children.length) {
|
||||
this.children.map(child => {
|
||||
// 判断子组件(uv-checkbox)如果有init方法的话,就就执行(执行的结果是子组件重新从父组件拉取了最新的值)
|
||||
typeof(child.init) === 'function' && child.init()
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.children = []
|
||||
},
|
||||
methods: {
|
||||
// 将其他的checkbox设置为未选中的状态
|
||||
unCheckedOther(childInstance) {
|
||||
const values = []
|
||||
this.children.map(child => {
|
||||
// 将被选中的checkbox,放到数组中返回
|
||||
if (child.isChecked) {
|
||||
values.push(child.name)
|
||||
}
|
||||
})
|
||||
// 修改通过v-model绑定的值
|
||||
// #ifdef VUE2
|
||||
this.$emit('input', values)
|
||||
// #endif
|
||||
// #ifdef VUE3
|
||||
this.$emit('update:modelValue',values)
|
||||
// #endif
|
||||
// 发出事件
|
||||
this.$emit('change', values)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '@/uni_modules/uv-ui-tools/libs/css/components.scss';
|
||||
@import '@/uni_modules/uv-ui-tools/libs/css/color.scss';
|
||||
|
||||
.uv-checkbox-group {
|
||||
flex: 1;
|
||||
|
||||
&--row {
|
||||
@include flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
&--column {
|
||||
@include flex(column);
|
||||
}
|
||||
}
|
||||
</style>
|
@ -1,70 +0,0 @@
|
||||
export default {
|
||||
props: {
|
||||
// checkbox的名称
|
||||
name: {
|
||||
type: [String, Number, Boolean],
|
||||
default: ''
|
||||
},
|
||||
// 形状,square为方形,circle为圆型
|
||||
shape: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 整体的大小
|
||||
size: {
|
||||
type: [String, Number],
|
||||
default: ''
|
||||
},
|
||||
// 是否默认选中
|
||||
checked: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 是否禁用
|
||||
disabled: {
|
||||
type: [String, Boolean],
|
||||
default: ''
|
||||
},
|
||||
// 选中状态下的颜色,如设置此值,将会覆盖parent的activeColor值
|
||||
activeColor: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 未选中的颜色
|
||||
inactiveColor: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 图标的大小,单位px
|
||||
iconSize: {
|
||||
type: [String, Number],
|
||||
default: ''
|
||||
},
|
||||
// 图标颜色
|
||||
iconColor: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// label提示文字,因为nvue下,直接slot进来的文字,由于特殊的结构,无法修改样式
|
||||
label: {
|
||||
type: [String, Number, Boolean],
|
||||
default: ''
|
||||
},
|
||||
// label的字体大小,px单位
|
||||
labelSize: {
|
||||
type: [String, Number],
|
||||
default: ''
|
||||
},
|
||||
// label的颜色
|
||||
labelColor: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 是否禁止点击提示语选中复选框
|
||||
labelDisabled: {
|
||||
type: [String, Boolean],
|
||||
default: ''
|
||||
},
|
||||
...uni.$uv?.props?.checkbox
|
||||
}
|
||||
}
|
@ -1,369 +0,0 @@
|
||||
<template>
|
||||
<view
|
||||
class="uv-checkbox"
|
||||
:style="[checkboxStyle]"
|
||||
@tap.stop="wrapperClickHandler"
|
||||
:class="[`uv-checkbox-label--${parentData.iconPlacement}`, parentData.borderBottom && parentData.placement === 'column' && 'uv-border-bottom']"
|
||||
>
|
||||
<view
|
||||
class="uv-checkbox__icon-wrap"
|
||||
@tap.stop="iconClickHandler"
|
||||
:class="iconClasses"
|
||||
:style="[iconWrapStyle]"
|
||||
>
|
||||
<slot name="icon">
|
||||
<uv-icon
|
||||
class="uv-checkbox__icon-wrap__icon"
|
||||
name="checkbox-mark"
|
||||
:size="elIconSize"
|
||||
:color="elIconColor"
|
||||
/>
|
||||
</slot>
|
||||
</view>
|
||||
<view
|
||||
class="uv-checkbox__label-wrap"
|
||||
@tap.stop="labelClickHandler">
|
||||
<slot>
|
||||
<text
|
||||
:style="{
|
||||
color: elDisabled ? elInactiveColor : elLabelColor,
|
||||
fontSize: elLabelSize,
|
||||
lineHeight: elLabelSize
|
||||
}"
|
||||
>{{label}}</text>
|
||||
</slot>
|
||||
</view>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import mpMixin from '@/uni_modules/uv-ui-tools/libs/mixin/mpMixin.js'
|
||||
import mixin from '@/uni_modules/uv-ui-tools/libs/mixin/mixin.js'
|
||||
import props from './props.js';
|
||||
/**
|
||||
* checkbox 复选框
|
||||
* @description 复选框组件一般用于需要多个选择的场景,该组件功能完整,使用方便
|
||||
* @tutorial https://www.uvui.cn/components/checkbox.html
|
||||
* @property {String | Number | Boolean} name checkbox组件的标示符
|
||||
* @property {String} shape 形状,square为方形,circle为圆型
|
||||
* @property {String | Number} size 整体的大小
|
||||
* @property {Boolean} checked 是否默认选中
|
||||
* @property {String | Boolean} disabled 是否禁用
|
||||
* @property {String} activeColor 选中状态下的颜色,如设置此值,将会覆盖parent的activeColor值
|
||||
* @property {String} inactiveColor 未选中的颜色
|
||||
* @property {String | Number} iconSize 图标的大小,单位px
|
||||
* @property {String} iconColor 图标颜色
|
||||
* @property {String | Number} label label提示文字,因为nvue下,直接slot进来的文字,由于特殊的结构,无法修改样式
|
||||
* @property {String} labelColor label的颜色
|
||||
* @property {String | Number} labelSize label的字体大小,px单位
|
||||
* @property {String | Boolean} labelDisabled 是否禁止点击提示语选中复选框
|
||||
* @property {Object} customStyle 定义需要用到的外部样式
|
||||
*
|
||||
* @event {Function} change 任一个checkbox状态发生变化时触发,回调为一个对象
|
||||
* @example <uv-checkbox v-model="checked" :disabled="false">天涯</uv-checkbox>
|
||||
*/
|
||||
export default {
|
||||
name: "uv-checkbox",
|
||||
mixins: [mpMixin, mixin, props],
|
||||
data() {
|
||||
return {
|
||||
isChecked: false,
|
||||
// 父组件的默认值,因为头条小程序不支持在computed中使用this.parent.shape的形式
|
||||
// 故只能使用如此方法
|
||||
parentData: {
|
||||
iconSize: 12,
|
||||
labelDisabled: null,
|
||||
disabled: null,
|
||||
shape: 'square',
|
||||
activeColor: null,
|
||||
inactiveColor: null,
|
||||
size: 18,
|
||||
value: null,
|
||||
modelValue: null,
|
||||
iconColor: null,
|
||||
placement: 'row',
|
||||
borderBottom: false,
|
||||
iconPlacement: 'left',
|
||||
labelSize: 14,
|
||||
labelColor: '#303133'
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
// 是否禁用,如果父组件uv-raios-group禁用的话,将会忽略子组件的配置
|
||||
elDisabled() {
|
||||
return this.disabled !== '' ? this.disabled : this.parentData.disabled !== null ? this.parentData.disabled : false;
|
||||
},
|
||||
// 是否禁用label点击
|
||||
elLabelDisabled() {
|
||||
return this.labelDisabled !== '' ? this.labelDisabled : this.parentData.labelDisabled !== null ? this.parentData.labelDisabled :
|
||||
false;
|
||||
},
|
||||
// 组件尺寸,对应size的值,默认值为21px
|
||||
elSize() {
|
||||
return this.size ? this.size : (this.parentData.size ? this.parentData.size : 21);
|
||||
},
|
||||
// 组件的勾选图标的尺寸,默认12px
|
||||
elIconSize() {
|
||||
return this.iconSize ? this.iconSize : (this.parentData.iconSize ? this.parentData.iconSize : 12);
|
||||
},
|
||||
// 组件选中激活时的颜色
|
||||
elActiveColor() {
|
||||
return this.activeColor ? this.activeColor : (this.parentData.activeColor ? this.parentData.activeColor : '#2979ff');
|
||||
},
|
||||
// 组件选未中激活时的颜色
|
||||
elInactiveColor() {
|
||||
return this.inactiveColor ? this.inactiveColor : (this.parentData.inactiveColor ? this.parentData.inactiveColor :
|
||||
'#c8c9cc');
|
||||
},
|
||||
// label的颜色
|
||||
elLabelColor() {
|
||||
return this.labelColor ? this.labelColor : (this.parentData.labelColor ? this.parentData.labelColor : '#606266')
|
||||
},
|
||||
// 组件的形状
|
||||
elShape() {
|
||||
return this.shape ? this.shape : (this.parentData.shape ? this.parentData.shape : 'circle');
|
||||
},
|
||||
// label大小
|
||||
elLabelSize() {
|
||||
return this.$uv.addUnit(this.labelSize ? this.labelSize : (this.parentData.labelSize ? this.parentData.labelSize :
|
||||
'15'))
|
||||
},
|
||||
elIconColor() {
|
||||
const iconColor = this.iconColor ? this.iconColor : (this.parentData.iconColor ? this.parentData.iconColor :
|
||||
'#ffffff');
|
||||
// 图标的颜色
|
||||
if (this.elDisabled) {
|
||||
// disabled状态下,已勾选的checkbox图标改为elInactiveColor
|
||||
return this.isChecked ? this.elInactiveColor : 'transparent'
|
||||
} else {
|
||||
return this.isChecked ? iconColor : 'transparent'
|
||||
}
|
||||
},
|
||||
iconClasses() {
|
||||
let classes = []
|
||||
// 组件的形状
|
||||
classes.push('uv-checkbox__icon-wrap--' + this.elShape)
|
||||
if (this.elDisabled) {
|
||||
classes.push('uv-checkbox__icon-wrap--disabled')
|
||||
}
|
||||
if (this.isChecked && this.elDisabled) {
|
||||
classes.push('uv-checkbox__icon-wrap--disabled--checked')
|
||||
}
|
||||
// 支付宝,头条小程序无法动态绑定一个数组类名,否则解析出来的结果会带有",",而导致失效
|
||||
// #ifdef MP-ALIPAY || MP-TOUTIAO
|
||||
classes = classes.join(' ')
|
||||
// #endif
|
||||
return classes
|
||||
},
|
||||
iconWrapStyle() {
|
||||
// checkbox的整体样式
|
||||
const style = {}
|
||||
style.backgroundColor = this.isChecked && !this.elDisabled ? this.elActiveColor : '#ffffff'
|
||||
style.borderColor = this.isChecked && !this.elDisabled ? this.elActiveColor : this.elInactiveColor
|
||||
style.width = this.$uv.addUnit(this.elSize)
|
||||
style.height = this.$uv.addUnit(this.elSize)
|
||||
// 如果是图标在右边的话,移除它的右边距
|
||||
if (this.parentData.iconPlacement === 'right') {
|
||||
style.marginRight = 0
|
||||
}
|
||||
return style
|
||||
},
|
||||
checkboxStyle() {
|
||||
const style = {}
|
||||
if (this.parentData.borderBottom && this.parentData.placement === 'row') {
|
||||
this.$uv.error('检测到您将borderBottom设置为true,需要同时将uv-checkbox-group的placement设置为column才有效')
|
||||
}
|
||||
// 当父组件设置了显示下边框并且排列形式为纵向时,给内容和边框之间加上一定间隔
|
||||
if (this.parentData.borderBottom && this.parentData.placement === 'column') {
|
||||
style.paddingBottom = '8px'
|
||||
}
|
||||
return this.$uv.deepMerge(style, this.$uv.addStyle(this.customStyle))
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.init()
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
// 支付宝小程序不支持provide/inject,所以使用这个方法获取整个父组件,在created定义,避免循环引用
|
||||
this.updateParentData()
|
||||
if (!this.parent) {
|
||||
this.$uv.error('uv-checkbox必须搭配uv-checkbox-group组件使用')
|
||||
}
|
||||
this.$nextTick(()=>{
|
||||
let parentValue = [];
|
||||
if(this.parentData.value.length) {
|
||||
parentValue = this.parentData.value;
|
||||
} else if (this.parentData.modelValue.length){
|
||||
parentValue = this.parentData.modelValue;
|
||||
}
|
||||
// 设置初始化时,是否默认选中的状态,父组件uv-checkbox-group的value可能是array,所以额外判断
|
||||
if (this.checked) {
|
||||
this.isChecked = true
|
||||
} else if (this.$uv.test.array(parentValue)) {
|
||||
// 查找数组是是否存在this.name元素值
|
||||
this.isChecked = parentValue.some(item => {
|
||||
return item === this.name
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
updateParentData() {
|
||||
this.getParentData('uv-checkbox-group')
|
||||
},
|
||||
// 横向两端排列时,点击组件即可触发选中事件
|
||||
wrapperClickHandler(e) {
|
||||
this.parentData.iconPlacement === 'right' && this.iconClickHandler(e)
|
||||
},
|
||||
// 点击图标
|
||||
iconClickHandler(e) {
|
||||
this.preventEvent(e)
|
||||
// 如果整体被禁用,不允许被点击
|
||||
if (!this.elDisabled) {
|
||||
this.setRadioCheckedStatus()
|
||||
}
|
||||
},
|
||||
// 点击label
|
||||
labelClickHandler(e) {
|
||||
this.preventEvent(e)
|
||||
// 如果按钮整体被禁用或者label被禁用,则不允许点击文字修改状态
|
||||
if (!this.elLabelDisabled && !this.elDisabled) {
|
||||
this.setRadioCheckedStatus()
|
||||
}
|
||||
},
|
||||
emitEvent() {
|
||||
this.$emit('change', this.isChecked)
|
||||
// 尝试调用uv-form的验证方法,进行一定延迟,否则微信小程序更新可能会不及时
|
||||
this.$nextTick(() => {
|
||||
this.$uv.formValidate(this, 'change')
|
||||
})
|
||||
},
|
||||
// 改变组件选中状态
|
||||
// 这里的改变的依据是,更改本组件的checked值为true,同时通过父组件遍历所有uv-checkbox实例
|
||||
// 将本组件外的其他uv-checkbox的checked都设置为false(都被取消选中状态),因而只剩下一个为选中状态
|
||||
setRadioCheckedStatus() {
|
||||
// 将本组件标记为与原来相反的状态
|
||||
this.isChecked = !this.isChecked
|
||||
this.emitEvent()
|
||||
typeof this.parent.unCheckedOther === 'function' && this.parent.unCheckedOther(this)
|
||||
}
|
||||
},
|
||||
watch:{
|
||||
checked(){
|
||||
this.isChecked = this.checked
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
$show-border: 1;
|
||||
$show-border-bottom: 1;
|
||||
@import '@/uni_modules/uv-ui-tools/libs/css/variable.scss';
|
||||
@import '@/uni_modules/uv-ui-tools/libs/css/components.scss';
|
||||
@import '@/uni_modules/uv-ui-tools/libs/css/color.scss';
|
||||
$uv-checkbox-label-wrap-padding-right:6px !default;
|
||||
$uv-checkbox-icon-wrap-font-size:6px !default;
|
||||
$uv-checkbox-icon-wrap-border-width:1px !default;
|
||||
$uv-checkbox-icon-wrap-border-color:#c8c9cc !default;
|
||||
$uv-checkbox-icon-wrap-icon-line-height:0 !default;
|
||||
$uv-checkbox-icon-wrap-circle-border-radius:100% !default;
|
||||
$uv-checkbox-icon-wrap-square-border-radius:3px !default;
|
||||
$uv-checkbox-icon-wrap-checked-color:#fff !default;
|
||||
$uv-checkbox-icon-wrap-checked-background-color:red !default;
|
||||
$uv-checkbox-icon-wrap-checked-border-color:#2979ff !default;
|
||||
$uv-checkbox-icon-wrap-disabled-background-color:#ebedf0 !default;
|
||||
$uv-checkbox-icon-wrap-disabled-checked-color:#c8c9cc !default;
|
||||
$uv-checkbox-label-margin-left:5px !default;
|
||||
$uv-checkbox-label-margin-right:12px !default;
|
||||
$uv-checkbox-label-color:$uv-content-color !default;
|
||||
$uv-checkbox-label-font-size:15px !default;
|
||||
$uv-checkbox-label-disabled-color:#c8c9cc !default;
|
||||
|
||||
.uv-checkbox {
|
||||
/* #ifndef APP-NVUE */
|
||||
@include flex(row);
|
||||
/* #endif */
|
||||
overflow: hidden;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
|
||||
&-label--left {
|
||||
flex-direction: row
|
||||
}
|
||||
|
||||
&-label--right {
|
||||
flex-direction: row-reverse;
|
||||
justify-content: space-between
|
||||
}
|
||||
|
||||
&__icon-wrap {
|
||||
/* #ifndef APP-NVUE */
|
||||
box-sizing: border-box;
|
||||
// nvue下,border-color过渡有问题
|
||||
transition-property: border-color, background-color, color;
|
||||
transition-duration: 0.2s;
|
||||
/* #endif */
|
||||
color: $uv-content-color;
|
||||
@include flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: transparent;
|
||||
text-align: center;
|
||||
font-size: $uv-checkbox-icon-wrap-font-size;
|
||||
border-width: $uv-checkbox-icon-wrap-border-width;
|
||||
border-color: $uv-checkbox-icon-wrap-border-color;
|
||||
border-style: solid;
|
||||
|
||||
/* #ifdef MP-TOUTIAO */
|
||||
// 头条小程序兼容性问题,需要设置行高为0,否则图标偏下
|
||||
&__icon {
|
||||
line-height: $uv-checkbox-icon-wrap-icon-line-height;
|
||||
}
|
||||
|
||||
/* #endif */
|
||||
|
||||
&--circle {
|
||||
border-radius: $uv-checkbox-icon-wrap-circle-border-radius;
|
||||
}
|
||||
|
||||
&--square {
|
||||
border-radius: $uv-checkbox-icon-wrap-square-border-radius;
|
||||
}
|
||||
|
||||
&--checked {
|
||||
color: $uv-checkbox-icon-wrap-checked-color;
|
||||
background-color: $uv-checkbox-icon-wrap-checked-background-color;
|
||||
border-color: $uv-checkbox-icon-wrap-checked-border-color;
|
||||
}
|
||||
|
||||
&--disabled {
|
||||
background-color: $uv-checkbox-icon-wrap-disabled-background-color !important;
|
||||
}
|
||||
|
||||
&--disabled--checked {
|
||||
color: $uv-checkbox-icon-wrap-disabled-checked-color !important;
|
||||
}
|
||||
}
|
||||
|
||||
&__label {
|
||||
/* #ifndef APP-NVUE */
|
||||
word-wrap: break-word;
|
||||
/* #endif */
|
||||
margin-left: $uv-checkbox-label-margin-left;
|
||||
margin-right: $uv-checkbox-label-margin-right;
|
||||
color: $uv-checkbox-label-color;
|
||||
font-size: $uv-checkbox-label-font-size;
|
||||
|
||||
&--disabled {
|
||||
color: $uv-checkbox-label-disabled-color;
|
||||
}
|
||||
}
|
||||
|
||||
&__label-wrap {
|
||||
padding-left: $uv-checkbox-label-wrap-padding-right;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -1,88 +0,0 @@
|
||||
{
|
||||
"id": "uv-checkbox",
|
||||
"displayName": "uv-checkbox 复选框 全面兼容vue3+2、app、h5、小程序等多端",
|
||||
"version": "1.0.13",
|
||||
"description": "复选框组件一般用于需要多个选择的场景,该组件功能完整,使用方便。",
|
||||
"keywords": [
|
||||
"uv-checkbox",
|
||||
"uvui",
|
||||
"uv-ui",
|
||||
"checkbox",
|
||||
"复选框"
|
||||
],
|
||||
"repository": "",
|
||||
"engines": {
|
||||
"HBuilderX": "^3.1.0"
|
||||
},
|
||||
"dcloudext": {
|
||||
"type": "component-vue",
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "插件不采集任何数据",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": ""
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": [
|
||||
"uv-ui-tools",
|
||||
"uv-icon"
|
||||
],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y"
|
||||
},
|
||||
"client": {
|
||||
"Vue": {
|
||||
"vue2": "y",
|
||||
"vue3": "y"
|
||||
},
|
||||
"App": {
|
||||
"app-vue": "y",
|
||||
"app-nvue": "y"
|
||||
},
|
||||
"H5-mobile": {
|
||||
"Safari": "y",
|
||||
"Android Browser": "y",
|
||||
"微信浏览器(Android)": "y",
|
||||
"QQ浏览器(Android)": "y"
|
||||
},
|
||||
"H5-pc": {
|
||||
"Chrome": "y",
|
||||
"IE": "y",
|
||||
"Edge": "y",
|
||||
"Firefox": "y",
|
||||
"Safari": "y"
|
||||
},
|
||||
"小程序": {
|
||||
"微信": "y",
|
||||
"阿里": "y",
|
||||
"百度": "y",
|
||||
"字节跳动": "y",
|
||||
"QQ": "y",
|
||||
"钉钉": "u",
|
||||
"快手": "u",
|
||||
"飞书": "u",
|
||||
"京东": "u"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "u",
|
||||
"联盟": "u"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
## Checkbox 复选框
|
||||
|
||||
> **组件名:uv-checkbox**
|
||||
|
||||
复选框组件一般用于需要多个选择的场景,该组件功能完整,使用方便。可配合 `uv-form` 组件进行表单验证等场景使用。
|
||||
|
||||
# <a href="https://www.uvui.cn/components/checkbox.html" target="_blank">查看文档</a>
|
||||
|
||||
## [下载完整示例项目](https://ext.dcloud.net.cn/plugin?name=uv-ui) <small>(请不要 下载插件ZIP)</small>
|
||||
|
||||
### [更多插件,请关注uv-ui组件库](https://ext.dcloud.net.cn/plugin?name=uv-ui)
|
||||
|
||||
<a href="https://ext.dcloud.net.cn/plugin?name=uv-ui" target="_blank">
|
||||
|
||||

|
||||
|
||||
</a>
|
||||
|
||||
#### 如使用过程中有任何问题反馈,或者您对uv-ui有一些好的建议,欢迎加入uv-ui官方交流群:<a href="https://www.uvui.cn/components/addQQGroup.html" target="_blank">官方QQ群</a>
|
@ -1,5 +0,0 @@
|
||||
## 1.0.1(2023-05-16)
|
||||
1. 优化组件依赖,修改后无需全局引入,组件导入即可使用
|
||||
2. 优化部分功能
|
||||
## 1.0.0(2023-05-10)
|
||||
uv-no-network 无网络提示
|
File diff suppressed because one or more lines are too long
@ -1,222 +0,0 @@
|
||||
<template>
|
||||
<uv-overlay
|
||||
:show="!isConnected"
|
||||
:zIndex="zIndex"
|
||||
@touchmove.stop.prevent="noop"
|
||||
:customStyle="{
|
||||
backgroundColor: '#fff',
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
}"
|
||||
>
|
||||
<view
|
||||
class="uv-no-network"
|
||||
>
|
||||
<uv-icon
|
||||
:name="image"
|
||||
size="150"
|
||||
imgMode="widthFit"
|
||||
class="uv-no-network__error-icon"
|
||||
></uv-icon>
|
||||
<text class="uv-no-network__tips">{{tips}}</text>
|
||||
<!-- 只有APP平台,才能跳转设置页,因为需要调用plus环境 -->
|
||||
<!-- #ifdef APP-PLUS -->
|
||||
<view class="uv-no-network__app">
|
||||
<text class="uv-no-network__app__setting">请检查网络,或前往</text>
|
||||
<text
|
||||
class="uv-no-network__app__to-setting"
|
||||
@tap="openSettings"
|
||||
>设置</text>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
<view class="uv-no-network__retry">
|
||||
<uv-button
|
||||
size="mini"
|
||||
text="重试"
|
||||
type="primary"
|
||||
plain
|
||||
@click="retry"
|
||||
></uv-button>
|
||||
</view>
|
||||
</view>
|
||||
</uv-overlay>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import mpMixin from '@/uni_modules/uv-ui-tools/libs/mixin/mpMixin.js'
|
||||
import mixin from '@/uni_modules/uv-ui-tools/libs/mixin/mixin.js'
|
||||
import props from './props.js';
|
||||
|
||||
/**
|
||||
* noNetwork 无网络提示
|
||||
* @description 该组件无需任何配置,引入即可,内部自动处理所有功能和事件。
|
||||
* @tutorial https://www.uvui.cn/components/noNetwork.html
|
||||
* @property {String} tips 没有网络时的提示语 (默认:'哎呀,网络信号丢失' )
|
||||
* @property {String | Number} zIndex 组件的z-index值
|
||||
* @property {String} image 无网络的图片提示,可用的src地址或base64图片
|
||||
* @event {Function} retry 用户点击页面的"重试"按钮时触发
|
||||
* @example <uv-no-network></uv-no-network>
|
||||
*/
|
||||
export default {
|
||||
name: "uv-no-network",
|
||||
mixins: [mpMixin, mixin, props],
|
||||
data() {
|
||||
return {
|
||||
isConnected: true, // 是否有网络连接
|
||||
networkType: "none", // 网络类型
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.isIOS = (uni.getSystemInfoSync().platform === 'ios')
|
||||
uni.onNetworkStatusChange((res) => {
|
||||
this.isConnected = res.isConnected
|
||||
this.networkType = res.networkType
|
||||
this.emitEvent(this.networkType)
|
||||
})
|
||||
uni.getNetworkType({
|
||||
success: (res) => {
|
||||
this.networkType = res.networkType
|
||||
this.emitEvent(this.networkType)
|
||||
if (res.networkType == 'none') {
|
||||
this.isConnected = false
|
||||
} else {
|
||||
this.isConnected = true
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
retry() {
|
||||
// 重新检查网络
|
||||
uni.getNetworkType({
|
||||
success: (res) => {
|
||||
this.networkType = res.networkType
|
||||
this.emitEvent(this.networkType)
|
||||
if (res.networkType == 'none') {
|
||||
this.$uv.toast('无网络连接')
|
||||
this.isConnected = false
|
||||
} else {
|
||||
this.$uv.toast('网络已连接')
|
||||
this.isConnected = true
|
||||
}
|
||||
}
|
||||
})
|
||||
this.$emit('retry')
|
||||
},
|
||||
// 发出事件给父组件
|
||||
emitEvent(networkType) {
|
||||
this.$emit(networkType === 'none' ? 'disconnected' : 'connected')
|
||||
},
|
||||
async openSettings() {
|
||||
if (this.networkType == "none") {
|
||||
this.openSystemSettings()
|
||||
return
|
||||
}
|
||||
},
|
||||
openAppSettings() {
|
||||
this.gotoAppSetting()
|
||||
},
|
||||
openSystemSettings() {
|
||||
// 以下方法来自5+范畴,如需深究,请自行查阅相关文档
|
||||
// https://ask.dcloud.net.cn/docs/
|
||||
if (this.isIOS) {
|
||||
this.gotoiOSSetting()
|
||||
} else {
|
||||
this.gotoAndroidSetting()
|
||||
}
|
||||
},
|
||||
network() {
|
||||
var result = null
|
||||
var cellularData = plus.ios.newObject("CTCellularData")
|
||||
var state = cellularData.plusGetAttribute("restrictedState")
|
||||
if (state == 0) {
|
||||
result = null
|
||||
} else if (state == 2) {
|
||||
result = 1
|
||||
} else if (state == 1) {
|
||||
result = 2
|
||||
}
|
||||
plus.ios.deleteObject(cellularData)
|
||||
return result
|
||||
},
|
||||
gotoAppSetting() {
|
||||
if (this.isIOS) {
|
||||
var UIApplication = plus.ios.import("UIApplication")
|
||||
var application2 = UIApplication.sharedApplication()
|
||||
var NSURL2 = plus.ios.import("NSURL")
|
||||
var setting2 = NSURL2.URLWithString("app-settings:")
|
||||
application2.openURL(setting2)
|
||||
plus.ios.deleteObject(setting2)
|
||||
plus.ios.deleteObject(NSURL2)
|
||||
plus.ios.deleteObject(application2)
|
||||
} else {
|
||||
var Intent = plus.android.importClass("android.content.Intent")
|
||||
var Settings = plus.android.importClass("android.provider.Settings")
|
||||
var Uri = plus.android.importClass("android.net.Uri")
|
||||
var mainActivity = plus.android.runtimeMainActivity()
|
||||
var intent = new Intent()
|
||||
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
|
||||
var uri = Uri.fromParts("package", mainActivity.getPackageName(), null)
|
||||
intent.setData(uri)
|
||||
mainActivity.startActivity(intent)
|
||||
}
|
||||
},
|
||||
gotoiOSSetting() {
|
||||
var UIApplication = plus.ios.import("UIApplication")
|
||||
var application2 = UIApplication.sharedApplication()
|
||||
var NSURL2 = plus.ios.import("NSURL")
|
||||
var setting2 = NSURL2.URLWithString("App-prefs:root=General")
|
||||
application2.openURL(setting2)
|
||||
plus.ios.deleteObject(setting2)
|
||||
plus.ios.deleteObject(NSURL2)
|
||||
plus.ios.deleteObject(application2)
|
||||
},
|
||||
gotoAndroidSetting() {
|
||||
var Intent = plus.android.importClass("android.content.Intent")
|
||||
var Settings = plus.android.importClass("android.provider.Settings")
|
||||
var mainActivity = plus.android.runtimeMainActivity()
|
||||
var intent = new Intent(Settings.ACTION_SETTINGS)
|
||||
mainActivity.startActivity(intent)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '@/uni_modules/uv-ui-tools/libs/css/components.scss';
|
||||
@import '@/uni_modules/uv-ui-tools/libs/css/color.scss';
|
||||
.uv-no-network {
|
||||
@include flex(column);
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-top: -100px;
|
||||
|
||||
&__tips {
|
||||
color: $uv-tips-color;
|
||||
font-size: 14px;
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
&__app {
|
||||
@include flex(row);
|
||||
margin-top: 6px;
|
||||
|
||||
&__setting {
|
||||
color: $uv-light-color;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
&__to-setting {
|
||||
font-size: 13px;
|
||||
color: $uv-primary;
|
||||
margin-left: 3px;
|
||||
}
|
||||
}
|
||||
|
||||
&__retry {
|
||||
@include flex(row);
|
||||
justify-content: center;
|
||||
margin-top: 15px;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -1,90 +0,0 @@
|
||||
{
|
||||
"id": "uv-no-network",
|
||||
"displayName": "uv-no-network 无网络提示 全面兼容小程序、nvue、vue2、vue3等多端",
|
||||
"version": "1.0.1",
|
||||
"description": "uv-no-network 该组件在没有任何网络的情况下,显示在内容上方,无需任何配置,引入即可,内部自动处理所有功能和事件。",
|
||||
"keywords": [
|
||||
"uv-no-network",
|
||||
"uvui",
|
||||
"uv-ui",
|
||||
"network",
|
||||
"无网络"
|
||||
],
|
||||
"repository": "",
|
||||
"engines": {
|
||||
"HBuilderX": "^3.1.0"
|
||||
},
|
||||
"dcloudext": {
|
||||
"type": "component-vue",
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "插件不采集任何数据",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": ""
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": [
|
||||
"uv-ui-tools",
|
||||
"uv-overlay",
|
||||
"uv-icon",
|
||||
"uv-button"
|
||||
],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y"
|
||||
},
|
||||
"client": {
|
||||
"Vue": {
|
||||
"vue2": "y",
|
||||
"vue3": "y"
|
||||
},
|
||||
"App": {
|
||||
"app-vue": "y",
|
||||
"app-nvue": "y"
|
||||
},
|
||||
"H5-mobile": {
|
||||
"Safari": "y",
|
||||
"Android Browser": "y",
|
||||
"微信浏览器(Android)": "y",
|
||||
"QQ浏览器(Android)": "y"
|
||||
},
|
||||
"H5-pc": {
|
||||
"Chrome": "y",
|
||||
"IE": "y",
|
||||
"Edge": "y",
|
||||
"Firefox": "y",
|
||||
"Safari": "y"
|
||||
},
|
||||
"小程序": {
|
||||
"微信": "y",
|
||||
"阿里": "y",
|
||||
"百度": "y",
|
||||
"字节跳动": "y",
|
||||
"QQ": "y",
|
||||
"钉钉": "u",
|
||||
"快手": "u",
|
||||
"飞书": "u",
|
||||
"京东": "u"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "u",
|
||||
"联盟": "u"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
## NoNetwork 无网络提示
|
||||
|
||||
> **组件名:uv-no-network**
|
||||
|
||||
该组件在没有任何网络的情况下,显示在内容上方,无需任何配置,引入即可,内部自动处理所有功能和事件。
|
||||
|
||||
### <a href="https://www.uvui.cn/components/noNetwork.html" target="_blank">查看文档</a>
|
||||
|
||||
### [完整示例项目下载 | 关注更多组件](https://ext.dcloud.net.cn/plugin?name=uv-ui)
|
||||
|
||||
#### 如使用过程中有任何问题,或者您对uv-ui有一些好的建议,欢迎加入 uv-ui 交流群:<a href="https://ext.dcloud.net.cn/plugin?id=12287" target="_blank">uv-ui</a>、<a href="https://www.uvui.cn/components/addQQGroup.html" target="_blank">官方QQ群</a>
|
@ -1,11 +0,0 @@
|
||||
## 1.0.4(2023-07-17)
|
||||
1. 优化文档
|
||||
2. 优化其他
|
||||
## 1.0.3(2023-06-26)
|
||||
1. H5增加属性h5SaveTip 保存二维码时候是否显示提示
|
||||
## 1.0.2(2023-06-01)
|
||||
1. 修复点击触发两次事件的BUG
|
||||
## 1.0.1(2023-05-23)
|
||||
1. 修复在部分平台不显示加载效果的BUG
|
||||
## 1.0.0(2023-05-17)
|
||||
1. 新增uv-qrcode组件
|
@ -1 +0,0 @@
|
||||
export const cacheImageList = [];
|
@ -1,241 +0,0 @@
|
||||
const isWeex = typeof WXEnvironment !== 'undefined';
|
||||
const isWeexIOS = isWeex && /ios/i.test(WXEnvironment.platform);
|
||||
const isWeexAndroid = isWeex && !isWeexIOS;
|
||||
|
||||
import GLmethod from '../context-webgl/GLmethod';
|
||||
|
||||
const GCanvasModule =
|
||||
(typeof weex !== 'undefined' && weex.requireModule) ? (weex.requireModule('gcanvas')) :
|
||||
(typeof __weex_require__ !== 'undefined') ? (__weex_require__('@weex-module/gcanvas')) : {};
|
||||
|
||||
let isDebugging = false;
|
||||
|
||||
let isComboDisabled = false;
|
||||
|
||||
const logCommand = (function () {
|
||||
const methodQuery = [];
|
||||
Object.keys(GLmethod).forEach(key => {
|
||||
methodQuery[GLmethod[key]] = key;
|
||||
})
|
||||
const queryMethod = (id) => {
|
||||
return methodQuery[parseInt(id)] || 'NotFoundMethod';
|
||||
}
|
||||
const logCommand = (id, cmds) => {
|
||||
const mId = cmds.split(',')[0];
|
||||
const mName = queryMethod(mId);
|
||||
console.log(`=== callNative - componentId:${id}; method: ${mName}; cmds: ${cmds}`);
|
||||
}
|
||||
return logCommand;
|
||||
})();
|
||||
|
||||
function joinArray(arr, sep) {
|
||||
let res = '';
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
if (i !== 0) {
|
||||
res += sep;
|
||||
}
|
||||
res += arr[i];
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
const commandsCache = {}
|
||||
|
||||
const GBridge = {
|
||||
|
||||
callEnable: (ref, configArray) => {
|
||||
|
||||
commandsCache[ref] = [];
|
||||
|
||||
return GCanvasModule.enable({
|
||||
componentId: ref,
|
||||
config: configArray
|
||||
});
|
||||
},
|
||||
|
||||
callEnableDebug: () => {
|
||||
isDebugging = true;
|
||||
},
|
||||
|
||||
callEnableDisableCombo: () => {
|
||||
isComboDisabled = true;
|
||||
},
|
||||
|
||||
callSetContextType: function (componentId, context_type) {
|
||||
GCanvasModule.setContextType(context_type, componentId);
|
||||
},
|
||||
|
||||
callReset: function(id){
|
||||
GCanvasModule.resetComponent && canvasModule.resetComponent(componentId);
|
||||
},
|
||||
|
||||
render: isWeexIOS ? function (componentId) {
|
||||
return GCanvasModule.extendCallNative({
|
||||
contextId: componentId,
|
||||
type: 0x60000001
|
||||
});
|
||||
} : function (componentId) {
|
||||
return callGCanvasLinkNative(componentId, 0x60000001, 'render');
|
||||
},
|
||||
|
||||
render2d: isWeexIOS ? function (componentId, commands, callback) {
|
||||
|
||||
if (isDebugging) {
|
||||
console.log('>>> >>> render2d ===');
|
||||
console.log('>>> commands: ' + commands);
|
||||
}
|
||||
|
||||
GCanvasModule.render([commands, callback?true:false], componentId, callback);
|
||||
|
||||
} : function (componentId, commands,callback) {
|
||||
|
||||
if (isDebugging) {
|
||||
console.log('>>> >>> render2d ===');
|
||||
console.log('>>> commands: ' + commands);
|
||||
}
|
||||
|
||||
callGCanvasLinkNative(componentId, 0x20000001, commands);
|
||||
if(callback){
|
||||
callback();
|
||||
}
|
||||
},
|
||||
|
||||
callExtendCallNative: isWeexIOS ? function (componentId, cmdArgs) {
|
||||
|
||||
throw 'should not be here anymore ' + cmdArgs;
|
||||
|
||||
} : function (componentId, cmdArgs) {
|
||||
|
||||
throw 'should not be here anymore ' + cmdArgs;
|
||||
|
||||
},
|
||||
|
||||
|
||||
flushNative: isWeexIOS ? function (componentId) {
|
||||
|
||||
const cmdArgs = joinArray(commandsCache[componentId], ';');
|
||||
commandsCache[componentId] = [];
|
||||
|
||||
if (isDebugging) {
|
||||
console.log('>>> >>> flush native ===');
|
||||
console.log('>>> commands: ' + cmdArgs);
|
||||
}
|
||||
|
||||
const result = GCanvasModule.extendCallNative({
|
||||
"contextId": componentId,
|
||||
"type": 0x60000000,
|
||||
"args": cmdArgs
|
||||
});
|
||||
|
||||
const res = result && result.result;
|
||||
|
||||
if (isDebugging) {
|
||||
console.log('>>> result: ' + res);
|
||||
}
|
||||
|
||||
return res;
|
||||
|
||||
} : function (componentId) {
|
||||
|
||||
const cmdArgs = joinArray(commandsCache[componentId], ';');
|
||||
commandsCache[componentId] = [];
|
||||
|
||||
if (isDebugging) {
|
||||
console.log('>>> >>> flush native ===');
|
||||
console.log('>>> commands: ' + cmdArgs);
|
||||
}
|
||||
|
||||
const result = callGCanvasLinkNative(componentId, 0x60000000, cmdArgs);
|
||||
|
||||
if (isDebugging) {
|
||||
console.log('>>> result: ' + result);
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
callNative: function (componentId, cmdArgs, cache) {
|
||||
|
||||
if (isDebugging) {
|
||||
logCommand(componentId, cmdArgs);
|
||||
}
|
||||
|
||||
commandsCache[componentId].push(cmdArgs);
|
||||
|
||||
if (!cache || isComboDisabled) {
|
||||
return GBridge.flushNative(componentId);
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
},
|
||||
|
||||
texImage2D(componentId, ...args) {
|
||||
if (isWeexIOS) {
|
||||
if (args.length === 6) {
|
||||
const [target, level, internalformat, format, type, image] = args;
|
||||
GBridge.callNative(
|
||||
componentId,
|
||||
GLmethod.texImage2D + ',' + 6 + ',' + target + ',' + level + ',' + internalformat + ',' + format + ',' + type + ',' + image.src
|
||||
)
|
||||
} else if (args.length === 9) {
|
||||
const [target, level, internalformat, width, height, border, format, type, image] = args;
|
||||
GBridge.callNative(
|
||||
componentId,
|
||||
GLmethod.texImage2D + ',' + 9 + ',' + target + ',' + level + ',' + internalformat + ',' + width + ',' + height + ',' + border + ',' +
|
||||
+ format + ',' + type + ',' + (image ? image.src : 0)
|
||||
)
|
||||
}
|
||||
} else if (isWeexAndroid) {
|
||||
if (args.length === 6) {
|
||||
const [target, level, internalformat, format, type, image] = args;
|
||||
GCanvasModule.texImage2D(componentId, target, level, internalformat, format, type, image.src);
|
||||
} else if (args.length === 9) {
|
||||
const [target, level, internalformat, width, height, border, format, type, image] = args;
|
||||
GCanvasModule.texImage2D(componentId, target, level, internalformat, width, height, border, format, type, (image ? image.src : 0));
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
texSubImage2D(componentId, target, level, xoffset, yoffset, format, type, image) {
|
||||
if (isWeexIOS) {
|
||||
if (arguments.length === 8) {
|
||||
GBridge.callNative(
|
||||
componentId,
|
||||
GLmethod.texSubImage2D + ',' + 6 + ',' + target + ',' + level + ',' + xoffset + ',' + yoffset, + ',' + format + ',' + type + ',' + image.src
|
||||
)
|
||||
}
|
||||
} else if (isWeexAndroid) {
|
||||
GCanvasModule.texSubImage2D(componentId, target, level, xoffset, yoffset, format, type, image.src);
|
||||
}
|
||||
},
|
||||
|
||||
bindImageTexture(componentId, src, imageId) {
|
||||
GCanvasModule.bindImageTexture([src, imageId], componentId);
|
||||
},
|
||||
|
||||
perloadImage([url, id], callback) {
|
||||
GCanvasModule.preLoadImage([url, id], function (image) {
|
||||
image.url = url;
|
||||
image.id = id;
|
||||
callback(image);
|
||||
});
|
||||
},
|
||||
|
||||
measureText(text, fontStyle, componentId) {
|
||||
return GCanvasModule.measureText([text, fontStyle], componentId);
|
||||
},
|
||||
|
||||
getImageData (componentId, x, y, w, h, callback) {
|
||||
GCanvasModule.getImageData([x, y,w,h],componentId,callback);
|
||||
},
|
||||
|
||||
putImageData (componentId, data, x, y, w, h, callback) {
|
||||
GCanvasModule.putImageData([x, y,w,h,data],componentId,callback);
|
||||
},
|
||||
|
||||
toTempFilePath(componentId, x, y, width, height, destWidth, destHeight, fileType, quality, callback){
|
||||
GCanvasModule.toTempFilePath([x, y, width,height, destWidth, destHeight, fileType, quality], componentId, callback);
|
||||
}
|
||||
}
|
||||
|
||||
export default GBridge;
|
@ -1,18 +0,0 @@
|
||||
class FillStyleLinearGradient {
|
||||
|
||||
constructor(x0, y0, x1, y1) {
|
||||
this._start_pos = { _x: x0, _y: y0 };
|
||||
this._end_pos = { _x: x1, _y: y1 };
|
||||
this._stop_count = 0;
|
||||
this._stops = [0, 0, 0, 0, 0];
|
||||
}
|
||||
|
||||
addColorStop = function (pos, color) {
|
||||
if (this._stop_count < 5 && 0.0 <= pos && pos <= 1.0) {
|
||||
this._stops[this._stop_count] = { _pos: pos, _color: color };
|
||||
this._stop_count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default FillStyleLinearGradient;
|
@ -1,8 +0,0 @@
|
||||
class FillStylePattern {
|
||||
constructor(img, pattern) {
|
||||
this._style = pattern;
|
||||
this._img = img;
|
||||
}
|
||||
}
|
||||
|
||||
export default FillStylePattern;
|
@ -1,17 +0,0 @@
|
||||
class FillStyleRadialGradient {
|
||||
constructor(x0, y0, r0, x1, y1, r1) {
|
||||
this._start_pos = { _x: x0, _y: y0, _r: r0 };
|
||||
this._end_pos = { _x: x1, _y: y1, _r: r1 };
|
||||
this._stop_count = 0;
|
||||
this._stops = [0, 0, 0, 0, 0];
|
||||
}
|
||||
|
||||
addColorStop(pos, color) {
|
||||
if (this._stop_count < 5 && 0.0 <= pos && pos <= 1.0) {
|
||||
this._stops[this._stop_count] = { _pos: pos, _color: color };
|
||||
this._stop_count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default FillStyleRadialGradient;
|
@ -1,666 +0,0 @@
|
||||
import FillStylePattern from './FillStylePattern';
|
||||
import FillStyleLinearGradient from './FillStyleLinearGradient';
|
||||
import FillStyleRadialGradient from './FillStyleRadialGradient';
|
||||
import GImage from '../env/image.js';
|
||||
import {
|
||||
ArrayBufferToBase64,
|
||||
Base64ToUint8ClampedArray
|
||||
} from '../env/tool.js';
|
||||
|
||||
export default class CanvasRenderingContext2D {
|
||||
|
||||
_drawCommands = '';
|
||||
|
||||
_globalAlpha = 1.0;
|
||||
|
||||
_fillStyle = 'rgb(0,0,0)';
|
||||
_strokeStyle = 'rgb(0,0,0)';
|
||||
|
||||
_lineWidth = 1;
|
||||
_lineCap = 'butt';
|
||||
_lineJoin = 'miter';
|
||||
|
||||
_miterLimit = 10;
|
||||
|
||||
_globalCompositeOperation = 'source-over';
|
||||
|
||||
_textAlign = 'start';
|
||||
_textBaseline = 'alphabetic';
|
||||
|
||||
_font = '10px sans-serif';
|
||||
|
||||
_savedGlobalAlpha = [];
|
||||
|
||||
timer = null;
|
||||
componentId = null;
|
||||
|
||||
_notCommitDrawImageCache = [];
|
||||
_needRedrawImageCache = [];
|
||||
_redrawCommands = '';
|
||||
_autoSaveContext = true;
|
||||
// _imageMap = new GHashMap();
|
||||
// _textureMap = new GHashMap();
|
||||
|
||||
constructor() {
|
||||
this.className = 'CanvasRenderingContext2D';
|
||||
//this.save()
|
||||
}
|
||||
|
||||
setFillStyle(value) {
|
||||
this.fillStyle = value;
|
||||
}
|
||||
|
||||
set fillStyle(value) {
|
||||
this._fillStyle = value;
|
||||
|
||||
if (typeof(value) == 'string') {
|
||||
this._drawCommands = this._drawCommands.concat("F" + value + ";");
|
||||
} else if (value instanceof FillStylePattern) {
|
||||
const image = value._img;
|
||||
if (!image.complete) {
|
||||
image.onload = () => {
|
||||
var index = this._needRedrawImageCache.indexOf(image);
|
||||
if (index > -1) {
|
||||
this._needRedrawImageCache.splice(index, 1);
|
||||
CanvasRenderingContext2D.GBridge.bindImageTexture(this.componentId, image.src, image._id);
|
||||
this._redrawflush(true);
|
||||
}
|
||||
}
|
||||
this._notCommitDrawImageCache.push(image);
|
||||
} else {
|
||||
CanvasRenderingContext2D.GBridge.bindImageTexture(this.componentId, image.src, image._id);
|
||||
}
|
||||
|
||||
//CanvasRenderingContext2D.GBridge.bindImageTexture(this.componentId, image.src, image._id);
|
||||
this._drawCommands = this._drawCommands.concat("G" + image._id + "," + value._style + ";");
|
||||
} else if (value instanceof FillStyleLinearGradient) {
|
||||
var command = "D" + value._start_pos._x.toFixed(2) + "," + value._start_pos._y.toFixed(2) + "," +
|
||||
value._end_pos._x.toFixed(2) + "," + value._end_pos._y.toFixed(2) + "," +
|
||||
value._stop_count;
|
||||
for (var i = 0; i < value._stop_count; ++i) {
|
||||
command += ("," + value._stops[i]._pos + "," + value._stops[i]._color);
|
||||
}
|
||||
this._drawCommands = this._drawCommands.concat(command + ";");
|
||||
} else if (value instanceof FillStyleRadialGradient) {
|
||||
var command = "H" + value._start_pos._x.toFixed(2) + "," + value._start_pos._y.toFixed(2) + "," + value._start_pos._r
|
||||
.toFixed(2) + "," +
|
||||
value._end_pos._x.toFixed(2) + "," + value._end_pos._y.toFixed(2) + "," + value._end_pos._r.toFixed(2) + "," +
|
||||
value._stop_count;
|
||||
for (var i = 0; i < value._stop_count; ++i) {
|
||||
command += ("," + value._stops[i]._pos + "," + value._stops[i]._color);
|
||||
}
|
||||
this._drawCommands = this._drawCommands.concat(command + ";");
|
||||
}
|
||||
}
|
||||
|
||||
get fillStyle() {
|
||||
return this._fillStyle;
|
||||
}
|
||||
|
||||
get globalAlpha() {
|
||||
return this._globalAlpha;
|
||||
}
|
||||
|
||||
setGlobalAlpha(value) {
|
||||
this.globalAlpha = value;
|
||||
}
|
||||
|
||||
set globalAlpha(value) {
|
||||
this._globalAlpha = value;
|
||||
this._drawCommands = this._drawCommands.concat("a" + value.toFixed(2) + ";");
|
||||
}
|
||||
|
||||
|
||||
get strokeStyle() {
|
||||
return this._strokeStyle;
|
||||
}
|
||||
|
||||
setStrokeStyle(value) {
|
||||
this.strokeStyle = value;
|
||||
}
|
||||
|
||||
set strokeStyle(value) {
|
||||
|
||||
this._strokeStyle = value;
|
||||
|
||||
if (typeof(value) == 'string') {
|
||||
this._drawCommands = this._drawCommands.concat("S" + value + ";");
|
||||
} else if (value instanceof FillStylePattern) {
|
||||
CanvasRenderingContext2D.GBridge.bindImageTexture(this.componentId, image.src, image._id);
|
||||
this._drawCommands = this._drawCommands.concat("G" + image._id + "," + value._style + ";");
|
||||
} else if (value instanceof FillStyleLinearGradient) {
|
||||
var command = "D" + value._start_pos._x.toFixed(2) + "," + value._start_pos._y.toFixed(2) + "," +
|
||||
value._end_pos._x.toFixed(2) + "," + value._end_pos._y.toFixed(2) + "," +
|
||||
value._stop_count;
|
||||
|
||||
for (var i = 0; i < value._stop_count; ++i) {
|
||||
command += ("," + value._stops[i]._pos + "," + value._stops[i]._color);
|
||||
}
|
||||
this._drawCommands = this._drawCommands.concat(command + ";");
|
||||
} else if (value instanceof FillStyleRadialGradient) {
|
||||
var command = "H" + value._start_pos._x.toFixed(2) + "," + value._start_pos._y.toFixed(2) + "," + value._start_pos._r
|
||||
.toFixed(2) + "," +
|
||||
value._end_pos._x.toFixed(2) + "," + value._end_pos._y + ",".toFixed(2) + value._end_pos._r.toFixed(2) + "," +
|
||||
value._stop_count;
|
||||
|
||||
for (var i = 0; i < value._stop_count; ++i) {
|
||||
command += ("," + value._stops[i]._pos + "," + value._stops[i]._color);
|
||||
}
|
||||
this._drawCommands = this._drawCommands.concat(command + ";");
|
||||
}
|
||||
}
|
||||
|
||||
get lineWidth() {
|
||||
return this._lineWidth;
|
||||
}
|
||||
|
||||
setLineWidth(value) {
|
||||
this.lineWidth = value;
|
||||
}
|
||||
|
||||
set lineWidth(value) {
|
||||
this._lineWidth = value;
|
||||
this._drawCommands = this._drawCommands.concat("W" + value + ";");
|
||||
}
|
||||
|
||||
get lineCap() {
|
||||
return this._lineCap;
|
||||
}
|
||||
|
||||
setLineCap(value) {
|
||||
this.lineCap = value;
|
||||
}
|
||||
|
||||
set lineCap(value) {
|
||||
this._lineCap = value;
|
||||
this._drawCommands = this._drawCommands.concat("C" + value + ";");
|
||||
}
|
||||
|
||||
get lineJoin() {
|
||||
return this._lineJoin;
|
||||
}
|
||||
|
||||
setLineJoin(value) {
|
||||
this.lineJoin = value
|
||||
}
|
||||
|
||||
set lineJoin(value) {
|
||||
this._lineJoin = value;
|
||||
this._drawCommands = this._drawCommands.concat("J" + value + ";");
|
||||
}
|
||||
|
||||
get miterLimit() {
|
||||
return this._miterLimit;
|
||||
}
|
||||
|
||||
setMiterLimit(value) {
|
||||
this.miterLimit = value
|
||||
}
|
||||
|
||||
set miterLimit(value) {
|
||||
this._miterLimit = value;
|
||||
this._drawCommands = this._drawCommands.concat("M" + value + ";");
|
||||
}
|
||||
|
||||
get globalCompositeOperation() {
|
||||
return this._globalCompositeOperation;
|
||||
}
|
||||
|
||||
set globalCompositeOperation(value) {
|
||||
|
||||
this._globalCompositeOperation = value;
|
||||
let mode = 0;
|
||||
switch (value) {
|
||||
case "source-over":
|
||||
mode = 0;
|
||||
break;
|
||||
case "source-atop":
|
||||
mode = 5;
|
||||
break;
|
||||
case "source-in":
|
||||
mode = 0;
|
||||
break;
|
||||
case "source-out":
|
||||
mode = 2;
|
||||
break;
|
||||
case "destination-over":
|
||||
mode = 4;
|
||||
break;
|
||||
case "destination-atop":
|
||||
mode = 4;
|
||||
break;
|
||||
case "destination-in":
|
||||
mode = 4;
|
||||
break;
|
||||
case "destination-out":
|
||||
mode = 3;
|
||||
break;
|
||||
case "lighter":
|
||||
mode = 1;
|
||||
break;
|
||||
case "copy":
|
||||
mode = 2;
|
||||
break;
|
||||
case "xor":
|
||||
mode = 6;
|
||||
break;
|
||||
default:
|
||||
mode = 0;
|
||||
}
|
||||
|
||||
this._drawCommands = this._drawCommands.concat("B" + mode + ";");
|
||||
}
|
||||
|
||||
get textAlign() {
|
||||
return this._textAlign;
|
||||
}
|
||||
|
||||
setTextAlign(value) {
|
||||
this.textAlign = value
|
||||
}
|
||||
|
||||
set textAlign(value) {
|
||||
|
||||
this._textAlign = value;
|
||||
let Align = 0;
|
||||
switch (value) {
|
||||
case "start":
|
||||
Align = 0;
|
||||
break;
|
||||
case "end":
|
||||
Align = 1;
|
||||
break;
|
||||
case "left":
|
||||
Align = 2;
|
||||
break;
|
||||
case "center":
|
||||
Align = 3;
|
||||
break;
|
||||
case "right":
|
||||
Align = 4;
|
||||
break;
|
||||
default:
|
||||
Align = 0;
|
||||
}
|
||||
|
||||
this._drawCommands = this._drawCommands.concat("A" + Align + ";");
|
||||
}
|
||||
|
||||
get textBaseline() {
|
||||
return this._textBaseline;
|
||||
}
|
||||
|
||||
setTextBaseline(value) {
|
||||
this.textBaseline = value
|
||||
}
|
||||
|
||||
set textBaseline(value) {
|
||||
this._textBaseline = value;
|
||||
let baseline = 0;
|
||||
switch (value) {
|
||||
case "alphabetic":
|
||||
baseline = 0;
|
||||
break;
|
||||
case "middle":
|
||||
baseline = 1;
|
||||
break;
|
||||
case "top":
|
||||
baseline = 2;
|
||||
break;
|
||||
case "hanging":
|
||||
baseline = 3;
|
||||
break;
|
||||
case "bottom":
|
||||
baseline = 4;
|
||||
break;
|
||||
case "ideographic":
|
||||
baseline = 5;
|
||||
break;
|
||||
default:
|
||||
baseline = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
this._drawCommands = this._drawCommands.concat("E" + baseline + ";");
|
||||
}
|
||||
|
||||
get font() {
|
||||
return this._font;
|
||||
}
|
||||
|
||||
setFontSize(size) {
|
||||
var str = this._font;
|
||||
var strs = str.trim().split(/\s+/);
|
||||
for (var i = 0; i < strs.length; i++) {
|
||||
var values = ["normal", "italic", "oblique", "normal", "small-caps", "normal", "bold",
|
||||
"bolder", "lighter", "100", "200", "300", "400", "500", "600", "700", "800", "900",
|
||||
"normal", "ultra-condensed", "extra-condensed", "condensed", "semi-condensed",
|
||||
"semi-expanded", "expanded", "extra-expanded", "ultra-expanded"
|
||||
];
|
||||
|
||||
if (-1 == values.indexOf(strs[i].trim())) {
|
||||
if (typeof size === 'string') {
|
||||
strs[i] = size;
|
||||
} else if (typeof size === 'number') {
|
||||
strs[i] = String(size) + 'px';
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.font = strs.join(" ");
|
||||
}
|
||||
|
||||
set font(value) {
|
||||
this._font = value;
|
||||
this._drawCommands = this._drawCommands.concat("j" + value + ";");
|
||||
}
|
||||
|
||||
setTransform(a, b, c, d, tx, ty) {
|
||||
this._drawCommands = this._drawCommands.concat("t" +
|
||||
(a === 1 ? "1" : a.toFixed(2)) + "," +
|
||||
(b === 0 ? "0" : b.toFixed(2)) + "," +
|
||||
(c === 0 ? "0" : c.toFixed(2)) + "," +
|
||||
(d === 1 ? "1" : d.toFixed(2)) + "," + tx.toFixed(2) + "," + ty.toFixed(2) + ";");
|
||||
}
|
||||
|
||||
transform(a, b, c, d, tx, ty) {
|
||||
this._drawCommands = this._drawCommands.concat("f" +
|
||||
(a === 1 ? "1" : a.toFixed(2)) + "," +
|
||||
(b === 0 ? "0" : b.toFixed(2)) + "," +
|
||||
(c === 0 ? "0" : c.toFixed(2)) + "," +
|
||||
(d === 1 ? "1" : d.toFixed(2)) + "," + tx + "," + ty + ";");
|
||||
}
|
||||
|
||||
resetTransform() {
|
||||
this._drawCommands = this._drawCommands.concat("m;");
|
||||
}
|
||||
|
||||
scale(a, d) {
|
||||
this._drawCommands = this._drawCommands.concat("k" + a.toFixed(2) + "," +
|
||||
d.toFixed(2) + ";");
|
||||
}
|
||||
|
||||
rotate(angle) {
|
||||
this._drawCommands = this._drawCommands
|
||||
.concat("r" + angle.toFixed(6) + ";");
|
||||
}
|
||||
|
||||
translate(tx, ty) {
|
||||
this._drawCommands = this._drawCommands.concat("l" + tx.toFixed(2) + "," + ty.toFixed(2) + ";");
|
||||
}
|
||||
|
||||
save() {
|
||||
this._savedGlobalAlpha.push(this._globalAlpha);
|
||||
this._drawCommands = this._drawCommands.concat("v;");
|
||||
}
|
||||
|
||||
restore() {
|
||||
this._drawCommands = this._drawCommands.concat("e;");
|
||||
this._globalAlpha = this._savedGlobalAlpha.pop();
|
||||
}
|
||||
|
||||
createPattern(img, pattern) {
|
||||
if (typeof img === 'string') {
|
||||
var imgObj = new GImage();
|
||||
imgObj.src = img;
|
||||
img = imgObj;
|
||||
}
|
||||
return new FillStylePattern(img, pattern);
|
||||
}
|
||||
|
||||
createLinearGradient(x0, y0, x1, y1) {
|
||||
return new FillStyleLinearGradient(x0, y0, x1, y1);
|
||||
}
|
||||
|
||||
createRadialGradient = function(x0, y0, r0, x1, y1, r1) {
|
||||
return new FillStyleRadialGradient(x0, y0, r0, x1, y1, r1);
|
||||
};
|
||||
|
||||
createCircularGradient = function(x0, y0, r0) {
|
||||
return new FillStyleRadialGradient(x0, y0, 0, x0, y0, r0);
|
||||
};
|
||||
|
||||
strokeRect(x, y, w, h) {
|
||||
this._drawCommands = this._drawCommands.concat("s" + x + "," + y + "," + w + "," + h + ";");
|
||||
}
|
||||
|
||||
|
||||
clearRect(x, y, w, h) {
|
||||
this._drawCommands = this._drawCommands.concat("c" + x + "," + y + "," + w +
|
||||
"," + h + ";");
|
||||
}
|
||||
|
||||
clip() {
|
||||
this._drawCommands = this._drawCommands.concat("p;");
|
||||
}
|
||||
|
||||
resetClip() {
|
||||
this._drawCommands = this._drawCommands.concat("q;");
|
||||
}
|
||||
|
||||
closePath() {
|
||||
this._drawCommands = this._drawCommands.concat("o;");
|
||||
}
|
||||
|
||||
moveTo(x, y) {
|
||||
this._drawCommands = this._drawCommands.concat("g" + x.toFixed(2) + "," + y.toFixed(2) + ";");
|
||||
}
|
||||
|
||||
lineTo(x, y) {
|
||||
this._drawCommands = this._drawCommands.concat("i" + x.toFixed(2) + "," + y.toFixed(2) + ";");
|
||||
}
|
||||
|
||||
quadraticCurveTo = function(cpx, cpy, x, y) {
|
||||
this._drawCommands = this._drawCommands.concat("u" + cpx + "," + cpy + "," + x + "," + y + ";");
|
||||
}
|
||||
|
||||
bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y, ) {
|
||||
this._drawCommands = this._drawCommands.concat(
|
||||
"z" + cp1x.toFixed(2) + "," + cp1y.toFixed(2) + "," + cp2x.toFixed(2) + "," + cp2y.toFixed(2) + "," +
|
||||
x.toFixed(2) + "," + y.toFixed(2) + ";");
|
||||
}
|
||||
|
||||
arcTo(x1, y1, x2, y2, radius) {
|
||||
this._drawCommands = this._drawCommands.concat("h" + x1 + "," + y1 + "," + x2 + "," + y2 + "," + radius + ";");
|
||||
}
|
||||
|
||||
beginPath() {
|
||||
this._drawCommands = this._drawCommands.concat("b;");
|
||||
}
|
||||
|
||||
|
||||
fillRect(x, y, w, h) {
|
||||
this._drawCommands = this._drawCommands.concat("n" + x + "," + y + "," + w +
|
||||
"," + h + ";");
|
||||
}
|
||||
|
||||
rect(x, y, w, h) {
|
||||
this._drawCommands = this._drawCommands.concat("w" + x + "," + y + "," + w + "," + h + ";");
|
||||
}
|
||||
|
||||
fill() {
|
||||
this._drawCommands = this._drawCommands.concat("L;");
|
||||
}
|
||||
|
||||
stroke(path) {
|
||||
this._drawCommands = this._drawCommands.concat("x;");
|
||||
}
|
||||
|
||||
arc(x, y, radius, startAngle, endAngle, anticlockwise) {
|
||||
|
||||
let ianticlockwise = 0;
|
||||
if (anticlockwise) {
|
||||
ianticlockwise = 1;
|
||||
}
|
||||
|
||||
this._drawCommands = this._drawCommands.concat(
|
||||
"y" + x.toFixed(2) + "," + y.toFixed(2) + "," +
|
||||
radius.toFixed(2) + "," + startAngle + "," + endAngle + "," + ianticlockwise +
|
||||
";"
|
||||
);
|
||||
}
|
||||
|
||||
fillText(text, x, y) {
|
||||
let tmptext = text.replace(/!/g, "!!");
|
||||
tmptext = tmptext.replace(/,/g, "!,");
|
||||
tmptext = tmptext.replace(/;/g, "!;");
|
||||
this._drawCommands = this._drawCommands.concat("T" + tmptext + "," + x + "," + y + ",0.0;");
|
||||
}
|
||||
|
||||
strokeText = function(text, x, y) {
|
||||
let tmptext = text.replace(/!/g, "!!");
|
||||
tmptext = tmptext.replace(/,/g, "!,");
|
||||
tmptext = tmptext.replace(/;/g, "!;");
|
||||
this._drawCommands = this._drawCommands.concat("U" + tmptext + "," + x + "," + y + ",0.0;");
|
||||
}
|
||||
|
||||
measureText(text) {
|
||||
return CanvasRenderingContext2D.GBridge.measureText(text, this.font, this.componentId);
|
||||
}
|
||||
|
||||
isPointInPath = function(x, y) {
|
||||
throw new Error('GCanvas not supported yet');
|
||||
}
|
||||
|
||||
drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh) {
|
||||
if (typeof image === 'string') {
|
||||
var imgObj = new GImage();
|
||||
imgObj.src = image;
|
||||
image = imgObj;
|
||||
}
|
||||
if (image instanceof GImage) {
|
||||
if (!image.complete) {
|
||||
imgObj.onload = () => {
|
||||
var index = this._needRedrawImageCache.indexOf(image);
|
||||
if (index > -1) {
|
||||
this._needRedrawImageCache.splice(index, 1);
|
||||
CanvasRenderingContext2D.GBridge.bindImageTexture(this.componentId, image.src, image._id);
|
||||
this._redrawflush(true);
|
||||
}
|
||||
}
|
||||
this._notCommitDrawImageCache.push(image);
|
||||
} else {
|
||||
CanvasRenderingContext2D.GBridge.bindImageTexture(this.componentId, image.src, image._id);
|
||||
}
|
||||
var srcArgs = [image, sx, sy, sw, sh, dx, dy, dw, dh];
|
||||
var args = [];
|
||||
for (var arg in srcArgs) {
|
||||
if (typeof(srcArgs[arg]) != 'undefined') {
|
||||
args.push(srcArgs[arg]);
|
||||
}
|
||||
}
|
||||
this.__drawImage.apply(this, args);
|
||||
//this.__drawImage(image,sx, sy, sw, sh, dx, dy, dw, dh);
|
||||
}
|
||||
}
|
||||
|
||||
__drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh) {
|
||||
const numArgs = arguments.length;
|
||||
|
||||
function drawImageCommands() {
|
||||
|
||||
if (numArgs === 3) {
|
||||
const x = parseFloat(sx) || 0.0;
|
||||
const y = parseFloat(sy) || 0.0;
|
||||
|
||||
return ("d" + image._id + ",0,0," +
|
||||
image.width + "," + image.height + "," +
|
||||
x + "," + y + "," + image.width + "," + image.height + ";");
|
||||
} else if (numArgs === 5) {
|
||||
const x = parseFloat(sx) || 0.0;
|
||||
const y = parseFloat(sy) || 0.0;
|
||||
const width = parseInt(sw) || image.width;
|
||||
const height = parseInt(sh) || image.height;
|
||||
|
||||
return ("d" + image._id + ",0,0," +
|
||||
image.width + "," + image.height + "," +
|
||||
x + "," + y + "," + width + "," + height + ";");
|
||||
} else if (numArgs === 9) {
|
||||
sx = parseFloat(sx) || 0.0;
|
||||
sy = parseFloat(sy) || 0.0;
|
||||
sw = parseInt(sw) || image.width;
|
||||
sh = parseInt(sh) || image.height;
|
||||
dx = parseFloat(dx) || 0.0;
|
||||
dy = parseFloat(dy) || 0.0;
|
||||
dw = parseInt(dw) || image.width;
|
||||
dh = parseInt(dh) || image.height;
|
||||
|
||||
return ("d" + image._id + "," +
|
||||
sx + "," + sy + "," + sw + "," + sh + "," +
|
||||
dx + "," + dy + "," + dw + "," + dh + ";");
|
||||
}
|
||||
}
|
||||
this._drawCommands += drawImageCommands();
|
||||
}
|
||||
|
||||
_flush(reserve, callback) {
|
||||
const commands = this._drawCommands;
|
||||
this._drawCommands = '';
|
||||
CanvasRenderingContext2D.GBridge.render2d(this.componentId, commands, callback);
|
||||
this._needRender = false;
|
||||
}
|
||||
|
||||
_redrawflush(reserve, callback) {
|
||||
const commands = this._redrawCommands;
|
||||
CanvasRenderingContext2D.GBridge.render2d(this.componentId, commands, callback);
|
||||
if (this._needRedrawImageCache.length == 0) {
|
||||
this._redrawCommands = '';
|
||||
}
|
||||
}
|
||||
|
||||
draw(reserve, callback) {
|
||||
if (!reserve) {
|
||||
this._globalAlpha = this._savedGlobalAlpha.pop();
|
||||
this._savedGlobalAlpha.push(this._globalAlpha);
|
||||
this._redrawCommands = this._drawCommands;
|
||||
this._needRedrawImageCache = this._notCommitDrawImageCache;
|
||||
if (this._autoSaveContext) {
|
||||
this._drawCommands = ("v;" + this._drawCommands);
|
||||
this._autoSaveContext = false;
|
||||
} else {
|
||||
this._drawCommands = ("e;X;v;" + this._drawCommands);
|
||||
}
|
||||
} else {
|
||||
this._needRedrawImageCache = this._needRedrawImageCache.concat(this._notCommitDrawImageCache);
|
||||
this._redrawCommands += this._drawCommands;
|
||||
if (this._autoSaveContext) {
|
||||
this._drawCommands = ("v;" + this._drawCommands);
|
||||
this._autoSaveContext = false;
|
||||
}
|
||||
}
|
||||
this._notCommitDrawImageCache = [];
|
||||
if (this._flush) {
|
||||
this._flush(reserve, callback);
|
||||
}
|
||||
}
|
||||
|
||||
getImageData(x, y, w, h, callback) {
|
||||
CanvasRenderingContext2D.GBridge.getImageData(this.componentId, x, y, w, h, function(res) {
|
||||
res.data = Base64ToUint8ClampedArray(res.data);
|
||||
if (typeof(callback) == 'function') {
|
||||
callback(res);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
putImageData(data, x, y, w, h, callback) {
|
||||
if (data instanceof Uint8ClampedArray) {
|
||||
data = ArrayBufferToBase64(data);
|
||||
CanvasRenderingContext2D.GBridge.putImageData(this.componentId, data, x, y, w, h, function(res) {
|
||||
if (typeof(callback) == 'function') {
|
||||
callback(res);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
toTempFilePath(x, y, width, height, destWidth, destHeight, fileType, quality, callback) {
|
||||
CanvasRenderingContext2D.GBridge.toTempFilePath(this.componentId, x, y, width, height, destWidth, destHeight,
|
||||
fileType, quality,
|
||||
function(res) {
|
||||
if (typeof(callback) == 'function') {
|
||||
callback(res);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
export default class WebGLActiveInfo {
|
||||
className = 'WebGLActiveInfo';
|
||||
|
||||
constructor({
|
||||
type, name, size
|
||||
}) {
|
||||
this.type = type;
|
||||
this.name = name;
|
||||
this.size = size;
|
||||
}
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
import {getTransferedObjectUUID} from './classUtils';
|
||||
|
||||
const name = 'WebGLBuffer';
|
||||
|
||||
function uuid(id) {
|
||||
return getTransferedObjectUUID(name, id);
|
||||
}
|
||||
|
||||
export default class WebGLBuffer {
|
||||
className = name;
|
||||
|
||||
constructor(id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
static uuid = uuid;
|
||||
|
||||
uuid() {
|
||||
return uuid(this.id);
|
||||
}
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
import {getTransferedObjectUUID} from './classUtils';
|
||||
|
||||
const name = 'WebGLFrameBuffer';
|
||||
|
||||
function uuid(id) {
|
||||
return getTransferedObjectUUID(name, id);
|
||||
}
|
||||
|
||||
export default class WebGLFramebuffer {
|
||||
className = name;
|
||||
|
||||
constructor(id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
static uuid = uuid;
|
||||
|
||||
uuid() {
|
||||
return uuid(this.id);
|
||||
}
|
||||
}
|
@ -1,298 +0,0 @@
|
||||
export default {
|
||||
"DEPTH_BUFFER_BIT": 256,
|
||||
"STENCIL_BUFFER_BIT": 1024,
|
||||
"COLOR_BUFFER_BIT": 16384,
|
||||
"POINTS": 0,
|
||||
"LINES": 1,
|
||||
"LINE_LOOP": 2,
|
||||
"LINE_STRIP": 3,
|
||||
"TRIANGLES": 4,
|
||||
"TRIANGLE_STRIP": 5,
|
||||
"TRIANGLE_FAN": 6,
|
||||
"ZERO": 0,
|
||||
"ONE": 1,
|
||||
"SRC_COLOR": 768,
|
||||
"ONE_MINUS_SRC_COLOR": 769,
|
||||
"SRC_ALPHA": 770,
|
||||
"ONE_MINUS_SRC_ALPHA": 771,
|
||||
"DST_ALPHA": 772,
|
||||
"ONE_MINUS_DST_ALPHA": 773,
|
||||
"DST_COLOR": 774,
|
||||
"ONE_MINUS_DST_COLOR": 775,
|
||||
"SRC_ALPHA_SATURATE": 776,
|
||||
"FUNC_ADD": 32774,
|
||||
"BLEND_EQUATION": 32777,
|
||||
"BLEND_EQUATION_RGB": 32777,
|
||||
"BLEND_EQUATION_ALPHA": 34877,
|
||||
"FUNC_SUBTRACT": 32778,
|
||||
"FUNC_REVERSE_SUBTRACT": 32779,
|
||||
"BLEND_DST_RGB": 32968,
|
||||
"BLEND_SRC_RGB": 32969,
|
||||
"BLEND_DST_ALPHA": 32970,
|
||||
"BLEND_SRC_ALPHA": 32971,
|
||||
"CONSTANT_COLOR": 32769,
|
||||
"ONE_MINUS_CONSTANT_COLOR": 32770,
|
||||
"CONSTANT_ALPHA": 32771,
|
||||
"ONE_MINUS_CONSTANT_ALPHA": 32772,
|
||||
"BLEND_COLOR": 32773,
|
||||
"ARRAY_BUFFER": 34962,
|
||||
"ELEMENT_ARRAY_BUFFER": 34963,
|
||||
"ARRAY_BUFFER_BINDING": 34964,
|
||||
"ELEMENT_ARRAY_BUFFER_BINDING": 34965,
|
||||
"STREAM_DRAW": 35040,
|
||||
"STATIC_DRAW": 35044,
|
||||
"DYNAMIC_DRAW": 35048,
|
||||
"BUFFER_SIZE": 34660,
|
||||
"BUFFER_USAGE": 34661,
|
||||
"CURRENT_VERTEX_ATTRIB": 34342,
|
||||
"FRONT": 1028,
|
||||
"BACK": 1029,
|
||||
"FRONT_AND_BACK": 1032,
|
||||
"TEXTURE_2D": 3553,
|
||||
"CULL_FACE": 2884,
|
||||
"BLEND": 3042,
|
||||
"DITHER": 3024,
|
||||
"STENCIL_TEST": 2960,
|
||||
"DEPTH_TEST": 2929,
|
||||
"SCISSOR_TEST": 3089,
|
||||
"POLYGON_OFFSET_FILL": 32823,
|
||||
"SAMPLE_ALPHA_TO_COVERAGE": 32926,
|
||||
"SAMPLE_COVERAGE": 32928,
|
||||
"NO_ERROR": 0,
|
||||
"INVALID_ENUM": 1280,
|
||||
"INVALID_VALUE": 1281,
|
||||
"INVALID_OPERATION": 1282,
|
||||
"OUT_OF_MEMORY": 1285,
|
||||
"CW": 2304,
|
||||
"CCW": 2305,
|
||||
"LINE_WIDTH": 2849,
|
||||
"ALIASED_POINT_SIZE_RANGE": 33901,
|
||||
"ALIASED_LINE_WIDTH_RANGE": 33902,
|
||||
"CULL_FACE_MODE": 2885,
|
||||
"FRONT_FACE": 2886,
|
||||
"DEPTH_RANGE": 2928,
|
||||
"DEPTH_WRITEMASK": 2930,
|
||||
"DEPTH_CLEAR_VALUE": 2931,
|
||||
"DEPTH_FUNC": 2932,
|
||||
"STENCIL_CLEAR_VALUE": 2961,
|
||||
"STENCIL_FUNC": 2962,
|
||||
"STENCIL_FAIL": 2964,
|
||||
"STENCIL_PASS_DEPTH_FAIL": 2965,
|
||||
"STENCIL_PASS_DEPTH_PASS": 2966,
|
||||
"STENCIL_REF": 2967,
|
||||
"STENCIL_VALUE_MASK": 2963,
|
||||
"STENCIL_WRITEMASK": 2968,
|
||||
"STENCIL_BACK_FUNC": 34816,
|
||||
"STENCIL_BACK_FAIL": 34817,
|
||||
"STENCIL_BACK_PASS_DEPTH_FAIL": 34818,
|
||||
"STENCIL_BACK_PASS_DEPTH_PASS": 34819,
|
||||
"STENCIL_BACK_REF": 36003,
|
||||
"STENCIL_BACK_VALUE_MASK": 36004,
|
||||
"STENCIL_BACK_WRITEMASK": 36005,
|
||||
"VIEWPORT": 2978,
|
||||
"SCISSOR_BOX": 3088,
|
||||
"COLOR_CLEAR_VALUE": 3106,
|
||||
"COLOR_WRITEMASK": 3107,
|
||||
"UNPACK_ALIGNMENT": 3317,
|
||||
"PACK_ALIGNMENT": 3333,
|
||||
"MAX_TEXTURE_SIZE": 3379,
|
||||
"MAX_VIEWPORT_DIMS": 3386,
|
||||
"SUBPIXEL_BITS": 3408,
|
||||
"RED_BITS": 3410,
|
||||
"GREEN_BITS": 3411,
|
||||
"BLUE_BITS": 3412,
|
||||
"ALPHA_BITS": 3413,
|
||||
"DEPTH_BITS": 3414,
|
||||
"STENCIL_BITS": 3415,
|
||||
"POLYGON_OFFSET_UNITS": 10752,
|
||||
"POLYGON_OFFSET_FACTOR": 32824,
|
||||
"TEXTURE_BINDING_2D": 32873,
|
||||
"SAMPLE_BUFFERS": 32936,
|
||||
"SAMPLES": 32937,
|
||||
"SAMPLE_COVERAGE_VALUE": 32938,
|
||||
"SAMPLE_COVERAGE_INVERT": 32939,
|
||||
"COMPRESSED_TEXTURE_FORMATS": 34467,
|
||||
"DONT_CARE": 4352,
|
||||
"FASTEST": 4353,
|
||||
"NICEST": 4354,
|
||||
"GENERATE_MIPMAP_HINT": 33170,
|
||||
"BYTE": 5120,
|
||||
"UNSIGNED_BYTE": 5121,
|
||||
"SHORT": 5122,
|
||||
"UNSIGNED_SHORT": 5123,
|
||||
"INT": 5124,
|
||||
"UNSIGNED_INT": 5125,
|
||||
"FLOAT": 5126,
|
||||
"DEPTH_COMPONENT": 6402,
|
||||
"ALPHA": 6406,
|
||||
"RGB": 6407,
|
||||
"RGBA": 6408,
|
||||
"LUMINANCE": 6409,
|
||||
"LUMINANCE_ALPHA": 6410,
|
||||
"UNSIGNED_SHORT_4_4_4_4": 32819,
|
||||
"UNSIGNED_SHORT_5_5_5_1": 32820,
|
||||
"UNSIGNED_SHORT_5_6_5": 33635,
|
||||
"FRAGMENT_SHADER": 35632,
|
||||
"VERTEX_SHADER": 35633,
|
||||
"MAX_VERTEX_ATTRIBS": 34921,
|
||||
"MAX_VERTEX_UNIFORM_VECTORS": 36347,
|
||||
"MAX_VARYING_VECTORS": 36348,
|
||||
"MAX_COMBINED_TEXTURE_IMAGE_UNITS": 35661,
|
||||
"MAX_VERTEX_TEXTURE_IMAGE_UNITS": 35660,
|
||||
"MAX_TEXTURE_IMAGE_UNITS": 34930,
|
||||
"MAX_FRAGMENT_UNIFORM_VECTORS": 36349,
|
||||
"SHADER_TYPE": 35663,
|
||||
"DELETE_STATUS": 35712,
|
||||
"LINK_STATUS": 35714,
|
||||
"VALIDATE_STATUS": 35715,
|
||||
"ATTACHED_SHADERS": 35717,
|
||||
"ACTIVE_UNIFORMS": 35718,
|
||||
"ACTIVE_ATTRIBUTES": 35721,
|
||||
"SHADING_LANGUAGE_VERSION": 35724,
|
||||
"CURRENT_PROGRAM": 35725,
|
||||
"NEVER": 512,
|
||||
"LESS": 513,
|
||||
"EQUAL": 514,
|
||||
"LEQUAL": 515,
|
||||
"GREATER": 516,
|
||||
"NOTEQUAL": 517,
|
||||
"GEQUAL": 518,
|
||||
"ALWAYS": 519,
|
||||
"KEEP": 7680,
|
||||
"REPLACE": 7681,
|
||||
"INCR": 7682,
|
||||
"DECR": 7683,
|
||||
"INVERT": 5386,
|
||||
"INCR_WRAP": 34055,
|
||||
"DECR_WRAP": 34056,
|
||||
"VENDOR": 7936,
|
||||
"RENDERER": 7937,
|
||||
"VERSION": 7938,
|
||||
"NEAREST": 9728,
|
||||
"LINEAR": 9729,
|
||||
"NEAREST_MIPMAP_NEAREST": 9984,
|
||||
"LINEAR_MIPMAP_NEAREST": 9985,
|
||||
"NEAREST_MIPMAP_LINEAR": 9986,
|
||||
"LINEAR_MIPMAP_LINEAR": 9987,
|
||||
"TEXTURE_MAG_FILTER": 10240,
|
||||
"TEXTURE_MIN_FILTER": 10241,
|
||||
"TEXTURE_WRAP_S": 10242,
|
||||
"TEXTURE_WRAP_T": 10243,
|
||||
"TEXTURE": 5890,
|
||||
"TEXTURE_CUBE_MAP": 34067,
|
||||
"TEXTURE_BINDING_CUBE_MAP": 34068,
|
||||
"TEXTURE_CUBE_MAP_POSITIVE_X": 34069,
|
||||
"TEXTURE_CUBE_MAP_NEGATIVE_X": 34070,
|
||||
"TEXTURE_CUBE_MAP_POSITIVE_Y": 34071,
|
||||
"TEXTURE_CUBE_MAP_NEGATIVE_Y": 34072,
|
||||
"TEXTURE_CUBE_MAP_POSITIVE_Z": 34073,
|
||||
"TEXTURE_CUBE_MAP_NEGATIVE_Z": 34074,
|
||||
"MAX_CUBE_MAP_TEXTURE_SIZE": 34076,
|
||||
"TEXTURE0": 33984,
|
||||
"TEXTURE1": 33985,
|
||||
"TEXTURE2": 33986,
|
||||
"TEXTURE3": 33987,
|
||||
"TEXTURE4": 33988,
|
||||
"TEXTURE5": 33989,
|
||||
"TEXTURE6": 33990,
|
||||
"TEXTURE7": 33991,
|
||||
"TEXTURE8": 33992,
|
||||
"TEXTURE9": 33993,
|
||||
"TEXTURE10": 33994,
|
||||
"TEXTURE11": 33995,
|
||||
"TEXTURE12": 33996,
|
||||
"TEXTURE13": 33997,
|
||||
"TEXTURE14": 33998,
|
||||
"TEXTURE15": 33999,
|
||||
"TEXTURE16": 34000,
|
||||
"TEXTURE17": 34001,
|
||||
"TEXTURE18": 34002,
|
||||
"TEXTURE19": 34003,
|
||||
"TEXTURE20": 34004,
|
||||
"TEXTURE21": 34005,
|
||||
"TEXTURE22": 34006,
|
||||
"TEXTURE23": 34007,
|
||||
"TEXTURE24": 34008,
|
||||
"TEXTURE25": 34009,
|
||||
"TEXTURE26": 34010,
|
||||
"TEXTURE27": 34011,
|
||||
"TEXTURE28": 34012,
|
||||
"TEXTURE29": 34013,
|
||||
"TEXTURE30": 34014,
|
||||
"TEXTURE31": 34015,
|
||||
"ACTIVE_TEXTURE": 34016,
|
||||
"REPEAT": 10497,
|
||||
"CLAMP_TO_EDGE": 33071,
|
||||
"MIRRORED_REPEAT": 33648,
|
||||
"FLOAT_VEC2": 35664,
|
||||
"FLOAT_VEC3": 35665,
|
||||
"FLOAT_VEC4": 35666,
|
||||
"INT_VEC2": 35667,
|
||||
"INT_VEC3": 35668,
|
||||
"INT_VEC4": 35669,
|
||||
"BOOL": 35670,
|
||||
"BOOL_VEC2": 35671,
|
||||
"BOOL_VEC3": 35672,
|
||||
"BOOL_VEC4": 35673,
|
||||
"FLOAT_MAT2": 35674,
|
||||
"FLOAT_MAT3": 35675,
|
||||
"FLOAT_MAT4": 35676,
|
||||
"SAMPLER_2D": 35678,
|
||||
"SAMPLER_CUBE": 35680,
|
||||
"VERTEX_ATTRIB_ARRAY_ENABLED": 34338,
|
||||
"VERTEX_ATTRIB_ARRAY_SIZE": 34339,
|
||||
"VERTEX_ATTRIB_ARRAY_STRIDE": 34340,
|
||||
"VERTEX_ATTRIB_ARRAY_TYPE": 34341,
|
||||
"VERTEX_ATTRIB_ARRAY_NORMALIZED": 34922,
|
||||
"VERTEX_ATTRIB_ARRAY_POINTER": 34373,
|
||||
"VERTEX_ATTRIB_ARRAY_BUFFER_BINDING": 34975,
|
||||
"IMPLEMENTATION_COLOR_READ_TYPE": 35738,
|
||||
"IMPLEMENTATION_COLOR_READ_FORMAT": 35739,
|
||||
"COMPILE_STATUS": 35713,
|
||||
"LOW_FLOAT": 36336,
|
||||
"MEDIUM_FLOAT": 36337,
|
||||
"HIGH_FLOAT": 36338,
|
||||
"LOW_INT": 36339,
|
||||
"MEDIUM_INT": 36340,
|
||||
"HIGH_INT": 36341,
|
||||
"FRAMEBUFFER": 36160,
|
||||
"RENDERBUFFER": 36161,
|
||||
"RGBA4": 32854,
|
||||
"RGB5_A1": 32855,
|
||||
"RGB565": 36194,
|
||||
"DEPTH_COMPONENT16": 33189,
|
||||
"STENCIL_INDEX8": 36168,
|
||||
"DEPTH_STENCIL": 34041,
|
||||
"RENDERBUFFER_WIDTH": 36162,
|
||||
"RENDERBUFFER_HEIGHT": 36163,
|
||||
"RENDERBUFFER_INTERNAL_FORMAT": 36164,
|
||||
"RENDERBUFFER_RED_SIZE": 36176,
|
||||
"RENDERBUFFER_GREEN_SIZE": 36177,
|
||||
"RENDERBUFFER_BLUE_SIZE": 36178,
|
||||
"RENDERBUFFER_ALPHA_SIZE": 36179,
|
||||
"RENDERBUFFER_DEPTH_SIZE": 36180,
|
||||
"RENDERBUFFER_STENCIL_SIZE": 36181,
|
||||
"FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE": 36048,
|
||||
"FRAMEBUFFER_ATTACHMENT_OBJECT_NAME": 36049,
|
||||
"FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL": 36050,
|
||||
"FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE": 36051,
|
||||
"COLOR_ATTACHMENT0": 36064,
|
||||
"DEPTH_ATTACHMENT": 36096,
|
||||
"STENCIL_ATTACHMENT": 36128,
|
||||
"DEPTH_STENCIL_ATTACHMENT": 33306,
|
||||
"NONE": 0,
|
||||
"FRAMEBUFFER_COMPLETE": 36053,
|
||||
"FRAMEBUFFER_INCOMPLETE_ATTACHMENT": 36054,
|
||||
"FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT": 36055,
|
||||
"FRAMEBUFFER_INCOMPLETE_DIMENSIONS": 36057,
|
||||
"FRAMEBUFFER_UNSUPPORTED": 36061,
|
||||
"FRAMEBUFFER_BINDING": 36006,
|
||||
"RENDERBUFFER_BINDING": 36007,
|
||||
"MAX_RENDERBUFFER_SIZE": 34024,
|
||||
"INVALID_FRAMEBUFFER_OPERATION": 1286,
|
||||
"UNPACK_FLIP_Y_WEBGL": 37440,
|
||||
"UNPACK_PREMULTIPLY_ALPHA_WEBGL": 37441,
|
||||
"CONTEXT_LOST_WEBGL": 37442,
|
||||
"UNPACK_COLORSPACE_CONVERSION_WEBGL": 37443,
|
||||
"BROWSER_DEFAULT_WEBGL": 37444
|
||||
};
|
@ -1,142 +0,0 @@
|
||||
let i = 1;
|
||||
|
||||
const GLmethod = {};
|
||||
|
||||
GLmethod.activeTexture = i++; //1
|
||||
GLmethod.attachShader = i++;
|
||||
GLmethod.bindAttribLocation = i++;
|
||||
GLmethod.bindBuffer = i++;
|
||||
GLmethod.bindFramebuffer = i++;
|
||||
GLmethod.bindRenderbuffer = i++;
|
||||
GLmethod.bindTexture = i++;
|
||||
GLmethod.blendColor = i++;
|
||||
GLmethod.blendEquation = i++;
|
||||
GLmethod.blendEquationSeparate = i++; //10
|
||||
GLmethod.blendFunc = i++;
|
||||
GLmethod.blendFuncSeparate = i++;
|
||||
GLmethod.bufferData = i++;
|
||||
GLmethod.bufferSubData = i++;
|
||||
GLmethod.checkFramebufferStatus = i++;
|
||||
GLmethod.clear = i++;
|
||||
GLmethod.clearColor = i++;
|
||||
GLmethod.clearDepth = i++;
|
||||
GLmethod.clearStencil = i++;
|
||||
GLmethod.colorMask = i++; //20
|
||||
GLmethod.compileShader = i++;
|
||||
GLmethod.compressedTexImage2D = i++;
|
||||
GLmethod.compressedTexSubImage2D = i++;
|
||||
GLmethod.copyTexImage2D = i++;
|
||||
GLmethod.copyTexSubImage2D = i++;
|
||||
GLmethod.createBuffer = i++;
|
||||
GLmethod.createFramebuffer = i++;
|
||||
GLmethod.createProgram = i++;
|
||||
GLmethod.createRenderbuffer = i++;
|
||||
GLmethod.createShader = i++; //30
|
||||
GLmethod.createTexture = i++;
|
||||
GLmethod.cullFace = i++;
|
||||
GLmethod.deleteBuffer = i++;
|
||||
GLmethod.deleteFramebuffer = i++;
|
||||
GLmethod.deleteProgram = i++;
|
||||
GLmethod.deleteRenderbuffer = i++;
|
||||
GLmethod.deleteShader = i++;
|
||||
GLmethod.deleteTexture = i++;
|
||||
GLmethod.depthFunc = i++;
|
||||
GLmethod.depthMask = i++; //40
|
||||
GLmethod.depthRange = i++;
|
||||
GLmethod.detachShader = i++;
|
||||
GLmethod.disable = i++;
|
||||
GLmethod.disableVertexAttribArray = i++;
|
||||
GLmethod.drawArrays = i++;
|
||||
GLmethod.drawArraysInstancedANGLE = i++;
|
||||
GLmethod.drawElements = i++;
|
||||
GLmethod.drawElementsInstancedANGLE = i++;
|
||||
GLmethod.enable = i++;
|
||||
GLmethod.enableVertexAttribArray = i++; //50
|
||||
GLmethod.flush = i++;
|
||||
GLmethod.framebufferRenderbuffer = i++;
|
||||
GLmethod.framebufferTexture2D = i++;
|
||||
GLmethod.frontFace = i++;
|
||||
GLmethod.generateMipmap = i++;
|
||||
GLmethod.getActiveAttrib = i++;
|
||||
GLmethod.getActiveUniform = i++;
|
||||
GLmethod.getAttachedShaders = i++;
|
||||
GLmethod.getAttribLocation = i++;
|
||||
GLmethod.getBufferParameter = i++; //60
|
||||
GLmethod.getContextAttributes = i++;
|
||||
GLmethod.getError = i++;
|
||||
GLmethod.getExtension = i++;
|
||||
GLmethod.getFramebufferAttachmentParameter = i++;
|
||||
GLmethod.getParameter = i++;
|
||||
GLmethod.getProgramInfoLog = i++;
|
||||
GLmethod.getProgramParameter = i++;
|
||||
GLmethod.getRenderbufferParameter = i++;
|
||||
GLmethod.getShaderInfoLog = i++;
|
||||
GLmethod.getShaderParameter = i++; //70
|
||||
GLmethod.getShaderPrecisionFormat = i++;
|
||||
GLmethod.getShaderSource = i++;
|
||||
GLmethod.getSupportedExtensions = i++;
|
||||
GLmethod.getTexParameter = i++;
|
||||
GLmethod.getUniform = i++;
|
||||
GLmethod.getUniformLocation = i++;
|
||||
GLmethod.getVertexAttrib = i++;
|
||||
GLmethod.getVertexAttribOffset = i++;
|
||||
GLmethod.isBuffer = i++;
|
||||
GLmethod.isContextLost = i++; //80
|
||||
GLmethod.isEnabled = i++;
|
||||
GLmethod.isFramebuffer = i++;
|
||||
GLmethod.isProgram = i++;
|
||||
GLmethod.isRenderbuffer = i++;
|
||||
GLmethod.isShader = i++;
|
||||
GLmethod.isTexture = i++;
|
||||
GLmethod.lineWidth = i++;
|
||||
GLmethod.linkProgram = i++;
|
||||
GLmethod.pixelStorei = i++;
|
||||
GLmethod.polygonOffset = i++; //90
|
||||
GLmethod.readPixels = i++;
|
||||
GLmethod.renderbufferStorage = i++;
|
||||
GLmethod.sampleCoverage = i++;
|
||||
GLmethod.scissor = i++;
|
||||
GLmethod.shaderSource = i++;
|
||||
GLmethod.stencilFunc = i++;
|
||||
GLmethod.stencilFuncSeparate = i++;
|
||||
GLmethod.stencilMask = i++;
|
||||
GLmethod.stencilMaskSeparate = i++;
|
||||
GLmethod.stencilOp = i++; //100
|
||||
GLmethod.stencilOpSeparate = i++;
|
||||
GLmethod.texImage2D = i++;
|
||||
GLmethod.texParameterf = i++;
|
||||
GLmethod.texParameteri = i++;
|
||||
GLmethod.texSubImage2D = i++;
|
||||
GLmethod.uniform1f = i++;
|
||||
GLmethod.uniform1fv = i++;
|
||||
GLmethod.uniform1i = i++;
|
||||
GLmethod.uniform1iv = i++;
|
||||
GLmethod.uniform2f = i++; //110
|
||||
GLmethod.uniform2fv = i++;
|
||||
GLmethod.uniform2i = i++;
|
||||
GLmethod.uniform2iv = i++;
|
||||
GLmethod.uniform3f = i++;
|
||||
GLmethod.uniform3fv = i++;
|
||||
GLmethod.uniform3i = i++;
|
||||
GLmethod.uniform3iv = i++;
|
||||
GLmethod.uniform4f = i++;
|
||||
GLmethod.uniform4fv = i++;
|
||||
GLmethod.uniform4i = i++; //120
|
||||
GLmethod.uniform4iv = i++;
|
||||
GLmethod.uniformMatrix2fv = i++;
|
||||
GLmethod.uniformMatrix3fv = i++;
|
||||
GLmethod.uniformMatrix4fv = i++;
|
||||
GLmethod.useProgram = i++;
|
||||
GLmethod.validateProgram = i++;
|
||||
GLmethod.vertexAttrib1f = i++; //new
|
||||
GLmethod.vertexAttrib2f = i++; //new
|
||||
GLmethod.vertexAttrib3f = i++; //new
|
||||
GLmethod.vertexAttrib4f = i++; //new //130
|
||||
GLmethod.vertexAttrib1fv = i++; //new
|
||||
GLmethod.vertexAttrib2fv = i++; //new
|
||||
GLmethod.vertexAttrib3fv = i++; //new
|
||||
GLmethod.vertexAttrib4fv = i++; //new
|
||||
GLmethod.vertexAttribPointer = i++;
|
||||
GLmethod.viewport = i++;
|
||||
|
||||
export default GLmethod;
|
@ -1,23 +0,0 @@
|
||||
const GLtype = {};
|
||||
|
||||
[
|
||||
"GLbitfield",
|
||||
"GLboolean",
|
||||
"GLbyte",
|
||||
"GLclampf",
|
||||
"GLenum",
|
||||
"GLfloat",
|
||||
"GLint",
|
||||
"GLintptr",
|
||||
"GLsizei",
|
||||
"GLsizeiptr",
|
||||
"GLshort",
|
||||
"GLubyte",
|
||||
"GLuint",
|
||||
"GLushort"
|
||||
].sort().map((typeName, i) => GLtype[typeName] = 1 >> (i + 1));
|
||||
|
||||
export default GLtype;
|
||||
|
||||
|
||||
|
@ -1,21 +0,0 @@
|
||||
import {getTransferedObjectUUID} from './classUtils';
|
||||
|
||||
const name = 'WebGLProgram';
|
||||
|
||||
function uuid(id) {
|
||||
return getTransferedObjectUUID(name, id);
|
||||
}
|
||||
|
||||
export default class WebGLProgram {
|
||||
className = name;
|
||||
|
||||
constructor(id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
static uuid = uuid;
|
||||
|
||||
uuid() {
|
||||
return uuid(this.id);
|
||||
}
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
import {getTransferedObjectUUID} from './classUtils';
|
||||
|
||||
const name = 'WebGLRenderBuffer';
|
||||
|
||||
function uuid(id) {
|
||||
return getTransferedObjectUUID(name, id);
|
||||
}
|
||||
|
||||
export default class WebGLRenderbuffer {
|
||||
className = name;
|
||||
|
||||
constructor(id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
static uuid = uuid;
|
||||
|
||||
uuid() {
|
||||
return uuid(this.id);
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,22 +0,0 @@
|
||||
import {getTransferedObjectUUID} from './classUtils';
|
||||
|
||||
const name = 'WebGLShader';
|
||||
|
||||
function uuid(id) {
|
||||
return getTransferedObjectUUID(name, id);
|
||||
}
|
||||
|
||||
export default class WebGLShader {
|
||||
className = name;
|
||||
|
||||
constructor(id, type) {
|
||||
this.id = id;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
static uuid = uuid;
|
||||
|
||||
uuid() {
|
||||
return uuid(this.id);
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
export default class WebGLShaderPrecisionFormat {
|
||||
className = 'WebGLShaderPrecisionFormat';
|
||||
|
||||
constructor({
|
||||
rangeMin, rangeMax, precision
|
||||
}) {
|
||||
this.rangeMin = rangeMin;
|
||||
this.rangeMax = rangeMax;
|
||||
this.precision = precision;
|
||||
}
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
import {getTransferedObjectUUID} from './classUtils';
|
||||
|
||||
const name = 'WebGLTexture';
|
||||
|
||||
function uuid(id) {
|
||||
return getTransferedObjectUUID(name, id);
|
||||
}
|
||||
|
||||
export default class WebGLTexture {
|
||||
className = name;
|
||||
|
||||
constructor(id, type) {
|
||||
this.id = id;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
static uuid = uuid;
|
||||
|
||||
uuid() {
|
||||
return uuid(this.id);
|
||||
}
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
import {getTransferedObjectUUID} from './classUtils';
|
||||
|
||||
const name = 'WebGLUniformLocation';
|
||||
|
||||
function uuid(id) {
|
||||
return getTransferedObjectUUID(name, id);
|
||||
}
|
||||
|
||||
export default class WebGLUniformLocation {
|
||||
className = name;
|
||||
|
||||
constructor(id, type) {
|
||||
this.id = id;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
static uuid = uuid;
|
||||
|
||||
uuid() {
|
||||
return uuid(this.id);
|
||||
}
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
export function getTransferedObjectUUID(name, id) {
|
||||
return `${name.toLowerCase()}-${id}`;
|
||||
}
|
@ -1,74 +0,0 @@
|
||||
import GContext2D from '../context-2d/RenderingContext';
|
||||
import GContextWebGL from '../context-webgl/RenderingContext';
|
||||
|
||||
export default class GCanvas {
|
||||
|
||||
// static GBridge = null;
|
||||
|
||||
id = null;
|
||||
|
||||
_needRender = true;
|
||||
|
||||
constructor(id, { disableAutoSwap }) {
|
||||
this.id = id;
|
||||
|
||||
this._disableAutoSwap = disableAutoSwap;
|
||||
if (disableAutoSwap) {
|
||||
this._swapBuffers = () => {
|
||||
GCanvas.GBridge.render(this.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getContext(type) {
|
||||
|
||||
let context = null;
|
||||
|
||||
if (type.match(/webgl/i)) {
|
||||
context = new GContextWebGL(this);
|
||||
|
||||
context.componentId = this.id;
|
||||
|
||||
if (!this._disableAutoSwap) {
|
||||
const render = () => {
|
||||
if (this._needRender) {
|
||||
GCanvas.GBridge.render(this.id);
|
||||
this._needRender = false;
|
||||
}
|
||||
}
|
||||
setInterval(render, 16);
|
||||
}
|
||||
|
||||
GCanvas.GBridge.callSetContextType(this.id, 1); // 0 for 2d; 1 for webgl
|
||||
} else if (type.match(/2d/i)) {
|
||||
context = new GContext2D(this);
|
||||
|
||||
context.componentId = this.id;
|
||||
|
||||
// const render = ( callback ) => {
|
||||
//
|
||||
// const commands = context._drawCommands;
|
||||
// context._drawCommands = '';
|
||||
//
|
||||
// GCanvas.GBridge.render2d(this.id, commands, callback);
|
||||
// this._needRender = false;
|
||||
// }
|
||||
// //draw方法触发
|
||||
// context._flush = render;
|
||||
// //setInterval(render, 16);
|
||||
|
||||
GCanvas.GBridge.callSetContextType(this.id, 0);
|
||||
} else {
|
||||
throw new Error('not supported context ' + type);
|
||||
}
|
||||
|
||||
return context;
|
||||
|
||||
}
|
||||
|
||||
reset() {
|
||||
GCanvas.GBridge.callReset(this.id);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,96 +0,0 @@
|
||||
let incId = 1;
|
||||
|
||||
const noop = function () { };
|
||||
|
||||
class GImage {
|
||||
|
||||
static GBridge = null;
|
||||
|
||||
constructor() {
|
||||
this._id = incId++;
|
||||
this._width = 0;
|
||||
this._height = 0;
|
||||
this._src = undefined;
|
||||
this._onload = noop;
|
||||
this._onerror = noop;
|
||||
this.complete = false;
|
||||
}
|
||||
|
||||
get width() {
|
||||
return this._width;
|
||||
}
|
||||
set width(v) {
|
||||
this._width = v;
|
||||
}
|
||||
|
||||
get height() {
|
||||
return this._height;
|
||||
}
|
||||
|
||||
set height(v) {
|
||||
this._height = v;
|
||||
}
|
||||
|
||||
get src() {
|
||||
return this._src;
|
||||
}
|
||||
|
||||
set src(v) {
|
||||
|
||||
if (v.startsWith('//')) {
|
||||
v = 'http:' + v;
|
||||
}
|
||||
|
||||
this._src = v;
|
||||
|
||||
GImage.GBridge.perloadImage([this._src, this._id], (data) => {
|
||||
if (typeof data === 'string') {
|
||||
data = JSON.parse(data);
|
||||
}
|
||||
if (data.error) {
|
||||
var evt = { type: 'error', target: this };
|
||||
this.onerror(evt);
|
||||
} else {
|
||||
this.complete = true;
|
||||
this.width = typeof data.width === 'number' ? data.width : 0;
|
||||
this.height = typeof data.height === 'number' ? data.height : 0;
|
||||
var evt = { type: 'load', target: this };
|
||||
this.onload(evt);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
addEventListener(name, listener) {
|
||||
if (name === 'load') {
|
||||
this.onload = listener;
|
||||
} else if (name === 'error') {
|
||||
this.onerror = listener;
|
||||
}
|
||||
}
|
||||
|
||||
removeEventListener(name, listener) {
|
||||
if (name === 'load') {
|
||||
this.onload = noop;
|
||||
} else if (name === 'error') {
|
||||
this.onerror = noop;
|
||||
}
|
||||
}
|
||||
|
||||
get onload() {
|
||||
return this._onload;
|
||||
}
|
||||
|
||||
set onload(v) {
|
||||
this._onload = v;
|
||||
}
|
||||
|
||||
get onerror() {
|
||||
return this._onerror;
|
||||
}
|
||||
|
||||
set onerror(v) {
|
||||
this._onerror = v;
|
||||
}
|
||||
}
|
||||
|
||||
export default GImage;
|
@ -1,24 +0,0 @@
|
||||
|
||||
export function ArrayBufferToBase64 (buffer) {
|
||||
var binary = '';
|
||||
var bytes = new Uint8ClampedArray(buffer);
|
||||
for (var len = bytes.byteLength, i = 0; i < len; i++) {
|
||||
binary += String.fromCharCode(bytes[i]);
|
||||
}
|
||||
return btoa(binary);
|
||||
}
|
||||
|
||||
export function Base64ToUint8ClampedArray(base64String) {
|
||||
const padding = '='.repeat((4 - base64String.length % 4) % 4);
|
||||
const base64 = (base64String + padding)
|
||||
.replace(/\-/g, '+')
|
||||
.replace(/_/g, '/');
|
||||
|
||||
const rawData = atob(base64);
|
||||
const outputArray = new Uint8ClampedArray(rawData.length);
|
||||
|
||||
for (let i = 0; i < rawData.length; ++i) {
|
||||
outputArray[i] = rawData.charCodeAt(i);
|
||||
}
|
||||
return outputArray;
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
import GCanvas from './env/canvas';
|
||||
import GImage from './env/image';
|
||||
|
||||
import GWebGLRenderingContext from './context-webgl/RenderingContext';
|
||||
import GContext2D from './context-2d/RenderingContext';
|
||||
|
||||
import GBridgeWeex from './bridge/bridge-weex';
|
||||
|
||||
export let Image = GImage;
|
||||
|
||||
export let WeexBridge = GBridgeWeex;
|
||||
|
||||
export function enable(el, { bridge, debug, disableAutoSwap, disableComboCommands } = {}) {
|
||||
|
||||
const GBridge = GImage.GBridge = GCanvas.GBridge = GWebGLRenderingContext.GBridge = GContext2D.GBridge = bridge;
|
||||
|
||||
GBridge.callEnable(el.ref, [
|
||||
0, // renderMode: 0--RENDERMODE_WHEN_DIRTY, 1--RENDERMODE_CONTINUOUSLY
|
||||
-1, // hybridLayerType: 0--LAYER_TYPE_NONE 1--LAYER_TYPE_SOFTWARE 2--LAYER_TYPE_HARDWARE
|
||||
false, // supportScroll
|
||||
false, // newCanvasMode
|
||||
1, // compatible
|
||||
'white',// clearColor
|
||||
false // sameLevel: newCanvasMode = true && true => GCanvasView and Webview is same level
|
||||
]);
|
||||
|
||||
if (debug === true) {
|
||||
GBridge.callEnableDebug();
|
||||
}
|
||||
if (disableComboCommands) {
|
||||
GBridge.callEnableDisableCombo();
|
||||
}
|
||||
|
||||
var canvas = new GCanvas(el.ref, { disableAutoSwap });
|
||||
canvas.width = el.style.width;
|
||||
canvas.height = el.style.height;
|
||||
|
||||
return canvas;
|
||||
};
|
@ -1,85 +0,0 @@
|
||||
export default {
|
||||
props: {
|
||||
//二维码内容
|
||||
value: {
|
||||
type: [String, Number]
|
||||
},
|
||||
//选项
|
||||
options: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
//二维码大小
|
||||
size: {
|
||||
type: [String, Number],
|
||||
default: 200
|
||||
},
|
||||
//导出的文件类型
|
||||
fileType: {
|
||||
type: String,
|
||||
default: 'png'
|
||||
},
|
||||
//是否初始化组件后就开始生成
|
||||
start: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
//是否数据发生改变自动重绘
|
||||
auto: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
//隐藏组件
|
||||
hide: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
/**
|
||||
* canvas 类型,微信小程序默认使用2d,非2d微信官方已放弃维护,问题比较多
|
||||
* 注意:微信小程序type2d手机上正常,PC上微信内打开小程序toDataURL报错,看后期微信官方团队会不会做兼容,不兼容的话只能在自行判断在PC使用非2d,或者直接提示用户请在手机上操作,微信团队的海报中心小程序就是这么做的
|
||||
*/
|
||||
type: {
|
||||
type: String,
|
||||
default: () => {
|
||||
// #ifdef MP-WEIXIN
|
||||
return '2d';
|
||||
// #endif
|
||||
// #ifndef MP-WEIXIN
|
||||
return 'normal';
|
||||
// #endif
|
||||
}
|
||||
},
|
||||
//队列绘制,主要针对NVue端
|
||||
queue: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
//是否队列加载图片,可减少canvas发起的网络资源请求,节省服务器资源
|
||||
isQueueLoadImage: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
//loading态
|
||||
loading: {
|
||||
type: Boolean,
|
||||
default: undefined
|
||||
},
|
||||
//H5保存即自动下载(在支持的环境下),默认false为仅弹层提示用户需要长按图片保存,不会自动下载
|
||||
h5SaveIsDownload: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
//H5下载名称
|
||||
h5DownloadName: {
|
||||
type: String,
|
||||
default: 'uvQRCode'
|
||||
},
|
||||
// H5保存二维码时候是否显示提示
|
||||
h5SaveTip: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because one or more lines are too long
@ -1,41 +0,0 @@
|
||||
function Queue() {
|
||||
let waitingQueue = this.waitingQueue = [];
|
||||
let isRunning = this.isRunning = false; // 记录是否有未完成的任务
|
||||
|
||||
function execute(task, resolve, reject) {
|
||||
task()
|
||||
.then((data) => {
|
||||
resolve(data);
|
||||
})
|
||||
.catch((e) => {
|
||||
reject(e);
|
||||
})
|
||||
.finally(() => {
|
||||
// 等待任务队列中如果有任务,则触发它;否则设置isRunning = false,表示无任务状态
|
||||
if (waitingQueue.length) {
|
||||
const next = waitingQueue.shift();
|
||||
execute(next.task, next.resolve, next.reject);
|
||||
} else {
|
||||
isRunning = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
this.exec = function(task) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (isRunning) {
|
||||
waitingQueue.push({
|
||||
task,
|
||||
resolve,
|
||||
reject
|
||||
});
|
||||
} else {
|
||||
isRunning = true;
|
||||
execute(task, resolve, reject);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/* 队列实例,某些平台一起使用多个组件时需要通过队列逐一绘制,否则部分绘制方法异常,nvue端的iOS gcanvas尤其明显,在不通过队列绘制时会出现图片丢失的情况 */
|
||||
export const queueDraw = new Queue();
|
||||
export const queueLoadImage = new Queue();
|
File diff suppressed because one or more lines are too long
@ -1,87 +0,0 @@
|
||||
{
|
||||
"id": "uv-qrcode",
|
||||
"displayName": "uv-qrcode 二维码 全面兼容vue3+2、app、h5、小程序等多端",
|
||||
"version": "1.0.4",
|
||||
"description": "该组件是超级强大二维码生成功能,可扩展性高。自定义二维码样式,如随机颜色、圆点、方块、块与块之间的间距等等,具体请查看文档。",
|
||||
"keywords": [
|
||||
"uv-qrcode",
|
||||
"qrcode",
|
||||
"uvui",
|
||||
"uv-ui",
|
||||
"二维码"
|
||||
],
|
||||
"repository": "",
|
||||
"engines": {
|
||||
"HBuilderX": "^3.1.0"
|
||||
},
|
||||
"dcloudext": {
|
||||
"type": "component-vue",
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "插件不采集任何数据",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": ""
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": [
|
||||
"uv-ui-tools"
|
||||
],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y"
|
||||
},
|
||||
"client": {
|
||||
"Vue": {
|
||||
"vue2": "y",
|
||||
"vue3": "y"
|
||||
},
|
||||
"App": {
|
||||
"app-vue": "y",
|
||||
"app-nvue": "y"
|
||||
},
|
||||
"H5-mobile": {
|
||||
"Safari": "y",
|
||||
"Android Browser": "y",
|
||||
"微信浏览器(Android)": "y",
|
||||
"QQ浏览器(Android)": "y"
|
||||
},
|
||||
"H5-pc": {
|
||||
"Chrome": "y",
|
||||
"IE": "y",
|
||||
"Edge": "y",
|
||||
"Firefox": "y",
|
||||
"Safari": "y"
|
||||
},
|
||||
"小程序": {
|
||||
"微信": "y",
|
||||
"阿里": "y",
|
||||
"百度": "y",
|
||||
"字节跳动": "y",
|
||||
"QQ": "y",
|
||||
"钉钉": "u",
|
||||
"快手": "u",
|
||||
"飞书": "u",
|
||||
"京东": "u"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "u",
|
||||
"联盟": "u"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
## QRCode 二维码生成器
|
||||
|
||||
> **组件名:uv-qrcode**
|
||||
|
||||
超级强大二维码生成组件,可扩展性高。自定义二维码样式,如随机颜色、圆点、方块、块与块之间的间距等等,具体请在下方查看文档。
|
||||
|
||||
灵活配置,开箱即用,文档全面,支持自定义二维码风格。
|
||||
|
||||
# <a href="https://www.uvui.cn/components/qrcode.html" target="_blank">查看文档</a>
|
||||
|
||||
## [下载完整示例项目](https://ext.dcloud.net.cn/plugin?name=uv-ui) <small style="font-size:14px;">(请不要 下载插件ZIP)</small>
|
||||
|
||||
### [更多插件,请关注uv-ui组件库](https://ext.dcloud.net.cn/plugin?name=uv-ui)
|
||||
|
||||
<a href="https://ext.dcloud.net.cn/plugin?name=uv-ui" target="_blank">
|
||||
|
||||

|
||||
|
||||
</a>
|
||||
|
||||
#### 如使用过程中有任何问题反馈,或者您对uv-ui有一些好的建议,欢迎加入uv-ui官方交流群:<a href="https://www.uvui.cn/components/addQQGroup.html" target="_blank">官方QQ群</a>
|
@ -1,10 +0,0 @@
|
||||
## 1.0.3(2023-06-29)
|
||||
1. 增加customStyle参数,方便设置样式
|
||||
## 1.0.2(2023-06-29)
|
||||
1. 新增title自定义
|
||||
2. 完善文档说明
|
||||
## 1.0.1(2023-05-16)
|
||||
1. 优化组件依赖,修改后无需全局引入,组件导入即可使用
|
||||
2. 优化部分功能
|
||||
## 1.0.0(2023-05-10)
|
||||
uv-steps 步骤条
|
@ -1,25 +0,0 @@
|
||||
export default {
|
||||
props: {
|
||||
// 标题
|
||||
title: {
|
||||
type: [String, Number],
|
||||
default: ''
|
||||
},
|
||||
// 描述文本
|
||||
desc: {
|
||||
type: [String, Number],
|
||||
default: ''
|
||||
},
|
||||
// 图标大小
|
||||
iconSize: {
|
||||
type: [String, Number],
|
||||
default: 17
|
||||
},
|
||||
// 当前步骤是否处于失败状态
|
||||
error: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
...uni.$uv?.props?.stepsItem
|
||||
}
|
||||
}
|
@ -1,347 +0,0 @@
|
||||
<template>
|
||||
<view
|
||||
class="uv-steps-item"
|
||||
ref="uv-steps-item"
|
||||
:class="[`uv-steps-item--${parentData.direction}`]"
|
||||
:style="[$uv.addStyle(customStyle)]"
|
||||
>
|
||||
<view
|
||||
class="uv-steps-item__line"
|
||||
v-if="index + 1 < childLength"
|
||||
:class="[`uv-steps-item__line--${parentData.direction}`]"
|
||||
:style="[lineStyle]">
|
||||
</view>
|
||||
<view
|
||||
:class="[
|
||||
'uv-steps-item__wrapper',
|
||||
`uv-steps-item__wrapper--${parentData.direction}`,
|
||||
parentData.dot && `uv-steps-item__wrapper--${parentData.direction}--dot`
|
||||
]">
|
||||
<slot name="icon">
|
||||
<view
|
||||
class="uv-steps-item__wrapper__dot"
|
||||
v-if="parentData.dot"
|
||||
:style="{
|
||||
backgroundColor: statusColor
|
||||
}">
|
||||
</view>
|
||||
<view
|
||||
class="uv-steps-item__wrapper__icon"
|
||||
v-else-if="parentData.activeIcon || parentData.inactiveIcon">
|
||||
<uv-icon
|
||||
:name="index <= parentData.current ? parentData.activeIcon : parentData.inactiveIcon"
|
||||
:size="iconSize"
|
||||
:color="index <= parentData.current ? parentData.activeColor : parentData.inactiveColor">
|
||||
</uv-icon>
|
||||
</view>
|
||||
<view
|
||||
v-else
|
||||
:style="{
|
||||
backgroundColor: statusClass === 'process' ? parentData.activeColor : 'transparent',
|
||||
borderColor: statusColor
|
||||
}"
|
||||
class="uv-steps-item__wrapper__circle">
|
||||
<text
|
||||
v-if="statusClass === 'process' || statusClass === 'wait'"
|
||||
class="uv-steps-item__wrapper__circle__text"
|
||||
:style="{
|
||||
color: index == parentData.current ? '#ffffff' : parentData.inactiveColor
|
||||
}">{{ index + 1}}</text>
|
||||
<uv-icon
|
||||
v-else
|
||||
:color="statusClass === 'error' ? 'error' : parentData.activeColor"
|
||||
size="12"
|
||||
:name="statusClass === 'error' ? 'close' : 'checkmark'">
|
||||
</uv-icon>
|
||||
</view>
|
||||
</slot>
|
||||
</view>
|
||||
<view
|
||||
:class="[
|
||||
'uv-steps-item__content',
|
||||
`uv-steps-item__content--${parentData.direction}`
|
||||
]"
|
||||
:style="[contentStyle]"
|
||||
>
|
||||
<slot name="title">
|
||||
<uv-text
|
||||
:text="title"
|
||||
:type="parentData.current == index ? 'main' : 'content'"
|
||||
lineHeight="20px"
|
||||
:size="parentData.current == index ? 14 : 13"
|
||||
></uv-text>
|
||||
</slot>
|
||||
<slot name="desc">
|
||||
<uv-text
|
||||
:text="desc"
|
||||
type="tips"
|
||||
size="12"
|
||||
></uv-text>
|
||||
</slot>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import mpMixin from '@/uni_modules/uv-ui-tools/libs/mixin/mpMixin.js'
|
||||
import mixin from '@/uni_modules/uv-ui-tools/libs/mixin/mixin.js'
|
||||
import props from './props.js';
|
||||
// #ifdef APP-NVUE
|
||||
const dom = uni.requireNativePlugin('dom')
|
||||
// #endif
|
||||
/**
|
||||
* StepsItem 步骤条的子组件
|
||||
* @description 本组件需要和uv-steps配合使用
|
||||
* @tutorial https://www.uvui.cn/components/steps.html
|
||||
* @property {String} title 标题文字
|
||||
* @property {String} current 描述文本
|
||||
* @property {String | Number} iconSize 图标大小 (默认 17 )
|
||||
* @property {Boolean} error 当前步骤是否处于失败状态 (默认 false )
|
||||
* @example <uv-steps current="0"><uv-steps-item title="已出库" desc="10:35" ></uv-steps-item></uv-steps>
|
||||
*/
|
||||
export default {
|
||||
name: 'uv-steps-item',
|
||||
mixins: [mpMixin, mixin, props],
|
||||
data() {
|
||||
return {
|
||||
index: 0,
|
||||
childLength: 0,
|
||||
showLine: false,
|
||||
size: {
|
||||
height: 0,
|
||||
width: 0
|
||||
},
|
||||
parentData: {
|
||||
direction: 'row',
|
||||
current: 0,
|
||||
activeColor: '',
|
||||
inactiveColor: '',
|
||||
activeIcon: '',
|
||||
inactiveIcon: '',
|
||||
dot: false
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
'parentData'(newValue, oldValue) {}
|
||||
},
|
||||
created() {
|
||||
this.init()
|
||||
},
|
||||
computed: {
|
||||
lineStyle() {
|
||||
const style = {}
|
||||
if (this.parentData.direction === 'row') {
|
||||
style.width = this.size.width + 'px'
|
||||
style.left = this.size.width / 2 + 'px'
|
||||
} else {
|
||||
style.height = this.size.height + 'px'
|
||||
}
|
||||
style.backgroundColor = this.parent.children?.[this.index + 1]?.error ? '#f56c6c' : this.index < this.parentData.current ? this.parentData.activeColor : this.parentData.inactiveColor
|
||||
return style
|
||||
},
|
||||
statusClass() {
|
||||
const {
|
||||
index,
|
||||
error
|
||||
} = this
|
||||
const {
|
||||
current
|
||||
} = this.parentData
|
||||
if (current == index) {
|
||||
return error === true ? 'error' : 'process'
|
||||
} else if (error) {
|
||||
return 'error'
|
||||
} else if (current > index) {
|
||||
return 'finish'
|
||||
} else {
|
||||
return 'wait'
|
||||
}
|
||||
},
|
||||
statusColor() {
|
||||
let color = ''
|
||||
switch (this.statusClass) {
|
||||
case 'finish':
|
||||
color = this.parentData.activeColor
|
||||
break
|
||||
case 'error':
|
||||
color = '#f56c6c'
|
||||
break
|
||||
case 'process':
|
||||
color = this.parentData.dot ? this.parentData.activeColor : 'transparent'
|
||||
break
|
||||
default:
|
||||
color = this.parentData.inactiveColor
|
||||
break
|
||||
}
|
||||
return color
|
||||
},
|
||||
contentStyle() {
|
||||
const style = {}
|
||||
if (this.parentData.direction === 'column') {
|
||||
style.marginLeft = this.parentData.dot ? '2px' : '6px'
|
||||
style.marginTop = this.parentData.dot ? '0px' : '6px'
|
||||
} else {
|
||||
style.marginTop = this.parentData.dot ? '2px' : '6px'
|
||||
style.marginLeft = this.parentData.dot ? '2px' : '6px'
|
||||
}
|
||||
return style
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.parent && this.parent.updateFromChild()
|
||||
this.$uv.sleep().then(() => {
|
||||
this.getStepsItemRect()
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
// 初始化数据
|
||||
this.updateParentData()
|
||||
if (!this.parent) {
|
||||
return this.$uv.error('uv-steps-item必须要搭配uv-steps组件使用')
|
||||
}
|
||||
this.index = this.parent.children.indexOf(this)
|
||||
this.childLength = this.parent.children.length
|
||||
},
|
||||
updateParentData() {
|
||||
// 此方法在mixin中
|
||||
this.getParentData('uv-steps')
|
||||
},
|
||||
// 父组件数据发生变化
|
||||
updateFromParent() {
|
||||
this.init()
|
||||
},
|
||||
// 获取组件的尺寸,用于设置横线的位置
|
||||
getStepsItemRect() {
|
||||
// #ifndef APP-NVUE
|
||||
this.$uvGetRect('.uv-steps-item').then(size => {
|
||||
this.size = size
|
||||
})
|
||||
// #endif
|
||||
// #ifdef APP-NVUE
|
||||
dom.getComponentRect(this.$refs['uv-steps-item'], res => {
|
||||
const {
|
||||
size
|
||||
} = res
|
||||
this.size = size
|
||||
})
|
||||
// #endif
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '@/uni_modules/uv-ui-tools/libs/css/components.scss';
|
||||
@import '@/uni_modules/uv-ui-tools/libs/css/color.scss';
|
||||
.uv-steps-item {
|
||||
flex: 1;
|
||||
@include flex;
|
||||
|
||||
&--row {
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
&--column {
|
||||
position: relative;
|
||||
flex-direction: row;
|
||||
justify-content: flex-start;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
|
||||
&__wrapper {
|
||||
@include flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
background-color: #fff;
|
||||
|
||||
&--column {
|
||||
width: 20px;
|
||||
height: 32px;
|
||||
|
||||
&--dot {
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
&--row {
|
||||
width: 32px;
|
||||
height: 20px;
|
||||
|
||||
&--dot {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
&__circle {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
/* #ifndef APP-NVUE */
|
||||
box-sizing: border-box;
|
||||
flex-shrink: 0;
|
||||
/* #endif */
|
||||
border-radius: 100px;
|
||||
border-width: 1px;
|
||||
border-color: $uv-tips-color;
|
||||
border-style: solid;
|
||||
@include flex(row);
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: background-color 0.3s;
|
||||
|
||||
&__text {
|
||||
color: $uv-tips-color;
|
||||
font-size: 11px;
|
||||
@include flex(row);
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
line-height: 11px;
|
||||
}
|
||||
}
|
||||
|
||||
&__dot {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-radius: 100px;
|
||||
background-color: $uv-content-color;
|
||||
}
|
||||
}
|
||||
|
||||
&__content {
|
||||
@include flex;
|
||||
flex: 1;
|
||||
|
||||
&--row {
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
&--column {
|
||||
flex-direction: column;
|
||||
margin-left: 6px;
|
||||
}
|
||||
}
|
||||
|
||||
&__line {
|
||||
position: absolute;
|
||||
background: $uv-tips-color;
|
||||
|
||||
&--row {
|
||||
top: 10px;
|
||||
height: 1px;
|
||||
}
|
||||
|
||||
&--column {
|
||||
width: 1px;
|
||||
left: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@ -1,40 +0,0 @@
|
||||
export default {
|
||||
props: {
|
||||
// 排列方向
|
||||
direction: {
|
||||
type: String,
|
||||
default: 'row'
|
||||
},
|
||||
// 设置第几个步骤
|
||||
current: {
|
||||
type: [String, Number],
|
||||
default: 0
|
||||
},
|
||||
// 激活状态颜色
|
||||
activeColor: {
|
||||
type: String,
|
||||
default: '#3c9cff'
|
||||
},
|
||||
// 未激活状态颜色
|
||||
inactiveColor: {
|
||||
type: String,
|
||||
default: '#969799'
|
||||
},
|
||||
// 激活状态的图标
|
||||
activeIcon: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 未激活状态图标
|
||||
inactiveIcon: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 是否显示点类型
|
||||
dot: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
...uni.$uv?.props?.steps
|
||||
}
|
||||
}
|
@ -1,83 +0,0 @@
|
||||
<template>
|
||||
<view
|
||||
:class="['uv-steps',`uv-steps--${direction}`]"
|
||||
:style="[$uv.addStyle(customStyle)]"
|
||||
>
|
||||
<slot></slot>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { func } from '@/uni_modules/uv-ui-tools/libs/function/test.js'
|
||||
import mpMixin from '@/uni_modules/uv-ui-tools/libs/mixin/mpMixin.js'
|
||||
import mixin from '@/uni_modules/uv-ui-tools/libs/mixin/mixin.js'
|
||||
import props from './props.js';
|
||||
/**
|
||||
* Steps 步骤条
|
||||
* @description 该组件一般用于完成一个任务要分几个步骤,标识目前处于第几步的场景。
|
||||
* @tutorial https://www.uvui.cn/components/steps.html
|
||||
* @property {String} direction row-横向,column-竖向 (默认 'row' )
|
||||
* @property {String | Number} current 设置当前处于第几步 (默认 0 )
|
||||
* @property {String} activeColor 激活状态颜色 (默认 '#3c9cff' )
|
||||
* @property {String} inactiveColor 未激活状态颜色 (默认 '#969799' )
|
||||
* @property {String} activeIcon 激活状态的图标
|
||||
* @property {String} inactiveIcon 未激活状态图标
|
||||
* @property {Boolean} dot 是否显示点类型 (默认 false )
|
||||
* @example <uv-steps current="0"><uv-steps-item title="已出库" desc="10:35" ></uv-steps-item></uv-steps>
|
||||
*/
|
||||
export default {
|
||||
name: 'uv-steps',
|
||||
mixins: [mpMixin, mixin, props],
|
||||
data() {
|
||||
return {
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
children() {
|
||||
this.updateChildData()
|
||||
},
|
||||
parentData() {
|
||||
this.updateChildData()
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
// 监听参数的变化,通过watch中,手动去更新子组件的数据,否则子组件不会自动变化
|
||||
parentData() {
|
||||
return [this.current, this.direction, this.activeColor, this.inactiveColor, this.activeIcon, this.inactiveIcon, this.dot]
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 更新子组件的数据
|
||||
updateChildData() {
|
||||
this.children.map(child => {
|
||||
// 先判断子组件是否存在对应的方法
|
||||
func((child || {}).updateFromParent()) && child.updateFromParent()
|
||||
})
|
||||
},
|
||||
// 接受子组件的通知,去修改其他子组件的数据
|
||||
updateFromChild() {
|
||||
this.updateChildData()
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.children = []
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '@/uni_modules/uv-ui-tools/libs/css/components.scss';
|
||||
|
||||
.uv-steps {
|
||||
@include flex;
|
||||
|
||||
&--column {
|
||||
flex-direction: column
|
||||
}
|
||||
|
||||
&--row {
|
||||
flex-direction: row;
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -1,89 +0,0 @@
|
||||
{
|
||||
"id": "uv-steps",
|
||||
"displayName": "uv-steps 步骤条 全面兼容小程序、nvue、vue2、vue3等多端",
|
||||
"version": "1.0.3",
|
||||
"description": "步骤条组件一般用于完成一个任务要分几个步骤,标识目前处于第几步的场景。",
|
||||
"keywords": [
|
||||
"uv-steps",
|
||||
"uvui",
|
||||
"uv-ui",
|
||||
"steps",
|
||||
"步骤条"
|
||||
],
|
||||
"repository": "",
|
||||
"engines": {
|
||||
"HBuilderX": "^3.1.0"
|
||||
},
|
||||
"dcloudext": {
|
||||
"type": "component-vue",
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "插件不采集任何数据",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": ""
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": [
|
||||
"uv-ui-tools",
|
||||
"uv-icon",
|
||||
"uv-text"
|
||||
],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y"
|
||||
},
|
||||
"client": {
|
||||
"Vue": {
|
||||
"vue2": "y",
|
||||
"vue3": "y"
|
||||
},
|
||||
"App": {
|
||||
"app-vue": "y",
|
||||
"app-nvue": "n"
|
||||
},
|
||||
"H5-mobile": {
|
||||
"Safari": "y",
|
||||
"Android Browser": "y",
|
||||
"微信浏览器(Android)": "y",
|
||||
"QQ浏览器(Android)": "y"
|
||||
},
|
||||
"H5-pc": {
|
||||
"Chrome": "y",
|
||||
"IE": "y",
|
||||
"Edge": "y",
|
||||
"Firefox": "y",
|
||||
"Safari": "y"
|
||||
},
|
||||
"小程序": {
|
||||
"微信": "y",
|
||||
"阿里": "y",
|
||||
"百度": "y",
|
||||
"字节跳动": "y",
|
||||
"QQ": "y",
|
||||
"钉钉": "u",
|
||||
"快手": "u",
|
||||
"飞书": "u",
|
||||
"京东": "u"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "u",
|
||||
"联盟": "u"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
## Steps 步骤条
|
||||
|
||||
> **组件名:uv-steps**
|
||||
|
||||
该组件一般用于完成一个任务要分几个步骤,标识目前处于第几步的场景。
|
||||
|
||||
### <a href="https://www.uvui.cn/components/steps.html" target="_blank">查看文档</a>
|
||||
|
||||
### [完整示例项目下载 | 关注更多组件](https://ext.dcloud.net.cn/plugin?name=uv-ui)
|
||||
|
||||
#### 如使用过程中有任何问题,或者您对uv-ui有一些好的建议,欢迎加入 uv-ui 交流群:<a href="https://ext.dcloud.net.cn/plugin?id=12287" target="_blank">uv-ui</a>、<a href="https://www.uvui.cn/components/addQQGroup.html" target="_blank">官方QQ群</a>
|
@ -1,11 +0,0 @@
|
||||
## 1.0.4(2023-10-13)
|
||||
1. 优化
|
||||
## 1.0.3(2023-10-13)
|
||||
1. unmounted兼容vue3
|
||||
## 1.0.2(2023-05-27)
|
||||
1. 不支持抖音小程序说明
|
||||
## 1.0.1(2023-05-16)
|
||||
1. 优化组件依赖,修改后无需全局引入,组件导入即可使用
|
||||
2. 优化部分功能
|
||||
## 1.0.0(2023-05-10)
|
||||
uv-swipe-action 滑动单元格
|
@ -1,256 +0,0 @@
|
||||
/**
|
||||
* 此为wxs模块,只支持APP-VUE,微信和QQ小程序以及H5平台
|
||||
* wxs内部不支持es6语法,变量只能使用var定义,无法使用解构,箭头函数等特性
|
||||
*/
|
||||
|
||||
// 开始触摸
|
||||
function touchstart(event, ownerInstance) {
|
||||
// 触发事件的组件的ComponentDescriptor实例
|
||||
var instance = event.instance
|
||||
// wxs内的局部变量快照,此快照是属于整个组件的,在touchstart和touchmove事件中都能获取到相同的结果
|
||||
var state = instance.getState()
|
||||
if (state.disable) return
|
||||
var touches = event.touches
|
||||
// 如果进行的是多指触控,不允许进行操作
|
||||
if (touches && touches.length > 1) return
|
||||
// 标识当前为滑动中状态
|
||||
state.moving = true
|
||||
// 记录触摸开始点的坐标值
|
||||
state.startX = touches[0].pageX
|
||||
state.startY = touches[0].pageY
|
||||
}
|
||||
|
||||
// 触摸滑动
|
||||
function touchmove(event, ownerInstance) {
|
||||
// 触发事件的组件的ComponentDescriptor实例
|
||||
var instance = event.instance
|
||||
// wxs内的局部变量快照
|
||||
var state = instance.getState()
|
||||
if (state.disabled || !state.moving) return
|
||||
|
||||
var touches = event.touches
|
||||
var pageX = touches[0].pageX
|
||||
var pageY = touches[0].pageY
|
||||
var moveX = pageX - state.startX
|
||||
var moveY = pageY - state.startY
|
||||
var buttonsWidth = state.buttonsWidth
|
||||
|
||||
// 移动的X轴距离大于Y轴距离,也即终点与起点位置连线,与X轴夹角小于45度时,禁止页面滚动
|
||||
if (Math.abs(moveX) > Math.abs(moveY) || Math.abs(moveX) > state.threshold) {
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
}
|
||||
// 如果移动的X轴距离小于Y轴距离,也即终点位置与起点位置连线,与Y轴夹角小于45度时,认为是页面上下滑动,而不是左右滑动单元格
|
||||
if (Math.abs(moveX) < Math.abs(moveY)) return
|
||||
|
||||
// 限制右滑的距离,不允许内容部分往右偏移,右滑会导致X轴偏移值大于0,以此做判断
|
||||
// 此处不能直接return,因为滑动过程中会缺失某些关键点坐标,会导致错乱,最好的办法就是
|
||||
// 在超出后,设置为0
|
||||
if (state.status === 'open') {
|
||||
// 在开启状态下,向左滑动,需忽略
|
||||
if (moveX < 0) moveX = 0
|
||||
// 想要收起菜单,最大能移动的距离为按钮的总宽度
|
||||
if (moveX > buttonsWidth) moveX = buttonsWidth
|
||||
// 如果是已经打开了的状态,向左滑动时,移动收起菜单
|
||||
moveSwipeAction(-buttonsWidth + moveX, instance, ownerInstance)
|
||||
} else {
|
||||
// 关闭状态下,右滑动需忽略
|
||||
if (moveX > 0) moveX = 0
|
||||
// 滑动的距离不允许超过所有按钮的总宽度,此时只能是左滑,最终设置按钮的总宽度,同时为负数
|
||||
if (Math.abs(moveX) > buttonsWidth) moveX = -buttonsWidth
|
||||
// 只要是在滑过程中,就不断移动菜单的内容部分,从而使隐藏的菜单显示出来
|
||||
moveSwipeAction(moveX, instance, ownerInstance)
|
||||
}
|
||||
}
|
||||
|
||||
// 触摸结束
|
||||
function touchend(event, ownerInstance) {
|
||||
// 触发事件的组件的ComponentDescriptor实例
|
||||
var instance = event.instance
|
||||
// wxs内的局部变量快照
|
||||
var state = instance.getState()
|
||||
if (!state.moving || state.disabled) return
|
||||
var touches = event.changedTouches ? event.changedTouches[0] : {}
|
||||
var pageX = touches.pageX
|
||||
var pageY = touches.pageY
|
||||
var moveX = pageX - state.startX
|
||||
if (state.status === 'open') {
|
||||
// 在展开的状态下,继续左滑,无需操作
|
||||
if (moveX < 0) return
|
||||
// 在开启状态下,点击一下内容区域,moveX为0,也即没有进行移动,这时执行收起菜单逻辑
|
||||
if (moveX === 0) {
|
||||
return closeSwipeAction(instance, ownerInstance)
|
||||
}
|
||||
// 在开启状态下,滑动距离小于阈值,则默认为不关闭,同时恢复原来的打开状态
|
||||
if (Math.abs(moveX) < state.threshold) {
|
||||
openSwipeAction(instance, ownerInstance)
|
||||
} else {
|
||||
// 如果滑动距离大于阈值,则执行收起逻辑
|
||||
closeSwipeAction(instance, ownerInstance)
|
||||
}
|
||||
} else {
|
||||
// 在关闭的状态下,右滑,无需操作
|
||||
if (moveX > 0) return
|
||||
// 理由同上
|
||||
if (Math.abs(moveX) < state.threshold) {
|
||||
closeSwipeAction(instance, ownerInstance)
|
||||
} else {
|
||||
openSwipeAction(instance, ownerInstance)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 获取过渡时间
|
||||
function getDuration(value) {
|
||||
if (value.toString().indexOf('s') >= 0) return value
|
||||
return value > 30 ? value + 'ms' : value + 's'
|
||||
}
|
||||
|
||||
// 滑动结束时判断滑动的方向
|
||||
function getMoveDirection(instance, ownerInstance) {
|
||||
var state = instance.getState()
|
||||
}
|
||||
|
||||
// 移动滑动选择器内容区域,同时显示出其隐藏的菜单
|
||||
function moveSwipeAction(moveX, instance, ownerInstance) {
|
||||
var state = instance.getState()
|
||||
// 获取所有按钮的实例,需要通过它去设置按钮的位移
|
||||
var buttons = ownerInstance.selectAllComponents('.uv-swipe-action-item__right__button')
|
||||
var len = buttons.length
|
||||
var previewButtonsMoveX = 0
|
||||
|
||||
// 设置菜单内容部分的偏移
|
||||
instance.requestAnimationFrame(function() {
|
||||
instance.setStyle({
|
||||
// 设置translateX的值
|
||||
'transition': 'none',
|
||||
transform: 'translateX(' + moveX + 'px)',
|
||||
'-webkit-transform': 'translateX(' + moveX + 'px)'
|
||||
})
|
||||
// 折叠按钮动画
|
||||
for (var i = len - 1; i >= 0; i--) {
|
||||
// 通过比例,得出元素自身该移动的距离
|
||||
var translateX = state.buttons[i].width / state.buttonsWidth * moveX
|
||||
// 最终移动的距离,是通过自身比例算出的距离,再加上在它之前所有按钮移动的距离之和
|
||||
var realTranslateX = translateX + previewButtonsMoveX
|
||||
buttons[i].setStyle({
|
||||
// 在移动期间,不能使用过渡效果,否则会造成卡顿,本质原因是每次移动一点,就要花一定时间去过渡这个过程
|
||||
'transition': 'none',
|
||||
'transform': 'translateX(' + realTranslateX + 'px)',
|
||||
'-webkit-transform': 'translateX(' + realTranslateX + 'px)'
|
||||
})
|
||||
// 记录本按钮之前的所有按钮的移动距离之和
|
||||
previewButtonsMoveX += translateX
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 一次性展开滑动菜单
|
||||
function openSwipeAction(instance, ownerInstance) {
|
||||
var state = instance.getState()
|
||||
// 获取所有按钮的实例,需要通过它去设置按钮的位移
|
||||
var buttons = ownerInstance.selectAllComponents('.uv-swipe-action-item__right__button')
|
||||
var len = buttons.length
|
||||
// 处理duration单位问题
|
||||
const duration = getDuration(state.duration)
|
||||
// 展开过程中,是向左移动,所以X的偏移应该为负值
|
||||
var buttonsWidth = -state.buttonsWidth
|
||||
var previewButtonsMoveX = 0
|
||||
instance.requestAnimationFrame(function() {
|
||||
// 设置菜单主体内容
|
||||
instance.setStyle({
|
||||
'transition': 'transform ' + duration,
|
||||
'transform': 'translateX(' + buttonsWidth + 'px)',
|
||||
'-webkit-transform': 'translateX(' + buttonsWidth + 'px)',
|
||||
})
|
||||
// 设置各个隐藏的按钮为展开的状态
|
||||
for (var i = len - 1; i >= 0; i--) {
|
||||
// 通过比例,得出元素自身该移动的距离
|
||||
var translateX = state.buttons[i].width / state.buttonsWidth * buttonsWidth
|
||||
// 最终移动的距离,是通过自身比例算出的距离,再加上在它之前所有按钮移动的距离之和
|
||||
var realTranslateX = translateX + previewButtonsMoveX
|
||||
buttons[i].setStyle({
|
||||
// 在移动期间,需要加上动画效果
|
||||
'transition': 'transform ' + duration,
|
||||
'transform': 'translateX(' + realTranslateX + 'px)',
|
||||
'-webkit-transform': 'translateX(' + realTranslateX + 'px)'
|
||||
})
|
||||
// 记录本按钮之前的所有按钮的移动距离之和
|
||||
previewButtonsMoveX += translateX
|
||||
}
|
||||
})
|
||||
setStatus('open', instance)
|
||||
}
|
||||
|
||||
// 标记菜单的当前状态,open-已经打开,close-已经关闭
|
||||
function setStatus(status, instance) {
|
||||
var state = instance.getState()
|
||||
state.status = status
|
||||
}
|
||||
|
||||
// 一次性收起滑动菜单
|
||||
function closeSwipeAction(instance, ownerInstance) {
|
||||
var state = instance.getState()
|
||||
// 获取所有按钮的实例,需要通过它去设置按钮的位移
|
||||
var buttons = ownerInstance.selectAllComponents('.uv-swipe-action-item__right__button')
|
||||
var len = buttons.length
|
||||
// 处理duration单位问题
|
||||
const duration = getDuration(state.duration)
|
||||
instance.requestAnimationFrame(function() {
|
||||
// 设置菜单主体内容
|
||||
instance.setStyle({
|
||||
'transition': 'transform ' + duration,
|
||||
'transform': 'translateX(0px)',
|
||||
'-webkit-transform': 'translateX(0px)'
|
||||
})
|
||||
// 设置各个隐藏的按钮为收起的状态
|
||||
for (var i = len - 1; i >= 0; i--) {
|
||||
buttons[i].setStyle({
|
||||
'transition': 'transform ' + duration,
|
||||
'transform': 'translateX(0px)',
|
||||
'-webkit-transform': 'translateX(0px)'
|
||||
})
|
||||
}
|
||||
})
|
||||
setStatus('close', instance)
|
||||
}
|
||||
|
||||
// show的状态发生变化
|
||||
function showChange(newValue, oldValue, ownerInstance, instance) {
|
||||
var state = instance.getState()
|
||||
if (state.disabled) return
|
||||
// 打开或关闭单元格
|
||||
if (newValue) {
|
||||
openSwipeAction(instance, ownerInstance)
|
||||
} else {
|
||||
closeSwipeAction(instance, ownerInstance)
|
||||
}
|
||||
}
|
||||
|
||||
// 菜单尺寸发生变化
|
||||
function sizeChange(newValue, oldValue, ownerInstance, instance) {
|
||||
// wxs内的局部变量快照
|
||||
var state = instance.getState()
|
||||
state.disabled = newValue.disabled
|
||||
state.duration = newValue.duration
|
||||
state.show = newValue.show
|
||||
state.threshold = newValue.threshold
|
||||
state.buttons = newValue.buttons
|
||||
|
||||
var len = state.buttons.length
|
||||
if (len) {
|
||||
var buttonsWidth = 0
|
||||
var buttons = newValue.buttons
|
||||
for (var i = 0; i < len; i++) {
|
||||
buttonsWidth += buttons[i].width
|
||||
}
|
||||
}
|
||||
state.buttonsWidth = buttonsWidth
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
touchstart: touchstart,
|
||||
touchmove: touchmove,
|
||||
touchend: touchend,
|
||||
sizeChange: sizeChange
|
||||
}
|
@ -1,225 +0,0 @@
|
||||
/**
|
||||
* 此为wxs模块,只支持APP-VUE,微信和QQ小程序以及H5平台
|
||||
* wxs内部不支持es6语法,变量只能使用var定义,无法使用解构,箭头函数等特性
|
||||
*/
|
||||
|
||||
// 开始触摸
|
||||
function touchstart(event, ownerInstance) {
|
||||
// 触发事件的组件的ComponentDescriptor实例
|
||||
var instance = event.instance
|
||||
// wxs内的局部变量快照,此快照是属于整个组件的,在touchstart和touchmove事件中都能获取到相同的结果
|
||||
var state = instance.getState()
|
||||
if (state.disabled) return
|
||||
var touches = event.touches
|
||||
// 如果进行的是多指触控,不允许进行操作
|
||||
if (touches && touches.length > 1) return
|
||||
// 标识当前为滑动中状态
|
||||
state.moving = true
|
||||
// 记录触摸开始点的坐标值
|
||||
state.startX = touches[0].pageX
|
||||
state.startY = touches[0].pageY
|
||||
|
||||
ownerInstance.callMethod('closeOther')
|
||||
}
|
||||
|
||||
// 触摸滑动
|
||||
function touchmove(event, ownerInstance) {
|
||||
// 触发事件的组件的ComponentDescriptor实例
|
||||
var instance = event.instance
|
||||
// wxs内的局部变量快照
|
||||
var state = instance.getState()
|
||||
if (state.disabled || !state.moving) return
|
||||
var touches = event.touches
|
||||
var pageX = touches[0].pageX
|
||||
var pageY = touches[0].pageY
|
||||
var moveX = pageX - state.startX
|
||||
var moveY = pageY - state.startY
|
||||
var buttonsWidth = state.buttonsWidth
|
||||
|
||||
// 移动的X轴距离大于Y轴距离,也即终点与起点位置连线,与X轴夹角小于45度时,禁止页面滚动
|
||||
if (Math.abs(moveX) > Math.abs(moveY) || Math.abs(moveX) > state.threshold) {
|
||||
event.preventDefault && event.preventDefault()
|
||||
event.stopPropagation && event.stopPropagation()
|
||||
}
|
||||
// 如果移动的X轴距离小于Y轴距离,也即终点位置与起点位置连线,与Y轴夹角小于45度时,认为是页面上下滑动,而不是左右滑动单元格
|
||||
if (Math.abs(moveX) < Math.abs(moveY)) return
|
||||
|
||||
// 限制右滑的距离,不允许内容部分往右偏移,右滑会导致X轴偏移值大于0,以此做判断
|
||||
// 此处不能直接return,因为滑动过程中会缺失某些关键点坐标,会导致错乱,最好的办法就是
|
||||
// 在超出后,设置为0
|
||||
if (state.status === 'open') {
|
||||
// 在开启状态下,向左滑动,需忽略
|
||||
if (moveX < 0) moveX = 0
|
||||
// 想要收起菜单,最大能移动的距离为按钮的总宽度
|
||||
if (moveX > buttonsWidth) moveX = buttonsWidth
|
||||
// 如果是已经打开了的状态,向左滑动时,移动收起菜单
|
||||
moveSwipeAction(-buttonsWidth + moveX, instance, ownerInstance)
|
||||
} else {
|
||||
// 关闭状态下,右滑动需忽略
|
||||
if (moveX > 0) moveX = 0
|
||||
// 滑动的距离不允许超过所有按钮的总宽度,此时只能是左滑,最终设置按钮的总宽度,同时为负数
|
||||
if (Math.abs(moveX) > buttonsWidth) moveX = -buttonsWidth
|
||||
// 只要是在滑过程中,就不断移动单元格内容部分,从而使隐藏的菜单显示出来
|
||||
moveSwipeAction(moveX, instance, ownerInstance)
|
||||
}
|
||||
}
|
||||
|
||||
// 触摸结束
|
||||
function touchend(event, ownerInstance) {
|
||||
// 触发事件的组件的ComponentDescriptor实例
|
||||
var instance = event.instance
|
||||
// wxs内的局部变量快照
|
||||
var state = instance.getState()
|
||||
if (!state.moving || state.disabled) return
|
||||
var touches = event.changedTouches ? event.changedTouches[0] : {}
|
||||
var pageX = touches.pageX
|
||||
var pageY = touches.pageY
|
||||
var moveX = pageX - state.startX
|
||||
if (state.status === 'open') {
|
||||
// 在展开的状态下,继续左滑,无需操作
|
||||
if (moveX < 0) return
|
||||
// 在开启状态下,点击一下内容区域,moveX为0,也即没有进行移动,这时执行收起菜单逻辑
|
||||
if (moveX === 0) {
|
||||
return closeSwipeAction(instance, ownerInstance)
|
||||
}
|
||||
// 在开启状态下,滑动距离小于阈值,则默认为不关闭,同时恢复原来的打开状态
|
||||
if (Math.abs(moveX) < state.threshold) {
|
||||
openSwipeAction(instance, ownerInstance)
|
||||
} else {
|
||||
// 如果滑动距离大于阈值,则执行收起逻辑
|
||||
closeSwipeAction(instance, ownerInstance)
|
||||
}
|
||||
} else {
|
||||
// 在关闭的状态下,右滑,无需操作
|
||||
if (moveX > 0) return
|
||||
// 理由同上
|
||||
if (Math.abs(moveX) < state.threshold) {
|
||||
closeSwipeAction(instance, ownerInstance)
|
||||
} else {
|
||||
openSwipeAction(instance, ownerInstance)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 获取过渡时间
|
||||
function getDuration(value) {
|
||||
if (value.toString().indexOf('s') >= 0) return value
|
||||
return value > 30 ? value + 'ms' : value + 's'
|
||||
}
|
||||
|
||||
// 滑动结束时判断滑动的方向
|
||||
function getMoveDirection(instance, ownerInstance) {
|
||||
var state = instance.getState()
|
||||
}
|
||||
|
||||
// 移动滑动选择器内容区域,同时显示出其隐藏的菜单
|
||||
function moveSwipeAction(moveX, instance, ownerInstance) {
|
||||
var state = instance.getState()
|
||||
// 获取所有按钮的实例,需要通过它去设置按钮的位移
|
||||
var buttons = ownerInstance.selectAllComponents('.uv-swipe-action-item__right__button')
|
||||
|
||||
// 设置菜单内容部分的偏移
|
||||
instance.requestAnimationFrame(function() {
|
||||
instance.setStyle({
|
||||
// 设置translateX的值
|
||||
'transition': 'none',
|
||||
transform: 'translateX(' + moveX + 'px)',
|
||||
'-webkit-transform': 'translateX(' + moveX + 'px)'
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// 一次性展开滑动菜单
|
||||
function openSwipeAction(instance, ownerInstance) {
|
||||
var state = instance.getState()
|
||||
// 获取所有按钮的实例,需要通过它去设置按钮的位移
|
||||
var buttons = ownerInstance.selectAllComponents('.uv-swipe-action-item__right__button')
|
||||
// 处理duration单位问题
|
||||
var duration = getDuration(state.duration)
|
||||
// 展开过程中,是向左移动,所以X的偏移应该为负值
|
||||
var buttonsWidth = -state.buttonsWidth
|
||||
instance.requestAnimationFrame(function() {
|
||||
// 设置菜单主体内容
|
||||
instance.setStyle({
|
||||
'transition': 'transform ' + duration,
|
||||
'transform': 'translateX(' + buttonsWidth + 'px)',
|
||||
'-webkit-transform': 'translateX(' + buttonsWidth + 'px)',
|
||||
})
|
||||
})
|
||||
setStatus('open', instance, ownerInstance)
|
||||
}
|
||||
|
||||
// 标记菜单的当前状态,open-已经打开,close-已经关闭
|
||||
function setStatus(status, instance, ownerInstance) {
|
||||
var state = instance.getState()
|
||||
state.status = status
|
||||
ownerInstance.callMethod('setState', status)
|
||||
}
|
||||
|
||||
// 一次性收起滑动菜单
|
||||
function closeSwipeAction(instance, ownerInstance) {
|
||||
var state = instance.getState()
|
||||
// 获取所有按钮的实例,需要通过它去设置按钮的位移
|
||||
var buttons = ownerInstance.selectAllComponents('.uv-swipe-action-item__right__button')
|
||||
var len = buttons.length
|
||||
// 处理duration单位问题
|
||||
var duration = getDuration(state.duration)
|
||||
instance.requestAnimationFrame(function() {
|
||||
// 设置菜单主体内容
|
||||
instance.setStyle({
|
||||
'transition': 'transform ' + duration,
|
||||
'transform': 'translateX(0px)',
|
||||
'-webkit-transform': 'translateX(0px)'
|
||||
})
|
||||
// 设置各个隐藏的按钮为收起的状态
|
||||
for (var i = len - 1; i >= 0; i--) {
|
||||
buttons[i].setStyle({
|
||||
'transition': 'transform ' + duration,
|
||||
'transform': 'translateX(0px)',
|
||||
'-webkit-transform': 'translateX(0px)'
|
||||
})
|
||||
}
|
||||
})
|
||||
setStatus('close', instance, ownerInstance)
|
||||
}
|
||||
|
||||
// status的状态发生变化
|
||||
function statusChange(newValue, oldValue, ownerInstance, instance) {
|
||||
var state = instance.getState()
|
||||
if (state.disabled) return
|
||||
// 打开或关闭单元格
|
||||
if (newValue === 'close' && state.status === 'open') {
|
||||
closeSwipeAction(instance, ownerInstance)
|
||||
} else if(newValue === 'open' && state.status === 'close') {
|
||||
openSwipeAction(instance, ownerInstance)
|
||||
}
|
||||
}
|
||||
|
||||
// 菜单尺寸发生变化
|
||||
function sizeChange(newValue, oldValue, ownerInstance, instance) {
|
||||
// wxs内的局部变量快照
|
||||
var state = instance.getState()
|
||||
state.disabled = newValue.disabled
|
||||
state.duration = newValue.duration
|
||||
state.show = newValue.show
|
||||
state.threshold = newValue.threshold
|
||||
state.buttons = newValue.buttons
|
||||
|
||||
if (state.buttons) {
|
||||
var len = state.buttons.length
|
||||
var buttonsWidth = 0
|
||||
var buttons = newValue.buttons
|
||||
for (var i = 0; i < len; i++) {
|
||||
buttonsWidth += buttons[i].width
|
||||
}
|
||||
}
|
||||
state.buttonsWidth = buttonsWidth
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
touchstart: touchstart,
|
||||
touchmove: touchmove,
|
||||
touchend: touchend,
|
||||
sizeChange: sizeChange,
|
||||
statusChange: statusChange
|
||||
}
|
@ -1,264 +0,0 @@
|
||||
// nvue操作dom的库,用于获取dom的尺寸信息
|
||||
const dom = uni.requireNativePlugin('dom')
|
||||
// nvue中用于操作元素动画的库,类似于uni.animation,只不过uni.animation不能用于nvue
|
||||
const animation = uni.requireNativePlugin('animation')
|
||||
import { sleep } from '@/uni_modules/uv-ui-tools/libs/function/index.js'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
// 是否滑动中
|
||||
moving: false,
|
||||
// 状态,open-打开状态,close-关闭状态
|
||||
status: 'close',
|
||||
// 开始触摸点的X和Y轴坐标
|
||||
startX: 0,
|
||||
startY: 0,
|
||||
// 所有隐藏按钮的尺寸信息数组
|
||||
buttons: [],
|
||||
// 所有按钮的总宽度
|
||||
buttonsWidth: 0,
|
||||
// 记录上一次移动的位置值
|
||||
moveX: 0,
|
||||
// 记录上一次滑动的位置,用于前后两次做对比,如果移动的距离小于某一阈值,则认为前后之间没有移动,为了解决可能存在的通信阻塞问题
|
||||
lastX: 0
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
// 获取过渡时间
|
||||
getDuratin() {
|
||||
let duration = String(this.duration)
|
||||
// 如果ms为单位,返回ms的数值部分
|
||||
if (duration.indexOf('ms') >= 0) return parseInt(duration)
|
||||
// 如果s为单位,为了得到ms的数值,需要乘以1000
|
||||
if (duration.indexOf('s') >= 0) return parseInt(duration) * 1000
|
||||
// 如果值传了数值,且小于30,认为是s单位
|
||||
duration = Number(duration)
|
||||
return duration < 30 ? duration * 1000 : duration
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
show: {
|
||||
immediate: true,
|
||||
handler(n) {
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
sleep(20).then(() => {
|
||||
this.queryRect()
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
close() {
|
||||
this.closeSwipeAction()
|
||||
},
|
||||
// 触摸单元格
|
||||
touchstart(event) {
|
||||
if (this.disabled) return
|
||||
this.closeOther()
|
||||
const { touches } = event
|
||||
// 记录触摸开始点的坐标值
|
||||
this.startX = touches[0].pageX
|
||||
this.startY = touches[0].pageY
|
||||
},
|
||||
// // 触摸滑动
|
||||
touchmove(event) {
|
||||
if (this.disabled) return
|
||||
const { touches } = event
|
||||
const { pageX } = touches[0]
|
||||
const { pageY } = touches[0]
|
||||
let moveX = pageX - this.startX
|
||||
const moveY = pageY - this.startY
|
||||
const { buttonsWidth } = this
|
||||
const len = this.buttons.length
|
||||
|
||||
// 判断前后两次的移动距离,如果小于一定值,则不进行移动处理
|
||||
if (Math.abs(pageX - this.lastX) < 0.3) return
|
||||
this.lastX = pageX
|
||||
|
||||
// 移动的X轴距离大于Y轴距离,也即终点与起点位置连线,与X轴夹角小于45度时,禁止页面滚动
|
||||
if (Math.abs(moveX) > Math.abs(moveY) || Math.abs(moveX) > this.threshold) {
|
||||
event.stopPropagation()
|
||||
}
|
||||
// 如果移动的X轴距离小于Y轴距离,也即终点位置与起点位置连线,与Y轴夹角小于45度时,认为是页面上下滑动,而不是左右滑动单元格
|
||||
if (Math.abs(moveX) < Math.abs(moveY)) return
|
||||
|
||||
// 限制右滑的距离,不允许内容部分往右偏移,右滑会导致X轴偏移值大于0,以此做判断
|
||||
// 此处不能直接return,因为滑动过程中会缺失某些关键点坐标,会导致错乱,最好的办法就是
|
||||
// 在超出后,设置为0
|
||||
if (this.status === 'open') {
|
||||
// 在开启状态下,向左滑动,需忽略
|
||||
if (moveX < 0) moveX = 0
|
||||
// 想要收起菜单,最大能移动的距离为按钮的总宽度
|
||||
if (moveX > buttonsWidth) moveX = buttonsWidth
|
||||
// 如果是已经打开了的状态,向左滑动时,移动收起菜单
|
||||
this.moveSwipeAction(-buttonsWidth + moveX)
|
||||
} else {
|
||||
// 关闭状态下,右滑动需忽略
|
||||
if (moveX > 0) moveX = 0
|
||||
// 滑动的距离不允许超过所有按钮的总宽度,此时只能是左滑,最终设置按钮的总宽度,同时为负数
|
||||
if (Math.abs(moveX) > buttonsWidth) moveX = -buttonsWidth
|
||||
// 只要是在滑过程中,就不断移动菜单的内容部分,从而使隐藏的菜单显示出来
|
||||
this.moveSwipeAction(moveX)
|
||||
}
|
||||
},
|
||||
// 单元格结束触摸
|
||||
touchend(event) {
|
||||
if (this.disabled) return
|
||||
const touches = event.changedTouches ? event.changedTouches[0] : {}
|
||||
const { pageX } = touches
|
||||
const { pageY } = touches
|
||||
const { buttonsWidth } = this
|
||||
this.moveX = pageX - this.startX
|
||||
if (this.status === 'open') {
|
||||
// 在展开的状态下,继续左滑,无需操作
|
||||
if (this.moveX < 0) this.moveX = 0
|
||||
if (this.moveX > buttonsWidth) this.moveX = buttonsWidth
|
||||
// 在开启状态下,点击一下内容区域,moveX为0,也即没有进行移动,这时执行收起菜单逻辑
|
||||
if (this.moveX === 0) {
|
||||
return this.closeSwipeAction()
|
||||
}
|
||||
// 在开启状态下,滑动距离小于阈值,则默认为不关闭,同时恢复原来的打开状态
|
||||
if (Math.abs(this.moveX) < this.threshold) {
|
||||
this.openSwipeAction()
|
||||
} else {
|
||||
// 如果滑动距离大于阈值,则执行收起逻辑
|
||||
this.closeSwipeAction()
|
||||
}
|
||||
} else {
|
||||
// 在关闭的状态下,右滑,无需操作
|
||||
if (this.moveX >= 0) this.moveX = 0
|
||||
if (this.moveX <= -buttonsWidth) this.moveX = -buttonsWidth
|
||||
// 理由同上
|
||||
if (Math.abs(this.moveX) < this.threshold) {
|
||||
this.closeSwipeAction()
|
||||
} else {
|
||||
this.openSwipeAction()
|
||||
}
|
||||
}
|
||||
},
|
||||
// 移动滑动选择器内容区域,同时显示出其隐藏的菜单
|
||||
moveSwipeAction(moveX) {
|
||||
if (this.moving) return
|
||||
this.moving = true
|
||||
|
||||
let previewButtonsMoveX = 0
|
||||
const len = this.buttons.length
|
||||
animation.transition(this.$refs['uv-swipe-action-item__content'].ref, {
|
||||
styles: {
|
||||
transform: `translateX(${moveX}px)`
|
||||
},
|
||||
timingFunction: 'linear'
|
||||
}, () => {
|
||||
this.moving = false
|
||||
})
|
||||
// 按钮的组的长度
|
||||
for (let i = len - 1; i >= 0; i--) {
|
||||
const buttonRef = this.$refs[`uv-swipe-action-item__right__button-${i}`][0].ref
|
||||
// 通过比例,得出元素自身该移动的距离
|
||||
const translateX = this.buttons[i].width / this.buttonsWidth * moveX
|
||||
// 最终移动的距离,是通过自身比例算出的距离,再加上在它之前所有按钮移动的距离之和
|
||||
const realTranslateX = translateX + previewButtonsMoveX
|
||||
animation.transition(buttonRef, {
|
||||
styles: {
|
||||
transform: `translateX(${realTranslateX}px)`
|
||||
},
|
||||
duration: 0,
|
||||
delay: 0,
|
||||
timingFunction: 'linear'
|
||||
}, () => {})
|
||||
// 记录本按钮之前的所有按钮的移动距离之和
|
||||
previewButtonsMoveX += translateX
|
||||
}
|
||||
},
|
||||
// 关闭菜单
|
||||
closeSwipeAction() {
|
||||
if (this.status === 'close') return
|
||||
this.moving = true
|
||||
const { buttonsWidth } = this
|
||||
animation.transition(this.$refs['uv-swipe-action-item__content'].ref, {
|
||||
styles: {
|
||||
transform: 'translateX(0px)'
|
||||
},
|
||||
duration: this.getDuratin,
|
||||
timingFunction: 'ease-in-out'
|
||||
}, () => {
|
||||
this.status = 'close'
|
||||
this.moving = false
|
||||
this.closeHandler()
|
||||
})
|
||||
// 按钮的组的长度
|
||||
const len = this.buttons.length
|
||||
for (let i = len - 1; i >= 0; i--) {
|
||||
const buttonRef = this.$refs[`uv-swipe-action-item__right__button-${i}`][0].ref
|
||||
// 如果不满足边界条件,返回
|
||||
if (this.buttons.length === 0 || !this.buttons[i] || !this.buttons[i].width) return
|
||||
|
||||
animation.transition(buttonRef, {
|
||||
styles: {
|
||||
transform: 'translateX(0px)'
|
||||
},
|
||||
duration: this.getDuratin,
|
||||
timingFunction: 'ease-in-out'
|
||||
}, () => {})
|
||||
}
|
||||
},
|
||||
// 打开菜单
|
||||
openSwipeAction() {
|
||||
if (this.status === 'open') return
|
||||
this.moving = true
|
||||
const buttonsWidth = -this.buttonsWidth
|
||||
let previewButtonsMoveX = 0
|
||||
animation.transition(this.$refs['uv-swipe-action-item__content'].ref, {
|
||||
styles: {
|
||||
transform: `translateX(${buttonsWidth}px)`
|
||||
},
|
||||
duration: this.getDuratin,
|
||||
timingFunction: 'ease-in-out'
|
||||
}, () => {
|
||||
this.status = 'open'
|
||||
this.moving = false
|
||||
this.openHandler()
|
||||
})
|
||||
// 按钮的组的长度
|
||||
const len = this.buttons.length
|
||||
for (let i = len - 1; i >= 0; i--) {
|
||||
const buttonRef = this.$refs[`uv-swipe-action-item__right__button-${i}`][0].ref
|
||||
// 如果不满足边界条件,返回
|
||||
if (this.buttons.length === 0 || !this.buttons[i] || !this.buttons[i].width) return
|
||||
// 通过比例,得出元素自身该移动的距离
|
||||
const translateX = this.buttons[i].width / this.buttonsWidth * buttonsWidth
|
||||
// 最终移动的距离,是通过自身比例算出的距离,再加上在它之前所有按钮移动的距离之和
|
||||
const realTranslateX = translateX + previewButtonsMoveX
|
||||
animation.transition(buttonRef, {
|
||||
styles: {
|
||||
transform: `translateX(${realTranslateX}px)`
|
||||
},
|
||||
duration: this.getDuratin,
|
||||
timingFunction: 'ease-in-out'
|
||||
}, () => {})
|
||||
previewButtonsMoveX += translateX
|
||||
}
|
||||
},
|
||||
// 查询按钮节点信息
|
||||
queryRect() {
|
||||
// 历遍所有按钮数组,通过getRectByDom返回一个promise
|
||||
const promiseAll = this.rightOptions.map((item, index) => this.getRectByDom(this.$refs[`uv-swipe-action-item__right__button-${index}`][0]))
|
||||
// 通过promise.all方法,让所有按钮的查询结果返回一个数组的形式
|
||||
Promise.all(promiseAll).then((sizes) => {
|
||||
this.buttons = sizes
|
||||
// 计算所有按钮总宽度
|
||||
this.buttonsWidth = sizes.reduce((sum, cur) => sum + cur.width, 0)
|
||||
})
|
||||
},
|
||||
// 通过nvue的dom模块,查询节点信息
|
||||
getRectByDom(ref) {
|
||||
return new Promise((resolve) => {
|
||||
dom.getComponentRect(ref, (res) => {
|
||||
resolve(res.size)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
@ -1,182 +0,0 @@
|
||||
// nvue操作dom的库,用于获取dom的尺寸信息
|
||||
const dom = uni.requireNativePlugin('dom');
|
||||
const bindingX = uni.requireNativePlugin('bindingx');
|
||||
const animation = uni.requireNativePlugin('animation');
|
||||
import { getDuration, getPx } from '@/uni_modules/uv-ui-tools/libs/function/index.js'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
// 所有按钮的总宽度
|
||||
buttonsWidth: 0,
|
||||
// 是否正在移动中
|
||||
moving: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
// 获取过渡时间
|
||||
getDuratin() {
|
||||
let duration = String(this.duration)
|
||||
// 如果ms为单位,返回ms的数值部分
|
||||
if (duration.indexOf('ms') >= 0) return parseInt(duration)
|
||||
// 如果s为单位,为了得到ms的数值,需要乘以1000
|
||||
if (duration.indexOf('s') >= 0) return parseInt(duration) * 1000
|
||||
// 如果值传了数值,且小于30,认为是s单位
|
||||
duration = Number(duration)
|
||||
return duration < 30 ? duration * 1000 : duration
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
show(n) {
|
||||
if(n) {
|
||||
this.moveCellByAnimation('open')
|
||||
} else {
|
||||
this.moveCellByAnimation('close')
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
setTimeout(()=>{
|
||||
this.initialize()
|
||||
},20)
|
||||
},
|
||||
methods: {
|
||||
initialize() {
|
||||
this.queryRect()
|
||||
},
|
||||
// 关闭单元格,用于打开一个,自动关闭其他单元格的场景
|
||||
closeHandler() {
|
||||
if(this.status === 'open') {
|
||||
// 如果在打开状态下,进行点击的话,直接关闭单元格
|
||||
return this.moveCellByAnimation('close') && this.unbindBindingX()
|
||||
}
|
||||
},
|
||||
// 点击单元格
|
||||
clickHandler() {
|
||||
// 如果在移动中被点击,进行忽略
|
||||
if(this.moving) return
|
||||
// 尝试关闭其他打开的单元格
|
||||
this.parent && this.parent.closeOther(this)
|
||||
if(this.status === 'open') {
|
||||
// 如果在打开状态下,进行点击的话,直接关闭单元格
|
||||
return this.moveCellByAnimation('close') && this.unbindBindingX()
|
||||
}
|
||||
},
|
||||
// 滑动单元格
|
||||
onTouchstart(e) {
|
||||
// 如果当前正在移动中,或者disabled状态,则返回
|
||||
if(this.moving || this.disabled) {
|
||||
return this.unbindBindingX()
|
||||
}
|
||||
if(this.status === 'open') {
|
||||
// 如果在打开状态下,进行点击的话,直接关闭单元格
|
||||
return this.moveCellByAnimation('close') && this.unbindBindingX()
|
||||
}
|
||||
// 特殊情况下,e可能不为一个对象
|
||||
e?.stopPropagation && e.stopPropagation()
|
||||
e?.preventDefault && e.preventDefault()
|
||||
this.moving = true
|
||||
// 获取元素ref
|
||||
const content = this.getContentRef()
|
||||
let expression = `min(max(${-this.buttonsWidth}, x), 0)`
|
||||
// 尝试关闭其他打开的单元格
|
||||
this.parent && this.parent.closeOther(this)
|
||||
// 阿里为了KPI而开源的BindingX
|
||||
this.panEvent = bindingX.bind({
|
||||
anchor: content,
|
||||
eventType: 'pan',
|
||||
props: [{
|
||||
element: content,
|
||||
// 绑定width属性,设置其宽度值
|
||||
property: 'transform.translateX',
|
||||
expression
|
||||
}]
|
||||
}, (res) => {
|
||||
this.moving = false
|
||||
if (res.state === 'end' || res.state === 'exit') {
|
||||
const deltaX = res.deltaX
|
||||
if(deltaX <= -this.buttonsWidth || deltaX >= 0) {
|
||||
// 如果触摸滑动的过程中,大于单元格的总宽度,或者大于0,意味着已经动过滑动达到了打开或者关闭的状态
|
||||
// 这里直接进行状态的标记
|
||||
this.$nextTick(() => {
|
||||
this.status = deltaX <= -this.buttonsWidth ? 'open' : 'close'
|
||||
})
|
||||
} else if(Math.abs(deltaX) > getPx(this.threshold)) {
|
||||
// 在移动大于阈值、并且小于总按钮宽度时,进行自动打开或者关闭
|
||||
// 移动距离大于0时,意味着需要关闭状态
|
||||
if(Math.abs(deltaX) < this.buttonsWidth) {
|
||||
this.moveCellByAnimation(deltaX > 0 ? 'close' : 'open')
|
||||
}
|
||||
} else {
|
||||
// 在小于阈值时,进行关闭操作(如果在打开状态下,将不会执行bindingX)
|
||||
this.moveCellByAnimation('close')
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
// 释放bindingX
|
||||
unbindBindingX() {
|
||||
// 释放上一次的资源
|
||||
if (this?.panEvent?.token != 0) {
|
||||
bindingX.unbind({
|
||||
token: this.panEvent?.token,
|
||||
// pan为手势事件
|
||||
eventType: 'pan'
|
||||
})
|
||||
}
|
||||
},
|
||||
// 查询按钮节点信息
|
||||
queryRect() {
|
||||
// 历遍所有按钮数组,通过getRectByDom返回一个promise
|
||||
const promiseAll = this.options.map(async(item, index) => {
|
||||
return await this.getRectByDom(this.$refs[`uv-swipe-action-item__right__button-${index}`][0])
|
||||
})
|
||||
// 通过promise.all方法,让所有按钮的查询结果返回一个数组的形式
|
||||
Promise.all(promiseAll).then(sizes => {
|
||||
this.buttons = sizes
|
||||
// 计算所有按钮总宽度
|
||||
this.buttonsWidth = sizes.reduce((sum, cur) => sum + cur.width, 0)
|
||||
})
|
||||
},
|
||||
// 通过nvue的dom模块,查询节点信息
|
||||
getRectByDom(ref) {
|
||||
return new Promise(resolve => {
|
||||
dom.getComponentRect(ref, res => {
|
||||
resolve(res.size)
|
||||
})
|
||||
})
|
||||
},
|
||||
// 移动单元格到左边或者右边尽头
|
||||
moveCellByAnimation(status = 'open') {
|
||||
if(this.moving) return
|
||||
// 标识当前状态
|
||||
this.moveing = true
|
||||
const content = this.getContentRef()
|
||||
const x = status === 'open' ? -this.buttonsWidth : 0
|
||||
animation.transition(content, {
|
||||
styles: {
|
||||
transform: `translateX(${x}px)`,
|
||||
},
|
||||
duration: getDuration(this.duration, false),
|
||||
timingFunction: 'ease-in-out'
|
||||
}, () => {
|
||||
this.moving = false
|
||||
this.status = status
|
||||
this.unbindBindingX()
|
||||
})
|
||||
},
|
||||
// 获取元素ref
|
||||
getContentRef() {
|
||||
return this.$refs['uv-swipe-action-item__content'].ref
|
||||
}
|
||||
},
|
||||
// #ifdef VUE2
|
||||
beforeDestroy() {
|
||||
this.unbindBindingX()
|
||||
},
|
||||
// #endif
|
||||
// #ifdef VUE3
|
||||
unmounted() {
|
||||
this.unbindBindingX()
|
||||
}
|
||||
// #endif
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
export default {
|
||||
props: {
|
||||
// 控制打开或者关闭
|
||||
show: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 标识符,如果是v-for,可用index索引值
|
||||
name: {
|
||||
type: [String, Number],
|
||||
default: ''
|
||||
},
|
||||
// 是否禁用
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 是否自动关闭其他swipe按钮组
|
||||
autoClose: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// 滑动距离阈值,只有大于此值,才被认为是要打开菜单
|
||||
threshold: {
|
||||
type: Number,
|
||||
default: 20
|
||||
},
|
||||
// 右侧按钮内容
|
||||
options: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
// 动画过渡时间,单位ms
|
||||
duration: {
|
||||
type: [String, Number],
|
||||
default: 300
|
||||
},
|
||||
...uni.$uv?.props?.swipeActionItem
|
||||
}
|
||||
}
|
@ -1,200 +0,0 @@
|
||||
<template>
|
||||
<view class="uv-swipe-action-item" ref="uv-swipe-action-item">
|
||||
<view class="uv-swipe-action-item__right">
|
||||
<slot name="button">
|
||||
<view v-for="(item,index) in options" :key="index" class="uv-swipe-action-item__right__button"
|
||||
:ref="`uv-swipe-action-item__right__button-${index}`" :style="[{
|
||||
alignItems: item.style && item.style.borderRadius ? 'center' : 'stretch'
|
||||
}]" @tap="buttonClickHandler(item, index)">
|
||||
<view class="uv-swipe-action-item__right__button__wrapper" :style="[{
|
||||
backgroundColor: item.style && item.style.backgroundColor ? item.style.backgroundColor : '#C7C6CD',
|
||||
borderRadius: item.style && item.style.borderRadius ? item.style.borderRadius : '0',
|
||||
padding: item.style && item.style.borderRadius ? '0' : '0 15px',
|
||||
}, item.style]">
|
||||
<uv-icon v-if="item.icon" :name="item.icon"
|
||||
:color="item.style && item.style.color ? item.style.color : '#ffffff'"
|
||||
:size="item.iconSize ? $uv.addUnit(item.iconSize) : item.style && item.style.fontSize ? $uv.getPx(item.style.fontSize) * 1.2 : 17"
|
||||
:customStyle="{
|
||||
marginRight: item.text ? '2px' : 0
|
||||
}"></uv-icon>
|
||||
<text v-if="item.text" class="uv-swipe-action-item__right__button__wrapper__text uv-line-1"
|
||||
:style="[{
|
||||
color: item.style && item.style.color ? item.style.color : '#ffffff',
|
||||
fontSize: item.style && item.style.fontSize ? item.style.fontSize : '16px',
|
||||
lineHeight: item.style && item.style.fontSize ? item.style.fontSize : '16px',
|
||||
}]">{{ item.text }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</slot>
|
||||
</view>
|
||||
<!-- #ifndef APP-NVUE -->
|
||||
<view class="uv-swipe-action-item__content" @touchstart="wxs.touchstart" @touchmove="wxs.touchmove"
|
||||
@touchend="wxs.touchend" :status="status" :change:status="wxs.statusChange" :size="size"
|
||||
:change:size="wxs.sizeChange">
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef APP-NVUE -->
|
||||
<view class="uv-swipe-action-item__content" ref="uv-swipe-action-item__content" @panstart="onTouchstart"
|
||||
@tap="clickHandler">
|
||||
<!-- #endif -->
|
||||
<slot />
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<!-- #ifdef APP-VUE || MP-WEIXIN || H5 || MP-QQ -->
|
||||
<script src="./index.wxs" module="wxs" lang="wxs"></script>
|
||||
<!-- #endif -->
|
||||
<script>
|
||||
import touch from '@/uni_modules/uv-ui-tools/libs/mixin/touch.js'
|
||||
import mpMixin from '@/uni_modules/uv-ui-tools/libs/mixin/mpMixin.js'
|
||||
import mixin from '@/uni_modules/uv-ui-tools/libs/mixin/mixin.js'
|
||||
import props from './props.js';
|
||||
// #ifdef APP-NVUE
|
||||
import nvue from './nvue.js';
|
||||
// #endif
|
||||
// #ifdef APP-VUE || MP-WEIXIN || H5 || MP-QQ
|
||||
import wxs from './wxs.js';
|
||||
// #endif
|
||||
/**
|
||||
* SwipeActionItem 滑动单元格子组件
|
||||
* @description 该组件一般用于左滑唤出操作菜单的场景,用的最多的是左滑删除操作
|
||||
* @tutorial https://www.uvui.cn/components/swipeAction.html
|
||||
* @property {Boolean} show 控制打开或者关闭(默认 false )
|
||||
* @property {String | Number} index 标识符,如果是v-for,可用index索引
|
||||
* @property {Boolean} disabled 是否禁用(默认 false )
|
||||
* @property {Boolean} autoClose 是否自动关闭其他swipe按钮组(默认 true )
|
||||
* @property {Number} threshold 滑动距离阈值,只有大于此值,才被认为是要打开菜单(默认 30 )
|
||||
* @property {Array} options 右侧按钮内容
|
||||
* @property {String | Number} duration 动画过渡时间,单位ms(默认 350 )
|
||||
* @event {Function(index)} open 组件打开时触发
|
||||
* @event {Function(index)} close 组件关闭时触发
|
||||
* @example <uv-swipe-action><uv-swipe-action-item :options="options1" ></uv-swipe-action-item></uv-swipe-action>
|
||||
*/
|
||||
export default {
|
||||
name: 'uv-swipe-action-item',
|
||||
emits: ['click'],
|
||||
// #ifndef APP-NVUE
|
||||
mixins: [mpMixin, mixin, props, touch],
|
||||
// #endif
|
||||
// #ifdef APP-NVUE
|
||||
mixins: [mpMixin, mixin, props, nvue , touch],
|
||||
// #endif
|
||||
// #ifdef APP-VUE || MP-WEIXIN || H5 || MP-QQ
|
||||
mixins: [mpMixin, mixin, props, touch, wxs],
|
||||
// #endif
|
||||
data() {
|
||||
return {
|
||||
// 按钮的尺寸信息
|
||||
size: {},
|
||||
// 父组件uv-swipe-action的参数
|
||||
parentData: {
|
||||
autoClose: true,
|
||||
},
|
||||
// 当前状态,open-打开,close-关闭
|
||||
status: 'close',
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
// 由于wxs无法直接读取外部的值,需要在外部值变化时,重新执行赋值逻辑
|
||||
wxsInit(newValue, oldValue) {
|
||||
this.queryRect()
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
wxsInit() {
|
||||
return [this.disabled, this.autoClose, this.threshold, this.options, this.duration]
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// #ifdef MP-TOUTIAO
|
||||
this.$uv.error('抖音小程序暂不支持wxs,故该组件暂不支持抖音小程序');
|
||||
// #endif
|
||||
this.init()
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
// 初始化父组件数据
|
||||
this.updateParentData()
|
||||
// #ifndef APP-NVUE
|
||||
this.$uv.sleep().then(() => {
|
||||
this.queryRect()
|
||||
})
|
||||
// #endif
|
||||
},
|
||||
updateParentData() {
|
||||
// 此方法在mixin中
|
||||
this.getParentData('uv-swipe-action')
|
||||
},
|
||||
// #ifndef APP-NVUE
|
||||
// 查询节点
|
||||
queryRect() {
|
||||
this.$uvGetRect('.uv-swipe-action-item__right__button', true).then(buttons => {
|
||||
this.size = {
|
||||
buttons,
|
||||
show: this.show,
|
||||
disabled: this.disabled,
|
||||
threshold: this.threshold,
|
||||
duration: this.duration
|
||||
}
|
||||
})
|
||||
},
|
||||
// #endif
|
||||
// 按钮被点击
|
||||
buttonClickHandler(item, index) {
|
||||
this.$emit('click', {
|
||||
index,
|
||||
name: this.name
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
$show-lines: 1;
|
||||
@import '@/uni_modules/uv-ui-tools/libs/css/variable.scss';
|
||||
@import '@/uni_modules/uv-ui-tools/libs/css/components.scss';
|
||||
|
||||
.uv-swipe-action-item {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
/* #ifndef APP-NVUE || MP-WEIXIN */
|
||||
touch-action: pan-y;
|
||||
/* #endif */
|
||||
|
||||
&__content {
|
||||
background-color: #FFFFFF;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
&__right {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
@include flex;
|
||||
|
||||
&__button {
|
||||
@include flex;
|
||||
justify-content: center;
|
||||
overflow: hidden;
|
||||
align-items: center;
|
||||
|
||||
&__wrapper {
|
||||
@include flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0 15px;
|
||||
|
||||
&__text {
|
||||
@include flex;
|
||||
align-items: center;
|
||||
color: #FFFFFF;
|
||||
font-size: 15px;
|
||||
text-align: center;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@ -1,15 +0,0 @@
|
||||
export default {
|
||||
methods: {
|
||||
// 关闭时执行
|
||||
closeHandler() {
|
||||
this.status = 'close'
|
||||
},
|
||||
setState(status) {
|
||||
this.status = status
|
||||
},
|
||||
closeOther() {
|
||||
// 尝试关闭其他打开的单元格
|
||||
this.parent && this.parent.closeOther(this)
|
||||
}
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
export default {
|
||||
props: {
|
||||
// 是否自动关闭其他swipe按钮组
|
||||
autoClose: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
...uni.$uv?.props?.swipeAction
|
||||
}
|
||||
}
|
@ -1,65 +0,0 @@
|
||||
<template>
|
||||
<view class="uv-swipe-action">
|
||||
<slot></slot>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import mpMixin from '@/uni_modules/uv-ui-tools/libs/mixin/mpMixin.js'
|
||||
import mixin from '@/uni_modules/uv-ui-tools/libs/mixin/mixin.js'
|
||||
import props from './props.js';
|
||||
/**
|
||||
* SwipeAction 滑动单元格
|
||||
* @description 该组件一般用于左滑唤出操作菜单的场景,用的最多的是左滑删除操作
|
||||
* @tutorial https://www.uvui.cn/components/swipeAction.html
|
||||
* @property {Boolean} autoClose 是否自动关闭其他swipe按钮组
|
||||
* @event {Function(index)} click 点击组件时触发
|
||||
* @example <uv-swipe-action><uv-swipe-action-item :rightOptions="options1" ></uv-swipe-action-item></uv-swipe-action>
|
||||
*/
|
||||
export default {
|
||||
name: 'uv-swipe-action',
|
||||
mixins: [mpMixin, mixin, props],
|
||||
data() {
|
||||
return {}
|
||||
},
|
||||
provide() {
|
||||
return {
|
||||
swipeAction: this
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
// 这里computed的变量,都是子组件uv-swipe-action-item需要用到的,由于头条小程序的兼容性差异,子组件无法实时监听父组件参数的变化
|
||||
// 所以需要手动通知子组件,这里返回一个parentData变量,供watch监听,在其中去通知每一个子组件重新从父组件(uv-swipe-action-item)
|
||||
// 拉取父组件新的变化后的参数
|
||||
parentData() {
|
||||
return [this.autoClose]
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
// 当父组件需要子组件需要共享的参数发生了变化,手动通知子组件
|
||||
parentData() {
|
||||
if (this.children.length) {
|
||||
this.children.map(child => {
|
||||
// 判断子组件(uv-swipe-action-item)如果有updateParentData方法的话,就就执行(执行的结果是子组件重新从父组件拉取了最新的值)
|
||||
typeof(child.updateParentData) === 'function' && child.updateParentData()
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.children = []
|
||||
},
|
||||
methods: {
|
||||
closeOther(child) {
|
||||
if (this.autoClose) {
|
||||
// 历遍所有的单元格,找出非当前操作中的单元格,进行关闭
|
||||
this.children.map((item, index) => {
|
||||
if (child !== item) {
|
||||
item.closeHandler()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
@ -1,88 +0,0 @@
|
||||
{
|
||||
"id": "uv-swipe-action",
|
||||
"displayName": "uv-swipe-action 滑动单元格 全面兼容小程序、nvue、vue2、vue3等多端",
|
||||
"version": "1.0.4",
|
||||
"description": "滑动单元格组件一般用于左滑唤出操作菜单的场景,用的最多的是左滑删除操作。",
|
||||
"keywords": [
|
||||
"uv-swipe-action",
|
||||
"uvui",
|
||||
"uv-ui",
|
||||
"swipe-action",
|
||||
"滑动单元格"
|
||||
],
|
||||
"repository": "",
|
||||
"engines": {
|
||||
"HBuilderX": "^3.1.0"
|
||||
},
|
||||
"dcloudext": {
|
||||
"type": "component-vue",
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "插件不采集任何数据",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": ""
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": [
|
||||
"uv-ui-tools",
|
||||
"uv-icon"
|
||||
],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y"
|
||||
},
|
||||
"client": {
|
||||
"Vue": {
|
||||
"vue2": "y",
|
||||
"vue3": "y"
|
||||
},
|
||||
"App": {
|
||||
"app-vue": "y",
|
||||
"app-nvue": "y"
|
||||
},
|
||||
"H5-mobile": {
|
||||
"Safari": "y",
|
||||
"Android Browser": "y",
|
||||
"微信浏览器(Android)": "y",
|
||||
"QQ浏览器(Android)": "y"
|
||||
},
|
||||
"H5-pc": {
|
||||
"Chrome": "y",
|
||||
"IE": "y",
|
||||
"Edge": "y",
|
||||
"Firefox": "y",
|
||||
"Safari": "y"
|
||||
},
|
||||
"小程序": {
|
||||
"微信": "y",
|
||||
"阿里": "y",
|
||||
"百度": "y",
|
||||
"字节跳动": "y",
|
||||
"QQ": "y",
|
||||
"钉钉": "u",
|
||||
"快手": "u",
|
||||
"飞书": "u",
|
||||
"京东": "u"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "u",
|
||||
"联盟": "u"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
## SwipeAction 滑动单元格
|
||||
|
||||
> **组件名:uv-swipe-action**
|
||||
|
||||
该组件一般用于左滑唤出操作菜单的场景,用的最多的是左滑删除操作。
|
||||
|
||||
### <a href="https://www.uvui.cn/components/swipeAction.html" target="_blank">查看文档</a>
|
||||
|
||||
### [完整示例项目下载 | 关注更多组件](https://ext.dcloud.net.cn/plugin?name=uv-ui)
|
||||
|
||||
#### 如使用过程中有任何问题,或者您对uv-ui有一些好的建议,欢迎加入 uv-ui 交流群:<a href="https://ext.dcloud.net.cn/plugin?id=12287" target="_blank">uv-ui</a>、<a href="https://www.uvui.cn/components/addQQGroup.html" target="_blank">官方QQ群</a>
|
@ -1,14 +0,0 @@
|
||||
## 1.0.5(2023-08-24)
|
||||
1. 修复标题文字过多未隐藏掉的BUG
|
||||
## 1.0.4(2023-07-24)
|
||||
1. 增加 滑动方向是否为纵向 属性vertical
|
||||
## 1.0.3(2023-06-27)
|
||||
1. 增加titleStyle属性,方便修改标题样式
|
||||
2. 标题上去掉是否是图片的判断,避免无后缀的图片不显示
|
||||
## 1.0.2(2023-06-01)
|
||||
1. 修复点击触发两次事件的BUG
|
||||
## 1.0.1(2023-05-16)
|
||||
1. 优化组件依赖,修改后无需全局引入,组件导入即可使用
|
||||
2. 优化部分功能
|
||||
## 1.0.0(2023-05-10)
|
||||
uv-swiper 轮播图,走马灯
|
@ -1,30 +0,0 @@
|
||||
export default {
|
||||
props: {
|
||||
// 轮播的长度
|
||||
length: {
|
||||
type: [String, Number],
|
||||
default: 0
|
||||
},
|
||||
// 当前处于活动状态的轮播的索引
|
||||
current: {
|
||||
type: [String, Number],
|
||||
default: 0
|
||||
},
|
||||
// 指示器非激活颜色
|
||||
indicatorActiveColor: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 指示器的激活颜色
|
||||
indicatorInactiveColor: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 指示器模式,line-线型,dot-点型
|
||||
indicatorMode: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
...uni.$uv?.props?.swiperIndicator
|
||||
}
|
||||
}
|
@ -1,112 +0,0 @@
|
||||
<template>
|
||||
<view class="uv-swiper-indicator">
|
||||
<view
|
||||
class="uv-swiper-indicator__wrapper"
|
||||
v-if="indicatorMode === 'line'"
|
||||
:class="[`uv-swiper-indicator__wrapper--${indicatorMode}`]"
|
||||
:style="{
|
||||
width: $uv.addUnit(lineWidth * length),
|
||||
backgroundColor: indicatorInactiveColor
|
||||
}"
|
||||
>
|
||||
<view
|
||||
class="uv-swiper-indicator__wrapper--line__bar"
|
||||
:style="[lineStyle]"
|
||||
></view>
|
||||
</view>
|
||||
<view
|
||||
class="uv-swiper-indicator__wrapper"
|
||||
v-if="indicatorMode === 'dot'"
|
||||
>
|
||||
<view
|
||||
class="uv-swiper-indicator__wrapper__dot"
|
||||
v-for="(item, index) in length"
|
||||
:key="index"
|
||||
:class="[index === current && 'uv-swiper-indicator__wrapper__dot--active']"
|
||||
:style="[dotStyle(index)]"
|
||||
>
|
||||
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import mpMixin from '@/uni_modules/uv-ui-tools/libs/mixin/mpMixin.js'
|
||||
import mixin from '@/uni_modules/uv-ui-tools/libs/mixin/mixin.js'
|
||||
import props from './props.js';
|
||||
/**
|
||||
* SwiperIndicator 轮播图指示器
|
||||
* @description 该组件一般用于导航轮播,广告展示等场景,可开箱即用,
|
||||
* @tutorial https://www.uvui.cn/components/swiper.html
|
||||
* @property {String | Number} length 轮播的长度(默认 0 )
|
||||
* @property {String | Number} current 当前处于活动状态的轮播的索引(默认 0 )
|
||||
* @property {String} indicatorActiveColor 指示器非激活颜色
|
||||
* @property {String} indicatorInactiveColor 指示器的激活颜色
|
||||
* @property {String} indicatorMode 指示器模式(默认 'line' )
|
||||
* @example <uv-swiper :list="list4" indicator keyName="url" :autoplay="false"></uv-swiper>
|
||||
*/
|
||||
export default {
|
||||
name: 'uv-swiper-indicator',
|
||||
mixins: [mpMixin, mixin, props],
|
||||
data() {
|
||||
return {
|
||||
lineWidth: 22
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
// 指示器为线型的样式
|
||||
lineStyle() {
|
||||
let style = {}
|
||||
style.width = this.$uv.addUnit(this.lineWidth)
|
||||
style.transform = `translateX(${ this.$uv.addUnit(this.current * this.lineWidth) })`
|
||||
style.backgroundColor = this.indicatorActiveColor
|
||||
return style
|
||||
},
|
||||
// 指示器为点型的样式
|
||||
dotStyle() {
|
||||
return index => {
|
||||
let style = {}
|
||||
style.backgroundColor = index === this.current ? this.indicatorActiveColor : this.indicatorInactiveColor
|
||||
return style
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '@/uni_modules/uv-ui-tools/libs/css/components.scss';
|
||||
|
||||
.uv-swiper-indicator {
|
||||
|
||||
&__wrapper {
|
||||
@include flex;
|
||||
|
||||
&--line {
|
||||
border-radius: 100px;
|
||||
height: 4px;
|
||||
|
||||
&__bar {
|
||||
width: 22px;
|
||||
height: 4px;
|
||||
border-radius: 100px;
|
||||
background-color: #FFFFFF;
|
||||
transition: transform 0.3s;
|
||||
}
|
||||
}
|
||||
|
||||
&__dot {
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
border-radius: 100px;
|
||||
margin: 0 4px;
|
||||
|
||||
&--active {
|
||||
width: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</style>
|
@ -1,136 +0,0 @@
|
||||
export default {
|
||||
props: {
|
||||
// 列表数组,元素可为字符串,如为对象可通过keyName指定目标属性名
|
||||
list: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
// 是否显示面板指示器
|
||||
indicator: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 指示器非激活颜色
|
||||
indicatorActiveColor: {
|
||||
type: String,
|
||||
default: '#fff'
|
||||
},
|
||||
// 指示器的激活颜色
|
||||
indicatorInactiveColor: {
|
||||
type: String,
|
||||
default: 'rgba(255, 255, 255, 0.35)'
|
||||
},
|
||||
// 指示器样式,可通过bottom,left,right进行定位
|
||||
indicatorStyle: {
|
||||
type: [String, Object],
|
||||
default: ''
|
||||
},
|
||||
// 指示器模式,line-线型,dot-点型
|
||||
indicatorMode: {
|
||||
type: String,
|
||||
default: 'line'
|
||||
},
|
||||
// 是否自动切换
|
||||
autoplay: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
// 当前所在滑块的 index
|
||||
current: {
|
||||
type: [String, Number],
|
||||
default: 0
|
||||
},
|
||||
// 当前所在滑块的 item-id ,不能与 current 被同时指定
|
||||
currentItemId: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 滑块自动切换时间间隔
|
||||
interval: {
|
||||
type: [String, Number],
|
||||
default: 3000
|
||||
},
|
||||
// 滑块切换过程所需时间
|
||||
duration: {
|
||||
type: [String, Number],
|
||||
default: 300
|
||||
},
|
||||
// 播放到末尾后是否重新回到开头
|
||||
circular: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 滑动方向是否为纵向
|
||||
vertical: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 前边距,可用于露出前一项的一小部分,nvue和支付宝不支持
|
||||
previousMargin: {
|
||||
type: [String, Number],
|
||||
default: 0
|
||||
},
|
||||
// 后边距,可用于露出后一项的一小部分,nvue和支付宝不支持
|
||||
nextMargin: {
|
||||
type: [String, Number],
|
||||
default: 0
|
||||
},
|
||||
// 当开启时,会根据滑动速度,连续滑动多屏,支付宝不支持
|
||||
acceleration: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 同时显示的滑块数量,nvue、支付宝小程序不支持
|
||||
displayMultipleItems: {
|
||||
type: Number,
|
||||
default: 1
|
||||
},
|
||||
// 指定swiper切换缓动动画类型,有效值:default、linear、easeInCubic、easeOutCubic、easeInOutCubic
|
||||
// 只对微信小程序有效
|
||||
easingFunction: {
|
||||
type: String,
|
||||
default: 'default'
|
||||
},
|
||||
// list数组中指定对象的目标属性名
|
||||
keyName: {
|
||||
type: String,
|
||||
default: 'url'
|
||||
},
|
||||
// 图片的裁剪模式
|
||||
imgMode: {
|
||||
type: String,
|
||||
default: 'aspectFill'
|
||||
},
|
||||
// 组件高度
|
||||
height: {
|
||||
type: [String, Number],
|
||||
default: 130
|
||||
},
|
||||
// 背景颜色
|
||||
bgColor: {
|
||||
type: String,
|
||||
default: '#f3f4f6'
|
||||
},
|
||||
// 组件圆角,数值或带单位的字符串
|
||||
radius: {
|
||||
type: [String, Number],
|
||||
default: 4
|
||||
},
|
||||
// 是否加载中
|
||||
loading: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 是否显示标题,要求数组对象中有title属性
|
||||
showTitle: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// 显示的标题样式
|
||||
titleStyle: {
|
||||
type: Object,
|
||||
default: ()=>{}
|
||||
},
|
||||
...uni.$uv?.props?.swiper
|
||||
}
|
||||
}
|
@ -1,263 +0,0 @@
|
||||
<template>
|
||||
<view
|
||||
class="uv-swiper"
|
||||
:style="{
|
||||
backgroundColor: bgColor,
|
||||
height: $uv.addUnit(height),
|
||||
borderRadius: $uv.addUnit(radius)
|
||||
}"
|
||||
>
|
||||
<view
|
||||
class="uv-swiper__loading"
|
||||
v-if="loading"
|
||||
>
|
||||
<uv-loading-icon mode="circle"></uv-loading-icon>
|
||||
</view>
|
||||
<swiper
|
||||
v-else
|
||||
class="uv-swiper__wrapper"
|
||||
:style="{
|
||||
height: $uv.addUnit(height),
|
||||
flex: 1
|
||||
}"
|
||||
@change="change"
|
||||
:circular="circular"
|
||||
:vertical="vertical"
|
||||
:interval="interval"
|
||||
:duration="duration"
|
||||
:autoplay="autoplay"
|
||||
:current="current"
|
||||
:currentItemId="currentItemId"
|
||||
:previousMargin="$uv.addUnit(previousMargin)"
|
||||
:nextMargin="$uv.addUnit(nextMargin)"
|
||||
:acceleration="acceleration"
|
||||
:displayMultipleItems="displayMultipleItems"
|
||||
:easingFunction="easingFunction"
|
||||
>
|
||||
<swiper-item
|
||||
class="uv-swiper__wrapper__item"
|
||||
v-for="(item, index) in list"
|
||||
:key="index"
|
||||
>
|
||||
<view
|
||||
class="uv-swiper__wrapper__item__wrapper"
|
||||
:style="[itemStyle(index)]"
|
||||
>
|
||||
<!-- 在nvue中,image图片的宽度默认为屏幕宽度,需要通过flex:1撑开,另外必须设置高度才能显示图片 -->
|
||||
<image
|
||||
class="uv-swiper__wrapper__item__wrapper__image"
|
||||
v-if="getItemType(item) === 'image'"
|
||||
:src="getSource(item)"
|
||||
:mode="imgMode"
|
||||
@tap="clickHandler(index)"
|
||||
:style="{
|
||||
height: $uv.addUnit(height),
|
||||
borderRadius: $uv.addUnit(radius)
|
||||
}"
|
||||
></image>
|
||||
<video
|
||||
class="uv-swiper__wrapper__item__wrapper__video"
|
||||
v-if="getItemType(item) === 'video'"
|
||||
:id="`video-${index}`"
|
||||
:enable-progress-gesture="false"
|
||||
:src="getSource(item)"
|
||||
:poster="getPoster(item)"
|
||||
:title="showTitle && $uv.test.object(item) && item.title ? item.title : ''"
|
||||
:style="{
|
||||
height: $uv.addUnit(height)
|
||||
}"
|
||||
controls
|
||||
@tap="clickHandler(index)"
|
||||
></video>
|
||||
<text
|
||||
v-if="showTitle && $uv.test.object(item) && item.title"
|
||||
class="uv-swiper__wrapper__item__wrapper__title uv-line-1"
|
||||
:style="[$uv.addStyle(titleStyle)]"
|
||||
>{{ item.title }}</text>
|
||||
</view>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
<view class="uv-swiper__indicator" :style="[$uv.addStyle(indicatorStyle)]">
|
||||
<slot name="indicator">
|
||||
<uv-swiper-indicator
|
||||
v-if="!loading && indicator && !showTitle"
|
||||
:indicatorActiveColor="indicatorActiveColor"
|
||||
:indicatorInactiveColor="indicatorInactiveColor"
|
||||
:length="list.length"
|
||||
:current="currentIndex"
|
||||
:indicatorMode="indicatorMode"
|
||||
></uv-swiper-indicator>
|
||||
</slot>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import mpMixin from '@/uni_modules/uv-ui-tools/libs/mixin/mpMixin.js'
|
||||
import mixin from '@/uni_modules/uv-ui-tools/libs/mixin/mixin.js'
|
||||
import props from './props.js';
|
||||
/**
|
||||
* Swiper 轮播图
|
||||
* @description 该组件一般用于导航轮播,广告展示等场景,可开箱即用,
|
||||
* @tutorial https://www.uvui.cn/components/swiper.html
|
||||
* @property {Array} list 轮播图数据
|
||||
* @property {Boolean} indicator 是否显示面板指示器(默认 false )
|
||||
* @property {String} indicatorActiveColor 指示器非激活颜色(默认 '#FFFFFF' )
|
||||
* @property {String} indicatorInactiveColor 指示器的激活颜色(默认 'rgba(255, 255, 255, 0.35)' )
|
||||
* @property {String | Object} indicatorStyle 指示器样式,可通过bottom,left,right进行定位
|
||||
* @property {String} indicatorMode 指示器模式(默认 'line' )
|
||||
* @property {Boolean} autoplay 是否自动切换(默认 true )
|
||||
* @property {String | Number} current 当前所在滑块的 index(默认 0 )
|
||||
* @property {String} currentItemId 当前所在滑块的 item-id ,不能与 current 被同时指定
|
||||
* @property {String | Number} interval 滑块自动切换时间间隔(ms)(默认 3000 )
|
||||
* @property {String | Number} duration 滑块切换过程所需时间(ms)(默认 300 )
|
||||
* @property {Boolean} circular 播放到末尾后是否重新回到开头(默认 false )
|
||||
* @property {String | Number} previousMargin 前边距,可用于露出前一项的一小部分,nvue和支付宝不支持(默认 0 )
|
||||
* @property {String | Number} nextMargin 后边距,可用于露出后一项的一小部分,nvue和支付宝不支持(默认 0 )
|
||||
* @property {Boolean} acceleration 当开启时,会根据滑动速度,连续滑动多屏,支付宝不支持(默认 false )
|
||||
* @property {Number} displayMultipleItems 同时显示的滑块数量,nvue、支付宝小程序不支持(默认 1 )
|
||||
* @property {String} easingFunction 指定swiper切换缓动动画类型, 只对微信小程序有效(默认 'default' )
|
||||
* @property {String} keyName list数组中指定对象的目标属性名(默认 'url' )
|
||||
* @property {String} imgMode 图片的裁剪模式(默认 'aspectFill' )
|
||||
* @property {String | Number} height 组件高度(默认 130 )
|
||||
* @property {String} bgColor 背景颜色(默认 '#f3f4f6' )
|
||||
* @property {String | Number} radius 组件圆角,数值或带单位的字符串(默认 4 )
|
||||
* @property {Boolean} loading 是否加载中(默认 false )
|
||||
* @property {Boolean} showTitle 是否显示标题,要求数组对象中有title属性(默认 false )
|
||||
* @event {Function(index)} click 点击轮播图时触发 index:点击了第几张图片,从0开始
|
||||
* @event {Function(index)} change 轮播图切换时触发(自动或者手动切换) index:切换到了第几张图片,从0开始
|
||||
* @example <uv-swiper :list="list4" keyName="url" :autoplay="false"></uv-swiper>
|
||||
*/
|
||||
export default {
|
||||
name: 'uv-swiper',
|
||||
mixins: [mpMixin, mixin, props],
|
||||
emits: ['click','change'],
|
||||
data() {
|
||||
return {
|
||||
currentIndex: 0
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
current(val, preVal) {
|
||||
if(val === preVal) return;
|
||||
this.currentIndex = val; // 和上游数据关联上
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
itemStyle() {
|
||||
return index => {
|
||||
const style = {}
|
||||
// #ifndef APP-NVUE || MP-TOUTIAO
|
||||
// 左右流出空间的写法不支持nvue和头条
|
||||
// 只有配置了此二值,才加上对应的圆角,以及缩放
|
||||
if (this.nextMargin && this.previousMargin) {
|
||||
style.borderRadius = this.$uv.addUnit(this.radius)
|
||||
if (index !== this.currentIndex) style.transform = 'scale(0.92)'
|
||||
}
|
||||
// #endif
|
||||
return style
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getItemType(item) {
|
||||
if (typeof item === 'string') return this.$uv.test.video(this.getSource(item)) ? 'video' : 'image'
|
||||
if (typeof item === 'object' && this.keyName) {
|
||||
if (!item.type) return this.$uv.test.video(this.getSource(item)) ? 'video' : 'image'
|
||||
if (item.type === 'image') return 'image'
|
||||
if (item.type === 'video') return 'video'
|
||||
return 'image'
|
||||
}
|
||||
},
|
||||
// 获取目标路径,可能数组中为字符串,对象的形式,额外可指定对象的目标属性名keyName
|
||||
getSource(item) {
|
||||
if (typeof item === 'string') return item
|
||||
if (typeof item === 'object' && this.keyName) return item[this.keyName]
|
||||
else this.$uv.error('请按格式传递列表参数')
|
||||
return ''
|
||||
},
|
||||
// 轮播切换事件
|
||||
change(e) {
|
||||
// 当前的激活索引
|
||||
const {
|
||||
current
|
||||
} = e.detail
|
||||
this.pauseVideo(this.currentIndex)
|
||||
this.currentIndex = current
|
||||
this.$emit('change', e.detail)
|
||||
},
|
||||
// 切换轮播时,暂停视频播放
|
||||
pauseVideo(index) {
|
||||
const lastItem = this.getSource(this.list[index])
|
||||
if (this.$uv.test.video(lastItem)) {
|
||||
// 当视频隐藏时,暂停播放
|
||||
const video = uni.createVideoContext(`video-${index}`, this)
|
||||
video.pause()
|
||||
}
|
||||
},
|
||||
// 当一个轮播item为视频时,获取它的视频海报
|
||||
getPoster(item) {
|
||||
return typeof item === 'object' && item.poster ? item.poster : ''
|
||||
},
|
||||
// 点击某个item
|
||||
clickHandler(index) {
|
||||
this.$emit('click', index)
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
$show-lines: 1;
|
||||
@import '@/uni_modules/uv-ui-tools/libs/css/variable.scss';
|
||||
@import '@/uni_modules/uv-ui-tools/libs/css/components.scss';
|
||||
.uv-swiper {
|
||||
@include flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
&__wrapper {
|
||||
flex: 1;
|
||||
|
||||
&__item {
|
||||
flex: 1;
|
||||
|
||||
&__wrapper {
|
||||
@include flex;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
transition: transform 0.3s;
|
||||
flex: 1;
|
||||
|
||||
&__image {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
&__video {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
&__title {
|
||||
position: absolute;
|
||||
background-color: rgba(0, 0, 0, 0.3);
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
font-size: 28rpx;
|
||||
height: 60rpx;
|
||||
line-height: 60rpx;
|
||||
color: #FFFFFF;
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__indicator {
|
||||
position: absolute;
|
||||
bottom: 10px;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -1,88 +0,0 @@
|
||||
{
|
||||
"id": "uv-swiper",
|
||||
"displayName": "uv-swiper 轮播图 全面兼容vue3+2、app、h5、小程序等多端",
|
||||
"version": "1.0.5",
|
||||
"description": "该组件为轮播、跑马灯,支持卡片式。一般用于导航轮播,广告展示等场景,开箱即用",
|
||||
"keywords": [
|
||||
"swiper",
|
||||
"uvui",
|
||||
"uv-ui",
|
||||
"轮播图",
|
||||
"走马灯"
|
||||
],
|
||||
"repository": "",
|
||||
"engines": {
|
||||
"HBuilderX": "^3.1.0"
|
||||
},
|
||||
"dcloudext": {
|
||||
"type": "component-vue",
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "插件不采集任何数据",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": ""
|
||||
},
|
||||
"uni_modules": {
|
||||
"dependencies": [
|
||||
"uv-ui-tools",
|
||||
"uv-loading-icon"
|
||||
],
|
||||
"encrypt": [],
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y"
|
||||
},
|
||||
"client": {
|
||||
"Vue": {
|
||||
"vue2": "y",
|
||||
"vue3": "y"
|
||||
},
|
||||
"App": {
|
||||
"app-vue": "y",
|
||||
"app-nvue": "y"
|
||||
},
|
||||
"H5-mobile": {
|
||||
"Safari": "y",
|
||||
"Android Browser": "y",
|
||||
"微信浏览器(Android)": "y",
|
||||
"QQ浏览器(Android)": "y"
|
||||
},
|
||||
"H5-pc": {
|
||||
"Chrome": "y",
|
||||
"IE": "y",
|
||||
"Edge": "y",
|
||||
"Firefox": "y",
|
||||
"Safari": "y"
|
||||
},
|
||||
"小程序": {
|
||||
"微信": "y",
|
||||
"阿里": "y",
|
||||
"百度": "y",
|
||||
"字节跳动": "y",
|
||||
"QQ": "y",
|
||||
"钉钉": "u",
|
||||
"快手": "u",
|
||||
"飞书": "u",
|
||||
"京东": "u"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "u",
|
||||
"联盟": "u"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
## Swiper 轮播图
|
||||
|
||||
> **组件名:uv-swiper**
|
||||
|
||||
该组件为轮播、跑马灯,支持卡片式。一般用于导航轮播,广告展示等场景,开箱即用。
|
||||
|
||||
# <a href="https://www.uvui.cn/components/swiper.html" target="_blank">查看文档</a>
|
||||
|
||||
## [下载完整示例项目](https://ext.dcloud.net.cn/plugin?name=uv-ui) <small>(请不要 下载插件ZIP)</small>
|
||||
|
||||
### [更多插件,请关注uv-ui组件库](https://ext.dcloud.net.cn/plugin?name=uv-ui)
|
||||
|
||||
<a href="https://ext.dcloud.net.cn/plugin?name=uv-ui" target="_blank">
|
||||
|
||||

|
||||
|
||||
</a>
|
||||
|
||||
#### 如使用过程中有任何问题反馈,或者您对uv-ui有一些好的建议,欢迎加入uv-ui官方交流群:<a href="https://www.uvui.cn/components/addQQGroup.html" target="_blank">官方QQ群</a>
|
Loading…
Reference in New Issue
Block a user