This commit is contained in:
yyy 2024-12-07 16:50:20 +08:00
parent 61ab038c4e
commit 1b4278010e
91 changed files with 55 additions and 11039 deletions

26
App.vue
View File

@ -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>

View File

@ -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": "我的",

View File

@ -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 {

View File

@ -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>

View File

@ -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 = () => {

View File

@ -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>

View File

@ -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>

View File

@ -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";
}

View File

@ -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

View File

@ -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';

View File

@ -1,8 +0,0 @@
## 1.0.22023-07-03
1. 优化插槽自定义内容部分
2. 增加backToTop方法说明
## 1.0.12023-05-16
1. 优化组件依赖,修改后无需全局引入,组件导入即可使用
2. 优化部分功能
## 1.0.02023-05-10
uv-back-top 返回顶部

View File

@ -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
}
}

View File

@ -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>

View File

@ -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"
}
}
}
}
}

View File

@ -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>

View File

@ -1,32 +0,0 @@
## 1.0.132023-10-11
1. 优化同类问题https://gitee.com/climblee/uv-ui/issues/I872VD
## 1.0.122023-09-22
1. 修复change回调中v-model值不更新的BUG
## 1.0.112023-09-01
1. 修复点击空隙处无效的问题
2. label支持插槽下可点击
## 1.0.102023-08-27
1. 修复label设置布尔值不生效的BUG
## 1.0.92023-08-16
1. 解决数据多不换行的BUG
## 1.0.82023-07-13
1. 修复 uv-checkbox设置value属性不生效的BUG
## 1.0.72023-07-05
修复vue3模式下动态修改v-model绑定的值无效的BUG
## 1.0.62023-06-29
1. 增加label插槽与radio保持一致
2. 优化文档
## 1.0.52023-06-12
1. 修复1.0.4改出的问题
## 1.0.42023-06-08
1. 复选框修复全局设置不生效的BUG
## 1.0.32023-06-06
1. uv-checkbox-group 兼容自定义样式customStyle方便通过样式调整整体位置等
2. .uv-checkbox-group--row增加flex-wrap: wrap;允许换行
## 1.0.22023-05-30
1. 修复error报错的BUG
## 1.0.12023-05-16
1. 优化组件依赖,修改后无需全局引入,组件导入即可使用
2. 优化部分功能
## 1.0.02023-05-10
uv-checkbox 复选框

View File

@ -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
}
}

View File

@ -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: {
// computeduv-checkbox
// parentDatawatch(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.bemcomputedmixin
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>

View File

@ -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
}
}

View File

@ -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;
},
// size21px
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) {
// disabledcheckboxelInactiveColor
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-groupvaluearray
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')
})
},
//
// checkedtrueuv-checkbox
// uv-checkboxcheckedfalse()
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;
// nvueborder-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>

View File

@ -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"
}
}
}
}
}

View File

@ -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">
![image](https://mp-a667b617-c5f1-4a2d-9a54-683a67cff588.cdn.bspapp.com/uv-ui/banner.png)
</a>
#### 如使用过程中有任何问题反馈或者您对uv-ui有一些好的建议欢迎加入uv-ui官方交流群<a href="https://www.uvui.cn/components/addQQGroup.html" target="_blank">官方QQ群</a>

View File

@ -1,5 +0,0 @@
## 1.0.12023-05-16
1. 优化组件依赖,修改后无需全局引入,组件导入即可使用
2. 优化部分功能
## 1.0.02023-05-10
uv-no-network 无网络提示

File diff suppressed because one or more lines are too long

View File

@ -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>

View File

@ -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"
}
}
}
}
}

View File

@ -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>

View File

@ -1,11 +0,0 @@
## 1.0.42023-07-17
1. 优化文档
2. 优化其他
## 1.0.32023-06-26
1. H5增加属性h5SaveTip 保存二维码时候是否显示提示
## 1.0.22023-06-01
1. 修复点击触发两次事件的BUG
## 1.0.12023-05-23
1. 修复在部分平台不显示加载效果的BUG
## 1.0.02023-05-17
1. 新增uv-qrcode组件

View File

@ -1 +0,0 @@
export const cacheImageList = [];

View File

@ -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;

View File

@ -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;

View File

@ -1,8 +0,0 @@
class FillStylePattern {
constructor(img, pattern) {
this._style = pattern;
this._img = img;
}
}
export default FillStylePattern;

View File

@ -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;

View File

@ -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);
}
});
}
}

View File

@ -1,11 +0,0 @@
export default class WebGLActiveInfo {
className = 'WebGLActiveInfo';
constructor({
type, name, size
}) {
this.type = type;
this.name = name;
this.size = size;
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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
};

View File

@ -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;

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -1,11 +0,0 @@
export default class WebGLShaderPrecisionFormat {
className = 'WebGLShaderPrecisionFormat';
constructor({
rangeMin, rangeMax, precision
}) {
this.rangeMin = rangeMin;
this.rangeMax = rangeMax;
this.precision = precision;
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -1,3 +0,0 @@
export function getTransferedObjectUUID(name, id) {
return `${name.toLowerCase()}-${id}`;
}

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
};

View File

@ -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

View File

@ -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

View File

@ -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"
}
}
}
}
}

View File

@ -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">
![image](https://mp-a667b617-c5f1-4a2d-9a54-683a67cff588.cdn.bspapp.com/uv-ui/banner.png)
</a>
#### 如使用过程中有任何问题反馈或者您对uv-ui有一些好的建议欢迎加入uv-ui官方交流群<a href="https://www.uvui.cn/components/addQQGroup.html" target="_blank">官方QQ群</a>

View File

@ -1,10 +0,0 @@
## 1.0.32023-06-29
1. 增加customStyle参数方便设置样式
## 1.0.22023-06-29
1. 新增title自定义
2. 完善文档说明
## 1.0.12023-05-16
1. 优化组件依赖,修改后无需全局引入,组件导入即可使用
2. 优化部分功能
## 1.0.02023-05-10
uv-steps 步骤条

View File

@ -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
}
}

View File

@ -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>

View File

@ -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
}
}

View File

@ -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>

View File

@ -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"
}
}
}
}
}

View File

@ -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>

View File

@ -1,11 +0,0 @@
## 1.0.42023-10-13
1. 优化
## 1.0.32023-10-13
1. unmounted兼容vue3
## 1.0.22023-05-27
1. 不支持抖音小程序说明
## 1.0.12023-05-16
1. 优化组件依赖,修改后无需全局引入,组件导入即可使用
2. 优化部分功能
## 1.0.02023-05-10
uv-swipe-action 滑动单元格

View File

@ -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
}

View File

@ -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
}

View File

@ -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)
})
})
}
}
}

View File

@ -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
}

View File

@ -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
}
}

View File

@ -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>

View File

@ -1,15 +0,0 @@
export default {
methods: {
// 关闭时执行
closeHandler() {
this.status = 'close'
},
setState(status) {
this.status = status
},
closeOther() {
// 尝试关闭其他打开的单元格
this.parent && this.parent.closeOther(this)
}
}
}

View File

@ -1,10 +0,0 @@
export default {
props: {
// 是否自动关闭其他swipe按钮组
autoClose: {
type: Boolean,
default: true
},
...uni.$uv?.props?.swipeAction
}
}

View File

@ -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: {
// computeduv-swipe-action-item
// parentDatawatch(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>

View File

@ -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"
}
}
}
}
}

View File

@ -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>

View File

@ -1,14 +0,0 @@
## 1.0.52023-08-24
1. 修复标题文字过多未隐藏掉的BUG
## 1.0.42023-07-24
1. 增加 滑动方向是否为纵向 属性vertical
## 1.0.32023-06-27
1. 增加titleStyle属性方便修改标题样式
2. 标题上去掉是否是图片的判断,避免无后缀的图片不显示
## 1.0.22023-06-01
1. 修复点击触发两次事件的BUG
## 1.0.12023-05-16
1. 优化组件依赖,修改后无需全局引入,组件导入即可使用
2. 优化部分功能
## 1.0.02023-05-10
uv-swiper 轮播图,走马灯

View File

@ -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
}
}

View File

@ -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>

View File

@ -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)'
},
// 指示器样式可通过bottomleftright进行定位
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
}
}

View File

@ -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 指示器样式可通过bottomleftright进行定位
* @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>

View File

@ -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"
}
}
}
}
}

View File

@ -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">
![image](https://mp-a667b617-c5f1-4a2d-9a54-683a67cff588.cdn.bspapp.com/uv-ui/banner.png)
</a>
#### 如使用过程中有任何问题反馈或者您对uv-ui有一些好的建议欢迎加入uv-ui官方交流群<a href="https://www.uvui.cn/components/addQQGroup.html" target="_blank">官方QQ群</a>