This commit is contained in:
ghusermoon 2020-06-11 17:54:15 +08:00
parent 0481322bdb
commit f5b61b7247
135 changed files with 38192 additions and 45 deletions

16
.vscode/ftp-kr.json vendored Normal file
View File

@ -0,0 +1,16 @@
{
"host": "192.168.3.137",
"username": "hdemingshangjia",
"password": "123456",
"remotePath": "/",
"protocol": "ftp",
"port": 14147,
"fileNameEncoding": "utf8",
"autoUpload": true,
"autoDelete": false,
"autoDownload": false,
"ignore": [
".git",
"/.vscode"
]
}

37
.vscode/ftp-kr.sync.cache.json vendored Normal file
View File

@ -0,0 +1,37 @@
{
"ftp://192.168.3.137:14147@hdemingshangjia": {
"App.vue": {
"type": "-",
"size": 270,
"lmtime": 0,
"modified": false
},
"main.js": {
"type": "-",
"size": 160,
"lmtime": 0,
"modified": false
},
"manifest.json": {
"type": "-",
"size": 3360,
"lmtime": 0,
"modified": false
},
"pages": {},
"pages.json": {
"type": "-",
"size": 408,
"lmtime": 0,
"modified": false
},
"static": {},
"uni.scss": {
"type": "-",
"size": 2311,
"lmtime": 0,
"modified": false
}
},
"$version": 1
}

View File

@ -12,6 +12,7 @@
}
</script>
<style>
<style lang="scss">
/*每个页面公共css */
</style>
@import "uview-ui/index.scss";
</style>

View File

@ -0,0 +1,81 @@
<template>
<view class="item" @click="toDetailsPage">
<image></image>
<view class="goods">
<view class="status" v-if="cur==4">待处理订单</view>
<view class="name u-line-1">心机小黑裙连衣裙赫本风夏季爆款...</view>
<view class="info">
<view class="num">共一件商品</view>
<view class="price">实付<span>199.9</span></view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {}
},
props: {
cur: [Number, String]
},
methods: {
toDetailsPage() {
console.log(1)
uni.navigateTo({
url: '/pages/index/details'
});
},
},
};
</script>
<style lang="scss" scoped>
.item {
margin: 0 auto 20rpx;
width: 690rpx;
height: 220rpx;
background: rgba(255,255,255,1);
border-radius: 10rpx;
padding: 30rpx;
display: flex;
align-items: center;
> image {
width: 160rpx;
height: 160rpx;
flex-shrink: 0;
margin-right: 25rpx;
background-color: aqua;
}
.goods {
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: center;
.status {
align-self: flex-end;
font-size: 26rpx;
color: rgba(255,49,49,1);
margin-bottom: 30rpx;
}
.name {
width: 439rpx;
font-size: 28rpx;
color: rgba(51,51,51,1);
margin-bottom: 30rpx;
}
.info {
width: 100%;
display: flex;
align-items: center;
font-size: 26rpx;
color: rgba(102,102,102,1);
.price {
margin-left: 10rpx;
> span {
color: #FF780F;
}
}
}
}
}
</style>

View File

@ -1,6 +1,9 @@
import Vue from 'vue'
import App from './App'
import uView from "uview-ui";
Vue.use(uView);
Vue.config.productionTip = false
App.mpType = 'app'
@ -8,4 +11,4 @@ App.mpType = 'app'
const app = new Vue({
...App
})
app.$mount()
app.$mount()

21
node_modules/uview-ui/LICENSE generated vendored Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2020 www.uviewui.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

102
node_modules/uview-ui/README.md generated vendored Normal file
View File

@ -0,0 +1,102 @@
<p align="center">
<img alt="logo" src="https://uviewui.com/common/logo.png" width="120" height="120" style="margin-bottom: 10px;">
</p>
<h3 align="center" style="margin: 30px 0 30px;font-weight: bold;font-size:40px;">uView</h3>
<h3 align="center">多平台快速开发的UI框架</h3>
## 说明
uView UI是[uni-app](https://uniapp.dcloud.io/)生态优秀的UI框架全面的组件和便捷的工具会让您信手拈来如鱼得水
## 特性
- 兼容安卓iOS微信小程序H5QQ小程序百度小程序支付宝小程序头条小程序
- 60+精选组件,功能丰富,多端兼容,让您快速集成,开箱即用
- 众多贴心的JS利器让您飞镖在手召之即来百步穿杨
- 众多的常用页面和布局,让您专注逻辑,事半功倍
- 详尽的文档支持,现代化的演示效果
- 按需引入,精简打包体积
## 安装
```bash
# npm方式安装
npm i uview-ui
```
## 快速上手
1. `main.js`引入uView库
```js
// main.js
import uView from 'uview-ui';
Vue.use(uView);
```
2. `App.vue`引入基础样式(注意style标签需声明scss属性支持)
```css
/* App.vue */
<style lang="scss">
@import "uview-ui/index.scss";
</style>
```
3. `uni.scss`引入全局scss变量文件
```css
/* uni.scss */
@import "uview-ui/theme.scss";
```
4. `pages.json`配置easycom规则(按需引入)
```js
// pages.json
{
"easycom": {
"^u-(.*)": "uview-ui/components/u-$1/u-$1.vue"
},
// 此为本身已有的内容
"pages": [
// ......
]
}
```
请通过[快速上手](https://uviewui.com/components/quickstart.html)了解更详细的内容
## 使用方法
配置easycom规则后自动按需引入无需`import`组件,直接引用即可。
```html
<template>
<u-button>按钮</u-button>
</template>
```
请通过[快速上手](https://uviewui.com/components/quickstart.html)了解更详细的内容
## 链接
- [官方文档](https://uviewui.com/)
- [更新日志](https://uviewui.com/components/changelog.html)
- [升级指南](https://uviewui.com/components/changelog.html)
- [关于我们](https://uviewui.com/cooperation/about.html)
## 预览
您可以通过**微信**扫码,查看最佳的演示效果。
<br>
<br>
<img src="https://uviewui.com/common/weixin_mini_qrcode.png" width="220" height="220" >
<!-- ## 捐赠uView的研发
uView文档和源码全部开源免费如果您认为uView帮到了您的开发工作您可以捐赠uView的研发工作捐赠无门槛哪怕是一杯可乐也好(相信这比打赏主播更有意义)。
<img src="https://uviewui.com/common/wechat.png" width="220" >
<img style="margin-left: 100px;" src="https://uviewui.com/common/alipay.png" width="220" >
-->
## 版权信息
uView遵循[MIT](https://en.wikipedia.org/wiki/MIT_License)开源协议意味着您无需支付任何费用也无需授权即可将uView应用到您的产品中。

View File

@ -0,0 +1,170 @@
<template>
<u-popup mode="bottom" :border-radius="borderRadius" :popup="false" v-model="value" :maskCloseAble="maskCloseAble"
length="auto" :safeAreaInsetBottom="safeAreaInsetBottom" @close="popupClose" :z-index="uZIndex">
<view class="u-tips u-border-bottom" v-if="tips.text" :style="[tipsStyle]">
{{tips.text}}
</view>
<block v-for="(item, index) in list" :key="index">
<view @touchmove.stop.prevent @tap="itemClick(index)" :style="[itemStyle(index)]" class="u-action-sheet-item" :class="[index < list.length - 1 ? 'u-border-bottom' : '']"
hover-class="u-hover-class" :hover-stay-time="150">
{{item.text}}
</view>
</block>
<view class="u-gab" v-if="cancelBtn">
</view>
<view @touchmove.stop.prevent class="u-actionsheet-cancel u-action-sheet-item" hover-class="u-hover-class"
:hover-stay-time="150" v-if="cancelBtn" @tap="close">{{cancelText}}</view>
</u-popup>
</template>
<script>
/**
* actionSheet 操作菜单
* @description 本组件用于从底部弹出一个操作菜单供用户选择并返回结果本组件功能类似于uni的uni.showActionSheetAPI配置更加灵活所有平台都表现一致
* @tutorial https://www.uviewui.com/components/actionSheet.html
* @property {Array<Object>} list 按钮的文字数组见官方文档示例
* @property {Object} tips 顶部的提示文字见官方文档示例
* @property {String} cancel-text 取消按钮的提示文字
* @property {Boolean} cancel-btn 是否显示底部的取消按钮默认true
* @property {Number String} border-radius 弹出部分顶部左右的圆角值单位rpx默认0
* @property {Boolean} mask-close-able 点击遮罩是否可以关闭默认true
* @property {Boolean} safe-area-inset-bottom 是否开启底部安全区适配默认false
* @property {Number String} z-index z-index值默认1075
* @property {String} cancel-text 取消按钮的提示文字
* @event {Function} click 点击ActionSheet列表项时触发
* @event {Function} close 点击取消按钮时触发
* @example <u-action-sheet :list="list" @click="click" v-model="show"></u-action-sheet>
*/
export default {
name: "u-action-sheet",
props: {
// actionsheet
maskCloseAble: {
type: Boolean,
default: true
},
// rpx
list: {
type: Array,
default () {
//
// return [{
// text: '',
// color: '',
// fontSize: ''
// }]
return [];
}
},
//
tips: {
type: Object,
default () {
return {
text: '',
color: '',
fontSize: '26'
}
}
},
//
cancelBtn: {
type: Boolean,
default: true
},
// iPhoneX
safeAreaInsetBottom: {
type: Boolean,
default: false
},
//
value: {
type: Boolean,
default: false
},
//
borderRadius: {
type: [String, Number],
default: 0
},
// z-index
zIndex: {
type: [String, Number],
default: 0
},
//
cancelText: {
type: String,
default: '取消'
}
},
computed: {
//
tipsStyle() {
let style = {};
if (this.tips.color) style.color = this.tips.color;
if (this.tips.fontSize) style.fontSize = this.tips.fontSize + 'rpx';
return style;
},
//
itemStyle() {
return (index) => {
let style = {};
if (this.list[index].color) style.color = this.list[index].color;
if (this.list[index].fontSize) style.fontSize = this.list[index].fontSize + 'rpx';
return style;
}
},
uZIndex() {
// z-index使
return this.zIndex ? this.zIndex : this.$u.zIndex.popup;
}
},
methods: {
//
close() {
// inputpropsvalue
// vue
this.popupClose();
this.$emit('close');
},
//
popupClose() {
this.$emit('input', false);
},
// itemif (!this.show) return;
itemClick(index) {
this.$emit('click', index);
this.$emit('input', false);
}
}
}
</script>
<style lang="scss" scoped>
.u-tips {
font-size: 26rpx;
text-align: center;
padding: 34rpx 0;
line-height: 1;
color: $u-tips-color;
}
.u-action-sheet-item {
display: flex;
line-height: 1;
justify-content: center;
align-items: center;
font-size: 34rpx;
padding: 34rpx 0;
}
.u-gab {
height: 12rpx;
background-color: rgb(234, 234, 236);
}
.u-actionsheet-cancel {
color: $u-main-color;
}
</style>

View File

@ -0,0 +1,189 @@
<template>
<view class="u-alert-tips" v-if="show" :class="{'u-close-alert-tips': !show}" :style="{
backgroundColor: computeBgColor,
borderColor: computeBorderColor
}">
<view class="u-icon-wrap">
<u-icon v-if="showIcon" :name="$u.type2icon(type)" :size="description ? 40 : 32" class="u-icon" :color="computeColor"></u-icon>
</view>
<view class="u-alert-content" @tap.stop="click">
<view class="u-alert-title" :style="{fontWeight: description ? 500 : 'normal'}">
{{title}}
</view>
<view v-if="description" class="u-alert-desc">
{{description}}
</view>
</view>
<view class="u-icon-wrap">
<u-icon @click="close" v-if="closeAble && !closeText" hoverClass="u-type-error-hover-color" name="close" color="#c0c4cc"
:size="22" class="u-close-icon" :style="{
top: description ? '18rpx' : '24rpx'
}"></u-icon>
</view>
<text v-if="closeAble && closeText" class="u-close-text" :style="{
top: description ? '18rpx' : '24rpx'
}">{{closeText}}</text>
</view>
</template>
<script>
/**
* alertTips 警告提示
* @description 警告提示展现需要关注的信息
* @tutorial https://uviewui.com/components/alertTips.html
* @property {String} title 显示的标题文字
* @property {String} description 辅助性文字颜色比title浅一点字号也小一点可选
* @property {String} type 关闭按钮(默认为叉号icon图标)
* @property {String} close-able 用文字替代关闭图标close-able为true时有效
* @property {Boolean} show-icon 是否显示左边的辅助图标
* @property {Boolean} show 显示或隐藏组件
* @event {Function} click 点击组件时触发
* @event {Function} close 点击关闭按钮时触发
*/
export default {
name: 'u-alert-tips',
props: {
//
title: {
type: String,
default: ''
},
// success/warning/info/error
type: {
type: String,
default: 'warning'
},
//
description: {
type: String,
default: ''
},
//
closeAble: {
type: Boolean,
default: false
},
//
closeText: {
type: String,
default: ''
},
//
showIcon: {
type: Boolean,
default: false
},
// coloricon
color: {
type: String,
default: ''
},
//
bgColor: {
type: String,
default: ''
},
//
borderColor: {
type: String,
default: ''
},
//
show: {
type: Boolean,
default: true
}
},
data() {
return {
}
},
computed: {
// uview
computeColor() {
if (this.color) return this.color;
else return this.$u.color[this.type];
},
//
computeBgColor() {
if (this.bgColor) return this.bgColor;
return this.$u.color[this.type + 'Light'];
},
computeBorderColor() {
if (this.borderColor) return this.borderColor;
return this.$u.color[this.type + 'Disabled'];
}
},
methods: {
//
click() {
this.$emit('click');
},
//
close() {
this.$emit('close');
}
}
}
</script>
<style lang="scss" scoped>
.u-alert-tips {
display: flex;
align-items: center;
padding: 16rpx 30rpx;
border-radius: 8rpx;
position: relative;
transition: all 0.3s linear;
border: 1px solid #fff;
}
.u-close-alert-tips {
opacity: 0;
visibility: hidden;
}
@keyframes myfirst {
from {
height: 100%;
}
to {
height: 0
}
}
.u-icon {
margin-right: 16rpx;
}
.u-alert-title {
font-size: 28rpx;
color: $u-main-color;
}
.u-alert-desc {
font-size: 26rpx;
text-align: left;
color: $u-content-color;
}
.u-close-icon {
position: absolute;
top: 20rpx;
right: 20rpx;
}
.u-close-hover {
color: red;
}
.u-close-text {
font-size: 24rpx;
color: $u-tips-color;
position: absolute;
top: 20rpx;
right: 20rpx;
line-height: 1;
}
</style>

View File

@ -0,0 +1,283 @@
<template>
<view class="content">
<view class="cropper-wrapper" :style="{ height: cropperOpt.height + 'px' }">
<canvas
class="cropper"
:disable-scroll="true"
@touchstart="touchStart"
@touchmove="touchMove"
@touchend="touchEnd"
:style="{ width: cropperOpt.width, height: cropperOpt.height, backgroundColor: 'rgba(0, 0, 0, 0.8)' }"
canvas-id="cropper"
></canvas>
<canvas
class="cropper"
:disable-scroll="true"
:style="{
position: 'fixed',
top: `-${cropperOpt.width * cropperOpt.pixelRatio}px`,
left: `-${cropperOpt.height * cropperOpt.pixelRatio}px`,
width: `${cropperOpt.width * cropperOpt.pixelRatio}px`,
height: `${cropperOpt.height * cropperOpt.pixelRatio}`
}"
canvas-id="targetId"
></canvas>
</view>
<view class="cropper-buttons safe-area-padding" :style="{ height: bottomNavHeight + 'px' }">
<!-- #ifdef H5 -->
<view class="upload" @tap="uploadTap">选择图片</view>
<!-- #endif -->
<!-- #ifndef H5 -->
<view class="upload" @tap="uploadTap">重新选择</view>
<!-- #endif -->
<view class="getCropperImage" @tap="getCropperImage(false)">确定</view>
</view>
</view>
</template>
<script>
import WeCropper from './weCropper.js';
export default {
props: {
// lineWidth-(rpx)color:
// mask-rgba"rgba(0, 0, 0, 0.35)"
boundStyle: {
type: Object,
default() {
return {
lineWidth: 4,
borderColor: 'rgb(245, 245, 245)',
mask: 'rgba(0, 0, 0, 0.35)'
};
}
}
// // rpx
// rectWidth: {
// type: [String, Number],
// default: 400
// },
// // rpx
// rectHeight: {
// type: [String, Number],
// default: 400
// },
// // rpx
// destWidth: {
// type: [String, Number],
// default: 400
// },
// // rpx
// destHeight: {
// type: [String, Number],
// default: 400
// },
// // "png""jpg"
// fileType: {
// type: String,
// default: 'jpg',
// },
// //
// // H5使
// quality: {
// type: [Number, String],
// default: 1
// }
},
data() {
return {
//
bottomNavHeight: 50,
originWidth: 200,
width: 0,
height: 0,
cropperOpt: {
id: 'cropper',
targetId: 'targetCropper',
pixelRatio: 1,
width: 0,
height: 0,
scale: 2.5,
zoom: 8,
cut: {
x: (this.width - this.originWidth) / 2,
y: (this.height - this.originWidth) / 2,
width: this.originWidth,
height: this.originWidth
},
boundStyle: {
lineWidth: uni.upx2px(this.boundStyle.lineWidth),
mask: this.boundStyle.mask,
color: this.boundStyle.borderColor
}
},
//
// px
destWidth: 200,
// px
rectWidth: 200,
// 'png'"jpg"
fileType: 'jpg'
};
},
onLoad(option) {
let rectInfo = uni.getSystemInfoSync();
this.width = rectInfo.windowWidth;
this.height = rectInfo.windowHeight - this.bottomNavHeight;
this.cropperOpt.width = this.width;
this.cropperOpt.height = this.height;
this.cropperOpt.pixelRatio = rectInfo.pixelRatio;
if (option.destWidth) this.destWidth = option.destWidth;
if (option.rectWidth) {
let rectWidth = Number(option.rectWidth);
this.cropperOpt.cut = {
x: (this.width - rectWidth) / 2,
y: (this.height - rectWidth) / 2,
width: rectWidth,
height: rectWidth
};
}
this.rectWidth = option.rectWidth;
if (option.fileType) this.fileType = option.fileType;
//
this.cropper = new WeCropper(this.cropperOpt)
.on('ready', ctx => {
// console.log(`wecropper is ready for work!`)
})
.on('beforeImageLoad', ctx => {
// console.log(`before picture loaded, i can do something`)
})
.on('imageLoad', ctx => {
// console.log(`picture loaded`)
})
.on('beforeDraw', (ctx, instance) => {
// console.log(`before canvas draw,i can do something`)
});
// page.json
uni.setNavigationBarColor({
frontColor: '#ffffff',
backgroundColor: '#000000'
});
uni.chooseImage({
count: 1, // 9
sizeType: ['compressed'], //
sourceType: ['album', 'camera'], //
success: res => {
let src = res.tempFilePaths[0];
// datasrc
this.cropper.pushOrign(src);
}
});
},
methods: {
touchStart(e) {
this.cropper.touchStart(e);
},
touchMove(e) {
this.cropper.touchMove(e);
},
touchEnd(e) {
this.cropper.touchEnd(e);
},
getCropperImage(isPre = false) {
let cropper_opt = {
destHeight: Number(this.destWidth), // uni.canvasToTempFilePath
destWidth: Number(this.destWidth),
fileType: this.fileType
};
this.cropper.getCropperImage(cropper_opt, (path, err) => {
if (err) {
uni.showModal({
title: '温馨提示',
content: err.message
});
} else {
if (isPre) {
uni.previewImage({
current: '', // http
urls: [path] // http
});
} else {
uni.$emit('uAvatarCropper', path);
this.$u.route({
type: 'back'
});
}
}
});
},
uploadTap() {
const self = this;
uni.chooseImage({
count: 1, // 9
sizeType: ['original', 'compressed'], //
sourceType: ['album', 'camera'], //
success(res) {
const src = res.tempFilePaths[0];
// datasrc
self.cropper.pushOrign(src);
}
});
}
}
};
</script>
<style scoped>
.content {
background: rgba(255, 255, 255, 1);
}
.cropper {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 99999999999999;
}
.cropper-buttons {
background-color: #000000;
color: #eee;
}
.cropper-wrapper {
position: relative;
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
width: 100%;
background-color: #000;
}
.cropper-buttons {
width: 100vw;
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
position: fixed;
bottom: 0;
left: 0;
font-size: 28rpx;
}
.cropper-buttons .upload,
.cropper-buttons .getCropperImage {
width: 50%;
text-align: center;
}
.cropper-buttons .upload {
text-align: left;
padding-left: 50rpx;
}
.cropper-buttons .getCropperImage {
text-align: right;
padding-right: 50rpx;
}
</style>

File diff suppressed because it is too large Load Diff

120
node_modules/uview-ui/components/u-avatar/u-avatar.vue generated vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,145 @@
<template>
<view @tap="backToTop" class="u-back-top" :class="['u-back-top--mode--' + mode]" :style="[{
bottom: bottom + 'rpx',
right: right + 'rpx',
borderRadius: mode == 'circle' ? '10000rpx' : '8rpx',
zIndex: uZIndex,
opacity: opacity
}, customStyle]">
<view class="" v-if="!$slots.default">
<u-icon @click="backToTop" :name="icon" :custom-style="iconStyle"></u-icon>
<view class="u-back-top__tips">
{{tips}}
</view>
</view>
<slot v-else />
</view>
</template>
<script>
export default {
name: 'u-back-top',
props: {
// circle-square-
mode: {
type: String,
default: 'circle'
},
//
icon: {
type: String,
default: 'arrow-upward'
},
//
tips: {
type: String,
default: ''
},
//
duration: {
type: [Number, String],
default: 100
},
//
scrollTop: {
type: [Number, String],
default: 0
},
// rpx
top: {
type: [Number, String],
default: 400
},
// rpx
bottom: {
type: [Number, String],
default: 200
},
// rpx
right: {
type: [Number, String],
default: 40
},
//
zIndex: {
type: [Number, String],
default: '9'
},
//
iconStyle: {
type: Object,
default() {
return {
color: '#909399',
fontSize: '38rpx'
}
}
},
//
customStyle: {
type: Object,
default() {
return {}
}
}
},
watch: {
showBackTop(nVal, oVal) {
//
// v-if
if(nVal) {
this.uZIndex = this.zIndex;
this.opacity = 1;
} else {
this.uZIndex = -1;
this.opacity = 0;
}
}
},
computed: {
showBackTop() {
// scrollToppxtop(rpx)
// px
return this.scrollTop > uni.upx2px(this.top);
},
},
data() {
return {
//
opacity: 0,
// z-index-1
uZIndex: -1
}
},
methods: {
backToTop() {
uni.pageScrollTo({
scrollTop: 0,
duration: this.duration
});
}
}
}
</script>
<style lang="scss" scoped>
.u-back-top {
width: 80rpx;
height: 80rpx;
position: fixed;
z-index: 9;
display: flex;
flex-direction: column;
justify-content: center;
background-color: #E1E1E1;
color: $u-content-color;
align-items: center;
transition: opacity 0.4s;
&__tips {
font-size: 24rpx;
transform: scale(0.8);
line-height: 1;
}
}
</style>

193
node_modules/uview-ui/components/u-badge/u-badge.vue generated vendored Normal file
View File

@ -0,0 +1,193 @@
<template>
<view v-if="show" class="u-badge-box" :class="[isDot ? 'u-badge-dot' : 'u-badge', size == 'mini' ? 'u-badge-mini' : '']" :style="[{
top: offset[0] + 'rpx',
right: offset[1] + 'rpx',
fontSize: fontSize + 'rpx',
position: absolute ? 'absolute' : 'static',
color: color,
backgroundColor: backgroundColor
}, boxStyle]">
{{showText}}
</view>
</template>
<script>
/**
* badge 角标
* @description 本组件一般用于展示头像的地方如个人中心或者评论列表页的用户头像展示等场所
* @tutorial https://www.uviewui.com/components/badge.html
* @property {String Number} count 展示的数字大于 overflowCount 时显示为 ${overflowCount}+为0且show-zero为false时隐藏
* @property {Boolean} is-dot 不展示数字只有一个小点默认false
* @property {Boolean} absolute 组件是否绝对定位为true时offset参数才有效默认true
* @property {String Number} overflow-count 展示封顶的数字值默认99
* @property {String} type 使用预设的背景颜色默认error
* @property {Boolean} show-zero 当数值为 0 是否展示 Badge默认false
* @property {String} size Badge的尺寸设为mini会得到小一号的Badge默认default
* @property {Array} offset 设置badge的位置偏移格式为 [x, y]也即设置的为top和right的值单位rpxabsolute为true时有效默认[20, 20]
* @property {String} color 字体颜色默认#ffffff
* @property {String} bgColor 背景颜色优先级比type高如设置type参数会失效
* @property {Boolean} is-center 组件中心点是否和父组件右上角重合优先级比offset高如设置offset参数会失效默认false
* @example <u-badge type="error" count="7"></u-badge>
*/
export default {
name: 'u-badge',
props: {
// primary,warning,success,error,info
type: {
type: String,
default: 'error'
},
// default, mini
size: {
type: String,
default: 'default'
},
//
isDot: {
type: Boolean,
default: false
},
//
count: {
type: [Number, String],
},
//
overflowCount: {
type: Number,
default: 99
},
// 0 Badge
showZero: {
type: Boolean,
default: false
},
//
offset: {
type: Array,
default: () => {
return [20, 20]
}
},
// offset
absolute: {
type: Boolean,
default: true
},
//
fontSize: {
type: [String, Number],
default: '24'
},
//
color: {
type: String,
default: '#ffffff'
},
// badge
bgColor: {
type: String,
default: ''
},
// badgeoffset
isCenter: {
type: Boolean,
default: false
}
},
computed: {
// badge
boxStyle() {
let style = {};
if(this.isCenter) {
style.top = 0;
style.right = 0;
// Y-50%badgebadgeX50%
style.transform = "translateY(-50%) translateX(50%)";
} else {
style.top = this.offset[0] + 'rpx';
style.right = this.offset[1] + 'rpx';
style.transform = "translateY(0) translateX(0)";
}
// miniscal()
if(this.size == 'mini') {
style.transform = style.transform + " scale(0.8)";
}
return style;
},
// isDot
showText() {
if(this.isDot) return '';
else {
if(this.count > this.overflowCount) return `${this.overflowCount}+`;
else return this.count;
}
},
//
show() {
// count0showZerofalse
if(this.count == 0 && this.showZero == false) return false;
else return true;
},
// bgColortype
backgroundColor() {
return this.bgColor ? this.bgColor : this.$u.color[this.type];
}
}
}
</script>
<style lang="scss" scoped>
.u-badge-box {
display: inline-flex;
justify-content: center;
align-items: center;
}
.u-badge {
line-height: 24rpx;
padding: 4rpx 8rpx;
border-radius: 100rpx;
}
.u-badge-dot {
height: 16rpx;
width: 16rpx;
border-radius: 100rpx;
line-height: 1;
}
.u-badge-mini {
transform: scale(0.8);
transform-origin: center center;
}
// .u-primary {
// background: $u-type-primary;
// color: #fff;
// }
// .u-error {
// background: $u-type-error;
// color: #fff;
// }
// .u-warning {
// background: $u-type-warning;
// color: #fff;
// }
// .u-success {
// background: $u-type-success;
// color: #fff;
// }
// .u-black {
// background: #585858;
// color: #fff;
// }
.u-info {
background: $u-type-info;
color: #fff;
}
</style>

512
node_modules/uview-ui/components/u-button/u-button.vue generated vendored Normal file
View File

@ -0,0 +1,512 @@
<template>
<button
id="u-wave-btn"
class="u-btn u-line-1 u-fix-ios-appearance"
:class="[
'u-size-' + size,
plain ? 'u-' + type + '-plain' : '',
loading ? 'u-loading' : '',
shape == 'circle' ? 'u-round-circle' : '',
hairLine ? showHairLineBorder : 'u-bold-border'
]"
:disabled="disabled"
:form-type="formType"
:open-type="openType"
:app-parameter="appParameter"
:hover-stop-propagation="hoverStopPropagation"
:send-message-title="sendMessageTitle"
send-message-path="sendMessagePath"
:lang="lang"
:session-from="sessionFrom"
:send-message-img="sendMessageImg"
:show-message-card="showMessageCard"
@getphonenumber="getphonenumber"
@getuserinfo="getuserinfo"
@error="error"
@opensetting="opensetting"
@launchapp="launchapp"
:style="[buttonStyle]"
@tap.stop="click($event)"
:hover-class="getHoverClass"
:loading="loading"
>
<slot></slot>
<view
v-if="ripple"
class="u-wave-ripple"
:class="[waveActive ? 'u-wave-active' : '']"
:style="{
top: rippleTop + 'px',
left: rippleLeft + 'px',
width: fields.targetWidth + 'px',
height: fields.targetWidth + 'px',
'background-color': rippleBgColor || 'rgba(0, 0, 0, 0.15)'
}"
></view>
</button>
</template>
<script>
/**
* button 按钮
* @description Button 按钮
* @tutorial https://www.uviewui.com/components/button.html
* @property {String} size 按钮的大小
* @property {Boolean} ripple 是否开启点击水波纹效果
* @property {String} ripple-bg-color 水波纹的背景色ripple为true时有效
* @property {String} type 按钮的样式类型
* @property {Boolean} plain 按钮是否镂空背景色透明
* @property {Boolean} disabled 是否禁用
* @property {Boolean} hair-line 是否显示按钮的细边框(默认true)
* @property {Boolean} shape 按钮外观形状见文档说明
* @property {Boolean} loading 按钮名称前是否带 loading 图标(App-nvue 平台 ios 上为雪花Android上为圆圈)
* @property {String} form-type 用于 <form> 组件点击分别会触发 <form> 组件的 submit/reset 事件
* @property {String} open-type 开放能力
* @property {String} hover-class 指定按钮按下去的样式类 hover-class="none" 没有点击态效果(App-nvue 平台暂不支持)
* @property {Number} hover-start-time 按住后多久出现点击态单位毫秒
* @property {Number} hover-stay-time 手指松开后点击态保留时间单位毫秒
* @property {Object} custom-style 对按钮的自定义样式对象形式见文档说明
* @event {Function} click 按钮点击
* @event {Function} getphonenumber open-type="getPhoneNumber"时有效
* @event {Function} getuserinfo 用户点击该按钮时会返回获取到的用户信息从返回参数的detail中获取到的值同uni.getUserInfo
* @event {Function} error 当使用开放能力时发生错误的回调
* @event {Function} opensetting 在打开授权设置页并关闭后回调
* @event {Function} launchapp 打开 APP 成功的回调
* @example <u-button>月落</u-button>
*/
export default {
name: 'u-button',
props: {
//
hairLine: {
type: Boolean,
default: true
},
// defaultprimaryerrorwarningsuccess
type: {
type: String,
default: 'default'
},
// defaultmediummini
size: {
type: String,
default: 'default'
},
// circlesquare
shape: {
type: String,
default: 'square'
},
//
plain: {
type: Boolean,
default: false
},
//
disabled: {
type: Boolean,
default: false
},
//
loading: {
type: Boolean,
default: false
},
// uniappbutton
// https://uniapp.dcloud.io/component/button
openType: {
type: String,
default: ''
},
// <form> <form> submit/reset
// submitreset
formType: {
type: String,
default: ''
},
// APP APP open-type=launchApp
// QQ
appParameter: {
type: String,
default: ''
},
//
hoverStopPropagation: {
type: Boolean,
default: false
},
// zh_CN zh_TW en
lang: {
type: String,
default: 'en'
},
// open-type="contact"
sessionFrom: {
type: String,
default: ''
},
// open-type="contact"
//
sendMessageTitle: {
type: String,
default: ''
},
// open-type="contact"
//
sendMessagePath: {
type: String,
default: ''
},
// open-type="contact"
//
sendMessageImg: {
type: String,
default: ''
},
// true""
// open-type="contact"
showMessageCard: {
type: Boolean,
default: false
},
//
hoverBgColor: {
type: String,
default: ''
},
//
rippleBgColor: {
type: String,
default: ''
},
//
ripple: {
type: Boolean,
default: false
},
//
hoverClass: {
type: String,
default: ''
},
//
customStyle: {
type: Object,
default() {
return {};
}
}
},
computed: {
// bgColor
getHoverClass() {
// hover-class
if (this.loading || this.disabled || this.ripple || this.hoverClass) return '';
let hoverClass = '';
hoverClass = this.plain ? 'u-' + this.type + '-plain-hover' : 'u-' + this.type + '-hover';
return hoverClass;
},
//
buttonStyle() {
let style = {};
if (this.type == 'default') {
if (this.disabled) {
style.color = '#c0c4cc';
style.backgroundColor = '#ffffff';
style.borderColor = '#e4e7ed';
} else {
style.color = this.$u.color['contentColor'];
style.backgroundColor = '#ffffff';
style.borderColor = '#c0c4cc';
}
} else {
if (this.disabled) {
if (this.plain) {
style.color = this.$u.color[this.type + 'Disabled'];
style.backgroundColor = this.$u.color[this.type + 'Light'];
style.borderColor = this.$u.color[this.type + 'Disabled'];
} else {
style.color = '#ffffff';
style.backgroundColor = this.$u.color[this.type + 'Disabled'];
style.borderColor = this.$u.color[this.type + 'Disabled'];
}
} else {
if (this.plain) {
style.color = this.$u.color[this.type];
style.backgroundColor = this.$u.color[this.type + 'Light'];
style.borderColor = this.$u.color[this.type + 'Disabled'];
} else {
style.color = '#ffffff';
style.backgroundColor = this.$u.color[this.type];
style.borderColor = this.$u.color[this.type];
}
}
}
return Object.assign(style, this.customStyle);
},
// 'primary', 'success', 'error', 'warning'
showHairLineBorder() {
if (['primary', 'success', 'error', 'warning'].indexOf(this.type) >= 0 && !this.plain) {
return '';
} else {
return 'u-hairline-border';
}
}
},
data() {
return {
rippleTop: 0, // Y
rippleLeft: 0, // X
fields: {}, //
waveActive: false //
};
},
methods: {
//
click(e) {
// disabledloading
if (this.loading === true || this.disabled === true) return;
//
if (this.ripple) {
//
this.waveActive = false;
this.$nextTick(function() {
this.getWaveQuery(e);
});
}
this.$emit('click');
},
//
getWaveQuery(e) {
this.getElQuery().then(res => {
//
let data = res[0];
//
if (!data.width || !data.width) return;
// (border-radius)
//
data.targetWidth = data.height > data.width ? data.height : data.width;
if (!data.targetWidth) return;
this.fields = data;
let touchesX = '',
touchesY = '';
// #ifdef MP-BAIDU
touchesX = e.changedTouches[0].clientX;
touchesY = e.changedTouches[0].clientY;
// #endif
// #ifdef MP-ALIPAY
touchesX = e.detail.clientX;
touchesY = e.detail.clientY;
// #endif
// #ifndef MP-BAIDU || MP-ALIPAY
touchesX = e.touches[0].clientX;
touchesY = e.touches[0].clientY;
// #endif
// xytouchesYdata.top
// `transform-origin`centerview
//
this.rippleTop = touchesY - data.top - data.targetWidth / 2;
this.rippleLeft = touchesX - data.left - data.targetWidth / 2;
this.$nextTick(() => {
this.waveActive = true;
});
});
},
//
getElQuery() {
return new Promise(resolve => {
let queryInfo = '';
// uniapp
// https://uniapp.dcloud.io/api/ui/nodes-info?id=nodesrefboundingclientrect
queryInfo = uni.createSelectorQuery().in(this);
//#ifdef MP-ALIPAY
queryInfo = uni.createSelectorQuery();
//#endif
queryInfo.select('.u-btn').boundingClientRect();
queryInfo.exec(data => {
resolve(data);
});
});
},
// uniapp
getphonenumber(res) {
this.$emit('getphonenumber', res);
},
getuserinfo(res) {
this.$emit('getuserinfo', res);
},
error(res) {
this.$emit('error', res);
},
opensetting(res) {
this.$emit('opensetting', res);
},
launchapp(res) {
this.$emit('launchapp', res);
}
}
};
</script>
<style scoped lang="scss">
.u-btn::after {
border: none;
}
.u-btn {
position: relative;
border: 0;
//border-radius: 10rpx;
display: inline-block;
overflow: hidden;
line-height: 1;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
padding: 0 40rpx;
z-index: 1;
box-sizing: border-box;
transition: all 0.15s;
}
.u-hairline-border:after {
content: ' ';
position: absolute;
pointer-events: none;
// border-boxscale0.5border-boxborder
box-sizing: border-box;
// (scale())
-webkit-transform-origin: 0 0;
transform-origin: 0 0;
left: 0;
top: 0;
width: 199.8%;
height: 199.7%;
-webkit-transform: scale(0.5, 0.5);
transform: scale(0.5, 0.5);
border: 1px solid currentColor;
z-index: 1;
}
.u-bold-border {
border: 1px solid #ffffff;
}
.u-wave-ripple {
z-index: 0;
position: absolute;
border-radius: 100%;
background-clip: padding-box;
pointer-events: none;
user-select: none;
transform: scale(0);
opacity: 1;
transform-origin: center;
}
.u-wave-ripple.u-wave-active {
opacity: 0;
transform: scale(2);
transition: opacity 1s linear, transform 0.4s linear;
}
.u-round-circle {
border-radius: 100rpx;
}
.u-round-circle::after {
border-radius: 100rpx;
}
.u-loading::after {
background-color: hsla(0, 0%, 100%, 0.35);
}
.u-size-default {
font-size: 30rpx;
height: 80rpx;
line-height: 80rpx;
}
.u-size-medium {
display: inline-flex;
width: auto;
font-size: 26rpx;
height: 70rpx;
line-height: 70rpx;
padding: 0 80rpx;
}
.u-size-mini {
display: inline-flex;
width: auto;
font-size: 22rpx;
padding-top: 1px;
height: 50rpx;
line-height: 50rpx;
padding: 0 20rpx;
}
.u-primary-plain-hover {
color: #ffffff !important;
background: $u-type-primary-dark !important;
}
.u-default-plain-hover {
color: $u-type-primary-dark !important;
background: $u-type-primary-light !important;
}
.u-success-plain-hover {
color: #ffffff !important;
background: $u-type-success-dark !important;
}
.u-warning-plain-hover {
color: #ffffff !important;
background: $u-type-warning-dark !important;
}
.u-error-plain-hover {
color: #ffffff !important;
background: $u-type-error-dark !important;
}
.u-info-plain-hover {
color: #ffffff !important;
background: $u-type-info-dark !important;
}
.u-default-hover {
color: $u-type-primary-dark !important;
border-color: $u-type-primary-dark !important;
background-color: $u-type-primary-light !important;
}
.u-primary-hover {
background: $u-type-primary-dark !important;
color: #fff;
}
.u-success-hover {
background: $u-type-success-dark !important;
color: #fff;
}
.u-info-hover {
background: $u-type-info-dark !important;
color: #fff;
}
.u-warning-hover {
background: $u-type-warning-dark !important;
color: #fff;
}
.u-error-hover {
background: $u-type-error-dark !important;
color: #fff;
}
</style>

View File

@ -0,0 +1,608 @@
<template>
<u-popup closeable :maskCloseAble="maskCloseAble" mode="bottom" :popup="false" v-model="value" length="auto"
:safeAreaInsetBottom="safeAreaInsetBottom" @close="close" :z-index="uZIndex" :border-radius="borderRadius" :closeable="closeable">
<view class="u-calendar">
<view class="u-calendar__header">
<view class="u-calendar__header__text" v-if="!$slots['tooltip']">
{{toolTip}}
</view>
<slot v-else name="tooltip" />
</view>
<view class="u-calendar__action u-flex u-row-center">
<view class="u-calendar__action__icon">
<u-icon v-if="changeYear" name="arrow-left-double" :color="yearArrowColor" @click="changeYearHandler(0)"></u-icon>
</view>
<view class="u-calendar__action__icon">
<u-icon v-if="changeMonth" name="arrow-left" :color="monthArrowColor" @click="changeMonthHandler(0)"></u-icon>
</view>
<view class="u-calendar__action__text">{{ showTitle }}</view>
<view class="u-calendar__action__icon">
<u-icon v-if="changeMonth" name="arrow-right" :color="monthArrowColor" @click="changeMonthHandler(1)"></u-icon>
</view>
<view class="u-calendar__action__icon">
<u-icon v-if="changeYear" name="arrow-right-double" :color="yearArrowColor" @click="changeYearHandler(1)"></u-icon>
</view>
</view>
<view class="u-calendar__week-day">
<view class="u-calendar__week-day__text" v-for="(item, index) in weekDayZh" :key="index">{{item}}</view>
</view>
<view class="u-calendar__content">
<!-- 前置空白部分 -->
<block v-for="(item, index) in weekdayArr" :key="index">
<view class="u-calendar__content__item"></view>
</block>
<view class="u-calendar__content__item" :class="{
'u-hover-class':openDisAbled(year,month,index+1),
'u-calendar__content--start-date': (mode == 'range' && startDate==`${year}-${month}-${index+1}`) || mode== 'date',
'u-calendar__content--end-date':(mode== 'range' && endDate==`${year}-${month}-${index+1}`) || mode == 'date'
}" :style="{backgroundColor: getColor(index,1)}" v-for="(item, index) in daysArr" :key="index"
@tap="dateClick(index)">
<view class="u-calendar__content__item__inner" :style="{color: getColor(index,2)}">
<view>{{ index + 1 }}</view>
</view>
<view class="u-calendar__content__item__tips" :style="{color:activeColor}" v-if="mode== 'range' && startDate==`${year}-${month}-${index+1}` && startDate!=endDate">{{startText}}</view>
<view class="u-calendar__content__item__tips" :style="{color:activeColor}" v-if="mode== 'range' && endDate==`${year}-${month}-${index+1}`">{{endText}}</view>
</view>
<view class="u-calendar__content__bg-month">{{month}}</view>
</view>
<view class="u-calendar__bottom">
<view class="u-calendar__bottom__choose">
<text>{{mode == 'date' ? activeDate : startDate}}</text>
<text v-if="endDate">{{endDate}}</text>
</view>
<view class="u-calendar__bottom__btn">
<u-button :type="btnType" shape="circle" size="default" @click="btnFix(false)">确定</u-button>
</view>
</view>
</view>
</u-popup>
</template>
<script>
export default {
name: 'u-calendar',
props: {
safeAreaInsetBottom: {
type: Boolean,
default: false
},
// Picker
maskCloseAble: {
type: Boolean,
default: true
},
//
value: {
type: Boolean,
default: false
},
// z-index
zIndex: {
type: [String, Number],
default: 0
},
//
changeYear: {
type: Boolean,
default: true
},
//
changeMonth: {
type: Boolean,
default: true
},
// date-range-+
mode: {
type: String,
default: 'date'
},
//
maxYear: {
type: [Number, String],
default: 2050
},
//
minYear: {
type: [Number, String],
default: 1950
},
// ()
minDate: {
type: [Number, String],
default: '1950-01-01'
},
/**
* 最大可选日期
* 默认最大值为今天之后的日期不可选
* 2030-12-31
* */
maxDate: {
type: [Number, String],
default: ''
},
//
borderRadius: {
type: [String, Number],
default: 20
},
//
monthArrowColor: {
type: String,
default: '#606266'
},
//
yearArrowColor: {
type: String,
default: '#909399'
},
//
color: {
type: String,
default: '#303133'
},
// |
activeBgColor: {
type: String,
default: '#2979ff'
},
// |
activeColor: {
type: String,
default: '#ffffff'
},
//
rangeBgColor: {
type: String,
default: 'rgba(41,121,255,0.13)'
},
//
rangeColor: {
type: String,
default: '#2979ff'
},
// mode=range
startText: {
type: String,
default: '开始'
},
// mode=range
endText: {
type: String,
default: '结束'
},
//
btnType: {
type: String,
default: 'primary'
},
//
isActiveCurrent: {
type: Boolean,
default: true
},
// mode=date
isChange: {
type: Boolean,
default: false
},
//
closeable: {
type: Boolean,
default: true
},
//
toolTip: {
type: String,
default: '选择日期'
}
},
data() {
return {
// ,1-7
weekday: 1,
weekdayArr:[],
//
days: 0,
daysArr:[],
showTitle: '',
year: 2020,
month: 0,
day: 0,
startYear: 0,
startMonth: 0,
startDay: 0,
endYear: 0,
endMonth: 0,
endDay: 0,
today: '',
activeDate: '',
startDate: '',
endDate: '',
isStart: true,
min: null,
max: null,
weekDayZh: ['日', '一', '二', '三', '四', '五', '六']
};
},
computed: {
dataChange() {
return `${this.mode}-${this.minDate}-${this.maxDate}`;
},
uZIndex() {
// z-index使
return this.zIndex ? this.zIndex : this.$u.zIndex.popup;
}
},
watch: {
dataChange(val) {
this.init()
}
},
created() {
this.init()
},
methods: {
getColor(index, type) {
let color = type == 1 ? '' : this.color;
let day = index + 1
let date = `${this.year}-${this.month}-${day}`
let timestamp = new Date(date.replace(/\-/g, '/')).getTime();
let start = this.startDate.replace(/\-/g, '/')
let end = this.endDate.replace(/\-/g, '/')
if ((this.isActiveCurrent && this.activeDate == date) || this.startDate == date || this.endDate == date) {
color = type == 1 ? this.activeBgColor : this.activeColor;
} else if (this.endDate && timestamp > new Date(start).getTime() && timestamp < new Date(end).getTime()) {
color = type == 1 ? this.rangeBgColor : this.rangeColor;
}
return color;
},
init() {
let now = new Date();
this.year = now.getFullYear();
this.month = now.getMonth() + 1;
this.day = now.getDate();
this.today = `${now.getFullYear()}-${now.getMonth() + 1}-${now.getDate()}`;
this.activeDate = this.today;
this.min = this.initDate(this.minDate);
this.max = this.initDate(this.maxDate || this.today);
this.startDate = "";
this.startYear = 0;
this.startMonth = 0;
this.startDay = 0;
this.endYear = 0;
this.endMonth = 0;
this.endDay = 0;
this.endDate = "";
this.isStart = true;
this.changeData();
},
//
initDate(date) {
let fdate = date.split('-');
return {
year: Number(fdate[0] || 1920),
month: Number(fdate[1] || 1),
day: Number(fdate[2] || 1)
}
},
openDisAbled: function(year, month, day) {
let bool = true;
let date = `${year}/${month}/${day}`;
// let today = this.today.replace(/\-/g, '/');
let min = `${this.min.year}/${this.min.month}/${this.min.day}`;
let max = `${this.max.year}/${this.max.month}/${this.max.day}`;
let timestamp = new Date(date).getTime();
if (timestamp >= new Date(min).getTime() && timestamp <= new Date(max).getTime()) {
bool = false;
}
return bool;
},
generateArray: function(start, end) {
return Array.from(new Array(end + 1).keys()).slice(start);
},
formatNum: function(num) {
return num < 10 ? '0' + num : num + '';
},
//
getMonthDay(year, month) {
let days = new Date(year, month, 0).getDate();
return days;
},
getWeekday(year, month) {
let date = new Date(`${year}/${month}/01 00:00:00`);
return date.getDay();
},
checkRange(year) {
let overstep = false;
if (year < this.minYear || year > this.maxYear) {
uni.showToast({
title: "日期超出范围啦~",
icon: 'none'
})
overstep = true;
}
return overstep;
},
changeMonthHandler(isAdd) {
if (isAdd) {
let month = this.month + 1;
let year = month > 12 ? this.year + 1 : this.year;
if (!this.checkRange(year)) {
this.month = month > 12 ? 1 : month;
this.year = year;
this.changeData();
}
} else {
let month = this.month - 1;
let year = month < 1 ? this.year - 1 : this.year;
if (!this.checkRange(year)) {
this.month = month < 1 ? 12 : month;
this.year = year;
this.changeData();
}
}
},
changeYearHandler(isAdd) {
let year = isAdd ? this.year + 1 : this.year - 1;
if (!this.checkRange(year)) {
this.year = year;
this.changeData();
}
},
changeData() {
this.days = this.getMonthDay(this.year, this.month);
this.daysArr=this.generateArray(1,this.days)
this.weekday = this.getWeekday(this.year, this.month);
this.weekdayArr=this.generateArray(1,this.weekday)
this.showTitle = `${this.year}${this.month}`;
if (this.isChange && this.mode == 'date') {
this.btnFix(true);
}
},
dateClick: function(day) {
day += 1;
if (!this.openDisAbled(this.year, this.month, day)) {
this.day = day;
let date = `${this.year}-${this.month}-${day}`;
if (this.mode == 'date') {
this.activeDate = date;
} else {
let compare = new Date(date.replace(/\-/g, '/')).getTime() < new Date(this.startDate.replace(/\-/g, '/')).getTime()
if (this.isStart || compare) {
this.startDate = date;
this.startYear = this.year;
this.startMonth = this.month;
this.startDay = this.day;
this.endYear = 0;
this.endMonth = 0;
this.endDay = 0;
this.endDate = "";
this.activeDate = "";
this.isStart = false;
} else {
this.endDate = date;
this.endYear = this.year;
this.endMonth = this.month;
this.endDay = this.day;
this.isStart = true;
}
}
}
},
close() {
// v-modelfalse
this.$emit('input', false);
},
getWeekText(date) {
date = new Date(`${date.replace(/\-/g, '/')} 00:00:00`);
let week = date.getDay();
return '星期' + ['日', '一', '二', '三', '四', '五', '六'][week];
},
btnFix(show) {
if (!show) {
this.close();
}
if (this.mode == 'date') {
let arr = this.activeDate.split('-')
let year = this.isChange ? this.year : Number(arr[0]);
let month = this.isChange ? this.month : Number(arr[1]);
let day = this.isChange ? this.day : Number(arr[2]);
//
let days = this.getMonthDay(year, month);
let result = `${year}-${this.formatNum(month)}-${this.formatNum(day)}`;
let weekText = this.getWeekText(result);
let isToday = false;
if (`${year}-${month}-${day}` == this.today) {
//
isToday = true;
}
this.$emit('change', {
year: year,
month: month,
day: day,
days: days,
result: result,
week: weekText,
isToday: isToday,
// switch: show //
});
} else {
if (!this.startDate || !this.endDate) return;
let startMonth = this.formatNum(this.startMonth);
let startDay = this.formatNum(this.startDay);
let startDate = `${this.startYear}-${startMonth}-${startDay}`;
let startWeek = this.getWeekText(startDate)
let endMonth = this.formatNum(this.endMonth);
let endDay = this.formatNum(this.endDay);
let endDate = `${this.endYear}-${endMonth}-${endDay}`;
let endWeek = this.getWeekText(endDate);
this.$emit('change', {
startYear: this.startYear,
startMonth: this.startMonth,
startDay: this.startDay,
startDate: startDate,
startWeek: startWeek,
endYear: this.endYear,
endMonth: this.endMonth,
endDay: this.endDay,
endDate: endDate,
endWeek: endWeek
});
}
}
}
};
</script>
<style scoped lang="scss">
.u-calendar {
color: $u-content-color;
&__header {
width: 100%;
box-sizing: border-box;
font-size: 30rpx;
background-color: #fff;
color: $u-main-color;
&__text {
margin-top: 30rpx;
padding: 0 60rpx;
display: flex;
justify-content: center;
align-items: center;
}
}
&__action {
padding: 40rpx 0 40rpx 0;
&__icon {
margin: 0 10rpx;
}
&__text {
padding: 0 16rpx;
color: $u-main-color;
font-size: 32rpx;
line-height: 32rpx;
font-weight: bold;
}
}
&__week-day {
display: flex;
align-items: center;
justify-content: center;
padding: 6px 0;
overflow: hidden;
&__text {
flex: 1;
text-align: center;
}
}
&__content {
width: 100%;
display: flex;
flex-wrap: wrap;
padding: 6px 0;
box-sizing: border-box;
background-color: #fff;
position: relative;
&--end-date {
border-top-right-radius: 8rpx;
border-bottom-right-radius: 8rpx;
}
&--start-date {
border-top-left-radius: 8rpx;
border-bottom-left-radius: 8rpx;
}
&__item {
width: 14.2857%;
display: flex;
align-items: center;
justify-content: center;
padding: 6px 0;
overflow: hidden;
position: relative;
z-index: 2;
&__inner {
height: 84rpx;
display: -webkit-box;
display: -webkit-flex;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
font-size: 32rpx;
position: relative;
border-radius: 50%;
&__desc {
width: 100%;
font-size: 24rpx;
line-height: 24rpx;
transform: scale(0.75);
transform-origin: center center;
position: absolute;
left: 0;
text-align: center;
bottom: 2rpx;
}
}
&__tips {
width: 100%;
font-size: 24rpx;
line-height: 24rpx;
position: absolute;
left: 0;
transform: scale(0.8);
transform-origin: center center;
text-align: center;
bottom: 8rpx;
z-index: 2;
}
}
&__bg-month {
position: absolute;
font-size: 130px;
line-height: 130px;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
color: #e4e7ed;
z-index: 1;
}
}
&__bottom {
width: 100%;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
background-color: #fff;
padding: 0 40rpx 30rpx;
box-sizing: border-box;
font-size: 24rpx;
color: $u-tips-color;
&__choose {
height: 50rpx;
}
&__btn {
width: 100%;
}
}
}
</style>

View File

@ -0,0 +1,250 @@
<template>
<view class="u-keyboard" @touchmove.stop.prevent>
<view class="u-keyboard-grids">
<block>
<view class="u-keyboard-grids-item" v-for="(group, i) in abc ? EngKeyBoardList : areaList" :key="i">
<view :hover-stay-time="100" @tap="carInputClick(i, j)" hover-class="u-carinput-hover" class="u-keyboard-grids-btn"
v-for="(item, j) in group" :key="j">
{{ item }}
</view>
</view>
<view @touchstart="backspaceClick" @touchend="clearTimer" :hover-stay-time="100" class="u-keyboard-back"
hover-class="u-hover-class">
<u-icon :size="38" name="backspace" :bold="true"></u-icon>
</view>
<view :hover-stay-time="100" class="u-keyboard-change" hover-class="u-carinput-hover" @tap="changeCarInputMode">
<text class="zh" :class="[!abc ? 'active' : 'inactive']"></text>
/
<text class="en" :class="[abc ? 'active' : 'inactive']"></text>
</view>
</block>
</view>
</view>
</template>
<script>
export default {
name: "u-keyboard",
props: {
//
random: {
type: Boolean,
default: false
}
},
data() {
return {
// abc=truebac=false
abc: false
};
},
computed: {
areaList() {
let data = [
'京',
'沪',
'粤',
'津',
'冀',
'豫',
'云',
'辽',
'黑',
'湘',
'皖',
'鲁',
'苏',
'浙',
'赣',
'鄂',
'桂',
'甘',
'晋',
'陕',
'蒙',
'吉',
'闽',
'贵',
'渝',
'川',
'青',
'琼',
'宁',
'挂',
'藏',
'港',
'澳',
'新',
'使',
'学'
];
let tmp = [];
//
if (this.random) data = this.$u.randomArray(data);
//
tmp[0] = data.slice(0, 10);
tmp[1] = data.slice(10, 20);
tmp[2] = data.slice(20, 30);
tmp[3] = data.slice(30, 36);
return tmp;
},
EngKeyBoardList() {
let data = [
1,
2,
3,
4,
5,
6,
7,
8,
9,
0,
'Q',
'W',
'E',
'R',
'T',
'Y',
'U',
'I',
'O',
'P',
'A',
'S',
'D',
'F',
'G',
'H',
'J',
'K',
'L',
'Z',
'X',
'C',
'V',
'B',
'N',
'M'
];
let tmp = [];
if (this.random) data = this.$u.randomArray(data);
tmp[0] = data.slice(0, 10);
tmp[1] = data.slice(10, 20);
tmp[2] = data.slice(20, 30);
tmp[3] = data.slice(30, 36);
return tmp;
}
},
methods: {
//
carInputClick(i, j) {
let value = '';
//
if (this.abc) value = this.EngKeyBoardList[i][j];
else value = this.areaList[i][j];
this.$emit('change', value);
},
// |
changeCarInputMode() {
this.abc = !this.abc;
},
// 退
backspaceClick() {
this.$emit('backspace');
clearInterval(this.timer); //
this.timer = setInterval(() => {
this.$emit('backspace');
}, 250);
},
clearTimer() {
clearInterval(this.timer);
},
}
};
</script>
<style lang="scss" scoped>
.u-keyboard-grids {
background: rgb(215, 215, 217);
padding: 24rpx 0;
position: relative;
}
.u-keyboard-grids-item {
display: flex;
align-items: center;
justify-content: center;
}
.u-keyboard-grids-btn {
text-decoration: none;
width: 62rpx;
flex: 0 0 64rpx;
height: 80rpx;
display: inline-block;
font-size: 36rpx;
text-align: center;
line-height: 80rpx;
background-color: #fff;
margin: 8rpx 5rpx;
border-radius: 8rpx;
box-shadow: 0 2rpx 0rpx #888992;
font-weight: 500;
}
.u-carinput-hover {
background-color: rgb(185, 188, 195) !important;
}
.u-keyboard-back {
position: absolute;
width: 96rpx;
right: 22rpx;
bottom: 32rpx;
height: 80rpx;
background-color: rgb(185, 188, 195);
display: flex;
align-items: center;
border-radius: 8rpx;
justify-content: center;
box-shadow: 0 2rpx 0rpx #888992;
}
.u-keyboard-change {
font-size: 24rpx;
box-shadow: 0 2rpx 0rpx #888992;
position: absolute;
width: 96rpx;
left: 22rpx;
line-height: 1;
bottom: 32rpx;
height: 80rpx;
background-color: #ffffff;
display: flex;
align-items: center;
border-radius: 8rpx;
justify-content: center;
}
.u-keyboard-change .inactive.zh {
transform: scale(0.85) translateY(-10rpx);
}
.u-keyboard-change .inactive.en {
transform: scale(0.85) translateY(10rpx);
}
.u-keyboard-change .active {
color: rgb(237, 112, 64);
font-size: 30rpx;
}
.u-keyboard-change .zh {
transform: translateY(-10rpx);
}
.u-keyboard-change .en {
transform: translateY(10rpx);
}
</style>

275
node_modules/uview-ui/components/u-card/u-card.vue generated vendored Normal file
View File

@ -0,0 +1,275 @@
<template>
<view
class="u-card"
@tap.stop="click"
:class="{ 'u-border': border, 'u-card-full': full }"
:style="{
borderRadius: full ? 0 : borderRadius + 'rpx',
margin: margin
}"
>
<view
class="u-card__head"
:style="[headStyle, {padding: padding + 'rpx'}]"
:class="{
'u-border-bottom': headBorderBottom
}"
@tap="headClick"
>
<view v-if="!$slots.head" class="u-flex u-row-between">
<view class="u-card__head--left u-flex u-line-1" v-if="title">
<image
:src="thumb"
class="u-card__head--left__thumb"
mode="aspectfull"
v-if="thumb"
:style="{
height: thumbWidth + 'rpx',
width: thumbWidth + 'rpx',
borderRadius: thumbCircle ? '100rpx' : '6rpx'
}"
></image>
<text
class="u-card__head--left__title u-line-1"
:style="{
fontSize: titleSize + 'rpx',
color: titleColor
}"
>
{{ title }}
</text>
</view>
<view class="u-card__head--right u-line-1" v-if="subTitle">
<text
class="u-card__head__title__text"
:style="{
fontSize: subTitleSize + 'rpx',
color: subTitleColor
}"
>
{{ subTitle }}
</text>
</view>
</view>
<slot name="head" v-else />
</view>
<view @tap="bodyClick" class="u-card__body" :style="[bodyStyle, {padding: padding + 'rpx'}]"><slot name="body" /></view>
<view
class="u-card__foot"
@tap="footClick"
:style="[footStyle, {padding: $slots.foot ? padding + 'rpx' : 0}]"
:class="{
'u-border-top': footBorderTop
}"
>
<slot name="foot" />
</view>
</view>
</template>
<script>
/**
* card 卡片
* @description 卡片组件一般用于多个列表条目且风格统一的场景
* @tutorial https://www.uviewui.com/components/line.html
* @property {Boolean} full 卡片与屏幕两侧是否留空隙默认false
* @property {String} title 头部左边的标题
* @property {String} title-color 标题颜色默认#303133
* @property {String | Number} title-size 标题字体大小单位rpx默认30
* @property {String} sub-title 头部右边的副标题
* @property {String} sub-title-color 副标题颜色默认#909399
* @property {String | Number} sub-title-size 副标题字体大小默认26
* @property {Boolean} border 是否显示边框默认true
* @property {String | Number} index 用于标识点击了第几个卡片
* @property {String} margin 卡片与屏幕两边和上下元素的间距需带单位"30rpx 20rpx"默认30rpx
* @property {String | Number} border-radius 卡片整体的圆角值单位rpx默认16
* @property {Object} head-style 头部自定义样式对象形式
* @property {Object} body-style 中部自定义样式对象形式
* @property {Object} foot-style 底部自定义样式对象形式
* @property {Boolean} head-border-bottom 是否显示头部的下边框默认true
* @property {Boolean} foot-border-top 是否显示底部的上边框默认true
* @property {String} thumb 缩略图路径如设置将显示在标题的左边不建议使用相对路径
* @property {String | Number} thumb-width 缩略图的宽度高等于宽单位rpx默认60
* @property {Boolean} thumb-circle 缩略图是否为圆形默认false
* @event {Function} click 整个卡片任意位置被点击时触发
* @event {Function} head-click 卡片头部被点击时触发
* @event {Function} body-click 卡片主体部分被点击时触发
* @event {Function} foot-click 卡片底部部分被点击时触发
* @example <u-card padding="30" title="card"></u-card>
*/
export default {
name: 'u-card',
props: {
//
full: {
type: Boolean,
default: false
},
//
title: {
type: String,
default: ''
},
//
titleColor: {
type: String,
default: '#303133'
},
// rpx
titleSize: {
type: [Number, String],
default: '30'
},
//
subTitle: {
type: String,
default: ''
},
//
subTitleColor: {
type: String,
default: '#909399'
},
// rpx
subTitleSize: {
type: [Number, String],
default: '26'
},
// full=false()
border: {
type: Boolean,
default: true
},
//
index: {
type: [Number, String, Object],
default: ''
},
// "30rpx 30rpx""20rpx 20rpx 30rpx 30rpx"
margin: {
type: String,
default: '30rpx'
},
// card
borderRadius: {
type: [Number, String],
default: '16'
},
//
headStyle: {
type: Object,
default() {
return {};
}
},
//
bodyStyle: {
type: Object,
default() {
return {};
}
},
//
footStyle: {
type: Object,
default() {
return {};
}
},
//
headBorderBottom: {
type: Boolean,
default: true
},
//
footBorderTop: {
type: Boolean,
default: true
},
//
thumb: {
type: String,
default: ''
},
// rpx
thumbWidth: {
type: [String, Number],
default: '60'
},
//
thumbCircle: {
type: Boolean,
default: false
},
// headbodyfoot
padding: {
type: [String, Number],
default: '30'
}
},
data() {
return {};
},
methods: {
click() {
this.$emit('click', this.index);
},
headClick() {
this.$emit('head-click', this.index);
},
bodyClick() {
this.$emit('body-click', this.index);
},
footClick() {
this.$emit('foot-click', this.index);
}
}
};
</script>
<style lang="scss" scoped>
.u-card {
position: relative;
overflow: hidden;
font-size: 28rpx;
background-color: #ffffff;
box-sizing: border-box;
&-full {
// 0
margin-left: 0 !important;
margin-right: 0 !important;
}
&:after {
border-radius: 20rpx;
}
&__head {
&--left {
color: $u-main-color;
&__thumb {
margin-right: 16rpx;
}
&__title {
max-width: 400rpx;
}
}
&--right {
color: $u-tips-color;
margin-left: 6rpx;
}
}
&__body {
color: $u-content-color;
}
&__foot {
color: $u-tips-color;
}
}
</style>

View File

@ -0,0 +1,72 @@
<template>
<view class="u-cell-box">
<view class="u-cell-title" v-if="title" :style="[titleStyle]">
{{title}}
</view>
<view class="u-cell-item-box" :class="{'u-border-bottom u-border-top': border}">
<slot />
</view>
</view>
</template>
<script>
/**
* cellGroup 单元格父组件Group
* @description cell单元格一般用于一组列表的情况比如个人中心页设置页等搭配u-cell-item
* @tutorial https://www.uviewui.com/components/cell.html
* @property {String} title 分组标题
* @property {Boolean} border 是否显示外边框默认true
* @property {Object} title-style 分组标题的的样式对象形式{'font-size': '24rpx'} {'fontSize': '24rpx'}
* @example <u-cell-group title="设置喜好">
*/
export default {
name: "u-cell-group",
props: {
//
title: {
type: String,
default: ''
},
// list
border: {
type: Boolean,
default: true
},
//
// {'font-size': '24rpx'} {'fontSize': '24rpx'}
titleStyle: {
type: Object,
default () {
return {};
}
}
},
data() {
return {
index: 0,
}
},
provide() {
return {
uCellGroup: this
}
},
}
</script>
<style lang="scss" scoped>
.u-cell-box {
width: 100%;
}
.u-cell-title {
padding: 30rpx 32rpx 10rpx 32rpx;
font-size: 30rpx;
text-align: left;
color: $u-tips-color;
}
.u-cell-item-box {
background-color: #FFFFFF;
}
</style>

View File

@ -0,0 +1,300 @@
<template>
<view
@tap="click"
class="u-cell"
:class="{ 'u-cell-border': itemIndex > 0 && borderBottom, 'u-col-center': center, 'u-border-gap': borderGap, 'u-cell--required': required }"
hover-stay-time="150"
:hover-class="hoverClass"
:style="{
backgroundColor: bgColor
}"
>
<u-icon :size="iconSize" :name="icon" v-if="icon" class="u-cell__left-icon-wrap"></u-icon>
<view class="u-flex" v-else>
<slot name="icon"></slot>
</view>
<view
class="u-cell_title"
:style="[
{
width: titleWidth ? titleWidth + 'rpx' : 'auto'
},
titleStyle
]"
>
<block v-if="title">{{ title }}</block>
<slot name="title" v-else></slot>
<view class="u-cell__label" v-if="label || $slots.label" :style="[labelStyle]">
<block v-if="label">{{ label }}</block>
<slot name="label" v-else></slot>
</view>
</view>
<view class="u-cell__value" :style="[valueStyle]">
<block class="u-cell__value" v-if="value">{{ value }}</block>
<slot v-else></slot>
</view>
<u-icon v-if="arrow" name="arrow-right" :style="[arrowStyle]" class="u-icon-wrap u-cell__right-icon-wrap"></u-icon>
<view class="u-flex" v-else>
<slot name="right-icon"></slot>
</view>
</view>
</template>
<script>
/**
* cellItem 单元格Item
* @description cell单元格一般用于一组列表的情况比如个人中心页设置页等搭配u-cell-group使用
* @tutorial https://www.uviewui.com/components/cell.html
* @property {String} title 左侧标题
* @property {String} icon 左侧图标名只支持uView内置图标见Icon 图标
* @property {String} value 右侧内容
* @property {String} label 标题下方的描述信息
* @property {Boolean} border-bottom 是否显示每个cell的下边框默认true
* @property {Boolean} center 是否使内容垂直居中默认false
* @property {String} hover-class 是否开启点击反馈none为无效果默认true
* @property {Boolean} border-gap border-bottom为true时Cell列表中间的条目的下边框是否与左边有一个间隔默认true
* @property {Boolean} arrow 是否显示右侧箭头默认true
* @property {Boolean} required 箭头方向可选值默认right
* @property {Boolean} arrow-direction 是否显示左边表示必填的星号默认false
* @property {Object} title-style 标题样式对象形式
* @property {Object} value-style 右侧内容样式对象形式
* @property {Object} label-style 标题下方描述信息的样式对象形式
* @property {String} bg-color 背景颜色默认transparent
* @property {String Number} index 用于在click事件回调中返回标识当前是第几个Item
* @property {String Number} title-width 标题的宽度单位rpx
* @example <u-cell-item icon="integral-fill" title="会员等级" value="新版本"></u-cell-item>
*/
export default {
name: 'u-cell-item',
props: {
// (uView)src
icon: {
type: String,
default: ''
},
//
title: {
type: [String, Number],
default: ''
},
//
value: {
type: [String, Number],
default: ''
},
//
label: {
type: [String, Number],
default: ''
},
//
borderBottom: {
type: Boolean,
default: true
},
// cellcell线线
borderGap: {
type: Boolean,
default: true
},
// cellnone
hoverClass: {
type: String,
default: 'u-cell-hover'
},
//
arrow: {
type: Boolean,
default: true
},
//
center: {
type: Boolean,
default: false
},
//
required: {
type: Boolean,
default: false
},
// rpx
titleWidth: {
type: [Number, String],
default: ''
},
// right|up|downright
arrowDirection: {
type: String,
default: 'right'
},
//
titleStyle: {
type: Object,
default() {
return {};
}
},
//
valueStyle: {
type: Object,
default() {
return {};
}
},
//
labelStyle: {
type: Object,
default() {
return {};
}
},
//
bgColor: {
type: String,
default: 'transparent'
},
// cell
index: {
type: [String, Number],
default: ''
},
// 使lable
useLabelSlot: {
type: Boolean,
default: false
},
// rpxicon
iconSize: {
type: [Number, String],
default: 34
}
},
inject: {
uCellGroup: {
// u-cell-itemu-cell-group使
default() {
return {
index: 0
}
}
}
},
data() {
return {
itemIndex: 0
};
},
created() {
this.itemIndex = this.uCellGroup.index++;
},
computed: {
arrowStyle() {
let style = {};
if (this.arrowDirection == 'up') style.transform = 'rotate(-90deg)';
else if (this.arrowDirection == 'down') style.transform = 'rotate(90deg)';
else style.transform = 'rotate(0deg)';
return style;
}
},
methods: {
click() {
this.$emit('click', this.index);
}
}
};
</script>
<style lang="scss" scoped>
.u-cell {
position: relative;
display: flex;
box-sizing: border-box;
width: 100%;
padding: 20rpx 32rpx;
font-size: 28rpx;
line-height: 48rpx;
color: $u-content-color;
background-color: #fff;
text-align: left;
}
.u-cell_title {
font-size: 28rpx;
}
.u-cell__left-icon-wrap {
margin-right: 10rpx;
font-size: 32rpx;
}
.u-cell__right-icon-wrap {
margin-left: 10rpx;
color: #969799;
font-size: 28rpx;
}
.u-cell__left-icon-wrap,
.u-cell__right-icon-wrap {
display: flex;
align-items: center;
height: 48rpx;
}
.u-cell-border:after {
position: absolute;
box-sizing: border-box;
content: ' ';
pointer-events: none;
right: 0;
left: 0;
top: 0;
border-bottom: 1px solid $u-border-color;
-webkit-transform: scaleY(0.5);
transform: scaleY(0.5);
}
.u-cell-border {
position: relative;
}
.u-border-gap:after {
left: 32rpx !important;
}
.u-cell__label {
margin-top: 6rpx;
font-size: 26rpx;
line-height: 36rpx;
color: $u-tips-color;
}
.u-cell__value {
overflow: hidden;
text-align: right;
vertical-align: middle;
color: $u-tips-color;
font-size: 26rpx;
}
.u-cell__title,
.u-cell__value {
flex: 1;
}
.u-cell--required {
overflow: visible;
display: flex;
align-items: center;
}
.u-cell--required:before {
position: absolute;
content: '*';
left: 8px;
margin-top: 4rpx;
font-size: 14px;
color: $u-type-error;
}
</style>

View File

@ -0,0 +1,106 @@
<template>
<view class="u-checkbox-group u-clearfix">
<slot></slot>
</view>
</template>
<script>
import Emitter from '../../libs/util/emitter.js';
/**
* checkboxGroup 开关选择器父组件Group
* @description 复选框组件一般用于需要多个选择的场景该组件功能完整使用方便
* @tutorial https://www.uviewui.com/components/checkbox.html
* @property {String Number} max 最多能选中多少个checkbox默认999
* @property {String Number} size 组件整体的大小单位rpx默认40
* @property {Boolean} disabled 是否禁用所有checkbox默认false
* @property {String} width 宽度需带单位
* @property {Boolean} wrap 是否每个checkbox都换行默认false
* @property {String} active-color 选中时的颜色应用到所有子Checkbox组件默认#2979ff
* @event {Function} change 任一个checkbox状态发生变化时触发回调为一个对象
* @example <u-checkbox-group></u-checkbox-group>
*/
export default {
name: 'u-checkbox-group',
mixins: [Emitter],
props: {
// checkbox
max: {
type: [Number, String],
default: 999
},
// name
// value: {
// default: Array,
// default() {
// return []
// }
// },
//
disabled: {
type: Boolean,
default: false
},
//
name: {
type: [Boolean, String],
default: ''
},
//
activeColor: {
type: String,
default: '#2979ff'
},
//
size: {
type: [String, Number],
default: 34
},
// checkboxu-checkbox-group
width: {
type: String,
default: 'auto'
},
// checkbox
wrap: {
type: Boolean,
default: false
}
},
provide() {
return {
checkboxGroup: this
}
},
data() {
return {
}
},
created() {
// childrendata
this.children = [];
},
methods: {
emitEvent() {
let values = [];
this.children.map(val => {
if(val.value) values.push(val.name);
})
this.$emit('change', values);
// checkbox
this.$nextTick(() => {
// u-form-item
this.dispatch('u-form-item', 'on-form-change', values);
});
}
}
}
</script>
<style lang="scss" scoped>
.u-checkbox-group {
/* #ifndef MP */
display: inline-flex;
flex-wrap: wrap;
/* #endif */
}
</style>

View File

@ -0,0 +1,278 @@
<template>
<view class="u-checkbox" :style="[checkboxStyle]">
<view class="u-checkbox__icon-wrap" @tap="toggle">
<u-icon :class="iconClass" name="checkbox-mark" :size="iconSize" :color="iconColor" class="u-checkbox__icon" :style="[iconStyle]" />
</view>
<view class="u-label-class u-checkbox__label" @tap="onClickLabel" :style="{
fontSize: labelSize + 'rpx'
}">
<slot />
</view>
</view>
</template>
<script>
/**
* checkbox 复选框
* @description 该组件需要搭配checkboxGroup组件使用以便用户进行操作时获得当前复选框组的选中情况
* @tutorial https://www.uviewui.com/components/checkbox.html
* @property {String Number} icon-size 图标大小单位rpx默认24
* @property {String Number} label-size label字体大小单位rpx默认28
* @property {String Number} name checkbox组件的标示符
* @property {String} shape 形状见官网说明默认circle
* @property {Boolean} disabled 是否禁用默认false
* @property {Boolean} label-disabled 点击文本是否可以操作checkbox默认true
* @property {String} active-color 选中时的颜色如设置CheckboxGroup的active-color将失效
* @event {Function} change 某个checkbox状态发生变化时触发回调为一个对象
* @example <u-checkbox v-model="checked" :disabled="false">天涯</u-checkbox>
*/
export default {
name: "u-checkbox",
props: {
// checkbox
name: {
type: [String, Number],
default: ''
},
// squarecircle
shape: {
type: String,
default: 'square'
},
//
value: {
type: Boolean,
default: false
},
//
disabled: {
type: Boolean,
default: false
},
//
labelDisabled: {
type: Boolean,
default: false
},
// checkboxGroupactiveColor
activeColor: {
type: String,
default: ''
},
// rpx
iconSize: {
type: [String, Number],
default: 20
},
// labelrpx
labelSize: {
type: [String, Number],
default: 28
},
//
size: {
type: [String, Number],
default: 34
},
},
inject: {
checkboxGroup: {
// u-checkboxu-checkbox-group使
default() {
return {
disabled: false,
children: [],
size: 34,
activeColor: '#2979ff',
max: 999999,
emitEvent: () => {},
width: '',
wrap: false
}
}
}
},
data() {
return {
parentDisabled: false,
};
},
created() {
this.parentDisabled = this.checkboxGroup.disabled;
this.checkboxGroup.children.push(this);
},
computed: {
iconStyle() {
let style = {};
if (this.checkboxActiveColor && this.value && !this.disabled && !this.parentDisabled) {
style.borderColor = this.checkboxActiveColor;
style.backgroundColor = this.checkboxActiveColor;
}
style.width = this.checkboxGroup.size + 'rpx';
style.height = this.checkboxGroup.size + 'rpx';
return style;
},
iconColor() {
return this.value ? '#ffffff' : 'transparent';
},
iconClass() {
let classs = [];
classs.push('u-checkbox__icon--' + this.shape);
if (this.value == true) classs.push('u-checkbox__icon--checked');
if (this.disabled || this.parentDisabled) classs.push('u-checkbox__icon--disabled');
if (this.value && (this.disabled || this.parentDisabled)) classs.push('u-checkbox__icon--disabled--checked');
return classs;
},
// checkboxGroupactiveColor
// activeColor
checkboxActiveColor() {
return this.activeColor ? this.activeColor : this.checkboxGroup.activeColor;
},
checkboxStyle() {
let style = {};
if(this.checkboxGroup.width) {
style.width = this.checkboxGroup.width;
// #ifdef MP
// 使float
style.float = 'left';
// #endif
// #ifndef MP
// H5APP使flex
style.flex = `0 0 ${this.checkboxGroup.width}`;
// #endif
}
if(this.checkboxGroup.wrap) {
style.width = '100%';
// #ifndef MP
// H5APP使flex100%
style.flex = '0 0 100%';
// #endif
}
return style;
}
},
methods: {
onClickLabel() {
if (!this.disabled && !this.labelDisabled && !this.parentDisabled) {
this.setValue();
}
},
toggle() {
if (!this.disabled && !this.parentDisabled) {
this.setValue();
}
},
emitEvent() {
this.$emit('change', {
value: this.value,
name: this.name
})
this.checkboxGroup.emitEvent();
},
// inputinputv-model
setValue() {
//
let checkedNum = 0;
this.checkboxGroup.children.map(val => {
if (val.value) checkedNum++;
})
//
if (this.value == true) {
this.$emit('input', !this.value);
// this.$emit('input')
this.$nextTick(function() {
this.emitEvent();
})
} else if (checkedNum < this.checkboxGroup.max && this.value == false) {
// max
this.$emit('input', !this.value);
// this.$emit('input')
this.$nextTick(function() {
this.emitEvent();
})
}
}
}
};
</script>
<style lang="scss" scoped>
.u-checkbox {
display: -webkit-flex;
display: flex;
-webkit-align-items: center;
align-items: center;
overflow: hidden;
-webkit-user-select: none;
user-select: none;
line-height: 1.8;
}
.u-checkbox__icon-wrap,
.u-checkbox__label {
color: $u-content-color;
}
.u-checkbox__icon-wrap {
-webkit-flex: none;
flex: none;
}
.u-checkbox__icon {
display: -webkit-flex;
display: flex;
-webkit-align-items: center;
align-items: center;
-webkit-justify-content: center;
justify-content: center;
box-sizing: border-box;
width: 42rpx;
height: 42rpx;
color: transparent;
text-align: center;
transition-property: color, border-color, background-color;
font-size: 20px;
border: 1px solid #c8c9cc;
transition-duration: 0.2s;
}
.u-checkbox__icon--circle {
border-radius: 100%;
}
.u-checkbox__icon--square {
border-radius: 3px;
}
.u-checkbox__icon--checked {
color: #fff;
background-color: #2979ff;
border-color: #2979ff;
}
.u-checkbox__icon--disabled {
background-color: #ebedf0;
border-color: #c8c9cc;
}
.u-checkbox__icon--disabled--checked {
color: #c8c9cc !important;
}
.u-checkbox__label {
word-wrap: break-word;
margin-left: 10rpx;
margin-right: 24rpx;
color: $u-content-color;
font-size: 30rpx;
}
.u-checkbox__label--disabled {
color: #c8c9cc;
}
.u-checkbox__label:empty {
margin: 0;
}
</style>

View File

@ -0,0 +1,214 @@
<template>
<view
class="u-circle-progress"
:style="{
width: widthPx + 'px',
height: widthPx + 'px',
backgroundColor: bgColor
}"
>
<canvas
class="u-canvas-bg"
:canvas-id="elBgId"
:style="{
width: widthPx + 'px',
height: widthPx + 'px'
}"
></canvas>
<canvas
class="u-canvas"
:canvas-id="elId"
:style="{
width: widthPx + 'px',
height: widthPx + 'px'
}"
></canvas>
<slot></slot>
</view>
</template>
<script>
/**
* circleProgress 环形进度条
* @description 展示操作或任务的当前进度比如上传文件是一个圆形的进度条注意此组件的percent值只能动态增加不能动态减少
* @tutorial https://www.uviewui.com/components/circleProgress.html
* @property {String Number} percent 圆环进度百分比值为数值类型0-100
* @property {String} inactive-color 圆环的底色默认为灰色(该值无法动态变更)默认#ececec
* @property {String} active-color 圆环激活部分的颜色(该值无法动态变更)默认#19be6b
* @property {String Number} width 整个圆环组件的宽度高度默认等于宽度值单位rpx默认200
* @property {String Number} border-width 圆环的边框宽度单位rpx默认14
* @property {String Number} duration 整个圆环执行一圈的时间单位ms默认呢1500
* @property {String} type 如设置active-color值将会失效
* @property {String} bg-color 整个组件背景颜色默认为白色
* @example <u-circle-progress active-color="#2979ff" :percent="80"></u-circle-progress>
*/
export default {
name: 'u-circle-progress',
props: {
//
percent: {
type: Number,
default: 0,
// 0100
validator: val => {
return val >= 0 && val <= 100;
}
},
//
inactiveColor: {
type: String,
default: '#ececec'
},
//
activeColor: {
type: String,
default: '#19be6b'
},
// 线rpx
borderWidth: {
type: [Number, String],
default: 14
},
// rpx
width: {
type: [Number, String],
default: 200
},
// ms
duration: {
type: [Number, String],
default: 1500
},
//
type: {
type: String,
default: ''
},
//
bgColor: {
type: String,
default: '#ffffff'
}
},
data() {
return {
// #ifdef MP-WEIXIN
elBgId: 'uCircleProgressBgId', // 使this.$u.guid()id
elId: 'uCircleProgressElId',
// #endif
// #ifndef MP-WEIXIN
elBgId: this.$u.guid(), // id
elId: this.$u.guid(),
// #endif
widthPx: uni.upx2px(this.width), // px
borderWidthPx: uni.upx2px(this.borderWidth), // px
startAngle: -Math.PI / 2, // canvas312
progressContext: null, // canvas
newPercent: 0, //
oldPercent: 0 //
};
},
watch: {
percent(nVal, oVal = 0) {
if (nVal > 100) nVal = 100;
if (nVal < 0) oVal = 0;
// this.percent
this.newPercent = nVal;
this.oldPercent = oVal;
setTimeout(() => {
//
//
this.drawCircleByProgress(oVal);
}, 50);
}
},
created() {
// 使
this.newPercent = this.percent;
this.oldPercent = 0;
},
computed: {
// type
circleColor() {
if (['success', 'error', 'info', 'primary', 'warning'].indexOf(this.type) >= 0) return this.$u.color[this.type];
else return this.activeColor;
}
},
mounted() {
// h5this.$nextTick()(HX2.4.7)
setTimeout(() => {
this.drawProgressBg();
this.drawCircleByProgress(this.oldPercent);
}, 50);
},
methods: {
drawProgressBg() {
let ctx = uni.createCanvasContext(this.elBgId, this);
ctx.setLineWidth(this.borderWidthPx); //
ctx.setStrokeStyle(this.inactiveColor); // 线
ctx.beginPath(); //
// (110,110)100
let radius = this.widthPx / 2;
ctx.arc(radius, radius, radius - this.borderWidthPx, 0, 2 * Math.PI, false);
ctx.stroke(); //
ctx.draw();
},
drawCircleByProgress(progress) {
// this.data使
let ctx = this.progressContext;
if (!ctx) {
ctx = uni.createCanvasContext(this.elId, this);
this.progressContext = ctx;
}
//
ctx.setLineCap('round');
// 线
ctx.setLineWidth(this.borderWidthPx);
ctx.setStrokeStyle(this.circleColor);
// 100
let time = Math.floor(this.duration / 100);
// 2π100
// 312this.startAngle
let endAngle = ((2 * Math.PI) / 100) * progress + this.startAngle;
ctx.beginPath();
// canvas
let radius = this.widthPx / 2;
ctx.arc(radius, radius, radius - this.borderWidthPx, this.startAngle, endAngle, false);
ctx.stroke();
ctx.draw();
//
if (this.newPercent > this.oldPercent) {
//
progress++;
//
if (progress > this.newPercent) return;
} else {
//
progress--;
if (progress < this.newPercent) return;
}
setTimeout(() => {
// time
this.drawCircleByProgress(progress);
}, time);
}
}
};
</script>
<style lang="scss" scoped>
.u-circle-progress {
position: relative;
display: inline-flex;
align-items: center;
justify-content: center;
}
.u-canvas-bg {
position: absolute;
}
.u-canvas {
position: absolute;
}
</style>

98
node_modules/uview-ui/components/u-col/u-col.vue generated vendored Normal file
View File

@ -0,0 +1,98 @@
<template>
<view class="u-col" :class="[
'u-col-' + span
]" :style="{
padding: `0 ${Number(gutter)/2 + 'rpx'}`,
marginLeft: 100 / 12 * offset + '%',
flex: `0 0 ${100 / 12 * span}%`
}">
<slot></slot>
</view>
</template>
<script>
/**
* col 布局单元格
* @description 通过基础的 12 分栏迅速简便地创建布局搭配<u-row>使用
* @tutorial https://www.uviewui.com/components/layout.html
* @property {String Number} span 栅格占据的列数总12等分默认0
* @property {String Number} offset 分栏左边偏移计算方式与span相同默认0
* @example <u-col span="3"><view class="demo-layout bg-purple"></view></u-col>
*/
export default {
name: "u-col",
props: {
// 12
span: {
type: [Number, String],
default: 12
},
// (12)
offset: {
type: [Number, String],
default: 0
},
},
inject: ['gutter'],
}
</script>
<style lang="scss">
.u-col {
/* #ifdef MP-WEIXIN */
float: left;
/* #endif */
}
.u-col-0 {
width: 0;
}
.u-col-1 {
width: calc(100%/12);
}
.u-col-2 {
width: calc(100%/12 * 2);
}
.u-col-3 {
width: calc(100%/12 * 3);
}
.u-col-4 {
width: calc(100%/12 * 4);
}
.u-col-5 {
width: calc(100%/12 * 5);
}
.u-col-6 {
width: calc(100%/12 * 6);
}
.u-col-7 {
width: calc(100%/12 * 7);
}
.u-col-8 {
width: calc(100%/12 * 8);
}
.u-col-9 {
width: calc(100%/12 * 9);
}
.u-col-10 {
width: calc(100%/12 * 10);
}
.u-col-11 {
width: calc(100%/12 * 11);
}
.u-col-12 {
width: calc(100%/12 * 12);
}
</style>

View File

@ -0,0 +1,196 @@
<template>
<view class="u-collapse-item" :style="[itemStyle]">
<view :hover-stay-time="200" class="u-collapse-head" @tap.stop="headClick" :hover-class="hoverClass" :style="[headStyle]">
<view class="u-collapse-title u-line-1" :style="[{ textAlign: align ? align : 'left' },
isShow && activeStyle && !arrow ? activeStyle : '']">
{{ title }}
</view>
<view class="u-icon-wrap">
<u-icon v-if="arrow" :color="arrowColor ? arrowColor : $u.color.tipsColor" :class="{ 'u-arrow-down-icon-active': isShow }"
class="u-arrow-down-icon" name="arrow-down"></u-icon>
</view>
</view>
<view class="u-collapse-body" :style="[{
height: isShow ? height + 'px' : '0'
}]">
<view class="u-collapse-content" :id="elId" :style="[bodyStyle]">
<slot></slot>
</view>
</view>
</view>
</template>
<script>
/**
* collapseItem 手风琴Item
* @description 通过折叠面板收纳内容区域搭配u-collapse使用
* @tutorial https://www.uviewui.com/components/collapse.html
* @property {String} title 面板标题
* @property {String Number} index 主要用于事件的回调标识那个Item被点击
* @property {Boolean} disabled 面板是否可以打开或收起默认false
* @property {Boolean} open 设置某个面板的初始状态是否打开默认false
* @property {String Number} name 唯一标识符如不设置默认用当前collapse-item的索引值
* @property {String} align 标题的对齐方式默认left
* @property {Object} active-style 不显示箭头时可以添加当前选择的collapse-item活动样式对象形式
* @event {Function} change 某个item被打开或者收起时触发
* @example <u-collapse-item :title="item.head" v-for="(item, index) in itemList" :key="index">{{item.body}}</u-collapse-item>
*/
export default {
name: "u-collapse-item",
props: {
//
title: {
type: String,
default: ''
},
//
align: {
type: String,
default: 'left'
},
//
disabled: {
type: Boolean,
default: false
},
// collapse
open: {
type: Boolean,
default: false
},
//
name: {
type: [Number, String],
default: ''
},
//
activeStyle: {
type: Object,
default () {
return {}
}
},
//
index: {
type: [String, Number],
default: ''
}
},
inject: ['uCollapse'],
data() {
return {
isShow: false,
elId: this.$u.guid(),
height: 0, // body
headStyle: {}, //
bodyStyle: {}, //
//itemStyle: {}, // item
arrowColor: '', //
hoverClass: '', //
};
},
mounted() {
this.$nextTick(() => {
this.queryRect();
});
},
watch: {
open(val) {
this.isShow = val;
}
},
computed: {
arrow() {
return this.uCollapse.arrow;
},
itemStyle() {
return this.uCollapse.itemStyle;
}
},
created() {
this.isShow = this.open;
this.nameSync = this.name ? this.name : this.uCollapse.childrens.length;
this.uCollapse.childrens.push(this);
//this.itemStyle = this.uCollapse.itemStyle;
this.headStyle = this.uCollapse.headStyle;
this.bodyStyle = this.uCollapse.bodyStyle;
this.arrowColor = this.uCollapse.arrowColor;
this.hoverClass = this.uCollapse.hoverClass;
},
methods: {
// collapsehead
headClick() {
if (this.disabled) return;
if (this.uCollapse.accordion == true) {
this.uCollapse.childrens.map(val => {
// falsethis.isShow = !this.isShow;
if (this != val) {
val.isShow = false;
}
});
}
this.isShow = !this.isShow;
//
uni.$emit('change', {
index: this.index,
show: this.isShow
})
//
if (this.isShow) this.uCollapse.onChange();
this.$forceUpdate();
},
//
queryRect() {
// $uGetRectuViewhttps://www.uviewui.com/js/getRect.html
// this.$uGetRectthis.$u.getRect
this.$uGetRect('#' + this.elId).then(res => {
this.height = res.height;
})
}
}
};
</script>
<style lang="scss" scoped>
.u-collapse-head {
position: relative;
display: flex;
justify-content: space-between;
align-items: center;
color: $u-main-color;
font-size: 30rpx;
line-height: 1;
padding: 24rpx 0;
text-align: left;
}
.u-collapse-title {
flex: 1;
overflow: hidden;
margin-right: 14rpx;
}
.u-arrow-down-icon {
transition: all 0.3s;
margin-right: 24rpx;
}
.u-arrow-down-icon-active {
transform: rotate(180deg);
transform-origin: center center;
}
.u-collapse-body {
overflow: hidden;
transition: all 0.3s;
}
.u-collapse-content {
overflow: hidden;
font-size: 28rpx;
color: $u-tips-color;
text-align: left;
}
</style>

View File

@ -0,0 +1,98 @@
<template>
<view class="u-collapse">
<slot />
</view>
</template>
<script>
/**
* collapse 手风琴
* @description 通过折叠面板收纳内容区域
* @tutorial https://www.uviewui.com/components/collapse.html
* @property {Boolean} accordion 是否手风琴模式默认true
* @property {Boolean} arrow 是否显示标题右侧的箭头默认true
* @property {String} arrow-color 标题右侧箭头的颜色默认#909399
* @property {Object} head-style 标题自定义样式对象形式
* @property {Object} body-style 主体自定义样式对象形式
* @property {String} hover-class 样式类名按下时有效默认u-hover-class
* @event {Function} change 当前激活面板展开时触发(如果是手风琴模式参数activeNames类型为String否则为Array)
* @example <u-collapse></u-collapse>
*/
export default {
name:"u-collapse",
props: {
//
accordion: {
type: Boolean,
default: true
},
//
headStyle: {
type: Object,
default () {
return {}
}
},
//
bodyStyle: {
type: Object,
default () {
return {}
}
},
// item
itemStyle: {
type: Object,
default () {
return {}
}
},
//
arrow: {
type: Boolean,
default: true
},
//
arrowColor: {
type: String,
default: ''
},
// "none"
hoverClass: {
type: String,
default: 'u-hover-class'
}
},
provide() {
return {
uCollapse: this
}
},
created() {
this.childrens = []
},
data() {
return {
}
},
methods: {
// collapse itemcollapse item
onChange() {
let activeItem = [];
this.childrens.forEach((vm, index) => {
if (vm.isShow) {
activeItem.push(vm.nameSync);
}
})
// activeItem1
if (this.accordion) activeItem = activeItem.join('');
this.$emit('change', activeItem);
}
}
}
</script>
<style lang="scss" scoped>
</style>

View File

@ -0,0 +1,222 @@
<template>
<view
class="u-notice-bar"
:style="{
background: computeBgColor,
padding: padding
}"
>
<view class="u-icon-wrap">
<u-icon class="u-left-icon" v-if="volumeIcon" name="volume-fill" :size="volumeSize" :color="computeColor"></u-icon>
</view>
<swiper :disable-touch="disableTouch" @change="change" :autoplay="autoplay && playState == 'play'" :vertical="vertical" circular :interval="duration" class="u-swiper">
<swiper-item v-for="(item, index) in list" :key="index" class="u-swiper-item">
<view
class="u-news-item u-line-1"
:style="{
color: computeColor,
fontSize: fontSize + 'rpx'
}"
@tap="click(index)"
>
{{ item }}
</view>
</swiper-item>
</swiper>
<view class="u-icon-wrap">
<u-icon @click="getMore" class="u-right-icon" v-if="moreIcon" name="arrow-right" :size="26" :color="computeColor"></u-icon>
<u-icon @click="close" class="u-right-icon" v-if="closeIcon" name="close" :size="24" :color="computeColor"></u-icon>
</view>
</view>
</template>
<script>
export default {
props: {
//
list: {
type: Array,
default() {
return [];
}
},
// success|error|primary|info|warning
type: {
type: String,
default: 'warning'
},
//
volumeIcon: {
type: Boolean,
default: true
},
//
moreIcon: {
type: Boolean,
default: false
},
//
closeIcon: {
type: Boolean,
default: false
},
//
autoplay: {
type: Boolean,
default: true
},
// 使
color: {
type: String,
default: ''
},
//
bgColor: {
type: String,
default: ''
},
// row-column-
direction: {
type: String,
default: 'row'
},
//
show: {
type: Boolean,
default: true
},
// rpx
fontSize: {
type: [Number, String],
default: 26
},
// ms
duration: {
type: [Number, String],
default: 2000
},
//
volumeSize: {
type: [Number, String],
default: 34
},
// rpx
speed: {
type: Number,
default: 160
},
//
isCircular: {
type: Boolean,
default: true
},
// horizontal-vertical-
mode: {
type: String,
default: 'horizontal'
},
// play-paused-
playState: {
type: String,
default: 'play'
},
//
// HX2.6.11App 2.5.5+H5 2.5.5+
disableTouch: {
type: Boolean,
default: true
},
//
padding: {
type: [Number, String],
default: '18rpx 24rpx'
}
},
computed: {
// uview
computeColor() {
if (this.color) return this.color;
else if(this.type == 'none') return this.$u.color['contentColor'];
else return this.$u.color[this.type];
},
//
vertical() {
if(this.mode == 'horizontal') return false;
else return true;
},
//
computeBgColor() {
if (this.bgColor) return this.bgColor;
else if(this.type == 'none') return 'transparent';
else return this.$u.color[this.type + 'Light'];
}
},
data() {
return {
// animation: false
};
},
methods: {
//
click(index) {
this.$emit('click', index);
},
//
close() {
this.$emit('close');
},
//
getMore() {
this.$emit('getMore');
},
change(e) {
let index = e.detail.current;
if(index == this.list.length - 1) {
this.$emit('end');
}
}
}
};
</script>
<style lang="scss" scoped>
.u-notice-bar {
width: 100%;
display: flex;
align-items: center;
justify-content: center;
flex-wrap: nowrap;
padding: 18rpx 24rpx;
overflow: hidden;
}
.u-swiper {
font-size: 26rpx;
height: 32rpx;
display: flex;
align-items: center;
flex: 1;
margin-left: 12rpx;
}
.u-swiper-item {
display: flex;
align-items: center;
overflow: hidden;
}
.u-news-item {
overflow: hidden;
}
.u-right-icon {
margin-left: 12rpx;
display: inline-flex;
align-items: center;
}
.u-left-icon {
display: inline-flex;
align-items: center;
}
</style>

View File

@ -0,0 +1,299 @@
<template>
<view class="u-countdown">
<view class="u-countdown-item" :style="[itemStyle]" v-if="showDays">
<view class="u-countdown-time" :style="[letterStyle]">
{{ d }}
</view>
</view>
<view
class="u-countdown-colon"
:style="{fontSize: separatorSize + 'rpx', color: separatorColor, paddingBottom: separator == 'colon' ? '4rpx' : 0}"
v-if="showDays"
>
{{ separator == 'colon' ? ':' : '天' }}
</view>
<view class="u-countdown-item" :style="[itemStyle]" v-if="showHours">
<view class="u-countdown-time" :style="{ fontSize: fontSize + 'rpx', color: color}">
{{ h }}
</view>
</view>
<view
class="u-countdown-colon"
:style="{fontSize: separatorSize + 'rpx', color: separatorColor, paddingBottom: separator == 'colon' ? '4rpx' : 0}"
v-if="showHours"
>
{{ separator == 'colon' ? ':' : '时' }}
</view>
<view class="u-countdown-item" :style="[itemStyle]" v-if="showMinutes">
<view class="u-countdown-time" :style="{ fontSize: fontSize + 'rpx', color: color}">
{{ i }}
</view>
</view>
<view
class="u-countdown-colon"
:style="{fontSize: separatorSize + 'rpx', color: separatorColor, paddingBottom: separator == 'colon' ? '4rpx' : 0}"
v-if="showMinutes"
>
{{ separator == 'colon' ? ':' : '分' }}
</view>
<view class="u-countdown-item" :style="[itemStyle]" v-if="showSeconds">
<view class="u-countdown-time" :style="{ fontSize: fontSize + 'rpx', color: color}">
{{ s }}
</view>
</view>
<view
class="u-countdown-colon"
:style="{fontSize: separatorSize + 'rpx', color: separatorColor, paddingBottom: separator == 'colon' ? '4rpx' : 0}"
v-if="showSeconds && separator == 'zh'"
>
</view>
</view>
</template>
<script>
/**
* countDown 倒计时
* @description 该组件一般使用于某个活动的截止时间上通过数字的变化给用户明确的时间感受提示用户进行某一个行为操作
* @tutorial https://www.uviewui.com/components/countDown.html
* @property {String Number} timestamp 倒计时单位为秒
* @property {Boolean} autoplay 是否自动开始倒计时如果为false需手动调用开始方法见官网说明默认true
* @property {String} separator 分隔符colon为英文冒号zh为中文默认colon
* @property {String Number} separator-size 分隔符的字体大小单位rpx默认30
* @property {String} separator-color 分隔符的颜色默认#303133
* @property {String Number} font-size 倒计时字体大小单位rpx默认30
* @property {Boolean} show-border 是否显示倒计时数字的边框默认false
* @property {String} border-color 数字边框的颜色默认#303133
* @property {String} bg-color 倒计时数字的背景颜色默认#ffffff
* @property {String} color 倒计时数字的颜色默认#303133
* @property {String} height 数字高度值(宽度等同此值)设置边框时看情况是否需要设置此值单位rpx默认auto
* @property {Boolean} show-days 是否显示倒计时的"天"部分默认true
* @property {Boolean} show-hours 是否显示倒计时的"时"部分默认true
* @property {Boolean} show-minutes 是否显示倒计时的"分"部分默认true
* @property {Boolean} show-seconds 是否显示倒计时的"秒"部分默认true
* @event {Function} end 倒计时结束
* @event {Function} change 每秒触发一次回调为当前剩余的倒计秒数
* @example <u-count-down ref="uCountDown" :timestamp="86400" :autoplay="false"></u-count-down>
*/
export default {
name: 'u-count-down',
props: {
//
timestamp: {
type: [Number, String],
default: 0
},
//
autoplay: {
type: Boolean,
default: true
},
// (colon)(zh)false"11:22""1122"
separator: {
type: String,
default: 'colon'
},
// rpx
separatorSize: {
type: [Number, String],
default: 30
},
//
separatorColor: {
type: String,
default: "#303133"
},
//
color: {
type: String,
default: '#303133'
},
// rpx
fontSize: {
type: [Number, String],
default: 30
},
//
bgColor: {
type: String,
default: '#fff'
},
// rpx
height: {
type: [Number, String],
default: 'auto'
},
//
showBorder: {
type: Boolean,
default: false
},
//
borderColor: {
type: String,
default: '#303133'
},
//
showSeconds: {
type: Boolean,
default: true
},
//
showMinutes: {
type: Boolean,
default: true
},
//
showHours: {
type: Boolean,
default: true
},
//
showDays: {
type: Boolean,
default: true
},
},
watch: {
//
timestamp(newVal, oldVal) {
//
clearInterval(this.timer);
this.start();
}
},
data() {
return {
d: '00', //
h: '00', //
i: '00', //
s: '00', //
timer: null ,//
seconds: 0, //
};
},
computed: {
// itemitem
itemStyle() {
let style = {};
if(this.height) {
style.height = this.height + 'rpx';
style.width = this.height + 'rpx';
}
if(this.showBorder) {
style.borderStyle = 'solid';
style.borderColor = this.borderColor;
style.borderWidth = '1px';
}
if(this.bgColor) {
style.backgroundColor = this.bgColor;
}
return style;
},
//
letterStyle() {
let style = {};
if(this.fontSize) style.fontSize = this.fontSize + 'rpx';
if(this.color) style.color = this.color;
return style;
}
},
mounted() {
//
this.autoplay && this.timestamp && this.start();
},
methods: {
//
start() {
if (this.timestamp <= 0) return;
this.seconds = Number(this.timestamp);
this.formatTime(this.seconds);
this.timer = setInterval(() => {
this.seconds--;
// change
this.$emit('change', this.seconds);
if (this.seconds < 0) {
return this.end();
}
this.formatTime(this.seconds);
}, 1000);
},
//
formatTime(seconds) {
// 0
seconds <= 0 && this.end();
let [day, hour, minute, second] = [0, 0, 0, 0];
day = Math.floor(seconds / (60 * 60 * 24));
//
// hour()
hour = Math.floor(seconds / (60 * 60)) - day * 24;
// showHour
let showHour = null;
if(this.showDays) {
showHour = hour;
} else {
//
showHour = Math.floor(seconds / (60 * 60));
}
minute = Math.floor(seconds / 60) - hour * 60 - day * 24 * 60;
second = Math.floor(seconds) - day * 24 * 60 * 60 - hour * 60 * 60 - minute * 60;
// 10"0"
showHour = showHour < 10 ? '0' + showHour : showHour;
minute = minute < 10 ? '0' + minute : minute;
second = second < 10 ? '0' + second : second;
this.d = day;
this.h = showHour;
this.i = minute;
this.s = second;
},
//
end() {
//
clearInterval(this.timer);
this.timer = null;
this.$emit('end', {});
}
},
beforeDestroy() {
clearInterval(this.timer);
this.timer = null;
}
};
</script>
<style scoped lang="scss">
.u-countdown {
display: inline-flex;
align-items: center;
}
.u-countdown-item {
display: flex;
align-items: center;
justify-content: center;
padding: 2rpx;
border-radius: 6rpx;
white-space: nowrap;
transform: translateZ(0);
}
.u-countdown-time {
margin: 0;
padding: 0;
line-height: 1;
}
.u-countdown-colon {
display: flex;
justify-content: center;
padding: 0 5rpx;
line-height: 1;
align-items: center;
padding-bottom: 4rpx;
}
.u-countdown-scale {
transform: scale(0.9);
transform-origin: center center;
}
</style>

View File

@ -0,0 +1,237 @@
<template>
<view
class="u-count-num"
:style="{
fontSize: fontSize + 'rpx',
fontWeight: bold ? 'bold' : 'normal',
color: color
}"
>
{{ displayValue }}
</view>
</template>
<script>
/**
* countTo 数字滚动
* @description 该组件一般用于需要滚动数字到某一个值的场景目标要求是一个递增的值
* @tutorial https://www.uviewui.com/components/countTo.html
* @property {String Number} start-val 开始值
* @property {String Number} end-val 结束值
* @property {String Number} duration 滚动过程所需的时间单位ms默认2000
* @property {Boolean} autoplay 是否自动开始滚动默认true
* @property {String Number} decimals 要显示的小数位数见官网说明默认0
* @property {Boolean} use-easing 滚动结束时是否缓动结尾见官网说明默认true
* @property {String} separator 千位分隔符见官网说明
* @property {String} color 字体颜色默认#303133
* @property {String Number} font-size 字体大小单位rpx默认50
* @property {Boolean} bold 字体是否加粗默认false
* @event {Function} end 数值滚动到目标值时触发
* @example <u-count-to ref="uCountTo" :end-val="endVal" :autoplay="autoplay"></u-count-to>
*/
export default {
name: 'u-count-to',
props: {
// 0
startVal: {
type: [Number, String],
default: 0
},
//
endVal: {
type: [Number, String],
default: 0,
required: true
},
// ms
duration: {
type: [Number, String],
default: 2000
},
//
autoplay: {
type: Boolean,
default: true
},
//
decimals: {
type: [Number, String],
default: 0
},
// 使
useEasing: {
type: Boolean,
default: true
},
//
decimal: {
type: [Number, String],
default: '.'
},
//
color: {
type: String,
default: '#303133'
},
//
fontSize: {
type: [Number, String],
default: 50
},
//
bold: {
type: Boolean,
default: false
},
// (23,321.05",")
separator: {
type: String,
default: ''
}
},
data() {
return {
localStartVal: this.startVal,
displayValue: this.formatNumber(this.startVal),
printVal: null,
paused: false, //
localDuration: Number(this.duration),
startTime: null, //
timestamp: null, //
remaining: null, //
rAF: null,
lastTime: 0 //
};
},
computed: {
countDown() {
return this.startVal > this.endVal;
}
},
watch: {
startVal() {
this.autoplay && this.start();
},
endVal() {
this.autoplay && this.start();
}
},
mounted() {
this.autoplay && this.start();
},
methods: {
easingFn(t, b, c, d) {
return (c * (-Math.pow(2, (-10 * t) / d) + 1) * 1024) / 1023 + b;
},
requestAnimationFrame(callback) {
const currTime = new Date().getTime();
// 使setTimteout60
const timeToCall = Math.max(0, 16 - (currTime - this.lastTime));
const id = setTimeout(() => {
callback(currTime + timeToCall);
}, timeToCall);
this.lastTime = currTime + timeToCall;
return id;
},
cancelAnimationFrame(id) {
clearTimeout(id);
},
//
start() {
this.localStartVal = this.startVal;
this.startTime = null;
this.localDuration = this.duration;
this.paused = false;
this.rAF = this.requestAnimationFrame(this.count);
},
//
reStart() {
if (this.paused) {
this.resume();
this.paused = false;
} else {
this.stop();
this.paused = true;
}
},
//
stop() {
this.cancelAnimationFrame(this.rAF);
},
// ()
resume() {
this.startTime = null;
this.localDuration = this.remaining;
this.localStartVal = this.printVal;
this.requestAnimationFrame(this.count);
},
//
reset() {
this.startTime = null;
this.cancelAnimationFrame(this.rAF);
this.displayValue = this.formatNumber(this.startVal);
},
count(timestamp) {
if (!this.startTime) this.startTime = timestamp;
this.timestamp = timestamp;
const progress = timestamp - this.startTime;
this.remaining = this.localDuration - progress;
if (this.useEasing) {
if (this.countDown) {
this.printVal = this.localStartVal - this.easingFn(progress, 0, this.localStartVal - this.endVal, this.localDuration);
} else {
this.printVal = this.easingFn(progress, this.localStartVal, this.endVal - this.localStartVal, this.localDuration);
}
} else {
if (this.countDown) {
this.printVal = this.localStartVal - (this.localStartVal - this.endVal) * (progress / this.localDuration);
} else {
this.printVal = this.localStartVal + (this.endVal - this.localStartVal) * (progress / this.localDuration);
}
}
if (this.countDown) {
this.printVal = this.printVal < this.endVal ? this.endVal : this.printVal;
} else {
this.printVal = this.printVal > this.endVal ? this.endVal : this.printVal;
}
this.displayValue = this.formatNumber(this.printVal);
if (progress < this.localDuration) {
this.rAF = this.requestAnimationFrame(this.count);
} else {
this.$emit('end');
}
},
//
isNumber(val) {
return !isNaN(parseFloat(val));
},
formatNumber(num) {
// numNumbertoFixed
num = Number(num);
num = num.toFixed(Number(this.decimals));
num += '';
const x = num.split('.');
let x1 = x[0];
const x2 = x.length > 1 ? this.decimal + x[1] : '';
const rgx = /(\d+)(\d{3})/;
if (this.separator && !this.isNumber(this.separator)) {
while (rgx.test(x1)) {
x1 = x1.replace(rgx, '$1' + this.separator + '$2');
}
}
return x1 + x2;
},
destroyed() {
this.cancelAnimationFrame(this.rAF);
}
}
};
</script>
<style lang="scss" scoped>
.u-count-num {
display: inline-block;
text-align: center;
}
</style>

View File

@ -0,0 +1,131 @@
<template>
<view class="u-divider" :style="{
height: height == 'auto' ? 'auto' : height + 'rpx',
backgroundColor: bgColor,
marginBottom: marginBottom + 'rpx',
marginTop: marginTop + 'rpx'
}" @tap="click">
<view class="u-divider-line" :style="[lineStyle]"></view>
<view v-if="useSlot" class="u-divider-text" :style="{
color: color,
fontSize: fontSize + 'rpx'
}"><slot /></view>
<view class="u-divider-line" :style="[lineStyle]"></view>
</view>
</template>
<script>
/**
* divider 分割线
* @description 区隔内容的分割线一般用于页面底部"没有更多"的提示
* @tutorial https://www.uviewui.com/components/divider.html
* @property {String Number} half-width 文字左或右边线条宽度数值或百分比数值时单位为rpx
* @property {String} border-color 线条颜色优先级高于type默认#dcdfe6
* @property {String} color 文字颜色默认#909399
* @property {String Number} fontSize 字体大小单位rpx默认26
* @property {String} bg-color 整个divider的背景颜色默认呢#ffffff
* @property {String Number} height 整个divider的高度单位rpx默认40
* @property {String} type 将线条设置主题色默认primary
* @property {Boolean} useSlot 是否使用slot传入内容如果不传入中间不会有空隙默认true
* @property {String Number} margin-top 与前一个组件的距离单位rpx默认0
* @property {String Number} margin-bottom 与后一个组件的距离单位rpx0
* @event {Function} click divider组件被点击时触发
* @example <u-divider color="#fa3534">长河落日圆</u-divider>
*/
export default {
name: 'u-divider',
props: {
// divider线()rpx
halfWidth: {
type: [Number, String],
default: 150
},
// divider线
borderColor: {
type: String,
default: '#dcdfe6'
},
// primary|info|success|warning|error
type: {
type: String,
default: 'primary'
},
//
color: {
type: String,
default: '#909399'
},
// rpx
fontSize: {
type: [Number, String],
default: 26
},
// divider
bgColor: {
type: String,
default: '#ffffff'
},
// dividerrpx
height: {
type: [Number, String],
default: 'auto'
},
//
marginTop: {
type: [String, Number],
default: 0
},
//
marginBottom: {
type: [String, Number],
default: 0
},
// 使slotslot
useSlot: {
type: Boolean,
default: true
}
},
computed: {
lineStyle() {
let style = {};
if(String(this.halfWidth).indexOf('%') != -1) style.width = this.halfWidth;
else style.width = this.halfWidth + 'rpx';
// borderColortype
if(this.borderColor) style.borderColor = this.borderColor;
else style.borderColor = this.$u.color[this.type];
return style;
}
},
methods: {
click() {
this.$emit('click');
}
}
};
</script>
<style lang="scss" scoped>
.u-divider {
width: 100%;
position: relative;
text-align: center;
display: flex;
justify-content: center;
align-items: center;
overflow: hidden;
flex-direction: row;
}
.u-divider-line {
border-bottom: 1px solid $u-border-color;
transform: scale(1, 0.5);
transform-origin: center;
}
.u-divider-text {
white-space: nowrap;
padding: 0 16rpx;
display: inline-flex;
}
</style>

View File

@ -0,0 +1,241 @@
<template>
<view class="dropdown-list-wapper u-flex u-flex-1">
<view
v-for="(drop, index) in dropdownListFromFather"
:key="drop.name"
:show="drop.show"
class="u-selected-class u-dropdown-list"
:style="{ zIndex: zIndex + 1 }"
>
<slot name="selectionbox">
<view
:style="{ height: top + 'rpx' }"
class="drop-item u-flex u-justify-center"
@click="handleDropClick(drop)"
>
<text :style="{ color: drop.show ? activeColor : '#999' }">
{{ getTitle(drop.options) }}
</text>
<view
class="u-animation"
:class="[drop.show ? 'u-animation-show' : '']"
>
<u-icon
v-if="drop.show"
name="arrow-up-fill"
:size="18"
:color="activeColor"
></u-icon>
<u-icon v-else name="arrow-down-fill" :size="18"></u-icon>
</view>
</view>
</slot>
<view
class="u-dropdown-view"
:class="[drop.show ? 'u-dropdownlist-show' : '']"
:style="{
background: bgcolor,
height: drop.show ? 'auto' : 0,
top: top + 'rpx'
}"
>
<slot name="dropdownbox">
<view class="u-selected-list">
<view
class="select-item u-flex u-align-center u-border-bottom u-align-between"
:style="{ color: select.select ? activeColor : '#666666' }"
@tap="handleSelected(select, drop.options)"
v-for="(select, n) in drop.options"
:key="n"
>
<text>{{ select.text }}</text>
<u-icon
v-if="select.select"
class="select-icon"
:color="activeColor"
size="35"
name="checkmark"
></u-icon>
</view>
</view>
</slot>
</view>
</view>
<u-mask
duration="100"
:show="dropdownShow"
@click="closeMask"
:z-index="zIndex"
></u-mask>
</view>
</template>
<script>
const dropdownOption1 = [
{ id: 0, text: '类型', value: '', select: false },
{ id: 1, text: '全场券', value: 1, select: false },
{ id: 2, text: '品类券', value: 2, select: false },
{ id: 3, text: '单品券', value: 3, select: false },
{ id: 4, text: '业务券', value: 4, select: false }
]
const dropdownOption2 = [
{ id: 5, text: '状态', value: '', select: false },
{ id: 6, text: '可使用', value: 1, select: false },
{ id: 7, text: '已过期', value: 2, select: false }
]
const dropdownOption3 = [
{ id: 8, text: '优惠力度', value: '', select: false },
{ id: 9, text: '满100-20', value: 1, select: false },
{ id: 10, text: '满100-50', value: 2, select: false }
]
export default {
props: {
//
dropdownList: {
type: Array,
default: () => [
{ show: false, options: dropdownOption1 },
{ show: false, options: dropdownOption2 },
{ show: false, options: dropdownOption3 }
],
required: true,
validator: value =>
value.every(item => Array.isArray(item.options) && item.options.length)
},
//
bgcolor: {
type: String,
default: 'none'
},
//top rpx
top: {
type: Number,
default: 90
},
//
activeColor: {
type: String,
default: '#e7141a'
},
// maskz-index
zIndex: {
type: [String, Number],
default: 21
}
},
data() {
return {
dropdownShow: false,
dropdownListFromFather: this.dropdownList
}
},
computed: {},
methods: {
getTitle(item = []) {
const obj = item.find(v => v.select) || {}
if (obj.select) {
return obj.text
} else {
if (item[0]) {
item[0].select = true
return item[0].text
}
}
return ''
},
handleDropClick(item) {
if (item.show) {
item.show = false
this.dropdownShow = false
return
}
this.dropdownListFromFather.map(item => {
item.show = false
})
const t = setTimeout(() => {
item.show = true
this.dropdownShow = true
clearTimeout(t)
}, 100)
},
closeMask() {
this.dropdownShow = false
this.dropdownListFromFather.map(item => {
item.show = false
})
},
handleSelected(select, options) {
options.map(item => {
item.select = false
})
select.select = true
this.closeMask()
//
this.$emit('change', select, options)
}
},
watch: {
dropdownList: {
handler(v) {
this.dropdownListFromFather = v
},
deep: true
}
}
}
</script>
<style lang="scss" scoped>
.dropdown-list-wapper {
position: relative;
}
.u-dropdown-view {
width: 100%;
overflow: hidden;
position: absolute;
z-index: 9999;
left: 0;
right: 0;
/* opacity: 0; */
visibility: hidden;
transition: height 0.5s ease-in-out;
.u-selected-list {
background-color: #fff;
.select-item {
color: #666666;
font-size: 28rpx;
padding: 30rpx 54rpx 30rpx 30rpx;
margin-left: 30rpx;
}
.select-item.selectActive {
color: #e7141a;
}
}
}
.u-dropdownlist-show {
/* opacity: 1; */
visibility: visible;
}
.u-dropdown-list {
flex: 1;
// z-index: 22;
background: #fff;
position: static;
}
.drop-item {
justify-content: center;
color: #999999;
font-size: 30rpx;
> text {
margin-right: 10rpx;
}
/deep/ {
.uicon {
position: relative;
top: -2rpx;
}
}
}
</style>

58
node_modules/uview-ui/components/u-empty/icon.js generated vendored Normal file

File diff suppressed because one or more lines are too long

116
node_modules/uview-ui/components/u-empty/u-empty.vue generated vendored Normal file
View File

@ -0,0 +1,116 @@
<template>
<view class="u-empty" v-if="show" :style="{
marginTop: marginTop + 'rpx'
}">
<image class="u-image" :src="src ? src : icons[mode].image" mode="widthFix" :style="{
width: imgWidth + 'rpx',
height: imgHeight == 'auto' ? 'auto' : imgHeight + 'rpx'
}"></image>
<text :style="{
color: color,
fontSize: fontSize + 'rpx',
}">
{{text ? text : icons[mode].text}}
</text>
<view class="u-slot-wrap">
<slot name="bottom"></slot>
</view>
</view>
</template>
<script>
import icon from "./icon.js";
/**
* empty 内容为空
* @description 该组件用于需要加载内容但是加载的第一页数据就为空提示一个"没有内容"的场景 我们精心挑选了十几个场景的图标方便您使用
* @tutorial https://www.uviewui.com/components/empty.html
* @property {String} color 文字颜色默认#c0c4cc
* @property {String} text 文字提示默认无内容
* @property {String} src 自定义图标路径如定义mode参数会失效
* @property {String Number} font-size 提示文字的大小单位rpx默认28
* @property {String} mode 内置的图标见官网说明默认data
* @property {String Number} img-width 图标的宽度单位rpx默认240
* @property {String} img-height 图标的高度单位rpx默认auto
* @property {String Number} margin-top 组件距离上一个元素之间的距离默认0
* @property {Boolean} show 是否显示组件默认true
* @event {Function} click 点击组件时触发
* @event {Function} close 点击关闭按钮时触发
* @example <u-empty text="所谓伊人,在水一方" mode="list"></u-empty>
*/
export default {
name: "u-empty",
props: {
//
src: {
type: String,
default: ''
},
//
text: {
type: String,
default: ''
},
//
color: {
type: String,
default: '#c0c4cc'
},
// rpx
fontSize: {
type: [String, Number],
default: 26
},
//
mode: {
type: String,
default: 'data'
},
// rpx
imgWidth: {
type: [String, Number],
default: 240
},
// rpx
imgHeight: {
type: [String, Number],
default: 'auto'
},
//
show: {
type: Boolean,
default: true
},
//
marginTop: {
type: [String, Number],
default: 0
}
},
data() {
return {
icons: icon
}
}
}
</script>
<style lang="scss" scoped>
.u-empty {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100%;
}
.u-image {
margin-bottom: 20rpx;
}
.u-slot-wrap {
display: flex;
justify-content: center;
align-items: center;
margin-top: 20rpx;
}
</style>

363
node_modules/uview-ui/components/u-field/u-field.vue generated vendored Normal file
View File

@ -0,0 +1,363 @@
<template>
<view class="u-field" :class="{'u-field-border': itemIndex > 0 }">
<view class="u-field-inner" :class="[type == 'textarea' ? 'u-textarea-inner' : '', 'u-label-postion-' + labelPosition]">
<view class="u-label" :class="[required ? 'u-required' : '']" :style="{
justifyContent: justifyContent,
flex: labelPosition == 'left' ? `0 0 ${labelWidth}rpx` : '1'
}">
<view class="u-icon-wrap" v-if="icon">
<u-icon size="32" :name="icon" :color="iconColor" class="u-icon"></u-icon>
</view>
<slot name="icon"></slot>
<text class="u-label-text" :class="[this.$slots.icon || icon ? 'u-label-left-gap' : '']">{{ label }}</text>
</view>
<view class="fild-body">
<view class="u-flex-1 u-flex" :style="[inputWrapStyle]">
<textarea v-if="type == 'textarea'" class="u-flex-1 u-textarea-class" :style="[fieldStyle]" :value="value"
:placeholder="placeholder" :placeholderStyle="placeholderStyle" :disabled="disabled" :maxlength="inputMaxlength"
:focus="focus" :autoHeight="autoHeight" :fixed="fixed" @input="onInput" @blur="onBlur" @focus="onFocus" @confirm="onConfirm"
@tap="fieldClick" />
<input
v-else
:style="[fieldStyle]"
:type="type"
class="u-flex-1 u-field__input-wrap"
:value="value"
:password="password || type === 'password'"
:placeholder="placeholder"
:placeholderStyle="placeholderStyle"
:disabled="disabled"
:maxlength="inputMaxlength"
:focus="focus"
:confirmType="confirmType"
@focus="onFocus"
@blur="onBlur"
@input="onInput"
@confirm="onConfirm"
@tap="fieldClick"
/>
</view>
<u-icon :size="clearSize" v-if="clearable && value && focused" name="close-circle-fill" color="#c0c4cc" class="u-clear-icon" @touchstart="onClear"/>
<view class="u-button-wrap"><slot name="right" /></view>
<u-icon v-if="rightIcon" @click="rightIconClick" :name="rightIcon" color="#c0c4cc" :style="[rightIconStyle]" size="26" class="u-arror-right" />
</view>
</view>
<view v-if="errorMessage !== false && errorMessage != ''" class="u-error-message" :style="{
paddingLeft: labelWidth + 'rpx'
}">{{ errorMessage }}</view>
</view>
</template>
<script>
/**
* field 输入框
* @description 借助此组件可以实现表单的输入 "text""textarea"类型的此外借助uView的picker和actionSheet组件可以快速实现上拉菜单时间地区选择等 为表单解决方案的利器
* @tutorial https://www.uviewui.com/components/field.html
* @property {String} type 输入框的类型默认text
* @property {String} icon label左边的图标限uView的图标名称
* @property {Boolean} right-icon 输入框右边的图标名称限uView的图标名称默认false
* @property {Boolean} required 是否必填左边您显示红色"*"默认false
* @property {String} label 输入框左边的文字提示
* @property {Boolean} password 是否密码输入方式(用点替换文字)type为text时有效默认false
* @property {Boolean} clearable 是否显示右侧清空内容的图标控件(输入框有内容且获得焦点时才显示)点击可清空输入框内容默认true
* @property {Number String} label-width label的宽度单位rpx默认130
* @property {String} label-align label的文字对齐方式默认left
* @property {Object} field-style 自定义输入框的样式对象形式
* @property {Number | String} clear-size 清除图标的大小单位rpx默认30
* @property {String} input-align 输入框内容对齐方式默认left
* @property {String} icon-color 左边通过icon配置的图标的颜色默认#606266
* @property {Boolean} auto-height 是否自动增高输入区域type为textarea时有效默认true
* @property {String Boolean} error-message 显示的错误提示内容如果为空字符串或者false则不显示错误信息
* @property {String} placeholder 输入框的提示文字
* @property {String} placeholder-style placeholder的样式(内联样式字符串)"color: #ddd"
* @property {Boolean} focus 是否自动获得焦点默认false
* @property {Boolean} fixed 如果type为textarea且在一个"position:fixed"的区域需要指明为true默认false
* @property {Boolean} disabled 是否不可输入默认false
* @property {Number String} maxlength 最大输入长度设置为 -1 的时候不限制最大长度默认140
* @property {String} confirm-type 设置键盘右下角按钮的文字仅在type="text"时生效默认done
* @event {Function} input 输入框内容发生变化时触发
* @event {Function} focus 输入框获得焦点时触发
* @event {Function} blur 输入框失去焦点时触发
* @event {Function} confirm 点击完成按钮时触发
* @event {Function} right-icon-click 通过right-icon生成的图标被点击时触发
* @event {Function} click 输入框被点击或者通过right-icon生成的图标被点击时触发这样设计是考虑到传递右边的图标一般都为需要弹出"picker"等操作时的场景点击倒三角图标理应发出此事件见上方说明
* @example <u-field v-model="mobile" label="手机号" required :error-message="errorMessage"></u-field>
*/
export default {
name:"u-field",
props: {
icon: String,
rightIcon: String,
// arrowDirection: {
// type: String,
// default: 'right'
// },
required: Boolean,
label: String,
password: Boolean,
clearable: {
type: Boolean,
default: true
},
// rpx
labelWidth: {
type: [Number, String],
default: 130
},
// left|center|right
labelAlign: {
type: String,
default: 'left'
},
inputAlign: {
type: String,
default: 'left'
},
iconColor: {
type: String,
default: '#606266'
},
autoHeight: {
type: Boolean,
default: true
},
errorMessage: {
type: [String, Boolean],
default: ''
},
placeholder: String,
placeholderStyle: String,
focus: Boolean,
fixed: Boolean,
value: [Number, String],
type: {
type: String,
default: 'text'
},
disabled: {
type: Boolean,
default: false
},
maxlength: {
type: [Number, String],
default: 140
},
confirmType: {
type: String,
default: 'done'
},
// lable left-top-
labelPosition: {
type: String,
default: 'left'
},
//
fieldStyle: {
type: Object,
default() {
return {}
}
},
//
clearSize: {
type: [Number, String],
default: 30
}
},
inject: ['uCellGroup'],
data() {
return {
focused: false,
itemIndex: 0,
};
},
created() {
if(this.uCellGroup) {
this.itemIndex = this.uCellGroup.index++;
}
},
computed: {
inputWrapStyle() {
let style = {};
style.textAlign = this.inputAlign;
// lableleftinput
if(this.labelPosition == 'left') {
style.margin = `0 8rpx`;
} else {
// labletopinput
style.marginRight = `8rpx`;
}
return style;
},
rightIconStyle() {
let style = {};
if (this.arrowDirection == 'top') style.transform = 'roate(-90deg)';
if (this.arrowDirection == 'bottom') style.transform = 'roate(90deg)';
else style.transform = 'roate(0deg)';
return style;
},
labelStyle() {
let style = {};
if(this.labelAlign == 'left') style.justifyContent = 'flext-start';
if(this.labelAlign == 'center') style.justifyContent = 'center';
if(this.labelAlign == 'right') style.justifyContent = 'flext-end';
return style;
},
// unicomputedstyle.justifyContent = 'center'
justifyContent() {
if(this.labelAlign == 'left') return 'flex-start';
if(this.labelAlign == 'center') return 'center';
if(this.labelAlign == 'right') return 'flex-end';
},
// uniappinputmaxlength
inputMaxlength() {
return Number(this.maxlength)
},
// label
fieldInnerStyle() {
let style = {};
if(this.labelPosition == 'left') {
style.flexDirection = 'row';
} else {
style.flexDirection = 'column';
}
return style;
}
},
methods: {
onInput(event) {
this.$emit('input', event.target.value);
},
onFocus(event) {
this.focused = true;
this.$emit('focus', event);
},
onBlur(event) {
this.focused = false;
this.$emit('blur', event);
},
onConfirm(e) {
this.$emit('confirm', e.detail.value);
},
onClear(event) {
this.$emit('input', '');
},
rightIconClick() {
this.$emit('right-icon-click');
this.$emit('click');
},
fieldClick() {
this.$emit('click');
}
}
};
</script>
<style lang="scss" scoped>
.u-field {
font-size: 28rpx;
padding: 20rpx 28rpx;
text-align: left;
position: relative;
color: $u-main-color;
}
.u-field-inner {
display: flex;
align-items: center;
}
.u-textarea-inner {
align-items: flex-start;
}
.u-textarea-class {
min-height: 96rpx;
width: auto;
font-size: 28rpx;
}
.fild-body {
display: flex;
flex: 1;
align-items: center;
}
.u-arror-right {
margin-left: 8rpx;
}
.u-label-text {
display: inline-block;
}
.u-label-left-gap {
margin-left: 6rpx;
}
.u-label-postion-top {
flex-direction: column;
align-items: flex-start;
}
.u-label {
width: 130rpx;
flex: 1 1 130rpx;
text-align: left;
position: relative;
display: flex;
align-items: center;
}
.u-required::before {
content: '*';
position: absolute;
left: -16rpx;
font-size: 14px;
color: $u-type-error;
height: 9px;
line-height: 1;
}
.u-field__input-wrap {
position: relative;
overflow: hidden;
font-size: 28rpx;
height: 48rpx;
flex: 1;
width: auto;
}
.u-clear-icon {
display: flex;
align-items: center;
}
.u-field-border:after {
left: 32rpx!important;
position: absolute;
box-sizing: border-box;
content: ' ';
pointer-events: none;
right: 0;
top: 0;
border-bottom: 1px solid $u-border-color;
-webkit-transform: scaleY(0.5);
transform: scaleY(0.5);
}
.u-error-message {
color: $u-type-error;
font-size: 26rpx;
text-align: left;
}
.placeholder-style {
color: rgb(150, 151, 153);
}
.u-input-class {
font-size: 28rpx;
}
</style>

View File

@ -0,0 +1,338 @@
<template>
<view class="u-form-item" :class="{'u-border-bottom': borderBottom, 'u-form-item__border-bottom--error': validateState === 'error' && showError('border-bottom')}">
<view class="u-form-item__body" :style="{
flexDirection: labelPosition == 'left' ? 'row' : 'column'
}">
<view class="u-form-item--left" :style="{
width: labelPosition == 'left' ? labelWidth + 'rpx' : '100%',
flex: `0 0 ${labelPosition == 'left' ? labelWidth + 'rpx' : '100%'}`,
marginBottom: labelPosition == 'left' ? 0 : '10rpx',
}">
<!-- 为了块对齐 -->
<view class="u-form-item--left__content">
<!-- nvue不支持伪元素before -->
<text v-if="isRequired" class="u-form-item--left__content--required">*</text>
<view class="u-form-item--left__content__icon" v-if="leftIcon">
<u-icon :name="leftIcon" :custom-style="leftIconStyle"></u-icon>
</view>
<view class="u-form-item--left__content__label" :style="[labelStyle, {
'justify-content': labelAlign == 'left' ? 'flex-star' : labelAlign == 'center' ? 'center' : 'flex-end'
}]">
{{label}}
</view>
</view>
</view>
<view class="u-form-item--right u-flex">
<view class="u-form-item--right__content">
<view class="u-form-item--right__content__slot ">
<slot />
</view>
<view class="u-form-item--right__content__icon u-flex" v-if="$slots.right || rightIcon">
<u-icon :custom-style="rightIconStyle" v-if="rightIcon" :name="rightIcon"></u-icon>
<slot name="right" />
</view>
</view>
</view>
</view>
<view class="u-form-item__message" v-if="validateState === 'error' && showError('message')" :style="{
paddingLeft: labelPosition == 'left' ? `${labelWidth}rpx` : '0',
}">{{validateMessage}}</view>
</view>
</template>
<script>
import Emitter from '../../libs/util/emitter.js';
import schema from '../../libs/util/async-validator';
//
schema.warning = function(){};
export default {
name: 'u-form-item',
mixins: [Emitter],
inject: {
uForm: {
default() {
return null
}
}
},
props: {
// inputlabel
label: {
type: String,
default: ''
},
//
prop: {
type: String,
default: ''
},
// 线
borderBottom: {
type: Boolean,
default: true
},
// labelleft-top-
labelPosition: {
type: String,
default: 'left'
},
// labelrpx
labelWidth: {
type: [String, Number],
default: 90
},
// lable
labelStyle: {
type: Object,
default() {
return {}
}
},
// lable
labelAlign: {
type: String,
default: 'left'
},
//
rightIcon: {
type: String,
default: ''
},
//
leftIcon: {
type: String,
default: ''
},
//
leftIconStyle: {
type: Object,
default() {
return {}
}
},
//
rightIconStyle: {
type: Object,
default() {
return {}
}
}
},
data() {
return {
initialValue: '', //
isRequired: false, //
validateState: '', //
validateMessage: '' ,//
// message-border-input
// border-bottom-none-
errorType: ['message']
};
},
watch: {
validateState(val) {
this.broadcastInputError();
},
// u-formerrorType
"uForm.errorType"(val) {
this.errorType = val;
this.broadcastInputError();
}
},
computed: {
fieldValue() {
return this.uForm.model[this.prop];
},
showError() {
return type => {
// errorTypenone
if(this.errorType.indexOf('none') >= 0) return false;
else if(this.errorType.indexOf(type) >= 0) return true;
else return false;
}
}
},
methods: {
broadcastInputError() {
// truefalsetrue
this.broadcast('u-input', 'on-form-item-error', this.validateState === 'error' && this.showError('border'));
},
// required
setRules() {
let that = this;
// u-formu-form-item
let rules = this.getRules();
if (rules.length) {
this.isRequired = rules.some(rule => {
// undefined
return rule.required;
});
}
// blur
this.$on('on-form-blur', that.onFieldBlur);
// change
this.$on('on-form-change', that.onFieldChange);
},
// u-formrulesu-form-item
getRules() {
//
let rules = this.uForm.rules;
rules = rules ? rules[this.prop] : [];
//
return [].concat(rules || []);
},
// blur
onFieldBlur() {
this.validation('blur');
},
// change
onFieldChange() {
this.validation('change');
},
// rule
getFilteredRule(triggerType = '') {
let rules = this.getRules();
// triggerType
if(!triggerType) return rules;
// blurchange
// return rules.filter(res => res.trigger == triggerType);
// 使indexOftrigger"blur,change"
return rules.filter(res => !res.trigger || res.trigger.indexOf(triggerType) !== -1);
},
//
validation(trigger, callback = () => {}) {
// blurchange
let rules = this.getFilteredRule(trigger);
// u-form
// count
if (!rules || rules.length === 0) {
return callback('');
}
//
this.validateState = 'validating';
// async-validator
let validator = new schema({ [this.prop]: rules });
validator.validate({ [this.prop]: this.fieldValue }, { firstFields: true }, (errors, fields) => {
//
this.validateState = !errors ? 'success' : 'error';
this.validateMessage = errors ? errors[0].message : '';
//
callback(this.validateMessage);
});
},
// u-form-item
resetField() {
this.uForm.model[this.prop] = this.initialValue;
// `success`
this.validateState = 'success';
}
},
// u-form
mounted() {
// propuForm(u-form-input使uForm)
if (!this.prop || this.uForm === null) return;
//
this.dispatch('u-form', 'on-form-item-add', this);
this.errorType = this.uForm.errorType;
//
this.initialValue = this.fieldValue;
//
this.setRules();
},
// Form
beforeDestroy() {
this.dispatch('u-form', 'on-form-item-remove', this);
}
};
</script>
<style lang="scss" scoped>
.u-form-item {
display: flex;
// align-items: flex-start;
padding: 20rpx 0;
font-size: 28rpx;
color: $u-main-color;
box-sizing: border-box;
line-height: $u-form-item-height;
flex-direction: column;
&__border-bottom--error:after {
border-color: $u-type-error;
}
&__body {
display: flex;
}
&--left {
display: flex;
align-items: center;
&__content {
position: relative;
display: flex;
align-items: center;
padding-right: 10rpx;
flex: 1;
&__icon {
margin-right: 8rpx;
}
&--required {
position: absolute;
left: -16rpx;
vertical-align: middle;
color: $u-type-error;
padding-top: 6rpx;
}
&__label {
display: flex;
align-items: center;
flex: 1;
}
}
}
&--right {
flex: 1;
&__content {
display: flex;
align-items: center;
flex: 1;
&__slot {
flex: 1;
/* #ifndef MP */
display: flex;
align-items: center;
/* #endif */
}
&__icon {
margin-left: 10rpx;
}
}
}
&__message {
font-size: 24rpx;
line-height: 24rpx;
color: $u-type-error;
margin-top: 12rpx;
}
}
</style>

97
node_modules/uview-ui/components/u-form/u-form.vue generated vendored Normal file
View File

@ -0,0 +1,97 @@
<template>
<view class="u-form"><slot /></view>
</template>
<script>
export default {
name: 'u-form',
props: {
// form
model: {
type: Object,
default() {
return {};
}
},
//
// rules: {
// type: [Object, Function, Array],
// default() {
// return {};
// }
// },
// message-border-input
// border-bottom-none-
errorType: {
type: Array,
default() {
return ['message']
}
}
},
provide() {
return {
uForm: this
};
},
data() {
return {
rules: {}
};
},
created() {
// formu-form-item
// data
this.fields = [];
//
let that = this;
// on-form-item-addfields
this.$on('on-form-item-add', item => {
if (item) {
that.fields.push(item);
}
});
//
this.$on('on-form-item-remove', item => {
// prop
if (item.prop) {
that.fields.splice(that.fields.indexOf(item), 1);
}
});
},
methods: {
setRules(rules) {
this.rules = rules;
},
// u-form-itemu-form-itemresetField()
resetFields() {
this.fields.map(field => {
field.resetField();
});
},
//
validate(callback) {
return new Promise(resolve => {
// u-form-item
let valid = true; //
let count = 0; //
this.fields.map(field => {
// u-form-itemvalidation
field.validation('', error => {
// u-form-item
if (error) valid = false;
// u-form-itempromisethen
if (++count === this.fields.length) {
resolve(valid); // promisethen
//
if (typeof callback == 'function') callback(valid);
}
});
});
});
}
}
};
</script>
<style></style>

View File

@ -0,0 +1,50 @@
<template>
<u-modal v-model="show" :show-cancel-button="true" confirm-text="升级" title="发现新版本" @cancel="cancel" @confirm="confirm">
<view class="u-update-content">
<rich-text :nodes="content"></rich-text>
</view>
</u-modal>
</template>
<script>
export default {
data() {
return {
show: true,
content: `
1. 修复badge组件的size参数无效问题<br>
2. 新增Modal模态框组件<br>
3. 新增压窗屏组件可以在APP上以弹窗的形式遮盖导航栏和底部tabbar<br>
4. 修复键盘组件在微信小程序上遮罩无效的问题
`,
}
},
onShow() {
this.show = true;
},
methods: {
cancel() {
this.closeModal();
},
confirm() {
this.closeModal();
},
closeModal() {
uni.navigateBack();
}
}
}
</script>
<style scoped lang="scss">
.u-full-content {
background-color: #00C777;
}
.u-update-content {
font-size: 26rpx;
color: $u-content-color;
line-height: 1.7;
padding: 30rpx;
}
</style>

52
node_modules/uview-ui/components/u-gap/u-gap.vue generated vendored Normal file
View File

@ -0,0 +1,52 @@
<template>
<view class="u-gap" :style="[gapStyle]"></view>
</template>
<script>
/**
* gap 间隔槽
* @description 该组件一般用于内容块之间的用一个灰色块隔开的场景方便用户风格统一减少工作量
* @tutorial https://www.uviewui.com/components/gap.html
* @property {String} bg-color 背景颜色默认#f3f4f6
* @property {String Number} height 分割槽高度单位rpx默认30
* @property {String Number} margin-top 与前一个组件的距离单位rpx默认0
* @property {String Number} margin-bottom 与后一个组件的距离单位rpx0
* @example <u-gap height="80" bg-color="#bbb"></u-gap>
*/
export default {
name: "u-gap",
props: {
bgColor: {
type: String,
default: 'transparent ' //
},
//
height: {
type: [String, Number],
default: 30
},
//
marginTop: {
type: [String, Number],
default: 0
},
//
marginBottom: {
type: [String, Number],
default: 0
},
},
computed: {
gapStyle() {
return {
backgroundColor: this.bgColor,
height: this.height + 'rpx',
marginTop: this.marginTop + 'rpx',
marginBottom: this.marginBottom + 'rpx'
};
}
}
};
</script>
<style></style>

View File

@ -0,0 +1,111 @@
<template>
<view class="u-grid-item" :hover-class="hoverClass"
:hover-stay-time="200" @tap="click" :style="{
background: bgColor,
width: width,
}">
<view class="u-grid-item-box" :class="[showBorder ? 'u-border-right u-border-bottom' : '']">
<slot />
</view>
</view>
</template>
<script>
/**
* gridItem 提示
* @description 宫格组件一般用于同时展示多个同类项目的场景可以给宫格的项目设置徽标组件(badge)或者图标等也可以扩展为左右滑动的轮播形式搭配u-grid使用
* @tutorial https://www.uviewui.com/components/grid.html
* @property {String} bg-color 宫格的背景颜色默认#ffffff
* @property {String Number} index 点击宫格时返回的值
* @event {Function} click 点击宫格触发
* @example <u-grid-item></u-grid-item>
*/
export default {
name: "u-grid-item",
props: {
//
bgColor: {
type: String,
default: '#ffffff'
},
// index
index: {
type: [Number, String],
default: ''
},
},
// providethis
inject: ['uGrid'],
data() {
return {
hoverClass: '', //
};
},
created() {
this.hoverClass = this.uGrid.hoverClass;
},
computed: {
// 221212
colNum() {
return this.col < 2 ? 2 : this.col > 12 ? 12 : this.col;
},
// grid-item
width() {
return 100 / Number(this.uGrid.col) + '%';
},
//
// created
showBorder() {
return this.uGrid.border;
}
},
methods: {
click() {
this.$emit('click', this.index);
this.uGrid.click(this.index);
}
},
};
</script>
<style scoped lang="scss">
.u-grid-item {
box-sizing: border-box;
background: #fff;
display: flex;
align-items: center;
justify-content: center;
position: relative;
flex-direction: column;
/* #ifdef MP */
position: relative;
float: left;
/* #endif */
}
.u-grid-item-hover {
background: #f7f7f7 !important;
}
.u-grid-marker-box {
position: absolute;
display: inline-block;
line-height: 0;
}
.u-grid-marker-wrap {
position: absolute;
}
.u-grid-item-box {
padding: 30rpx 0;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
flex: 1;
width: 100%;
height: 100%;
}
</style>

93
node_modules/uview-ui/components/u-grid/u-grid.vue generated vendored Normal file
View File

@ -0,0 +1,93 @@
<template>
<view class="u-grid" :class="{'u-border-top u-border-left': border}" :style="[gridStyle]"><slot /></view>
</template>
<script>
/**
* grid 宫格布局
* @description 宫格组件一般用于同时展示多个同类项目的场景可以给宫格的项目设置徽标组件(badge)或者图标等也可以扩展为左右滑动的轮播形式
* @tutorial https://www.uviewui.com/components/grid.html
* @property {String Number} col 宫格的列数默认3
* @property {Boolean} border 是否显示宫格的边框默认true
* @property {Boolean} hover-class 点击宫格的时候是否显示按下的灰色背景默认false
* @event {Function} click 点击宫格触发
* @example <u-grid :col="3" @click="click"></u-grid>
*/
export default {
name: 'u-grid',
props: {
//
col: {
type: [Number, String],
default: 3
},
//
border: {
type: Boolean,
default: true
},
//
align: {
type: String,
default: 'left'
},
// "none"
hoverClass: {
type: String,
default: 'u-hover-class'
}
},
data() {
return {
index: 0,
}
},
provide() {
return {
uGrid: this
}
},
computed: {
//
gridStyle() {
let style = {};
switch(this.align) {
case 'left':
style.justifyContent = 'flex-start';
break;
case 'center':
style.justifyContent = 'center';
break;
case 'right':
style.justifyContent = 'flex-end';
break;
default: style.justifyContent = 'flex-start';
};
return style;
}
},
methods: {
click(index) {
this.$emit('click', index);
}
}
};
</script>
<style scoped lang="scss">
.u-grid {
width: 100%;
/* #ifdef MP */
position: relative;
box-sizing: border-box;
overflow: hidden;
/* #endif */
/* #ifndef MP */
display: flex;
flex-wrap: wrap;
align-items: center;
/* #endif */
}
</style>

174
node_modules/uview-ui/components/u-icon/u-icon.vue generated vendored Normal file
View File

@ -0,0 +1,174 @@
<template>
<view :style="[customStyle]" class="u-icon" @tap="click" :class="[labelPos == 'bottom' ? 'u-flex-col u-row-center' : 'u-flex u-col-center']">
<image class="u-icon__img" v-if="isImg" :src="name" :mode="imgMode" :style="[imgStyle]"></image>
<text v-else class="u-icon__icon" :class="customClass" :style="[iconStyle]" :hover-class="hoverClass" @touchstart="touchstart"></text>
<text v-if="label" class="u-icon__label" :style="{
color: labelColor,
fontSize: labelSize + 'rpx',
marginLeft: labelPos == 'right' ? marginLeft + 'rpx' : 0,
marginTop: labelPos == 'bottom' ? marginTop + 'rpx' : 0,
}">{{label}}</text>
</view>
</template>
<script>
/**
* icon 图标
* @description 基于字体的图标集包含了大多数常见场景的图标
* @tutorial https://www.uviewui.com/components/icon.html
* @property {String} name 图标名称见示例图标集
* @property {String} color 图标颜色默认inherit
* @property {String | Number} size 图标字体大小单位rpx默认32
* @property {String | Number} label-size label字体大小单位rpx默认28
* @property {String} label 图标右侧的label文字默认28
* @property {String} label-pos label文字相对于图标的位置只能right或bottom默认right
* @property {String} label-color label字体颜色默认#606266
* @property {String | Number} margin-left label在右侧时与图标的距离单位rpx默认6
* @property {String | Number} margin-top label在下方时与图标的距离单位rpx默认6
* @property {String} label-pos label相对于图标的位置只能right或bottom默认right
* @property {String} index 一个用于区分多个图标的值点击图标时通过click事件传出
* @property {String} hover-class 图标按下去的样式类用法同uni的view组件的hover-class参数详情见官网
* @event {Function} click 点击图标时触发
* @example <u-icon name="photo" color="#2979ff" size="28"></u-icon>
*/
export default {
name: 'u-icon',
props: {
//
name: {
type: String,
default: ''
},
//
color: {
type: String,
default: ''
},
// rpx
size: {
type: [Number, String],
default: 'inherit'
},
//
bold: {
type: Boolean,
default: false
},
// index
index: {
type: [Number, String],
default: ''
},
//
hoverClass: {
type: String,
default: ''
},
// 便
customPrefix: {
type: String,
default: 'uicon'
},
//
label: {
type: String,
default: ''
},
// label
labelPos: {
type: String,
default: 'right'
},
// label
labelSize: {
type: [String, Number],
default: '28'
},
// label
labelColor: {
type: String,
default: '#606266'
},
// label()
marginLeft: {
type: [String, Number],
default: '6'
},
// label()
marginTop: {
type: [String, Number],
default: '6'
},
// mode
imgMode: {
type: String,
default: 'widthFix'
},
//
customStyle: {
type: Object,
default() {
return {}
}
}
},
data() {
return {};
},
computed: {
customClass() {
let classes = [];
classes.push(this.customPrefix + '-' + this.name);
// uViewu-iconfont
if (this.customPrefix == 'uicon') classes.push('u-iconfont');
else classes.push(this.customPrefix);
// 使[a, b, c]
//
//#ifdef MP-ALIPAY || MP-TOUTIAO || MP-BAIDU
classes = classes.join(' ');
//#endif
return classes;
},
iconStyle() {
let style = {};
style = {
fontSize: this.size == 'inherit' ? 'inherit' : this.size + 'rpx',
fontWeight: this.bold ? 'bold' : 'normal'
};
if (this.color) style.color = this.color;
return style;
},
// name"/"
isImg() {
return this.name.indexOf('/') !== -1;
},
imgStyle() {
let style = {};
style.width = this.size + 'rpx';
return style;
}
},
methods: {
click() {
this.$emit('click', this.index);
},
touchstart() {
this.$emit('touchstart', this.index);
}
}
};
</script>
<style scoped lang="scss">
@import '../../iconfont.css';
.u-icon {
display: inline-flex;
align-items: center;
}
.u-icon__img {
height: auto;
will-change: transform;
}
</style>

View File

@ -0,0 +1,79 @@
<template>
<view class="u-index-anchor-wrapper" :id="$u.guid()" :style="[wrapperStyle]">
<view class="u-index-anchor " :class="[active ? 'u-index-anchor--active' : '']" :style="[customAnchorStyle]">
<slot v-if="useSlot" />
<block v-else>
<text>{{ index }}</text>
</block>
</view>
</view>
</template>
<script>
/**
* indexAnchor 索引列表锚点
* @description 通过折叠面板收纳内容区域,搭配<u-index-anchor>使用
* @tutorial https://www.uviewui.com/components/indexList.html#indexanchor-props
* @property {Boolean} use-slot 是否使用自定义内容的插槽默认false
* @property {String Number} index 索引字符如果定义了use-slot此参数自动失效
* @property {Object} custStyle 自定义样式对象形式"{color: 'red'}"
* @event {Function} default 锚点位置显示内容默认为索引字符
* @example <u-index-anchor :index="item" />
*/
export default {
name: "u-index-anchor",
props: {
useSlot: {
type: Boolean,
default: false
},
index: {
type: String,
default: ''
},
customStyle: {
type: Object,
default () {
return {}
}
}
},
data() {
return {
active: false,
wrapperStyle: {},
anchorStyle: {}
}
},
inject: ['UIndexList'],
mounted() {
this.UIndexList.children.push(this);
this.UIndexList.updateData();
},
computed: {
customAnchorStyle() {
return Object.assign(this.anchorStyle, this.customStyle);
}
}
}
</script>
<style lang="scss" scoped>
.u-index-anchor {
box-sizing: border-box;
padding: 14rpx 24rpx;
color: #606266;
width: 100%;
font-weight: 500;
font-size: 28rpx;
line-height: 1.2;
background-color: rgb(245, 245, 245);
}
.u-index-anchor--active {
right: 0;
left: 0;
color: #2979ff;
background-color: #fff;
}
</style>

View File

@ -0,0 +1,316 @@
<template>
<view class="u-index-bar">
<slot />
<view v-if="showSidebar" class="u-index-bar__sidebar" @touchstart.stop.prevent="onTouchMove" @touchmove.stop.prevent="onTouchMove"
@touchend.stop.prevent="onTouchStop" @touchcancel.stop.prevent="onTouchStop">
<view v-for="(item, index) in indexList" :key="index" class="u-index-bar__index" :style="{zIndex: zIndex + 1, color: activeAnchorIndex === index ? activeColor : ''}"
:data-index="index">
{{ item }}
</view>
</view>
<view class="u-indexed-list-alert" v-if="touchmove && indexList[touchmoveIndex]" :style="{
zIndex: alertZIndex
}">
<text>{{indexList[touchmoveIndex]}}</text>
</view>
</view>
</template>
<script>
var indexList = function() {
var indexList = [];
var charCodeOfA = 'A'.charCodeAt(0);
for (var i = 0; i < 26; i++) {
indexList.push(String.fromCharCode(charCodeOfA + i));
}
return indexList;
};
/**
* indexList 索引列表
* @description 通过折叠面板收纳内容区域,搭配<u-index-anchor>使用
* @tutorial https://www.uviewui.com/components/indexList.html#indexanchor-props
* @property {Number String} scroll-top 当前滚动高度自定义组件无法获得滚动条事件所以依赖接入方传入
* @property {Array} index-list 索引字符列表数组默认A-Z
* @property {Number String} z-index 锚点吸顶时的层级默认965
* @property {Boolean} sticky 是否开启锚点自动吸顶默认true
* @property {Number String} offset-top 锚点自动吸顶时与顶部的距离默认0
* @property {String} highlight-color 锚点和右边索引字符高亮颜色默认#2979ff
* @event {Function} select 选中右边索引字符时触发
* @example <u-index-list :scrollTop="scrollTop"></u-index-list>
*/
export default {
name: "u-index-list",
props: {
sticky: {
type: Boolean,
default: true
},
zIndex: {
type: [Number, String],
default: ''
},
scrollTop: {
type: [Number, String],
default: 0,
},
offsetTop: {
type: [Number, String],
default: 0
},
indexList: {
type: Array,
default () {
return indexList()
}
},
activeColor: {
type: String,
default: '#2979ff'
}
},
created() {
// #ifdef H5
this.stickyOffsetTop = this.offsetTop ? uni.upx2px(this.offsetTop) : 44;
// #endif
// #ifndef H5
this.stickyOffsetTop = this.offsetTop ? uni.upx2px(this.offsetTop) : 0;
// #endif
// createdchildrendataprovide/inject
// push
this.children = [];
},
provide() {
return {
UIndexList: this
}
},
data() {
return {
activeAnchorIndex: 0,
showSidebar: true,
// children: [],
touchmove: false,
touchmoveIndex: 0,
}
},
watch: {
scrollTop() {
this.updateData()
}
},
computed: {
// toastz-index
alertZIndex() {
return this.$u.zIndex.toast;
}
},
methods: {
updateData() {
this.timer && clearTimeout(this.timer);
this.timer = setTimeout(() => {
this.showSidebar = !!this.children.length;
this.setRect().then(() => {
this.onScroll();
});
}, 0);
},
setRect() {
return Promise.all([
this.setAnchorsRect(),
this.setListRect(),
this.setSiderbarRect()
]);
},
setAnchorsRect() {
return Promise.all(this.children.map((anchor, index) => anchor
.$uGetRect('.u-index-anchor-wrapper')
.then((rect) => {
Object.assign(anchor, {
height: rect.height,
top: rect.top
});
})));
},
setListRect() {
return this.$uGetRect('.u-index-bar').then((rect) => {
Object.assign(this, {
height: rect.height,
top: rect.top + this.scrollTop
});
});
},
setSiderbarRect() {
return this.$uGetRect('.u-index-bar__sidebar').then(rect => {
this.sidebar = {
height: rect.height,
top: rect.top
};
});
},
getActiveAnchorIndex() {
const {
children
} = this;
const {
sticky
} = this;
for (let i = this.children.length - 1; i >= 0; i--) {
const preAnchorHeight = i > 0 ? children[i - 1].height : 0;
const reachTop = sticky ? preAnchorHeight : 0;
if (reachTop >= children[i].top) {
return i;
}
}
return -1;
},
onScroll() {
const {
children = []
} = this;
if (!children.length) {
return;
}
const {
sticky,
stickyOffsetTop,
zIndex,
scrollTop,
activeColor
} = this;
const active = this.getActiveAnchorIndex();
this.activeAnchorIndex = active;
if (sticky) {
let isActiveAnchorSticky = false;
if (active !== -1) {
isActiveAnchorSticky =
children[active].top <= 0;
}
children.forEach((item, index) => {
if (index === active) {
let wrapperStyle = '';
let anchorStyle = {
color: `${activeColor}`
};
if (isActiveAnchorSticky) {
wrapperStyle = {
height: `${children[index].height}px`
};
anchorStyle = {
position: 'fixed',
top: `${stickyOffsetTop}px`,
zIndex: `${zIndex ? zIndex : this.$u.zIndex.indexListSticky}`,
color: `${activeColor}`
};
}
item.active = active;
item.wrapperStyle = wrapperStyle;
item.anchorStyle = anchorStyle;
} else if (index === active - 1) {
const currentAnchor = children[index];
const currentOffsetTop = currentAnchor.top;
const targetOffsetTop = index === children.length - 1 ?
this.top :
children[index + 1].top;
const parentOffsetHeight = targetOffsetTop - currentOffsetTop;
const translateY = parentOffsetHeight - currentAnchor.height;
const anchorStyle = {
position: 'relative',
transform: `translate3d(0, ${translateY}px, 0)`,
zIndex: `${zIndex ? zIndex : this.$u.zIndex.indexListSticky}`,
color: `${activeColor}`
};
item.active = active;
item.anchorStyle = anchorStyle;
} else {
item.active = false;
item.anchorStyle = '';
item.wrapperStyle = '';
}
});
}
},
onTouchMove(event) {
this.touchmove = true;
const sidebarLength = this.children.length;
const touch = event.touches[0];
const itemHeight = this.sidebar.height / sidebarLength;
let clientY = 0;
clientY = touch.clientY;
let index = Math.floor((clientY - this.sidebar.top) / itemHeight);
if (index < 0) {
index = 0;
} else if (index > sidebarLength - 1) {
index = sidebarLength - 1;
}
this.touchmoveIndex = index;
this.scrollToAnchor(index);
},
onTouchStop() {
this.touchmove = false;
this.scrollToAnchorIndex = null;
},
scrollToAnchor(index) {
if (this.scrollToAnchorIndex === index) {
return;
}
this.scrollToAnchorIndex = index;
const anchor = this.children.find((item) => item.index === this.indexList[index]);
if (anchor) {
this.$emit('select', anchor.index);
uni.pageScrollTo({
duration: 0,
scrollTop: anchor.top + this.scrollTop
});
}
}
}
};
</script>
<style lang="scss" scoped>
.u-index-bar {
position: relative
}
.u-index-bar__sidebar {
position: fixed;
top: 50%;
right: 0;
display: flex;
flex-direction: column;
text-align: center;
transform: translateY(-50%);
user-select: none;
z-index: 99;
}
.u-index-bar__index {
font-weight: 500;
padding: 8rpx 18rpx;
font-size: 22rpx;
line-height: 1
}
.u-indexed-list-alert {
position: fixed;
width: 120rpx;
height: 120rpx;
right: 90rpx;
top: 50%;
margin-top: -60rpx;
border-radius: 24rpx;
font-size: 50rpx;
color: #fff;
background-color: rgba(0, 0, 0, 0.65);
display: flex;
justify-content: center;
align-items: center;
padding: 0;
z-index: 9999999;
}
.u-indexed-list-alert text {
line-height: 50rpx;
}
</style>

319
node_modules/uview-ui/components/u-input/u-input.vue generated vendored Normal file
View File

@ -0,0 +1,319 @@
<template>
<view
class="u-input"
:class="{
'u-input--border': border,
'u-input--error': validateState
}"
:style="{
padding: `0 ${border ? 20 : 0}rpx`,
borderColor: borderColor,
textAlign: inputAlign
}"
@tap.stop="inputClick"
>
<textarea
v-if="type == 'textarea'"
class="u-input__input u-input__textarea"
:style="[getStyle]"
:value="value"
:placeholder="placeholder"
:placeholderStyle="placeholderStyle"
:disabled="disabled"
:maxlength="inputMaxlength"
:fixed="fixed"
:focus="focus"
:autoHeight="autoHeight"
@input="handleInput"
@blur="handleBlur"
@focus="onFocus"
@confirm="onConfirm"
/>
<input
v-else
class="u-input__input"
:type="type == 'password' ? 'text' : type"
:style="[getStyle]"
:value="defaultValue"
:password="type == 'password' && showPassword"
:placeholder="placeholder"
:placeholderStyle="placeholderStyle"
:disabled="disabled || type === 'select'"
:maxlength="inputMaxlength"
:focus="focus"
:confirmType="confirmType"
@focus="onFocus"
@blur="handleBlur"
@input="handleInput"
@confirm="onConfirm"
/>
<view class="u-input__right-icon u-flex">
<view class="u-input__right-icon__clear u-input__right-icon__item" v-if="clearable && value && focused">
<u-icon size="32" name="close-circle-fill" color="#c0c4cc" @touchstart="onClear"/>
</view>
<view class="u-input__right-icon__clear u-input__right-icon__item" v-if="passwordIcon && type == 'password'">
<u-icon size="32" :name="showPassword ? 'eye' : 'eye-fill'" color="#c0c4cc" @click="showPassword = !showPassword"/>
</view>
<view class="u-input__right-icon--select u-input__right-icon__item" v-if="type == 'select'" :class="{
'u-input__right-icon--select--reverse': selectOpen
}">
<u-icon name="arrow-down-fill" size="26" color="#c0c4cc"></u-icon>
</view>
</view>
</view>
</template>
<script>
import Emitter from '../../libs/util/emitter.js';
export default {
name: 'u-input',
mixins: [Emitter],
props: {
value: {
type: String,
default: ''
},
// textareatextnumber
type: {
type: String,
default: 'text'
},
clearable: {
type: Boolean,
default: true
},
inputAlign: {
type: String,
default: 'left'
},
placeholder: {
type: String,
default: '请输入内容'
},
disabled: {
type: Boolean,
default: false
},
maxlength: {
type: [Number, String],
default: 140
},
placeholderStyle: {
type: String,
default: 'color: #c0c4cc;'
},
confirmType: {
type: String,
default: 'done'
},
//
customStyle: {
type: Object,
default() {
return {};
}
},
// textarea position:fixed fixed true
fixed: {
type: Boolean,
default: false
},
//
focus: {
type: Boolean,
default: false
},
//
passwordIcon: {
type: Boolean,
default: true
},
// input|textarea
border: {
type: Boolean,
default: false
},
//
borderColor: {
type: String,
default: '#dcdfe6'
},
autoHeight: {
type: Boolean,
default: true
},
// type=selectselect
// open-close-
selectOpen: {
type: Boolean,
default: false
},
// rpx
height: {
type: [Number, String],
default: ''
},
//
clearable: {
type: Boolean,
default: true
},
},
data() {
return {
defaultValue: this.value,
inputHeight: 70, // input
textareaHeight: 100, // textarea
validateState: false, // input
focused: false, //
showPassword: this.passwordIcon, //
marginRight: 0, //
};
},
watch: {
value(nVal, oVal) {
this.defaultValue = nVal;
// select(inputdisabled@input)@input
if(nVal != oVal && this.type == 'select') this.handleInput({
detail: {
value: nVal
}
})
},
focused(nVal) {
if(this.clearable && this.value) {
this.getMarginRight();
}
}
},
computed: {
// uniappinputmaxlength
inputMaxlength() {
return Number(this.maxlength);
},
getStyle() {
let style = {};
// typeinputtextare
style.minHeight = this.height ? this.height + 'rpx' : this.type == 'textarea' ?
this.textareaHeight + 'rpx' : this.inputHeight + 'rpx';
style.marginRight = this.marginRight + 'px';
style = Object.assign(style, this.customStyle);
return style;
}
},
created() {
// u-form-item
this.$on('on-form-item-error', this.onFormItemError);
},
mounted() {
this.getMarginRight();
},
methods: {
//
getMarginRight() {
this.$nextTick(() => {
this.$uGetRect('.u-input__right-icon').then(res => {
// 20rpxright
this.marginRight = res.width + uni.upx2px(20);
})
})
},
/**
* change 事件
* @param event
*/
handleInput(event) {
// model
this.defaultValue = event.detail.value;
// vue return
this.$emit('input', event.detail.value);
// u-form-itemthis.$emit('input')
// u-form-item
this.$nextTick(() => {
// u-form-item
this.dispatch('u-form-item', 'on-form-change', event.detail.value);
});
},
/**
* blur 事件
* @param event
*/
handleBlur(event) {
this.focused = false;
// vue return
this.$emit('blur', event.detail.value);
this.$nextTick(() => {
// u-form-item
this.dispatch('u-form-item', 'on-form-blur', event.detail.value);
});
},
onFormItemError(status) {
this.validateState = status;
},
onFocus(event) {
this.focused = true;
this.$emit('focus');
},
onConfirm(e) {
this.$emit('confirm', e.detail.value);
},
onClear(event) {
this.$emit('input');
},
inputClick() {
this.$emit('click');
}
}
};
</script>
<style lang="scss" scoped>
.u-input {
position: relative;
flex: 1;
&__input {
//height: $u-form-item-height;
font-size: 28rpx;
color: $u-main-color;
}
&__textarea {
width: auto;
font-size: 28rpx;
color: $u-main-color;
padding: 10rpx 0;
line-height: normal;
}
&--border {
border-radius: 6rpx;
border-radius: 4px;
border: 1px solid $u-form-item-border-color;
}
&--error {
border-color: $u-type-error!important;
}
&__right-icon {
position: absolute;
right: 20rpx;
top: 50%;
z-index: 3;
transform: translateY(-50%);
&__item {
margin-left: 10rpx;
}
&--select {
transition: transform .4s;
&--reverse {
transform: rotate(-180deg);
}
}
}
}
</style>

View File

@ -0,0 +1,203 @@
<template>
<u-popup class="" :mask="mask" :maskCloseAble="maskCloseAble" mode="bottom" :popup="false" v-model="value" length="auto"
:safeAreaInsetBottom="safeAreaInsetBottom" @close="popupClose">
<slot />
<view class="u-tooltip" v-if="tooltip">
<view class="u-tooltip-item u-tooltip-cancel" hover-class="u-tooltip-cancel-hover" @tap="onCancel">
{{cancelBtn ? '取消' : ''}}
</view>
<view v-if="showTips" class="u-tooltip-item u-tooltip-tips">
{{tips ? tips : mode == 'number' ? '数字键盘' : mode == 'card' ? '身份证键盘' : '车牌号键盘'}}
</view>
<view v-if="confirmBtn" @tap="onConfirm" class="u-tooltip-item u-tooltips-submit" hover-class="u-tooltips-submit-hover">
{{confirmBtn ? '完成' : ''}}
</view>
</view>
<block v-if="mode == 'number' || mode == 'card'">
<u-number-keyboard :random="random" @backspace="backspace" @change="change" :mode="mode" :dotEnabled="dotEnabled"></u-number-keyboard>
</block>
<block v-else>
<u-car-keyboard :random="random" @backspace="backspace" @change="change"></u-car-keyboard>
</block>
</u-popup>
</template>
<script>
/**
* keyboard 键盘
* @description 此为uViw自定义的键盘面板内含了数字键盘车牌号键身份证号键盘3中模式都有可以打乱按键顺序的选项
* @tutorial https://www.uviewui.com/components/keyboard.html
* @property {String} mode 键盘类型见官网基本使用的说明默认number
* @property {Boolean} dot-enabled 是否显示"."按键只在mode=number时有效默认true
* @property {Boolean} tooltip 是否显示键盘顶部工具条默认true
* @property {String} tips 工具条中间的提示文字见上方基本使用的说明如不需要请传""空字符
* @property {Boolean} cancel-btn 是否显示工具条左边的"取消"按钮默认true
* @property {Boolean} confirm-btn 是否显示工具条右边的"完成"按钮默认true
* @property {Boolean} mask 是否显示遮罩默认true
* @property {Number String} z-index 弹出键盘的z-index值默认1075
* @property {Boolean} random 是否打乱键盘按键的顺序默认false
* @property {Boolean} safe-area-inset-bottom 是否开启底部安全区适配默认false
* @property {Boolean} mask-close-able 是否允许点击遮罩收起键盘默认true
* @event {Function} change 按键被点击(不包含退格键被点击)
* @event {Function} cancel 键盘顶部工具条左边的"取消"按钮被点击
* @event {Function} confirm 键盘顶部工具条右边的"完成"按钮被点击
* @event {Function} backspace 键盘退格键被点击
* @example <u-keyboard mode="number" v-model="show"></u-keyboard>
*/
export default {
name: "u-keyboard",
props: {
// number-card-car-
mode: {
type: String,
default: 'number'
},
// "."
dotEnabled: {
type: Boolean,
default: true
},
//
tooltip: {
type: Boolean,
default: true
},
//
showTips: {
type: Boolean,
default: true
},
//
tips: {
type: String,
default: ''
},
// ""
cancelBtn: {
type: Boolean,
default: true
},
// ""
confirmBtn: {
type: Boolean,
default: true
},
//
random: {
type: Boolean,
default: false
},
// iPhoneX
safeAreaInsetBottom: {
type: Boolean,
default: false
},
//
maskCloseAble: {
type: Boolean,
default: true
},
//
value: {
type: Boolean,
default: false
},
//
mask: {
type: Boolean,
default: true
},
// z-index
zIndex: {
type: [Number, String],
default: ''
}
},
data() {
return {
//show: false
}
},
computed: {
uZIndex() {
return this.zIndex ? this.zIndex : this.$u.zIndex.popup;
}
},
methods: {
change(e) {
this.$emit('change', e);
},
//
popupClose() {
// inputpropsvalue
this.$emit('input', false);
},
//
onConfirm() {
this.popupClose();
this.$emit('confirm');
},
//
onCancel() {
this.popupClose();
this.$emit('cancel');
},
// 退
backspace() {
this.$emit('backspace');
},
//
// close() {
// this.show = false;
// },
// //
// open() {
// this.show = true;
// }
}
}
</script>
<style lang="scss" scoped>
.u-keyboard {
position: relative;
z-index: 1003;
}
.u-tooltip {
display: flex;
justify-content: space-between;
}
.u-tooltip-item {
color: #333333;
flex: 0 0 33.333333%;
text-align: center;
padding: 20rpx 10rpx;
font-size: 28rpx;
}
.u-tooltips-submit {
text-align: right;
flex-grow: 1;
flex-wrap: 0;
padding-right: 40rpx;
color: $u-type-primary;
}
.u-tooltip-cancel {
text-align: left;
flex-grow: 1;
flex-wrap: 0;
padding-left: 40rpx;
color: #888888;
}
.u-tooltips-submit-hover {
color: $u-type-success;
}
.u-tooltip-cancel-hover {
color: #333333;
}
</style>

View File

@ -0,0 +1,225 @@
<template>
<view class="u-wrap" :style="{
opacity: Number(opacity),
borderRadius: borderRadius + 'rpx',
// time,duration(prop)
transition: `opacity ${time / 1000}s ease-in-out`
}"
:class="'u-lazy-item-' + elIndex">
<view :class="'u-lazy-item-' + elIndex">
<image :style="{borderRadius: borderRadius + 'rpx', height: imgHeight}" v-if="!isError" class="u-lazy-item"
:src="isShow ? image : loadingImg" :mode="imgMode" @load="imgLoaded" @error="loadError" @tap="clickImg"></image>
<image :style="{borderRadius: borderRadius + 'rpx', height: imgHeight}" class="u-lazy-item error" v-else :src="errorImg"
:mode="imgMode" @load="errorImgLoaded" @tap="clickImg"></image>
</view>
</view>
</template>
<script>
/**
* lazyLoad 懒加载
* @description 懒加载使用的场景为页面有很多图片时APP会同时加载所有的图片导致页面卡顿各个位置的图片出现前后不一致等.
* @tutorial https://www.uviewui.com/components/lazyLoad.html
* @property {String Number} index 用户自定义值在事件触发时回调用以区分是哪个图片
* @property {String} image 图片路径
* @property {String} loading-img 预加载时的占位图
* @property {String} error-img 图片加载出错时的占位图
* @property {String} threshold 触发加载时的位置见上方说明单位 rpx默认300
* @property {String Number} duration 图片加载成功时淡入淡出时间单位ms默认
* @property {String} effect 图片加载成功时淡入淡出的css动画效果默认ease-in-out
* @property {Boolean} is-effect 图片加载成功时是否启用淡入淡出效果默认true
* @property {String Number} border-radius 图片圆角值单位rpx默认0
* @property {String Number} height 图片高度注意实际高度可能受img-mode参数影响默认450
* @property {String Number} mg-mode 图片的裁剪模式详见image组件裁剪模式默认widthFix
* @event {Function} click 点击图片时触发
* @event {Function} load 图片加载成功时触发
* @event {Function} error 图片加载失败时触发
* @example <u-lazy-load :image="image" :loading-img="loadingImg" :error-img="errorImg"></u-lazy-load>
*/
export default {
name: 'u-lazy-load',
props: {
index: {
type: [Number, String]
},
//
image: {
type: String,
default: ''
},
//
imgMode: {
type: String,
default: 'widthFix'
},
//
loadingImg: {
type: String,
default: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAMAAAC3Ycb+AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OUM0QjNBQjkyQUQ2MTFFQTlCNUQ4RTIzNDE5RUIxNjciIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OUM0QjNBQkEyQUQ2MTFFQTlCNUQ4RTIzNDE5RUIxNjciPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo5QzRCM0FCNzJBRDYxMUVBOUI1RDhFMjM0MTlFQjE2NyIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo5QzRCM0FCODJBRDYxMUVBOUI1RDhFMjM0MTlFQjE2NyIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PtRHfPcAAAAzUExURZWVldfX18PDw62trZubm9zc3Li4uKGhoebm5tLS0uHh4c3Nzaenp729vcjIyLKysuvr6141L40AAAcXSURBVHja7NzZlqpGAEBR5lG0//9rIw7IJKJi4or7PGTdtN10wr5SVAEGf/qqArsAiIAAERAgAgJEQIAIiIAAERAgAgJEQIAIiIAAERAgAgJEQIAIiIAAERAgAgJEQIAIiIAAERAgAgJEQIAIiIAAERAgAgJEQIAIiIAAERAgAgJEQIAIiIAAERAgAgJEQIAIiIAAERAgAgJEQIAIiIAAERAgAgJEQIAICBABERAgAgJEQIAICBABERAgAgJEQIAICBABERAgAgJEQIAICBABERAgAgJEQIAICBABERAgAgJEQIAICBABERAgAgJEQIAICBABERAgAgJEQIAICBABERAgAgJEQIAICBABERAg+nmQFMi5Jis+sIniED23jSzIgLTtg2D//iYme/8QBM/9lQ+CAEhbNLM3N9hEHAThX7GPCiBfAxK1b51kD+R7QMLjXg7iCsgWIPUh7pfVozG791oeBPngm48G583uW5GkBvI+SBaM2xXDn1oqum423bX/mgF5FySc2cv93Voug9TdZotsggnkBZB2NzbhrSY5HnoG07jei8dvzsJB/c3W60SALILE46+WCztsbhPR7R2VJq0ukEcT49nyy8QhaKcRa3fYHZD4+ufqOJAcgDz8/59vtw1I3QP5K6JsOG0vm3hce4I8LQp/BaRZGJC3AAn7IKOKXbC+7EdA5vdmmVwOLksgRThqOqiH4XEGsht+peoPUE8U/jJIO5OLH4GEwUslV5G0PTBG5Uiw/Y2jyigO3l9HAHKv9PYb82LloH74dZBoBUgar+l48NsNvtD0fkez9iwrAvIYZDRCl+Xs149Hm/KZmQ+QjUCiO1ei4ru7EsgnQYrkznlQb7thCuRfAzlOAPN72427P4VA/i2Q/DKT/Ls/VR8fvIBsDZIuz7TPF6TCbnk4GJkB2RokejTjuE7/unlgCuSTIO0Cy+Plp6vDfnQlBchy8QtjSHVd3EgmK1bHLm+H6+nXYbz2DuQRSPnqoL7vvq0u70on4zvxgCyWD3b9UyDVdW24PaWaiGTnFZJwPIQAebDpIKheBIm7n124ZthMJipAlkqHO+IZkP1tbfzOJark/A7MgKyvvl60fRqkvXfhuow+t9+q00+0/yyBrK8ZngOtBzldhw2X9tvpNGty0gvkmbPeJ0Cy/r09s/stbmfo0yMWkEdjevgKyOn2t2pxv7UXoibTdCDLje9/Ww1ymqzn87dbp92242ZmMRjI8hASvwKSLq4udqN6ksw8nxXN3tszD9L8Gkg+2mFrQYql5az4tvFj5xOx4VwnSdeBtGdyPwUytxK77pBVlNHdO7OK3rh/eTPUvdutT3fO52tuHMqD4N7llv8pyOQQ//w19YVDfX27+Sfuby9/6nau4pdA8vEdOZuChEH/quHt0Jg+IRJ/5+PrHwKZXfjbDiS73Zo7mu5UkzX7uTsXe0e/7nC3ePf1O69+BUg2XDfZCqSqOu7rGVf8cHBe8zhC2b61dtUHXv0OkGo6ZL4JkpbRYXdUaFevivx2M/1GIOctNh949TtAoumQ+TpIHMX54CJu+8BDd8FkE5BqcZh/59XvAClmTvKfB0nDqIlHo3T70SftyW1eX9dXtgQJqs1f/Q6QaOa/7wmQKtxH8eiGoCRuovODIO3VxOMmruZbHrLyD7z6DSDtGyT7ew1kf9hNn07c986JTovzzem0Id9wUG+Vk/IDr34DSNR7huZJkMFT6vEhqrPx/j5cnlZML8N6/PAzh9Y99Flm5Yde/c9BquDOkvkKkMP58dA4qi9vivE8JOvGz/j8FokfPpr288+pH2ZPOZrLmeGD+7KOh6dqYWJ48ki7yUg0tz0go/fv/LLddfV3sgOLJyaGPY/zrSlh1a36Arkzoue9CyG35ze6E6/dzO2Ga0EGHqdRJIkfn9/8OEjTW8Vq91ZWh39FeehWA7Nu9ft8CpUEk1WWOyDF0OPyEU2Pnzf/bZC0P6IPzmAvu7KauQBVrgKpJ0tG2arHzX8e5Pb3PezNs/PrX+3JMyCLn9XXf37tPFHvt09WfCDDjx+yyn1/p1V11j7GnB/q3leLuVva79S/tzed+db08YpF4uOZtmz/9oXWMq6BCAgQAQEiIEAERECACAgQAQEiIEAERECACAgQAQEiIEAERECACAgQAQEiIEAERECACAgQAQEiIEAERECACAgQAQEiIEAERECACAgQAQEiIEAERECACAgQAQEiIEAERECACAgQAQEiIEAERECACAgQAQEiIEAEBIiACAgQAQEiIEAEBIiACAgQAQEiIEAEBIiACAgQAQEiIEAEBIiACAgQAQEiIEAEBIiACAgQAQEiIEAEBIiACAgQAQEiIEAEBIiACAgQAQEiIEAEBIiACAgQAQEiIEAEBIiACAgQAQEiIEAEBIiAALELvqt/BBgACqVeUBXxcCkAAAAASUVORK5CYII='
},
//
errorImg: {
type: String,
default: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAAGQCAMAAAC3Ycb+AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6ODdDMjhENDYyQUQ2MTFFQTlDQ0VBODgxQjFFOEEyMEMiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6ODdDMjhENDcyQUQ2MTFFQTlDQ0VBODgxQjFFOEEyMEMiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo4N0MyOEQ0NDJBRDYxMUVBOUNDRUE4ODFCMUU4QTIwQyIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo4N0MyOEQ0NTJBRDYxMUVBOUNDRUE4ODFCMUU4QTIwQyIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PhLwhikAAAAzUExURZWVldfX162trcPDw5ubm7i4uNzc3Obm5s3NzaGhoeHh4cjIyKenp9LS0r29vbKysuvr67sDMEkAAAlpSURBVHja7NzpYqMgAIVRUVHc8/5PO66R1WAbOzX97q+ZtDEpR0AWTR7kVyWhCAAhgABCAAGEAAIIAQQQAggBBBACCCAEEEAIIIAQQAgggBBAACGAAEIAAYQAQgABhAACCAEEEAIIIAQQAgggBBBACCCAEEAAIYAQQAAhgABCAAGEAAIIAYQAAggBBBACCCAEEEAIIAQQQAgggBBAACGAAEIAIYAAQgABhAACCAEEEAIIAQQQAgggBBBACCCAEEAAIYAQQAAhgABCAAGEAAIIAYQAAggBBBACCCAEEEAIIAQQQAgggBBAACGAAEIAIYAAQgABhAACCAEEEAIIAQQQAgggBBBACCCAEEAIIIAQQAAhgABCAAGEAEIAAYQAAggBBBACCCAEEAIIIAQQQAgggBBAACGAEEAAIYAAsqeX5QWHKIcs/Ptl03lfL4zDFPWfBGmSpPn+IZzSH5KkCL5B+n+oklwz6Iz//R2QzFOabzhEmiRirAmZt/bl0w/dpMbLqeeo4wEdpC7zR5WAPKziHKtO7ql+ReKvIa9BxgNaL5ZtEkpeAGIVp5jKJa09xVo9vgSSzQcszdYvmOqjQNSQ6pHK6rO1n1Xj32788miwHLaZz1Tl9i/yayDlYJ/60/+lp8GSY7OY1B8E4p55bWmfquFk22GLuUUxi78cX+m+BjL2GLkhMrV+/muS6Sfic0CEp5T1Yu2OQdTzsKV0MJV73KVjroyTffxfuv5Tf3fd6iLT9wz8YdVHgUzF2Is9/Xhi5sYJqP1w/GUpjOiHVbaI0w2L+pg3GZzvtokcgHxWDXHaiy78l3sPke01qphamT5c+dqyeAGSumdL/mkggauTam0e3L/mPEiqtzKDbl0Z1Wn8xOa4ySo8X/7TQIJnY/seEKWf12UmC72CKP9xYjr19RPT7NNA+oMO+R0gwmlotAry+C6I0f59ch8yXVQOr0BKYcXt1IUYRyCt+Ur9HGsrQKI79WY9sY9ARPKlzFOFdb41ioD8b5Bp+mqeeRKAxINkESBFGpOpKhgv9OuYpH8A8l4Qa3qp60Kl2/k+rG2sWafuuyCBafb2j4JkgZUob3nWcmicpkxEgmTLLGejTxnWSWCi8lPmsk6DlIHFJv24ojiYyYoGacwL8zXTLEAVaDI/Ybb3NIgKDSv2oXpmHkvNs+PTpMASEdlk7fOZeRk37fwJ6yGnQarQsGIfqqcvx43rTOXY6jf7uKXdRzdLDRPbjIrx1cIj3Kr4KyBFezzgUGuR5893qkOQ19fR2uVBaU+r16LphJNOiatK7PeBZK/Kb+tUn71rcQjSvARpghfH/yG/D2RetTuI3N5QrMWdP46brP7FmKZ//CGQ9At9SL01DLkzY/Vs8Z97fQZ7gelw7jHqCz+/Wile5J4g3Vc79eb5a6oLSue+Ve83gaSv2jp5PxCzjzwFUm9zw9MllSMil1kS4d2E9SaQ1xNo9wMxx0+nQNLnew/WDHvveMAHYm08mofl3TFI/8pD3Q6kMAv6DIi2jTCwRJUvNdDYrrJum9oHhusCbWALonwxBRk1vXMnEGWuT5wAmfYuVGUYpJ7fUZujCN92hvzwWlrFgxSfANKb10DxIMbShnfrynyZZV30imA7P43ArXXHbvBVkTCIuGy25AdBrHmNeBCpL214QdLp9LZarG3IMWrmW0ehtuO7F2PS09UcgqS3B7FKPhpknrStD0HGF/vQRne37LwLG8EbHT4WxN7/Fg0yD9Yr/3br4nnstA+0Il6QxzdBmg8A6a2/IRbkcK9h/uzV8zywF/oSkOyageCPglRWgcWClHnEzs9q/t/SENVXgFijlsq3VtXdCsRp4qObrLLLgjuzSq3fX89ZZW6AfxNIzF6X9FYgThN/fk093KkvHX/hbWd+DqS/FUhlf+G3gohEXzVs3g9iDluWoaW8fL73QhB34u+tIHIf19nLuF4Q98a09Eynnl56q+ePgEhnX+dbQOp6H5XnJ0ACd8dFgkwf12nTOTcEqd2pom+CFF02TIPw6dKmrLS5qOtBpo8b5quUtrwrSGbuqPkeSJqllTFHO02NPxdMrm+y5LKdWyWXjw4vA5nGEtnjuyCFyHqNYvEolzmASm3zK1Eg5zr13lhqV1tlksnVw8Pkwgri7O07AVKLJkutRYw87bPlRpBpNXE8xGb+fhBlvEGrGPLqViu5sILIx9dAmqF1705sxF4M8+R8P5dOdQwi12fMnATpjJ2JSt/POIvU9wPJEs/jduJAjLvU0yFT0i64Yb1bsVi79dA4pEy3TzoHMq2O7Re4vXm5O9+l290NpE4CU+YRIMNye2iaqbVS2AUnn2fsekthYKReVNutVedA5juttyIXrT38mOds+ps9DWhwL7GWc61/DVKPzVN9UHDarf1icU98IOU8tm6L031Iq63t1tKzj3fe/FCpO4F0/i0Z2+yvA1KeGBjqj1qYx8/zoxpKZ1Yl367I1k+sfcft/QPy9csXy/32qX1qLZsrryG5BGQaRj0vc/b7N54XXq293TCLB5HO42Fy517obW19b+qjl3CHp0fdLJcWvmdy1etESi/uAdJrs1hTaUklHuW8qSDdC3UfXVR5cnD3rAFSSqtFb7z7eapErx7rC739jCXfbK3aWiipjXo8UbmxXPa7QQq9R289j2Gr88N7Ag5AlHPRKc37pNZv0CZtX1tVMG6rm8qW1/KlCgQvcMss933ybwXZz3dReW5yce4ByZtHFIhwT9kmjxg8BzbKDUe1PB9edBJqSN7/KM1LmqyuMZ5BpeTUw1aD/uDI0relPfSHa/Wn8Pxq1BNfxy/h3IdwOJqIKumb9CHvTqMefyY82RoQAgggBBBACCCAEEAAIYAQQAAhgABCAAGEAAIIAYQAAggBBBACCCAEEEAIIAQQQAgggBBAACGAAEIAIYAAQgABhAACCAEEEAIIAQQQAgggBBBACCCAEEAIIIAQQAAhgABCAAGEAEIAAYQAAggBBBACCCAEEAIIIAQQQAgggBBAACGAEEAAIYAAQgABhAACCAEEEAIIAQQQAgggBBBACCCAEEAIIIAQQAAhgABCAAGEAEIAAYQAAggBBBACCCAEEAIIIAQQQAgggBBAACGAEEAAIYAAQgABhAACCAGEAAIIAQQQAgggBBBACCAEEEAIIIAQQAAhgABCACGAAEIAAYQAAggBBBACCAEEEAIIIAQQQAggfyL/BBgA8PgLdH0TBtkAAAAASUVORK5CYII='
},
// rpx
// ()
threshold: {
type: [Number, String],
default: 100
},
//
duration: {
type: [Number, String],
default: 500
},
// 线
// linear|ease|ease-in|ease-out|ease-in-out|cubic-bezier(n,n,n,n);
effect: {
type: String,
default: 'ease-in-out'
},
// 使
isEffect: {
type: Boolean,
default: true
},
//
borderRadius: {
type: [Number, String],
default: 0
},
// rpx
height: {
type: [Number, String],
default: '450'
}
},
data() {
return {
isShow: false,
opacity: 1,
time: this.duration,
loadStatus: '', //
isError: false, //
elIndex: this.$u.guid()
}
},
computed: {
// thresholdrpxpx
getThreshold() {
// thresholdthis.threshold
let thresholdPx = uni.upx2px(Math.abs(this.threshold));
return this.threshold < 0 ? -thresholdPx : thresholdPx;
},
// auto%
imgHeight() {
return this.height == 'auto' ? 'auto' : String(this.height).indexOf('%') != -1 ? this.height : this.height + 'rpx';
}
},
created() {
// data
this.observer = {};
},
watch: {
isShow(nVal) {
//
if (!this.isEffect) return;
this.time = 0;
// opacity1()0( )1
this.opacity = 0;
// 30msH5
setTimeout(() => {
this.time = this.duration;
this.opacity = 1;
}, 30)
}
},
methods: {
// ,loadlazy-loading-loaded-
clickImg() {
let whichImg = '';
// isShowfalse
if (this.isShow == false) whichImg = 'lazyImg';
// isErrortrue
// ~
else if (this.isError == true) whichImg = 'errorImg';
//
else whichImg = 'realImg';
// index
this.$emit('click', this.index);
},
// isShow
imgLoaded() {
//
if (this.loadStatus == '') {
this.loadStatus = 'lazyed';
}
//
else if (this.loadStatus == 'lazyed') {
this.loadStatus = 'loaded';
this.$emit('load', this.index);
}
},
//
errorImgLoaded() {
this.$emit('error', this.index);
},
//
loadError() {
this.isError = true;
},
disconnectObserver(observerName) {
const observer = this[observerName];
observer && observer.disconnect();
},
},
beforeDestroy() {
//
//observer.disconnect();
},
mounted() {
// uOnReachBottommixin.js
this.$nextTick(() => {
uni.$once('uOnReachBottom', () => {
if (!this.isShow) this.isShow = true;
});
})
// mounted30ms
setTimeout(() => {
// uni.createIntersectionObserverthis.createIntersectionObserver
this.disconnectObserver('contentObserver');
const contentObserver = uni.createIntersectionObserver(this);
//
// https://blog.csdn.net/qq_25324335/article/details/83687695
contentObserver.relativeToViewport({
bottom: this.getThreshold,
}).observe('.u-lazy-item-' + this.elIndex, (res) => {
if (res.intersectionRatio > 0) {
//
this.isShow = true;
//
this.disconnectObserver('contentObserver');
}
})
this.contentObserver = contentObserver;
}, 30)
}
}
</script>
<style scoped lang="scss">
.u-wrap {
background-color: #eee;
overflow: hidden;
}
.u-lazy-item {
width: 100%;
//
transform: transition3d(0, 0, 0);
//
will-change: transform;
display: block;
}
</style>

View File

@ -0,0 +1,136 @@
<template>
<view class="u-progress" :style="{
borderRadius: round ? '100rpx' : 0,
height: height + 'rpx',
backgroundColor: inactiveColor
}">
<view :class="{'u-striped': striped, 'u-striped-active': striped && stripedActive}" class="u-active" :style="[progressStyle]">{{showPercent ? percent + '%' : ''}}</view>
</view>
</template>
<script>
/**
* lineProgress 线型进度条
* @description 展示操作或任务的当前进度比如上传文件是一个线形的进度条
* @tutorial https://www.uviewui.com/components/lineProgress.html
* @property {String Number} percent 进度条百分比值为数值类型0-100
* @property {Boolean} round 进度条两端是否为半圆默认true
* @property {String} type 如设置active-color值将会失效
* @property {String} active-color 进度条激活部分的颜色默认#19be6b
* @property {String} inactive-color 进度条的底色默认#ececec
* @property {Boolean} show-percent 是否在进度条内部显示当前的百分比值数值默认true
* @property {String Number} height 进度条的高度单位rpx默认28
* @property {Boolean} striped 是否显示进度条激活部分的条纹默认false
* @property {Boolean} striped-active 条纹是否具有动态效果默认false
* @example <u-line-progress :percent="70" :show-percent="true"></u-line-progress>
*/
export default {
name: "u-line-progress",
props: {
//
round: {
type: Boolean,
default: true
},
//
type: {
type: String,
default: ''
},
//
activeColor: {
type: String,
default: '#19be6b'
},
inactiveColor: {
type: String,
default: '#ececec'
},
//
percent: {
type: Number,
default: 0
},
//
showPercent: {
type: Boolean,
default: true
},
// rpx
height: {
type: [Number, String],
default: 28
},
//
striped: {
type: Boolean,
default: false
},
//
stripedActive: {
type: Boolean,
default: false
}
},
data() {
return {
}
},
computed: {
progressStyle() {
let style = {};
style.width = this.percent + '%';
if (['success', 'error', 'info', 'primary', 'warning'].indexOf(this.type) >= 0) style.backgroundColor = this.$u.color[
this.type];
else style.backgroundColor = this.activeColor;
return style;
}
},
methods: {
}
}
</script>
<style lang="scss" scoped>
.u-progress {
overflow: hidden;
height: 15px;
display: inline-flex;
align-items: center;
width: 100%;
border-radius: 100rpx;
}
.u-active {
width: 0;
height: 100%;
align-items: center;
display: flex;
justify-items: flex-end;
justify-content: space-around;
font-size: 20rpx;
color: #ffffff;
transition: all 0.4s ease;
}
.u-striped {
background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
background-size: 39px 39px;
}
.u-striped-active {
animation: progress-stripes 2s linear infinite;
}
@keyframes progress-stripes {
0% {
background-position: 0 0;
}
100% {
background-position: 39px 0;
}
}
</style>

73
node_modules/uview-ui/components/u-line/u-line.vue generated vendored Normal file
View File

@ -0,0 +1,73 @@
<template>
<view class="u-line" :style="[lineStyle]">
</view>
</template>
<script>
/**
* line 线条
* @description 此组件一般用于显示一根线条用于分隔内容块有横向和竖向两种模式且能设置0.5px线条使用也很简单
* @tutorial https://www.uviewui.com/components/line.html
* @property {String} color 线条的颜色(默认#e4e7ed)
* @property {String} length 长度竖向时表现为高度横向时表现为长度可以为百分比带rpx单位的值等
* @property {String} direction 线条的方向row-横向col-竖向(默认row)
* @property {Boolean} hair-line 是否显示细线条(默认true)
* @property {String} margin 线条与上下左右元素的间距字符串形式"30rpx"
* @example <u-line color="red"></u-line>
*/
export default {
name: 'u-line',
props: {
color: {
type: String,
default: '#e4e7ed'
},
// rpx
length: {
type: String,
default: '100%'
},
// 线col-row-
direction: {
type: String,
default: 'row'
},
//
hairLine: {
type: Boolean,
default: true
},
// 线"30rpx""20rpx 30rpx"
margin: {
type: String,
default: '0'
}
},
computed: {
lineStyle() {
let style = {};
style.backgroundColor = this.color;
style.margin = this.margin;
// 线1pxtransform0.5px
if(this.direction == 'row') {
style.height = '1px';
style.width = this.length;
if(this.hairLine) style.transform = 'scaleY(0.5)';
} else {
// 线1pxtransform0.5px
style.width = '1px';
style.height = this.length;
if(this.hairLine) style.transform = 'scaleX(0.5)';
}
return style;
}
}
}
</script>
<style scoped lang="scss">
.u-line {
vertical-align: middle;
}
</style>

87
node_modules/uview-ui/components/u-link/u-link.vue generated vendored Normal file
View File

@ -0,0 +1,87 @@
<template>
<text class="u-link" @tap.stop="openLink" :style="{
color: color,
fontSize: fontSize + 'rpx',
borderBottom: underLine ? `1px solid ${lineColor ? lineColor : color}` : 'none',
paddingBottom: underLine ? '0rpx' : '0'
}">
<slot></slot>
</text>
</template>
<script>
/**
* link 超链接
* @description 该组件为超链接组件在不同平台有不同表现形式在APP平台会通过plus环境打开内置浏览器在小程序中把链接复制到粘贴板同时提示信息在H5中通过window.open打开链接
* @tutorial https://www.uviewui.com/components/link.html
* @property {String} color 文字颜色默认#606266
* @property {String Number} font-size 字体大小单位rpx默认28
* @property {Boolean} under-line 是否显示下划线默认false
* @property {String} href 跳转的链接要带上http(s)
* @property {String} line-color 下划线颜色默认同color参数颜色
* @property {String} mp-tips 各个小程序平台把链接复制到粘贴板后的提示语默认链接已复制请在浏览器打开
* @example <u-link href="http://www.uviewui.com">蜀道难难于上青天</u-link>
*/
export default {
name: "u-link",
props: {
//
color: {
type: String,
default: '#2979ff'
},
// rpx
fontSize: {
type: [String, Number],
default: 28
},
// 线
underLine: {
type: Boolean,
default: false
},
//
href: {
type: String,
default: ''
},
//
mpTips: {
type: String,
default: '链接已复制,请在浏览器打开'
},
// 线
lineColor: {
type: String,
default: ''
}
},
methods: {
openLink() {
// #ifdef APP-PLUS
plus.runtime.openURL(this.href)
// #endif
// #ifdef H5
window.open(this.href)
// #endif
// #ifdef MP
uni.setClipboardData({
data: this.href,
success() {
uni.hideToast();
}
});
this.$nextTick(() => {
this.$u.toast(this.mpTips);
})
// #endif
}
}
}
</script>
<style lang="scss" scoped>
.u-link {
line-height: 1;
}
</style>

View File

@ -0,0 +1,99 @@
<template>
<view v-if="show" class="u-loading" :class="mode == 'circle' ? 'u-loading-circle' : 'u-loading-flower'" :style="[cricleStyle]">
</view>
</template>
<script>
/**
* loading 加载动画
* @description 警此组件为一个小动画目前用在uView的loadmore加载更多和switch开关等组件的正在加载状态场景
* @tutorial https://www.uviewui.com/components/loading.html
* @property {String} mode 模式选择见官网说明默认circle
* @property {String} color 动画活动区域的颜色只对 mode = flower 模式有效默认#c7c7c7
* @property {String Number} size 加载图标的大小单位rpx默认34
* @property {Boolean} show 是否显示动画默认true
* @example <u-loading mode="circle"></u-loading>
*/
export default {
name: "u-loading",
props: {
//
mode: {
type: String,
default: 'circle'
},
//
color: {
type: String,
default: '#c7c7c7'
},
// rpx
size: {
type: [String, Number],
default: '34'
},
//
show: {
type: Boolean,
default: true
}
},
computed: {
//
cricleStyle() {
let style = {};
style.width = this.size + 'rpx';
style.height = this.size + 'rpx';
if (this.mode == 'circle') style.borderColor = `#e4e4e4 #e4e4e4 #e4e4e4 ${this.color ? this.color : '#c7c7c7'}`;
return style;
},
}
}
</script>
<style lang="scss" scoped>
.u-loading-circle {
display: inline-block;
vertical-align: middle;
width: 28rpx;
height: 28rpx;
background: 0 0;
border-radius: 50%;
border: 2px solid;
border-color: #e5e5e5 #e5e5e5 #e5e5e5 #8f8d8e;
animation: u-circle 1s linear infinite;
}
.u-loading-flower {
width: 20px;
height: 20px;
display: inline-block;
vertical-align: middle;
-webkit-animation: a 1s steps(12) infinite;
animation: u-flower 1s steps(12) infinite;
background: transparent url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMjAiIGhlaWdodD0iMTIwIiB2aWV3Qm94PSIwIDAgMTAwIDEwMCI+PHBhdGggZmlsbD0ibm9uZSIgZD0iTTAgMGgxMDB2MTAwSDB6Ii8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjRTlFOUU5IiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAgLTMwKSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iIzk4OTY5NyIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSgzMCAxMDUuOTggNjUpIi8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjOUI5OTlBIiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0icm90YXRlKDYwIDc1Ljk4IDY1KSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iI0EzQTFBMiIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSg5MCA2NSA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNBQkE5QUEiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoMTIwIDU4LjY2IDY1KSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iI0IyQjJCMiIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSgxNTAgNTQuMDIgNjUpIi8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjQkFCOEI5IiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0icm90YXRlKDE4MCA1MCA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNDMkMwQzEiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoLTE1MCA0NS45OCA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNDQkNCQ0IiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoLTEyMCA0MS4zNCA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNEMkQyRDIiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoLTkwIDM1IDY1KSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iI0RBREFEQSIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSgtNjAgMjQuMDIgNjUpIi8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjRTJFMkUyIiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0icm90YXRlKC0zMCAtNS45OCA2NSkiLz48L3N2Zz4=) no-repeat;
background-size: 100%;
}
@keyframes u-flower {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
to {
-webkit-transform: rotate(1turn);
transform: rotate(1turn);
}
}
@-webkit-keyframes u-circle {
0% {
transform: rotate(0);
}
100% {
transform: rotate(360deg);
}
}
</style>

View File

@ -0,0 +1,190 @@
<template>
<view class="u-load-more-wrap" :style="{
backgroundColor: bgColor,
marginBottom: marginBottom + 'rpx',
marginTop: marginTop + 'rpx'
}">
<!-- 加载中和没有更多的状态才显示两边的横线 -->
<view :class="status == 'loadmore' || status == 'nomore' ? 'u-more' : ''" class="u-load-more-inner">
<u-loading class="u-loadmore-icon" :color="iconColor" :mode="iconType == 'circle' ? 'circle' : 'flower'" :show="status == 'loading' && icon"></u-loading>
<!-- 如果没有更多的状态下显示内容为dot粗点加载特定样式 -->
<view :style="[loadTextStyle]" :class="[(status == 'nomore' && isDot == true) ? 'u-dot-text' : 'u-more-text']" @tap="loadMore">
{{ showText }}
</view>
</view>
</view>
</template>
<script>
/**
* loadmore 加载更多
* @description 此组件一般用于标识页面底部加载数据时的状态
* @tutorial https://www.uviewui.com/components/loadMore.html
* @property {String} status 组件状态默认loadmore
* @property {String} bg-color 组件背景颜色在页面是非白色时会用到默认#ffffff
* @property {Boolean} icon 加载中时是否显示图标默认true
* @property {String} icon-type 加载中时的图标类型默认circle
* @property {String} icon-color icon-type为circle时有效加载中的动画图标的颜色默认#b7b7b7
* @property {Boolean} is-dot status为nomore时内容显示为一个"●"默认false
* @property {String} color 字体颜色默认#606266
* @property {String Number} font-size 字体大小单位rpx默认28
* @property {Object} load-text 自定义显示的文字见上方说明示例
* @event {Function} loadmore status为loadmore时点击组件会发出此事件
* @example <u-loadmore :status="status" icon-type="iconType" load-text="loadText" />
*/
export default {
name: "u-loadmore",
props: {
//
bgColor: {
type: String,
default: '#fff'
},
//
icon: {
type: Boolean,
default: true
},
//
fontSize: {
type: String,
default: '28'
},
//
color: {
type: String,
default: '#606266'
},
// loadmore-loading-nomore-
status: {
type: String,
default: 'loadmore'
},
// flower-circle-
iconType: {
type: String,
default: 'circle'
},
//
loadText: {
type: Object,
default () {
return {
loadmore: '加载更多',
loading: '正在加载...',
nomore: '没有更多了'
}
}
},
//
isDot: {
type: Boolean,
default: false
},
//
iconColor: {
type: String,
default: '#b7b7b7'
},
//
marginTop: {
type: [String, Number],
default: 0
},
//
marginBottom: {
type: [String, Number],
default: 0
},
},
data() {
return {
//
dotText: "●"
}
},
computed: {
//
loadTextStyle() {
return {
color: this.color,
fontSize: this.fontSize + 'rpx',
position: 'relative',
zIndex: 1,
backgroundColor: this.bgColor,
//
padding: this.status == 'loading' ? '0 8px' : '0 12px',
}
},
//
cricleStyle() {
return {
borderColor: `#e5e5e5 #e5e5e5 #e5e5e5 ${this.circleColor}`
}
},
//
// base64
flowerStyle() {
return {
}
},
//
showText() {
let text = '';
if(this.status == 'loadmore') text = this.loadText.loadmore;
else if(this.status == 'loading') text = this.loadText.loading;
else if(this.status == 'nomore' && this.isDot) text = this.dotText;
else text = this.loadText.nomore;
return text;
}
},
methods: {
loadMore() {
//
if(this.status == 'loadmore') this.$emit('loadmore');
}
}
}
</script>
<style scoped lang="scss">
.u-load-more-wrap {
width: 100%;
display: flex;
justify-content: center;
}
.u-load-more-inner {
display: flex;
justify-content: center;
align-items: center;
}
.u-more {
width: 60%;
position: relative;
display: flex;
justify-content: center;
}
.u-more::before {
content: ' ';
position: absolute;
border-bottom: 1px solid #d4d4d4;
-webkit-transform: scaleY(0.5);
transform: scaleY(0.5);
width: 100%;
top: 50%;
left: 0;
}
.u-dot-text {
font-size: 28rpx;
}
.u-loadmore-icon {
display: flex;
align-items: center;
justify-content: center;
}
</style>

98
node_modules/uview-ui/components/u-mask/u-mask.vue generated vendored Normal file
View File

@ -0,0 +1,98 @@
<template>
<view class="u-mask" :style="[maskStyle]" :class="[show ? 'u-mask-show' : '']" @tap="click" @touchmove.stop.prevent>
<slot />
</view>
</template>
<script>
/**
* mask 遮罩
* @description 创建一个遮罩层用于强调特定的页面元素并阻止用户对遮罩下层的内容进行操作一般用于弹窗场景
* @tutorial https://www.uviewui.com/components/mask.html
* @property {Boolean} show 是否显示遮罩默认false
* @property {String Number} z-index z-index 层级默认1070
* @property {Object} custom-style 自定义样式对象见上方说明
* @property {String Number} duration 动画时长单位毫秒默认300
* @property {Boolean} zoom 是否使用scale对这招进行缩放默认true
* @property {Boolean} mask-click-able 遮罩是否可点击为false时点击不会发送click事件默认true
* @event {Function} click mask-click-able为true时点击遮罩发送此事件
* @example <u-mask :show="show" @click="show = false"></u-mask>
*/
export default {
name: "u-mask",
props: {
//
show: {
type: Boolean,
default: false
},
// z-index
zIndex: {
type: [Number, String],
default: ''
},
//
customStyle: {
type: Object,
default () {
return {}
}
},
// 使使zoomscale
zoom: {
type: Boolean,
default: true
},
// ms
duration: {
type: [Number, String],
default: 300
},
//
maskClickAble: {
type: Boolean,
default: true
}
},
computed: {
maskStyle() {
let style = {};
style.backgroundColor = "rgba(0, 0, 0, 0.6)";
if(this.show) style.zIndex = this.zIndex ? this.zIndex : this.$u.zIndex.mask;
else style.zIndex = -1;
style.transition = `all ${this.duration / 1000}s ease-in-out`;
//
if (this.zoom == true) style.transform = 'scale(1.2, 1.2)';
//
if (Object.keys(this.customStyle).length) style = { ...style,
...this.customStyle
};
//
//Object.assign(style, customStyle);
return style;
}
},
methods: {
click() {
if (!this.maskClickAble) return;
this.$emit('click');
}
}
}
</script>
<style lang="scss" scoped>
.u-mask {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
opacity: 0;
}
.u-mask-show {
opacity: 1;
transform: scale(1);
}
</style>

View File

@ -0,0 +1,302 @@
<template>
<view class="u-char-box">
<view class="u-char-flex">
<input :disabled="disabledKeyboard" :value="valueModel" type="number" :focus="focus" :maxlength="maxlength" class="u-input" @input="getVal"/>
<view v-for="(item, index) in maxlength" :key="index">
<view :class="[breathe && charArrLength == index ? 'u-breathe' : '', 'u-char-item',
charArrLength === index && mode == 'box' ? 'u-box-active' : '',
mode === 'box' ? 'u-box' : '']" :style="{
fontWeight: bold ? 'bold' : 'normal',
fontSize: fontSize + 'rpx',
width: width + 'rpx',
height: width + 'rpx',
color: inactiveColor
}">
<view class="u-placeholder-line" :style="{
display: charArrLength === index ? 'block' : 'none',
height: width * 0.5 +'rpx'
}"
v-if="mode !== 'middleLine'"
></view>
<view v-if="mode === 'middleLine' && charArrLength <= index" :class="[breathe && charArrLength == index ? 'u-breathe' : '', charArrLength === index ? 'u-middle-line-active' : '']"
class="u-middle-line" :style="{height: bold ? '4px' : '2px', background: charArrLength === index ? activeColor : inactiveColor}"></view>
<view v-if="mode === 'bottomLine'" :class="[breathe && charArrLength == index ? 'u-breathe' : '', charArrLength === index ? 'u-buttom-line-active' : '']"
class="u-bottom-line" :style="{height: bold ? '4px' : '2px', background: charArrLength === index ? activeColor : inactiveColor}"></view>
<block v-if="!dotFill"> {{ charArr[index] ? charArr[index] : ''}}</block>
<block v-else>
<text class="u-dot">{{ charArr[index] ? '●' : ''}}</text>
</block>
</view>
</view>
</view>
</view>
</template>
<script>
/**
* messageInput 验证码输入框
* @description 该组件一般用于验证用户短信验证码的场景也可以结合uView的键盘组件使用
* @tutorial https://www.uviewui.com/components/messageInput.html
* @property {String Number} maxlength 输入字符个数默认4
* @property {Boolean} dot-fill 是否用圆点填充默认false
* @property {String} mode 模式选择见上方"基本使用"说明默认box
* @property {String Number} value 预置值
* @property {Boolean} breathe 是否开启呼吸效果见上方说明默认true
* @property {Boolean} focus 是否自动获取焦点默认false
* @property {Boolean} bold 字体和输入横线是否加粗默认true
* @property {String Number} font-size 字体大小单位rpx默认60
* @property {String} active-color 当前激活输入框的样式默认#2979ff
* @property {String} focus 非激活输入框的样式文字颜色同此值默认#606266
* @property {String | Number} width 输入框宽度单位rpx高等于宽默认80
* @property {Boolean} disabled-keyboard 禁止点击输入框唤起系统键盘默认false
* @event {Function} change 输入内容发生改变时触发具体见官网说明
* @event {Function} finish 输入字符个数达maxlength值时触发见官网说明
* @example <u-message-input mode="bottomLine"></u-message-input>
*/
export default {
name: "u-message-input",
props: {
//
maxlength: {
type: [Number, String],
default: 4
},
//
dotFill: {
type: Boolean,
default: false
},
// box-bottomLine-线middleLine-线
mode: {
type: String,
default: "box"
},
//
value: {
type: [String, Number],
default: ''
},
// item
breathe: {
type: Boolean,
default: true
},
//
focus: {
type: Boolean,
default: false
},
//
bold: {
type: Boolean,
default: false
},
//
fontSize: {
type: [String, Number],
default: 60
},
//
activeColor: {
type: String,
default: '#2979ff'
},
//
inactiveColor: {
type: String,
default: '#606266'
},
// rpx
width: {
type: [Number, String],
default: '80'
},
// true
disabledKeyboard: {
type: Boolean,
default: false
}
},
watch: {
maxlength: {
// truemaxlengthcreated
immediate: true,
handler(val) {
this.maxlength = Number(val);
}
},
value: {
immediate: true,
handler(val) {
//
val = String(val);
//
this.valueModel = val.substring(0, this.maxlength);
}
},
},
data() {
return {
valueModel: ""
}
},
computed: {
//
animationClass() {
return (index) => {
if (this.breathe && this.charArr.length == index) return 'u-breathe';
else return '';
}
},
//
charArr() {
return this.valueModel.split('');
},
charArrLength() {
return this.charArr.length;
}
},
methods: {
getVal(e) {
let {
value
} = e.detail
this.valueModel = value;
// maxlengthinputmaxlength
if (String(value).length > this.maxlength) return;
// maxlengthchangefinish
this.$emit('change', value);
if (String(value).length == this.maxlength) {
this.$emit('finish', value);
}
}
}
}
</script>
<style scoped lang="scss">
@keyframes breathe {
0% {
opacity: 0.3;
}
50% {
opacity: 1;
}
100% {
opacity: 0.3;
}
}
.u-char-box {
text-align: center;
}
.u-char-flex {
display: flex;
justify-content: center;
flex-wrap: wrap;
position: relative;
}
.u-input {
position: absolute;
top: 0;
left: -100%;
width: 200%;
height: 100%;
text-align: left;
z-index: 9;
opacity: 0;
background: none;
}
.u-char-item {
position: relative;
width: 90rpx;
height: 90rpx;
margin: 10rpx 10rpx;
font-size: 60rpx;
font-weight: bold;
color: $u-main-color;
line-height: 90rpx;
display: flex;
justify-content: center;
align-items: center;
}
.u-middle-line {
border: none;
}
.u-box {
box-sizing: border-box;
border: 2rpx solid #cccccc;
border-radius: 6rpx;
}
.u-box-active {
overflow: hidden;
animation-timing-function: ease-in-out;
animation-duration: 1500ms;
animation-iteration-count: infinite;
animation-direction: alternate;
border: 2rpx solid $u-type-primary;
}
.u-middle-line-active {
background: $u-type-primary;
}
.u-breathe {
animation: breathe 2s infinite ease;
}
.u-placeholder-line {
display: none;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 2rpx;
height: 40rpx;
background: #333333;
animation: twinkling 1.5s infinite ease;
}
.u-animation-breathe {
animation-name: breathe;
}
.u-dot {
font-size: 34rpx;
line-height: 34rpx;
}
.u-middle-line {
height: 4px;
background: #000000;
width: 80%;
position: absolute;
border-radius: 2px;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.u-buttom-line-active {
background: $u-type-primary;
}
.u-bottom-line {
height: 4px;
background: #000000;
width: 80%;
position: absolute;
border-radius: 2px;
bottom: 0;
left: 50%;
transform: translate(-50%);
}
</style>

301
node_modules/uview-ui/components/u-modal/u-modal.vue generated vendored Normal file
View File

@ -0,0 +1,301 @@
<template>
<view>
<u-popup :zoom="zoom"
mode="center" :popup="false"
:z-index="uZIndex" v-model="value"
:length="width" :mask-close-able="maskCloseAble"
:border-radius="borderRadius"
@close="popupClose"
>
<view class="u-model">
<view v-if="showTitle" class="u-model-title u-line-1" :style="[titleStyle]">{{ title }}</view>
<view class="u-model-content">
<view :style="[contentStyle]" v-if="$slots.default">
<slot />
</view>
<view v-else class="u-model-content-message" :style="[contentStyle]">{{ content }}</view>
</view>
<view class="u-model-footer u-border-top">
<view
v-if="showCancelButton"
:hover-stay-time="100"
hover-class="btn-hover"
class="u-model-footer-button"
type="default"
:style="[cancelBtnStyle]"
@tap="cancel"
>
{{cancelText}}
</view>
<view
v-if="showConfirmButton"
:hover-stay-time="100"
:hover-class="asyncClose ? 'none' : 'btn-hover'"
class="u-model-footer-button hairline-left"
:style="[confirmBtnStyle]"
@tap="confirm"
>
<u-loading mode="circle" :color="confirmColor" v-if="loading"></u-loading>
<block v-else>
{{confirmText}}
</block>
</view>
</view>
</view>
</u-popup>
</view>
</template>
<script>
/**
* modal 模态框
* @description 弹出模态框常用于消息提示消息确认在当前页面内完成特定的交互操作
* @tutorial https://www.uviewui.com/components/modal.html
* @property {Boolean} value 是否显示模态框
* @property {String | Number} z-index 层级
* @property {String} title 模态框标题默认"提示"
* @property {String | Number} width 模态框宽度默认600
* @property {String} content 模态框内容默认"内容"
* @property {Boolean} show-title 是否显示标题默认true
* @property {Boolean} async-close 是否异步关闭只对确定按钮有效默认false
* @property {Boolean} show-confirm-button 是否显示确认按钮默认true
* @property {Boolean} show-cancel-button 是否显示取消按钮默认false
* @property {Boolean} mask-close-able 是否允许点击遮罩关闭modal默认false
* @property {String} confirm-text 确认按钮的文字内容默认"确认"
* @property {String} cancel-text 取消按钮的文字内容默认"取消"
* @property {String} cancel-color 取消按钮的颜色默认"#606266"
* @property {String} confirm-color 确认按钮的文字内容默认"#2979ff"
* @property {String | Number} border-radius 模态框圆角值单位rpx默认16
* @property {Object} title-style 自定义标题样式对象形式
* @property {Object} content-style 自定义内容样式对象形式
* @property {Object} cancel-style 自定义取消按钮样式对象形式
* @property {Object} confirm-style 自定义确认按钮样式对象形式
* @property {Boolean} zoom 是否开启缩放模式默认true
* @event {Function} confirm 确认按钮被点击
* @event {Function} cancel 取消按钮被点击
* @example <u-modal :src="title" :content="content"></u-modal>
*/
export default {
name: 'u-modal',
props: {
// Modal
value: {
type: Boolean,
default: false
},
// z-index
zIndex: {
type: [Number, String],
default: ''
},
//
title: {
type: [String],
default: '提示'
},
// (rpx)auto
width: {
type: [Number, String],
default: 600
},
//
content: {
type: String,
default: '内容'
},
//
showTitle: {
type: Boolean,
default: true
},
//
showConfirmButton: {
type: Boolean,
default: true
},
//
showCancelButton: {
type: Boolean,
default: false
},
//
confirmText: {
type: String,
default: '确认'
},
//
cancelText: {
type: String,
default: '取消'
},
//
confirmColor: {
type: String,
default: '#2979ff'
},
//
cancelColor: {
type: String,
default: '#606266'
},
//
borderRadius: {
type: [Number, String],
default: 16
},
//
titleStyle: {
type: Object,
default() {
return {}
}
},
//
contentStyle: {
type: Object,
default() {
return {}
}
},
//
cancelStyle: {
type: Object,
default() {
return {}
}
},
//
confirmStyle: {
type: Object,
default() {
return {}
}
},
//
zoom: {
type: Boolean,
default: true
},
//
asyncClose: {
type: Boolean,
default: false
},
// modal
maskCloseAble: {
type: Boolean,
default: false
}
},
data() {
return {
loading: false, //
}
},
computed: {
cancelBtnStyle() {
return Object.assign({color: this.cancelColor}, this.cancelStyle);
},
confirmBtnStyle() {
return Object.assign({color: this.confirmColor}, this.confirmStyle);
},
uZIndex() {
return this.zIndex ? this.zIndex : this.$u.zIndex.popup;
}
},
watch: {
// v-modelfalseloading
//
value(n) {
if(n === true) this.loading = false;
}
},
methods: {
confirm() {
this.$emit('confirm');
//
if(this.asyncClose) {
this.loading = true;
} else {
this.$emit('input', false);
}
},
cancel() {
this.$emit('cancel');
this.$emit('input', false);
// popup
// ""modal
setTimeout(() => {
this.loading = false;
}, 300);
},
// modalv-modelfalsemodal
popupClose() {
this.$emit('input', false);
},
//
clearLoading() {
this.loading = false;
}
}
};
</script>
<style lang="scss" scoped>
.u-mask {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
opacity: 0;
visibility: hidden;
}
.btn-hover {
background-color: rgb(230, 230, 230);
}
.u-mask-show {
opacity: 1;
visibility: visible;
}
.u-model {
height: auto;
overflow: hidden;
font-size: 32rpx;
background-color: #fff;
&-title {
padding-top: 48rpx;
font-weight: 500;
text-align: center;
color: $u-main-color;
}
&-content {
&-message {
padding: 48rpx;
font-size: 30rpx;
text-align: center;
color: $u-content-color;
}
}
&-footer {
display: flex;
&-button {
flex: 1;
height: 100rpx;
line-height: 100rpx;
font-size: 32rpx;
box-sizing: border-box;
cursor: pointer;
text-align: center;
border-radius: 4rpx;
}
}
}
</style>

289
node_modules/uview-ui/components/u-navbar/u-navbar.vue generated vendored Normal file
View File

@ -0,0 +1,289 @@
<template>
<view class="">
<view class="u-navbar" :style="[navbarStyle]" :class="{'u-navbar-fixed': isFixed, 'u-border-bottom': borderBottom}">
<view class="u-status-bar" :style="{ height: statusBarHeight + 'px' }"></view>
<view class="u-navbar-inner" :style="[navbarInnerStyle]">
<view class="u-back-wrap" v-if="isBack" @tap="goBack">
<view class="u-icon-wrap">
<u-icon :name="backIconName" :color="backIconColor" :size="backIconSize"></u-icon>
</view>
<view class="u-icon-wrap u-back-text u-line-1" v-if="backText" :style="[backTextStyle]">
{{backText}}
</view>
</view>
<view class="u-navbar-content-title" v-if="title" :style="[titleStyle]">
<view class="u-title u-line-1" :style="{
color: titleColor,
fontSize: titleSize + 'rpx'
}">
{{title}}
</view>
</view>
<view class="u-slot-content">
<slot></slot>
</view>
<view class="u-slot-right">
<slot name="right"></slot>
</view>
</view>
</view>
<!-- 解决fixed定位后导航栏塌陷的问题 -->
<view class="u-navbar-placeholder" v-if="isFixed" :style="{width: '100%',height: Number(navbarHeight) + statusBarHeight + 'px'}">
</view>
</view>
</template>
<script>
//
let systemInfo = uni.getSystemInfoSync();
let menuButtonInfo = {};
// (API)
// #ifdef MP
menuButtonInfo = uni.getMenuButtonBoundingClientRect();
// #endif
/**
* navbar 自定义导航栏
* @description 此组件一般用于在特殊情况下需要自定义导航栏的时候用到一般建议使用uniapp自带的导航栏
* @tutorial https://www.uviewui.com/components/navbar.html
* @property {String Number} height 导航栏高度(不包括状态栏高度在内内部自动加上)注意这里的单位是px默认44
* @property {String} back-icon-color 左边返回图标的颜色默认#606266
* @property {String} back-icon-name 左边返回图标的名称只能为uView自带的图标默认arrow-left
* @property {String Number} back-icon-size 左边返回图标的大小单位rpx默认30
* @property {String} back-text 返回图标右边的辅助提示文字
* @property {Object} back-text-style 返回图标右边的辅助提示文字的样式对象形式默认{ color: '#606266' }
* @property {String} title 导航栏标题如设置为空字符将会隐藏标题占位区域
* @property {String Number} title-width 导航栏标题的最大宽度内容超出会以省略号隐藏单位rpx默认250
* @property {String} title-color 标题的颜色默认#606266
* @property {String Number} title-size 导航栏标题字体大小单位rpx默认32
* @property {String Number} z-index 固定在顶部时的z-index值默认980
* @property {Boolean} is-back 是否显示导航栏左边返回图标和辅助文字默认true
* @property {Object} background 导航栏背景设置见官网说明默认{ background: '#ffffff' }
* @property {Boolean} is-fixed 导航栏是否固定在顶部默认true
* @property {Boolean} border-bottom 导航栏底部是否显示下边框如定义了较深的背景颜色可取消此值默认true
* @example <u-navbar back-text="返回" title="剑未配妥,出门已是江湖"></u-navbar>
*/
export default {
name: "u-navbar",
props: {
// pxrpx
height: {
type: [String, Number],
default: ''
},
//
backIconColor: {
type: String,
default: '#606266'
},
//
backIconName: {
type: String,
default: 'arrow-left'
},
// rpx
backIconSize: {
type: [String, Number],
default: '30'
},
//
backText: {
type: String,
default: ''
},
//
backTextStyle: {
type: Object,
default() {
return {
color: '#606266'
}
}
},
//
title: {
type: String,
default: ''
},
// rpx
titleWidth: {
type: [String, Number],
default: '250'
},
//
titleColor: {
type: String,
default: '#606266'
},
//
titleSize: {
type: [String, Number],
default: 32
},
isBack: {
type: [Boolean, String],
default: true
},
// 线
background: {
type: Object,
default() {
return {
background: '#ffffff'
}
}
},
//
isFixed: {
type: Boolean,
default: true
},
//
borderBottom: {
type: Boolean,
default: true
},
zIndex: {
type: [String, Number],
default: ''
}
},
data() {
return {
menuButtonInfo: menuButtonInfo,
statusBarHeight: systemInfo.statusBarHeight
};
},
computed: {
//
navbarInnerStyle() {
let style = {};
//
style.height = this.navbarHeight + 'px';
// //
// #ifdef MP
let rightButtonWidth = systemInfo.windowWidth - menuButtonInfo.left;
style.marginRight = rightButtonWidth + 'px';
// #endif
return style;
},
//
navbarStyle() {
let style = {};
style.zIndex = this.zIndex ? this.zIndex : this.$u.zIndex.navbar;
//
Object.assign(style, this.background);
return style;
},
//
titleStyle() {
let style = {};
// #ifndef MP
style.left = (systemInfo.windowWidth - uni.upx2px(this.titleWidth)) / 2 + 'px';
style.right = (systemInfo.windowWidth - uni.upx2px(this.titleWidth)) / 2 + 'px';
// #endif
// #ifdef MP
// 使
let rightButtonWidth = systemInfo.windowWidth - menuButtonInfo.left;
style.left = (systemInfo.windowWidth - uni.upx2px(this.titleWidth)) / 2 + 'px';
style.right = rightButtonWidth - (systemInfo.windowWidth - uni.upx2px(this.titleWidth)) / 2 + rightButtonWidth + 'px';
// #endif
style.width = uni.upx2px(this.titleWidth) + 'px';
return style;
},
//
navbarHeight() {
// #ifdef APP-PLUS || H5
return this.height ? this.height : 44;
// #endif
// #ifdef MP
// = + ()
// (px)
// return menuButtonInfo.height + (menuButtonInfo.top - this.statusBarHeight) * 2;//
let height = systemInfo.platform == 'ios' ? 44 : 48;
return this.height ? this.height : height;
// #endif
}
},
created() {},
methods: {
goBack() {
uni.navigateBack();
}
}
};
</script>
<style scoped lang="scss">
.u-navbar {
width: 100%;
}
.u-navbar-fixed {
position: fixed;
left: 0;
right: 0;
top: 0;
z-index: 991;
}
.u-status-bar {
width: 100%;
}
.u-navbar-inner {
display: flex;
justify-content: space-between;
position: relative;
align-items: center;
}
.u-back-wrap {
display: flex;
align-items: center;
flex: 1;
flex-grow: 0;
padding: 14rpx 14rpx 14rpx 24rpx;
}
.u-back-text {
padding-left: 4rpx;
font-size: 30rpx;
}
.u-navbar-content-title {
display: flex;
align-items: center;
justify-content: center;
flex: 1;
position: absolute;
left: 0;
right: 0;
height: 60rpx;
text-align: center;
flex-shrink: 0;
}
.u-navbar-centent-slot {
flex: 1;
}
.u-title {
line-height: 1;
font-size: 32rpx;
flex: 1;
}
.u-navbar-right {
flex: 1;
display: flex;
align-items: center;
justify-content: flex-end;
}
.u-slot-content {
flex: 1;
display: flex;
align-items: center;
}
</style>

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,270 @@
<template>
<view class="u-notice-bar-wrap" v-if="isShow" :style="{
borderRadius: borderRadius + 'rpx',
}">
<block v-if="mode == 'horizontal' && isCircular">
<u-row-notice
:type="type"
:color="color"
:bgColor="bgColor"
:list="list"
:volumeIcon="volumeIcon"
:moreIcon="moreIcon"
:volumeSize="volumeSize"
:closeIcon="closeIcon"
:mode="mode"
:fontSize="fontSize"
:speed="speed"
:playState="playState"
:padding="padding"
@getMore="getMore"
@close="close"
@click="click"
></u-row-notice>
</block>
<block v-if="mode == 'vertical' || (mode == 'horizontal' && !isCircular)">
<u-column-notice
:type="type"
:color="color"
:bgColor="bgColor"
:list="list"
:volumeIcon="volumeIcon"
:moreIcon="moreIcon"
:closeIcon="closeIcon"
:mode="mode"
:volumeSize="volumeSize"
:disable-touch="disableTouch"
:fontSize="fontSize"
:duration="duration"
:playState="playState"
:padding="padding"
@getMore="getMore"
@close="close"
@click="click"
@end="end"
></u-column-notice>
</block>
</view>
</template>
<script>
/**
* noticeBar 滚动通知
* @description 该组件用于滚动通告场景有多种模式可供选择
* @tutorial https://www.uviewui.com/components/noticeBar.html
* @property {Array} list 滚动内容数组形式见上方说明
* @property {String} type 显示的主题默认warning
* @property {Boolean} volume-icon 是否显示小喇叭图标默认true
* @property {Boolean} more-icon 是否显示右边的向右箭头默认false
* @property {Boolean} close-icon 是否显示关闭图标默认false
* @property {Boolean} autoplay 是否自动播放默认true
* @property {String} color 文字颜色
* @property {String Number} bg-color 背景颜色
* @property {String} mode 滚动模式默认horizontal
* @property {Boolean} show 是否显示默认true
* @property {String Number} font-size 字体大小单位rpx默认28
* @property {String Number} volume-size 左边喇叭的大小默认34
* @property {String Number} duration 滚动周期时长只对步进模式有效横向衔接模式无效单位ms默认2000
* @property {String Number} speed 水平滚动时的滚动速度即每秒移动多少距离只对水平衔接方式有效单位rpx默认160
* @property {String Number} font-size 字体大小单位rpx默认28
* @property {Boolean} is-circular mode为horizontal时指明是否水平衔接滚动默认true
* @property {String} play-state 播放状态play - 播放paused - 暂停默认play
* @property {String Nubmer} border-radius 通知栏圆角默认为0
* @property {String Nubmer} padding 内边距字符串与普通的内边距css写法一直默认"18rpx 24rpx"
* @property {Boolean} no-list-hidden 列表为空时是否显示组件默认false
* @property {Boolean} disable-touch 是否禁止通过手动滑动切换通知只有mode = vertical或者mode = horizontal且is-circular = false时有效默认true
* @event {Function} click 点击通告文字触发只有mode = vertical或者mode = horizontal且is-circular = false时有效
* @event {Function} close 点击右侧关闭图标触发
* @event {Function} getMore 点击右侧向右图标触发
* @event {Function} end 列表的消息每次被播放一个周期时触发只有mode = vertical或者mode = horizontal且is-circular = false时有效
* @example <u-notice-bar :more-icon="true" :list="list"></u-notice-bar>
*/
export default {
name: "u-notice-bar",
props: {
//
list: {
type: Array,
default() {
return [];
}
},
// success|error|primary|info|warning
type: {
type: String,
default: 'warning'
},
//
volumeIcon: {
type: Boolean,
default: true
},
//
volumeSize: {
type: [Number, String],
default: 34
},
//
moreIcon: {
type: Boolean,
default: false
},
//
closeIcon: {
type: Boolean,
default: false
},
//
autoplay: {
type: Boolean,
default: true
},
// 使
color: {
type: String,
default: ''
},
//
bgColor: {
type: String,
default: ''
},
// horizontal-vertical-
mode: {
type: String,
default: 'horizontal'
},
//
show: {
type: Boolean,
default: true
},
// rpx
fontSize: {
type: [Number, String],
default: 28
},
// ms
duration: {
type: [Number, String],
default: 2000
},
// rpx
speed: {
type: [Number, String],
default: 160
},
//
// swiper
isCircular: {
type: Boolean,
default: true
},
// play-paused-
playState: {
type: String,
default: 'play'
},
//
// HX2.6.11App 2.5.5+H5 2.5.5+
disableTouch: {
type: Boolean,
default: true
},
//
borderRadius: {
type: [Number, String],
default: 0
},
//
padding: {
type: [Number, String],
default: '18rpx 24rpx'
},
// list
noListHidden: {
type: Boolean,
default: true
}
},
computed: {
// showfalsenoListHiddentruelist
isShow() {
if(this.show == false || (this.noListHidden == true && this.list.length == 0)) return false;
else return true;
}
},
methods: {
//
click(index) {
this.$emit('click', index);
},
//
close() {
this.$emit('close');
},
//
getMore() {
this.$emit('getMore');
},
//
end() {
this.$emit('end');
}
}
};
</script>
<style lang="scss" scoped>
.u-notice-bar-wrap {
overflow: hidden;
}
.u-notice-bar {
padding: 18rpx 24rpx;
overflow: hidden;
}
.u-direction-row {
display: flex;
align-items: center;
justify-content: space-between;
}
.u-left-icon {
display: flex;
align-items: center;
}
.u-notice-box {
flex: 1;
display: flex;
overflow: hidden;
margin-left: 12rpx;
}
.u-right-icon {
margin-left: 12rpx;
display: flex;
align-items: center;
}
.u-notice-content {
line-height: 1;
white-space: nowrap;
font-size: 26rpx;
animation: u-loop-animation 10s linear infinite both;
text-align: right;
//
padding-left: 100%;
}
@keyframes u-loop-animation {
0% {
transform: translate3d(0, 0, 0);
}
100% {
transform: translate3d(-100%, 0, 0);
}
}
</style>

View File

@ -0,0 +1,286 @@
<template>
<view class="u-numberbox">
<view class="u-icon-minus" @tap.stop="minus" :class="{ 'u-icon-disabled': disabled || inputVal <= min }" :style="{
background: bgColor,
height: inputHeight + 'rpx',
color: color
}">
<u-icon name="minus" :size="size"></u-icon>
</view>
<input :disabled="disabledInput || disabled" :cursor-spacing="getCursorSpacing" :class="{ 'u-input-disabled': disabled }" v-model="inputVal" class="u-number-input" @blur="onBlur"
type="number" :style="{
color: color,
fontSize: size + 'rpx',
background: bgColor,
height: inputHeight + 'rpx',
width: inputWidth + 'rpx'
}" />
<view class="u-icon-plus" @tap.stop="plus" :class="{ 'u-icon-disabled': disabled || inputVal >= max }" :style="{
background: bgColor,
height: inputHeight + 'rpx',
color: color
}">
<u-icon name="plus" :size="size"></u-icon>
</view>
</view>
</template>
<script>
/**
* numberBox 步进器
* @description 该组件一般用于商城购物选择物品数量的场景注意该输入框只能输入大于或等于0的整数不支持小数输入
* @tutorial https://www.uviewui.com/components/numberBox.html
* @property {Number} value 输入框初始值默认1
* @property {String} bg-color 输入框和按钮的背景颜色默认#F2F3F5
* @property {Number} min 用户可输入的最小值默认0
* @property {Number} max 用户可输入的最大值默认99999
* @property {Number} step 步长每次加或减的值默认1
* @property {Boolean} disabled 是否禁用操作禁用后无法加减或手动修改输入框的值默认false
* @property {Boolean} disabled-input 是否禁止输入框手动输入值默认false
* @property {String | Number} size 输入框文字和按钮字体大小单位rpx默认26
* @property {String} color 输入框文字和加减按钮图标的颜色默认#323233
* @property {String | Number} input-width 输入框宽度单位rpx默认80
* @property {String | Number} input-height 输入框和按钮的高度单位rpx默认50
* @property {String | Number} index 事件回调时用以区分当前发生变化的是哪个输入框
* @property {String | Number} cursor-spacing 指定光标于键盘的距离避免键盘遮挡输入框单位rpx默认200
* @event {Function} change 输入框内容发生变化时触发对象形式
* @event {Function} blur 输入框失去焦点时触发对象形式
* @event {Function} minus 点击减少按钮时触发(按钮可点击情况下)对象形式
* @event {Function} plus 点击增加按钮时触发(按钮可点击情况下)对象形式
* @example <u-number-box :min="1" :max="100"></u-number-box>
*/
export default {
name: "u-number-box",
props: {
//
value: {
type: Number,
default: 1
},
//
bgColor: {
type: String,
default: '#F2F3F5'
},
//
min: {
type: Number,
default: 0
},
//
max: {
type: Number,
default: 99999
},
//
step: {
type: Number,
default: 1
},
//
disabled: {
type: Boolean,
default: false
},
// inputrpx
size: {
type: [Number, String],
default: 26
},
//
color: {
type: String,
default: '#323233'
},
// inputrpx
inputWidth: {
type: [Number, String],
default: 80
},
// inputrpx
inputHeight: {
type: [Number, String],
default: 50
},
// index使numberbox使forindex
index: {
type: [Number, String],
default: ''
},
// disabledOR
// disabledfalsedisabledInputtrue
disabledInput: {
type: Boolean,
default: false
},
//
cursorSpacing: {
type: [Number, String],
default: 100
}
},
watch: {
value(val, val1) {
// changevalutchange
if(Number(val) != this.inputVal) this.inputVal = Number(val);
},
inputVal(v1, v2) {
//
if (v1 == '') return;
let value = 0;
// minmax使
let tmp = /(^\d+$)/.test(v1);
if (tmp && v1 >= this.min && v1 <= this.max) value = v1;
else value = v2;
this.handleChange(value, 'change');
this.$nextTick(() => {
this.inputVal = value;
})
}
},
data() {
return {
inputVal: 0 // 使propsvalueprops
};
},
created() {
this.inputVal = Number(this.value);
},
computed: {
getCursorSpacing() {
// px
return Number(uni.upx2px(this.cursorSpacing));
}
},
methods: {
minus() {
this.computeVal('minus');
},
plus() {
this.computeVal('plus');
},
//
calcPlus(num1, num2) {
let baseNum, baseNum1, baseNum2;
try {
baseNum1 = num1.toString().split('.')[1].length;
} catch (e) {
baseNum1 = 0;
}
try {
baseNum2 = num2.toString().split('.')[1].length;
} catch (e) {
baseNum2 = 0;
}
baseNum = Math.pow(10, Math.max(baseNum1, baseNum2));
let precision = baseNum1 >= baseNum2 ? baseNum1 : baseNum2; //
return ((num1 * baseNum + num2 * baseNum) / baseNum).toFixed(precision);
},
//
calcMinus(num1, num2) {
let baseNum, baseNum1, baseNum2;
try {
baseNum1 = num1.toString().split('.')[1].length;
} catch (e) {
baseNum1 = 0;
}
try {
baseNum2 = num2.toString().split('.')[1].length;
} catch (e) {
baseNum2 = 0;
}
baseNum = Math.pow(10, Math.max(baseNum1, baseNum2));
let precision = baseNum1 >= baseNum2 ? baseNum1 : baseNum2;
return ((num1 * baseNum - num2 * baseNum) / baseNum).toFixed(precision);
},
computeVal(type) {
uni.hideKeyboard();
if (this.disabled) return;
let value = 0;
//
if (type === 'minus') {
value = this.calcMinus(this.inputVal, this.step);
} else if (type === 'plus') {
value = this.calcPlus(this.inputVal, this.step);
}
//
if (value < this.min || value > this.max) {
return;
}
this.inputVal = value;
this.handleChange(value, type);
},
//
onBlur(event) {
let val = 0;
let value = event.detail.value;
// 0-90min
// props min0
if (!/(^\d+$)/.test(value) || value[0] == 0) val = this.min;
val = +value;
if (val > this.max) {
val = this.max;
} else if (val < this.min) {
val = this.min;
}
this.$nextTick(() => {
this.inputVal = val;
})
this.handleChange(val, "blur");
},
handleChange(value, type) {
if (this.disabled) return;
// inputv-model
this.$emit('input', Number(value));
this.$emit(type, {
// Number
value: Number(value),
index: this.index
})
}
}
};
</script>
<style lang="scss" scoped>
.u-numberbox {
display: inline-flex;
align-items: center;
}
.u-number-input {
position: relative;
text-align: center;
padding: 0;
margin: 0 6rpx;
display: flex;
align-items: center;
justify-content: center;
}
.u-icon-plus,
.u-icon-minus {
width: 60rpx;
display: flex;
justify-content: center;
align-items: center;
}
.u-icon-plus {
border-radius: 0 8rpx 8rpx 0;
}
.u-icon-minus {
border-radius: 8rpx 0 0 8rpx;
}
.u-icon-disabled {
color: #c8c9cc !important;
background: #f7f8fa !important;
}
.u-input-disabled {
color: #c8c9cc !important;
background-color: #f2f3f5 !important;
}
</style>

View File

@ -0,0 +1,152 @@
<template>
<view class="u-keyboard" @touchmove.stop.prevent>
<view class="u-keyboard-grids">
<view
class="u-keyboard-grids-item"
:class="[btnBgGray(index) ? 'u-bg-gray' : '', index <= 2 ? 'u-border-top' : '', index < 9 ? 'u-border-bottom' : '', (index + 1) % 3 != 0 ? 'u-border-right' : '']"
:style="[itemStyle(index)]"
v-for="(item, index) in numList"
:key="index"
:hover-class="hoverClass(index)"
:hover-stay-time="100"
@tap="keyboardClick(item)"
>
<view class="u-keyboard-grids-btn">{{ item }}</view>
</view>
<view class="u-keyboard-grids-item u-bg-gray" hover-class="u-hover-class" :hover-stay-time="100" @touchstart.stop="backspaceClick" @touchend="clearTimer">
<view class="u-keyboard-back u-keyboard-grids-btn"><u-icon name="backspace" :size="38" :bold="true"></u-icon></view>
</view>
</view>
</view>
</template>
<script>
export default {
props: {
// number-card-
mode: {
type: String,
default: 'number'
},
// "."
dotEnabled: {
type: Boolean,
default: true
},
//
random: {
type: Boolean,
default: false
}
},
data() {
return {
backspace: 'backspace', // 退
dot: '.', //
timer: null, //
cardX: 'X' // X
};
},
computed: {
//
numList() {
let tmp = [];
if (!this.dotEnabled && this.mode == 'number') {
if (!this.random) {
return [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
} else {
return this.$u.randomArray([1, 2, 3, 4, 5, 6, 7, 8, 9, 0]);
}
} else if (this.dotEnabled && this.mode == 'number') {
if (!this.random) {
return [1, 2, 3, 4, 5, 6, 7, 8, 9, this.dot, 0];
} else {
return this.$u.randomArray([1, 2, 3, 4, 5, 6, 7, 8, 9, this.dot, 0]);
}
} else if (this.mode == 'card') {
if (!this.random) {
return [1, 2, 3, 4, 5, 6, 7, 8, 9, this.cardX, 0];
} else {
return this.$u.randomArray([1, 2, 3, 4, 5, 6, 7, 8, 9, this.cardX, 0]);
}
}
},
// &&&&index9
itemStyle() {
return index => {
let style = {};
if (this.mode == 'number' && !this.dotEnabled && index == 9) style.flex = '0 0 66.6666666666%';
return style;
};
},
// &&&&
btnBgGray() {
return index => {
if (!this.random && index == 9 && (this.mode != 'number' || (this.mode == 'number' && this.dotEnabled))) return true;
else return false;
};
},
hoverClass() {
return index => {
if(!this.random && index == 9 && (this.mode == 'number' && this.dotEnabled || this.mode == 'card')) return 'u-hover-class';
else return 'u-keyboard-hover';
}
}
},
methods: {
// 退
backspaceClick() {
this.$emit('backspace');
 clearInterval(this.timer); //
      this.timer = setInterval(() => {
    this.$emit('backspace');
      }, 250);
},
clearTimer() {
clearInterval(this.timer);
},
//
keyboardClick(val) {
//
if (this.dotEnabled && val != this.dot && val != this.cardX) val = Number(val);
this.$emit('change', val);
}
}
};
</script>
<style lang="scss" scoped>
.u-keyboard {
position: relative;
z-index: 1003;
}
.u-keyboard-grids {
display: flex;
flex-wrap: wrap;
}
.u-keyboard-grids-item {
flex: 0 0 33.3333333333%;
text-align: center;
font-size: 50rpx;
color: #333;
display: flex;
align-items: center;
justify-content: center;
height: 110rpx;
font-weight: 500;
}
.u-bg-gray {
background-color: #e7e6eb;
}
.u-keyboard-back {
font-size: 36rpx;
}
.u-keyboard-hover {
background-color: #e7e6eb;
}
</style>

617
node_modules/uview-ui/components/u-picker/u-picker.vue generated vendored Normal file
View File

@ -0,0 +1,617 @@
<template>
<u-popup :maskCloseAble="maskCloseAble" mode="bottom" :popup="false" v-model="value" length="auto"
:safeAreaInsetBottom="safeAreaInsetBottom" @close="close" :z-index="uZIndex">
<view class="u-datetime-picker" @tap.stop>
<view class="u-picker-header" @touchmove.stop.prevent="stop" catchtouchmove="stop">
<view class="u-btn-picker u-btn-picker--tips" :style="{ color: cancelColor }" hover-class="u-opacity" :hover-stay-time="150"
@tap="getResult('cancel')">取消</view>
<view class="u-btn-picker u-btn-picker--primary" :style="{ color: confirmColor }" hover-class="u-opacity" :hover-stay-time="150"
@touchmove.stop="" @tap.stop="getResult('confirm')">确定</view>
</view>
<view class="u-picker-body">
<picker-view v-if="mode == 'region'" :value="valueArr" @change="change" class="u-picker-view">
<picker-view-column v-if="params.province">
<view class="u-column-item" v-for="(item,index) in provinces" :key="index">
<view class="u-line-1">
{{item.label}}
</view>
</view>
</picker-view-column>
<picker-view-column v-if="params.city">
<view class="u-column-item" v-for="(item,index) in citys" :key="index">
<view class="u-line-1">
{{item.label}}
</view>
</view>
</picker-view-column>
<picker-view-column v-if="params.area">
<view class="u-column-item" v-for="(item,index) in areas" :key="index">
<view class="u-line-1">
{{item.label}}
</view>
</view>
</picker-view-column>
</picker-view>
<picker-view v-else-if="mode == 'time'" :value="valueArr" @change="change" class="u-picker-view">
<picker-view-column v-if="!reset && params.year">
<view class="u-column-item" v-for="(item,index) in years" :key="index">
{{ item }}<text class="u-text" v-if="showTimeTag"></text>
</view>
</picker-view-column>
<picker-view-column v-if="!reset && params.month">
<view class="u-column-item" v-for="(item,index) in months" :key="index">
{{ formatNumber(item)}}<text class="u-text" v-if="showTimeTag"></text>
</view>
</picker-view-column>
<picker-view-column v-if="!reset && params.day">
<view class="u-column-item" v-for="(item,index) in days" :key="index">
{{ formatNumber(item) }}<text class="u-text" v-if="showTimeTag"></text>
</view>
</picker-view-column>
<picker-view-column v-if="!reset && params.hour">
<view class="u-column-item" v-for="(item,index) in hours" :key="index">
{{ formatNumber(item) }}<text class="u-text" v-if="showTimeTag"></text>
</view>
</picker-view-column>
<picker-view-column v-if="!reset && params.minute">
<view class="u-column-item" v-for="(item,index) in minutes" :key="index">
{{ formatNumber(item) }}<text class="u-text" v-if="showTimeTag"></text>
</view>
</picker-view-column>
<picker-view-column v-if="!reset && params.second">
<view class="u-column-item" v-for="(item,index) in seconds" :key="index">
{{ formatNumber(item) }}<text class="u-text" v-if="showTimeTag"></text>
</view>
</picker-view-column>
</picker-view>
<picker-view v-else-if="mode == 'selector'" :value="defaultSelector" @change="change" class="u-picker-view">
<picker-view-column>
<view class="u-column-item" v-for="(item,index) in range" :key="index">
<view class="u-line-1">
{{getItemValue(item, 'selector')}}
</view>
</view>
</picker-view-column>
</picker-view>
<picker-view v-else-if="mode == 'multiSelector'" :value="defaultSelector" @change="change" class="u-picker-view">
<picker-view-column v-for="(item,index) in range" :key="index">
<view class="u-column-item" v-for="(item1,index1) in item" :key="index1">
<view class="u-line-1">
{{getItemValue(item1, 'multiSelector')}}
</view>
</view>
</picker-view-column>
</picker-view>
</view>
</view>
</u-popup>
</template>
<script>
import provinces from '../../libs/util/province.js';
import citys from '../../libs/util/city.js';
import areas from '../../libs/util/area.js';
/**
* picker picker弹出选择器
* @description 此选择器有两种弹出模式一是时间模式可以配置年秒参数 二是地区模式可以配置省区参数
* @tutorial https://www.uviewui.com/components/picker.html
* @property {Object} params 需要显示的参数见官网说明
* @property {String} mode 模式选择region-地区类型time-时间类型默认time
* @property {String Number} start-year 可选的开始年份mode=time时有效默认1950
* @property {String Number} end-year 可选的结束年份mode=time时有效默认2050
* @property {Boolean} safe-area-inset-bottom 是否开启底部安全区适配默认false
* @property {Boolean} show-time-tag 时间模式时是否显示后面的年月日中文提示
* @property {String} cancel-color 取消按钮的颜色默认#606266
* @property {String} confirm-color 确认按钮的颜色默认#2979ff
* @property {String} default-time 默认选中的时间mode=time时有效
* @property {String} default-region 默认选中的地区中文形式mode=region时有效
* @property {String} default-code 默认选中的地区编号形式mode=region时有效
* @property {Boolean} mask-close-able 是否允许通过点击遮罩关闭Picker默认true
* @property {String Number} z-index 弹出时的z-index值默认1075
* @property {Array} default-selector 数组形式其中每一项表示选择了range对应项中的第几个
* @property {Array} range 自定义选择的数据mode=selector或mode=multiSelector时有效
* @property {String} range-key 当range参数的元素为对象时指定Object中的哪个key的值作为选择器显示内容
* @event {Function} confirm 点击确定按钮返回当前选择的值
* @event {Function} cancel 点击取消按钮返回当前选择的值
* @example <u-picker v-model="show" mode="time"></u-picker>
*/
export default {
name: "u-picker",
props: {
// picker
params: {
type: Object,
default () {
return {
year: true,
month: true,
day: true,
hour: false,
minute: false,
second: false,
province: true,
city: true,
area: true
}
}
},
// mode=selectormode=multiSelector
range: {
type: Array,
default() {
return []
}
},
// mode=selectormode=multiSelector
defaultSelector: {
type: Array,
default() {
return [0]
}
},
// range ArrayObject range-key Object key
rangeKey: {
type: String,
default: ''
},
// region-time-selector-multiSelector-
mode: {
type: String,
default: 'time'
},
//
startYear: {
type: [String, Number],
default: 1950
},
//
endYear: {
type: [String, Number],
default: 2050
},
// ""
cancelColor: {
type: String,
default: '#606266'
},
// ""
confirmColor: {
type: String,
default: '#2979ff'
},
// 2025-07-02 || 2025-07-02 13:01:00 || 2025/07/02
defaultTime: {
type: String,
default: ''
},
// ["", "", ""]
defaultRegion: {
type: Array,
default () {
return [];
}
},
//
showTimeTag: {
type: Boolean,
default: true
},
// defaultRegionareaCodeareaCode["13", "1303", "130304"]
areaCode: {
type: Array,
default () {
return [];
}
},
safeAreaInsetBottom: {
type: Boolean,
default: false
},
// Picker
maskCloseAble: {
type: Boolean,
default: true
},
//
value: {
type: Boolean,
default: false
},
// z-index
zIndex: {
type: [String, Number],
default: 0
}
},
data() {
return {
years: [],
months: [],
days: [],
hours: [],
minutes: [],
seconds: [],
year: 0,
month: 0,
day: 0,
hour: 0,
minute: 0,
second: 0,
startDate: "",
endDate: "",
valueArr: [],
reset: false,
provinces: provinces,
citys: citys[0],
areas: areas[0][0],
province: 0,
city: 0,
area: 0,
}
},
mounted() {
this.init();
},
computed: {
propsChange() {
//
return `${this.mode}-${this.defaultTime}-${this.startYear}-${this.endYear}-${this.defaultRegion}-${this.areaCode}`;
},
regionChange() {
//
return `${this.province}-${this.city}`;
},
yearAndMonth() {
return `${this.year}-${this.month}`;
},
uZIndex() {
// z-index使
return this.zIndex ? this.zIndex : this.$u.zIndex.popup;
}
},
watch: {
propsChange() {
this.reset = true;
setTimeout(() => this.init(), 10);
},
// pickerthis.citysthis.areas
regionChange(val) {
this.citys = citys[this.province];
this.areas = areas[this.province][this.city];
},
// watch
// 3031229228
yearAndMonth(val) {
if (this.params.year) this.setDays();
},
// QQ()
value(n) {
if (n) {
this.reset = true;
setTimeout(() => this.init(), 10);
}
}
},
methods: {
//
getItemValue(item, mode) {
// (2020-05-25)uni-appv-iffalse
// getItemValue
if(this.mode == mode) {
return typeof item == 'object' ? item[this.rangeKey] : item
}
},
// 100
formatNumber(num) {
return +num < 10 ? '0' + num : String(num);
},
//
generateArray: function(start, end) {
end = end > start ? end : start;
//
return [...Array(end + 1).keys()].slice(start);
},
getIndex: function(arr, val) {
let index = arr.indexOf(val);
// index-1(index)~(-1)=-(-1)-1=0
return ~index ? index : 0;
},
//
initTimeValue() {
// IE(uni)"-"
let fdate = this.defaultTime.replace(/\-/g, '/');
fdate = fdate && fdate.indexOf("/") == -1 ? `2020/01/01 ${fdate}` : fdate
let time = null;
if (fdate)
time = new Date(fdate);
else
time = new Date();
//
this.year = time.getFullYear()
this.month = Number(time.getMonth()) + 1;
this.day = time.getDate();
this.hour = time.getHours();
this.minute = time.getMinutes();
this.second = time.getSeconds();
},
init() {
this.valueArr = [];
this.reset = false;
if (this.mode == 'time') {
this.initTimeValue();
if (this.params.year) {
this.valueArr.push(0);
this.setYears();
}
if (this.params.month) {
this.valueArr.push(0);
this.setMonths();
}
if (this.params.day) {
this.valueArr.push(0);
this.setDays();
}
if (this.params.hour) {
this.valueArr.push(0);
this.setHours();
}
if (this.params.minute) {
this.valueArr.push(0);
this.setMinutes();
}
if (this.params.second) {
this.valueArr.push(0);
this.setSeconds();
}
} else if(this.mode == 'region') {
if (this.params.province) {
this.valueArr.push(0);
this.setProvinces();
}
if (this.params.city) {
this.valueArr.push(0);
this.setCitys();
}
if (this.params.area) {
this.valueArr.push(0);
this.setAreas();
}
} else if(this.mode == 'selector') {
this.valueArr = this.defaultSelector;
} else if(this.mode == 'multiSelector') {
this.valueArr = this.defaultSelector;
this.multiSelectorValue = this.defaultSelector;
}
this.$forceUpdate();
},
// picker
setYears() {
//
this.years = this.generateArray(this.startYear, this.endYear);
// this.valueArrpicker
this.valueArr.splice(this.valueArr.length - 1, 1, this.getIndex(this.years, this.year));
},
setMonths() {
this.months = this.generateArray(1, 12);
this.valueArr.splice(this.valueArr.length - 1, 1, this.getIndex(this.months, this.month));
},
setDays() {
let totalDays = new Date(this.year, this.month, 0).getDate();
this.days = this.generateArray(1, totalDays);
let index = 0;
// 使setMonths()this.valueArr.splice(this.valueArr.length - 1, xxx)
// this.monththis.yearwatchthis.setDays()this.valueArr.length
if (this.params.year && this.params.month) index = 2;
else if (this.params.month) index = 1;
else if (this.params.year) index = 1;
else index = 0;
this.valueArr.splice(index, 1, this.getIndex(this.days, this.day));
},
setHours() {
this.hours = this.generateArray(0, 23);
this.valueArr.splice(this.valueArr.length - 1, 1, this.getIndex(this.hours, this.hour));
},
setMinutes() {
this.minutes = this.generateArray(0, 59);
this.valueArr.splice(this.valueArr.length - 1, 1, this.getIndex(this.minutes, this.minute));
},
setSeconds() {
this.seconds = this.generateArray(0, 59);
this.valueArr.splice(this.valueArr.length - 1, 1, this.getIndex(this.seconds, this.second));
},
setProvinces() {
// province
if (!this.params.province) return;
let tmp = '';
let useCode = false;
// defaultRegionareaCode使areaCode
if (this.areaCode.length) {
tmp = this.areaCode[0];
useCode = true;
} else if (this.defaultRegion.length) tmp = this.defaultRegion[0];
else tmp = 0;
//
provinces.map((v, k) => {
if (useCode ? v.value == tmp : v.label == tmp) {
tmp = k;
}
})
this.province = tmp;
this.provinces = provinces;
//
this.valueArr.splice(0, 1, this.province);
},
setCitys() {
if (!this.params.city) return;
let tmp = '';
let useCode = false;
if (this.areaCode.length) {
tmp = this.areaCode[1];
useCode = true;
} else if (this.defaultRegion.length) tmp = this.defaultRegion[1];
else tmp = 0;
citys[this.province].map((v, k) => {
if (useCode ? v.value == tmp : v.label == tmp) {
tmp = k;
}
})
this.city = tmp;
this.citys = citys[this.province];
this.valueArr.splice(1, 1, this.city);
},
setAreas() {
if (!this.params.area) return;
let tmp = '';
let useCode = false;
if (this.areaCode.length) {
tmp = this.areaCode[2];
useCode = true;
} else if (this.defaultRegion.length) tmp = this.defaultRegion[2];
else tmp = 0;
areas[this.province][this.city].map((v, k) => {
if (useCode ? v.value == tmp : v.label == tmp) {
tmp = k;
}
})
this.area = tmp;
this.areas = areas[this.province][this.city];
this.valueArr.splice(2, 1, this.area);
},
close() {
this.$emit('input', false);
},
// picker
change(e) {
this.valueArr = e.detail.value;
let i = 0;
if (this.mode == 'time') {
// 使i++this.valueArrthis.params
// ifi1
if (this.params.year) this.year = this.years[this.valueArr[i++]];
if (this.params.month) this.month = this.months[this.valueArr[i++]];
if (this.params.day) this.day = this.days[this.valueArr[i++]];
if (this.params.hour) this.hour = this.hours[this.valueArr[i++]];
if (this.params.minute) this.minute = this.minutes[this.valueArr[i++]];
if (this.params.second) this.second = this.seconds[this.valueArr[i++]];
} else if(this.mode == 'region') {
if (this.params.province) this.province = this.valueArr[i++];
if (this.params.city) this.city = this.valueArr[i++];
if (this.params.area) this.area = this.valueArr[i++];
} else if(this.mode == 'multiSelector') {
let index = null;
//
this.defaultSelector.map((val, idx) => {
if(val != e.detail.value[idx]) index = idx;
})
//
if(index != null) {
this.$emit('columnchange', {
column: index,
index: e.detail.value[index]
})
}
}
},
//
getResult(event = null) {
let result = {};
// this.paramstrue
if (this.mode == 'time') {
if (this.params.year) result.year = this.formatNumber(this.year || 0);
if (this.params.month) result.month = this.formatNumber(this.month || 0);
if (this.params.day) result.day = this.formatNumber(this.day || 0);
if (this.params.hour) result.hour = this.formatNumber(this.hour || 0);
if (this.params.minute) result.minute = this.formatNumber(this.minute || 0);
if (this.params.second) result.second = this.formatNumber(this.second || 0);
} else if (this.mode == 'region') {
if (this.params.province) result.province = provinces[this.province];
if (this.params.city) result.city = citys[this.province][this.city];
if (this.params.area) result.area = areas[this.province][this.city][this.area];
} else if (this.mode == 'selector') {
result = this.valueArr;
} else if (this.mode == 'multiSelector') {
result = this.valueArr;
}
if (event) this.$emit(event, result);
this.close();
}
}
}
</script>
<style lang="scss" scoped>
.u-datetime-picker {
position: relative;
z-index: 999;
}
.u-picker-view {
height: 100%;
box-sizing: border-box;
}
.u-picker-header {
width: 100%;
height: 90rpx;
padding: 0 40rpx;
display: flex;
justify-content: space-between;
align-items: center;
box-sizing: border-box;
font-size: 32rpx;
background: #fff;
position: relative;
}
.u-picker-header::after {
content: '';
position: absolute;
border-bottom: 1rpx solid #eaeef1;
-webkit-transform: scaleY(0.5);
transform: scaleY(0.5);
bottom: 0;
right: 0;
left: 0;
}
.u-picker-body {
width: 100%;
height: 500rpx;
overflow: hidden;
background-color: #fff;
}
.u-column-item {
display: flex;
align-items: center;
justify-content: center;
font-size: 32rpx;
color: $u-main-color;
padding: 0 8rpx;
}
.u-text {
font-size: 24rpx;
padding-left: 8rpx;
}
.u-btn-picker {
padding: 16rpx;
box-sizing: border-box;
text-align: center;
text-decoration: none;
}
.u-opacity {
opacity: 0.5;
}
.u-btn-picker--primary {
color: $u-type-primary;
}
.u-btn-picker--tips {
color: $u-tips-color;
}
</style>

396
node_modules/uview-ui/components/u-popup/u-popup.vue generated vendored Normal file
View File

@ -0,0 +1,396 @@
<template>
<view v-if="visibleSync" :style="[customStyle]" :class="{ 'u-drawer-visible': showDrawer }" class="u-drawer">
<u-mask :maskClickAble="maskCloseAble" :show="showDrawer && mask" @click="maskClick"></u-mask>
<view
class="u-drawer-content"
@tap="modeCenterClose(mode)"
:class="[
safeAreaInsetBottom ? 'safe-area-inset-bottom' : '',
'u-drawer-' + mode,
showDrawer ? 'u-drawer-content-visible' : '',
zoom && mode == 'center' ? 'u-animation-zoom' : ''
]"
@touchmove.stop.prevent
@tap.stop.prevent
:style="[style]"
>
<view class="u-mode-center-box" @tap.stop.prevent @touchmove.stop.prevent v-if="mode == 'center'" :style="[centerStyle]">
<u-icon
@click="close"
v-if="closeable"
class="u-close"
:class="['u-close--' + closeIconPos]"
:name="closeIcon"
:color="closeIconColor"
:size="closeIconSize"
></u-icon>
<slot />
</view>
<block v-else><slot /></block>
<u-icon
v-if="mode != 'center' && closeable"
@click="close"
class="u-close"
:class="['u-close--' + closeIconPos]"
:name="closeIcon"
:color="closeIconColor"
:size="closeIconSize"
></u-icon>
</view>
</view>
</template>
<script>
/**
* popup 弹窗
* @description 弹出层容器用于展示弹窗信息提示等内容支持上右和中部弹出组件只提供容器内部内容由用户自定义
* @tutorial https://www.uviewui.com/components/popup.html
* @property {String} mode 弹出方向默认left
* @property {Boolean} mask 是否显示遮罩默认true
* @property {Stringr | Number} length mode=left | 见官网说明默认auto
* @property {Boolean} zoom 是否开启缩放动画只在mode为center时有效默认true
* @property {Boolean} safe-area-inset-bottom 是否开启底部安全区适配默认false
* @property {Boolean} mask-close-able 点击遮罩是否可以关闭弹出层默认true
* @property {Object} custom-style 用户自定义样式
* @property {Numberr | String} border-radius 弹窗圆角值默认0
* @property {Numberr | String} z-index 弹出内容的z-index值默认1075
* @property {Boolean} closeable 是否显示关闭图标默认false
* @property {String} close-icon 关闭图标的名称只能uView的内置图标
* @property {String} close-icon-pos 自定义关闭图标位置默认top-right
* @property {String} close-icon-color 关闭图标的颜色默认#909399
* @property {Number | String} close-icon-size 关闭图标的大小单位rpx默认30
* @event {Function} open 弹出层打开
* @event {Function} close 弹出层收起
* @example <u-popup v-model="show"><view>出淤泥而不染濯清涟而不妖</view></u-popup>
*/
export default {
name: 'u-popup',
props: {
/**
* 显示状态
*/
show: {
type: Boolean,
default: false
},
/**
* 弹出方向left|right|top|bottom|center
*/
mode: {
type: String,
default: 'left'
},
/**
* 是否显示遮罩
*/
mask: {
type: Boolean,
default: true
},
// (mode=left|right)(mode=top|bottom)rpx"auto"
// "50%"
length: {
type: [Number, String],
default: 'auto'
},
// mode=center
zoom: {
type: Boolean,
default: true
},
// iPhoneX
safeAreaInsetBottom: {
type: Boolean,
default: false
},
//
maskCloseAble: {
type: Boolean,
default: true
},
//
customStyle: {
type: Object,
default() {
return {};
}
},
value: {
type: Boolean,
default: false
},
// 使Pickerkeyboard
// v-modelprops
popup: {
type: Boolean,
default: true
},
// rpx
borderRadius: {
type: [Number, String],
default: 0
},
zIndex: {
type: [Number, String],
default: ''
},
//
closeable: {
type: Boolean,
default: false
},
// uView
closeIcon: {
type: String,
default: 'close'
},
// top-lefttop-rightbottom-leftbottom-right
closeIconPos: {
type: String,
default: 'top-right'
},
//
closeIconColor: {
type: String,
default: '#909399'
},
// rpx
closeIconSize: {
type: [String, Number],
default: '30'
}
},
data() {
return {
visibleSync: false,
showDrawer: false,
timer: null,
style1: {}
};
},
computed: {
// mode(mode = left|right)(mode = top|bottom)
style() {
let style = {};
let translate = '100%';
// auto使rpx
let length = /%$/.test(this.length) || this.length == 'auto' ? this.length : uni.upx2px(this.length) + 'px';
// translate
if (this.mode == 'left' || this.mode == 'top') translate = length == 'auto' ? '-100%' : '-' + length;
if (this.mode == 'left' || this.mode == 'right') {
style = {
width: length,
height: '100%',
transform: `translate3D(${translate},0px,0px)`
};
} else if (this.mode == 'top' || this.mode == 'bottom') {
style = {
width: '100%',
height: length,
transform: `translate3D(0px,${translate},0px)`
};
}
style.zIndex = this.zIndex ? this.zIndex : this.$u.zIndex.popup;
// borderRadius
if (this.borderRadius) {
switch (this.mode) {
case 'left':
style.borderRadius = `0 ${this.borderRadius}rpx ${this.borderRadius}rpx 0`;
break;
case 'top':
style.borderRadius = `0 0 ${this.borderRadius}rpx ${this.borderRadius}rpx`;
break;
case 'right':
style.borderRadius = `${this.borderRadius}rpx 0 0 ${this.borderRadius}rpx`;
break;
case 'bottom':
style.borderRadius = `${this.borderRadius}rpx ${this.borderRadius}rpx 0 0`;
break;
default:
}
//
style.overflow = 'hidden';
}
return style;
},
//
centerStyle() {
let style = {};
let length = /%$/.test(this.length) || this.length == 'auto' ? this.length : uni.upx2px(this.length) + 'px';
style.width = length;
style.zIndex = this.zIndex ? this.zIndex : this.$u.zIndex.popup;
if (this.borderRadius) {
style.borderRadius = `${this.borderRadius}rpx`;
//
style.overflow = 'hidden';
}
return style;
}
},
watch: {
value(val) {
if (val) {
this.open();
} else {
this.close();
}
}
},
created() {
// ()
this.visibleSync = this.value;
setTimeout(() => {
this.showDrawer = this.value;
}, 30);
},
methods: {
//
maskClick() {
this.close();
},
close() {
this.change('showDrawer', 'visibleSync', false);
},
// .u-drawer-content
// mode=center
modeCenterClose(mode) {
if (mode != 'center' || !this.maskCloseAble) return;
this.close();
},
open() {
this.change('visibleSync', 'showDrawer', true);
},
//
//
change(param1, param2, status) {
// this.popupfalsepickeractionsheetpopup
if (this.popup == true) this.$emit('input', status);
this[param1] = status;
if (this.timer) {
clearTimeout(this.timer);
}
this.timer = setTimeout(() => {
this[param2] = status;
this.$emit(status ? 'open' : 'close');
},
status ? 30 : 300
);
}
}
};
</script>
<style scoped lang="scss">
.u-drawer {
/* #ifndef APP-NVUE */
display: block;
/* #endif */
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
overflow: hidden;
z-index: 999;
}
.u-drawer-content {
/* #ifndef APP-NVUE */
display: block;
/* #endif */
position: absolute;
z-index: 1003;
transition: all 0.3s linear;
}
.u-drawer-left {
top: 0;
bottom: 0;
left: 0;
background-color: #ffffff;
}
.u-drawer-right {
right: 0;
top: 0;
bottom: 0;
background-color: #ffffff;
}
.u-drawer-top {
top: 0;
left: 0;
right: 0;
background-color: #ffffff;
}
.u-drawer-bottom {
bottom: 0;
left: 0;
right: 0;
background-color: #ffffff;
}
.u-drawer-center {
/* #ifndef APP-NVUE */
display: flex;
flex-direction: column;
/* #endif */
bottom: 0;
left: 0;
right: 0;
top: 0;
justify-content: center;
align-items: center;
opacity: 0;
z-index: 99999;
}
.u-mode-center-box {
min-width: 100rpx;
min-height: 100rpx;
/* #ifndef APP-NVUE */
display: block;
/* #endif */
position: relative;
background-color: #ffffff;
}
.u-drawer-content-visible.u-drawer-center {
transform: scale(1);
opacity: 1;
}
.u-animation-zoom {
transform: scale(1.15);
}
.u-drawer-content-visible {
transform: translate3D(0px, 0px, 0px) !important;
}
.u-close {
position: absolute;
z-index: 1;
}
.u-close--top-left {
top: 30rpx;
left: 30rpx;
}
.u-close--top-right {
top: 30rpx;
right: 30rpx;
}
.u-close--bottom-left {
bottom: 30rpx;
left: 30rpx;
}
.u-close--bottom-right {
right: 30rpx;
bottom: 30rpx;
}
</style>

View File

@ -0,0 +1,84 @@
<template>
<view class="u-radio-group u-clearfix">
<slot></slot>
</view>
</template>
<script>
import Emitter from '../../libs/util/emitter.js';
/**
* radioRroup 单选框父组件
* @description 单选框用于有一个选择用户只能选择其中一个的场景搭配u-radio使用
* @tutorial https://www.uviewui.com/components/radio.html
* @property {Boolean} disabled 是否禁用所有radio默认false
* @property {String} active-color 选中时的颜色应用到所有子Radio组件默认#2979ff
* @event {Function} change 任一个radio状态发生变化时触发
* @property {String} width 宽度需带单位
* @property {Boolean} wrap 是否每个radio都换行默认false
* @example <u-radio-group v-model="value"></u-radio-group>
*/
export default {
name: "u-radio-group",
mixins: [Emitter],
props: {
//
disabled: {
type: Boolean,
default: false
},
// radioradionameradio
value: {
type: [String, Number],
default: ''
},
//
activeColor: {
type: String,
default: '#2979ff'
},
//
size: {
type: [String, Number],
default: 34
},
// checkboxu-checkbox-group
width: {
type: String,
default: 'auto'
},
// checkbox
wrap: {
type: Boolean,
default: false
}
},
provide() {
return {
radioGroup: this
}
},
methods: {
// radioradiovalue(propsvalue)
setValue(val) {
// emitv-model
this.$emit('input', val);
// this.$emit('input')
this.$nextTick(function() {
this.$emit('change', this.value);
// checkbox
// u-form-item
this.dispatch('u-form-item', 'on-form-change', this.value);
});
}
}
}
</script>
<style lang="scss" scoped>
.u-radio-group {
/* #ifndef MP */
display: inline-flex;
flex-wrap: wrap;
/* #endif */
}
</style>

227
node_modules/uview-ui/components/u-radio/u-radio.vue generated vendored Normal file
View File

@ -0,0 +1,227 @@
<template>
<view class="u-radio" :style="[radioStyle]">
<view class="u-radio__icon-wrap" @tap="toggle">
<u-icon :class="iconClass" name="checkbox-mark" :size="iconSize" :color="iconColor" class="u-radio__icon" :style="[iconStyle]" />
</view>
<view class="u-label-class u-radio__label" @tap="onClickLabel" :style="{
fontSize: labelSize + 'rpx'
}">
<slot />
</view>
</view>
</template>
<script>
/**
* radio 单选框
* @description 单选框用于有一个选择用户只能选择其中一个的场景搭配u-radio-group使用
* @tutorial https://www.uviewui.com/components/radio.html
* @property {String Number} icon-size 图标大小单位rpx默认24
* @property {String Number} label-size label字体大小单位rpx默认28
* @property {String Number} name radio组件的标示符
* @property {String} shape 形状见上方说明默认circle
* @property {Boolean} disabled 是否禁用默认false
* @property {Boolean} label-disabled 点击文本是否可以操作radio默认true
* @property {String} active-color 选中时的颜色如设置radioGroup的active-color将失效
* @event {Function} change 某个radio状态发生变化时触发(选中状态)
* @example <u-radio :label-disabled="false">门掩黄昏无计留春住</u-radio>
*/
export default {
name: "u-radio",
props: {
// radio
name: {
type: [String, Number],
default: ''
},
// squarecircle
shape: {
type: String,
default: 'square'
},
//
disabled: {
type: Boolean,
default: false
},
//
labelDisabled: {
type: Boolean,
default: false
},
// radioGroupactiveColor
activeColor: {
type: String,
default: ''
},
// rpx
iconSize: {
type: [String, Number],
default: 20
},
// labelrpx
labelSize: {
type: [String, Number],
default: 28
},
},
inject: ['radioGroup'],
data() {
return {
parentDisabled: false
};
},
created() {
this.parentDisabled = this.radioGroup.disabled;
},
computed: {
// radioradionameradioGroupvalue
iconStyle() {
let style = {};
if (this.radioActiveColor && this.name == this.radioGroup.value && !this.disabled && !this.parentDisabled) {
style.borderColor = this.radioActiveColor;
style.backgroundColor = this.radioActiveColor;
}
style.width = this.radioGroup.size + 'rpx';
style.height = this.radioGroup.size + 'rpx';
return style;
},
iconColor() {
return this.name == this.radioGroup.value ? '#ffffff' : 'transparent';
},
iconClass() {
let classs = [];
classs.push('u-radio__icon--' + this.shape);
if (this.name == this.radioGroup.value) classs.push('u-radio__icon--checked');
if (this.disabled || this.parentDisabled) classs.push('u-radio__icon--disabled');
if (this.name == this.radioGroup.value && (this.disabled || this.parentDisabled)) classs.push(
'u-radio__icon--disabled--checked');
return classs;
},
// radioGroupactiveColor
// activeColor
radioActiveColor() {
return this.activeColor ? this.activeColor : this.radioGroup.activeColor;
},
radioStyle() {
let style = {};
if(this.radioGroup.width) {
style.width = this.radioGroup.width;
// #ifdef MP
// 使float
style.float = 'left';
// #endif
// #ifndef MP
// H5APP使flex
style.flex = `0 0 ${this.radioGroup.width}`;
// #endif
}
if(this.radioGroup.wrap) {
style.width = '100%';
// #ifndef MP
// H5APP使flex100%
style.flex = '0 0 100%';
// #endif
}
return style;
}
},
methods: {
onClickLabel() {
if (!this.disabled && !this.labelDisabled && !this.parentDisabled) {
this.radioGroup.setValue(this.name);
this.emitEvent();
}
},
toggle() {
if (!this.disabled && !this.parentDisabled) {
this.radioGroup.setValue(this.name);
this.emitEvent();
}
},
emitEvent() {
this.$emit('change', this.name)
},
}
};
</script>
<style lang="scss" scoped>
.u-radio {
display: -webkit-flex;
display: flex;
-webkit-align-items: center;
align-items: center;
overflow: hidden;
-webkit-user-select: none;
user-select: none;
line-height: 1.8;
}
.u-radio__icon-wrap,
.u-radio__label {
color: $u-content-color;
}
.u-radio__icon-wrap {
-webkit-flex: none;
flex: none;
}
.u-radio__icon {
display: -webkit-flex;
display: flex;
-webkit-align-items: center;
align-items: center;
-webkit-justify-content: center;
justify-content: center;
box-sizing: border-box;
width: 42rpx;
height: 42rpx;
color: transparent;
text-align: center;
transition-property: color, border-color, background-color;
font-size: 20px;
border: 1px solid #c8c9cc;
transition-duration: 0.2s;
}
.u-radio__icon--circle {
border-radius: 100%;
}
.u-radio__icon--square {
border-radius: 3px;
}
.u-radio__icon--checked {
color: #fff;
background-color: #2979ff;
border-color: #2979ff;
}
.u-radio__icon--disabled {
background-color: #ebedf0;
border-color: #c8c9cc;
}
.u-radio__icon--disabled--checked {
color: #c8c9cc !important;
}
.u-radio__label {
word-wrap: break-word;
margin-left: 10rpx;
margin-right: 24rpx;
color: $u-content-color;
font-size: 30rpx;
}
.u-radio__label--disabled {
color: #c8c9cc;
}
.u-radio__label:empty {
margin: 0;
}
</style>

192
node_modules/uview-ui/components/u-rate/u-rate.vue generated vendored Normal file
View File

@ -0,0 +1,192 @@
<template>
<view class="u-rate" :id="elId" @touchmove.stop.prevent="touchMove">
<view class="u-star-wrap" v-for="(item, index) in count" :key="index" :class="[elClass]">
<u-icon
:name="activeIndex > index ? activeIcon : inactiveIcon"
@click="click(index + 1, $event)"
:color="activeIndex > index ? activeColor : inactiveColor"
:style="{
fontSize: size + 'rpx',
padding: `0 ${gutter / 2 + 'rpx'}`
}"
></u-icon>
</view>
</view>
</template>
<script>
/**
* rate 评分
* @description 该组件一般用于满意度调查星型评分的场景
* @tutorial https://www.uviewui.com/components/rate.html
* @property {String Number} count 最多可选的星星数量默认5
* @property {String Number} current 默认选中的星星数量默认0
* @property {Boolean} disabled 是否禁止用户操作默认false
* @property {String Number} size 星星的大小单位rpx默认32
* @property {String} inactive-color 未选中星星的颜色默认#b2b2b2
* @property {String} active-color 选中的星星颜色默认#FA3534
* @property {String} active-icon 选中时的图标名只能为uView的内置图标默认star-fill
* @property {String} inactive-icon 未选中时的图标名只能为uView的内置图标默认star
* @property {String} gutter 星星之间的距离默认10
* @property {String Number} min-count 最少选中星星的个数默认0
* @property {Boolean} allow-half 是否允许半星选择默认false
* @event {Function} change 选中的星星发生变化时触发
* @example <u-rate :count="count" :current="2"></u-rate>
*/
export default {
name: 'u-rate',
props: {
//
count: {
type: [Number, String],
default: 5
},
// ()
current: {
type: [Number, String],
default: 0
},
//
disabled: {
type: Boolean,
default: false
},
// rpx
size: {
type: [Number, String],
default: 32
},
//
inactiveColor: {
type: String,
default: '#b2b2b2'
},
//
activeColor: {
type: String,
default: '#FA3534'
},
// rpx
gutter: {
type: [Number, String],
default: 10
},
//
minCount: {
type: [Number, String],
default: 0
},
// ()
allowHalf: {
type: Boolean,
default: false
},
// ()
activeIcon: {
type: String,
default: 'star-fill'
},
// ()
inactiveIcon: {
type: String,
default: 'star'
}
},
data() {
return {
// id
elId: this.$u.guid(),
elClass: this.$u.guid(),
starBoxLeft: 0, //
activeIndex: this.current, // index
starWidth: 0, //
starWidthArr: [] //
};
},
watch: {
current(val) {
this.activeIndex = val;
}
},
methods: {
//
getElRectById() {
// uView
this.$u.getRect('#' + this.elId).then(res => {
this.starBoxLeft = res.left;
})
},
//
getElRectByClass() {
// uView
this.$u.getRect('.' + this.elClass).then(res => {
this.starWidth = res.width;
//
for (let i = 0; i < this.count; i++) {
this.starWidthArr[i] = (i + 1) * this.starWidth;
}
})
},
//
touchMove(e) {
if (this.disabled) {
return;
}
if (!e.changedTouches[0]) {
return;
}
const movePageX = e.changedTouches[0].pageX;
//
const distance = movePageX - this.starBoxLeft;
// 0
if (distance <= 0) {
this.activeIndex = 0;
}
//
let index = Math.ceil(distance / this.starWidth);
this.activeIndex = index > this.count ? this.count : index;
//
if (this.activeIndex < this.minCount) this.activeIndex = this.minCount;
this.$emit('change', this.activeIndex);
},
//
click(index, e) {
if (this.disabled) {
return;
}
//
if (this.allowHalf) {
}
// 0
if (index == 1) {
if (this.activeIndex == 1) this.activeIndex = 0;
else this.activeIndex = 1;
} else {
this.activeIndex = index;
}
//
if (this.activeIndex < this.minCount) this.activeIndex = this.minCount;
this.$emit('change', this.activeIndex);
}
},
mounted() {
this.getElRectById();
this.getElRectByClass();
}
};
</script>
<style scoped lang="scss">
.u-rate {
display: -webkit-inline-flex;
display: inline-flex;
align-items: center;
margin: 0;
padding: 0;
}
.u-icon {
box-sizing: border-box;
}
</style>

View File

@ -0,0 +1,158 @@
<template>
<view class="">
<view class="u-content" :style="{ height: isLongContent && !showMore ? showHeight + 'rpx' : 'auto' }">
<slot></slot>
</view>
<view @tap="toggleReadMore" v-if="isLongContent" class="u-showmore-wrap"
:class="{ 'u-show-more': showMore }"
:style="[innerShadowStyle]"
>
<text class="u-readmore-btn" :style="{
fontSize: fontSize + 'rpx',
color: color
}">
{{ showMore ? openText : closeText }}
</text>
<u-icon :color="color" :size="fontSize" class="u-icon" :name="showMore ? 'arrow-up' : 'arrow-down'"></u-icon>
</view>
</view>
</template>
<script>
/**
* readMore 阅读更多
* @description 该组件一般用于内容较长预先收起一部分点击展开全部内容的场景
* @tutorial https://www.uviewui.com/components/readMore.html
* @property {String Number} show-height 内容超出此高度才会显示展开全文按钮单位rpx默认400
* @property {Boolean} toggle 展开后是否显示收起按钮默认false
* @property {String} close-text 关闭时的提示文字默认展开阅读全文
* @property {String Number} font-size 提示文字的大小单位rpx默认28
* @property {String} open-text 展开时的提示文字默认收起
* @property {String} color 提示文字的颜色默认#2979ff
* @example <u-read-more><rich-text :nodes="content"></rich-text></u-read-more>
*/
export default {
name: "u-read-more",
props: {
// rpx
showHeight: {
type: [Number, String],
default: 400
},
// ""
toggle: {
type: Boolean,
default: false
},
//
closeText: {
type: String,
default: '展开阅读全文'
},
//
openText: {
type: String,
default: '收起'
},
//
color: {
type: String,
default: '#2979ff'
},
//
fontSize: {
type: [String, Number],
default: 28
},
//
shadowStyle: {
type: Object,
default() {
return {
backgroundImage: "linear-gradient(-180deg, rgba(255, 255, 255, 0) 0%, #fff 80%)",
paddingTop: "300rpx",
marginTop: "-300rpx"
}
}
}
},
watch: {
paramsChange(val) {
this.init();
}
},
computed: {
paramsChange() {
return `${this.toggle}-${this.showHeight}`;
},
//
innerShadowStyle() {
if(this.showMore) return {};
else return this.shadowStyle
}
},
data() {
return {
isLongContent: false, //
showMore: false, // true-false-
};
},
mounted() {
this.init();
},
methods: {
init() {
this.$uGetRect('.u-content').then(res => {
//
if (res.height > uni.upx2px(this.showHeight)) {
this.isLongContent = true;
this.showMore = false;
}
})
},
//
toggleReadMore() {
this.showMore = !this.showMore;
// togglefalse""
if (this.toggle == false) this.isLongContent = false;
}
}
};
</script>
<style lang="scss" scoped>
.u-content {
font-size: 30rpx;
color: $u-content-color;
line-height: 1.8;
text-align: left;
text-indent: 2em;
overflow: hidden;
}
.u-showmore-wrap {
position: relative;
width: 100%;
padding-bottom: 26rpx;
display: flex;
align-items: center;
justify-content: center;
}
.u-show-more {
padding-top: 0;
background: none;
margin-top: 20rpx;
}
.u-readmore-btn {
display: flex;
align-items: center;
justify-content: center;
line-height: 1;
}
.u-icon {
margin-left: 14rpx;
}
</style>

View File

@ -0,0 +1,256 @@
<template>
<view
v-if="show"
class="u-notice-bar"
:style="{
background: computeBgColor,
padding: padding
}"
>
<view class="u-direction-row">
<view class="u-icon-wrap">
<u-icon class="u-left-icon" v-if="volumeIcon" name="volume-fill" :size="volumeSize" :color="computeColor"></u-icon>
</view>
<view class="u-notice-box" id="u-notice-box">
<view
class="u-notice-content"
id="u-notice-content"
:style="{
animationDuration: animationDuration,
color: computeColor,
animationPlayState: animationPlayState,
}"
>
<text class="u-notice-text" @tap="click" :style="{
fontSize: fontSize + 'rpx',
}">{{showText}}</text>
</view>
</view>
<view class="u-icon-wrap">
<u-icon @click="getMore" class="u-right-icon" v-if="moreIcon" name="arrow-right" :size="26" :color="computeColor"></u-icon>
<u-icon @click="close" class="u-right-icon" v-if="closeIcon" name="close" :size="24" :color="computeColor"></u-icon>
</view>
</view>
</view>
</template>
<script>
export default {
props: {
//
list: {
type: Array,
default() {
return [];
}
},
// success|error|primary|info|warning|none
// none(contentColor)
type: {
type: String,
default: 'warning'
},
//
volumeIcon: {
type: Boolean,
default: true
},
//
moreIcon: {
type: Boolean,
default: false
},
//
closeIcon: {
type: Boolean,
default: false
},
//
autoplay: {
type: Boolean,
default: true
},
// 使
color: {
type: String,
default: ''
},
//
bgColor: {
type: String,
default: ''
},
//
show: {
type: Boolean,
default: true
},
// rpx
fontSize: {
type: [Number, String],
default: 26
},
//
volumeSize: {
type: [Number, String],
default: 34
},
// rpx
speed: {
type: [Number, String],
default: 160
},
// play-paused-
playState: {
type: String,
default: 'play'
},
//
padding: {
type: [Number, String],
default: '18rpx 24rpx'
}
},
data() {
return {
textWidth: 0, //
boxWidth: 0, //
animationDuration: '10s', //
animationPlayState: 'paused', //
showText: '' //
};
},
watch: {
list: {
immediate: true,
handler(val) {
this.showText = val.join('');
this.$nextTick(() => {
this.initSize();
});
}
},
playState(val) {
if(val == 'play') this.animationPlayState = 'running';
else this.animationPlayState = 'paused';
},
speed(val) {
this.initSize();
}
},
computed: {
// uview
computeColor() {
if (this.color) return this.color;
else if(this.type == 'none') return this.$u.color['contentColor'];
else return this.$u.color[this.type];
},
//
computeBgColor() {
if (this.bgColor) return this.bgColor;
else if(this.type == 'none') return 'transparent';
else return this.$u.color[this.type + 'Light'];
}
},
mounted() {
this.$nextTick(() => {
this.initSize();
});
},
methods: {
initSize() {
let query = [],
boxWidth = 0,
textWidth = 0;
let textQuery = new Promise((resolve, reject) => {
uni.createSelectorQuery()
.in(this)
.select(`#u-notice-content`)
.boundingClientRect()
.exec(ret => {
this.textWidth = ret[0].width;
resolve();
});
});
query.push(textQuery);
Promise.all(query).then(() => {
// t=s/v(=/)#u-notice-box.u-notice-contentpadding-left: 100%
// #u-notice-box
this.animationDuration = `${this.textWidth / uni.upx2px(this.speed)}s`;
// APP(HX2.4.6IOS13)
this.animationPlayState = 'paused';
setTimeout(() => {
if(this.playState == 'play' && this.autoplay) this.animationPlayState = 'running';
}, 10);
});
},
//
click(index) {
this.$emit('click');
},
//
close() {
this.$emit('close');
},
//
getMore() {
this.$emit('getMore');
}
}
};
</script>
<style lang="scss" scoped>
.u-notice-bar {
padding: 18rpx 24rpx;
overflow: hidden;
}
.u-direction-row {
display: flex;
align-items: center;
justify-content: space-between;
}
.u-left-icon {
display: inline-flex;
align-items: center;
}
.u-notice-box {
flex: 1;
display: flex;
overflow: hidden;
margin-left: 12rpx;
}
.u-right-icon {
margin-left: 12rpx;
display: inline-flex;
align-items: center;
}
.u-notice-content {
animation: u-loop-animation 10s linear infinite both;
text-align: right;
//
padding-left: 100%;
display: flex;
flex-wrap: nowrap;
}
.u-notice-text {
font-size: 26rpx;
word-break: keep-all;
white-space: nowrap
}
@keyframes u-loop-animation {
0% {
transform: translate3d(0, 0, 0);
}
100% {
transform: translate3d(-100%, 0, 0);
}
}
</style>

76
node_modules/uview-ui/components/u-row/u-row.vue generated vendored Normal file
View File

@ -0,0 +1,76 @@
<template>
<view class="u-row" :style="{
marginLeft: `-${gutter/2 + 'rpx'}`,
marginRight: `-${gutter/2 + 'rpx'}`,
alignItems: uAlignItem,
justifyContent: uJustify
}">
<slot />
</view>
</template>
<script>
/**
* row 行布局
* @description 通过基础的 12 分栏迅速简便地创建布局
* @tutorial https://www.uviewui.com/components/layout.html#row-props
* @property {String Number} gutter 栅格间隔左右各为此值的一半单位rpx默认0
* @property {String} justify 水平排列方式(微信小程序暂不支持)默认start(或flex-start)
* @property {String} align 垂直排列方式默认center
* @example <u-row gutter="16"></u-row>
*/
export default {
name: "u-row",
props: {
// col
gutter: {
type: [String, Number],
default: 20
},
// `start`(`flex-start`)`end`(`flex-end`)`center``around`(`space-around`)`between`(`space-between`)
justify: {
type: String,
default: 'start'
},
// topcenterbottom
align: {
type: String,
default: 'center'
}
},
provide() {
return {
gutter: this.gutter
}
},
computed: {
uJustify() {
if (this.justify == 'end' || this.justify == 'start') return 'flex-' + this.justify;
else if (this.justify == 'around' || this.justify == 'between') return 'space-' + this.justify;
else return this.justify;
},
uAlignItem() {
if (this.align == 'top') return 'flex-start';
if (this.align == 'bottom') return 'flex-end';
else return this.align;
}
}
}
</script>
<style lang="scss">
.u-row {
// 使floatflex
/* #ifndef MP-WEIXIN */
display: flex;
/* #endif */
}
.u-row:after {
/* #ifdef MP-WEIXIN */
display: table;
clear: both;
content: "";
/* #endif */
}
</style>

319
node_modules/uview-ui/components/u-search/u-search.vue generated vendored Normal file
View File

@ -0,0 +1,319 @@
<template>
<view class="u-search" :style="{
margin: margin,
}">
<view
class="u-content"
:style="{
backgroundColor: bgColor,
borderRadius: shape == 'round' ? '100rpx' : '10rpx',
border: borderStyle,
height: height + 'rpx'
}"
>
<view class="u-icon-wrap"><u-icon class="u-clear-icon" :size="30" name="search" :color="searchIconColor ? searchIconColor : color"></u-icon></view>
<input
confirm-type="search"
@blur="blur"
:value="value"
@confirm="search"
@input="inputChange"
:disabled="disabled"
@focus="getFocus"
:maxlength="getMaxlength"
:focus="focus"
placeholder-class="u-placeholder-class"
:placeholder="placeholder"
:placeholder-style="`color: ${placeholderColor}`"
class="u-input"
type="text"
:style="[{
textAlign: inputAlign,
color: color
}, inputStyle]"
/>
<view class="u-close-wrap" v-if="keyword && clearabled && focused" @touchstart="clear">
<u-icon class="u-clear-icon" name="close-circle-fill" size="34" color="#c0c4cc"></u-icon>
</view>
</view>
<view :style="[actionStyle]" class="u-action"
:class="[showActionBtn || show ? 'u-action-active' : '']"
@touchstart.stop.prevent="custom"
>{{ actionText }}</view>
</view>
</template>
<script>
/**
* search 搜索框
* @description 搜索组件集成了常见搜索框所需功能用户可以一键引入开箱即用
* @tutorial https://www.uviewui.com/components/search.html
* @property {String} shape 搜索框形状round-圆形square-方形默认round
* @property {String} bg-color 搜索框背景颜色默认#f2f2f2
* @property {String} border-color 边框颜色配置了颜色才会有边框
* @property {String} placeholder 占位文字内容默认请输入关键字
* @property {Boolean} clearabled 是否启用清除控件默认true
* @property {Boolean} focus 是否自动获得焦点默认false
* @property {Boolean} show-action 是否显示右侧控件默认true
* @property {String} action-text 右侧控件文字默认搜索
* @property {Object} action-style 右侧控件的样式对象形式
* @property {String} input-align 输入框内容水平对齐方式默认left
* @property {Boolean} disabled 是否启用输入框默认false
* @property {String} search-icon-color 搜索图标的颜色默认同输入框字体颜色
* @property {String} color 输入框字体颜色默认#606266
* @property {String} placeholder-color placeholder的颜色默认#909399
* @property {String} margin 组件与其他上下左右元素之间的距离带单位的字符串形式"30rpx"
* @property {Boolean} animation 是否开启动画见上方说明默认false
* @property {String} value 输入框初始值
* @property {String | Number} maxlength 输入框最大能输入的长度-1为不限制长度
* @property {Boolean} input-style input输入框的样式可以定义文字颜色大小等对象形式
* @property {String | Number} height 输入框高度单位rpx默认64
* @event {Function} change 输入框内容发生变化时触发
* @event {Function} search 用户确定搜索时触发用户按回车键或者手机键盘右下角的"搜索"键时触发
* @event {Function} custom 用户点击右侧控件时触发
* @event {Function} clear 用户点击清除按钮时触发
* @example <u-search placeholder="日照香炉生紫烟" v-model="keyword"></u-search>
*/
export default {
name: "u-search",
props: {
// round-square-
shape: {
type: String,
default: 'round'
},
// #f2f2f2
bgColor: {
type: String,
default: '#f2f2f2'
},
//
placeholder: {
type: String,
default: '请输入关键字'
},
//
clearabled: {
type: Boolean,
default: true
},
//
focus: {
type: Boolean,
default: false
},
//
showAction: {
type: Boolean,
default: true
},
//
actionStyle: {
type: Object,
default() {
return {};
}
},
//
actionText: {
type: String,
default: '搜索'
},
// left|center|right
inputAlign: {
type: String,
default: 'left'
},
//
disabled: {
type: Boolean,
default: false
},
// showActioninput
animation: {
type: Boolean,
default: false
},
//
borderColor: {
type: String,
default: 'none'
},
//
value: {
type: String,
default: ''
},
// rpx
height: {
type: [Number, String],
default: 64
},
// input
inputStyle: {
type: Object,
default() {
return {}
}
},
// -1(uniapp)
maxlength: {
type: [Number, String],
default: -1
},
//
searchIconColor: {
type: String,
default: ''
},
//
color: {
type: String,
default: '#606266'
},
// placeholder
placeholderColor: {
type: String,
default: '#909399'
},
// "30rpx""30rpx 20rpx"
margin: {
type: String,
default: '0'
}
},
data() {
return {
keyword: '',
showClear: false, //
show: false,
// input
focused: this.focus
//
// inputValue: this.value
};
},
watch: {
keyword(nVal) {
// v-model
this.$emit('input', nVal);
// changev-model
this.$emit('change', nVal);
},
value: {
immediate: true,
handler(nVal) {
this.keyword = nVal;
}
}
},
computed: {
showActionBtn() {
if (!this.animation && this.showAction) return true;
else return false;
},
// none
borderStyle() {
if (this.borderColor) return `1px solid ${this.borderColor}`;
else return 'none';
},
// maxlength
getMaxlength() {
return Number(this.maxlength);
}
},
methods: {
// HX2.6.9 v-modelinput
inputChange(e) {
this.keyword = e.detail.value;
},
//
// this.$refs
clear() {
this.keyword = '';
this.$emit('clear');
},
//
search() {
this.$emit('search', this.keyword);
//
uni.hideKeyboard();
},
//
custom() {
this.$emit('custom', this.keyword);
//
uni.hideKeyboard();
},
//
getFocus() {
this.focused = true;
//
if (this.animation && this.showAction) this.show = true;
this.$emit('focus', this.keyword);
},
//
blur() {
this.focused = false;
this.show = false;
this.$emit('blur', this.keyword);
}
}
};
</script>
<style lang="scss" scoped>
.u-search {
display: flex;
align-items: center;
flex: 1;
}
.u-content {
display: flex;
align-items: center;
padding: 0 18rpx;
flex: 1;
}
.u-clear-icon {
display: flex;
align-items: center;
}
.u-input {
flex: 1;
font-size: 28rpx;
line-height: 1;
margin: 0 10rpx;
color: $u-tips-color;
}
.u-close-wrap {
width: 40rpx;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
}
.u-placeholder-class {
color: $u-tips-color;
}
.u-action {
font-size: 28rpx;
color: $u-main-color;
width: 0;
overflow: hidden;
transition: all 0.3s;
white-space: nowrap;
text-align: center;
}
.u-action-active {
width: 80rpx;
margin-left: 10rpx;
}
</style>

View File

@ -0,0 +1,129 @@
<template>
<view class="u-section">
<view class="u-section-title" :style="{
fontWeight: bold ? 'bold' : 'normal',
color: color,
fontSize: fontSize + 'rpx',
paddingLeft: showLine ? '10rpx' : 0
}" :class="{
'u-section--line': showLine
}">
{{title}}
</view>
<view class="u-right-info" v-if="right" :style="{
color: subColor
}" @tap="rightClick">
{{subTitle}}
<view class="u-icon-arrow">
<u-icon name="arrow-right" size="24" :color="subColor"></u-icon>
</view>
</view>
</view>
</template>
<script>
/**
* section 查看更多
* @description 该组件一般用于分类信息有很多但是限于篇幅只能列出一部分让用户通过"查看更多"获得更多信息的场景实际效果见演示
* @tutorial https://www.uviewui.com/components/section.html
* @property {String} title 左边主标题
* @property {String} sub-title 右边副标题默认更多
* @property {Boolean} right 是否显示右边的内容默认true
* @property {Boolean} showLine 是否显示左边的竖条默认true
* @property {String Number} font-size 主标题的字体大小默认28
* @property {Boolean} bold 主标题是否加粗默认true
* @property {String} color 主标题颜色默认#303133
* @event {Function} click 组件右侧的内容被点击时触发用于跳转"更多"
* @example <u-section title="今日热门" :right="false"></u-section>
*/
export default {
name: "u-section",
props: {
//
title: {
type: String,
default: ''
},
//
subTitle: {
type: String,
default: '更多'
},
//
right: {
type: Boolean,
default: true
},
fontSize: {
type: [Number, String],
default: 28
},
//
bold: {
type: Boolean,
default: true
},
//
color: {
type: String,
default: '#303133'
},
//
subColor: {
type: String,
default: '#909399'
},
//
showLine: {
type: Boolean,
default: false
}
},
data() {
return {
}
},
methods: {
rightClick() {
this.$emit('click');
}
}
}
</script>
<style lang="scss" scoped>
.u-section {
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
}
.u-section-title {
position: relative;
font-size: 28rpx;
line-height: 1;
}
.u-section--line:after {
position: absolute;
width: 4px;
height: 100%;
content: '';
left: 0;
border-radius: 10px;
background-color: currentColor;
}
.u-right-info {
color: $u-tips-color;
font-size: 26rpx;
display: flex;
align-items: center;
}
.u-icon-arrow {
margin-left: 6rpx;
}
</style>

319
node_modules/uview-ui/components/u-select/u-select.vue generated vendored Normal file
View File

@ -0,0 +1,319 @@
<template>
<view class="u-select">
<!-- <view class="u-select__action" :class="{
'u-select--border': border
}" @tap.stop="selectHandler">
<view class="u-select__action__icon" :class="{
'u-select__action__icon--reverse': value == true
}">
<u-icon name="arrow-down-fill" size="26" color="#c0c4cc"></u-icon>
</view>
</view> -->
<u-popup :maskCloseAble="maskCloseAble" mode="bottom" :popup="false" v-model="value" length="auto" :safeAreaInsetBottom="safeAreaInsetBottom" @close="close" :z-index="uZIndex">
<view class="u-select">
<view class="u-select__header" @touchmove.stop.prevent="stop" catchtouchmove="stop">
<view
class="u-select__header__cancel u-select__header__btn"
:style="{ color: cancelColor }"
hover-class="u-hover-class"
:hover-stay-time="150"
@tap="getResult('cancel')"
>
取消
</view>
<view
class="u-select__header__confirm u-select__header__btn"
:style="{ color: confirmColor }"
hover-class="u-hover-class"
:hover-stay-time="150"
@touchmove.stop=""
@tap.stop="getResult('confirm')"
>
确定
</view>
</view>
<view class="u-select__body">
<picker-view @change="columnChange" class="u-select__body__picker-view" :value="defaultSelector">
<picker-view-column v-for="(item, index) in columnData" :key="index">
<view class="u-select__body__picker-view__item" v-for="(item1, index1) in item" :key="index1">
<view class="u-line-1">{{ item1.label }}</view>
</view>
</picker-view-column>
</picker-view>
</view>
</view>
</u-popup>
</view>
</template>
<script>
export default {
props: {
//
list: {
type: Array,
default() {
return [];
}
},
//
border: {
type: Boolean,
default: true
},
//
value: {
type: Boolean,
default: false
},
// ""
cancelColor: {
type: String,
default: '#606266'
},
// ""
confirmColor: {
type: String,
default: '#2979ff'
},
// z-index
zIndex: {
type: [String, Number],
default: 0
},
safeAreaInsetBottom: {
type: Boolean,
default: false
},
// Picker
maskCloseAble: {
type: Boolean,
default: true
},
//
defaultValue: {
type: Array,
default() {
return [0];
}
},
// single-column-mutil-column-mutil-column-auto-
mode: {
type: String,
default: 'single-column'
}
},
data() {
return {
//
defaultSelector: [0],
// picker-view
columnData: [],
//
selectValue: [],
// index
lastSelectIndex: [],
//
columnNum: 0,
};
},
watch: {
// select
value: {
immediate: true,
handler(val) {
if(val) setTimeout(() => this.init(), 10);
}
},
},
computed: {
uZIndex() {
// z-index使
return this.zIndex ? this.zIndex : this.$u.zIndex.popup;
},
},
methods: {
init() {
this.setColumnNum();
this.setDefaultSelector();
this.setColumnData();
this.setSelectValue();
},
//
setDefaultSelector() {
// columnNum0
this.defaultSelector = this.defaultValue.length == this.columnNum ? this.defaultValue : Array(this.columnNum).fill(0);
this.lastSelectIndex = this.$u.deepClone(this.defaultSelector);
},
//
setColumnNum() {
// 1
if(this.mode == 'single-column') this.columnNum = 1;
// this.list
else if(this.mode == 'mutil-column') this.columnNum = this.list.length;
// this.list
else if(this.mode == 'mutil-column-auto') {
let num = 1;
let column = this.list;
// children
while(column[0].children) {
column = column[0] ? column[0].children : {};
num ++;
}
this.columnNum = num;
}
},
// picker
setColumnData() {
let data = [];
this.selectValue = [];
if(this.mode == 'mutil-column-auto') {
//
let column = this.list[this.defaultSelector.length ? this.defaultSelector[0] : 0];
//
for (let i = 0; i < this.columnNum; i++) {
// list
if (i == 0) {
data[i] = this.list;
column = column.children;
} else {
//
data[i] = column;
column = column[this.defaultSelector[i]].children;
}
}
} else if(this.mode == 'single-column') {
data[0] = this.list;
} else {
data = this.list;
}
this.columnData = data;
},
// defaultValue
setSelectValue() {
for(let i = 0; i < this.columnNum; i++) {
this.selectValue.push({
value: this.columnData[i][this.defaultSelector[i]].value,
label: this.columnData[i][this.defaultSelector[i]].label,
})
}
},
//
columnChange(e) {
let index = null;
let cloumnIndex = e.detail.value;
// push
this.selectValue = [];
if(this.mode == 'mutil-column-auto') {
//
this.lastSelectIndex.map((val, idx) => {
if (val != cloumnIndex[idx]) index = idx;
});
this.defaultSelector = cloumnIndex;
for (let i = index + 1; i < this.columnNum; i++) {
// children
//
this.columnData[i] = this.columnData[i - 1][i - 1 == index ? cloumnIndex[index] : 0].children;
//
this.defaultSelector[i] = 0;
}
// this.columnDatacolumnChange
// undefined
cloumnIndex.map((item, index) => {
let data = this.columnData[index][cloumnIndex[index]];
this.selectValue.push({
value: data ? data.value : null,
label: data ? data.label : null
})
})
//
this.lastSelectIndex = cloumnIndex;
} else if(this.mode == 'single-column') {
//
this.selectValue.push({
value: this.columnData[0][cloumnIndex[0]].value,
label: this.columnData[0][cloumnIndex[0]].label,
})
} else if(this.mode == 'mutil-column') {
//
cloumnIndex.map((item, index) => {
let data = this.columnData[index][cloumnIndex[index]];
this.selectValue.push({
value: data ? data.value : null,
label: data ? data.label : null
})
})
}
},
close() {
this.$emit('input', false);
},
//
getResult(event = null) {
if (event) this.$emit(event, this.selectValue);
this.close();
},
selectHandler() {
this.$emit('click');
}
}
};
</script>
<style scoped lang="scss">
.u-select {
&__action {
position: relative;
line-height: $u-form-item-height;
height: $u-form-item-height;
&__icon {
position: absolute;
right: 20rpx;
top: 50%;
transition: transform .4s;
transform: translateY(-50%);
z-index: 1;
&--reverse {
transform: rotate(-180deg) translateY(50%);
}
}
}
&--border {
border-radius: 6rpx;
border-radius: 4px;
border: 1px solid $u-form-item-border-color;
}
&__header {
display: flex;
align-items: center;
justify-content: space-between;
height: 80rpx;
padding: 0 40rpx;
}
&__body {
width: 100%;
height: 500rpx;
overflow: hidden;
background-color: #fff;
&__picker-view {
height: 100%;
box-sizing: border-box;
&__item {
display: flex;
align-items: center;
justify-content: center;
font-size: 32rpx;
color: $u-main-color;
padding: 0 8rpx;
}
}
}
}
</style>

View File

@ -0,0 +1,165 @@
<template>
<view v-if="loading" :style="{
width: windowWinth + 'px',
height: windowHeight + 'px',
backgroundColor: bgColor,
position: 'absolute',
left: left + 'px',
top: top + 'px',
zIndex: 9998,
overflow: 'hidden'
}"
@touchmove.stop.prevent>
<view v-for="(item, index) in RectNodes" :key="$u.guid()" :class="[animation ? 'skeleton-fade' : '']" :style="{
width: item.width + 'px',
height: item.height + 'px',
backgroundColor: elColor,
position: 'absolute',
left: (item.left - left) + 'px',
top: (item.top - top) + 'px'
}"></view>
<view v-for="(item, index) in circleNodes" :key="$u.guid()" :class="animation ? 'skeleton-fade' : ''" :style="{
width: item.width + 'px',
height: item.height + 'px',
backgroundColor: elColor,
borderRadius: item.width/2 + 'px',
position: 'absolute',
left: (item.left - left) + 'px',
top: (item.top - top) + 'px'
}"></view>
<view v-for="(item, index) in filletNodes" :key="$u.guid()" :class="animation ? 'skeleton-fade' : ''" :style="{
width: item.width + 'px',
height: item.height + 'px',
backgroundColor: elColor,
borderRadius: borderRadius + 'rpx',
position: 'absolute',
left: (item.left - left) + 'px',
top: (item.top - top) + 'px'
}"></view>
</view>
</template>
<script>
/**
* skeleton 骨架屏
* @description 骨架屏一般用于页面在请求远程数据尚未完成时页面用灰色块预显示本来的页面结构给用户更好的体验
* @tutorial https://www.uviewui.com/components/skeleton.html
* @property {String} el-color 骨架块状元素的背景颜色默认#e5e5e5
* @property {String} bg-color 骨架组件背景颜色默认#ffffff
* @property {Boolean} animation 骨架块是否显示动画效果默认false
* @property {String Number} border-radius u-skeleton-fillet类名元素对应的骨架块的圆角大小单位rpx默认10
* @property {Boolean} loading 是否显示骨架组件请求完成后将此值设置为false默认true
* @example <u-skeleton :loading="true" :animation="true"></u-skeleton>
*/
export default {
name: "u-skeleton",
props: {
// rgb
elColor: {
type: String,
default: '#e5e5e5'
},
//
bgColor: {
type: String,
default: '#ffffff'
},
//
animation: {
type: Boolean,
default: false
},
// u-skeleton-fillet
borderRadius: {
type: [String, Number],
default: "10"
},
// true-false-
loading: {
type: Boolean,
default: true
}
},
data() {
return {
windowWinth: 750, //
windowHeight: 1500, //
filletNodes: [], //
circleNodes: [], //
RectNodes: [], //
top: 0,
left: 0,
}
},
methods: {
//
selecterQueryInfo() {
//
uni.createSelectorQuery().selectAll('.u-skeleton').boundingClientRect().exec((res) => {
this.windowHeight = res[0][0].height;
this.windowWinth = res[0][0].width;
this.top = res[0][0].bottom - res[0][0].height;
this.left = res[0][0].left;
});
//
this.getRectEls();
//
this.getCircleEls();
//
this.getFilletEls();
},
//
getRectEls() {
uni.createSelectorQuery().selectAll('.u-skeleton-rect').boundingClientRect().exec((res) => {
this.RectNodes = res[0];
});
},
//
getFilletEls() {
uni.createSelectorQuery().selectAll('.u-skeleton-fillet').boundingClientRect().exec((res) => {
this.filletNodes = res[0];
});
},
//
getCircleEls() {
uni.createSelectorQuery().selectAll('.u-skeleton-circle').boundingClientRect().exec((res) => {
this.circleNodes = res[0];
});
}
},
//
mounted() {
//
let systemInfo = uni.getSystemInfoSync();
this.windowHeight = systemInfo.windowHeight;
this.windowWinth = systemInfo.windowWidth;
this.selecterQueryInfo();
}
}
</script>
<style lang="scss" scoped>
.skeleton-fade {
width: 100%;
height: 100%;
background: rgb(194, 207, 214);
animation-duration: 1.5s;
animation-name: blink;
animation-timing-function: ease-in-out;
animation-iteration-count: infinite;
}
@keyframes blink {
0% {
opacity: 1;
}
50% {
opacity: 0.4;
}
100% {
opacity: 1;
}
}
</style>

252
node_modules/uview-ui/components/u-slider/u-slider.vue generated vendored Normal file
View File

@ -0,0 +1,252 @@
<template>
<view class="u-slider" @tap="onClick" :class="[disabled ? 'u-slider--disabled' : '']" :style="{
backgroundColor: inactiveColor
}">
<view
class="u-slider__gap"
:style="[
barStyle,
{
height: height + 'rpx',
backgroundColor: activeColor
}
]"
>
<view class="u-slider__button-wrap" @touchstart="onTouchStart"
@touchmove="onTouchMove" @touchend="onTouchEnd"
@touchcancel="onTouchEnd">
<slot v-if="$slots.default"/>
<view v-else class="u-slider__button" :style="[blockStyle, {
height: blockWidth + 'rpx',
width: blockWidth + 'rpx'
}]"></view>
</view>
</view>
</view>
</template>
<script>
/**
* slider 滑块选择器
* @tutorial https://uviewui.com/components/slider.html
* @property {Number | String} value 滑块默认值默认0
* @property {Number | String} min 最小值默认0
* @property {Number | String} max 最大值默认100
* @property {Number | String} step 步长默认1
* @property {Number | String} blockWidth 滑块宽度高等于宽30
* @property {Number | String} height 滑块条高度单位rpx默认6
* @property {String} inactiveColor 底部条背景颜色默认#c0c4cc
* @property {String} activeColor 底部选择部分的背景颜色默认#2979ff
* @property {String} blockColor 滑块颜色默认#ffffff
* @property {Object} blockStyle 给滑块自定义样式对象形式
* @property {Boolean} disabled 是否禁用滑块(默认为false)
* @event {Function} start 滑动触发
* @event {Function} moving 正在滑动中
* @event {Function} end 滑动结束
* @example <u-slider v-model="value" />
*/
export default {
name: 'u-slider',
props: {
// 0-100
value: {
type: [Number, String],
default: 0
},
//
disabled: {
type: Boolean,
default: false
},
// rpx
blockWidth: {
type: [Number, String],
default: 30
},
//
min: {
type: [Number, String],
default: 0
},
//
max: {
type: [Number, String],
default: 100
},
//
step: {
type: [Number, String],
default: 1
},
// rpx
height: {
type: [Number, String],
default: 6
},
//
activeColor: {
type: String,
default: '#2979ff'
},
//
inactiveColor: {
type: String,
default: '#c0c4cc'
},
//
blockColor: {
type: String,
default: '#ffffff'
},
//
blockStyle: {
type: Object,
default() {
return {};
}
},
},
data() {
return {
startX: 0,
status: 'end',
newValue: 0,
distanceX: 0,
startValue: 0,
barStyle: {},
sliderRect: {
left: 0,
width: 0
}
};
},
watch: {
value(n) {
// value
if(this.status == 'end') this.updateValue(this.value, false);
}
},
created() {
this.updateValue(this.value, false);
},
mounted() {
//
this.$uGetRect('.u-slider').then(rect => {
this.sliderRect = rect;
});
},
methods: {
onTouchStart(event) {
if (this.disabled) return;
this.startX = 0;
//
let touches = event.touches[0];
//
this.startX = touches.clientX;
// this.valueprops$emit('input')
this.startValue = this.format(this.value);
//
this.status = 'start';
},
onTouchMove(event) {
if (this.disabled) return;
//
// statusmoving
if (this.status == 'start') this.$emit('start');
let touches = event.touches[0];
//
this.distanceX = touches.clientX - this.sliderRect.left;
//
// step
this.newValue = (this.distanceX / this.sliderRect.width) * 100;
this.status = 'moving';
// moving
this.$emit('moving');
this.updateValue(this.newValue, true);
},
onTouchEnd() {
if (this.disabled) return;
if (this.status === 'moving') {
this.updateValue(this.newValue, false);
this.$emit('end');
}
this.status = 'end';
},
updateValue(value, drag) {
// step
const width = this.format(value);
//
let barStyle = {
width: width + '%'
};
//
if (drag == true) {
barStyle.transition = 'none';
} else {
// css
delete barStyle.transition;
}
// value
this.$emit('input', width);
this.barStyle = barStyle;
},
format(value) {
//
return Math.round(Math.max(this.min, Math.min(value, this.max)) / this.step) * this.step;
},
onClick(event) {
if (this.disabled) return;
// onTouchMove
const value = ((event.detail.x - this.sliderRect.left) / this.sliderRect.width) * 100;
this.updateValue(value, false);
}
}
};
</script>
<style lang="scss" scoped>
.u-slider {
position: relative;
border-radius: 999px;
border-radius: 999px;
background-color: #ebedf0;
}
.u-slider:before {
position: absolute;
right: 0;
left: 0;
content: '';
top: -8px;
bottom: -8px;
z-index: -1;
}
.u-slider__gap {
position: relative;
border-radius: inherit;
transition: width 0.2s;
transition: width 0.2s;
background-color: #1989fa;
}
.u-slider__button {
width: 24px;
height: 24px;
border-radius: 50%;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
background-color: #fff;
cursor: pointer;
}
.u-slider__button-wrap {
position: absolute;
top: 50%;
right: 0;
transform: translate3d(50%, -50%, 0);
}
.u-slider--disabled {
opacity: 0.5;
}
</style>

140
node_modules/uview-ui/components/u-steps/u-steps.vue generated vendored Normal file
View File

@ -0,0 +1,140 @@
<template>
<view class="">
<view class="u-steps">
<view class="u-steps-item" v-for="(item,index) in list" :key="index">
<view class="u-steps-item-num" v-if="mode == 'number' && current < index">{{index+1}}</view>
<view class="u-steps-item-dot" v-if="mode == 'dot'" :style="{backgroundColor: index <= current ? innerActiveColor : unActiveColor}"></view>
<u-icon size="22" class="u-steps-item-checked" :style="{backgroundColor: index <= current ? innerActiveColor : unActiveColor}"
v-if="mode == 'number' && current >= index" name="checkmark"></u-icon>
<text :style="{color: index <= current ? innerActiveColor : unActiveColor}">{{item.name}}</text>
<view class="u-steps-item-line" :style="{backgroundColor: index <= current ? innerActiveColor : unActiveColor, top: mode == 'dot' ? '24rpx' : '36rpx'}">
</view>
</view>
</view>
</view>
</template>
<script>
/**
* steps 步骤条
* @description 该组件一般用于完成一个任务要分几个步骤标识目前处于第几步的场景
* @tutorial https://www.uviewui.com/components/steps.html
* @property {String} mode 设置模式默认dot
* @property {Array} list 数轴条数据数组具体见上方示例
* @property {String} type type主题默认primary
* @property {Number String} current 设置当前处于第几步
* @property {String} active-color 已完成步骤的激活颜色如设置type值会失效
* @property {String} un-active-color 未激活的颜色用于表示未完成步骤的颜色默认#606266
* @example <u-steps :list="numList" active-color="#fa3534"></u-steps>
*/
export default {
name: "u-steps",
props: {
// dot|number
mode: {
type: String,
default: 'dot'
},
//
list: {
type: Array,
default () {
return []
}
},
// , primary|success|info|warning|error
type: {
type: String,
default: 'primary'
},
//
current: {
type: [Number, String],
default: 0
},
//
activeColor: {
type: String,
default: ''
},
//
unActiveColor: {
type: String,
default: '#606266'
}
},
data() {
return {
}
},
computed: {
innerActiveColor() {
if (this.activeColor) return this.activeColor;
else if (this.type) return this.$u.color[this.type];
else return "#2979ff";
},
}
}
</script>
<style lang="scss" scoped>
.u-steps {
display: flex;
}
.u-steps-item {
flex: 1;
text-align: center;
position: relative;
min-width: 100rpx;
font-size: 26rpx;
color: #8799a3;
}
.u-steps-item .u-steps-item-line {
content: "";
position: absolute;
height: 2rpx;
width: calc(100% - 80rpx);
left: calc(0rpx - (100% - 80rpx) / 2);
top: 36rpx;
z-index: 0;
}
.u-steps-item:first-child .u-steps-item-line {
display: none;
}
.u-steps-item-num {
display: flex;
align-items: center;
justify-content: center;
width: 44rpx;
height: 44rpx;
border: 1px solid #8799a3;
border-radius: 50%;
margin: 14rpx auto;
overflow: hidden;
}
.u-steps-item-dot {
width: 20rpx;
height: 20rpx;
display: flex;
border-radius: 50%;
margin: 14rpx auto;
}
.u-steps-item-checked {
display: flex;
align-items: center;
justify-content: center;
width: 44rpx;
color: #fff !important;
height: 44rpx;
border-radius: 50%;
margin: 14rpx auto;
overflow: hidden;
}
</style>

150
node_modules/uview-ui/components/u-sticky/u-sticky.vue generated vendored Normal file
View File

@ -0,0 +1,150 @@
<template>
<view class="">
<view class="u-sticky-wrap" :class="[elClass]" :style="{
height: fixed ? height + 'px' : 'auto',
backgroundColor: bgColor
}">
<view class="u-sticky" :style="{
position: fixed ? 'fixed' : 'static',
top: stickyTop + 'px',
left: left + 'px',
width: width == 'auto' ? 'auto' : width + 'px',
zIndex: uZIndex
}">
<slot></slot>
</view>
</view>
</view>
</template>
<script>
/**
* sticky 吸顶
* @description 该组件与CSS中position: sticky属性实现的效果一致当组件达到预设的到顶部距离时 就会固定在指定位置组件位置大于预设的顶部距离时会重新按照正常的布局排列
* @tutorial https://www.uviewui.com/components/sticky.html
* @property {String Number} offset-top 吸顶时与顶部的距离单位rpx默认0
* @property {String Number} index 自定义标识用于区分是哪一个组件
* @property {Boolean} enable 是否开启吸顶功能默认true
* @property {String} bg-color 组件背景颜色默认#ffffff
* @property {String Number} z-index 吸顶时的z-index值默认970
* @property {String Number} h5-nav-height 导航栏高度自定义导航栏时(无导航栏时需设置为0)需要传入此值单位px默认44
* @event {Function} fixed 组件吸顶时触发
* @example <u-sticky offset-top="200"><view>塞下秋来风景异衡阳雁去无留意</view></u-sticky>
*/
export default {
name: "u-sticky",
props: {
// H5NavigationBar44px
offsetTop: {
type: [Number, String],
default: 0
},
//
index: {
type: [Number, String],
default: ''
},
//
enable: {
type: Boolean,
default: true
},
// h5
h5NavHeight: {
type: [Number, String],
default: 44
},
//
bgColor: {
type: String,
default: '#ffffff'
},
// z-index
zIndex: {
type: [Number, String],
default: ''
}
},
data() {
return {
fixed: false,
height: 'auto',
stickyTop: 0,
elClass: this.$u.guid(),
left: 0,
width: 'auto',
};
},
watch: {
offsetTop(val) {
this.initObserver();
},
enable(val) {
if (val == false) {
this.fixed = false;
this.disconnectObserver('contentObserver');
} else {
this.initObserver();
}
}
},
computed: {
uZIndex() {
return this.zIndex ? this.zIndex : this.$u.zIndex.sticky;
}
},
mounted() {
this.initObserver();
},
methods: {
initObserver() {
if (!this.enable) return;
// #ifdef H5
this.stickyTop = this.offsetTop != 0 ? uni.upx2px(this.offsetTop) + this.h5NavHeight : this.h5NavHeight;
// #endif
// #ifndef H5
this.stickyTop = this.offsetTop != 0 ? uni.upx2px(this.offsetTop) : 0;
// #endif
this.disconnectObserver('contentObserver');
this.$uGetRect('.' + this.elClass).then((res) => {
this.height = res.height;
this.left = res.left;
this.width = res.width;
this.$nextTick(() => {
this.observeContent();
});
});
},
observeContent() {
this.disconnectObserver('contentObserver');
const contentObserver = this.createIntersectionObserver({
thresholds: [0.95, 0.98, 1]
});
contentObserver.relativeToViewport({
top: -this.stickyTop
});
contentObserver.observe('.' + this.elClass, res => {
if (!this.enable) return;
this.setFixed(res.boundingClientRect.top);
});
this.contentObserver = contentObserver;
},
setFixed(top) {
const fixed = top < this.stickyTop;
this.fixed = fixed;
if (fixed) this.$emit('fixed', this.index);
},
disconnectObserver(observerName) {
const observer = this[observerName];
observer && observer.disconnect();
},
}
};
</script>
<style scoped lang="scss">
.u-sticky {
z-index: 9999999999;
}
</style>

View File

@ -0,0 +1,353 @@
<template>
<view class="u-subsection" :style="[subsectionStyle]">
<view class="u-item u-line-1" :style="[itemStyle(index)]" @tap="click(index)" :class="[noBorderRight(index), 'u-item-' + index]"
v-for="(item, index) in listInfo" :key="index">
<view :style="[textStyle(index)]" class="u-item-text u-line-1">{{ item.name }}</view>
</view>
<view class="u-item-bg" :style="[itemBarStyle]"></view>
</view>
</template>
<script>
/**
* subsection 分段器
* @description 该分段器一般用于用户从几个选项中选择某一个的场景
* @tutorial https://www.uviewui.com/components/subsection.html
* @property {Array} list 选项的数组形式见上方"基本使用"
* @property {String Number} current 初始化时默认选中的选项索引值默认0
* @property {String} active-color 激活时的颜色mode为subsection时固定为白色默认#303133
* @property {String} inactive-color 未激活时字体的颜色mode为subsection时无效默认#606266
* @property {String} mode 模式选择见官网"模式选择"说明默认button
* @property {String Number} font-size 字体大小单位rpx默认28
* @property {Boolean} animation 是否开启动画效果见上方说明默认true
* @property {Boolean} bold 激活选项的字体是否加粗默认true
* @property {String} bg-color 组件背景颜色mode为button时有效默认#eeeeef
* @property {String} button-color 按钮背景颜色mode为button时有效默认#ffffff
* @event {Function} change 分段器选项发生改变时触发
* @example <u-subsection active-color="#ff9900"></u-subsection>
*/
export default {
name: "u-subsection",
props: {
// tab
list: {
type: Array,
default () {
return [];
}
},
// tabindex
current: {
type: [Number, String],
default: 0
},
//
activeColor: {
type: String,
default: '#303133'
},
//
inactiveColor: {
type: String,
default: '#606266'
},
// mode=buttonmode=subsection
mode: {
type: String,
default: 'button'
},
// rpx
fontSize: {
type: [Number, String],
default: 28
},
//
animation: {
type: Boolean,
default: true
},
// rpx
height: {
type: [Number, String],
default: 70
},
// tab
bold: {
type: Boolean,
default: true
},
// mode=button
bgColor: {
type: String,
default: '#eeeeef'
},
// mode = button
buttonColor: {
type: String,
default: '#ffffff'
},
//
vibrateShort: {
type: Boolean,
default: false
}
},
data() {
return {
listInfo: [],
itemBgStyle: {
width: 0,
left: 0,
backgroundColor: '#ffffff',
height: '100%',
transition: ''
},
currentIndex: this.current,
buttonPadding: 3, // mode = button
borderRadius: 5, //
firstTimeVibrateShort: true // current
};
},
watch: {
current: {
immediate: true,
handler(nVal) {
this.currentIndex = nVal;
this.changeSectionStatus(nVal);
}
}
},
created() {
// listlistInfopropslist
// ['', ''],[{name: ''}, {name: ''}]
this.listInfo = this.list.map((val, index) => {
if (typeof val != 'object') {
let obj = {
width: 0,
name: val
};
return obj;
} else {
val.width = 0;
return val;
}
});
},
computed: {
// mode=subsection
noBorderRight() {
return index => {
if (this.mode != 'subsection') return;
let classs = '';
//
if (index < this.list.length - 1) classs += ' u-none-border-right';
//
if (index == 0) classs += ' u-item-first';
if (index == this.list.length - 1) classs += ' u-item-last';
return classs;
};
},
//
textStyle() {
return index => {
let style = {};
//
if (this.mode == 'subsection') {
if (index == this.currentIndex) {
style.color = '#ffffff';
} else {
style.color = this.activeColor;
}
} else {
if (index == this.currentIndex) {
style.color = this.activeColor;
} else {
style.color = this.inactiveColor;
}
}
//
if (index == this.currentIndex && this.bold) style.fontWeight = 'bold';
//
style.fontSize = this.fontSize + 'rpx';
return style;
};
},
// item
itemStyle() {
return index => {
let style = {};
if (this.mode == 'subsection') {
// border
style.borderColor = this.activeColor;
style.borderWidth = '1px';
style.borderStyle = 'solid';
}
return style;
};
},
// mode=buttonview
subsectionStyle() {
let style = {};
style.height = uni.upx2px(this.height) + 'px';
if (this.mode == 'button') {
style.backgroundColor = this.bgColor;
style.padding = `${this.buttonPadding}px`;
style.borderRadius = `${this.borderRadius}px`;
}
return style;
},
//
itemBarStyle() {
let style = {};
style.backgroundColor = this.activeColor;
style.zIndex = 1;
if (this.mode == 'button') {
style.backgroundColor = this.buttonColor;
style.borderRadius = `${this.borderRadius}px`;
style.bottom = `${this.buttonPadding}px`;
style.height = uni.upx2px(this.height) - this.buttonPadding * 2 + 'px';
style.zIndex = 0;
}
return Object.assign(this.itemBgStyle, style);
}
},
mounted() {
setTimeout(() => {
this.getTabsInfo();
}, 10);
},
methods: {
//
changeSectionStatus(nVal) {
if (this.mode == 'subsection') {
//
if (nVal == this.list.length - 1) {
this.itemBgStyle.borderRadius = `0 ${this.buttonPadding}px ${this.buttonPadding}px 0`;
}
if (nVal == 0) {
this.itemBgStyle.borderRadius = `${this.buttonPadding}px 0 0 ${this.buttonPadding}px`;
}
if (nVal > 0 && nVal < this.list.length - 1) {
this.itemBgStyle.borderRadius = '0';
}
}
//
setTimeout(() => {
this.itemBgLeft();
}, 10);
if (this.vibrateShort && !this.firstTimeVibrateShort) {
// 使APP(HX 2.6.8)H5
// #ifndef H5
uni.vibrateShort();
// #endif
}
// firstTimeVibrateShortfalse()
this.firstTimeVibrateShort = false;
},
click(index) {
//
if (index == this.currentIndex) return;
this.currentIndex = index;
this.changeSectionStatus(index);
this.$emit('change', Number(index));
},
// tab
getTabsInfo() {
let view = uni.createSelectorQuery().in(this);
for (let i = 0; i < this.list.length; i++) {
view.select('.u-item-' + i).boundingClientRect();
}
view.exec(res => {
if (!res.length) {
setTimeout(() => {
this.getTabsInfo();
return;
}, 10);
}
// itemlistInfo
res.map((val, index) => {
this.listInfo[index].width = val.width;
});
//
if (this.mode == 'subsection') {
this.itemBgStyle.width = this.listInfo[0].width + 'px';
} else if (this.mode == 'button') {
this.itemBgStyle.width = this.listInfo[0].width + 'px';
}
//
this.itemBgLeft();
});
},
itemBgLeft() {
//
if (this.animation) {
this.itemBgStyle.transition = 'all 0.35s';
} else {
this.itemBgStyle.transition = 'all 0s';
}
let left = 0;
// item
this.listInfo.map((val, index) => {
if (index < this.currentIndex) left += val.width;
});
// mode
if (this.mode == 'subsection') {
this.itemBgStyle.left = left + 'px';
} else if (this.mode == 'button') {
this.itemBgStyle.left = left + this.buttonPadding + 'px';
}
}
}
};
</script>
<style lang="scss" scoped>
.u-subsection {
display: flex;
align-items: center;
overflow: hidden;
position: relative;
}
.u-item {
flex: 1;
text-align: center;
font-size: 26rpx;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
color: $u-main-color;
display: inline-flex;
padding: 0 6rpx;
}
.u-item-bg {
background-color: $u-type-primary;
position: absolute;
z-index: -1;
}
.u-none-border-right {
border-right: none !important;
}
.u-item-first {
border-top-left-radius: 8rpx;
border-bottom-left-radius: 8rpx;
}
.u-item-last {
border-top-right-radius: 8rpx;
border-bottom-right-radius: 8rpx;
}
.u-item-text {
transition: all 0.35s;
color: $u-main-color;
display: flex;
align-items: center;
position: relative;
z-index: 99;
}
</style>

View File

@ -0,0 +1,251 @@
<template>
<movable-area class="u-swipe-action" :style="{ backgroundColor: bgColor }">
<movable-view
class="u-swipe-view"
@change="change"
@touchend="touchend"
@touchstart="touchstart"
direction="horizontal"
:disabled="disabled"
:x="moveX"
:style="{
width: movableViewWidth ? movableViewWidth : '100%'
}"
>
<view
class="u-swipe-content"
@tap.stop="contentClick"
>
<slot></slot>
</view>
<view class="u-swipe-del" v-if="showBtn" @tap.stop="btnClick(index)" :style="[btnStyle(item.style)]" v-for="(item, index) in options" :key="index">
<view class="u-btn-text">{{ item.text }}</view>
</view>
</movable-view>
</movable-area>
</template>
<script>
/**
* swipeAction 左滑单元格
* @description 该组件一般用于左滑唤出操作菜单的场景用的最多的是左滑删除操作
* @tutorial https://www.uviewui.com/components/swipeAction.html
* @property {String} bg-color 整个组件背景颜色默认#ffffff
* @property {Array} options 数组形式可以配置背景颜色和文字
* @property {String Number} index 标识符点击时候用于区分点击了哪一个用v-for循环时的index即可
* @property {String Number} btn-width 按钮宽度单位rpx默认180
* @property {Boolean} disabled 是否禁止某个swipeAction滑动默认false
* @property {Boolean} show 打开或者关闭某个组件默认false
* @event {Function} click 点击组件时触发
* @event {Function} close 组件触发关闭状态时
* @event {Function} content-click 点击内容时触发
* @event {Function} open 组件触发打开状态时
* @example <u-swipe-action btn-text="收藏">...</u-swipe-action>
*/
export default {
name: 'u-swipe-action',
props: {
// index
index: {
type: [Number, String],
default: ''
},
// rpx
btnWidth: {
type: [String, Number],
default: 180
},
// action
disabled: {
type: Boolean,
default: false
},
//
show: {
type: Boolean,
default: false
},
//
bgColor: {
type: String,
default: '#ffffff'
},
// 使iOS(2020-05-06)
vibrateShort: {
type: Boolean,
default: false
},
//
options: {
type: Array,
default() {
return [];
}
}
},
watch: {
show: {
immediate: true,
handler(nVal, oVal) {
if (nVal) {
this.open();
} else {
this.close();
}
}
}
},
data() {
return {
moveX: 0, // movable-viewx
scrollX: 0, // movable-viewchangex
status: false, //
movableAreaWidth: 0, //
elId: this.$u.guid(), // id
showBtn: false, //
};
},
computed: {
movableViewWidth() {
return this.movableAreaWidth + this.allBtnWidth + 'px';
},
innerBtnWidth() {
return uni.upx2px(this.btnWidth);
},
allBtnWidth() {
return uni.upx2px(this.btnWidth) * this.options.length;
},
btnStyle() {
return style => {
let css = {};
style.width = this.btnWidth + 'rpx';
return style;
};
}
},
mounted() {
this.getActionRect();
// ""
setTimeout(() => {
this.showBtn = true;
}, 10);
},
methods: {
//
btnClick(index) {
this.status = false;
// this.indexindex(options)
this.$emit('click', this.index, index);
},
// movable-view
change(e) {
this.scrollX = e.detail.x;
},
//
close() {
this.moveX = 0;
this.status = false;
},
//
open() {
if (this.disabled) return;
this.moveX = -this.allBtnWidth;
this.status = true;
},
// movable-view
touchend() {
this.moveX = this.scrollX;
//
//
// this.moveX
// propsmovable-view
// https://uniapp.dcloud.io/use?id=%e5%b8%b8%e8%a7%81%e9%97%ae%e9%a2%98
this.$nextTick(function() {
if (this.status == false) {
// x
if (this.scrollX <= -this.allBtnWidth / 4) {
this.moveX = -this.allBtnWidth; // movable-view
this.status = true; //
this.emitOpenEvent();
//
if (this.vibrateShort) uni.vibrateShort();
} else {
this.moveX = 0; //
this.status = false;
this.emitCloseEvent();
}
} else {
// X()
if (this.scrollX > (-this.allBtnWidth * 3) / 4) {
this.moveX = 0;
this.$nextTick(() => {
this.moveX = 101;
});
this.status = false;
this.emitCloseEvent();
} else {
this.moveX = -this.allBtnWidth;
this.status = true;
this.emitOpenEvent();
}
}
});
},
emitOpenEvent() {
this.$emit('open', this.index);
},
emitCloseEvent() {
this.$emit('close', this.index);
},
//
touchstart() {},
getActionRect() {
this.$uGetRect('.u-swipe-action').then(res => {
this.movableAreaWidth = res.width;
});
},
//
contentClick() {
//
if (this.status == true) {
this.status = 'close';
this.moveX = 0;
}
this.$emit('content-click', this.index);
}
}
};
</script>
<style scoped lang="scss">
.u-swipe-action {
width: auto;
height: initial;
position: relative;
overflow: hidden;
}
.u-swipe-view {
display: flex;
height: initial;
position: relative;
/* 这一句很关键,覆盖默认的绝对定位 */
}
.u-swipe-content {
flex: 1;
}
.u-swipe-del {
position: relative;
font-size: 30rpx;
color: #ffffff;
}
.u-btn-text {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
</style>

312
node_modules/uview-ui/components/u-swiper/u-swiper.vue generated vendored Normal file
View File

@ -0,0 +1,312 @@
<template>
<view class="u-swiper-wrap" :style="{
borderRadius: `${borderRadius}rpx`
}">
<swiper @change="change" @animationfinish="animationfinish" :interval="interval" :circular="circular" :duration="duration" :autoplay="autoplay"
:previous-margin="effect3d ? effect3dPreviousMargin + 'rpx' : '0'" :next-margin="effect3d ? effect3dPreviousMargin + 'rpx' : '0'"
:style="{
height: height + 'rpx'
}">
<swiper-item class="u-swiper-item" v-for="(item, index) in list" :key="index" @tap="listClick(index)">
<view class="u-list-image-wrap" :class="[current != index ? 'u-list-scale' : '']" :style="{
borderRadius: `${borderRadius}rpx`,
transform: effect3d && current != index ? 'scaleY(0.9)' : 'scaleY(1)',
margin: effect3d && current != index ? '0 20rpx' : 0,
backgroundColor: bgColor
}">
<image class="u-swiper-image" :src="item[name]" :mode="imgMode"></image>
<view v-if="title" class="u-swiper-title u-line-1" :style="{
'padding-bottom': titlePaddingBottom
}">
{{ item.title }}
</view>
</view>
</swiper-item>
</swiper>
<view class="u-swiper-indicator" :style="{
top: indicatorPos == 'topLeft' || indicatorPos == 'topCenter' || indicatorPos == 'topRight' ? '12rpx' : 'auto',
bottom: indicatorPos == 'bottomLeft' || indicatorPos == 'bottomCenter' || indicatorPos == 'bottomRight' ? '12rpx' : 'auto',
justifyContent: justifyContent,
padding: `0 ${effect3d ? '74rpx' : '24rpx'}`
}">
<block v-if="mode == 'rect'">
<view class="u-indicator-item-rect" :class="{ 'u-indicator-item-rect-active': index == current }" v-for="(item, index) in list"
:key="index"></view>
</block>
<block v-if="mode == 'dot'">
<view class="u-indicator-item-dot" :class="{ 'u-indicator-item-dot-active': index == current }" v-for="(item, index) in list"
:key="index"></view>
</block>
<block v-if="mode == 'round'">
<view class="u-indicator-item-round" :class="{ 'u-indicator-item-round-active': index == current }" v-for="(item, index) in list"
:key="index"></view>
</block>
<block v-if="mode == 'number'">
<view class="u-indicator-item-number">{{ current + 1 }}/{{ list.length }}</view>
</block>
</view>
</view>
</template>
<script>
/**
* swiper 轮播图
* @description 该组件一般用于导航轮播广告展示等场景,可开箱即用
* @tutorial https://www.uviewui.com/components/swiper.html
* @property {Array} list 轮播图数据见官网"基本使用"说明
* @property {Boolean} title 是否显示标题文字需要配合list参数见官网说明默认false
* @property {String} mode 指示器模式见官网说明默认round
* @property {String Number} height 轮播图组件高度单位rpx默认250
* @property {String} indicator-pos 指示器的位置默认bottomCenter
* @property {Boolean} effect3d 是否开启3D效果默认false
* @property {Boolean} autoplay 是否自动播放默认true
* @property {String Number} interval 自动轮播时间间隔单位ms默认2500
* @property {Boolean} circular 是否衔接播放见官网说明默认true
* @property {String} bg-color 背景颜色默认#f3f4f6
* @property {String Number} border-radius 轮播图圆角值单位rpx默认8
* @property {Object} title-style 自定义标题样式
* @property {String Number} effect3d-previous-margin mode = true模式的情况下激活项与前后项之间的距离单位rpx默认50
* @property {String} img-mode 图片的裁剪模式详见image组件裁剪模式默认aspectFill
* @event {Function} click 点击轮播图时触发
* @example <u-swiper :list="list" mode="dot" indicator-pos="bottomRight"></u-swiper>
*/
export default {
name: "u-swiper",
props: {
// ,[{image: 'xxxx', title: 'xxxx'}{image: 'yyyy', title: 'yyyy'}]title
list: {
type: Array,
default () {
return [];
}
},
// title
title: {
type: Boolean,
default: false
},
//
indicator: {
type: Object,
default () {
return {};
}
},
//
borderRadius: {
type: [Number, String],
default: 8
},
//
interval: {
type: [String, Number],
default: 3000
},
// rect|dot|number|round
mode: {
type: String,
default: 'round'
},
// listrpx
height: {
type: [Number, String],
default: 250
},
// topLeft|topCenter|topRight|bottomLeft|bottomCenter|bottomRight
indicatorPos: {
type: String,
default: 'bottomCenter'
},
//
effect3d: {
type: Boolean,
default: false
},
// 3Ditemitemrpx
effect3dPreviousMargin: {
type: [Number, String],
default: 50
},
//
autoplay: {
type: Boolean,
default: true
},
// ms
duration: {
type: [Number, String],
default: 500
},
//
circular: {
type: Boolean,
default: true
},
//
imgMode: {
type: String,
default: 'aspectFill'
},
// list
name: {
type: String,
default: 'image'
},
//
bgColor: {
type: String,
default: '#f3f4f6'
}
},
watch: {
// listcurrent
list(nVal, oVal) {
if(nVal.length !== oVal.length) this.current = 0;
}
},
data() {
return {
current: 0 // swiper-itemindex
};
},
computed: {
justifyContent() {
if (this.indicatorPos == 'topLeft' || this.indicatorPos == 'bottomLeft') return 'flex-start';
if (this.indicatorPos == 'topCenter' || this.indicatorPos == 'bottomCenter') return 'center';
if (this.indicatorPos == 'topRight' || this.indicatorPos == 'bottomRight') return 'flex-end';
},
titlePaddingBottom() {
let tmp = 0;
if (this.mode == 'none') return '12rpx';
if (['bottomLeft', 'bottomCenter', 'bottomRight'].indexOf(this.indicatorPos) >= 0 && this.mode == 'number') {
tmp = '60rpx';
} else if (['bottomLeft', 'bottomCenter', 'bottomRight'].indexOf(this.indicatorPos) >= 0 && this.mode != 'number') {
tmp = '40rpx';
} else {
tmp = '12rpx';
}
return tmp;
}
},
methods: {
listClick(index) {
this.$emit('click', index);
},
change(e) {
this.current = e.detail.current;
},
// animationfinishchange
// swipercurrent
animationfinish(e) {
// #ifndef MP-TOUTIAO
// this.current = e.detail.current;
// #endif
}
}
};
</script>
<style lang="scss" scoped>
.u-swiper-wrap {
position: relative;
overflow: hidden;
transform: translateY(0);
}
.u-swiper-image {
width: 100%;
will-change: transform;
height: 100%;
display: block;
/* #ifdef H5 */
pointer-events: none;
/* #endif */
}
.u-swiper-indicator {
padding: 0 24rpx;
position: absolute;
display: flex;
width: 100%;
z-index: 1;
}
.u-indicator-item-rect {
width: 26rpx;
height: 8rpx;
margin: 0 6rpx;
transition: all 0.5s;
background-color: rgba(0, 0, 0, 0.3);
}
.u-indicator-item-rect-active {
background-color: rgba(255, 255, 255, 0.8);
}
.u-indicator-item-dot {
width: 14rpx;
height: 14rpx;
margin: 0 6rpx;
border-radius: 20rpx;
transition: all 0.5s;
background-color: rgba(0, 0, 0, 0.3);
}
.u-indicator-item-dot-active {
background-color: rgba(255, 255, 255, 0.8);
}
.u-indicator-item-round {
width: 14rpx;
height: 14rpx;
margin: 0 6rpx;
border-radius: 20rpx;
transition: all 0.5s;
background-color: rgba(0, 0, 0, 0.3);
}
.u-indicator-item-round-active {
width: 34rpx;
background-color: rgba(255, 255, 255, 0.8);
}
.u-indicator-item-number {
padding: 6rpx 16rpx;
line-height: 1;
background-color: rgba(0, 0, 0, 0.3);
border-radius: 100rpx;
font-size: 26rpx;
color: rgba(255, 255, 255, 0.8);
}
.u-list-scale {
transform-origin: center center;
}
.u-list-image-wrap {
width: 100%;
height: 100%;
flex: 1;
transition: all 0.5s;
overflow: hidden;
box-sizing: content-box;
position: relative;
}
.u-swiper-title {
position: absolute;
background-color: rgba(0, 0, 0, 0.3);
bottom: 0;
left: 0;
width: 100%;
font-size: 28rpx;
padding: 12rpx 24rpx;
color: rgba(255, 255, 255, 0.9);
}
.u-swiper-item {
display: flex;
overflow: hidden;
align-items: center;
}
</style>

174
node_modules/uview-ui/components/u-switch/u-switch.vue generated vendored Normal file
View File

@ -0,0 +1,174 @@
<template>
<view class="u-switch" :class="[value == true ? 'u-switch--on' : '', disabled ? 'u-switch--disabled' : '']" @tap="onClick"
:style="[switchStyle]">
<view class="u-switch__node node-class">
<u-loading :show="loading" class="u-switch__loading" :size="size * 0.6" :color="loadingColor" />
</view>
</view>
</template>
<script>
/**
* switch 开关选择器
* @description 选择开关一般用于只有两个选择且只能选其一的场景
* @tutorial https://www.uviewui.com/components/switch.html
* @property {Boolean} loading 是否处于加载中默认false
* @property {Boolean} disabled 是否禁用默认false
* @property {String Number} size 开关尺寸单位rpx默认50
* @property {String} active-color 打开时的背景色默认#2979ff
* @property {Boolean} inactive-color 关闭时的背景色默认#ffffff
* @property {Boolean | Number | String} active-value 打开选择器时通过change事件发出的值默认true
* @property {Boolean | Number | String} inactive-value 关闭选择器时通过change事件发出的值默认false
* @event {Function} change 在switch打开或关闭时触发
* @example <u-switch v-model="checked" active-color="red" inactive-color="#eee"></u-switch>
*/
export default {
name: "u-switch",
props: {
//
loading: {
type: Boolean,
default: false
},
//
disabled: {
type: Boolean,
default: false
},
// rpx
size: {
type: [Number, String],
default: 50
},
//
activeColor: {
type: String,
default: '#2979ff'
},
//
inactiveColor: {
type: String,
default: '#ffffff'
},
// v-model
value: {
type: Boolean,
default: false
},
// 使iOS(2020-05-06)
vibrateShort: {
type: Boolean,
default: false
},
//
activeValue: {
type: [Number, String, Boolean],
default: true
},
//
inactiveValue: {
type: [Number, String, Boolean],
default: false
},
},
data() {
return {
}
},
computed: {
switchStyle() {
let style = {};
style.fontSize = this.size + 'rpx';
style.backgroundColor = this.value ? this.activeColor : this.inactiveColor;
return style;
},
loadingColor() {
return this.value ? this.activeColor : null;
}
},
methods: {
onClick() {
if (!this.disabled && !this.loading) {
// 使APP(HX 2.6.8)H5
if(this.vibrateShort) uni.vibrateShort();
this.$emit('input', !this.value);
// value
this.$nextTick(() => {
this.$emit('change', this.value ? this.activeValue : this.inactiveValue);
})
}
}
}
};
</script>
<style lang="scss" scoped>
.u-switch {
position: relative;
display: inline-block;
box-sizing: initial;
width: 2em;
width: var(--switch-width, 2em);
height: 1em;
height: var(--switch-height, 1em);
background-color: #fff;
background-color: var(--switch-background-color, #fff);
border: 1px solid rgba(0, 0, 0, 0.1);
border: var(--switch-border, 1px solid rgba(0, 0, 0, 0.1));
border-radius: 1em;
border-radius: var(--switch-node-size, 1em);
transition: background-color 0.3s;
transition: background-color var(--switch-transition-duration, 0.3s);
}
.u-switch__node {
display: flex;
align-items: center;
justify-content: center;
position: absolute;
top: 0;
left: 0;
border-radius: 100%;
z-index: 1;
z-index: var(--switch-node-z-index, 1);
width: 1em;
width: var(--switch-node-size, 1em);
height: 1em;
height: var(--switch-node-size, 1em);
background-color: #fff;
background-color: var(--switch-node-background-color, #fff);
box-shadow: 0 3px 1px 0 rgba(0, 0, 0, 0.05), 0 2px 2px 0 rgba(0, 0, 0, 0.1), 0 3px 3px 0 rgba(0, 0, 0, 0.05);
box-shadow: var(--switch-node-box-shadow, 0 3px 1px 0 rgba(0, 0, 0, 0.05), 0 2px 2px 0 rgba(0, 0, 0, 0.1), 0 3px 3px 0 rgba(0, 0, 0, 0.05));
transition: -webkit-transform 0.3s cubic-bezier(0.3, 1.05, 0.4, 1.05);
transition: transform 0.3s cubic-bezier(0.3, 1.05, 0.4, 1.05);
transition: transform 0.3s cubic-bezier(0.3, 1.05, 0.4, 1.05), -webkit-transform 0.3s cubic-bezier(0.3, 1.05, 0.4, 1.05);
transition: -webkit-transform var(--switch-transition-duration, 0.3s) cubic-bezier(0.3, 1.05, 0.4, 1.05);
transition: transform var(--switch-transition-duration, 0.3s) cubic-bezier(0.3, 1.05, 0.4, 1.05);
transition: transform var(--switch-transition-duration, 0.3s) cubic-bezier(0.3, 1.05, 0.4, 1.05),
-webkit-transform var(--switch-transition-duration, 0.3s) cubic-bezier(0.3, 1.05, 0.4, 1.05);
}
.u-switch__loading {
display: flex;
align-items: center;
justify-content: center;
}
.u-switch--on {
background-color: #1989fa;
background-color: var(--switch-on-background-color, #1989fa);
}
.u-switch--on .u-switch__node {
-webkit-transform: translateX(1em);
transform: translateX(1em);
-webkit-transform: translateX(calc(var(--switch-width, 2em) - var(--switch-node-size, 1em)));
transform: translateX(calc(var(--switch-width, 2em) - var(--switch-node-size, 1em)));
}
.u-switch--disabled {
opacity: 0.4;
opacity: var(--switch-disabled-opacity, 0.4);
}
</style>

92
node_modules/uview-ui/components/u-table/u-table.vue generated vendored Normal file
View File

@ -0,0 +1,92 @@
<template>
<view class="u-table" :style="[tableStyle]">
<slot />
</view>
</template>
<script>
/**
* table 表格
* @description 表格组件一般用于展示大量结构化数据的场景
* @tutorial https://www.uviewui.com/components/table.html
* @property {String} border-color 表格边框的颜色默认#e4e7ed
* @property {String} bg-color 表格的背景颜色默认#ffffff
* @property {String} align 单元格的内容对齐方式作用类似css的text-align默认center
* @property {String} padding 单元格的内边距同css的padding写法默认10rpx 0
* @property {String Number} font-size 单元格字体大小单位rpx默认28
* @property {String} color 单元格字体颜色默认#606266
* @property {Object} th-style th单元格的样式对象形式(将th所需参数放在table组件是为了避免每一个th组件要写一遍
* @event {Function} click 点击组件时触发
* @event {Function} close 点击关闭按钮时触发
* @example <u-table></u-table>
*/
export default {
name: "u-table",
props: {
borderColor: {
type: String,
default: '#e4e7ed'
},
align: {
type: String,
default: 'center'
},
// td
padding: {
type: String,
default: '10rpx 6rpx'
},
//
fontSize: {
type: [String, Number],
default: 28
},
//
color: {
type: String,
default: '#606266'
},
// th
thStyle: {
type: Object,
default () {
return {}
}
},
// table
bgColor: {
type: String,
default: '#ffffff'
}
},
provide() {
return {
uTable: this,
uTd: this
};
},
data() {
return {}
},
computed: {
tableStyle() {
let style = {};
style.borderLeft = `solid 1px ${this.borderColor}`;
style.borderTop = `solid 1px ${this.borderColor}`;
style.backgroundColor = this.bgColor;;
return style;
}
}
}
</script>
<style lang="scss" scoped>
.u-table {
width: 100%;
box-sizing: border-box;
}
.u-table /deep/ t-tr {
display: flex;
}
</style>

View File

@ -0,0 +1,473 @@
<template>
<view class="u-tabs" :style="{
zIndex: zIndex,
background: bgColor
}">
<scroll-view scroll-x class="u-scroll-view" :scroll-left="scrollLeft" scroll-with-animation :style="{ zIndex: zIndex + 1 }">
<view class="u-tabs-scroll-box" :class="{'u-tabs-scorll-flex': !isScroll}">
<view class="u-tabs-item" :style="[tabItemStyle(index)]"
v-for="(item, index) in getTabs" :key="index" :class="[preId + index]" @tap="emit(index)">
{{ item[name] || item['name']}}
</view>
<view v-if="showBar" class="u-scroll-bar" :style="[tabBarStyle]"></view>
</view>
</scroll-view>
</view>
</template>
<script>
import colorGradient from '../../libs/function/colorGradient';
let color = colorGradient;
const {
windowWidth
} = uni.getSystemInfoSync();
const preId = 'UEl_';
/**
* tabsSwiper 全屏选项卡
* @description 该组件内部实现主要依托于uniapp的scroll-view和swiper组件主要特色是切换过程中tabsSwiper文字的颜色可以渐变底部滑块可以 跟随式滑动活动tab滚动居中等应用场景可以用于需要左右切换页面比如商城的订单中心(待收货-待付款-待评价-已退货)等应用场景
* @tutorial https://www.uviewui.com/components/tabsSwiper.html
* @property {Boolean} is-scroll tabs是否可以左右拖动默认true
* @property {Array} list 标签数组元素为对象[{name: '推荐'}]
* @property {String Number} current 指定哪个tab为激活状态默认0
* @property {String Number} height 导航栏的高度单位rpx默认80
* @property {String Number} font-size tab文字大小单位rpx默认30
* @property {String Number} swiper-width tabs组件外部swiper的宽度默认为屏幕宽度单位rpx默认750
* @property {String} active-color 滑块和激活tab文字的颜色默认#2979ff
* @property {String} inactive-color tabs文字颜色默认#303133
* @property {String Number} bar-width 滑块宽度单位rpx默认40
* @property {String Number} bar-height 滑块高度单位rpx默认6
* @property {Object} bar-style 底部滑块的样式对象形式
* @property {Object} active-item-style 活动tabs item的样式对象形式
* @property {Boolean} show-bar 是否显示底部的滑块默认true
* @property {String Number} gutter 单个tab标签的左右内边距之和单位rpx默认40
* @property {String} bg-color tabs导航栏的背景颜色默认#ffffff
* @property {String} name 组件内部读取的list参数中的属性名见官网说明默认name
* @property {Boolean} bold 激活选项的字体是否加粗默认true
* @event {Function} change 点击标签时触发
* @example <u-tabs-swiper ref="tabs" :list="list" :is-scroll="false"></u-tabs-swiper>
*/
export default {
name: "u-tabs-swiper",
props: {
// 23使flextab
isScroll: {
type: Boolean,
default: true
},
//
list: {
type: Array,
default () {
return [];
}
},
// tab
current: {
type: [Number, String],
default: 0
},
// rpx
height: {
type: [Number, String],
default: 80
},
// rpx
fontSize: {
type: [Number, String],
default: 30
},
// , s
// duration: {
// type: [Number, String],
// default: 0.5
// },
swiperWidth: {
//line3, swiper, rpx
type: [String, Number],
default: 750
},
//
activeColor: {
type: String,
default: '#2979ff'
},
//
inactiveColor: {
type: String,
default: '#303133'
},
// barrpx
barWidth: {
type: [Number, String],
default: 40
},
// bar
barHeight: {
type: [Number, String],
default: 6
},
// tabrpx
gutter: {
type: [Number, String],
default: 40
},
// z-index
zIndex: {
type: [Number, String],
default: 1
},
//
bgColor: {
type: String,
default: '#ffffff'
},
//
autoCenterMode: {
type: String,
default: 'window'
},
//
name: {
type: String,
default: 'name'
},
// tab
bold: {
type: Boolean,
default: true
},
// tab item
activeItemStyle: {
type: Object,
default() {
return {}
}
},
//
showBar: {
type: Boolean,
default: true
},
//
barStyle: {
type: Object,
default() {
return {}
}
}
},
data() {
return {
scrollLeft: 0, // scroll-view
tabQueryInfo: [], // tab
windowWidth: 0, // px
//scrollBarLeft: 0, // bartranslateX()
animationFinishCurrent: this.current,
componentsWidth: 0,
line3AddDx: 0,
line3Dx: 0,
preId,
sW: 0,
tabsInfo: [],
colorGradientArr: [],
colorStep: 100 //
};
},
computed: {
// current
getCurrent() {
const current = Number(this.current);
//
if (current > this.getTabs.length - 1) {
return this.getTabs.length - 1;
}
if (current < 0) return 0;
return current;
},
getTabs() {
return this.list;
},
//
scrollBarLeft() {
return Number(this.line3Dx) + Number(this.line3AddDx);
},
// px
barWidthPx() {
return uni.upx2px(this.barWidth);
},
// tab
tabItemStyle() {
return (index) => {
let style = {
height: this.height + 'rpx',
lineHeight: this.height + 'rpx',
padding: `0 ${this.gutter / 2}rpx`,
color: this.tabsInfo.length > 0 ? (this.tabsInfo[index] ? this.tabsInfo[index].color : this.activeColor) : this.inactiveColor,
fontSize: this.fontSize + 'rpx',
zIndex: this.zIndex + 2,
fontWeight: (index == this.getCurrent && this.bold) ? 'bold' : 'normal'
};
if(index == this.getCurrent) {
// tab item
style = Object.assign(style, this.activeItemStyle);
}
return style;
}
},
//
tabBarStyle() {
let style = {
width: this.barWidthPx + 'px',
height: this.barHeight + 'rpx',
borderRadius: '100px',
backgroundColor: this.activeColor,
left: this.scrollBarLeft + 'px'
};
return Object.assign(style, this.barStyle);
}
},
watch: {
current(n, o) {
this.change(n);
this.setFinishCurrent(n);
},
list() {
this.$nextTick(() => {
this.init();
})
}
},
mounted() {
this.init();
},
methods: {
async init() {
this.countPx();
await this.getTabsInfo();
this.countLine3Dx();
this.getQuery(() => {
this.setScrollViewToCenter();
});
//
this.colorGradientArr = color.colorGradient(this.inactiveColor, this.activeColor, this.colorStep);
},
// tab
getTabsInfo() {
return new Promise((resolve, reject) => {
let view = uni.createSelectorQuery().in(this);
for (let i = 0; i < this.list.length; i++) {
view.select('.' + preId + i).boundingClientRect();
}
view.exec(res => {
const arr = [];
for (let i = 0; i < res.length; i++) {
// tab
res[i].color = this.inactiveColor;
// tabactiveColor
if (i == this.getCurrent) res[i].color = this.activeColor;
arr.push(res[i]);
}
this.tabsInfo = arr;
resolve();
});
})
},
// swiper
countLine3Dx() {
const tab = this.tabsInfo[this.animationFinishCurrent];
// tab
if (tab) this.line3Dx = tab.left + tab.width / 2 - this.barWidthPx / 2 - this.tabsInfo[0].left;
},
countPx() {
// swiperrpxpxdxpx
this.sW = uni.upx2px(Number(this.swiperWidth));
},
emit(index) {
this.$emit('change', index);
},
change() {
this.setScrollViewToCenter();
},
getQuery(cb) {
try {
let view = uni.createSelectorQuery().in(this).select('.u-tabs');
view.fields({
size: true
},
data => {
if (data) {
this.componentsWidth = data.width;
if (cb && typeof cb === 'function') cb(data);
} else {
this.getQuery(cb);
}
}
).exec();
} catch (e) {
this.componentsWidth = windowWidth;
}
},
// tab
setScrollViewToCenter() {
let tab;
tab = this.tabsInfo[this.animationFinishCurrent];
if (tab) {
let tabCenter = tab.left + tab.width / 2;
let fatherWidth;
// tabtab
if (this.autoCenterMode === 'window') {
fatherWidth = windowWidth;
} else {
fatherWidth = this.componentsWidth;
}
this.scrollLeft = tabCenter - fatherWidth / 2;
}
},
setDx(dx) {
let nextTabIndex = dx > 0 ? this.animationFinishCurrent + 1 : this.animationFinishCurrent - 1;
//
nextTabIndex = nextTabIndex <= 0 ? 0 : nextTabIndex;
nextTabIndex = nextTabIndex >= this.list.length ? this.list.length - 1 : nextTabIndex;
const tab = this.tabsInfo[nextTabIndex];
// tabx
let nowTab = this.tabsInfo[this.animationFinishCurrent];
let nowTabX = nowTab.left + nowTab.width / 2;
// tab
let nextTab = this.tabsInfo[nextTabIndex];
let nextTabX = nextTab.left + nextTab.width / 2;
// tabtabtab
let distanceX = Math.abs(nextTabX - nowTabX);
this.line3AddDx = (dx / this.sW) * distanceX;
this.setTabColor(this.animationFinishCurrent, nextTabIndex, dx);
},
// tab
setTabColor(nowTabIndex, nextTabIndex, dx) {
let colorIndex = Math.abs(Math.ceil((dx / this.sW) * 100));
let colorLength = this.colorGradientArr.length;
//
colorIndex = colorIndex >= colorLength ? colorLength - 1 : colorIndex <= 0 ? 0 : colorIndex;
// tab
this.tabsInfo[nextTabIndex].color = this.colorGradientArr[colorIndex];
// tab
this.tabsInfo[nowTabIndex].color = this.colorGradientArr[colorLength - 1 - colorIndex];
},
// swiper
setFinishCurrent(current) {
// tabtab
if (current != this.animationFinishCurrent) {
this.tabsInfo.map((val, index) => {
if (current == index) val.color = this.activeColor;
else val.color = this.inactiveColor;
return val;
});
}
this.line3AddDx = 0;
this.animationFinishCurrent = current;
this.countLine3Dx();
}
}
};
</script>
<style scoped lang="scss">
view,
scroll-view {
box-sizing: border-box;
}
.u-tabs {
width: 100%;
transition-property: background-color, color;
}
::-webkit-scrollbar,
::-webkit-scrollbar,
::-webkit-scrollbar {
display: none;
width: 0 !important;
height: 0 !important;
-webkit-appearance: none;
background: transparent;
}
/* #ifdef H5 */
// 穿H5scroll-view
scroll-view /deep/ ::-webkit-scrollbar {
display: none;
width: 0 !important;
height: 0 !important;
-webkit-appearance: none;
background: transparent;
}
/* #endif */
.u-scroll-view {
width: 100%;
white-space: nowrap;
position: relative;
}
.u-tabs-scroll-box {
position: relative;
}
.u-tabs-scorll-flex {
display: flex;
justify-content: space-between;
}
.u-tabs-scorll-flex .u-tabs-item {
flex: 1;
}
.u-tabs-item {
position: relative;
display: inline-block;
text-align: center;
transition-property: background-color, color, font-weight;
}
.content {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.boxStyle {
pointer-events: none;
position: absolute;
transition-property: all;
}
.boxStyle2 {
pointer-events: none;
position: absolute;
bottom: 0;
transition-property: all;
transform: translateY(-100%);
}
.itemBackgroundBox {
pointer-events: none;
position: absolute;
top: 0;
transition-property: left, background-color;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
}
.itemBackground {
height: 100%;
width: 100%;
transition-property: all;
}
.u-scroll-bar {
position: absolute;
bottom: 4rpx;
}
</style>

335
node_modules/uview-ui/components/u-tabs/u-tabs.vue generated vendored Normal file
View File

@ -0,0 +1,335 @@
<template>
<view class="u-tabs" :id="id" :style="{
background: bgColor
}">
<scroll-view scroll-x class="u-scroll-view" :scroll-left="scrollLeft" scroll-with-animation>
<view class="u-scroll-box" :class="{'u-tabs-scorll-flex': !isScroll}">
<view class="u-tab-item" :id="'u-tab-item-' + index" v-for="(item, index) in list" :key="index" @tap="clickTab(index)"
:style="[tabItemStyle(index)]">
{{ item[name] || item['name']}}
</view>
<view v-if="showBar" class="u-tab-bar" :style="[tabBarStyle]"></view>
</view>
</scroll-view>
</view>
</template>
<script>
/**
* tabs 标签
* @description 该组件是一个tabs标签组件在标签多的时候可以配置为左右滑动标签少的时候可以禁止滑动 该组件的一个特点是配置为滚动模式时激活的tab会自动移动到组件的中间位置
* @tutorial https://www.uviewui.com/components/tabs.html
* @property {Boolean} is-scroll tabs是否可以左右拖动默认true
* @property {Array} list 标签数组元素为对象[{name: '推荐'}]
* @property {String Number} current 指定哪个tab为激活状态默认0
* @property {String Number} height 导航栏的高度单位rpx默认80
* @property {String Number} font-size tab文字大小单位rpx默认30
* @property {String Number} duration 滑块移动一次所需的时间单位秒默认0.5
* @property {String} active-color 滑块和激活tab文字的颜色默认#2979ff
* @property {String} inactive-color tabs文字颜色默认#303133
* @property {String Number} bar-width 滑块宽度单位rpx默认40
* @property {Object} active-item-style 活动tabs item的样式对象形式
* @property {Object} bar-style 底部滑块的样式对象形式
* @property {Boolean} show-bar 是否显示底部的滑块默认true
* @property {String Number} bar-height 滑块高度单位rpx默认6
* @property {String Number} gutter 单个tab标签的左右内边距之和单位rpx默认40
* @property {String} bg-color tabs导航栏的背景颜色默认#ffffff
* @property {String} name 组件内部读取的list参数中的属性名见官网说明默认name
* @property {Boolean} bold 激活选项的字体是否加粗默认true
* @event {Function} change 点击标签时触发
* @example <u-tabs ref="tabs" :list="list" :is-scroll="false"></u-tabs>
*/
export default {
name: "u-tabs",
props: {
// 23使flextab
isScroll: {
type: Boolean,
default: true
},
//
list: {
type: Array,
default () {
return [];
}
},
// tab
current: {
type: [Number, String],
default: 0
},
//
height: {
type: [String, Number],
default: 80
},
//
fontSize: {
type: [String, Number],
default: 30
},
// , ms
duration: {
type: [String, Number],
default: 0.5
},
//
activeColor: {
type: String,
default: '#2979ff'
},
//
inactiveColor: {
type: String,
default: '#303133'
},
// barrpx
barWidth: {
type: [String, Number],
default: 40
},
// bar
barHeight: {
type: [String, Number],
default: 6
},
// tab
gutter: {
type: [String, Number],
default: 30
},
//
bgColor: {
type: String,
default: '#ffffff'
},
//
name: {
type: String,
default: 'name'
},
// tab
bold: {
type: Boolean,
default: true
},
// tab item
activeItemStyle: {
type: Object,
default() {
return {}
}
},
//
showBar: {
type: Boolean,
default: true
},
//
barStyle: {
type: Object,
default() {
return {}
}
}
},
data() {
return {
scrollLeft: 0, // scroll-view
tabQueryInfo: [], // tab
componentWidth: 0, // px
scrollBarLeft: 0, // bartranslateX()
parentLeft: 0, // (tabs)
id: this.$u.guid(), // id
currentIndex: this.current,
barFirstTimeMove: true, // ()
};
},
watch: {
// tabtab使
// applist
list(n, o) {
// list
if(n.length !== o.length) this.currentIndex = 0;
// $nextTicktabtab
this.$nextTick(() => {
this.init();
});
},
current: {
immediate: true,
handler(nVal, oVal) {
//
this.$nextTick(() => {
this.currentIndex = nVal;
this.scrollByIndex();
});
}
},
},
computed: {
// bar
tabBarStyle() {
let style = {
width: this.barWidth + 'rpx',
transform: `translate(${this.scrollBarLeft}px, -100%)`,
//
'transition-duration': `${this.barFirstTimeMove ? 0 : this.duration }s`,
'background-color': this.activeColor,
height: this.barHeight + 'rpx',
//
'border-radius': `${this.barHeight / 2}px`
};
Object.assign(style, this.barStyle);
return style;
},
// tab
tabItemStyle() {
return (index) => {
let style = {
height: this.height + 'rpx',
'line-height': this.height + 'rpx',
'font-size': this.fontSize + 'rpx',
'transition-duration': `${this.duration}s`,
padding: this.isScroll ? `0 ${this.gutter}rpx` : '',
flex: this.isScroll ? 'auto' : '1'
};
//
if (index == this.currentIndex && this.bold) style.fontWeight = 'bold';
if (index == this.currentIndex) {
style.color = this.activeColor;
// tab item
style = Object.assign(style, this.activeItemStyle);
} else {
style.color = this.inactiveColor;
}
return style;
}
}
},
methods: {
// init便
async init() {
// tabs
let tabRect = await this.$uGetRect('#' + this.id);
// tabs
this.parentLeft = tabRect.left;
// tabs
this.componentWidth = tabRect.width;
this.getTabRect();
},
// tab
clickTab(index) {
// tab
if(index == this.currentIndex) return ;
//
this.$emit('change', index);
},
// tab
getTabRect() {
//
let query = uni.createSelectorQuery().in(this);
// tab使exec()
for (let i = 0; i < this.list.length; i++) {
// sizerect
query.select(`#u-tab-item-${i}`).fields({
size: true,
rect: true
});
}
//
query.exec(
function(res) {
this.tabQueryInfo = res;
// bar
this.scrollByIndex();
}.bind(this)
);
},
// scroll-viewtab
scrollByIndex() {
// tabtabwidthleft()
let tabInfo = this.tabQueryInfo[this.currentIndex];
if (!tabInfo) return;
// tab
let tabWidth = tabInfo.width;
// itemtabsitemlefttabsleft
let offsetLeft = tabInfo.left - this.parentLeft;
// tabs-itemscroll-view
let scrollLeft = offsetLeft - (this.componentWidth - tabWidth) / 2;
this.scrollLeft = scrollLeft < 0 ? 0 : scrollLeft;
// item
let left = tabInfo.left + tabInfo.width / 2 - this.parentLeft;
// item
this.scrollBarLeft = left - uni.upx2px(this.barWidth) / 2;
// barFirstTimeMovetruefalse
// scrollBarLeftcomputed
if(this.barFirstTimeMove == true) {
setTimeout(() => {
this.barFirstTimeMove = false;
}, 100)
}
}
},
mounted() {
this.init();
}
};
</script>
<style lang="scss">
view,
scroll-view {
box-sizing: border-box;
}
::-webkit-scrollbar,
::-webkit-scrollbar,
::-webkit-scrollbar {
display: none;
width: 0 !important;
height: 0 !important;
-webkit-appearance: none;
background: transparent;
}
.u-scroll-box {
position: relative;
}
/* #ifdef H5 */
// 穿H5scroll-view
scroll-view /deep/ ::-webkit-scrollbar {
display: none;
width: 0 !important;
height: 0 !important;
-webkit-appearance: none;
background: transparent;
}
/* #endif */
.u-scroll-view {
width: 100%;
white-space: nowrap;
position: relative;
}
.u-tab-item {
position: relative;
display: inline-block;
text-align: center;
transition-property: background-color, color;
}
.u-tab-bar {
position: absolute;
bottom: 0;
}
.u-tabs-scorll-flex {
display: flex;
justify-content: space-between;
}
</style>

278
node_modules/uview-ui/components/u-tag/u-tag.vue generated vendored Normal file
View File

@ -0,0 +1,278 @@
<template>
<view v-if="show" :class="[
disabled ? 'u-disabled' : '',
'u-size-' + size,
'u-shape-' + shape,
'u-mode-' + mode + '-' + type
]"
class="u-tag" :style="[customStyle]" @tap="clickTag">
{{text}}
<view class="u-icon-wrap" @tap.stop>
<u-icon @click="close" size="22" v-if="closeable" name="close" class="u-close-icon" :style="[iconStyle]"></u-icon>
</view>
</view>
</template>
<script>
/**
* tag 提示
* @description 该组件一般用于标记和选择
* @tutorial https://www.uviewui.com/components/tag.html
* @property {String} type 主题类型默认primary
* @property {String} size 标签大小默认default
* @property {String} shape 标签形状默认square
* @property {String} text 标签的文字内容
* @property {String} bg-color 自定义标签的背景颜色
* @property {String} border-color 标签的边框颜色
* @property {String} close-color 关闭按钮的颜色
* @property {String Number} index 点击标签时会通过click事件返回该值
* @property {String} mode 模式选择见官网说明默认light
* @property {Boolean} closeable 是否可关闭设置为true文字右边会出现一个关闭图标默认false
* @property {Boolean} show 标签显示与否默认true
* @event {Function} click 点击标签触发
* @event {Function} close closeable为true时点击标签关闭按钮触发
* @example <u-tag text="雪月夜" type="success" />
*/
export default {
name: 'u-tag',
//
props: {
// infoprimarysuccesswarningerror
type: {
type: String,
default: 'primary'
},
disabled: {
type: [Boolean, String],
default: false
},
// defaultmini
size: {
type: String,
default: 'default'
},
// tagcircle, squarecircleLeftcircleRight
shape: {
type: String,
default: 'square'
},
//
text: {
type: [String, Number],
default: ''
},
//
bgColor: {
type: String,
default: ''
},
//
color: {
type: String,
default: ''
},
//
borderColor: {
type: String,
default: ''
},
//
closeColor: {
type: String,
default: ''
},
//
index: {
type: [Number, String],
default: ''
},
// dark|light|plain
mode: {
type: String,
default: 'light'
},
//
closeable: {
type: Boolean,
default: false
},
//
show: {
type: Boolean,
default: true
}
},
data() {
return {
}
},
computed: {
customStyle() {
let style = {};
// type
if(this.color) style.color = this.color+"!important";
// tagtype
if(this.bgColor) style.backgroundColor = this.bgColor+"!important";
// tagborderColor使color
if(this.mode == 'plain' && this.color && !this.borderColor) style.borderColor = this.color;
else style.borderColor = this.borderColor;
return style;
},
iconStyle() {
if(!this.closeable) return ;
let style = {};
if(this.size == 'mini') style.fontSize = '20rpx';
else style.fontSize = '22rpx';
if(this.mode == 'plain' || this.mode == 'light') style.color = this.$u.color[this.type];
else if(this.mode == 'dark') style.color = "#ffffff";
if(this.closeColor) style.color = this.closeColor;
return style;
}
},
methods: {
//
clickTag() {
// disabled
if(this.disabled) return ;
this.$emit('click', this.index);
},
//
close() {
this.$emit('close', this.index);
}
}
}
</script>
<style lang="scss" scoped>
.u-tag {
box-sizing: border-box;
align-items: center;
border-radius: 6rpx;
display: inline-block;
line-height: 1;
}
.u-size-default {
font-size: 22rpx;
padding: 12rpx 22rpx;
}
.u-size-mini {
font-size: 20rpx;
padding: 6rpx 12rpx;
}
.u-mode-light-primary {
background-color: $u-type-primary-light;
color: $u-type-primary;
border: 1px solid rgb(215, 234, 254);
}
.u-mode-light-success {
background-color: $u-type-success-light;
color: $u-type-success;
border: 1px solid #BEF5C8;
}
.u-mode-light-error {
background-color: $u-type-error-light;
color: $u-type-error;
border: 1px solid #fde2e2;
}
.u-mode-light-warning {
background-color: $u-type-warning-light;
color: $u-type-warning;
border: 1px solid #faecd8;
}
.u-mode-light-info {
background-color: $u-type-info-light;
color: $u-type-info;
border: 1px solid #ebeef5;
}
.u-mode-dark-primary {
background-color: $u-type-primary;
color: #FFFFFF;
}
.u-mode-dark-success {
background-color: $u-type-success;
color: #FFFFFF;
}
.u-mode-dark-error {
background-color: $u-type-error;
color: #FFFFFF;
}
.u-mode-dark-warning {
background-color: $u-type-warning;
color: #FFFFFF;
}
.u-mode-dark-info {
background-color: $u-type-info;
color: #FFFFFF;
}
.u-mode-plain-primary {
background-color: #FFFFFF;
color: $u-type-primary;
border: 1px solid $u-type-primary;
}
.u-mode-plain-success {
background-color: #FFFFFF;
color: $u-type-success;
border: 1px solid $u-type-success;
}
.u-mode-plain-error {
background-color: #FFFFFF;
color: $u-type-error;
border: 1px solid $u-type-error;
}
.u-mode-plain-warning {
background-color: #FFFFFF;
color: $u-type-warning;
border: 1px solid $u-type-warning;
}
.u-mode-plain-info {
background-color: #FFFFFF;
color: $u-type-info;
border: 1px solid $u-type-info;
}
.u-disabled {
opacity: 0.55;
}
.u-shape-circle {
border-radius: 100rpx;
}
.u-shape-circleRight {
border-radius: 0 100rpx 100rpx 0;
}
.u-shape-circleLeft {
border-radius: 100rpx 0 0 100rpx;
}
.u-close-icon {
margin-left: 14rpx;
font-size: 22rpx;
color: $u-type-success;
}
.u-icon-wrap {
display: inline-flex;
transform: scale(0.86);
}
</style>

113
node_modules/uview-ui/components/u-td/u-td.vue generated vendored Normal file
View File

@ -0,0 +1,113 @@
<template>
<view class="u-td" :style="[tdStyle]">
<slot></slot>
</view>
</template>
<script>
/**
* td td单元格
* @description 表格组件一般用于展示大量结构化数据的场景搭配u-table使用
* @tutorial https://www.uviewui.com/components/table.html#td-props
* @property {String Number} width 单元格宽度百分比或者具体带单位的值如30% 200rpx等一般使用百分比单元格宽度默认为均分tr的长度默认auto
* @example <u-td>二年级</u-td>
*/
export default {
name: "u-td",
props: {
// 30% 200rpx使
width: {
type: [Number, String],
default: 'auto'
}
},
data() {
return {
tr: []
};
},
inject: ['uTable', 'uTr'],
provide() {
return {
uTd: this
}
},
created() {
},
computed: {
tdStyle() {
let style = {};
if (this.width != "auto") style.flex = `0 0 ${this.width}`;
style.textAlign = this.uTable.align;
style.padding = this.tr.length == 0 ? this.uTable.padding : 0;
style.borderBottom = this.tr.length == 0 ? `solid 1px ${this.uTable.borderColor}` : 0;
style.borderRight = this.tr.length == 0 ? `solid 1px ${this.uTable.borderColor}` : 0;
style.fontSize = this.uTable.fontSize + 'rpx';
style.color = this.uTable.color;
return style;
}
}
};
</script>
<style lang="scss" scoped>
.u-td {
display: flex;
flex-direction: column;
flex: 1;
justify-content: center;
font-size: 28rpx;
color: $u-content-color;
align-self: stretch;
box-sizing: border-box;
}
.u-col-1 {
flex: 0 0 calc(100%/12);
}
.u-col-2 {
flex: 0 0 calc(100%/12 * 2);
}
.u-col-3 {
flex: 0 0 calc(100%/12 * 3);
}
.u-col-4 {
flex: 0 0 calc(100%/12 * 4);
}
.u-col-5 {
flex: 0 0 calc(100%/12 * 5);
}
.u-col-6 {
flex: 0 0 calc(100%/12 * 6);
}
.u-col-7 {
flex: 0 0 calc(100%/12 * 7);
}
.u-col-8 {
flex: 0 0 calc(100%/12 * 8);
}
.u-col-9 {
flex: 0 0 calc(100%/12 * 9);
}
.u-col-10 {
flex: 0 0 calc(100%/12 * 10);
}
.u-col-11 {
flex: 0 0 calc(100%/12 * 11);
}
.u-col-12 {
flex: 0 0 calc(100%/12 * 12);
}
</style>

56
node_modules/uview-ui/components/u-th/u-th.vue generated vendored Normal file
View File

@ -0,0 +1,56 @@
<template>
<view class="u-th" :style="[thStyle]">
<slot></slot>
</view>
</template>
<script>
/**
* th th单元格
* @description 表格组件一般用于展示大量结构化数据的场景搭配u-table使用
* @tutorial https://www.uviewui.com/components/table.html#td-props
* @property {String Number} width 标题单元格宽度百分比或者具体带单位的值如30%200rpx等一般使用百分比单元格宽度默认为均分tr的长度
* @example 暂无示例
*/
export default {
name: "u-th",
props: {
// 30% 200rpx使
width: {
type: [Number, String],
default: ''
}
},
data() {
return {
};
},
inject: ['uTable'],
computed: {
thStyle() {
let style = {};
if (this.width) style.flex = `0 0 ${this.width}`;
style.textAlign = this.uTable.align;
style.padding = this.uTable.padding;
style.borderBottom = `solid 1px ${this.uTable.borderColor}`;
style.borderRight = `solid 1px ${this.uTable.borderColor}`;
Object.assign(style, this.uTable.thStyle);
return style;
}
}
};
</script>
<style lang="scss" scoped>
.u-th {
display: flex;
flex-direction: column;
flex: 1;
justify-content: center;
font-size: 28rpx;
color: $u-main-color;
font-weight: bold;
background-color: rgb(245, 246, 248);
}
</style>

View File

@ -0,0 +1,81 @@
<template>
<view class="u-time-axis-item">
<slot name="content" />
<view class="u-time-axis-node" :style="[nodeStyle]">
<slot name="node">
<view class="u-dot">
</view>
</slot>
</view>
</view>
</template>
<script>
/**
* timeLineItem 时间轴Item
* @description 时间轴组件一般用于物流信息展示各种跟时间相关的记录等场景(搭配u-time-line使用)
* @tutorial https://www.uviewui.com/components/timeLine.html
* @property {String} bg-color 左边节点的背景颜色一般通过slot内容自定义背景颜色即可默认#ffffff
* @property {String Number} node-top 节点左边图标绝对定位的top值单位rpx
* @example <u-time-line-item node-top="2">...</u-time-line-item>
*/
export default {
name: "u-time-line-item",
props: {
//
bgColor: {
type: String,
default: "#ffffff"
},
// top
nodeTop: {
type: [String, Number],
default: ""
}
},
data() {
return {
}
},
computed: {
nodeStyle() {
let style = {
backgroundColor: this.bgColor,
};
if (this.nodeTop != "") style.top = this.nodeTop + 'rpx';
return style;
}
}
}
</script>
<style lang="scss" scoped>
.u-time-axis-item {
display: flex;
flex-direction: column;
width: 100%;
position: relative;
margin-bottom: 32rpx;
}
.u-time-axis-node {
position: absolute;
top: 12rpx;
left: -40rpx;
transform-origin: 0;
transform: translateX(-50%);
display: flex;
align-items: center;
justify-content: center;
z-index: 1;
font-size: 24rpx;
}
.u-dot {
height: 16rpx;
width: 16rpx;
border-radius: 100rpx;
background: #ddd;
}
</style>

View File

@ -0,0 +1,41 @@
<template>
<view class="u-time-axis">
<slot />
</view>
</template>
<script>
/**
* timeLine 时间轴
* @description 时间轴组件一般用于物流信息展示各种跟时间相关的记录等场景
* @tutorial https://www.uviewui.com/components/timeLine.html
* @example <u-time-line></u-time-line>
*/
export default {
name: "u-time-line",
data() {
return {
}
}
}
</script>
<style lang="scss" scoped>
.u-time-axis {
padding-left: 40rpx;
position: relative;
}
.u-time-axis::before {
content: " ";
position: absolute;
left: 0;
top: 12rpx;
width: 1px;
bottom: 0;
border-left: 1px solid #ddd;
transform-origin: 0 0;
transform: scaleX(0.5);
}
</style>

211
node_modules/uview-ui/components/u-toast/u-toast.vue generated vendored Normal file
View File

@ -0,0 +1,211 @@
<template>
<view class="u-toast" :class="[isShow ? 'u-show' : '', 'u-type-' + config.type, 'u-position-' + config.position]" :style="{
zIndex: uZIndex
}">
<view class="u-icon-wrap">
<u-icon v-if="config.icon" class="u-icon" :name="iconName" :size="30" :color="$u.color[config.type]"></u-icon>
</view>
<text class="u-text">{{config.title}}</text>
</view>
</template>
<script>
/**
* toast 消息提示
* @description 此组件表现形式类似uni的uni.showToastAPI但也有不同的地方
* @tutorial https://www.uviewui.com/components/toast.html
* @property {String} z-index toast展示时的z-index值
* @event {Function} show 显示toast如需一进入页面就显示toast请在onReady生命周期调用
* @example <u-toast ref="uToast" />
*/
export default {
name: "u-toast",
props: {
// z-index
zIndex: {
type: [Number, String],
default: ''
},
},
data() {
return {
isShow: false,
timer: null, //
config: {
params: {}, // URL
title: '', //
type: '', // primarysuccesserrorwarningblack
duration: 2000, //
isTab: false, // tab
url: '', // toast
icon: true, //
position: 'center', // toast
}
};
},
computed: {
iconName() {
// nonetypeerror|warning|succes|info
if (['error', 'warning', 'success', 'info'].indexOf(this.config.type) >= 0 && this.config.icon) {
let icon = this.$u.type2icon(this.config.type);
return icon;
}
},
uZIndex() {
// toastz-index使
return this.isShow ? (this.zIndex ? this.zIndex : this.$u.zIndex.toast) : '999999';
}
},
methods: {
// toastthis.$refs.xxx.show(options)
show(options) {
this.config = Object.assign(this.config, options);
if (this.timer) {
//
clearTimeout(this.timer);
this.timer = null;
}
this.isShow = true;
this.timer = setTimeout(() => {
// toast
this.isShow = false;
clearTimeout(this.timer);
this.timer = null;
this.timeEnd();
}, this.config.duration);
},
// toastthis.$refs.xxx.hide()
hide() {
this.isShow = false;
if (this.timer) {
//
clearTimeout(this.timer);
this.timer = null;
}
},
//
timeEnd() {
// urlisTabtruefalse
if (this.config.url) {
// url"/"uni"/"
if (this.config.url[0] != '/') this.config.url = '/' + this.config.url;
//
if (Object.keys(this.config.params).length) {
// url
// 使"/","?","="/page/index/index?name=mary"
// params"?"
let query = '';
if (/.*\/.*\?.*=.*/.test(this.config.url)) {
// objectget
query = this.$u.queryParams(this.config.params, false);
this.config.url = this.config.url + "&" + query;
} else {
query = this.$u.queryParams(this.config.params);
this.config.url += query;
}
}
// tab使uni.switchTab
if (this.config.isTab) {
uni.switchTab({
url: this.config.url
});
} else {
uni.navigateTo({
url: this.config.url
});
}
}
}
}
};
</script>
<style lang="scss" scoped>
.u-toast {
position: fixed;
z-index: -1;
transition: opacity 0.3s;
text-align: center;
color: #fff;
border-radius: 8rpx;
background: #585858;
height: 80rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 28rpx;
opacity: 0;
pointer-events: none;
padding:0 40rpx;
}
.u-toast.u-show {
opacity: 1;
}
.u-text {
word-break: keep-all;
white-space: nowrap;
line-height: normal;
}
.u-icon {
margin-right: 10rpx;
display: flex;
align-items: center;
line-height: normal;
}
.u-position-center {
left: 50%;
top: 50%;
transform: translateX(-50%) translateY(-50%);
}
.u-position-top {
left: 50%;
top: 20%;
transform: translateX(-50%) translateY(-50%);
}
.u-position-bottom {
left: 50%;
bottom: 20%;
transform: translateX(-50%) translateY(-50%);
}
.u-type-primary {
color: $u-type-primary;
background-color: $u-type-primary-light;
border: 1px solid rgb(215, 234, 254);
}
.u-type-success {
color: $u-type-success;
background-color: $u-type-success-light;
border: 1px solid #BEF5C8;
}
.u-type-error {
color: $u-type-error;
background-color: $u-type-error-light;
border: 1px solid #fde2e2;
}
.u-type-warning {
color: $u-type-warning;
background-color: $u-type-warning-light;
border: 1px solid #faecd8;
}
.u-type-info {
color: $u-type-info;
background-color: $u-type-info-light;
border: 1px solid #ebeef5;
}
.u-type-default {
color: #fff;
background-color: #585858;
}
</style>

View File

@ -0,0 +1,119 @@
<template>
<view class="u-tips" :class="['u-' + type, isShow ? 'u-tip-show' : '']" :style="{
top: navbarHeight + 'px',
zIndex: uZIndex
}">{{ title }}</view>
</template>
<script>
/**
* topTips 顶部提示
* @description 该组件一般用于页面顶部向下滑出一个提示尔后自动收起的场景
* @tutorial https://www.uviewui.com/components/topTips.html
* @property {String Number} navbar-height 导航栏高度(包含状态栏高度在内)单位PX
* @property {String Number} z-index z-index值默认975
* @example <u-top-tips ref="uTips"></u-top-tips>
*/
export default {
name: "u-top-tips",
props: {
//
navbarHeight: {
type: [Number, String],
// #ifndef H5
default: 0,
// #endif
// #ifdef H5
default: 44,
// #endif
},
// z-index
zIndex: {
type: [Number, String],
default: ''
}
},
data() {
return {
timer: null, //
isShow: false, //
title: '', //
type: 'primary', // primarysuccesserrorwarninginfo
duration: 2000, //
};
},
computed: {
uZIndex() {
return this.zIndex ? this.zIndex : this.$u.zIndex.topTips;
}
},
methods: {
show(config = {}) {
//
clearTimeout(this.timer);
// (type)
if (config.duration) this.duration = config.duration;
if (config.type) this.type = config.type;
this.title = config.title;
this.isShow = true;
//
this.timer = setTimeout(() => {
this.isShow = false;
clearTimeout(this.timer);
this.timer = null;
}, this.duration);
}
}
};
</script>
<style lang="scss" scoped>
view {
box-sizing: border-box;
}
//
.u-tips {
width: 100%;
position: fixed;
z-index: 1;
padding: 20rpx 30rpx;
color: #FFFFFF;
font-size: 28rpx;
left: 0;
right: 0;
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
// translateY(-100%)Y(h5)(app)
transform: translateY(-100%);
transition: all 0.35s linear;
}
.u-tip-show {
transform: translateY(0);
opacity: 1;
z-index: 99;
}
.u-primary {
background: $u-type-primary;
}
.u-success {
background: $u-type-success;
}
.u-warning {
background: $u-type-warning;
}
.u-error {
background: $u-type-error;
}
.u-info {
background: $u-type-info;
}
</style>

34
node_modules/uview-ui/components/u-tr/u-tr.vue generated vendored Normal file
View File

@ -0,0 +1,34 @@
<template>
<view class="u-tr">
<slot></slot>
</view>
</template>
<script>
/**
* tr 表格行标签
* @description 表格组件一般用于展示大量结构化数据的场景搭配<u-table>使用
* @tutorial https://www.uviewui.com/components/table.html
* @example <u-tr></u-tr>
*/
export default {
name: "u-tr",
inject: ['uTable', 'uTd'],
provide() {
return {
uTr: this,
};
},
created() {
if (this.uTd && this.uTd.tr) {
this.uTd.tr.push(this);
}
}
}
</script>
<style lang="scss" scoped>
.u-tr {
display: flex;
}
</style>

509
node_modules/uview-ui/components/u-upload/u-upload.vue generated vendored Normal file
View File

@ -0,0 +1,509 @@
<template>
<view class="u-upload" v-if="!disabled">
<view v-if="showUploadList" class="u-list-item u-preview-wrap" v-for="(item, index) in lists" :key="index" :style="{
width: width + 'rpx',
height: width + 'rpx'
}">
<view v-if="deletable" class="u-delete-icon" @tap.stop="deleteItem(index)" :style="{
background: delBgColor
}">
<u-icon class="u-icon" :name="delIcon" size="20" :color="delColor"></u-icon>
</view>
<u-line-progress v-if="showProgress && item.progress > 0 && !item.error" :show-percent="false" height="16" class="u-progress" :percent="item.progress"></u-line-progress>
<view @tap.stop="retry(index)" v-if="item.error" class="u-error-btn">点击重试</view>
<image @tap.stop="doPreviewImage(item.url || item.path, index)" class="u-preview-image" v-if="!item.isImage" :src=" item.url || item.path "
:mode="imageMode"></image>
</view>
<slot name="file" :file="lists"></slot>
<view style="display: inline-block;" @tap="selectFile" v-if="maxCount > lists.length">
<slot name="addBtn"></slot>
<view v-if="!customBtn" class="u-list-item u-add-wrap" hover-class="u-add-wrap__hover" hover-stay-time="150" :style="{
width: width + 'rpx',
height: width + 'rpx'
}">
<u-icon name="plus" class="u-add-btn" size="40" @click="selectFile"></u-icon>
<view class="u-add-tips">{{uploadText}}</view>
</view>
</view>
</view>
</template>
<script>
/**
* upload 图片上传
* @description 该组件用于上传图片场景
* @tutorial https://www.uviewui.com/components/upload.html
* @property {String} action 服务器上传地址
* @property {String Number} max-count 最大选择图片的数量默认99
* @property {Boolean} custom-btn 如果需要自定义选择图片的按钮设置为true默认false
* @property {Boolean} show-progress 是否显示进度条默认true
* @property {Boolean} disabled 是否启用(显示/移仓)组件默认false
* @property {String} image-mode 预览图片等显示模式可选值为uni的image的mode属性值默认aspectFill
* @property {String} del-icon 右上角删除图标名称只能为uView内置图标
* @property {String} del-bg-color 右上角关闭按钮的背景颜色
* @property {String} del-color 右上角关闭按钮图标的颜色
* @property {Object} header 上传携带的头信息对象形式
* @property {Object} form-data 上传额外携带的参数
* @property {String} name 上传文件的字段名供后端获取使用默认file
* @property {Array<String>} size-type original 原图compressed 压缩图默认二者都有默认['original', 'compressed']
* @property {Array<String>} source-type 选择图片的来源album-从相册选图camera-使用相机默认二者都有默认['album', 'camera']
* @property {Boolean} preview-full-image 是否可以通过uni.previewImage预览已选择的图片默认true
* @property {Boolean} multiple 是否开启图片多选部分安卓机型不支持默认true
* @property {Boolean} deletable 是否显示删除图片的按钮默认true
* @property {String Number} max-size 选择单个文件的最大大小单位B(byte)默认不限制默认Number.MAX_VALUE
* @property {Array<Object>} file-list 默认显示的图片列表数组元素为对象必须提供url属性
* @property {Boolean} upload-text 选择图片按钮的提示文字默认选择图片
* @property {Boolean} auto-upload 选择完图片是否自动上传见上方说明默认true
* @property {Boolean} show-tips 特殊情况下是否自动提示toast见上方说明默认true
* @property {Boolean} show-upload-list 是否显示组件内部的图片预览默认true
* @event {Function} on-oversize 图片大小超出最大允许大小
* @event {Function} on-preview 全屏预览图片时触发
* @event {Function} on-remove 移除图片时触发
* @event {Function} on-success 图片上传成功时触发
* @event {Function} on-change 图片上传后无论成功或者失败都会触发
* @event {Function} on-error 图片上传失败时触发
* @event {Function} on-progress 图片上传过程中的进度变化过程触发
* @event {Function} on-uploaded 所有图片上传完毕触发
* @event {Function} on-choose-complete 每次选择图片后触发只是让外部可以得知每次选择后内部的文件列表
* @example <u-upload :action="action" :file-list="fileList" ></u-upload>
*/
export default {
name: 'u-upload',
props: {
//
showUploadList: {
type: Boolean,
default: true
},
//
action: {
type: String,
default: ''
},
//
maxCount: {
type: [String, Number],
default: 52
},
//
showProgress: {
type: Boolean,
default: true
},
//
disabled: {
type: Boolean,
default: false
},
// imagemode
imageMode: {
type: String,
default: 'aspectFill'
},
//
header: {
type: Object,
default () {
return {}
}
},
//
formData: {
type: Object,
default () {
return {}
}
},
//
name: {
type: String,
default: 'file'
},
// , original compressed
sizeType: {
type: Array,
default () {
return ['original', 'compressed']
}
},
sourceType: {
type: Array,
default () {
return ['album', 'camera']
}
},
//
previewFullImage: {
type: Boolean,
default: true
},
//
multiple: {
type: Boolean,
default: true
},
//
deletable: {
type: Boolean,
default: true
},
// byte
maxSize: {
type: [String, Number],
default: Number.MAX_VALUE
},
//
fileList: {
type: Array,
default () {
return []
}
},
//
uploadText: {
type: String,
default: '选择图片'
},
//
autoUpload: {
type: Boolean,
default: true
},
// toast
showTips: {
type: Boolean,
default: true
},
// slot
customBtn: {
type: Boolean,
default: false
},
//
width: {
type: [String, Number],
default: 200
},
//
delBgColor: {
type: String,
default: '#fa3534'
},
//
delColor: {
type: String,
default: '#ffffff'
},
// uView
delIcon: {
type: String,
default: 'close'
}
},
mounted() {
},
data() {
return {
lists: [],
isInCount: true,
uploading: false
}
},
watch: {
fileList: {
immediate: true,
handler(val) {
val.map(value => {
this.lists.push({url: value.url, error: false, progress: 100});
})
}
},
},
methods: {
//
clear() {
this.lists = [];
// "on-list-change"
this.$emit('on-list-change', this.lists);
},
//
reUpload() {
this.uploadFile();
},
//
selectFile() {
if (this.disabled) return;
const {
name = '', maxCount, multiple, maxSize, sizeType, lists, camera, compressed, maxDuration, sourceType
} = this;
let chooseFile = null;
const newMaxCount = maxCount - lists.length;
// 使 chooseImage
chooseFile = new Promise((resolve, reject) => {
uni.chooseImage({
count: multiple ? (newMaxCount > 9 ? 9 : newMaxCount) : 1,
sourceType: sourceType,
sizeType,
success: resolve,
fail: reject
});
});
chooseFile
.then((res) => {
let file = null;
let listOldLength = this.lists.length;
res.tempFiles.map((val, index) => {
// index1
if (!multiple && index >= 1) return;
if (val.size > maxSize) {
this.$emit('on-oversize', val, this.lists);
this.showToast('超出允许的文件大小');
} else {
if(maxCount <= lists.length) {
this.$emit('on-exceed', val, this.lists);
this.showToast('超出最大允许的文件个数');
return ;
}
lists.push({
url: val.path,
progress: 0,
error: false
});
//
this.$emit('on-list-change', this.lists);
}
})
//
this.$emit('on-choose-complete', this.lists);
if(this.autoUpload) this.uploadFile(listOldLength);
})
.catch(error => {
// this.$emit('on-error', error);
});
},
//
showToast(message, force = false) {
if(this.showTips || force) {
uni.showToast({
title: message,
icon: "none"
});
}
},
// ref
upload() {
this.uploadFile();
},
//
retry(index) {
this.lists[index].progress = 0;
this.lists[index].error = false;
this.lists[index].response = null;
uni.showLoading({
title: '重新上传'
});
this.uploadFile(index);
},
//
uploadFile(index = 0) {
if (this.disabled) return;
if(this.uploading) return ;
//
if (index >= this.lists.length) {
this.$emit('on-uploaded', this.lists);
return ;
}
//
if (!this.action) {
this.showToast('请配置上传地址', true);
return;
}
//
if (this.lists[index].progress == 100) {
if(this.autoUpload == false) this.uploadFile(index + 1);
return;
}
this.lists[index].error = false;
this.uploading = true;
//
const task = uni.uploadFile({
url: this.action,
filePath: this.lists[index].url,
name: this.name,
formData: this.formData,
header: this.header,
success: (res) => {
if (![200,201].includes(res.statusCode)) {
this.uploadError(index, res.data);
} else {
//
this.lists[index].response = res.data;
this.lists[index].progress = 100;
this.lists[index].error = false;
this.$emit('on-success', res.data, index, this.lists);
}
},
fail: (e) => {
this.uploadError(index, e);
},
complete: (res) => {
uni.hideLoading();
this.uploading = false;
this.uploadFile(index + 1);
this.$emit('on-change', res, index, this.lists);
}
});
task.onProgressUpdate((res) => {
if (res.progress > 0) {
this.lists[index].progress = res.progress;
this.$emit('on-progress', res, index, this.lists);
}
});
},
//
uploadError(index, err) {
this.lists[index].progress = 0;
this.lists[index].error = true;
this.lists[index].response = null;
this.$emit('on-error', err, index, this.lists);
this.showToast('上传失败,请重试');
},
//
deleteItem(index) {
uni.showModal({
title: '提示',
content: '您确定要删除此项吗?',
success: res => {
if (res.confirm) {
if (this.lists[index].process < 100 && this.lists[index].process > 0) {
typeof this.lists[index].uploadTask != 'undefined' && this.lists[index].uploadTask.abort();
}
this.lists.splice(index, 1);
this.$forceUpdate();
this.$emit('on-remove', index, this.lists);
this.showToast('移除成功');
//
this.$emit('on-list-change', this.lists);
}
}
});
},
// ref
remove(index) {
//
if(index >= 0 && index < this.lists.length) {
this.lists.splice(index, 1);
this.$emit('on-list-change', this.lists);
}
},
//
doPreviewImage(url, index) {
if (!this.previewFullImage)
return;
const images = this.lists.map(item => item.url || item.path);
uni.previewImage({
urls: images,
current: url,
success: () => {
this.$emit('on-preview', url, this.lists);
},
fail: () => {
uni.showToast({
title: '预览图片失败',
icon: 'none'
});
}
});
}
}
}
</script>
<style lang="scss" scoped>
.u-upload {
display: flex;
flex-wrap: wrap;
align-items: center;
}
.u-list-item {
width: 200rpx;
height: 200rpx;
overflow: hidden;
margin: 10rpx;
background: rgb(244, 245, 246);
position: relative;
border-radius: 10rpx;
display: inline-flex;
align-items: center;
justify-content: center;
}
.u-preview-wrap {
border: 1px solid rgb(235, 236, 238);
}
.u-add-wrap {
flex-direction: column;
color: $u-content-color;
font-size: 28rpx;
}
.u-add-tips {
margin-top: 20rpx;
}
.u-add-wrap__hover {
background-color: rgb(235, 236, 238);
}
.u-preview-image {
display: block;
width: 100%;
height: 100%;
}
.u-delete-icon {
position: absolute;
top: 10rpx;
right: 10rpx;
z-index: 10;
background-color: $u-type-error;
border-radius: 100rpx;
width: 44rpx;
height: 44rpx;
display: flex;
align-items: center;
justify-content: center;
}
.u-icon {
display: flex;
align-items: center;
justify-content: center;
}
.u-progress {
position: absolute;
bottom: 10rpx;
left: 8rpx;
right: 8rpx;
z-index: 9;
width: auto;
}
.u-error-btn {
color: #FFFFFF;
background-color: $u-type-error;
font-size: 20rpx;
padding: 4px 0;
text-align: center;
position: absolute;
bottom: 0;
left: 0;
right: 0;
z-index: 9;
line-height: 1;
}
</style>

View File

@ -0,0 +1,157 @@
<template>
<view class="u-code-wrap">
</view>
</template>
<script>
/**
* verificationCode 验证码输入框
* @description 考虑到用户实际发送验证码的场景可能是一个按钮也可能是一段文字提示语各有不同所以本组件 不提供界面显示只提供提示语由用户将提示语嵌入到具体的场景
* @tutorial https://www.uviewui.com/components/verificationCode.html
* @property {Number String} seconds 倒计时所需的秒数默认60
* @property {String} start-text 开始前的提示语见官网说明默认获取验证码
* @property {String} change-text 倒计时期间的提示语必须带有字母"x"见官网说明默认X秒重新获取
* @property {String} end-text 倒计结束的提示语见官网说明默认重新获取
* @property {Boolean} keep-running 是否在H5刷新或各端返回再进入时继续倒计时默认false
* @event {Function} change 倒计时期间每秒触发一次
* @event {Function} start 开始倒计时触发
* @event {Function} end 结束倒计时触发
* @example <u-verification-code :seconds="seconds" @end="end" @start="start" ref="uCode"
*/
export default {
name: "u-verification-code",
props: {
//
seconds: {
type: [String, Number],
default: 60
},
//
startText: {
type: String,
default: '获取验证码'
},
//
changeText: {
type: String,
default: 'X秒重新获取'
},
//
endText: {
type: String,
default: '重新获取'
},
// H5
keepRunning: {
type: Boolean,
default: false
}
},
data() {
return {
secNum: this.seconds,
timer: null,
canGetCode: true, //
}
},
mounted() {
this.checkKeepRunning();
},
watch: {
seconds: {
immediate: true,
handler(n) {
this.secNum = n;
}
}
},
methods: {
checkKeepRunning() {
// 退(H5)
let lastTimestamp = Number(uni.getStorageSync('$uCountDownTimestamp'));
//
let nowTimestamp = Math.floor((+ new Date()) / 1000);
//
if(this.keepRunning && lastTimestamp && lastTimestamp > nowTimestamp) {
//
this.secNum = lastTimestamp - nowTimestamp;
//
uni.setStorageSync('$uCountDownTimestamp', 0);
//
this.start();
} else {
//
this.changeEvent(this.startText);
}
},
//
start() {
//
if(this.timer) {
clearInterval(this.timer);
this.timer = null;
}
//this.secNum = this.seconds;
this.$emit('start');
this.canGetCode = false;
// setInterval1
this.changeEvent(this.changeText.replace(/x|X/, this.secNum));
this.timer = setInterval(() => {
if (--this.secNum) {
// "x"
this.changeEvent(this.changeText.replace(/x|X/, this.secNum));
} else {
clearInterval(this.timer);
this.timer = null;
this.changeEvent(this.endText);
this.secNum = this.seconds;
this.$emit('end');
this.canGetCode = true;
}
this.setTimeToStorage();
}, 1000);
},
//
reset() {
this.canGetCode = true;
clearInterval(this.timer);
this.secNum = this.seconds;
this.changeEvent(this.endText);
},
changeEvent(text) {
this.$emit('change', text);
},
// H5
setTimeToStorage() {
if(!this.keepRunning) return ;
//
// 0
if(this.secNum > 0 && this.secNum < this.seconds) {
// (+ new Date())1000
let nowTimestamp = Math.floor((+ new Date()) / 1000);
// => +
uni.setStorage({
key: '$uCountDownTimestamp',
data: nowTimestamp + this.secNum
})
}
}
},
//
beforeDestroy() {
clearTimeout(this.timer);
this.timer = null;
this.setTimeToStorage();
}
}
</script>
<style lang="scss" scoped>
.u-code-wrap {
width: 0;
height: 0;
position: fixed;
z-index: -1;
}
</style>

View File

@ -0,0 +1,178 @@
<template>
<view class="u-waterfall">
<view id="u-left-cloumn" class="u-cloumn"><slot name="left" :leftList="leftList"></slot></view>
<view id="u-right-cloumn" class="u-cloumn"><slot name="right" :rightList="rightList"></slot></view>
</view>
</template>
<script>
/**
* waterfall 瀑布流
* @description 这是一个瀑布流形式的组件内容分为左右两列结合uView的懒加载组件效果更佳相较于某些只是奇偶数左右分别或者没有利用vue作用域插槽的做法uView的瀑布流实现了真正的 组件化搭配LazyLoad 懒加载和loadMore 加载更多组件让您开箱即用眼前一亮
* @tutorial https://www.uviewui.com/components/waterfall.html
* @property {Array} flow-list 用于渲染的数据
* @property {String Number} add-time 单条数据添加到队列的时间间隔单位ms见上方注意事项说明默认200
* @example <u-waterfall :flowList="flowList"></u-waterfall>
*/
export default {
name: "u-waterfall",
props: {
value: {
//
type: Array,
required: true,
default: function() {
return [];
}
},
//
// ms
addTime: {
type: [Number, String],
default: 200
},
// ididKey{idx: 22, name: 'lisa'}
// idKeyidx
idKey: {
type: String,
default: 'id'
}
},
provide() {
return {
uWaterfall: this
}
},
data() {
return {
leftList: [],
rightList: [],
tempList: [],
children: []
}
},
watch: {
copyFlowList(nVal, oVal) {
//
let startIndex = Array.isArray(oVal) && oVal.length > 0 ? oVal.length : 0;
//
this.tempList = this.tempList.concat(this.cloneData(nVal.slice(startIndex)));
this.splitData();
}
},
mounted() {
this.tempList = this.cloneData(this.copyFlowList);
this.splitData();
},
computed: {
// flowListwatch
copyFlowList() {
return this.cloneData(this.value);
}
},
methods: {
async splitData() {
if (!this.tempList.length) return;
let leftRect = await this.$uGetRect('#u-left-cloumn');
let rightRect = await this.$uGetRect('#u-right-cloumn');
//
let item = this.tempList[0];
// await
// []itemundefined
if(!item) return ;
if (leftRect.height < rightRect.height) {
this.leftList.push(item);
} else if (leftRect.height > rightRect.height) {
this.rightList.push(item);
} else {
//
// 0
if (this.leftList.length <= this.rightList.length) {
this.leftList.push(item);
} else {
this.rightList.push(item);
}
}
//
this.tempList.splice(0, 1);
//
if (this.tempList.length) {
setTimeout(() => {
this.splitData();
}, this.addTime)
}
},
//
cloneData(data) {
return JSON.parse(JSON.stringify(data));
},
//
clear() {
this.leftList = [];
this.rightList = [];
//
this.$emit('input', []);
},
// id
remove(id) {
// findIndex-1
let index = -1;
index = this.leftList.findIndex(val => val[this.idKey] == id);
if(index != -1) {
// index-1idindex
this.leftList.splice(index, 1);
} else {
//
index = this.rightList.findIndex(val => val[this.idKey] == id);
if(index != -1) this.rightList.splice(index, 1);
}
// id
index = this.value.findIndex(val => val[this.idKey] == id);
if(index != -1) this.$emit('input', this.value.splice(index, 1));
},
//
modify(id, key, value) {
// findIndex-1
let index = -1;
index = this.leftList.findIndex(val => val[this.idKey] == id);
if(index != -1) {
// index-1idkey
this.leftList[key] = value;
} else {
//
index = this.rightList.findIndex(val => val[this.idKey] == id);
if(index != -1) this.leftList[key] = value;
}
// id
index = this.value.findIndex(val => val[this.idKey] == id);
if(index != -1) {
// value
let data = this.cloneData(this.value);
// keyvalue
data[index][key] = value;
// v-model
this.$emit('input', data);
}
}
}
}
</script>
<style lang="scss" scoped>
.u-waterfall {
display: flex;
flex-direction: row;
align-items: flex-start;
}
.u-cloumn {
display: flex;
flex: 1;
flex-direction: column;
height: auto;
}
.u-image {
width: 100%;
}
</style>

880
node_modules/uview-ui/iconfont.css generated vendored Normal file

File diff suppressed because one or more lines are too long

116
node_modules/uview-ui/index.js generated vendored Normal file
View File

@ -0,0 +1,116 @@
// 引入全局mixin
import mixin from './libs/mixin/mixin.js'
// 引入关于是否mixin集成小程序分享的配置
import wxshare from './libs/mixin/mpShare.js'
// 全局挂载引入http相关请求拦截插件
import http from './libs/request'
function wranning(str) {
// 开发环境进行信息输出,主要是一些报错信息
// 这个环境的来由是在程序编写时候,点击hx编辑器运行调试代码的时候,详见:
// https://uniapp.dcloud.io/frame?id=%e5%bc%80%e5%8f%91%e7%8e%af%e5%a2%83%e5%92%8c%e7%94%9f%e4%ba%a7%e7%8e%af%e5%a2%83
if (process.env.NODE_ENV === 'development') {
console.warn(str)
}
}
// 尝试判断在根目录的/store中是否有$u.mixin.js此文件uView默认为需要挂在到全局的vuex的state变量
// HX2.6.11版本,放到try中,控制台依然会警告,暂时不用此方式,
// let vuexStore = {};
// try {
// vuexStore = require("@/store/$u.mixin.js");
// } catch (e) {
// //TODO handle the exception
// }
// post类型对象参数转为get类型url参数
import queryParams from './libs/function/queryParams.js'
// 路由封装
import route from './libs/function/route.js'
// 时间格式化
import timeFormat from './libs/function/timeFormat.js'
// 时间戳格式化,返回多久之前
import timeFrom from './libs/function/timeFrom.js'
// 颜色渐变相关,colorGradient-颜色渐变,hexToRgb-十六进制颜色转rgb颜色,rgbToHex-rgb转十六进制
import colorGradient from './libs/function/colorGradient.js'
// 生成全局唯一guid字符串
import guid from './libs/function/guid.js'
// 主题相关颜色,info|success|warning|primary|default|error,此颜色已在uview.scss中定义,但是为js中也能使用,故也定义一份
import color from './libs/function/color.js'
// 根据type获取图标名称
import type2icon from './libs/function/type2icon.js'
// 打乱数组的顺序
import randomArray from './libs/function/randomArray.js'
// 对象和数组的深度克隆
import deepClone from './libs/function/deepClone.js'
// 对象深度拷贝
import deepMerge from './libs/function/deepMerge.js'
// 规则检验
import test from './libs/function/test.js'
// 随机数
import random from './libs/function/random.js'
// 去除空格
import trim from './libs/function/trim.js'
// toast提示对uni.showToast的封装
import toast from './libs/function/toast.js'
// 配置信息
import config from './libs/config/config.js'
// 各个需要fixed的地方的z-index配置文件
import zIndex from './libs/config/zIndex.js'
const $u = {
queryParams: queryParams,
route: route,
timeFormat: timeFormat,
date: timeFormat, // 另名date
timeFrom,
colorGradient: colorGradient.colorGradient,
guid,
color,
type2icon,
randomArray,
wranning,
get: http.get,
post: http.post,
put: http.put,
'delete': http.delete,
hexToRgb: colorGradient.hexToRgb,
rgbToHex: colorGradient.rgbToHex,
test,
random,
deepClone,
deepMerge,
trim,
type: ['primary', 'success', 'error', 'warning', 'info'],
http,
toast,
config, // uView配置信息相关比如版本号
zIndex
}
const install = Vue => {
Vue.mixin(mixin)
if (Vue.prototype.openShare) {
Vue.mixin(mpShare);
}
// Vue.mixin(vuexStore);
// 时间格式化同时两个名称date和timeFormat
Vue.filter('timeFormat', (timestamp, format) => {
return timeFormat(timestamp, format)
})
Vue.filter('date', (timestamp, format) => {
return timeFormat(timestamp, format)
})
// 将多久以前的方法,注入到全局过滤器
Vue.filter('timeFrom', (timestamp, format) => {
return timeFrom(timestamp, format)
})
Vue.prototype.$u = $u
}
export default {
install
}

258
node_modules/uview-ui/index.scss generated vendored Normal file
View File

@ -0,0 +1,258 @@
// 引入公共基础类
@import "./libs/css/common.scss";
@import "./libs/css/color.scss";
page {
color: $u-main-color;
font-size: 28rpx;
}
image {
display: inline-block;
// 解决图片加载时可能会瞬间变形的问题
will-change: transform;
}
view,
text {
box-sizing: border-box;
flex-direction: row;
}
/* start--去除webkit的默认样式--start */
.u-fix-ios-appearance {
-webkit-appearance:none;
}
/* end--去除webkit的默认样式--end */
/* start--icon图标外层套一个view让其达到更好的垂直居中的效果--start */
.u-icon-wrap {
display: flex;
align-items: center;
}
/* end-icon图标外层套一个view让其达到更好的垂直居中的效果--end */
/* start--微信小程序编译后页面有组件名的元素,特别处理--start */
/* #ifdef MP-WEIXIN */
u-td, u-th {
flex: 1;
align-self: stretch;
}
.u-td {
height: 100%;
}
u-icon {
display: flex;
align-items: center;
}
// 各家小程序宫格组件外层设置为100%避免受到父元素display: flex;的影响
u-grid {
width: 100%;
flex: 0 0 100%;
}
/* #endif */
/* end-微信小程序编译后页面有组件名的元素,特别处理--end */
/* start--iPhoneX底部安全区定义--start */
.safe-area-inset-bottom {
padding-bottom: 0;
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
}
/* end-iPhoneX底部安全区定义--end */
/* start--各种hover点击反馈相关的类名-start */
.u-hover-class {
// background-color: #f7f8f9!important;
opacity: 0.6;
}
.u-cell-hover {
background-color: #f7f8f9!important;
}
/* end--各种hover点击反馈相关的类名--end */
/* start--文本行数限制--start */
.u-line-1 {
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.u-line-2 {
-webkit-line-clamp: 2;
}
.u-line-3 {
-webkit-line-clamp: 3;
}
.u-line-4 {
-webkit-line-clamp: 4;
}
.u-line-5 {
-webkit-line-clamp: 5;
}
.u-line-2, .u-line-3, .u-line-4, .u-line-5 {
overflow: hidden;
word-break: break-all;
text-overflow: ellipsis;
display: -webkit-box; // 弹性伸缩盒
-webkit-box-orient: vertical; // 设置伸缩盒子元素排列方式
}
/* end--文本行数限制--end */
/* start--Retina 屏幕下的 1px 边框--start */
.u-border,
.u-border-bottom,
.u-border-left,
.u-border-right,
.u-border-top,
.u-border-top-bottom {
position: relative
}
.u-border-bottom:after,
.u-border-left:after,
.u-border-right:after,
.u-border-top-bottom:after,
.u-border-top:after,
.u-border:after {
content: ' ';
position: absolute;
left: 0;
top: 0;
pointer-events: none;
box-sizing: border-box;
-webkit-transform-origin: 0 0;
transform-origin: 0 0;
// 多加0.1%能解决有时候边框缺失的问题
width: 199.8%;
height: 199.7%;
transform: scale(0.5, 0.5);
border: 0 solid $u-border-color;
z-index: 2;
}
.u-border-top:after {
border-top-width: 1px
}
.u-border-left:after {
border-left-width: 1px
}
.u-border-right:after {
border-right-width: 1px
}
.u-border-bottom:after {
border-bottom-width: 1px
}
.u-border-top-bottom:after {
border-width: 1px 0
}
.u-border:after {
border-width: 1px
}
/* end--Retina 屏幕下的 1px 边框--end */
/* start--clearfix--start */
.u-clearfix:after,
.clearfix:after {
content: "";
display: table;
clear: both
}
/* end--clearfix--end */
/* start--演示页面使用的统一样式--start */
.u-demo {
padding: 50rpx 40rpx;
}
.u-demo-wrap {
border: 1px dashed #ddd;
background-color: rgb(250, 250, 250);
padding: 40rpx 20rpx;
border-radius: 6px;
}
.u-demo-area {
text-align: center;
}
.u-no-demo-here {
color: $u-tips-color;
font-size: 26rpx;
}
.u-demo-result-line {
border: 1px dashed #ddd;
padding: 10rpx 40rpx;
margin-top: 30rpx;
border-radius: 5px;
background-color: rgb(240, 240, 240);
color: $u-content-color;
display: inline-block;
font-size: 32rpx;
transition: all 0.35s;
word-break: break-word;
text-align: left;
}
.u-demo-title,
.u-config-title {
text-align: center;
font-size: 32rpx;
font-weight: bold;
margin-bottom: 40rpx;
}
.u-config-item {
margin-top: 50rpx;
}
.u-config-title {
margin-top: 40rpx;
padding-bottom: 10rpx;
}
.u-item-title {
position: relative;
font-size: 28rpx;
padding-left: 8px;
line-height: 1;
margin-bottom: 22rpx;
}
.u-item-title:after {
position: absolute;
width: 4px;
top: -1px;
height: 16px;
content: '';
left: 0;
border-radius: 10px;
background-color: $u-content-color;
}
/* end--演示页面使用的统一样式--end */
/* start--高斯模糊tabbar底部处理--start */
.u-blur-effect-inset {
width: 750rpx;
height: var(--window-bottom);
background-color: #FFFFFF;
}
/* end--高斯模糊tabbar底部处理--end */

7
node_modules/uview-ui/libs/config/config.js generated vendored Normal file
View File

@ -0,0 +1,7 @@
// 此版本发布于2020-06-10
let version = '1.3.3';
export default {
v: version,
version: version
}

19
node_modules/uview-ui/libs/config/zIndex.js generated vendored Normal file
View File

@ -0,0 +1,19 @@
// uniapp在H5中各API的z-index值如下
/**
* actionsheet: 999
* modal: 999
* navigate: 998
* tabbar: 998
*/
export default {
toast: 10090,
noNetwork: 10080,
// popup包含popupactionsheetkeyboardpicker的值
popup: 10075,
mask: 10070,
navbar: 980,
topTips: 975,
sticky: 970,
indexListSticky: 965,
}

155
node_modules/uview-ui/libs/css/color.scss generated vendored Normal file
View File

@ -0,0 +1,155 @@
.u-type-primary-light {
color: $u-type-primary-light!important;
}
.u-type-warning-light {
color: $u-type-warning-light!important;
}
.u-type-success-light {
color: $u-type-success-light!important;
}
.u-type-error-light {
color: $u-type-error-light!important;
}
.u-type-info-light {
color: $u-type-info-light!important;
}
.u-type-primary-light-bg {
background-color: $u-type-primary-light!important;
}
.u-type-warning-light-bg {
background-color: $u-type-warning-light!important;
}
.u-type-success-light-bg {
background-color: $u-type-success-light!important;
}
.u-type-error-light-bg {
background-color: $u-type-error-light!important;
}
.u-type-info-light-bg {
background-color: $u-type-info-light!important;
}
.u-type-primary-dark {
color: $u-type-primary-dark!important;
}
.u-type-warning-dark {
color: $u-type-warning-dark!important;
}
.u-type-success-dark {
color: $u-type-success-dark!important;
}
.u-type-error-dark {
color: $u-type-error-dark!important;
}
.u-type-info-dark {
color: $u-type-info-dark!important;
}
.u-type-primary-dark-bg {
background-color: $u-type-primary-dark!important;
}
.u-type-warning-dark-bg {
background-color: $u-type-warning-dark!important;
}
.u-type-success-dark-bg {
background-color: $u-type-success-dark!important;
}
.u-type-error-dark-bg {
background-color: $u-type-error-dark!important;
}
.u-type-info-dark-bg {
background-color: $u-type-info-dark!important;
}
.u-type-primary-disabled {
color: $u-type-primary-disabled!important;
}
.u-type-warning-disabled {
color: $u-type-warning-disabled!important;
}
.u-type-success-disabled {
color: $u-type-success-disabled!important;
}
.u-type-error-disabled {
color: $u-type-error-disabled!important;
}
.u-type-info-disabled {
color: $u-type-info-disabled!important;
}
.u-type-primary {
color: $u-type-primary!important;
}
.u-type-warning {
color: $u-type-warning!important;
}
.u-type-success {
color: $u-type-success!important;
}
.u-type-error {
color: $u-type-error!important;
}
.u-type-info {
color: $u-type-info!important;
}
.u-type-primary-bg {
background-color: $u-type-primary!important;
}
.u-type-warning-bg {
background-color: $u-type-warning!important;
}
.u-type-success-bg {
background-color: $u-type-success!important;
}
.u-type-error-bg {
background-color: $u-type-error!important;
}
.u-type-info-bg {
background-color: $u-type-info!important;
}
.u-main-color {
color: $u-main-color;
}
.u-content-color {
color: $u-content-color;
}
.u-tips-color {
color: $u-tips-color;
}
.u-light-color {
color: $u-light-color;
}

154
node_modules/uview-ui/libs/css/common.scss generated vendored Normal file
View File

@ -0,0 +1,154 @@
.u-relative,
.u-rela {
position: relative;
}
.u-absolute,
.u-abso {
position: absolute;
}
.u-font-xs {
font-size: 22rpx;
}
.u-font-sm {
font-size: 26rpx;
}
.u-font-md {
font-size: 28rpx;
}
.u-font-lg {
font-size: 30rpx;
}
.u-font-xl {
font-size: 34rpx;
}
.u-flex {
display: flex;
flex-direction: row;
align-items: center;
}
.u-flex-wrap {
flex-wrap: wrap;
}
.u-flex-nowrap {
flex-wrap: nowrap;
}
.u-col-center {
align-items: center;
}
.u-col-top {
align-items: flex-start;
}
.u-col-bottom {
align-items: flex-end;
}
.u-row-center {
justify-content: center;
}
.u-row-left {
justify-content: flex-start;
}
.u-row-right {
justify-content: flex-end;
}
.u-row-between {
justify-content: space-between;
}
.u-row-around {
justify-content: space-around;
}
.u-text-left {
text-align: left;
}
.u-text-center {
text-align: center;
}
.u-text-right {
text-align: right;
}
.u-flex-col {
display: flex;
flex-direction: column;
}
// 定义flex等分
@for $i from 1 through 12 {
.u-flex-#{$i} {
flex: $i;
}
}
// 定义字体(px)单位小于20都为px单位字体
@for $i from 9 to 20 {
.u-font-#{$i} {
font-size: $i + px;
}
}
// 定义字体(rpx)单位大于或等于20的都为rpx单位字体
@for $i from 20 through 40 {
.u-font-#{$i} {
font-size: $i + rpx;
}
}
// 定义内外边距历遍1-80
@for $i from 0 through 80 {
// 只要双数和能被5除尽的数
@if $i % 2 == 0 or $i % 5 == 0 {
// 得出u-margin-30或者u-m-30
.u-margin-#{$i}, .u-m-#{$i} {
margin: $i + rpx!important;
}
// 得出u-padding-30或者u-p-30
.u-padding-#{$i}, .u-p-#{$i} {
padding: $i + rpx!important;
}
@each $short, $long in l left, t top, r right, b bottom {
// 缩写版结果如 u-m-l-30
// 定义外边距
.u-m-#{$short}-#{$i} {
margin-#{$long}: $i + rpx!important;
}
// 定义内边距
.u-p-#{$short}-#{$i} {
padding-#{$long}: $i + rpx!important;
}
// 完整版结果如u-margin-left-30
// 定义外边距
.u-margin-#{$long}-#{$i} {
margin-#{$long}: $i + rpx!important;
}
// 定义内边距
.u-padding-#{$long}-#{$i} {
padding-#{$long}: $i + rpx!important;
}
}
}
}

38
node_modules/uview-ui/libs/function/bem.js generated vendored Normal file
View File

@ -0,0 +1,38 @@
var array = require('./array.wxs');
var object = require('./object.wxs');
var PREFIX = 'van-';
function join(name, mods) {
name = PREFIX + name;
mods = mods.map(function(mod) {
return name + '--' + mod;
});
mods.unshift(name);
return mods.join(' ');
}
function traversing(mods, conf) {
if (!conf) {
return;
}
if (typeof conf === 'string' || typeof conf === 'number') {
mods.push(conf);
} else if (array.isArray(conf)) {
conf.forEach(function(item) {
traversing(mods, item);
});
} else if (typeof conf === 'object') {
object.keys(conf).forEach(function(key) {
conf[key] && mods.push(key);
});
}
}
function bem(name, conf) {
var mods = [];
traversing(mods, conf);
return join(name, mods);
}
module.exports.bem = bem;

Some files were not shown because too many files have changed in this diff Show More