增加补充相关资料和小程序源码

This commit is contained in:
Wang Beihong
2026-02-07 23:14:57 +08:00
parent a0febb1e5b
commit a9be1dd6b9
1255 changed files with 476253 additions and 0 deletions

View File

@@ -0,0 +1,124 @@
Component({
properties: {
//是否显示操作菜单
show: {
type: Boolean,
value: false
},
//菜单按钮数组,可自定义文本颜色
itemList: {
type: Array,
value: [],
observer(val) {
this.initData(val)
}
},
textKey: {
type: String,
value: 'text'
},
//菜单按钮字体大小 rpx
itemSize: {
type: String,
optionalTypes: [Number],
value: 32
},
//v2.4.0+
itemColor: {
type: String,
value: '#181818'
},
//v2.4.0+
itemDarkColor: {
type: String,
value: '#D1D1D1'
},
//提示信息
tips: {
type: String,
value: ""
},
//提示信息文本颜色
color: {
type: String,
value: "#7F7F7F"
},
//提示文字大小 rpx
size: {
type: String,
optionalTypes: [Number],
value: 26
},
//是否需要圆角
radius: {
type: Boolean,
value: true
},
//是否需要取消按钮
isCancel: {
type: Boolean,
value: true
},
//v2.4.0+
cancelSize: {
type: String,
optionalTypes: [Number],
value: 32
},
//light/dark
theme: {
type: String,
value: 'light'
},
//点击遮罩 是否可关闭
maskClosable: {
type: Boolean,
value: false
},
zIndex: {
type: String,
optionalTypes: [Number],
value: 1001
}
},
data: {
vals: []
},
lifetimes: {
attached: function () {
this.initData(this.data.itemList)
}
},
methods: {
initData(vals) {
if (vals && vals.length > 0) {
if (typeof vals[0] !== 'object') {
vals = vals.map(item => {
return {
[this.data.textKey]: item
}
})
}
this.setData({
vals: vals
})
}
},
handleClickMask() {
if (!this.data.maskClosable) return;
this.handleClickCancel();
},
handleClickItem(e) {
let index = Number(e.currentTarget.dataset.index)
if (!this.data.show) return;
this.triggerEvent('click', {
index: index,
...this.data.vals[index]
});
},
handleClickCancel() {
this.triggerEvent('cancel');
},
stop() {}
}
})

View File

@@ -0,0 +1,3 @@
{
"component": true
}

View File

@@ -0,0 +1,18 @@
<view catchtouchmove="stop">
<view class="fui-actionsheet__mask {{show?'fui-actionsheet__mask-show':''}}" bindtap="handleClickMask" style="{{parse.getStyle(zIndex)}}"></view>
<view class="fui-actionsheet__wrap {{show?'fui-actionsheet__show':''}} {{radius?'fui-actionsheet__radius':''}} {{theme==='light'?'fui-as__bg-light':''}} {{theme==='dark'?'fui-as__bg-dark':''}}" style="z-index:{{zIndex}}">
<text class="fui-actionsheet__tips {{radius?'fui-actionsheet__radius':''}} {{theme==='light'?'fui-as__btn-light':''}} {{theme==='dark'?'fui-as__btn-dark':''}}" style="font-size:{{size}}rpx;color:{{color}}" wx:if="{{tips}}">{{tips}}</text>
<view class="{{isCancel?'fui-actionsheet__operate-box':''}}">
<text class="fui-actionsheet__btn {{!isCancel && index==vals.length-1?'fui-actionsheet__btn-last':''}} {{radius && !tips && index===0?'fui-actionsheet__radius':''}} {{(index!==0 || tips) && theme==='light'?'fui-as__divider-light':''}} {{(index!==0 || tips) && theme==='dark'?'fui-as__divider-dark':''}} {{theme==='light'?'fui-as__btn-light':''}} {{theme==='dark'?'fui-as__btn-dark':''}}" style="color:{{theme==='dark'?(item.darkColor || itemDarkColor):(item.color || itemColor)}};font-size:{{item.size || itemSize}}rpx" wx:for="{{vals}}" wx:key="index" bindtap="handleClickItem" data-index="{{index}}">{{item[textKey]}}</text>
</view>
<text style="color:{{theme==='dark'?itemDarkColor:itemColor}};font-size:{{cancelSize || itemSize}}rpx" class="fui-actionsheet__btn fui-actionsheet__cancel {{theme==='light'?'fui-as__btn-light':''}} {{theme==='dark'?'fui-as__btn-dark':''}}" wx:if="{{isCancel}}" bindtap="handleClickCancel">取消</text>
</view>
</view>
<wxs module="parse">
module.exports = {
getStyle: function (zIndex) {
return "z-index:" + (parseInt(zIndex) - 10)
}
}
</wxs>

View File

@@ -0,0 +1,128 @@
.fui-actionsheet__wrap {
width: 100%;
visibility: hidden;
min-height: 100rpx;
position: fixed;
left: 0;
right: 0;
bottom: 0;
transform: translate3d(0, 100%, 0);
transition: all 0.25s ease-in-out;
transform-origin: center center;
}
.fui-as__bg-light {
background-color: #F8F8F8;
}
.fui-as__bg-dark {
background-color: #111111;
}
.fui-actionsheet__radius {
border-top-left-radius: 24rpx;
border-top-right-radius: 24rpx;
overflow: hidden;
}
.fui-actionsheet__show {
transform: translate3d(0, 0, 0);
visibility: visible;
}
.fui-actionsheet__tips {
width: 100%;
box-sizing: border-box;
flex: 1;
padding: 40rpx 60rpx;
text-align: center;
display: flex;
align-items: center;
justify-content: center;
font-weight: normal;
}
.fui-as__btn-light {
background-color: #FFFFFF;
}
.fui-as__btn-dark {
background-color: #222222;
}
.fui-actionsheet__operate-box {
padding-bottom: 12rpx;
}
.fui-actionsheet__btn {
width: 100%;
flex: 1;
height: 100rpx;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
/* font-size: 32rpx; */
font-weight: normal;
position: relative;
}
.fui-actionsheet__btn:active {
background-color: var(--fui-bg-color-hover, rgba(0, 0, 0, 0.2)) !important;
}
.fui-actionsheet__btn-last {
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
}
.fui-as__divider-light::before {
content: " ";
position: absolute;
top: 0;
right: 0;
left: 0;
border-top: 1px solid var(--fui-color-border, #EEEEEE);
-webkit-transform: scaleY(0.5);
transform: scaleY(0.5);
transform-origin: 0 0;
z-index: 2;
pointer-events: none;
}
.fui-as__divider-dark::before {
content: " ";
position: absolute;
top: 0;
right: 0;
left: 0;
border-top: 1px solid #333;
-webkit-transform: scaleY(0.5);
transform: scaleY(0.5);
transform-origin: 0 0;
z-index: 2;
pointer-events: none;
}
.fui-actionsheet__cancel {
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
}
.fui-actionsheet__mask {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: var(--fui-bg-color-mask, rgba(0, 0, 0, 0.6));
transition: opacity 0.3s ease-in-out;
opacity: 0;
visibility: hidden;
}
.fui-actionsheet__mask-show {
visibility: visible;
opacity: 1;
}

View File

@@ -0,0 +1,112 @@
Component({
options: {
multipleSlots: true
},
properties: {
//info, success, warn, waiting,clear
type: {
type: String,
value: ''
},
//背景色如果设置type对应颜色失效
background: {
type: String,
value: ''
},
//padding值
padding: {
type: String,
value:'20rpx 32rpx'
},
//margin-top值单位rpx
marginTop: {
type: String,
optionalTypes: [Number],
value: 0
},
//margin-bottom值单位rpx
marginBottom: {
type: String,
optionalTypes: [Number],
value: 0
},
//圆角
radius: {
type: String,
value: '16rpx'
},
//icon颜色
iconColor: {
type: String,
value: '#fff'
},
//icon字体大小px
iconSize: {
type: Number,
value: 22
},
closable: {
type: Boolean,
value: false
},
closeColor: {
type: String,
value: '#fff'
},
//关闭icon字体大小px
closeSize: {
type: Number,
value: 22
},
//是否自定义左侧内容,默认图标失效
isLeft: {
type: Boolean,
value: false
},
//内容是否与图标之间有间隔isLeft为true时生效
spacing: {
type: Boolean,
value: false
},
title: {
type: String,
value: ''
},
color: {
type: String,
value: '#fff'
},
size: {
type: String,
value: '14px'
},
desc: {
type: String,
value: ''
},
descColor: {
type: String,
value: '#fff'
},
descSize: {
type: String,
value: '12px'
},
//描述文字单行展示,超出隐藏
single: {
type: Boolean,
value: false
}
},
methods: {
leftClick() {
this.triggerEvent('leftClick', {})
},
onClick() {
this.triggerEvent('click', {})
},
close() {
this.triggerEvent('close', {})
}
}
})

View File

@@ -0,0 +1,3 @@
{
"component": true
}

View File

@@ -0,0 +1,30 @@
<view class="fui-alert__wrap {{background?'':'fui-alert__'+type}}" style="background:{{background || parse.getColor(type)}};border-radius:{{radius}};padding:{{padding}};margin-top:{{marginTop}}rpx;margin-bottom:{{marginBottom}}rpx">
<view class="fui-alert__shrink" catchtap="leftClick">
<slot></slot>
<icon type="{{type}}" size="{{iconSize}}" color="{{iconColor}}" wx:if="{{!isLeft && type && type!==true}}"></icon>
</view>
<view class="fui-alert__content {{(!isLeft && type && type!=='true') || (spacing && isLeft)?'fui-text__p-left':''}} {{closable?'fui-text__p-right':''}}" catchtap="onClick">
<text class="fui-alert__text" style="font-size:{{size}};color:{{color}}" wx:if="{{title}}">{{title}}</text>
<text class="fui-alert__text fui-desc__padding {{single?'fui-alert__single':''}}" style="font-size:{{descSize}};color:{{descColor}}" wx:if="{{desc}}">{{desc}}</text>
<slot name="content"></slot>
</view>
<view class="fui-alert__shrink">
<slot name="right"></slot>
</view>
<icon catchtap="close" type="cancel" size="{{closeSize}}" color="{{closeColor}}" wx:if="{{closable}}" class=" {{desc?'fui-alert__icon-close':''}}">
</icon>
</view>
<wxs module="parse">
module.exports = {
getColor: function (type) {
var color = "#465CFF"
var colors = {
'success': '#09BE4F',
'warn': '#FFB703',
'clear': '#FF2B2B'
}
return colors[type] ? colors[type] : color;
}
}
</wxs>

View File

@@ -0,0 +1,71 @@
.fui-alert__wrap {
display: flex;
width: 100%;
box-sizing: border-box;
flex-direction: row;
align-items: center;
position: relative;
}
.fui-alert__info,
.fui-alert__waiting {
background-color: var(--fui-color-primary, #465CFF) !important;
}
.fui-alert__success {
background-color: var(--fui-color-success, #09BE4F) !important;
}
.fui-alert__warn {
background-color: var(--fui-color-warning, #FFB703) !important;
}
.fui-alert__clear {
background-color: var(--fui-color-danger, #FF2B2B) !important;
}
.fui-alert__shrink {
flex-shrink: 0;
display: flex;
align-items: center;
justify-content: center;
}
.fui-alert__content {
flex: 1;
flex-direction: column;
overflow: hidden;
}
.fui-alert__text {
word-break: break-all;
display: block;
box-sizing: border-box;
}
.fui-desc__padding {
padding-top: 3px;
}
.fui-text__p-left {
padding-left: 20rpx;
}
.fui-text__p-right {
padding-right: 60rpx;
}
.fui-alert__single {
display: block;
width: 100%;
white-space: nowrap;
flex-direction: row;
overflow: hidden;
text-overflow: ellipsis;
}
.fui-alert__icon-close {
position: absolute;
right: 30rpx;
top: 16rpx;
}

View File

@@ -0,0 +1,180 @@
Component({
properties: {
//是否显示
show: {
type: Boolean,
value: false,
observer(newVal) {
if (newVal) {
this.open();
} else {
this.data.isShow && this.close();
}
}
},
/*
过渡动画类型
['fade,'slide-top','slide-right','slide-bottom','slide-left','zoom-in','zoom-out']
*/
animationType: {
type: Array,
value: []
},
duration: {
type: Number,
value: 300
},
//styles 组件样式,同 css 样式
styles: {
type: Object,
value: {},
observer(val) {
this.setData({
stylesObject: this.getStylesObject()
})
}
}
},
data: {
isShow: false,
transform: '',
ani: {
in: '',
active: ''
},
stylesObject: ''
},
lifetimes: {
attached: function () {
this.setData({
stylesObject: this.getStylesObject()
})
}
},
methods: {
getStylesObject() {
//默认值
const defStyles = {
position: 'fixed',
bottom: 0,
top: 0,
left: 0,
right: 0,
display: 'flex',
'justify-content': 'center',
'align-items': 'center'
};
const mergeStyles = Object.assign({}, defStyles, this.data.styles);
let styles = {
...mergeStyles,
'transition-duration': this.data.duration / 1000 + 's'
};
let transfrom = '';
for (let i in styles) {
let line = this.toLine(i);
transfrom += line + ':' + styles[i] + ';';
}
return transfrom;
},
change() {
this.triggerEvent('click', {
value: this.data.isShow
});
},
open() {
clearTimeout(this.data.timer);
let ani_in = `ani.in`
this.setData({
isShow: true,
transform: '',
[ani_in]: ''
})
let transform = ''
for (let i in this.getTranfrom(false)) {
if (i === 'opacity') {
let ani_in = `ani.in`
this.setData({
[ani_in]: 'fui-popup__fade-out'
})
} else {
transform += `${this.getTranfrom(false)[i]} `;
}
}
this.setData({
transform: transform
}, () => {
setTimeout(() => {
this._animation(true);
}, 50);
})
},
close(type) {
clearTimeout(this.data.timer);
this._animation(false);
},
_animation(type) {
let styles = this.getTranfrom(type);
this.setData({
transform: ''
})
let transform = ''
let ani_in = `ani.in`
for (let i in styles) {
if (i === 'opacity') {
this.setData({
[ani_in]: `fui-popup__fade-${type ? 'in' : 'out'}`
})
} else {
transform += `${styles[i]} `;
}
}
this.setData({
transform: transform
})
this.data.timer = setTimeout(() => {
if (!type) {
this.setData({
isShow: false
})
}
this.triggerEvent('change', {
value: this.data.isShow
});
}, this.data.duration);
},
getTranfrom(type) {
let styles = {
transform: ''
};
this.data.animationType.forEach(mode => {
switch (mode) {
case 'fade':
styles.opacity = type ? 1 : 0;
break;
case 'slide-top':
styles.transform += `translateY(${type ? '0' : '-100%'}) `;
break;
case 'slide-right':
styles.transform += `translateX(${type ? '0' : '100%'}) `;
break;
case 'slide-bottom':
styles.transform += `translateY(${type ? '0' : '100%'}) `;
break;
case 'slide-left':
styles.transform += `translateX(${type ? '0' : '-100%'}) `;
break;
case 'zoom-in':
styles.transform += `scale(${type ? 1 : 0.8}) `;
break;
case 'zoom-out':
styles.transform += `scale(${type ? 1 : 1.2}) `;
break;
}
});
return styles;
},
toLine(name) {
return name.replace(/([A-Z])/g, '-$1').toLowerCase();
}
}
})

View File

@@ -0,0 +1,3 @@
{
"component": true
}

View File

@@ -0,0 +1,4 @@
<view wx:if="{{isShow}}" class="fui-popup__animation {{ani.in}}"
style="{{'transform:' + transform + ';' + stylesObject}}" bindtap="change">
<slot></slot>
</view>

View File

@@ -0,0 +1,20 @@
.fui-popup__animation {
transition-timing-function: ease;
transition-duration: 0.3s;
transition-property: transform, opacity;
position: relative;
z-index: 99;
}
.fui-popup__fade-out {
opacity: 0;
}
.fui-popup__fade-in {
opacity: 1;
}
.fui-popup__unshow{
opacity: 0;
visibility: hidden;
}

View File

@@ -0,0 +1,144 @@
Component({
properties: {
src: {
type: String,
value: '',
observer(val){
if(val){
this.setData({
showImg: val
})
}
}
},
errorSrc: {
type: String,
value: ''
},
mode: {
type: String,
value: 'scaleToFill'
},
//微信小程序、百度小程序、字节跳动小程序
//图片懒加载。只针对page与scroll-view下的image有效
lazyLoad: {
type: Boolean,
value: true
},
//默认不解析 webP 格式,只支持网络资源 微信小程序2.9.0
webp: {
type: Boolean,
value: false
},
background: {
type: String,
value: '#D1D1D1'
},
//small64、middle96、large128
size: {
type: String,
value: 'middle'
},
//图片宽度设置大于0的数值生效默认使用size
width: {
type: String,
optionalTypes: [Number],
value: 0
},
//默认等宽设置图大于0的数值且设置了图片宽度生效
height: {
type: String,
optionalTypes: [Number],
value: 0
},
//指定头像的形状,可选值为 circle、square
shape: {
type: String,
value: 'circle'
},
//图片圆角值默认使用shape当设置大于等于0的数值shape失效
radius: {
type: String,
optionalTypes: [Number],
value: -1
},
//没有src时可以使用文本代替
text: {
type: String,
value: ''
},
color: {
type: String,
value: '#fff'
},
//默认使用size下字体大小
fontSize: {
type: String,
optionalTypes: [Number],
value: 0
},
fontWeight: {
type: String,
optionalTypes: [Number],
value: 600
},
marginRight: {
type: String,
optionalTypes: [Number],
value: 0
},
marginBottom: {
type: String,
optionalTypes: [Number],
value: 0
},
block: {
type: Boolean,
value: false
},
//在列表中的索引值
index: {
type: Number,
value: 0
},
//其他参数
params: {
type: String,
optionalTypes: [Number],
value: 0
}
},
data:{
showImg:''
},
lifetimes:{
attached:function(){
if(this.data.src){
this.setData({
showImg: this.data.src
})
}
}
},
methods: {
handleError(e) {
if (this.data.src) {
if(this.data.errorSrc){
this.setData({
showImg: this.data.errorSrc
})
}
this.triggerEvent('error', {
index: this.data.index,
params: this.data.params
})
}
},
handleClick() {
this.triggerEvent('click', {
index: this.data.index,
params: this.data.params
})
}
}
})

View File

@@ -0,0 +1,4 @@
{
"component": true,
"usingComponents": {}
}

View File

@@ -0,0 +1,33 @@
<view class="fui-avatar__wrap {{width?'':'fui-avatar__size-'+size}} {{radius===-1?'fui-avatar__'+shape:''}} {{block?'fui-avatar__block':'fui-avatar__inline'}}" style="{{parse.wrapStyles(background, marginRight, marginBottom, width, height, radius)}}" bindtap="handleClick">
<image class="fui-avatar__img {{radius===-1?'fui-avatar__'+shape:''}} {{width?'':'fui-avatar__size-'+size}}" style="{{parse.styles(width, height, radius)}}" src="{{showImg}}" mode="{{mode}}" wx:if="{{src && src!==true}}" webp="{{webp}}" lazy-load="{{lazyLoad}}" binderror="handleError"></image>
<text class="fui-avatar__text {{width?'':'fui-avatar__text-'+size}}" wx:if="{{!src && src!==true && text}}" style="{{parse.textStyles(color, fontWeight, fontSize)}}">{{text}}</text>
<slot></slot>
</view>
<wxs module="parse">
var styles = function (width, height, radius) {
var styles = '';
if (width) {
styles = "width:" + width + "rpx;height:" + (height || width) + "rpx;"
}
if (radius !== -1) {
styles += "border-radius:" + radius + "rpx;"
}
return styles;
}
module.exports = {
wrapStyles: function (background, marginRight, marginBottom, width, height, radius) {
var style = "background:" + background + ";margin-right:" + marginRight + "rpx;margin-bottom:" + marginBottom + "rpx;"
return style + styles(width, height, radius)
},
styles: styles,
textStyles: function (color, fontWeight, fontSize) {
var styles = "color:" + color + ";font-weight:" + fontWeight + ";";
if (fontSize) {
styles += "font-size:" + fontSize + "rpx;"
}
return styles;
}
}
</wxs>

View File

@@ -0,0 +1,68 @@
.fui-avatar__wrap {
position: relative;
flex-direction: row;
align-items: center;
justify-content: center;
z-index: 3;
overflow: hidden;
}
.fui-avatar__block {
display: flex;
}
.fui-avatar__inline {
display: inline-flex;
vertical-align: middle;
}
.fui-avatar__img {
flex: 1;
display: block;
object-fit: cover;
}
.fui-avatar__text {
flex: 1;
display: block;
white-space: nowrap;
box-sizing: border-box;
overflow: hidden;
text-overflow: ellipsis;
text-align: center;
}
.fui-avatar__size-small {
width: 64rpx !important;
height: 64rpx !important;
}
.fui-avatar__text-small {
font-size: 32rpx !important;
}
.fui-avatar__size-middle {
width: 96rpx !important;
height: 96rpx !important;
}
.fui-avatar__text-middle {
font-size: 44rpx !important;
}
.fui-avatar__size-large {
width: 128rpx !important;
height: 128rpx !important;
}
.fui-avatar__text-large {
font-size: 56rpx !important;
}
.fui-avatar__circle {
border-radius: 50% !important;
}
.fui-avatar__square {
border-radius: 8rpx !important;
}

View File

@@ -0,0 +1,31 @@
Component({
properties: {
show: {
type: Boolean,
value: false
},
background: {
type: String,
value: ''
},
absolute: {
type: Boolean,
value: false
},
zIndex: {
type: Number,
value: 999
},
closable: {
type: Boolean,
value: false
}
},
methods: {
handleClick() {
if (this.data.closable && this.data.show) {
this.triggerEvent('click')
}
}
}
})

View File

@@ -0,0 +1,3 @@
{
"component": true
}

View File

@@ -0,0 +1,3 @@
<view class="fui-backdrop__wrap {{background?'':'fui-backdrop__bg'}} {{show?'fui-backdrop__show':''}}" style="background:{{background}};position:{{absolute?'absolute':'fixed'}};z-index:{{zIndex}}" bindtap="handleClick">
<slot></slot>
</view>

View File

@@ -0,0 +1,21 @@
.fui-backdrop__wrap {
left: 0;
right: 0;
top: 0;
bottom: 0;
display: flex;
opacity: 0;
visibility: hidden;
transition: all 0.3s;
align-items: center;
justify-content: center;
}
.fui-backdrop__bg {
background: var(--fui-bg-color-mask, rgba(0, 0, 0, 0.6)) !important;
}
.fui-backdrop__show {
visibility: visible !important;
opacity: 1 !important;
}

View File

@@ -0,0 +1,119 @@
Component({
properties: {
value: {
type: String,
optionalTypes: [Number],
value: '',
observer(val) {
this.getWidth()
}
},
max:{
type: String,
optionalTypes: [Number],
value: -1
},
//类型primarysuccesswarningdangerpurplewhite
type: {
type: String,
value: 'primary'
},
//背景色如果设置背景则type失效
background: {
type: String,
value: ''
},
//字体颜色
color: {
type: String,
value: '#FFFFFF'
},
//是否显示为圆点
dot: {
type: Boolean,
value: false
},
//margin-top值单位rpx
marginTop: {
type: String,
optionalTypes: [Number],
value: 0
},
//margin-left值单位rpx
marginLeft: {
type: String,
optionalTypes: [Number],
value: 0
},
//margin-right值单位rpx
marginRight: {
type: String,
optionalTypes: [Number],
value: 0
},
//是否绝对定位
absolute: {
type: Boolean,
value: false
},
top: {
type: String,
value: '-8rpx'
},
right: {
type: String,
value: '-18rpx'
},
//缩放比例
scaleRatio: {
type: Number,
value: 1
}
},
data: {
width: 0,
showValue: ''
},
lifetimes: {
ready() {
this.getWidth()
}
},
methods: {
_getTextWidth(text) {
let sum = 0;
for (let i = 0, len = text.length; i < len; i++) {
if (text.charCodeAt(i) >= 0 && text.charCodeAt(i) <= 255)
sum = sum + 1;
else
sum = sum + 2;
}
const sys = wx.getSystemInfoSync()
const px = sys.windowWidth / 750 * (text.length > 1 ? 32 : 24)
var strCode = text.charCodeAt();
let multiplier = 12;
if (strCode >= 65 && strCode <= 90) {
multiplier = 15;
}
return (sum / 2 * multiplier) + px + 'px';
},
getWidth() {
let max = Number(this.data.max)
let val = Number(this.data.value)
let value = ''
if (val === NaN || max === -1) {
value = this.data.value
} else {
value = val > max ? `${max}+` : val
}
let width = this.data.dot ? '8px' : this._getTextWidth(String(value))
this.setData({
showValue:value,
width: width
})
},
handleClick() {
this.triggerEvent('click');
}
}
})

View File

@@ -0,0 +1,3 @@
{
"component": true
}

View File

@@ -0,0 +1 @@
<text class="{{dot?'fui-badge__dot':'fui-badge__wrap'}} {{background?'':('fui-badge__bg-'+type)}} {{absolute?'fui-badge__absolute':''}} {{!background && type==='white'?'fui-badge__text-color':''}}" style="top:{{absolute?top:'auto'}};right:{{absolute?right:'auto'}};zoom:{{scaleRatio}};margin-top:{{marginTop}}rpx;margin-left:{{marginLeft}}rpx;margin-right:{{marginRight}}rpx;width:{{width}};color:{{color}};background:{{background}}" bindtap="handleClick" wx:if="{{showValue || dot}}">{{dot?'':showValue}}</text>

View File

@@ -0,0 +1,55 @@
.fui-badge__wrap {
height: 36rpx;
padding: 0 12rpx;
color: #FFFFFF;
font-size: 24rpx;
line-height: 36rpx;
border-radius: 100px;
min-width: 36rpx !important;
display: flex;
box-sizing: border-box;
flex-direction: row;
align-items: center;
justify-content: center;
z-index: 10;
}
.fui-badge__dot {
height: 8px !important;
width: 8px !important;
display: inline-block;
border-radius: 50%;
z-index: 10;
}
.fui-badge__bg-primary {
background-color: var(--fui-color-primary, #465CFF) !important;
}
.fui-badge__bg-success {
background-color: var(--fui-color-success, #09BE4F) !important;
}
.fui-badge__bg-warning {
background-color: var(--fui-color-warning, #FFB703) !important;
}
.fui-badge__bg-danger {
background-color: var(--fui-color-danger, #FF2B2B) !important;
}
.fui-badge__bg-purple {
background-color: var(--fui-color-purple, #6831FF) !important;
}
.fui-badge__bg-white {
background-color: var(--fui-color-white, #FFFFFF) !important;
}
.fui-badge__text-color {
color: var(--fui-color-danger, #FF2B2B) !important;
}
.fui-badge__absolute {
position: absolute;
}

View File

@@ -0,0 +1,40 @@
Component({
properties: {
show: {
type: Boolean,
value: false
},
//背景颜色
background: {
type: String,
value: '#fff'
},
//圆角
radius: {
type: Number,
optionalTypes: [String],
value: 24
},
zIndex: {
type: Number,
optionalTypes: [String],
value: 1001
},
//点击遮罩 是否可关闭
maskClosable: {
type: Boolean,
value: true
},
maskBackground: {
type: String,
value: 'rgba(0,0,0,.6)'
}
},
methods: {
handleClose(e) {
if (!this.data.maskClosable) return;
this.triggerEvent('close', {});
},
stop(e) {}
}
})

View File

@@ -0,0 +1,3 @@
{
"component": true
}

View File

@@ -0,0 +1,5 @@
<view class="fui-bottom__popup-wrap {{show?'fui-bottom__popwrap-show':''}}" style="z-index:{{zIndex}};background:{{maskBackground}}" catchtap="handleClose" catchtouchmove="stop">
<view class="fui-bottom__popup {{show?'fui-bottom__popup-show':''}}" style="border-top-left-radius:{{radius}}rpx;border-top-right-radius:{{radius}}rpx;background:{{background}}" catchtap="stop">
<slot></slot>
</view>
</view>

View File

@@ -0,0 +1,36 @@
.fui-bottom__popup-wrap {
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
z-index: 1001;
display: flex;
flex-direction: row;
align-items: flex-end;
justify-content: center;
transition: all ease-in-out .2s;
visibility: hidden;
opacity: 0;
overflow: hidden;
}
.fui-bottom__popwrap-show {
opacity: 1;
visibility: visible;
}
.fui-bottom__popup {
width: 100%;
transform: translate3d(0, 100%, 0);
transition: all 0.3s ease-in-out;
min-height: 20rpx;
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
flex: 1;
overflow: hidden;
}
.fui-bottom__popup-show {
transform: translate3d(0, 0, 0);
}

View File

@@ -0,0 +1,224 @@
Component({
behaviors: ['wx://form-field-button'],
properties: {
//样式类型primarysuccess warningdangerlinkpurplegray
type: {
type: String,
value: 'primary'
},
//按钮背景色当传入值时type失效
background: {
type: String,
value: ''
},
//按钮显示文本
text: {
type: String,
value: ''
},
//按钮字体颜色
color: {
type: String,
value: '#fff'
},
//按钮禁用背景色
disabledBackground: {
type: String,
value: ''
},
//按钮禁用字体颜色
disabledColor: {
type: String,
value: ''
},
borderWidth: {
type: String,
value: '1px'
},
borderColor: {
type: String,
value: ''
},
//V1.9.8+ 按钮大小优先级高于width和heightmedium、small、mini
btnSize: {
type: String,
value: ''
},
//宽度
width: {
type: String,
value: '100%'
},
//高度
height: {
type: String,
value: ''
},
//字体大小单位rpx
size: {
type: Number,
optionalTypes: [String],
value: 0
},
bold: {
type: Boolean,
value: false
},
margin: {
type: String,
value: '0'
},
//圆角
radius: {
type: String,
value: ''
},
plain: {
type: Boolean,
value: false
},
disabled: {
type: Boolean,
value: false
},
loading: {
type: Boolean,
value: false
},
formType: {
type: String,
value: ''
},
openType: {
type: String,
value: ''
},
appParameter: {
type: String,
value: ''
},
//v2.3.0+
hoverStopPropagation: {
type: Boolean,
value: false
},
lang: {
type: String,
value: 'en'
},
sessionFrom: {
type: String,
value: ''
},
sendMessageTitle: {
type: String,
value: ''
},
sendMessagePath: {
type: String,
value: ''
},
sendMessageImg: {
type: String,
value: ''
},
showMessageCard: {
type: Boolean,
value: false
},
phoneNumberNoQuotaToast: {
type: Boolean,
value: true
},
index: {
type: Number,
optionalTypes: [String],
value: 0
}
},
data: {
time: 0,
trigger: false,
tap: false,
c_height: (wx.$fui && wx.$fui.fuiButton.height) || '96rpx',
c_size: (wx.$fui && wx.$fui.fuiButton.size) || 32,
c_radius: (wx.$fui && wx.$fui.fuiButton.radius) || '16rpx'
},
methods: {
handleStart() {
if (this.data.disabled) return;
this.data.trigger = false;
this.data.tap = true;
if (new Date().getTime() - this.data.time <= 150) return;
this.data.trigger = true;
this.setData({
time: new Date().getTime()
})
},
handleClick() {
if (this.data.disabled || !this.data.trigger) return;
this.setData({
time: 0
})
},
handleEnd() {
if (this.data.disabled) return;
setTimeout(() => {
this.setData({
time: 0
})
}, 150);
},
handleTap() {
if (this.disabled) return;
this.triggerEvent('click', {
index: Number(this.data.index)
});
},
bindgetuserinfo({
detail = {}
} = {}) {
this.triggerEvent('getuserinfo', detail);
},
bindcontact({
detail = {}
} = {}) {
this.triggerEvent('contact', detail);
},
bindgetphonenumber({
detail = {}
} = {}) {
this.triggerEvent('getphonenumber', detail);
},
binderror({
detail = {}
} = {}) {
this.triggerEvent('error', detail);
},
bindopensetting({
detail = {}
} = {}) {
this.triggerEvent('opensetting', detail);
},
bindchooseavatar({
detail = {}
} = {}) {
this.triggerEvent('chooseavatar', detail);
},
bindlaunchapp({
detail = {}
} = {}) {
this.triggerEvent('launchapp', detail);
},
agreeprivacyauthorization({
detail = {}
} = {}) {
this.triggerEvent('agreeprivacyauthorization', detail);
},
bindgetrealtimephonenumber({
detail = {}
} = {}) {
this.triggerEvent('getrealtimephonenumber', detail);
}
}
})

View File

@@ -0,0 +1,3 @@
{
"component": true
}

View File

@@ -0,0 +1,64 @@
<view class="fui-button__wrap {{(!width || width==='100%' || width===true) && !btnSize?'fui-button__flex-1':''}}" style="width: {{parse.getWidth(width,btnSize)}};height: {{parse.getHeight(height,btnSize,c_height)}};margin:{{margin}};border-radius:{{radius}}" bindtouchstart="handleStart" bindtouchend="handleClick" bindtouchcancel="handleEnd">
<button
class="fui-button {{bold ? 'fui-text__bold' : ''}} {{ time && (plain || type==='link') ? 'fui-button__opacity' : ''}} {{disabled && !disabledBackground ? 'fui-button__opacity' : ''}} {{!background && !disabledBackground && !plain?('fui-button__'+type):''}} {{(!width || width==='100%' || width===true) && !btnSize?'fui-button__flex-1':''}} {{time && !plain && type!=='link' ? 'fui-button__active' : ''}}"
style="width: {{parse.getWidth(width,btnSize)}};height: {{parse.getHeight(height,btnSize,c_height)}};line-height: {{parse.getHeight(height,btnSize,c_height)}};background: {{disabled && disabledBackground ? disabledBackground : (plain ? 'transparent' : background)}};border-radius: {{radius}};font-size: {{parse.getSize(size,btnSize,c_size)}}rpx;color: {{disabled && disabledBackground ? disabledColor : color}}"
loading="{{loading}}" form-type="{{formType}}" app-parameter="{{appParameter}}" open-type="{{openType}}" hoverStopPropagation="{{hoverStopPropagation}}" lang="{{lang}}" sessionFrom="{{sessionFrom}}" sendMessageTitle="{{sendMessageTitle}}" sendMessagePath="{{sendMessagePath}}" sendMessageImg="{{sendMessageImg}}" showMessageCard="{{showMessageCard}}" phoneNumberNoQuotaToast="{{phoneNumberNoQuotaToast}}" bindgetuserinfo="bindgetuserinfo"
bindgetphonenumber="bindgetphonenumber" bindcontact="bindcontact" binderror="binderror"
bindopensetting="bindopensetting" bindchooseavatar="bindchooseavatar" bindlaunchapp="bindlaunchapp" bindagreeprivacyauthorization="agreeprivacyauthorization" bindgetrealtimephonenumber="bindgetrealtimephonenumber" disabled="{{disabled}}" catchtap="handleTap">
<text
class="fui-button__text {{!background && !disabledBackground && !plain && type==='gray' && color==='#fff'?'fui-btn__gray-color':''}} {{bold?'fui-text__bold':''}}"
wx:if="{{text}}"
style="font-size: {{parse.getSize(size,btnSize,c_size)}}rpx;line-height:{{parse.getSize(size,btnSize,c_size)}}rpx;color:{{disabled && disabledBackground ? disabledColor : color}}">{{text}}</text>
<slot></slot>
</button>
<view wx:if="{{borderColor}}" class="fui-button__thin-border {{time && (plain || type==='link') && !disabled ? 'fui-button__opacity' : ''}} {{disabled && !disabledBackground ? 'fui-button__opacity' : ''}}"
style="border-width:{{borderWidth}};border-color:{{borderColor ? borderColor : disabled && disabledBackground ? disabledBackground : (background || 'transparent')}};border-radius:{{parse.getBorderRadius(radius,c_radius)}}">
</view>
</view>
<wxs module="parse">
module.exports={
getBorderRadius:function(radius,c_radius) {
var radius = radius || c_radius || '0'
if (~radius.indexOf('rpx')) {
radius = (parseInt(radius.replace('rpx', '')) * 2) + 'rpx'
} else if (~radius.indexOf('px')) {
radius = (parseInt(radius.replace('px', '')) * 2) + 'px'
} else if (~radius.indexOf('%')) {
radius = (parseInt(radius.replace('%', '')) * 2) + '%'
}
return radius
},
getWidth:function(width,btnSize){
var w = width;
if (btnSize && btnSize !== true) {
w = {
'medium': '400rpx',
'small': '200rpx',
'mini': '120rpx'
} [btnSize] || w
}
return w
},
getHeight:function(height,btnSize,c_height) {
var h = height || c_height
if (btnSize && btnSize !== true) {
h = {
'medium': '84rpx',
'small': '72rpx',
'mini': '64rpx'
} [btnSize] || height
}
return h
},
getSize:function(size,btnSize,c_size) {
var fontSize = size || c_size;
if (btnSize === 'small') {
fontSize = fontSize > 28 ? 28 : fontSize;
} else if (btnSize === 'mini') {
fontSize = fontSize > 28 ? 24 : fontSize;
}
return fontSize;
}
}
</wxs>

View File

@@ -0,0 +1,116 @@
.fui-button__wrap {
position: relative;
}
.fui-button__thin-border {
position: absolute;
width: 200%;
height: 200%;
transform-origin: 0 0;
transform: scale(0.5, 0.5) translateZ(0);
box-sizing: border-box;
left: 0;
top: 0;
border-radius: 32rpx;
border-style: solid;
pointer-events: none;
}
.fui-button {
border-width: 0;
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
border-style: solid;
position: relative;
padding-left: 0;
padding-right: 0;
overflow: hidden;
transform: translateZ(0);
-webkit-touch-callout: none;
-webkit-user-select: none;
user-select: none;
}
.fui-button__flex-1 {
flex: 1;
width: 100%;
}
.fui-button::after {
border: 0;
}
.fui-button__active {
overflow: hidden !important;
}
.fui-button__active::after {
content: ' ';
background-color: var(--fui-bg-color-hover, rgba(0, 0, 0, 0.2));
position: absolute;
width: 100%;
height: 100%;
left: 0;
right: 0;
top: 0;
transform: none;
z-index: 1;
border-radius: 0;
}
.fui-button__text {
text-align: center;
flex-direction: row;
align-items: center;
justify-content: center !important;
padding-left: 0 !important;
}
.fui-button__opacity {
opacity: 0.5;
}
.fui-text__bold {
font-weight: bold;
}
.fui-button__link {
border-color: transparent !important;
background: transparent !important;
}
.fui-button__primary {
border-color: var(--fui-color-primary, #465CFF) !important;
background: var(--fui-color-primary, #465CFF) !important;
}
.fui-button__success {
border-color: var(--fui-color-success, #09BE4F) !important;
background: var(--fui-color-success, #09BE4F) !important;
}
.fui-button__warning {
border-color: var(--fui-color-warning, #FFB703) !important;
background: var(--fui-color-warning, #FFB703) !important;
}
.fui-button__danger {
border-color: var(--fui-color-danger, #FF2B2B) !important;
background: var(--fui-color-danger, #FF2B2B) !important;
}
.fui-button__purple {
border-color: var(--fui-color-purple, #6831FF) !important;
background: var(--fui-color-purple, #6831FF) !important;
}
.fui-button__gray {
border-color: var(--fui-bg-color-content, #F8F8F8) !important;
background: var(--fui-bg-color-content, #F8F8F8) !important;
color: var(--fui-color-primary, #465CFF) !important;
}
.fui-btn__gray-color {
color: var(--fui-color-primary, #465CFF) !important;
}

View File

@@ -0,0 +1,116 @@
Component({
options: {
multipleSlots: true,
styleIsolation: 'apply-shared'
},
properties: {
//card margin值
margin: {
type: String,
value: '0 32rpx'
},
//是否通栏为true时margin-leftmargin-right失效
full: {
type: Boolean,
value: false
},
//card 背景色
background: {
type: String,
value: '#fff'
},
//card 圆角showBorder为false时生效
radius: {
type: String,
value: '16rpx'
},
//阴影
shadow: {
type: String,
value: '0 2rpx 4rpx 0 rgba(2, 4, 38, 0.05)'
},
//是否显示card 边框为true时box-shadow失效
showBorder: {
type: Boolean,
value: false
},
headerBackground: {
type: String,
value: '#fff'
},
//是否需要header底部线条
headerLine: {
type: Boolean,
value: true
},
//是否需要内容与footer之间线条
footerLine: {
type: Boolean,
value: false
},
//header padding值
padding: {
type: String,
value: '20rpx 20rpx'
},
//头像,图标图片地址
src: {
type: String,
value: ''
},
//图片宽度单位rpx
width: {
type: Number,
optionalTypes: [String],
value: 64
},
//图片高度单位rpx
height: {
type: Number,
optionalTypes: [String],
value: 64
},
//图片圆角
imageRadius: {
type: String,
value: '8rpx'
},
title: {
type: String,
value: ''
},
size: {
type: Number,
optionalTypes: [String],
value: 30
},
color: {
type: String,
value: '#7F7F7F'
},
tag: {
type: String,
value: ''
},
tagSize: {
type: Number,
optionalTypes: [String],
value: 24
},
tagColor: {
type: String,
value: '#b2b2b2'
},
index: {
type: Number,
value: 0
}
},
methods: {
handleClick() {
this.triggerEvent('click', {
index: this.data.index
})
}
}
})

View File

@@ -0,0 +1,3 @@
{
"component": true
}

View File

@@ -0,0 +1,17 @@
<view class="fui-card__wrap {{full?'fui-card__full':''}} {{showBorder?'fui-card__border':''}} {{showBorder && !isNvue && !full?'fui-card__border-radius':''}}" style="margin:{{margin}};background:{{background}};border-radius:{{radius}};box-shadow:{{shadow}}" bindtap="handleClick">
<view class="fui-card__header {{headerLine?'fui-card__header-line':''}}" wx:if="{{tag || title || src}}" style="border-top-left-radius:{{full?0:radius}};border-top-right-radius:{{full?0:radius}};padding:{{padding}}">
<view class="fui-card__header-left">
<image src="{{src}}" class="fui-card__header-thumb" mode="widthFix" wx:if="{{src}}" style="height:{{height}}rpx;width:{{width}}rpx;border-radius:{{imageRadius}}"></image>
<text class="fui-card__header-title" style="font-size:{{size}}rpx;color:{{color}}" wx:if="{{title}}">{{title}}</text>
</view>
<view class="fui-card__header-right" wx:if="{{tag}}">
<text style="font-size:{{tagSize}}rpx;color:{{tagColor}}">{{tag}}</text>
</view>
</view>
<view class="fui-card__body {{footerLine?'fui-card__header-line':''}}">
<slot></slot>
</view>
<view class="fui-card__footer" style="border-bottom-left-radius:{{full?0:radius}};border-bottom-right-radius:{{full?0:radius}}">
<slot name="footer"></slot>
</view>
</view>

View File

@@ -0,0 +1,99 @@
.fui-card__wrap {
overflow: hidden;
flex: 1;
box-sizing: border-box;
}
.fui-card__full {
margin-left: 0 !important;
margin-right: 0 !important;
border-radius: 0 !important;
}
.fui-card__full::after {
border-radius: 0 !important;
}
.fui-card__border {
position: relative;
box-shadow: none !important;
}
.fui-card__border-radius {
border-radius: 16rpx !important;
}
.fui-card__border::after {
content: ' ';
position: absolute;
height: 200%;
width: 200%;
border: 1px solid var(--fui-color-border, #EEEEEE);
transform-origin: 0 0;
-webkit-transform-origin: 0 0;
-webkit-transform: scale(0.5);
transform: scale(0.5);
left: 0;
top: 0;
border-radius: 32rpx;
box-sizing: border-box;
pointer-events: none;
}
.fui-card__header {
width: 100%;
display: flex;
box-sizing: border-box;
align-items: center;
justify-content: space-between;
position: relative;
overflow: hidden;
}
.fui-card__header-left {
white-space: nowrap;
}
.fui-card__header-line {
position: relative;
}
.fui-card__header-line::after {
content: '';
position: absolute;
border-bottom: 1px solid var(--fui-color-border, #EEEEEE);
-webkit-transform: scaleY(0.5);
transform: scaleY(0.5);
transform-origin: 0 100%;
bottom: 0;
right: 0;
left: 0;
pointer-events: none;
}
.fui-card__header-thumb {
vertical-align: middle;
margin-right: 20rpx;
}
.fui-card__header-title {
display: inline-block;
vertical-align: middle;
max-width: 380rpx;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.fui-card__header-right {
text-align: right;
flex-shrink: 0;
}
.fui-card__body {
box-sizing: border-box;
}
.fui-card__footer {
box-sizing: border-box;
}

View File

@@ -0,0 +1,70 @@
Component({
behaviors: ['wx://form-field-group'],
properties: {
name: {
type: String,
value: ''
},
value: {
type: String,
value: "[]",
observer(vals) {
this.modelChange(vals)
}
}
},
relations: {
'../fui-checkbox/fui-checkbox': {
type: 'descendant',
linked: function (target) {
this.data.childrens.push(target)
let vals = JSON.parse(this.data.value || '[]')
if (vals.length > 0) {
target.setData({
val: vals.includes(target.data.value)
})
}
}
}
},
data: {
vals: '[]',
childrens: []
},
methods: {
checkboxChange(e) {
this.setData({
value: JSON.stringify(e.value)
})
this.triggerEvent('change', e)
},
changeValue(checked, target) {
let vals = []
this.data.childrens.forEach(item => {
if (item.data.val) {
vals.push(item.data.value);
}
})
this.setData({
vals: vals
})
let e = {
value: vals
}
this.checkboxChange(e)
},
modelChange(vals) {
this.data.childrens.forEach(item => {
if (vals.includes(item.data.value)) {
item.setData({
val: true
})
} else {
item.setData({
val: false
})
}
})
}
}
})

View File

@@ -0,0 +1,6 @@
{
"component": true,
"usingComponents": {
"fui-form-field": "/components/firstui/fui-form-field/fui-form-field"
}
}

View File

@@ -0,0 +1,3 @@
<fui-form-field name="{{name}}" value="{{vals}}">
<slot></slot>
</fui-form-field>

View File

@@ -0,0 +1,96 @@
Component({
options: {
virtualHost: true
},
properties: {
value: {
type: String,
value: ''
},
checked: {
type: Boolean,
value: false,
observer(newVal) {
this.setData({
val: newVal
},()=>{
this.parentChangeValue()
})
}
},
disabled: {
type: Boolean,
value: false
},
//checkbox选中背景颜色
color: {
type: String,
value: ''
},
//checkbox未选中时边框颜色
borderColor: {
type: String,
value: '#ccc'
},
borderRadius: {
type: String,
value: '50%'
},
//是否只展示对号,无边框背景
isCheckMark: {
type: Boolean,
value: false
},
//对号颜色
checkMarkColor: {
type: String,
value: '#fff'
},
scaleRatio: {
type: String,
optionalTypes: [Number],
value: 1
}
},
relations: {
'../fui-checkbox-group/fui-checkbox-group': {
type: 'ancestor'
},
'../fui-label/fui-label': {
type: 'ancestor'
}
},
data: {
val: false
},
lifetimes: {
attached: function () {
this.setData({
val: this.data.checked
},()=>{
this.parentChangeValue()
})
}
},
methods: {
checkboxChange(e) {
if (this.data.disabled) return;
this.setData({
val: !this.data.val
}, () => {
this.parentChangeValue()
})
},
parentChangeValue() {
const group = this.getRelationNodes('../fui-checkbox-group/fui-checkbox-group')[0]
group && group.changeValue(this.data.val, this);
this.triggerEvent('change', {
checked: this.data.val,
value: this.data.value
})
},
labelClick() {
this.checkboxChange()
}
}
})

View File

@@ -0,0 +1,3 @@
{
"component": true
}

View File

@@ -0,0 +1,24 @@
<view class="fui-checkbox__input {{disabled?'fui-checkbox__disabled':''}} {{!color && val && !isCheckMark?'fui-checkbox__color':''}}" style="background:{{parse.getBackgroundColor(val,isCheckMark,color)}};border-color:{{parse.getBorderColor(val,isCheckMark, color, borderColor)}};zoom:{{scaleRatio}};border-radius:{{borderRadius}}" catchtap="checkboxChange">
<view class="fui-check__mark" style="border-bottom-color:{{checkMarkColor}};border-right-color:{{checkMarkColor}}" wx:if="{{val}}"></view>
<checkbox class="fui-checkbox__hidden" color="{{color}}" disabled="{{disabled}}" value="{{value}}" checked="{{val}}">
</checkbox>
</view>
<wxs module="parse">
module.exports = {
getBackgroundColor: function (val, isCheckMark, color) {
var _color = val ? color : '#fff'
if (isCheckMark) {
_color = 'transparent'
}
return _color;
},
getBorderColor: function (val, isCheckMark, color, borderColor) {
var _color = val ? color : borderColor;
if (isCheckMark) {
_color = 'transparent'
}
return _color;
}
}
</wxs>

View File

@@ -0,0 +1,56 @@
.fui-checkbox__input {
font-size: 0;
color: rgba(0, 0, 0, 0);
width: 40rpx;
height: 40rpx;
border-width: 1px;
border-style: solid;
display: inline-flex;
box-sizing: border-box;
border-radius: 50%;
vertical-align: top;
flex-shrink: 0;
flex-direction: row;
align-items: center;
justify-content: center;
overflow: hidden;
position: relative;
}
.fui-checkbox__color {
background: var(--fui-color-primary, #465CFF) !important;
border-color: var(--fui-color-primary, #465CFF) !important;
}
.fui-check__mark {
width: 20rpx;
height: 40rpx;
border-bottom-style: solid;
border-bottom-width: 3px;
border-bottom-color: #FFFFFF;
border-right-style: solid;
border-right-width: 3px;
border-right-color: #FFFFFF;
box-sizing: border-box;
transform: rotate(45deg) scale(0.5) translateZ(0);
transform-origin: 54% 48%;
}
.fui-checkbox__hidden {
display: inline-block;
width: 100%;
height: 100%;
border: 0 none;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
position: absolute;
top: 0;
left: 0;
opacity: 0;
z-index: 2;
}
.fui-checkbox__disabled {
opacity: 0.6;
}

View File

@@ -0,0 +1,131 @@
Component({
options: {
virtualHost: true
},
properties: {
//栅格占据的列数
span: {
type: Number,
value: 24,
observer(val) {
this.updateCol();
}
},
//栅格左侧的间隔格数
offset: {
type: Number,
value: 0,
observer(val) {
this.updateCol();
}
},
//栅格向右移动格数
pushLeft: {
type: Number,
value: -1,
observer(val) {
this.updateCol();
}
},
//栅格向左移动格数
pullRight: {
type: Number,
value: -1,
observer(val) {
this.updateCol();
}
},
//max-width:767px 响应式栅格数或者栅格属性对象
//Number时表示在此屏幕宽度下栅格占据的列数。Object时可配置多个描述{span: 4, offset: 4}
xs: {
type: Number,
optionalTypes: [Object],
value: -1
},
//max-width:768px 响应式栅格数或者栅格属性对象
sm: {
type: Number,
optionalTypes: [Object],
value: -1
},
//max-width:992px 响应式栅格数或者栅格属性对象
md: {
type: Number,
optionalTypes: [Object],
value: -1
},
//max-width:1200px 响应式栅格数或者栅格属性对象
lg: {
type: Number,
optionalTypes: [Object],
value: -1
},
//max-width:1920px 响应式栅格数或者栅格属性对象
xl: {
type: Number,
optionalTypes: [Object],
value: -1
}
},
relations: {
'../fui-row/fui-row': {
type: 'ancestor',
linked: function (target) {
this.updateGutter(target.data.gutter)
}
}
},
data: {
classList: 'fui-col',
gutter: 0,
right: 0,
left: 0
},
lifetimes: {
attached: function () {
this.updateCol();
}
},
methods: {
updateGutter(parentGutter) {
parentGutter = Number(parentGutter);
if (!isNaN(parentGutter)) {
this.setData({
gutter: parentGutter / 2
})
}
},
updateCol() {
let classList = ['fui-col'];
classList.push('fui-col-' + this.data.span);
classList.push('fui-col-offset-' + this.data.offset);
if (this.data.pushLeft !== -1) {
this.data.pushLeft && classList.push('fui-col-push-' + this.data.pushLeft);
}
if (this.data.pullRight !== -1) {
this.data.pullRight && classList.push('fui-col-pull-' + this.data.pullRight);
}
this.screenSizeSet('xs', classList);
this.screenSizeSet('sm', classList);
this.screenSizeSet('md', classList);
this.screenSizeSet('lg', classList);
this.screenSizeSet('xl', classList);
this.setData({
classList: classList
})
},
screenSizeSet(screen, classList) {
if (typeof this.data[screen] === 'number' && this.data[screen] !== -1) {
classList.push('fui-col-' + screen + '-' + this.data[screen]);
} else if (typeof this.data[screen] === 'object') {
typeof this.data[screen].offset === 'number' && classList.push('fui-col-' + screen + '-offset-' + this.data[
screen].offset);
typeof this.data[screen].pushLeft === 'number' && classList.push('fui-col-' + screen + '-push-' + this.data[
screen].pushLeft);
typeof this.data[screen].pullRight === 'number' && classList.push('fui-col-' + screen + '-pull-' + this.data[
screen].pullRight);
typeof this.data[screen].span === 'number' && classList.push('fui-col-' + screen + '-' + this.data[screen].span);
}
}
}
})

View File

@@ -0,0 +1,3 @@
{
"component": true
}

View File

@@ -0,0 +1,3 @@
<view class="{{classList}}" style="padding-left:{{gutter}}rpx; padding-right:{{gutter}}rpx">
<slot></slot>
</view>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,155 @@
const elId = `fui_${Math.ceil(Math.random() * 10e5).toString(36)}`
Component({
options: {
multipleSlots: true,
virtualHost: true
},
properties: {
//item项索引或者唯一标识
index: {
type: String,
optionalTypes: [Number],
value: 0
},
// 是否禁用
disabled: {
type: Boolean,
value: false
},
background: {
type: String,
value: '#fff'
},
//是否显示动画,如果动画卡顿严重建议不开启
animation: {
type: Boolean,
value: true
},
// 是否展开
open: {
type: Boolean,
value: false,
observer(val) {
this.setData({
isOpen: val
})
}
},
isBorder: {
type: Boolean,
value: true
},
borderColor: {
type: String,
value: ''
},
borderLeft: {
type: String,
optionalTypes: [Number],
value: 0
},
arrow: {
type: Boolean,
value: true
},
arrowColor: {
type: String,
value: '#B2B2B2'
},
arrowRight: {
type: String,
optionalTypes: [Number],
value: 24
},
contentBg: {
type: String,
value: '#fff'
},
marginTop: {
type: String,
optionalTypes: [Number],
value: 0
},
marginBottom: {
type: String,
optionalTypes: [Number],
value: 0
}
},
relations: {
'../fui-collapse/fui-collapse': {
type: 'ancestor',
linked: function (target) {
this.data.collapse = target
}
}
},
data: {
isOpen: false,
isHeight: null,
height: 0,
elId: elId,
oldHeight: 0,
collapse: null
},
lifetimes: {
ready: function () {
this.setData({
isOpen: this.data.open
})
this.init()
},
detached: function () {
this.uninstall()
}
},
methods: {
init() {
this.getCollapseHeight()
},
uninstall() {
if (this.data.collapse && this.data.collapse.children) {
this.data.collapse.children.forEach((item, index) => {
if (item === this) {
this.data.collapse.children.splice(index, 1)
}
})
}
},
onClick(e) {
if (this.data.disabled) return
let isOpen = !this.data.isOpen
this.setData({
isOpen: isOpen
})
if (this.data.collapse) {
this.data.collapse.collapseChange(this, isOpen, this.data.index)
} else {
this.triggerEvent('change', {
index: this.data.index,
isOpen: isOpen
})
}
},
getCollapseHeight(index = 0) {
wx.createSelectorQuery()
.in(this)
.select(`#${this.data.elId}`)
.fields({
size: true
}, data => {
if (index >= 10) return
if (!data) {
index++
this.getCollapseHeight(index)
return
}
this.setData({
height: data.height,
isHeight: true
})
})
.exec()
}
}
})

View File

@@ -0,0 +1,3 @@
{
"component": true
}

View File

@@ -0,0 +1,16 @@
<view class="fui-collapse__item" style="margin-top: {{marginTop}}rpx;margin-bottom: {{marginBottom}}rpx;">
<view catchtap="onClick" class="fui-collapse-item__title {{disabled?'fui-collapse__disabled':''}}" style="background:{{background}}">
<view class="fui-collapse__title">
<slot></slot>
</view>
<view wx:if="{{arrow}}" class="fui-collapse__arrow {{isOpen?'fui-collapse__arrow-active':''}} {{animation?'fui-collapse__item-ani':''}}" style="margin-right:{{arrowRight}}rpx">
<view class="fui-collapse__arrow-inner" style="border-color:{{arrowColor}}"></view>
</view>
<view wx:if="{{isBorder}}" style="background:{{borderColor}};left:{{borderLeft}}rpx" class="fui-collapse__border {{!borderColor?'fui-collapse__border-color':''}}"></view>
</view>
<view class="fui-collapse__content-wrap {{animation?'fui-collapse-__content-ani':''}}" style="height:{{isOpen?height:0}}px;background:{{contentBg}}">
<view id="{{elId}}" class="fui-collapse__content {{isHeight?'fui-collapse__content-open':''}}">
<slot name="content"></slot>
</view>
</view>
</view>

View File

@@ -0,0 +1,91 @@
.fui-collapse__item {
box-sizing: border-box;
}
.fui-collapse-item__title {
display: flex;
width: 100%;
box-sizing: border-box;
flex-direction: row;
align-items: center;
transition: border-bottom-color 0.3s;
position: relative;
}
.fui-collapse__border {
position: absolute;
bottom: 0;
right: 0;
height: 1px;
-webkit-transform: scaleY(0.5);
transform: scaleY(0.5);
transform-origin: 0 100%;
z-index: 1;
}
.fui-collapse__border-color {
background: var(--fui-color-border, #EEEEEE) !important;
}
.fui-collapse__disabled {
opacity: .5;
}
.fui-collapse__title {
width: 100%;
flex: 1;
}
.fui-collapse__arrow-inner {
height: 40rpx;
width: 40rpx;
border-width: 0 3px 3px 0;
border-style: solid;
transform: rotate(45deg) scale(.5);
box-sizing: border-box;
position: absolute;
top: -6rpx;
left: 0;
}
.fui-collapse__arrow {
width: 40rpx;
height: 40rpx;
transform: rotate(0deg);
position: relative;
flex-shrink: 0;
}
.fui-collapse__arrow-active {
transform: rotate(180deg);
}
.fui-collapse__item-ani {
transition-property: transform;
transition-duration: 0.3s;
transition-timing-function: ease;
}
.fui-collapse__content-wrap {
will-change: height;
box-sizing: border-box;
overflow: hidden;
position: relative;
height: 0;
}
.fui-collapse-__content-ani {
transition-property: height;
transition-duration: 0.3s;
will-change: height;
}
.fui-collapse__content {
width: 100%;
position: absolute;
}
.fui-collapse__content-open {
position: relative;
}

View File

@@ -0,0 +1,46 @@
Component({
properties: {
// 是否开启手风琴效果
accordion: {
type: Boolean,
value: false
},
background: {
type: String,
value: 'transparent'
}
},
data: {
children: []
},
relations: {
'../fui-collapse-item/fui-collapse-item': {
type: 'descendant',
linked: function (target) {
this.data.children.push(target)
},
linkChanged: function (target) {
setTimeout(() => {
target && target.init()
}, 50)
}
}
},
methods: {
collapseChange(obj, isOpen, idx) {
if (this.data.accordion && isOpen) {
this.data.children.forEach((item, index) => {
if (item !== obj) {
item.setData({
isOpen: false
})
}
})
}
this.triggerEvent('change', {
index: idx,
isOpen: isOpen
})
}
}
})

View File

@@ -0,0 +1,3 @@
{
"component": true
}

View File

@@ -0,0 +1,3 @@
<view class="fui-collapse__wrap" style="background: {{background}};">
<slot></slot>
</view>

View File

@@ -0,0 +1,5 @@
.fui-collapse__wrap {
width: 100%;
display: flex;
flex-direction: column;
}

View File

@@ -0,0 +1,125 @@
/*
===========================================
当前组件库版本号为V2.1.0
如果与文档最新版本不一致,请更新至最新版本使用!
===========================================
*/
/*
组件属性全局配置文件。优先级全局配置文件props < 直接设置组件props
目前支持配置的组件fui-button、fui-icon、fui-text、fui-input、fui-list-cell、fui-section、fui-white-space、fui-wing-blank
*/
// 主色仅适用无法使用css变量控制颜色的组件使用【保持与fui-theme中一致】
const color = {
primary: '#465CFF',
success: '#09BE4F',
warning: '#FFB703',
danger: '#FF2B2B',
purple: '#6831FF',
link: '#465CFF'
}
//全局方法V1.9.8+
const app = {
// 设计稿 375 的宽度
rpx2px(value) {
let sys = wx.getSystemInfoSync()
return sys.windowWidth / 750 * value
},
toast: function (text, icon = 'none') {
text && wx.showToast({
title: text,
icon: icon,
duration: 2000
})
},
modal: function (title, content, callback, showCancel, confirmColor, confirmText) {
wx.showModal({
title: title,
content: content,
showCancel: showCancel || false,
cancelColor: "#7F7F7F",
confirmColor: confirmColor || color.primary,
confirmText: confirmText || "确定",
success(res) {
if (res.confirm) {
callback && callback(true)
} else {
callback && callback(false)
}
},
fail(err) {
console.log(err)
}
})
},
href(url, isMain) {
if (isMain) {
wx.switchTab({
url: url
})
} else {
wx.navigateTo({
url: url
});
}
}
}
const fuiConfig = {
//组件名称,小驼峰命名
//如fui-button写成fuiButton
fuiButton: {
//组件属性值
height: '96rpx',
size: 32,
radius: '16rpx'
},
fuiIcon: {
size: 64,
unit: 'rpx'
},
fuiText: {
size: 32,
unit: 'rpx'
},
fuiInput: {
labelSize: 32,
labelColor: '#333',
size: 32,
color: '#333'
},
fuiListCell: {
padding: '32rpx',
arrowColor: '#B2B2B2',
bottomLeft: 32
},
// V1.9.9+
fuiSection: {
size: 32,
color: '#181818',
fontWeight: 600,
descrSize: 28,
descrColor: '#B2B2B2',
descrTop: 12
},
//v2.1.0+
fuiWhiteSpace: {
size: 'default',
//设置了height则size失效
height: 0,
background: 'transparent'
},
//v2.1.0+
fuiWingBlank: {
size: 'default',
//设置了gap则size失效
gap: 0,
background: 'transparent'
},
color,
...app
}
export default fuiConfig

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,64 @@
Component({
properties: {
show: {
type: Boolean,
value: false
},
title: {
type: String,
value: '温馨提示'
},
color: {
type: String,
value: '#333'
},
content: {
type: String,
value: ''
},
contentColor: {
type: String,
value: '#7F7F7F'
},
buttons: {
type: Array,
value: [{
text: '取消'
}, {
text: '确定',
color: '#465CFF'
}]
},
background: {
type: String,
value: '#fff'
},
radius: {
type: Number,
optionalTypes: [String],
value: 24
},
maskBackground: {
type: String,
value: 'rgba(0,0,0,.6)'
},
maskClosable: {
type: Boolean,
value: true
}
},
methods: {
handleClick(e) {
let index = Number(e.currentTarget.dataset.index)
this.triggerEvent('click', {
index,
...this.data.buttons[index]
});
},
maskClose() {
if (!this.data.maskClosable) return;
this.triggerEvent('close', {});
},
stop() {}
}
})

View File

@@ -0,0 +1,3 @@
{
"component": true
}

View File

@@ -0,0 +1,12 @@
<view bindtap="maskClose" style="background:{{maskBackground}}" class="fui-dialog__wrap {{show?'fui-wrap__show':''}}" catchtouchmove="stop">
<view class="fui-dialog__inner" style="background:{{background}};border-radius:{{radius}}rpx">
<text class="fui-dialog__title" style="color:{{color}}" wx:if="{{title}}">{{title}}</text>
<view class="fui-dialog__body {{title?'':'fui-dialog__mtop'}}">
<text class="fui-dialog__descr" style="color:{{contentColor}}" wx:if="{{content}}">{{content}}</text>
<slot></slot>
</view>
<view class="fui-dialog__footer">
<text wx:for="{{buttons}}" wx:key="index" style="color:{{item.color || '#333333'}}" class="fui-dialog__btn {{index===0?'fui-dialog__btn-first':''}}" bindtap="handleClick" data-index="{{index}}">{{item.text}}</text>
</view>
</view>
</view>

View File

@@ -0,0 +1,108 @@
.fui-dialog__wrap {
position: fixed;
z-index: 1000;
top: 0;
right: 0;
left: 0;
bottom: 0;
transition-property: all;
transition-timing-function: ease-in;
transition-duration: 0.2s;
display: flex;
transform: scale3d(1, 1, 0);
visibility: hidden;
align-items: center;
justify-content: center;
opacity: 0;
}
.fui-dialog__inner {
width: 680rpx;
text-align: center;
overflow: hidden;
display: flex;
max-height: 90%;
flex-direction: column;
}
.fui-dialog__title {
padding: 64rpx 48rpx 0;
font-weight: 700;
font-size: 34rpx;
text-align: center;
}
.fui-dialog__body {
padding: 32rpx 48rpx;
margin-bottom: 32rpx;
word-break: break-all;
-webkit-hyphens: auto;
hyphens: auto;
}
.fui-dialog__descr {
font-size: 30rpx;
font-weight: normal;
text-align: center;
}
.fui-dialog__mtop {
margin-top: 32rpx;
}
.fui-dialog__footer {
display: flex;
flex-direction: row;
position: relative;
line-height: 112rpx;
height: 112rpx;
}
.fui-dialog__footer:after {
content: " ";
position: absolute;
left: 0;
top: 0;
right: 0;
height: 1px;
border-top: 1px solid var(--fui-color-border, #EEEEEE);
transform-origin: 0 0;
transform: scaleY(.5)
}
.fui-dialog__btn {
display: block;
text-decoration: none;
flex: 1;
height: 112rpx;
line-height: 112rpx;
font-weight: 700;
position: relative;
font-size: 34rpx;
text-align: center;
}
.fui-dialog__btn:active {
background-color: var(--fui-bg-color-hover, rgba(0, 0, 0, 0.2));
}
.fui-dialog__btn::after {
content: " ";
position: absolute;
left: 0;
top: 0;
width: 1px;
bottom: 0;
border-left: 1px solid var(--fui-color-border, #EEEEEE);
transform-origin: 0 0;
transform: scaleX(.5)
}
.fui-dialog__btn-first::after {
width: 0;
border-left: 0 !important;
}
.fui-wrap__show {
opacity: 1;
transform: scale3d(1, 1, 1);
visibility: visible;
}

View File

@@ -0,0 +1,40 @@
Component({
properties: {
text: {
type: String,
value: ''
},
//divider占据高度单位rpx
height: {
type: Number,
optionalTypes: [String],
value: 100
},
//divider宽度
width: {
type: String,
value: '400rpx'
},
//divider颜色
dividerColor: {
type: String,
value: '#CCCCCC'
},
//文字颜色
color: {
type: String,
value: '#B2B2B2'
},
//文字大小 rpx
size: {
type: Number,
optionalTypes: [String],
value: 24
},
fontWeight: {
type: Number,
optionalTypes: [String],
value: 400
}
}
})

View File

@@ -0,0 +1,3 @@
{
"component": true
}

View File

@@ -0,0 +1,12 @@
<view class="fui-divider__wrap" style="height:{{height}}rpx">
<view class="fui-divider__wrap" style="height:{{height}}rpx;width:{{width}};">
<view class="fui-divider__line" style="width:{{width}};background: {{dividerColor}};">
</view>
<view class="fui-divider__text-box">
<slot></slot>
<text class="fui-divider__text" style="font-weight: {{fontWeight}};color: {{color}};font-size:{{size}}rpx;line-height:{{size}} rpx" wx:if="{{text}}">{{text}}</text>
</view>
<view class="fui-divider__line" style="width:{{width}};background: {{dividerColor}};">
</view>
</view>
</view>

View File

@@ -0,0 +1,34 @@
.fui-divider__wrap {
width: 100%;
display: flex;
box-sizing: border-box;
position: relative;
text-align: center;
flex-direction: row;
justify-content: center;
align-items: center;
overflow: hidden;
}
.fui-divider__line {
height: 1px;
-webkit-transform: scaleY(0.5) translateZ(0);
transform: scaleY(0.5) translateZ(0);
flex: 1;
}
.fui-divider__text-box {
position: relative;
text-align: center;
padding: 0 8rpx;
z-index: 1;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.fui-divider__text {
padding: 0 10rpx;
}

View File

@@ -0,0 +1,45 @@
Component({
properties: {
show: {
type: Boolean,
value: false
},
//left/right
direction: {
type: String,
value: 'right'
},
//背景颜色
background: {
type: String,
value: '#fff'
},
zIndex: {
type: Number,
optionalTypes:[String],
value: 996
},
//点击遮罩 是否可关闭
maskClosable: {
type: Boolean,
value: true
},
maskBackground: {
type: String,
value: 'rgba(0,0,0,.6)'
},
//圆角值,左侧打开时为右侧圆角,右侧打开时为左侧圆角
radius: {
type: String,
optionalTypes:[Number],
value: 0
}
},
methods: {
stop() {},
handleClose(e) {
if (!this.data.maskClosable) return;
this.triggerEvent('close', {});
}
}
})

View File

@@ -0,0 +1,4 @@
{
"component": true,
"usingComponents": {}
}

View File

@@ -0,0 +1,5 @@
<view class="fui-drawer__popup-wrap {{show?'fui-drawer__wrap-show':''}}" style="z-index: {{zIndex}};background:{{maskBackground}};align-items:{{direction==='left'?'flex-start':'flex-end'}}" catchtap="handleClose" catchtouchmove="stop">
<view class="fui-drawer__popup {{'fui-drawer_'+direction}} {{show?'fui-drawer__show':''}}" style="background:{{background}};border-top-left-radius: {{direction==='right'? radius:0}}rpx;border-bottom-left-radius: {{direction==='right'? radius:0}}rpx;border-top-right-radius: {{direction==='left'? radius:0}}rpx;border-bottom-right-radius: {{direction==='left'? radius:0}}rpx;" catchtap="stop">
<slot></slot>
</view>
</view>

View File

@@ -0,0 +1,40 @@
.fui-drawer__popup-wrap {
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
z-index: 1001;
display: flex;
flex-direction: column;
transition: all ease-in-out .3s;
visibility: hidden;
opacity: 0;
overflow: hidden;
}
.fui-drawer__wrap-show {
opacity: 1;
visibility: visible;
}
.fui-drawer__popup {
height: 100%;
transition: all 0.3s ease-in-out;
min-width: 40rpx;
display: flex;
flex: 1;
flex-direction: column;
overflow: hidden;
}
.fui-drawer_left {
transform: translate3d(-100%, 0, 0);
}
.fui-drawer_right {
transform: translate3d(100%, 0, 0);
}
.fui-drawer__show {
transform: translate3d(0, 0, 0);
}

View File

@@ -0,0 +1,173 @@
Component({
properties: {
options: {
type: Array,
value: [],
observer(val) {
this.initData(val)
}
},
textKey: {
type: String,
value: 'text'
},
srcKey: {
type: String,
value: 'src'
},
checkedKey: {
type: String,
value: 'checked'
},
height: {
type: String,
optionalTypes: [Number],
value: 0
},
width: {
type: String,
optionalTypes: [Number],
value: 0
},
background: {
type: String,
value: '#fff'
},
radius: {
type: String,
optionalTypes: [Number],
value: 0
},
padding: {
type: String,
value: '32rpx'
},
isCheckbox: {
type: Boolean,
value: true
},
checkboxColor: {
type: String,
value: ''
},
borderColor: {
type: String,
value: '#ccc'
},
isCheckMark: {
type: Boolean,
value: false
},
checkmarkColor: {
type: String,
value: '#fff'
},
isReverse: {
type: Boolean,
value: false
},
splitLine: {
type: Boolean,
value: false
},
iconWidth: {
type: String,
optionalTypes: [Number],
value: 48
},
size: {
type: String,
optionalTypes: [Number],
value: 32
},
color: {
type: String,
value: '#181818'
},
selectedColor: {
type: String,
value: ''
},
//点击遮罩 是否可关闭
maskClosable: {
type: Boolean,
value: true
},
maskBackground: {
type: String,
value: 'rgba(0, 0, 0, 0.6)'
},
zIndex: {
type: Number,
value: 1001
}
},
data: {
itemList: [],
isShow: false
},
lifetimes: {
attached: function () {
this.initData(this.data.options)
}
},
methods: {
initData(vals) {
if (vals && vals.length > 0) {
if (typeof vals[0] !== 'object') {
vals = vals.map(item => {
return {
[this.data.textKey]: item,
[this.data.checkedKey]: false
}
})
} else {
vals.map(item => {
item[this.data.checkedKey] = item[this.data.checkedKey] || false
})
}
this.setData({
itemList: vals
})
} else {
this.setData({
itemList: []
})
}
},
itemClick(e) {
let index = Number(e.currentTarget.dataset.index)
let item = this.data.itemList[index]
let vals = [...this.data.itemList]
vals.forEach((item, idx) => {
if (index === idx) {
item[this.data.checkedKey] = true
} else {
item[this.data.checkedKey] = false
}
})
this.setData({
itemList: vals
})
this.triggerEvent('click', {
index: index,
...item
})
this.close(2)
},
close(e) {
let type = e === 2 ? 2 : 1
this.setData({
isShow: false
})
if (type === 1 && this.data.maskClosable) {
this.triggerEvent('close', {})
}
},
show() {
this.setData({
isShow: true
})
}
}
})

View File

@@ -0,0 +1,3 @@
{
"component": true
}

View File

@@ -0,0 +1,35 @@
<view class="fui-dropdown__list-wrap {{isShow?'fui-dropdown__list-show':''}}" style="background:{{maskBackground}};z-index:{{zIndex}}" bindtap="close">
<view class="fui-dropdown__list" style="border-radius:{{radius}}rpx;background:{{background}}">
<scroll-view class="fui-ddl__scroll" scroll-y style="{{parse.getStyles(height, width)}}">
<slot></slot>
<view class="fui-dropdown__list-item {{isReverse?'fui-ddl__reverse':''}} {{splitLine && itemList.length-1!==index?'fui-ddl__item-line':''}}" style="background:{{background}};padding:{{padding}};" wx:for="{{itemList}}" wx:for-item="model" wx:key="index" catchtap="itemClick" data-index="{{index}}">
<view class="fui-ddl__checkbox {{isCheckMark?'fui-is__checkmark':''}} {{(!checkboxColor || checkboxColor=='true') && model[checkedKey] && !isCheckMark?'fui-ddl__checkbox-color':''}}" style="background:{{model[checkedKey] && !isCheckMark ?checkboxColor:'transparent'}};border-color:{{model[checkedKey] && !isCheckMark ?checkboxColor:borderColor}}" wx:if="{{isCheckbox}}">
<view class="fui-ddl__checkmark" style="border-bottom-color:{{checkmarkColor}};border-right-color:{{checkmarkColor}}" wx:if="{{model[checkedKey]}}"></view>
</view>
<view class="fui-ddl__flex">
<view class="fui-ddl__icon-box {{!isReverse && isCheckbox?'fui-ddl__icon-ml':''}} {{isReverse?'fui-ddl__icon-mr':''}}" style="width:{{iconWidth}}rpx;height:{{iconWidth}}rpx" wx:if="{{model[srcKey]}}">
<image src="{{model[srcKey]}}" style="width:{{iconWidth}}rpx;height:{{iconWidth}}rpx"></image>
</view>
<text class="fui-ddl__item-text {{!isReverse && (isCheckbox || model[srcKey])?'fui-ddl__text-pl':''}} {{isReverse && (isCheckbox || model[srcKey])?'fui-ddl__text-pr':''}}" style="font-size:{{size}}rpx;color:{{selectedColor && model[checkedKey]?selectedColor:color}}">{{model[textKey]}}</text>
</view>
</view>
</scroll-view>
</view>
</view>
<wxs module="parse">
module.exports = {
getStyles: function (height, width) {
var styles = '';
var height = parseInt(height || 0)
var width = parseInt(width || 0)
if (height > 0) {
styles += "height:" + height + "rpx;"
}
if (width > 0) {
styles += "width:" + width + "rpx;"
}
return styles
}
}
</wxs>

View File

@@ -0,0 +1,147 @@
.fui-dropdown__list-wrap {
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
padding: 64rpx;
display: flex;
visibility: hidden;
box-sizing: border-box;
align-items: center;
justify-content: center;
transition-property: opacity, visibility;
transition-timing-function: ease-in-out;
transition-duration: 0.3s;
opacity: 0;
}
.fui-ddl__scroll {
width: auto;
flex: 1;
}
.fui-dropdown__list {
box-shadow: 0 0 10rpx rgba(2, 4, 38, 0.05);
overflow: hidden;
}
.fui-dropdown__list-show {
visibility: visible;
opacity: 1;
}
.fui-dropdown__list-item {
width: 100%;
display: flex;
box-sizing: border-box;
flex: 1;
flex-direction: row;
align-items: center;
background-color: #FFFFFF;
position: relative;
}
.fui-ddl__flex {
width: 100%;
display: flex;
box-sizing: border-box;
flex: 1;
flex-direction: row;
align-items: center;
}
.fui-ddl__item-line {
position: relative;
border-bottom-width: 0;
}
.fui-ddl__item-line::after {
content: '';
position: absolute;
border-bottom: 1px solid var(--fui-color-border, #EEEEEE);
transform: scaleY(0.5) translateZ(0);
transform-origin: 0 100%;
bottom: 0;
right: 0;
left: 32rpx;
pointer-events: none;
}
.fui-dropdown__list-item:active {
background-color: var(--fui-bg-color-hover, rgba(0, 0, 0, .2)) !important;
}
.fui-ddl__reverse {
justify-content: space-between;
flex-direction: row-reverse;
}
.fui-ddl__checkbox {
font-size: 0;
color: rgba(0, 0, 0, 0);
width: 40rpx;
height: 40rpx;
border-width: 1px;
border-style: solid;
display: inline-flex;
box-sizing: border-box;
border-radius: 50%;
vertical-align: top;
flex-shrink: 0;
flex-direction: row;
align-items: center;
justify-content: center;
overflow: hidden;
position: relative;
}
.fui-ddl__checkbox-color {
background: var(--fui-color-primary, #465CFF) !important;
border-color: var(--fui-color-primary, #465CFF) !important;
}
.fui-is__checkmark {
border-width: 0 !important;
background: transparent !important;
}
.fui-ddl__checkmark {
width: 20rpx;
height: 40rpx;
border-bottom-style: solid;
border-bottom-width: 3px;
border-bottom-color: #FFFFFF;
border-right-style: solid;
border-right-width: 3px;
border-right-color: #FFFFFF;
box-sizing: border-box;
transform: rotate(45deg) scale(0.5) translateZ(0);
transform-origin: 54% 48%;
}
.fui-ddl__item-text {
word-break: break-all;
font-weight: normal;
}
.fui-ddl__text-pl {
padding-left: 24rpx;
}
.fui-ddl__text-pr {
padding-right: 24rpx;
}
.fui-ddl__icon-box {
overflow: hidden;
background-color: #F1F4FA;
flex-shrink: 0;
}
.fui-ddl__icon-ml {
margin-left: 24rpx;
}
.fui-ddl__icon-mr {
margin-right: 24rpx;
}

View File

@@ -0,0 +1,186 @@
Component({
options: {
virtualHost: true
},
textKey: {
type: String,
value: 'text'
},
srcKey: {
type: String,
value: 'src'
},
checkedKey: {
type: String,
value: 'checked'
},
properties: {
options: {
type: Array,
value: [],
observer(val) {
this.initData(val)
}
},
maxHeight: {
type: String,
optionalTypes: [Number],
value: 400
},
minWidth: {
type: String,
optionalTypes: [Number],
value: 0
},
left: {
type: String,
optionalTypes: [Number],
value: 0
},
right: {
type: String,
optionalTypes: [Number],
value: -1
},
background: {
type: String,
value: '#fff'
},
radius: {
type: String,
optionalTypes: [Number],
value: 0
},
padding: {
type: String,
value: '32rpx'
},
isCheckbox: {
type: Boolean,
value: true
},
checkboxColor: {
type: String,
value: ''
},
borderColor: {
type: String,
value: '#ccc'
},
isCheckMark: {
type: Boolean,
value: false
},
checkmarkColor: {
type: String,
value: '#fff'
},
isReverse: {
type: Boolean,
value: false
},
splitLine: {
type: Boolean,
value: false
},
iconWidth: {
type: String,
optionalTypes: [Number],
value: 48
},
size: {
type: String,
optionalTypes: [Number],
value: 32
},
color: {
type: String,
value: '#181818'
},
selectedColor: {
type: String,
value: ''
},
isMask: {
type: Boolean,
value: true
},
maskBackground: {
type: String,
value: 'transparent'
},
//down/up
direction: {
type: String,
value: 'down'
}
},
data: {
itemList: [],
isShow: false
},
lifetimes: {
attached: function () {
this.initData(this.data.options)
}
},
methods: {
initData(vals) {
if (vals && vals.length > 0) {
if (typeof vals[0] !== 'object') {
vals = vals.map(item => {
return {
[this.data.textKey]: item,
[this.data.checkedKey]: false
}
})
} else {
vals.map(item => {
item[this.data.checkedKey] = item[this.data.checkedKey] || false
})
}
this.setData({
itemList: vals
})
} else {
this.setData({
itemList: []
})
}
},
itemClick(e) {
let index = Number(e.currentTarget.dataset.index)
let item = this.data.itemList[index]
let vals = [...this.data.itemList]
vals.forEach((item, idx) => {
if (index === idx) {
item[this.data.checkedKey] = true
} else {
item[this.data.checkedKey] = false
}
})
this.setData({
itemList: vals
})
this.triggerEvent('click', {
index: index,
...item
})
this.close(2)
},
close(e) {
let type = e === 2 ? 2 : 1
this.setData({
isShow: false
})
if (type === 1) {
this.triggerEvent('close', {})
}
},
show() {
this.setData({
isShow: true
})
}
}
})

View File

@@ -0,0 +1,3 @@
{
"component": true
}

View File

@@ -0,0 +1,36 @@
<view class="fui-dropdown__menu">
<slot></slot>
<view class="fui-dropdown__menu-list {{direction!=='up'?'fui-ddm__down':''}} {{direction==='up'?'fui-ddm__up':''}} {{isShow && direction!=='up'?'fui-ddm__down-show':''}} {{isShow && direction==='up'?'fui-ddm__up-show':''}}" style="{{parse.getStyles(radius, background, right,left)}}">
<scroll-view class="fui-ddm__scroll" scroll-y style="max-height:{{maxHeight}}rpx;min-width:{{minWidth}}rpx">
<slot name="item"></slot>
<view class="fui-dropdown__menu-item {{isReverse?'fui-ddm__reverse':''}} {{splitLine && itemList.length-1!==index?'fui-ddm__item-line':''}}" style="background:{{background}};padding:{{padding}}" wx:for="{{itemList}}" wx:for-item="model" wx:key="index" catchtap="itemClick" data-index="{{index}}">
<view class="fui-ddm__checkbox {{isCheckMark?'fui-is__checkmark':''}} {{(!checkboxColor || checkboxColor===true) && model[checkedKey] && !isCheckMark?'fui-ddm__checkbox-color':''}}" style="background:{{model[checkedKey] && !isCheckMark ?checkboxColor:'transparent'}};border-color:{{model[checkedKey] && !isCheckMark ?checkboxColor:borderColor}}" wx:if="{{isCheckbox}}">
<view class="fui-ddm__checkmark" style="border-bottom-color:{{checkmarkColor}};border-right-color:{{checkmarkColor}}" wx:if="{{model[checkedKey]}}"></view>
</view>
<view class="fui-ddm__flex">
<view class="fui-ddm__icon-box {{!isReverse && isCheckbox?'fui-ddm__icon-ml':''}} {{isReverse?'fui-ddm__icon-mr':''}}" style="width:{{iconWidth}}rpx;height:{{iconWidth}}rpx" wx:if="{{model[srcKey]}}">
<image src="{{model[srcKey]}}" style="width:{{iconWidth}}rpx;height:{{iconWidth}}rpx"></image>
</view>
<text class="fui-ddm__item-text {{!isReverse && (isCheckbox || model[srcKey])?'fui-ddm__text-pl':''}} {{isReverse && (isCheckbox || model[srcKey])?'fui-ddm__text-pr':''}}" style="font-size:{{size}}rpx;color:{{selectedColor && model[checkedKey]?selectedColor:color}}">{{model[textKey]}}</text>
</view>
</view>
</scroll-view>
</view>
<view class="fui-ddm__mask" style="background:{{maskBackground}}" wx:if="{{isShow && isMask}}" bindtap="close">
</view>
</view>
<wxs module="parse">
module.exports = {
getStyles: function (radius, background, right,left) {
var styles = "border-radius:" + radius + "rpx;background:" + background + ";"
var rightValue = parseInt(right || 0)
if (rightValue >= 0) {
styles += 'right:0;'
} else {
styles += 'left:' + (left || 0) + 'rpx;'
}
return styles
}
}
</wxs>

View File

@@ -0,0 +1,167 @@
.fui-dropdown__menu {
flex: 1;
position: relative;
}
.fui-ddm__scroll {
width: auto;
}
.fui-dropdown__menu-list {
position: absolute;
box-shadow: 0 0 10rpx rgba(2, 4, 38, 0.05);
overflow: hidden;
z-index: 992;
opacity: 0;
visibility: hidden;
transition: all 0.3s ease-in-out;
}
.fui-ddm__down {
transform-origin: 0 0;
bottom: 0;
transform: translate3d(0, 100%, 0) scaleY(0);
}
.fui-ddm__down-show {
transform: translate3d(0, 100%, 0) scaleY(1) !important;
visibility: visible;
opacity: 1;
}
.fui-ddm__up {
transform-origin: 0 100%;
top: 0;
transform: translate3d(0, -100%, 0) scaleY(0);
}
.fui-ddm__up-show {
transform: translate3d(0, -100%, 0) scaleY(1) !important;
visibility: visible !important;
opacity: 1;
}
.fui-ddm__mask {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 990;
}
.fui-dropdown__menu-item {
width: 100%;
display: flex;
box-sizing: border-box;
transform: scale(1) translateZ(0);
flex: 1;
flex-direction: row;
align-items: center;
background-color: #FFFFFF;
position: relative;
}
.fui-ddm__flex {
width: 100%;
display: flex;
box-sizing: border-box;
flex: 1;
flex-direction: row;
align-items: center;
}
.fui-ddm__item-line {
position: relative;
}
.fui-ddm__item-line::after {
content: '';
position: absolute;
border-bottom: 1px solid var(--fui-color-border, #EEEEEE);
transform: scaleY(0.5) translateZ(0);
transform-origin: 0 100%;
bottom: 0;
right: 0;
left: 32rpx;
pointer-events: none;
}
.fui-dropdown__menu-item:active {
background-color: var(--fui-bg-color-hover, rgba(0, 0, 0, .2)) !important;
}
.fui-ddm__reverse {
justify-content: space-between;
flex-direction: row-reverse;
}
.fui-ddm__checkbox {
font-size: 0;
color: rgba(0, 0, 0, 0);
width: 40rpx;
height: 40rpx;
border-width: 1px;
border-style: solid;
display: inline-flex;
box-sizing: border-box;
border-radius: 50%;
vertical-align: top;
flex-shrink: 0;
flex-direction: row;
align-items: center;
justify-content: center;
overflow: hidden;
position: relative;
}
.fui-ddm__checkbox-color {
background: var(--fui-color-primary, #465CFF) !important;
border-color: var(--fui-color-primary, #465CFF) !important;
}
.fui-is__checkmark {
border-width: 0 !important;
background: transparent !important;
}
.fui-ddm__checkmark {
width: 20rpx;
height: 40rpx;
border-bottom-style: solid;
border-bottom-width: 3px;
border-bottom-color: #FFFFFF;
border-right-style: solid;
border-right-width: 3px;
border-right-color: #FFFFFF;
box-sizing: border-box;
transform: rotate(45deg) scale(0.5) translateZ(0);
transform-origin: 54% 48%;
}
.fui-ddm__item-text {
word-break: break-all;
font-weight: normal;
}
.fui-ddm__text-pl {
padding-left: 24rpx;
}
.fui-ddm__text-pr {
padding-right: 24rpx;
}
.fui-ddm__icon-box {
overflow: hidden;
background-color: #F1F4FA;
flex-shrink: 0;
}
.fui-ddm__icon-ml {
margin-left: 24rpx;
}
.fui-ddm__icon-mr {
margin-right: 24rpx;
}

View File

@@ -0,0 +1,53 @@
Component({
properties: {
src: {
type: String,
value: ''
},
width: {
type: String,
optionalTypes:[Number],
value: 576
},
height: {
type: String,
optionalTypes:[Number],
value: 318
},
title: {
type: String,
value: ''
},
color: {
type: String,
value: ''
},
size: {
type: String,
optionalTypes:[Number],
value: 32
},
descr: {
type: String,
value: ''
},
descrColor: {
type: String,
value: ''
},
descrSize: {
type: String,
optionalTypes:[Number],
value: 24
},
isFixed: {
type: Boolean,
value: false
},
marginTop: {
type: String,
optionalTypes:[Number],
value: 0
}
}
})

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