移除 lib下miniprogram_npm
This commit is contained in:
parent
21061896f4
commit
3df45090a6
|
|
@ -1,265 +0,0 @@
|
|||
import WxCanvas from './wx-canvas';
|
||||
import * as echarts from './echarts';
|
||||
|
||||
let ctx;
|
||||
|
||||
function compareVersion(v1, v2) {
|
||||
v1 = v1.split('.')
|
||||
v2 = v2.split('.')
|
||||
const len = Math.max(v1.length, v2.length)
|
||||
|
||||
while (v1.length < len) {
|
||||
v1.push('0')
|
||||
}
|
||||
while (v2.length < len) {
|
||||
v2.push('0')
|
||||
}
|
||||
|
||||
for (let i = 0; i < len; i++) {
|
||||
const num1 = parseInt(v1[i])
|
||||
const num2 = parseInt(v2[i])
|
||||
|
||||
if (num1 > num2) {
|
||||
return 1
|
||||
} else if (num1 < num2) {
|
||||
return -1
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
Component({
|
||||
properties: {
|
||||
canvasId: {
|
||||
type: String,
|
||||
value: 'ec-canvas'
|
||||
},
|
||||
|
||||
ec: {
|
||||
type: Object
|
||||
},
|
||||
|
||||
forceUseOldCanvas: {
|
||||
type: Boolean,
|
||||
value: false
|
||||
}
|
||||
},
|
||||
|
||||
data: {
|
||||
isUseNewCanvas: false
|
||||
},
|
||||
|
||||
ready: function () {
|
||||
// Disable prograssive because drawImage doesn't support DOM as parameter
|
||||
// See https://developers.weixin.qq.com/miniprogram/dev/api/canvas/CanvasContext.drawImage.html
|
||||
echarts.registerPreprocessor(option => {
|
||||
if (option && option.series) {
|
||||
if (option.series.length > 0) {
|
||||
option.series.forEach(series => {
|
||||
series.progressive = 0;
|
||||
});
|
||||
}
|
||||
else if (typeof option.series === 'object') {
|
||||
option.series.progressive = 0;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (!this.data.ec) {
|
||||
console.warn('组件需绑定 ec 变量,例:<ec-canvas id="mychart-dom-bar" '
|
||||
+ 'canvas-id="mychart-bar" ec="{{ ec }}"></ec-canvas>');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.data.ec.lazyLoad) {
|
||||
this.init();
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
init: function (callback) {
|
||||
const version = wx.getSystemInfoSync().SDKVersion
|
||||
|
||||
const canUseNewCanvas = compareVersion(version, '2.9.0') >= 0;
|
||||
const forceUseOldCanvas = this.data.forceUseOldCanvas;
|
||||
const isUseNewCanvas = canUseNewCanvas && !forceUseOldCanvas;
|
||||
this.setData({ isUseNewCanvas });
|
||||
|
||||
if (forceUseOldCanvas && canUseNewCanvas) {
|
||||
console.warn('开发者强制使用旧canvas,建议关闭');
|
||||
}
|
||||
|
||||
if (isUseNewCanvas) {
|
||||
// console.log('微信基础库版本大于2.9.0,开始使用<canvas type="2d"/>');
|
||||
// 2.9.0 可以使用 <canvas type="2d"></canvas>
|
||||
this.initByNewWay(callback);
|
||||
} else {
|
||||
const isValid = compareVersion(version, '1.9.91') >= 0
|
||||
if (!isValid) {
|
||||
console.error('微信基础库版本过低,需大于等于 1.9.91。'
|
||||
+ '参见:https://github.com/ecomfe/echarts-for-weixin'
|
||||
+ '#%E5%BE%AE%E4%BF%A1%E7%89%88%E6%9C%AC%E8%A6%81%E6%B1%82');
|
||||
return;
|
||||
} else {
|
||||
console.warn('建议将微信基础库调整大于等于2.9.0版本。升级后绘图将有更好性能');
|
||||
this.initByOldWay(callback);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
initByOldWay(callback) {
|
||||
// 1.9.91 <= version < 2.9.0:原来的方式初始化
|
||||
ctx = wx.createCanvasContext(this.data.canvasId, this);
|
||||
const canvas = new WxCanvas(ctx, this.data.canvasId, false);
|
||||
|
||||
echarts.setCanvasCreator(() => {
|
||||
return canvas;
|
||||
});
|
||||
// const canvasDpr = wx.getSystemInfoSync().pixelRatio // 微信旧的canvas不能传入dpr
|
||||
const canvasDpr = 1
|
||||
var query = wx.createSelectorQuery().in(this);
|
||||
query.select('.ec-canvas').boundingClientRect(res => {
|
||||
if (typeof callback === 'function') {
|
||||
this.chart = callback(canvas, res.width, res.height, canvasDpr);
|
||||
}
|
||||
else if (this.data.ec && typeof this.data.ec.onInit === 'function') {
|
||||
this.chart = this.data.ec.onInit(canvas, res.width, res.height, canvasDpr);
|
||||
}
|
||||
else {
|
||||
this.triggerEvent('init', {
|
||||
canvas: canvas,
|
||||
width: res.width,
|
||||
height: res.height,
|
||||
canvasDpr: canvasDpr // 增加了dpr,可方便外面echarts.init
|
||||
});
|
||||
}
|
||||
}).exec();
|
||||
},
|
||||
|
||||
initByNewWay(callback) {
|
||||
// version >= 2.9.0:使用新的方式初始化
|
||||
const query = wx.createSelectorQuery().in(this)
|
||||
query
|
||||
.select('.ec-canvas')
|
||||
.fields({ node: true, size: true })
|
||||
.exec(res => {
|
||||
const canvasNode = res[0].node
|
||||
this.canvasNode = canvasNode
|
||||
|
||||
const canvasDpr = wx.getSystemInfoSync().pixelRatio
|
||||
const canvasWidth = res[0].width
|
||||
const canvasHeight = res[0].height
|
||||
|
||||
const ctx = canvasNode.getContext('2d')
|
||||
|
||||
const canvas = new WxCanvas(ctx, this.data.canvasId, true, canvasNode)
|
||||
echarts.setCanvasCreator(() => {
|
||||
return canvas
|
||||
})
|
||||
|
||||
if (typeof callback === 'function') {
|
||||
this.chart = callback(canvas, canvasWidth, canvasHeight, canvasDpr)
|
||||
} else if (this.data.ec && typeof this.data.ec.onInit === 'function') {
|
||||
this.chart = this.data.ec.onInit(canvas, canvasWidth, canvasHeight, canvasDpr)
|
||||
} else {
|
||||
this.triggerEvent('init', {
|
||||
canvas: canvas,
|
||||
width: canvasWidth,
|
||||
height: canvasHeight,
|
||||
dpr: canvasDpr
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
canvasToTempFilePath(opt) {
|
||||
if (this.data.isUseNewCanvas) {
|
||||
// 新版
|
||||
const query = wx.createSelectorQuery().in(this)
|
||||
query
|
||||
.select('.ec-canvas')
|
||||
.fields({ node: true, size: true })
|
||||
.exec(res => {
|
||||
const canvasNode = res[0].node
|
||||
opt.canvas = canvasNode
|
||||
wx.canvasToTempFilePath(opt)
|
||||
})
|
||||
} else {
|
||||
// 旧的
|
||||
if (!opt.canvasId) {
|
||||
opt.canvasId = this.data.canvasId;
|
||||
}
|
||||
ctx.draw(true, () => {
|
||||
wx.canvasToTempFilePath(opt, this);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
touchStart(e) {
|
||||
if (this.chart && e.touches.length > 0) {
|
||||
var touch = e.touches[0];
|
||||
var handler = this.chart.getZr().handler;
|
||||
handler.dispatch('mousedown', {
|
||||
zrX: touch.x,
|
||||
zrY: touch.y,
|
||||
preventDefault: () => {},
|
||||
stopImmediatePropagation: () => {},
|
||||
stopPropagation: () => {}
|
||||
});
|
||||
handler.dispatch('mousemove', {
|
||||
zrX: touch.x,
|
||||
zrY: touch.y,
|
||||
preventDefault: () => {},
|
||||
stopImmediatePropagation: () => {},
|
||||
stopPropagation: () => {}
|
||||
});
|
||||
handler.processGesture(wrapTouch(e), 'start');
|
||||
}
|
||||
},
|
||||
|
||||
touchMove(e) {
|
||||
if (this.chart && e.touches.length > 0) {
|
||||
var touch = e.touches[0];
|
||||
var handler = this.chart.getZr().handler;
|
||||
handler.dispatch('mousemove', {
|
||||
zrX: touch.x,
|
||||
zrY: touch.y,
|
||||
preventDefault: () => {},
|
||||
stopImmediatePropagation: () => {},
|
||||
stopPropagation: () => {}
|
||||
});
|
||||
handler.processGesture(wrapTouch(e), 'change');
|
||||
}
|
||||
},
|
||||
|
||||
touchEnd(e) {
|
||||
if (this.chart) {
|
||||
const touch = e.changedTouches ? e.changedTouches[0] : {};
|
||||
var handler = this.chart.getZr().handler;
|
||||
handler.dispatch('mouseup', {
|
||||
zrX: touch.x,
|
||||
zrY: touch.y,
|
||||
preventDefault: () => {},
|
||||
stopImmediatePropagation: () => {},
|
||||
stopPropagation: () => {}
|
||||
});
|
||||
handler.dispatch('click', {
|
||||
zrX: touch.x,
|
||||
zrY: touch.y,
|
||||
preventDefault: () => {},
|
||||
stopImmediatePropagation: () => {},
|
||||
stopPropagation: () => {}
|
||||
});
|
||||
handler.processGesture(wrapTouch(e), 'end');
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function wrapTouch(event) {
|
||||
for (let i = 0; i < event.touches.length; ++i) {
|
||||
const touch = event.touches[i];
|
||||
touch.offsetX = touch.x;
|
||||
touch.offsetY = touch.y;
|
||||
}
|
||||
return event;
|
||||
}
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
{
|
||||
"component": true,
|
||||
"usingComponents": {}
|
||||
}
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
<!-- 新的:接口对其了H5 -->
|
||||
<canvas wx:if="{{isUseNewCanvas}}" type="2d" class="ec-canvas" canvas-id="{{ canvasId }}" bindinit="init" bindtouchstart="{{ ec.disableTouch ? '' : 'touchStart' }}" bindtouchmove="{{ ec.disableTouch ? '' : 'touchMove' }}" bindtouchend="{{ ec.disableTouch ? '' : 'touchEnd' }}"></canvas>
|
||||
<!-- 旧的 -->
|
||||
<canvas wx:else class="ec-canvas" canvas-id="{{ canvasId }}" bindinit="init" bindtouchstart="{{ ec.disableTouch ? '' : 'touchStart' }}" bindtouchmove="{{ ec.disableTouch ? '' : 'touchMove' }}" bindtouchend="{{ ec.disableTouch ? '' : 'touchEnd' }}"></canvas>
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
.ec-canvas {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
type Options = {
|
||||
width?: number;
|
||||
height?: number;
|
||||
devicePixelRatio?: number;
|
||||
};
|
||||
export declare function init(dom: any, theme?: string | null, options?: Options): any;
|
||||
export {};
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -1,111 +0,0 @@
|
|||
export default class WxCanvas {
|
||||
constructor(ctx, canvasId, isNew, canvasNode) {
|
||||
this.ctx = ctx;
|
||||
this.canvasId = canvasId;
|
||||
this.chart = null;
|
||||
this.isNew = isNew
|
||||
if (isNew) {
|
||||
this.canvasNode = canvasNode;
|
||||
}
|
||||
else {
|
||||
this._initStyle(ctx);
|
||||
}
|
||||
|
||||
// this._initCanvas(zrender, ctx);
|
||||
|
||||
this._initEvent();
|
||||
}
|
||||
|
||||
getContext(contextType) {
|
||||
if (contextType === '2d') {
|
||||
return this.ctx;
|
||||
}
|
||||
}
|
||||
|
||||
// canvasToTempFilePath(opt) {
|
||||
// if (!opt.canvasId) {
|
||||
// opt.canvasId = this.canvasId;
|
||||
// }
|
||||
// return wx.canvasToTempFilePath(opt, this);
|
||||
// }
|
||||
|
||||
setChart(chart) {
|
||||
this.chart = chart;
|
||||
}
|
||||
|
||||
addEventListener() {
|
||||
// noop
|
||||
}
|
||||
|
||||
attachEvent() {
|
||||
// noop
|
||||
}
|
||||
|
||||
detachEvent() {
|
||||
// noop
|
||||
}
|
||||
|
||||
_initCanvas(zrender, ctx) {
|
||||
zrender.util.getContext = function () {
|
||||
return ctx;
|
||||
};
|
||||
|
||||
zrender.util.$override('measureText', function (text, font) {
|
||||
ctx.font = font || '12px sans-serif';
|
||||
return ctx.measureText(text);
|
||||
});
|
||||
}
|
||||
|
||||
_initStyle(ctx) {
|
||||
ctx.createRadialGradient = () => {
|
||||
return ctx.createCircularGradient(arguments);
|
||||
};
|
||||
}
|
||||
|
||||
_initEvent() {
|
||||
this.event = {};
|
||||
const eventNames = [{
|
||||
wxName: 'touchStart',
|
||||
ecName: 'mousedown'
|
||||
}, {
|
||||
wxName: 'touchMove',
|
||||
ecName: 'mousemove'
|
||||
}, {
|
||||
wxName: 'touchEnd',
|
||||
ecName: 'mouseup'
|
||||
}, {
|
||||
wxName: 'touchEnd',
|
||||
ecName: 'click'
|
||||
}];
|
||||
eventNames.forEach(name => {
|
||||
this.event[name.wxName] = e => {
|
||||
const touch = e.touches[0];
|
||||
this.chart.getZr().handler.dispatch(name.ecName, {
|
||||
zrX: name.wxName === 'tap' ? touch.clientX : touch.x,
|
||||
zrY: name.wxName === 'tap' ? touch.clientY : touch.y,
|
||||
preventDefault: () => {},
|
||||
stopImmediatePropagation: () => {},
|
||||
stopPropagation: () => {}
|
||||
});
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
set width(w) {
|
||||
if (this.canvasNode) this.canvasNode.width = w
|
||||
}
|
||||
set height(h) {
|
||||
if (this.canvasNode) this.canvasNode.height = h
|
||||
}
|
||||
|
||||
get width() {
|
||||
if (this.canvasNode)
|
||||
return this.canvasNode.width
|
||||
return 0
|
||||
}
|
||||
get height() {
|
||||
if (this.canvasNode)
|
||||
return this.canvasNode.height
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
|
@ -1,124 +0,0 @@
|
|||
import zIndex from '../behaviors/zIndex';
|
||||
import hover from '../behaviors/hover';
|
||||
|
||||
Component({
|
||||
behaviors: [zIndex,hover],
|
||||
externalClasses: ['l-class-title', 'l-class-item', 'l-class-cancel','l-title-class','l-item-class','l-cancel-class'],
|
||||
properties: {
|
||||
locked: Boolean,
|
||||
showCancel: Boolean,
|
||||
show: Boolean,
|
||||
itemList: Array,
|
||||
cancelText: {
|
||||
type: String,
|
||||
value: '取消'
|
||||
},
|
||||
title: String,
|
||||
zIndex:{
|
||||
type:Number,
|
||||
value: 777
|
||||
},
|
||||
openApi: {
|
||||
type: Boolean,
|
||||
value: true,
|
||||
}
|
||||
},
|
||||
data: {
|
||||
success: '',
|
||||
fail: '',
|
||||
isIphoneX: false
|
||||
},
|
||||
attached() {
|
||||
if (this.data.openApi) {
|
||||
this.initActionSheet();
|
||||
}
|
||||
this.initUIAdapter();
|
||||
},
|
||||
|
||||
pageLifetimes: {
|
||||
show() {
|
||||
if (this.data.openApi) {
|
||||
this.initActionSheet();
|
||||
}
|
||||
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* 区分UI尺寸
|
||||
*/
|
||||
initUIAdapter() {
|
||||
wx.getSystemInfo({
|
||||
success: (res) => {
|
||||
this.setData({
|
||||
isIphoneX: res.model === 'iPhone X',
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
initActionSheet() {
|
||||
wx.lin = wx.lin || {};
|
||||
wx.lin.showActionSheet = (options={}) => {
|
||||
const {
|
||||
itemList = [],
|
||||
success = null,
|
||||
fail = null,
|
||||
title = '',
|
||||
locked = false,
|
||||
cancelText = '取消',
|
||||
showCancel = false,
|
||||
} = options;
|
||||
this.setData({
|
||||
itemList: itemList.slice(0, 10),
|
||||
success,
|
||||
fail,
|
||||
title,
|
||||
locked,
|
||||
cancelText,
|
||||
showCancel,
|
||||
show: true,
|
||||
});
|
||||
return this;
|
||||
};
|
||||
},
|
||||
handleClickItem(e) {
|
||||
const {
|
||||
success
|
||||
} = this.data;
|
||||
success && success({ ...e.currentTarget.dataset });
|
||||
this.triggerEvent('linitemtap', { ...e.currentTarget.dataset },{ bubbles: true, composed: true });
|
||||
this._hideActionSheet();
|
||||
},
|
||||
|
||||
_showActionSheet() {
|
||||
this.setData({
|
||||
show: true
|
||||
});
|
||||
},
|
||||
|
||||
_hideActionSheet() {
|
||||
this.setData({
|
||||
show: false
|
||||
});
|
||||
},
|
||||
|
||||
handleClickCancel() {
|
||||
const {
|
||||
fail
|
||||
} = this.data;
|
||||
fail && fail({
|
||||
errMsg: 'showactionsheet:fail cancel'
|
||||
});
|
||||
this.triggerEvent('lincancel', {
|
||||
errMsg: 'showactionsheet:fail cancel'
|
||||
},{ bubbles: true, composed: true });
|
||||
this._hideActionSheet();
|
||||
},
|
||||
|
||||
handleClickPopUp() {
|
||||
if (!this.data.locked) {
|
||||
this.handleClickCancel();
|
||||
}
|
||||
},
|
||||
}
|
||||
});
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"l-icon":"../icon/index",
|
||||
"l-popup":"../popup/index",
|
||||
"l-button":"../button/index"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
.l-action-sheet {
|
||||
background:#f7f7f7;
|
||||
}
|
||||
|
||||
.l-item-button {
|
||||
height: 88rpx;
|
||||
line-height: 88rpx;
|
||||
text-align: center;
|
||||
background: #fff;
|
||||
border-bottom: 2rpx solid #F3F3F3;
|
||||
font-size: 28rpx;
|
||||
color: #45526B;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.l-cancel {
|
||||
margin-top: 12rpx;
|
||||
}
|
||||
|
||||
.l-cancel-x .l-item-button{
|
||||
padding-bottom: 44rpx;
|
||||
}
|
||||
|
||||
.l-image-button > .l-button-text{
|
||||
margin-left: 20rpx;
|
||||
}
|
||||
|
||||
.list-hover{
|
||||
opacity: .8;
|
||||
}
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
<l-popup show="{{show}}" showMask="{{true}}" contentAlign="bottom" locked="{{locked}}" bind:lintap="handleClickPopUp" z-index="{{zIndex}}">
|
||||
<view class='l-action-sheet'>
|
||||
<view class="l-item-button l-class-title l-title-class" wx:if="{{title}}">
|
||||
{{ title }}
|
||||
</view>
|
||||
<view wx:for="{{ itemList }}" wx:key="name" hover-class="{{isHover?'list-hover':''}}">
|
||||
<l-button bind:lintap="handleClickItem" data-index="{{ index }}" data-item="{{ item }}" open-type="{{ item.openType }}" icon="{{ item.icon }}" type="default" size="large" special="{{true}}" long>
|
||||
<view style="{{ item.color ? 'color: ' + item.color : '' }}" class="l-item-button l-class-item l-item-class {{item.image || item.icon ? 'l-image-button':''}}">
|
||||
<image wx:if="{{item.image}}" class="l-button-image" src="{{item.image}}" style="{{item.imageStyle}}"/>
|
||||
<l-icon
|
||||
wx:elif="{{ item.icon }}"
|
||||
name="{{ item.icon }}"
|
||||
l-class="l-item-button"
|
||||
size="{{ item.iconSize }}"
|
||||
color="{{item.iconColor?item.iconColor:item.color}}"></l-icon>
|
||||
<text class="l-button-text">{{ item.name }}</text>
|
||||
</view>
|
||||
</l-button>
|
||||
</view>
|
||||
<view class="l-cancel l-class-cancel l-cancel-class {{isIphoneX ? 'l-cancel-x':''}}" wx:if="{{ showCancel }}" hover-class="{{isHover?'list-hover':''}}">
|
||||
<l-button type="default" size="large" long="true" bind:lintap="handleClickCancel" special="{{true}}">
|
||||
<view class="l-item-button l-cancel-button">{{ cancelText }}</view>
|
||||
</l-button>
|
||||
</view>
|
||||
</view>
|
||||
</l-popup>
|
||||
|
|
@ -1,189 +0,0 @@
|
|||
// miniprogram_npm/lin-ui/album/index.js
|
||||
Component({
|
||||
externalClasses: ['l-class', 'l-single-image-class', 'l-multi-image-class'],
|
||||
properties: {
|
||||
urls: {
|
||||
type: Array
|
||||
},
|
||||
// 是否可以预览
|
||||
preview: {
|
||||
type: Boolean,
|
||||
value: true
|
||||
},
|
||||
gapRow: {
|
||||
type: Number,
|
||||
value: 10,
|
||||
},
|
||||
gapColumn: {
|
||||
type: Number,
|
||||
value: 10,
|
||||
},
|
||||
// 单图时长边大小
|
||||
singleSize: {
|
||||
type: Number,
|
||||
value: 360,
|
||||
},
|
||||
// 多图时图片边长
|
||||
multipleSize: {
|
||||
type: Number,
|
||||
value: 158,
|
||||
},
|
||||
// 单图显示模式
|
||||
singleMode: {
|
||||
type: String,
|
||||
value: 'aspectFit',
|
||||
},
|
||||
// 多图显示模式
|
||||
multipleMode: {
|
||||
type: String,
|
||||
value: 'aspectFill',
|
||||
},
|
||||
key: {
|
||||
type: String,
|
||||
value: 'url'
|
||||
},
|
||||
maxNumber: {
|
||||
type: Number,
|
||||
value: 9
|
||||
},
|
||||
customRowNumber: {
|
||||
type: Boolean,
|
||||
value: false
|
||||
},
|
||||
everyRowNumber: {
|
||||
type: Number,
|
||||
value: 3
|
||||
},
|
||||
previewFullImage: {
|
||||
type: Boolean,
|
||||
value: true,
|
||||
}
|
||||
},
|
||||
|
||||
data: {
|
||||
// 传值方式是新方式还是旧方式
|
||||
newType: true,
|
||||
// 单图短边大小
|
||||
shortSideValue: 0,
|
||||
// 用于显示的图片列表
|
||||
showUrls: [],
|
||||
// 传入的url长度是否大于maxNumber指定的数量
|
||||
isLong: false,
|
||||
},
|
||||
|
||||
observers: {
|
||||
'urls': function () {
|
||||
this.init();
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
||||
/**
|
||||
* 在 urls 数据变化后进行初始化
|
||||
*/
|
||||
init() {
|
||||
// 取出参数
|
||||
let {urls, maxNumber, key} = this.data;
|
||||
|
||||
// 如果 urls 长度超出指定图片数量,则将其截断
|
||||
if (urls.length > maxNumber) {
|
||||
urls = urls.slice(0, maxNumber);
|
||||
this.setData({
|
||||
isLong: true,
|
||||
});
|
||||
}
|
||||
|
||||
this.setData({
|
||||
showUrls: urls
|
||||
});
|
||||
|
||||
if (!this.data.customRowNumber) {
|
||||
let urlLength = this.data.showUrls.length;
|
||||
if (urlLength > 1 && urlLength < 5 && urlLength !== 3) {
|
||||
this.setData({
|
||||
everyRowNumber: 2
|
||||
});
|
||||
} else (this.setData({
|
||||
everyRowNumber: 3
|
||||
}));
|
||||
}
|
||||
|
||||
// 判断传入模式
|
||||
const newType = this.judgeType();
|
||||
this.setData({
|
||||
newType
|
||||
});
|
||||
|
||||
if (urls.length === 1) {
|
||||
this.horizontalOrVertical(newType ? urls[0][key] : urls[0]);
|
||||
}
|
||||
},
|
||||
|
||||
// 判断传入的urls是字符串列表(old模式)还是对象列表(new模式)
|
||||
judgeType() {
|
||||
const urls = this.data.urls;
|
||||
if (urls.length !== 0) {
|
||||
if (typeof (urls[0]) !== 'object') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
//判断照片是横屏还是竖屏并计算短边的长度
|
||||
//如不指定短边的长度,短边会默认显示image组件的长度
|
||||
horizontalOrVertical: function (src) {
|
||||
wx.getImageInfo({
|
||||
src: src,
|
||||
success: (res) => {
|
||||
const longSide = res.width >= res.height ? res.width : res.height;
|
||||
const shortSide = res.width >= res.height ? res.height : res.width;
|
||||
this.setData({
|
||||
horizontalScreen: res.width >= res.height,
|
||||
shortSideValue: shortSide * this.data.singleSize / longSide
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
onPreviewTap(e) {
|
||||
const index = e.currentTarget.id;
|
||||
let urls;
|
||||
if (this.data.previewFullImage) {
|
||||
urls = this.data.urls;
|
||||
} else {
|
||||
urls = this.data.showUrls;
|
||||
}
|
||||
|
||||
let tempFilePath = '';
|
||||
let previewImageList = [];
|
||||
const newType = this.data.newType;
|
||||
const key = this.data.key;
|
||||
|
||||
if (newType) {
|
||||
tempFilePath = urls[index][key];
|
||||
for (let i = 0; i < urls.length; i++) {
|
||||
previewImageList.push(urls[i][key]);
|
||||
}
|
||||
} else {
|
||||
tempFilePath = urls[index];
|
||||
previewImageList = urls;
|
||||
}
|
||||
|
||||
let detail = {
|
||||
index, // 下标
|
||||
current: urls[index], // 当前显示图片的http链接
|
||||
all: urls // 需要预览的图片http链接列表
|
||||
};
|
||||
let option = {};
|
||||
if (this.data.preview === true) {
|
||||
wx.previewImage({
|
||||
current: tempFilePath, // 当前显示图片的http链接
|
||||
urls: previewImageList // 需要预览的图片http链接列表
|
||||
});
|
||||
}
|
||||
this.triggerEvent('lintap', detail, option);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
}
|
||||
}
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
/* miniprogram_npm/lin-ui/picture-album/index.wxss */
|
||||
.container {
|
||||
display: grid;
|
||||
}
|
||||
|
||||
.vertical {
|
||||
height: 360rpx;
|
||||
}
|
||||
|
||||
.parent {
|
||||
display: inline-grid;
|
||||
grid-template-columns: repeat(auto-fill);
|
||||
}
|
||||
|
||||
.child {
|
||||
box-sizing: border-box;
|
||||
background-color: white;
|
||||
flex: 0 0 44%;
|
||||
height: 100px;
|
||||
border: 1px solid red;
|
||||
margin-top: 4%;
|
||||
margin-left: 2%;
|
||||
margin-right: 2%;
|
||||
}
|
||||
|
||||
.dimback {
|
||||
background: #000;
|
||||
}
|
||||
|
||||
.dim {
|
||||
opacity: 0.6;
|
||||
filter: alpha(opacity=60);
|
||||
}
|
||||
|
||||
|
||||
.imageContainer {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.imageContainer:last-child>.text {
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
font-size: larger;
|
||||
}
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
<wxs src="index.wxs" module="album"></wxs>
|
||||
<!-- 最外层 view 用于修复 issue 1100 -->
|
||||
<view class="l-class" style="display:flex">
|
||||
<view style="{{album.gridStyle(gapRow, gapColumn, multipleSize, everyRowNumber)}}">
|
||||
<block wx:for="{{showUrls}}" wx:key="index" class="child">
|
||||
<view class="imageContainer {{album.dimBack(isLong, index, maxNumber, previewFullImage)}}" style="{{album.blockStyle(urls, horizontalScreen, shortSideValue, singleSize, multipleSize)}}">
|
||||
<image class="{{album.blockClass(urls, horizontalScreen) + ' ' + album.dim(isLong, index, maxNumber, previewFullImage)}}" id='{{index}}' bind:tap="onPreviewTap" style="{{album.blockStyle(urls, horizontalScreen, shortSideValue, singleSize, multipleSize)}}" src="{{newType?item[key]:item}}" mode="{{urls.length === 1?singleMode:multipleMode}}" />
|
||||
<view wx:if="{{album.image(isLong, index, maxNumber, previewFullImage)}}" class="text">+{{urls.length-maxNumber}}</view>
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
</view>
|
||||
|
|
@ -1,79 +0,0 @@
|
|||
var containerStyle = function (urls, multipleSize, gapRow, gapColumn) {
|
||||
if (urls.length === 2 || urls.length === 4) {
|
||||
return 'width:' + (2 * multipleSize + gapRow) + 'rpx; grid-row-gap:' + gapColumn + 'rpx; grid-column-gap:' + gapRow + 'rpx;grid-template-columns:repeat(auto-fit, ' + multipleSize + 'rpx);'
|
||||
} else {
|
||||
return 'width:' + (3 * multipleSize + 2 * gapRow) + 'rpx; grid-row-gap:' + gapColumn + 'rpx; grid-column-gap:' + gapRow + 'rpx;grid-template-columns:repeat(auto-fit, ' + multipleSize + 'rpx);'
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var blockClass = function (urls, horizontalScreen) {
|
||||
if (urls.length === 1) {
|
||||
if (horizontalScreen) {
|
||||
return 'l-single-image-class'
|
||||
} else {
|
||||
return 'vertical l-single-image-class'
|
||||
}
|
||||
} else {
|
||||
return 'l-multi-image-class'
|
||||
}
|
||||
}
|
||||
|
||||
var blockStyle = function (urls, horizontalScreen, shortSideValue, singleSize, multipleSize) {
|
||||
if (urls.length === 1) {
|
||||
if (horizontalScreen) {
|
||||
return 'height:' + shortSideValue + 'rpx;width:' + singleSize + 'rpx;'
|
||||
} else {
|
||||
return 'width:' + shortSideValue + 'rpx;height:' + singleSize + 'rpx;'
|
||||
}
|
||||
} else {
|
||||
return 'height:' + multipleSize + 'rpx;width:' + multipleSize + 'rpx;'
|
||||
}
|
||||
}
|
||||
|
||||
var gridStyle = function (gapRow, gapColumn, multipleSize, everyRowNumber) {
|
||||
return 'display:inline-grid;grid-template-columns: repeat(' + everyRowNumber + ',' + multipleSize + 'rpx);grid-row-gap:' + gapRow + 'rpx;grid-column-gap:' + gapColumn + 'rpx;'
|
||||
}
|
||||
|
||||
var dimBack = function (isLong, index, maxNumber, previewFullImage) {
|
||||
if (previewFullImage) {
|
||||
if (isLong) {
|
||||
if (index == maxNumber - 1) {
|
||||
return 'dimback'
|
||||
}
|
||||
}
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
var dim = function (isLong, index, maxNumber, previewFullImage) {
|
||||
if (previewFullImage) {
|
||||
if (isLong) {
|
||||
if (index == maxNumber - 1) {
|
||||
return 'dim'
|
||||
}
|
||||
}
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
var image = function (isLong, index, maxNumber, previewFullImage) {
|
||||
if (previewFullImage) {
|
||||
if (isLong) {
|
||||
if (index == maxNumber - 1) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
containerStyle: containerStyle,
|
||||
blockClass: blockClass,
|
||||
blockStyle: blockStyle,
|
||||
gridStyle: gridStyle,
|
||||
dimBack: dimBack,
|
||||
dim: dim,
|
||||
image: image,
|
||||
}
|
||||
|
|
@ -1,166 +0,0 @@
|
|||
import validator from '../behaviors/validator';
|
||||
import zIndex from '../behaviors/zIndex';
|
||||
const detail = true;
|
||||
const option = {
|
||||
bubbles: true,
|
||||
composed: true
|
||||
};
|
||||
|
||||
Component({
|
||||
/**
|
||||
* 组件的属性列表
|
||||
*/
|
||||
behaviors: [zIndex, validator],
|
||||
externalClasses: ['l-class', 'l-panel-class', 'l-bg-class', 'l-header-class'],
|
||||
options: {
|
||||
multipleSlots: true // 在组件定义时的选项中启用多slot支持
|
||||
},
|
||||
properties: {
|
||||
// 显示与隐藏
|
||||
show: {
|
||||
type: Boolean,
|
||||
value: false
|
||||
},
|
||||
// 最大高度
|
||||
maxHeight: {
|
||||
type: Number,
|
||||
value: 600
|
||||
},
|
||||
// 最小高度
|
||||
minHeight: {
|
||||
type: Number,
|
||||
value: 200
|
||||
},
|
||||
// 顶部弧度
|
||||
arcRadius: {
|
||||
type: Number,
|
||||
value: 18
|
||||
},
|
||||
// 动画效果的显示和隐藏
|
||||
transition: {
|
||||
type: Boolean,
|
||||
value: true
|
||||
},
|
||||
// 锁定
|
||||
locked: {
|
||||
type: Boolean,
|
||||
value: false
|
||||
},
|
||||
// 背景透明度
|
||||
opacity: {
|
||||
type: Number,
|
||||
value: 0.4
|
||||
},
|
||||
// 弹出方向
|
||||
direction: {
|
||||
type: String,
|
||||
options: ['top', 'bottom'],
|
||||
value: 'bottom'
|
||||
},
|
||||
// header是否吸顶
|
||||
headerFixed: {
|
||||
type: Boolean,
|
||||
value: true
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 组件的初始数据
|
||||
*/
|
||||
data: {
|
||||
_arcRadiusTop: 12,
|
||||
_ardRadiusBottom: 18,
|
||||
arcStyle: ''
|
||||
},
|
||||
|
||||
/**
|
||||
* 侦听器
|
||||
*/
|
||||
observers: {
|
||||
'show': function (show) {
|
||||
if (show) {
|
||||
this.triggerEvent('linshow', detail, option);
|
||||
this.getArcPopupStyle();
|
||||
} else {
|
||||
this.triggerEvent('linclose', detail, option);
|
||||
}
|
||||
},
|
||||
'arcRadius': function (arcRadius) {
|
||||
if (this.properties.direction === 'top') {
|
||||
this.data._arcRadiusTop = arcRadius;
|
||||
} else {
|
||||
this.data._ardRadiusBottom = arcRadius;
|
||||
}
|
||||
this.getArcPopupStyle();
|
||||
}
|
||||
},
|
||||
|
||||
pageLifetimes: {
|
||||
show() {
|
||||
this._init();
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* 组件的方法列表
|
||||
*/
|
||||
methods: {
|
||||
_init() {
|
||||
wx.lin = wx.lin || {};
|
||||
wx.lin.showArcPopup = (options) => {
|
||||
const {
|
||||
zIndex = 99,
|
||||
tranistion = true,
|
||||
direction = 'bottom',
|
||||
locked = false
|
||||
} = {
|
||||
...options
|
||||
};
|
||||
this.setData({
|
||||
zIndex,
|
||||
tranistion,
|
||||
direction,
|
||||
locked,
|
||||
show: true
|
||||
});
|
||||
};
|
||||
wx.lin.hideArcPopup = () => {
|
||||
this.setData({
|
||||
show: false
|
||||
});
|
||||
};
|
||||
},
|
||||
getArcPopupStyle() {
|
||||
const direction = this.properties.direction;
|
||||
const arcRadiusTop = this.data._arcRadiusTop;
|
||||
const ardRadiusBottom = this.data._ardRadiusBottom;
|
||||
const maxHeight = this.properties.maxHeight;
|
||||
const minHeight = this.properties.minHeight;
|
||||
const arcStyle = `
|
||||
border-bottom-left-radius:${direction === 'top' ? arcRadiusTop : 0}rpx;
|
||||
border-bottom-right-radius:${direction === 'top' ? arcRadiusTop : 0}rpx;
|
||||
border-top-left-radius:${direction === 'bottom' ? ardRadiusBottom : 0}rpx;
|
||||
border-top-right-radius:${direction === 'bottom' ? ardRadiusBottom : 0}rpx;
|
||||
max-height:${maxHeight}rpx;
|
||||
min-height:${minHeight}rpx;
|
||||
`;
|
||||
this.setData({
|
||||
arcStyle,
|
||||
});
|
||||
},
|
||||
onArcPopupTap() {
|
||||
if (this.data.locked) {
|
||||
return;
|
||||
}
|
||||
if (this.properties.show) {
|
||||
this.setData({
|
||||
show: false
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
ready() {
|
||||
this.getArcPopupStyle();
|
||||
}
|
||||
});
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"l-popup": "../popup/index"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
.container-arc-popup {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.arc-popup {
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.content-arc-popup {
|
||||
padding: 30rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.header-popup {
|
||||
width: 100%;
|
||||
z-index: 999;
|
||||
|
||||
&.fixed {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
background-color: #fff;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
<l-popup
|
||||
show="{{show}}"
|
||||
contentAlign="{{direction}}"
|
||||
transition="{{transition}}"
|
||||
opacity="{{opacity}}"
|
||||
locked="{{locked}}"
|
||||
z-index="{{zIndex}}"
|
||||
l-class="l-class"
|
||||
l-bg-class="l-bg-class"
|
||||
bind:lintap="onArcPopupTap"
|
||||
>
|
||||
<scroll-view
|
||||
scroll-y="true"
|
||||
class="arc-popup l-panel-class"
|
||||
style="{{arcStyle}}"
|
||||
>
|
||||
<view class="header-popup {{headerFixed ? 'fixed' : ''}} l-header-class">
|
||||
<slot name="header" />
|
||||
</view>
|
||||
<view class="content-arc-popup">
|
||||
<slot />
|
||||
</view>
|
||||
</scroll-view>
|
||||
</l-popup>
|
||||
|
|
@ -1,70 +0,0 @@
|
|||
Component({
|
||||
externalClasses: [
|
||||
'l-class',
|
||||
'l-class-text',
|
||||
'l-text-class'
|
||||
],
|
||||
properties: {
|
||||
icon: String,
|
||||
iconColor: {
|
||||
type: String,
|
||||
value: '#3963BC'
|
||||
},
|
||||
iconSize: {
|
||||
type: String,
|
||||
value: '28'
|
||||
},
|
||||
text: String,
|
||||
src: String,
|
||||
openData: {
|
||||
type: Array,
|
||||
observer: '_initOpenData'
|
||||
},
|
||||
shape: {
|
||||
type: String,
|
||||
value: 'circle'
|
||||
},
|
||||
mode: {
|
||||
type: String,
|
||||
value: 'scaleToFill'
|
||||
},
|
||||
size: {
|
||||
type: Number,
|
||||
value: 120,
|
||||
},
|
||||
placement: {
|
||||
type: String,
|
||||
value: 'right'
|
||||
},
|
||||
},
|
||||
data: {
|
||||
_isHaveUserNickName: false,
|
||||
_isHaveUserAvatarUrl: false,
|
||||
_iconSize: '',
|
||||
_iconColor: '#ffffff'
|
||||
},
|
||||
methods: {
|
||||
_initOpenData: function (openData) {
|
||||
this._isHaveUserAvatarUrl(openData);
|
||||
this._isHaveUserNickName(openData);
|
||||
},
|
||||
|
||||
_isHaveUserAvatarUrl: function (openData) {
|
||||
this.setData({
|
||||
_isHaveUserAvatarUrl: openData.indexOf('userAvatarUrl') !== -1
|
||||
});
|
||||
},
|
||||
|
||||
_isHaveUserNickName: function (openData) {
|
||||
this.setData({
|
||||
_isHaveUserNickName: openData.indexOf('userNickName') !== -1
|
||||
});
|
||||
},
|
||||
tapAvatar: function (e) {
|
||||
this.triggerEvent('lintap', e, {
|
||||
bubbles: true,
|
||||
composed: true
|
||||
});
|
||||
},
|
||||
}
|
||||
});
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"l-icon":"../icon/index"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,80 +0,0 @@
|
|||
@import "../styles/_base.less";
|
||||
.l-avatar {
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.l-avatar-image {
|
||||
flex: 1;
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background: @avatar-bg;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.l-avatar-text {
|
||||
display: inline-block;
|
||||
height: max-content;
|
||||
width: max-content;
|
||||
font-size:28rpx;
|
||||
color:rgba(69,82,107,1);
|
||||
line-height:40px;
|
||||
}
|
||||
.open-data {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.l-avatar-text .open-data,
|
||||
.l-avatar-text .l-avatar-text-text {
|
||||
font-size:inherit;
|
||||
color:inherit;
|
||||
line-height:inherit;
|
||||
}
|
||||
|
||||
.l-square {
|
||||
border-radius: 8rpx;
|
||||
}
|
||||
|
||||
.l-circle {
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.l-placement-left,
|
||||
.l-placement-right{
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.l-placement-left{
|
||||
margin-right: 24rpx;
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
|
||||
.l-placement-left .l-avatar-text {
|
||||
margin-right: 24rpx;
|
||||
}
|
||||
|
||||
.l-placement-right {
|
||||
flex-direction: row;
|
||||
}
|
||||
.l-placement-right .l-avatar-text {
|
||||
margin-left: 24rpx;
|
||||
}
|
||||
|
||||
.l-placement-top {
|
||||
flex-direction: column-reverse;
|
||||
}
|
||||
.l-placement-top .l-avatar-text {
|
||||
margin-bottom: 12rpx;
|
||||
}
|
||||
|
||||
|
||||
.l-placement-bottom {
|
||||
flex-direction: column;
|
||||
|
||||
}
|
||||
.l-placement-bottom .l-avatar-text {
|
||||
margin-top: 12rpx;
|
||||
}
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
|
||||
<view class="l-avatar {{text||_isHaveUserNickName?'l-placement-'+placement:''}}" mut-bind:tap="tapAvatar">
|
||||
<view class="l-avatar-image {{shape?'l-'+shape:''}} l-class" wx:if="{{_isHaveUserAvatarUrl||icon||src}}" style="width:{{size}}rpx;height:{{size}}rpx;min-width:{{size}}rpx;min-height:{{size}}rpx;">
|
||||
<open-data class="open-data" wx:if="{{_isHaveUserAvatarUrl}}" type="userAvatarUrl" />
|
||||
<l-icon wx:elif="{{icon}}" size="{{iconSize || size*0.6}}" color="{{iconColor||'#ffffff'}}" name="{{icon}}" />
|
||||
<image wx:elif="{{src}}" src="{{src}}" mode="{{mode}}" style="width:{{size}}rpx;height:{{size}}rpx" />
|
||||
</view>
|
||||
<view class="l-avatar-text l-class-text l-text-class" wx:if="{{text||_isHaveUserNickName}}">
|
||||
<open-data class="open-data" wx:if="{{_isHaveUserNickName}}" type="userNickName" />
|
||||
<text class="l-avatar-text-text" wx:elif="{{text}}">{{text}}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
|
@ -1,93 +0,0 @@
|
|||
import validator from '../behaviors/validator';
|
||||
|
||||
Component({
|
||||
externalClasses: ['l-class', 'l-class-self', 'l-self-class'],
|
||||
behaviors: [validator],
|
||||
properties: {
|
||||
// 红点模式
|
||||
dot: {
|
||||
type: Boolean,
|
||||
value: false
|
||||
},
|
||||
shape: {
|
||||
type: String,
|
||||
value: 'horn',
|
||||
options: ['horn', 'circle']
|
||||
},
|
||||
value: {
|
||||
type: String,
|
||||
value: '0'
|
||||
},
|
||||
mode: {
|
||||
type: String,
|
||||
value: 'number',
|
||||
options: ['number', 'text']
|
||||
},
|
||||
// 数字最大值
|
||||
maxCount: {
|
||||
type: Number,
|
||||
value: 99
|
||||
},
|
||||
// 数字形式
|
||||
numberType: {
|
||||
type: String,
|
||||
value: 'overflow',
|
||||
options: ['overflow', 'limit', 'ellipsis']
|
||||
},
|
||||
show: {
|
||||
type: Boolean,
|
||||
value: true
|
||||
}
|
||||
},
|
||||
data: {
|
||||
finalCount: 0
|
||||
},
|
||||
observers: {
|
||||
'value': function () {
|
||||
this.finalCount();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 最终数字
|
||||
finalCount() {
|
||||
if (isNaN(Number(this.data.value)) || (this.data.mode === 'text')) {
|
||||
this.setData({
|
||||
finalCount: this.data.value
|
||||
});
|
||||
} else {
|
||||
this.switchType();
|
||||
}
|
||||
},
|
||||
switchType() {
|
||||
switch (this.data.numberType) {
|
||||
case 'overflow':
|
||||
this.setData({
|
||||
finalCount: Number(this.data.value) > Number(this.data.maxCount) ? `${this.data.maxCount}+` : this.data.value
|
||||
});
|
||||
break;
|
||||
case 'ellipsis':
|
||||
this.setData({
|
||||
finalCount: Number(this.data.value) > Number(this.data.maxCount) ? '...' : this.data.value
|
||||
});
|
||||
break;
|
||||
case 'limit':
|
||||
this.setData({
|
||||
finalCount: Number(this.data.value) > 999 ? (Number(this.data.value) >= 9999 ? Math.floor(this.data.value / 10000 * 100) / 100 + 'w' : Math.floor(this.data.value / 1000 * 100) / 100 + 'k') : this.data.value
|
||||
});
|
||||
break;
|
||||
default:
|
||||
this.setData({
|
||||
finalCount: Number(this.data.value)
|
||||
});
|
||||
break;
|
||||
}
|
||||
},
|
||||
// 点击事件
|
||||
handleTap() {
|
||||
this.triggerEvent('lintap', {}, {
|
||||
bubbles: true,
|
||||
composed: true
|
||||
});
|
||||
},
|
||||
}
|
||||
});
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
@import "../styles/_base.less";
|
||||
|
||||
.l-badge {
|
||||
position : relative;
|
||||
display : inline-block;
|
||||
line-height : 1;
|
||||
vertical-align: middle;
|
||||
|
||||
&-content {
|
||||
max-width : 650rpx;
|
||||
left : 70%;
|
||||
background-color : #ff474b;
|
||||
color : #fff;
|
||||
position : absolute;
|
||||
font-size : 20rpx;
|
||||
display : inline-block;
|
||||
white-space : nowrap;
|
||||
text-overflow : ellipsis;
|
||||
overflow : hidden;
|
||||
text-align : center;
|
||||
box-sizing : border-box;
|
||||
z-index : 10;
|
||||
letter-spacing : .5rpx;
|
||||
|
||||
&-horn {
|
||||
height : 28rpx;
|
||||
min-width : 54rpx;
|
||||
padding : 0 8rpx;
|
||||
border-radius: 14rpx 14rpx 14rpx 0rpx;
|
||||
line-height : 28rpx;
|
||||
top : -10rpx;
|
||||
}
|
||||
|
||||
&-circle {
|
||||
height : 32rpx;
|
||||
min-width : 32rpx;
|
||||
padding : 0 10rpx;
|
||||
border-radius: 16rpx;
|
||||
line-height : 32rpx;
|
||||
top : -10rpx;
|
||||
}
|
||||
}
|
||||
|
||||
&-dot {
|
||||
height : 16rpx;
|
||||
width : 16rpx;
|
||||
transform : translateX(50%);
|
||||
border-radius : 50%;
|
||||
background-color: #ff474b;
|
||||
position : absolute;
|
||||
top : -4rpx;
|
||||
right : 0rpx;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
<view class="l-badge" mut-bind:tap="handleTap">
|
||||
<slot/>
|
||||
<block wx:if="{{show}}">
|
||||
<view wx:if="{{dot}}" class="l-badge-dot l-class l-class-self l-self-class"></view>
|
||||
<view wx:else class="{{'l-badge-content-'+shape}} l-badge-content l-class l-class-self l-self-class">{{finalCount}}</view>
|
||||
</block>
|
||||
</view>
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
// eslint-disable-next-line no-undef
|
||||
export default Behavior({
|
||||
behaviors: [],
|
||||
properties: {},
|
||||
data: {
|
||||
distance: 0
|
||||
},
|
||||
attached(){
|
||||
this.offsetMargin();
|
||||
},
|
||||
methods: {
|
||||
offsetMargin() {
|
||||
const { windowHeight, screenHeight } = wx.getSystemInfoSync();
|
||||
this.setData({
|
||||
distance: (screenHeight-windowHeight )
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -1,222 +0,0 @@
|
|||
// eslint-disable-next-line no-undef
|
||||
export default Behavior({
|
||||
behaviors: [],
|
||||
properties: {
|
||||
time: {
|
||||
optionalTypes: [String, Object],
|
||||
value: new Date().getTime() + 86400000,
|
||||
observer: function (newVal, oldVal) {
|
||||
if (newVal && !oldVal) {
|
||||
this.getLatestTime();
|
||||
}
|
||||
}
|
||||
},
|
||||
status: {
|
||||
type: Boolean,
|
||||
value: true,
|
||||
observer: function (newVal) {
|
||||
if (newVal) {
|
||||
this.init();
|
||||
} else if (!newVal) {
|
||||
clearInterval(this.data.timer);
|
||||
}
|
||||
}
|
||||
},
|
||||
timeType: {
|
||||
type: String,
|
||||
value: 'datetime'
|
||||
},
|
||||
format: {
|
||||
type: String,
|
||||
value: '{%d}天{%h}时{%m}分{%s}秒'
|
||||
},
|
||||
isZeroPadd: {
|
||||
type: Boolean,
|
||||
value: true,
|
||||
},
|
||||
countdownType: {
|
||||
type: String,
|
||||
value: 'normal'
|
||||
},
|
||||
isClearInterval: {
|
||||
type: Boolean,
|
||||
value: true
|
||||
}
|
||||
},
|
||||
data: {
|
||||
initAddTime: 0,
|
||||
timer: null,
|
||||
date: [],
|
||||
},
|
||||
ready: function () {
|
||||
this.getLatestTime();
|
||||
},
|
||||
|
||||
detached: function () {
|
||||
if (this.data.isClearInterval) {
|
||||
clearInterval(this.data.timer);
|
||||
}
|
||||
},
|
||||
|
||||
pageLifetimes: {
|
||||
hide() {
|
||||
if (this.data.isClearInterval) {
|
||||
clearInterval(this.data.timer);
|
||||
}
|
||||
|
||||
},
|
||||
show() {
|
||||
if (this.data.isClearInterval) {
|
||||
this.getLatestTime();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
// 自动补零
|
||||
zeroPadding(num) {
|
||||
num = num.toString();
|
||||
return num[1] ? num : '0' + num;
|
||||
},
|
||||
|
||||
init() {
|
||||
clearInterval(this.data.timer);
|
||||
const timer = setTimeout(() => {
|
||||
this.getLatestTime.call(this);
|
||||
}, 1000);
|
||||
this.setData({
|
||||
timer
|
||||
});
|
||||
},
|
||||
|
||||
getLatestTime() {
|
||||
let {
|
||||
time,
|
||||
status,
|
||||
timeType,
|
||||
initAddTime,
|
||||
countdownType,
|
||||
} = this.data;
|
||||
// IOS不支持2019-04-23 的日期格式
|
||||
let countDownTime = time;
|
||||
if (countdownType === 'normal') { //当countdownType === normal时,不影响之前的代码
|
||||
if (timeType !== 'second') {
|
||||
countDownTime = typeof time === 'string' ? countDownTime.replace(/-/g, '/') : countDownTime;
|
||||
countDownTime = Math.ceil((new Date(countDownTime).getTime() - new Date().getTime()) / 1000);
|
||||
}
|
||||
|
||||
if (countDownTime < 0 && timeType !== 'second') {
|
||||
this._getTimeValue(0);
|
||||
this.CountdownEnd();
|
||||
return;
|
||||
}
|
||||
|
||||
if (countDownTime - initAddTime > 0) {
|
||||
this.getLatestForCountDown(countDownTime);
|
||||
} else if (countDownTime - initAddTime < 0) {
|
||||
this.getLatestForAddTime(countDownTime);
|
||||
} else if (countDownTime - initAddTime === 0) {
|
||||
if (initAddTime <= 0) {
|
||||
this._getTimeValue(countDownTime);
|
||||
}
|
||||
this.CountdownEnd();
|
||||
}
|
||||
|
||||
if (status && countDownTime - initAddTime !== 0) {
|
||||
this.init.call(this);
|
||||
}
|
||||
|
||||
} else if (countdownType === 'anniversary') { // 当countdownType === anniversary时,为纪念日模式
|
||||
if (timeType === 'second') { // 纪念日模式不能设置timeType === second
|
||||
console.error(`countdownType为${countdownType}类型时,不可设置timeType值为second`);
|
||||
} else {
|
||||
countDownTime = typeof time === 'string' ? countDownTime.replace(/-/g, '/') : countDownTime;
|
||||
countDownTime = Math.ceil((new Date().getTime() - new Date(countDownTime).getTime()) / 1000);
|
||||
if (countDownTime >= 0) { // countDownTime计算结果不能为负数
|
||||
this.getLatestForCountDown(countDownTime);
|
||||
this.init.call(this);
|
||||
} else {
|
||||
console.error('time传值错误');
|
||||
}
|
||||
}
|
||||
} else { // countdownType 不能设置为 normal,anniversary 以外的值
|
||||
console.error('错误的countdownType类型');
|
||||
}
|
||||
},
|
||||
|
||||
getLatestForAddTime(countDownTime) {
|
||||
let {
|
||||
initAddTime
|
||||
} = this.data;
|
||||
if (initAddTime !== Math.abs(countDownTime)) {
|
||||
initAddTime++;
|
||||
this._getTimeValue(initAddTime);
|
||||
this.setData({
|
||||
initAddTime
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
getLatestForCountDown(countDownTime) {
|
||||
this._getTimeValue(countDownTime);
|
||||
this.setData({
|
||||
time: this.data.timeType === 'second' ? --countDownTime : this.data.time,
|
||||
});
|
||||
},
|
||||
|
||||
_getTimeValue(countDownTime) {
|
||||
const {
|
||||
format
|
||||
} = this.data;
|
||||
const date = [];
|
||||
const fomatArray = format.split(/(\{.*?\})/);
|
||||
const formatType = [{
|
||||
key: '{%d}',
|
||||
type: 'day',
|
||||
count: 86400
|
||||
}, {
|
||||
key: '{%h}',
|
||||
type: 'hour',
|
||||
count: 3600
|
||||
}, {
|
||||
key: '{%m}',
|
||||
type: 'minute',
|
||||
count: 60
|
||||
}, {
|
||||
key: '{%s}',
|
||||
type: 'second',
|
||||
count: 1,
|
||||
}];
|
||||
let diffSecond = countDownTime;
|
||||
formatType.forEach(format => {
|
||||
const index = this._findTimeName(fomatArray, format.key);
|
||||
if (index === -1) return;
|
||||
const name = fomatArray[index];
|
||||
const formatItem = {
|
||||
type: format.type,
|
||||
name,
|
||||
value: parseInt(diffSecond / format.count)
|
||||
};
|
||||
if (this.data.isZeroPadd) {
|
||||
formatItem.value = this.zeroPadding(formatItem.value);
|
||||
}
|
||||
diffSecond %= format.count;
|
||||
date.push(formatItem);
|
||||
});
|
||||
this.setData({
|
||||
date
|
||||
});
|
||||
return date;
|
||||
},
|
||||
|
||||
_findTimeName(fomatArray, str) {
|
||||
const index = fomatArray.indexOf(str);
|
||||
if (index === -1) return -1;
|
||||
return index + 1;
|
||||
},
|
||||
|
||||
CountdownEnd() {
|
||||
this.triggerEvent('linend', {});
|
||||
},
|
||||
}
|
||||
});
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
// eslint-disable-next-line no-undef
|
||||
export default Behavior({
|
||||
behaviors: [],
|
||||
properties: {
|
||||
isHover:{
|
||||
type: Boolean,
|
||||
value: true
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -1,144 +0,0 @@
|
|||
import Schema from '../common/async-validator/index';
|
||||
import validator from '../behaviors/validator';
|
||||
|
||||
/**
|
||||
* @param tipType String [toast , message , text]
|
||||
*/
|
||||
// eslint-disable-next-line no-undef
|
||||
export default Behavior({
|
||||
behaviors: [validator],
|
||||
properties: {
|
||||
// 校验
|
||||
rules: {
|
||||
optionalTypes: [Object, Array],
|
||||
value: []
|
||||
},
|
||||
tipType: {
|
||||
type: String,
|
||||
value: 'toast',
|
||||
options: ['toast', 'message', 'text']
|
||||
}
|
||||
},
|
||||
data: {
|
||||
schema: '',
|
||||
tipFun: {
|
||||
'message': 'showMessage',
|
||||
'toast': 'showToast',
|
||||
},
|
||||
tipContent: {
|
||||
'message': 'content',
|
||||
'toast': 'title',
|
||||
},
|
||||
errorText: '',
|
||||
errors: []
|
||||
},
|
||||
|
||||
methods: {
|
||||
initRules() {
|
||||
// const rulesName = this.data.name;
|
||||
const {
|
||||
rules
|
||||
} = this.data;
|
||||
if (!rules) return;
|
||||
// 如果rule 是单个object
|
||||
if (Object.prototype.toString.call(rules) === '[object Object]') {
|
||||
this.data.rules = [rules];
|
||||
}
|
||||
|
||||
this.data.rules.forEach(item => {
|
||||
if (!item.trigger) {
|
||||
item.trigger = [];
|
||||
return;
|
||||
}
|
||||
if (typeof item.trigger === 'string') {
|
||||
item.trigger = [item.trigger];
|
||||
return;
|
||||
}
|
||||
// if(Object.prototype.toString.call(item.trigger) === '[object Object]') {
|
||||
// item.trigger = ['blur'];
|
||||
// return;
|
||||
// }
|
||||
});
|
||||
|
||||
},
|
||||
getNeedValidateRule(type) {
|
||||
const rulesName = this.data.name;
|
||||
const {
|
||||
rules
|
||||
} = this.data;
|
||||
if (!rules) return;
|
||||
|
||||
const list = type ? rules.filter(item => {
|
||||
return item.trigger.indexOf(type) > -1;
|
||||
}) : rules;
|
||||
const schema = new Schema({
|
||||
[rulesName]: list,
|
||||
});
|
||||
this.setData({
|
||||
schema,
|
||||
});
|
||||
return list;
|
||||
},
|
||||
validatorData(value, type) {
|
||||
const {
|
||||
tipType,
|
||||
tipFun,
|
||||
tipContent
|
||||
} = this.data;
|
||||
const rules = this.getNeedValidateRule(type);
|
||||
|
||||
if (!rules) return;
|
||||
|
||||
// 把空字符串设置为 undefined ,见 issue 856
|
||||
// async-validator 对空字符串会进行类型检查,与required会冲突
|
||||
Object.getOwnPropertyNames(value).forEach((key) => {
|
||||
if (value[key] === '') {
|
||||
value[key] = undefined;
|
||||
}
|
||||
});
|
||||
|
||||
this.data.schema.validate(value, (errors) => {
|
||||
this.setData({
|
||||
errors: errors || []
|
||||
});
|
||||
|
||||
this.triggerEvent('linvalidate', {
|
||||
errors,
|
||||
isError: !!errors
|
||||
});
|
||||
|
||||
if (errors && tipType) {
|
||||
const funName = tipFun[tipType];
|
||||
const contentName = tipContent[tipType];
|
||||
if (tipType === 'text') {
|
||||
this.setData({
|
||||
errorText: errors[0].message
|
||||
});
|
||||
return errors;
|
||||
}
|
||||
|
||||
if (!wx.lin || !wx.lin[funName]) {
|
||||
wx.showToast({
|
||||
icon: 'none',
|
||||
title: `请在页面内引入${tipType}组件`
|
||||
});
|
||||
return errors;
|
||||
}
|
||||
|
||||
wx.lin[funName] && wx.lin[funName]({
|
||||
[contentName]: errors[0].message,
|
||||
duration: 1500,
|
||||
mask: false,
|
||||
});
|
||||
return errors;
|
||||
} else if (!errors && tipType) {
|
||||
this.setData({
|
||||
errorText: ''
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -1,57 +0,0 @@
|
|||
// eslint-disable-next-line no-undef
|
||||
export default Behavior({
|
||||
methods: {
|
||||
getRect(selector, all = false) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const query = wx.createSelectorQuery().in(this);
|
||||
const type = all ? query.selectAll(selector) : query.select(selector);
|
||||
type.boundingClientRect((res) => {
|
||||
if (!res) return reject('找不到元素');
|
||||
resolve(res);
|
||||
}).exec();
|
||||
});
|
||||
},
|
||||
queryScrollNode(res, currentIndex, type = 'width') {
|
||||
if (currentIndex < 0) return;
|
||||
const currentRect = res[currentIndex];
|
||||
this.getRect('.l-tabsscroll').then(_ => {
|
||||
if (!_) return console.error('找不到元素');
|
||||
const scrollWidth = _[type];
|
||||
let transformDistance = res
|
||||
.slice(0, currentIndex)
|
||||
.reduce((prev, curr) => prev + curr[type], 0);
|
||||
transformDistance += (currentRect[type] - scrollWidth) / 2;
|
||||
|
||||
if (type === 'width') {
|
||||
this.setData({
|
||||
transformX: transformDistance,
|
||||
transformY: 0
|
||||
});
|
||||
} else {
|
||||
this.setData({
|
||||
transformX: 0,
|
||||
transformY: transformDistance
|
||||
});
|
||||
}
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
});
|
||||
},
|
||||
queryMultipleNodes() {
|
||||
const {
|
||||
placement,
|
||||
currentIndex
|
||||
} = this.data;
|
||||
this.getRect('.l-tabs-item', true)
|
||||
.then((res) => {
|
||||
if (['top', 'bottom'].indexOf(placement) !== -1) {
|
||||
this.queryScrollNode(res, currentIndex);
|
||||
} else {
|
||||
this.queryScrollNode(res, currentIndex, 'height');
|
||||
}
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -1,122 +0,0 @@
|
|||
const isObj = (x) => {
|
||||
const type = typeof x;
|
||||
return x !== null && (type === 'object' || type === 'function');
|
||||
};
|
||||
const getClassNames = (name) => ({
|
||||
enter: `l-${name}-enter l-${name}-enter-active l-enter-class l-enter-active-class`,
|
||||
'enter-to': `l-${name}-enter-to l-${name}-enter-active l-enter-to-class l-enter-active-class`,
|
||||
leave: `l-${name}-leave l-${name}-leave-active l-leave-class l-leave-active-class`,
|
||||
'leave-to': `l-${name}-leave-to l-${name}-leave-active l-leave-to-class l-leave-active-class`
|
||||
});
|
||||
const nextTick = () => new Promise(resolve => setTimeout(resolve, 1000 / 30));
|
||||
export default (showDefaultValue) => {
|
||||
// eslint-disable-next-line no-undef
|
||||
return Behavior({
|
||||
properties: {
|
||||
customStyle: String,
|
||||
show: {
|
||||
type: Boolean,
|
||||
value: showDefaultValue,
|
||||
observer: 'observeShow'
|
||||
},
|
||||
duration: {
|
||||
type: null,
|
||||
value: 300,
|
||||
observer: 'observeDuration'
|
||||
},
|
||||
name: {
|
||||
type: String,
|
||||
value: 'fade'
|
||||
}
|
||||
},
|
||||
data: {
|
||||
type: '',
|
||||
inited: false,
|
||||
display: false
|
||||
},
|
||||
attached() {
|
||||
if (this.data.show) {
|
||||
this.enter();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
observeShow(value) {
|
||||
value ? this.enter() : this.leave();
|
||||
},
|
||||
enter() {
|
||||
const { duration, name } = this.data;
|
||||
const classNames = getClassNames(name);
|
||||
const currentDuration = isObj(duration) ? duration.enter : duration;
|
||||
this.status = 'enter';
|
||||
this.triggerEvent('linbeforeenter');
|
||||
Promise.resolve()
|
||||
.then(nextTick)
|
||||
.then(() => {
|
||||
this.checkStatus('enter');
|
||||
this.triggerEvent('linenter');
|
||||
this.setData({
|
||||
inited: true,
|
||||
display: true,
|
||||
classes: classNames.enter,
|
||||
currentDuration
|
||||
});
|
||||
})
|
||||
.then(nextTick)
|
||||
.then(() => {
|
||||
this.checkStatus('enter');
|
||||
this.transitionEnded = false;
|
||||
this.setData({
|
||||
classes: classNames['enter-to']
|
||||
});
|
||||
})
|
||||
.catch(() => { });
|
||||
},
|
||||
leave() {
|
||||
if (!this.data.display) {
|
||||
return;
|
||||
}
|
||||
const { duration, name } = this.data;
|
||||
const classNames = getClassNames(name);
|
||||
const currentDuration = isObj(duration) ? duration.leave : duration;
|
||||
this.status = 'leave';
|
||||
this.triggerEvent('linbeforeleave');
|
||||
Promise.resolve()
|
||||
.then(nextTick)
|
||||
.then(() => {
|
||||
this.checkStatus('leave');
|
||||
this.triggerEvent('linleave');
|
||||
this.setData({
|
||||
classes: classNames.leave,
|
||||
currentDuration
|
||||
});
|
||||
})
|
||||
.then(nextTick)
|
||||
.then(() => {
|
||||
this.checkStatus('leave');
|
||||
this.transitionEnded = false;
|
||||
setTimeout(() => this.onTransitionEnd(), currentDuration);
|
||||
this.setData({
|
||||
classes: classNames['leave-to']
|
||||
});
|
||||
})
|
||||
.catch(() => { });
|
||||
},
|
||||
checkStatus(status) {
|
||||
if (status !== this.status) {
|
||||
throw new Error(`incongruent status: ${status}`);
|
||||
}
|
||||
},
|
||||
onTransitionEnd() {
|
||||
if (this.transitionEnded) {
|
||||
return;
|
||||
}
|
||||
this.transitionEnded = true;
|
||||
this.triggerEvent(`linafter${this.status}`);
|
||||
const { show, display } = this.data;
|
||||
if (!show && display) {
|
||||
this.setData({ display: false });
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
// eslint-disable-next-line no-undef
|
||||
export default Behavior({
|
||||
definitionFilter(defFields) {
|
||||
const {
|
||||
properties
|
||||
} = defFields;
|
||||
const propsKey = Object.keys(properties);
|
||||
propsKey.forEach(name => {
|
||||
const {
|
||||
options
|
||||
} = properties[name];
|
||||
if (options) {
|
||||
properties[name].observer = function (newValue) {
|
||||
if (!options.includes(newValue) && newValue) {
|
||||
console.error(`${name}: ${newValue} must be in the [${options}]`);
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
// eslint-disable-next-line no-undef
|
||||
export default Behavior({
|
||||
observers: {
|
||||
'show': function (show) {
|
||||
show && this.changeStatus();
|
||||
if (!show) this.setData({
|
||||
status: show
|
||||
});
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
changeStatus() {
|
||||
this.setData({
|
||||
status: true
|
||||
});
|
||||
if (this.data.timer) clearTimeout(this.data.timer);
|
||||
this.data.timer = setTimeout(() => {
|
||||
this.setData({
|
||||
status: false
|
||||
});
|
||||
if (this.data.success) this.data.success();
|
||||
this.data.timer = null;
|
||||
}, this.properties.duration);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
// eslint-disable-next-line no-undef
|
||||
export default Behavior({
|
||||
behaviors: [],
|
||||
properties: {
|
||||
zIndex:{
|
||||
type: Number,
|
||||
value: 777
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -1,94 +0,0 @@
|
|||
import validator from '../behaviors/validator';
|
||||
|
||||
Component({
|
||||
externalClasses: [
|
||||
'l-class',
|
||||
'l-label-class',
|
||||
'l-hover-class',
|
||||
'l-img-class',
|
||||
'l-icon-class'
|
||||
],
|
||||
behaviors: [validator],
|
||||
properties: {
|
||||
// button组建标识
|
||||
name: {
|
||||
type: String,
|
||||
value: 'lin'
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
value: 'default',
|
||||
options: ['warning', 'success', 'error', 'default']
|
||||
},
|
||||
plain: Boolean,
|
||||
size: {
|
||||
type: String,
|
||||
value: 'medium',
|
||||
options: ['medium', 'large', 'mini', 'long']
|
||||
},
|
||||
shape: {
|
||||
type: String,
|
||||
value: 'circle',
|
||||
options: ['square', 'circle', 'semicircle']
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
special: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
loading: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
// 微信原生接口
|
||||
width: Number,
|
||||
height: Number,
|
||||
icon: String,
|
||||
image: String,
|
||||
bgColor: String,
|
||||
iconColor: String,
|
||||
iconSize: String,
|
||||
openType: String,
|
||||
appParameter: String,
|
||||
lang: String,
|
||||
hoverStopPropagation: Boolean,
|
||||
hoverStartTime: {
|
||||
type: Number,
|
||||
value: 20
|
||||
},
|
||||
hoverStayTime: {
|
||||
type: Number,
|
||||
value: 70
|
||||
},
|
||||
sessionFrom: {
|
||||
type: String,
|
||||
value: ''
|
||||
},
|
||||
sendMessageTitle: String,
|
||||
sendMessagePath: String,
|
||||
sendMessageImg: String,
|
||||
showMessageCard: Boolean,
|
||||
formType: String,
|
||||
disabledHover: {
|
||||
type: Boolean,
|
||||
value: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// button点击事件
|
||||
handleTap() {
|
||||
if (this.data.disabled || this.data.loading) return false;
|
||||
this.triggerEvent('lintap', {}, {
|
||||
bubbles: true,
|
||||
composed: true
|
||||
});
|
||||
},
|
||||
// 开放能力事件回调
|
||||
openTypeEvent(data) {
|
||||
this.triggerEvent(data.type, data.detail, {});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"l-icon":"../icon/index"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,189 +0,0 @@
|
|||
@import '../styles/_base.less';
|
||||
@import '../styles/_mixins.less';
|
||||
|
||||
.btn-hover::before {
|
||||
.active();
|
||||
}
|
||||
|
||||
.special-container {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.l-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
white-space: nowrap;
|
||||
font-size: 28rpx;
|
||||
position: relative;
|
||||
color: #fff;
|
||||
padding: 0 12rpx;
|
||||
box-sizing: border-box;
|
||||
|
||||
// img-size
|
||||
&-img {
|
||||
&-mini {
|
||||
width: @btn-height-mini / 2;
|
||||
height: @btn-height-mini / 2;
|
||||
}
|
||||
&-medium {
|
||||
width: @btn-height / 2;
|
||||
height: @btn-height / 2;
|
||||
}
|
||||
&-large {
|
||||
height: @btn-height-large / 2;
|
||||
width: @btn-height-large / 2;
|
||||
}
|
||||
}
|
||||
|
||||
// Size
|
||||
&-long {
|
||||
border-radius: 0;
|
||||
height: 88rpx;
|
||||
width: 100%;
|
||||
}
|
||||
&-medium {
|
||||
height: @btn-height;
|
||||
min-width: @btn-width;
|
||||
}
|
||||
&-large {
|
||||
height: @btn-height-large;
|
||||
min-width: @btn-width-large;
|
||||
}
|
||||
&-mini {
|
||||
height: @btn-height-mini;
|
||||
min-width: @btn-width-mini;
|
||||
font-size: @size-font-mini;
|
||||
}
|
||||
|
||||
//Type
|
||||
&-default {
|
||||
background-color: @default-color;
|
||||
}
|
||||
|
||||
&-success {
|
||||
background-color: @success-color;
|
||||
}
|
||||
|
||||
&-warning {
|
||||
background-color: @warning-color;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
&-error {
|
||||
background-color: @error-color;
|
||||
}
|
||||
|
||||
// Shape
|
||||
&-square {
|
||||
border-radius: 0;
|
||||
}
|
||||
&-semicircle {
|
||||
border-radius: @btn-circle-size;
|
||||
}
|
||||
&-large&-semicircle {
|
||||
border-radius: @btn-circle-size-large;
|
||||
}
|
||||
&-mini&-semicircle {
|
||||
border-radius: @btn-circle-size-mini;
|
||||
}
|
||||
&-circle {
|
||||
border-radius: @btn-circle-size / 5;
|
||||
}
|
||||
&-large&-circle {
|
||||
border-radius: @btn-circle-size-large / 5;
|
||||
}
|
||||
&-mini&-circle {
|
||||
border-radius: @btn-circle-size-mini / 5;
|
||||
}
|
||||
|
||||
// Plain
|
||||
&-plain {
|
||||
background-color: #fff;
|
||||
color: @default-color;
|
||||
border: 2rpx solid @default-color;
|
||||
}
|
||||
&-success&-plain {
|
||||
background-color: #fff;
|
||||
color: @success-color;
|
||||
border: 2rpx solid @success-color;
|
||||
}
|
||||
&-error&-plain {
|
||||
background-color: #fff;
|
||||
color: @error-color;
|
||||
border: 2rpx solid @error-color;
|
||||
}
|
||||
&-warning&-plain {
|
||||
background-color: #fff;
|
||||
color: @warning-color;
|
||||
border: 2rpx solid @warning-color;
|
||||
}
|
||||
|
||||
// Loading
|
||||
&-loading {
|
||||
opacity: 0.6;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
width: 24rpx;
|
||||
height: 24rpx;
|
||||
background: transparent;
|
||||
border-radius: 50%;
|
||||
border: 4rpx solid @btn-loading-color;
|
||||
border-color: @btn-loading-color @btn-loading-color @btn-loading-color
|
||||
transparent;
|
||||
animation: btn-spin 0.6s linear;
|
||||
animation-iteration-count: infinite;
|
||||
&-default {
|
||||
border: 4rpx solid @default-color;
|
||||
border-color: @default-color @default-color @default-color
|
||||
transparent;
|
||||
}
|
||||
&-success {
|
||||
border: 4rpx solid @success-color;
|
||||
border-color: @success-color @success-color @success-color
|
||||
transparent;
|
||||
}
|
||||
&-error {
|
||||
border: 4rpx solid @error-color;
|
||||
border-color: @error-color @error-color @error-color transparent;
|
||||
}
|
||||
&-warning {
|
||||
border: 4rpx solid @warning-color;
|
||||
border-color: @warning-color @warning-color @warning-color
|
||||
transparent;
|
||||
}
|
||||
}
|
||||
|
||||
// Disabled
|
||||
&-disabled {
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
|
||||
.icon {
|
||||
display: flex !important;
|
||||
}
|
||||
|
||||
.margin {
|
||||
&-mini {
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
&-medium {
|
||||
margin-right: 18rpx;
|
||||
}
|
||||
&-large {
|
||||
margin-right: 24rpx;
|
||||
}
|
||||
&-long {
|
||||
margin-right: 24rpx;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes btn-spin {
|
||||
0% {
|
||||
transform: rotate(0);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
<label for="{{name}}" mut-bind:tap="handleTap" class="l-label-class">
|
||||
<block wx:if="{{special}}">
|
||||
<view class="special-container l-class">
|
||||
<slot/>
|
||||
</view>
|
||||
</block>
|
||||
<block wx:else>
|
||||
<view class="l-btn {{ 'l-btn-' + size }} {{ 'l-btn-' + type }} {{ 'l-btn-' + shape }} {{plain?'l-btn-plain':''}} {{ disabled ? 'l-btn-disabled' : ''}} l-class "
|
||||
hover-class="{{disabled?'':disabledHover?'':'btn-hover l-hover-class'}}"
|
||||
hover-stop-propagation="{{hoverStopPropagation}}"
|
||||
hover-start-time="{{hoverStartTime}}"
|
||||
hover-stay-time="{{hoverStayTime}}"
|
||||
style="{{width?'min-width:'+width+'rpx;':''}} {{height?'height:'+height+'rpx;'+'line-height:'+height+'rpx;':''}} {{size=='long'?'border-radius:0;':''}} {{'background-color:'+bgColor}}">
|
||||
<view wx:if="{{loading}}" class="l-btn-loading {{'margin-' + size}} {{ plain ?'l-btn-loading-' + type : '' }}"></view>
|
||||
<l-icon l-class="l-icon-class" class="{{'margin-' + size}}" wx:if="{{icon}}" name="{{icon}}" color="{{iconColor}}" size="{{iconSize}}" />
|
||||
<slot/>
|
||||
</view>
|
||||
</block>
|
||||
</label>
|
||||
<button style="position: absolute;top: -999px;left: -999px;"
|
||||
wx:if="{{openType}}"
|
||||
id="{{name}}"
|
||||
lang="{{lang}}"
|
||||
form-type="{{formType}}"
|
||||
open-type="{{openType}}"
|
||||
app-parameter="{{ appParameter }}"
|
||||
hover-stop-propagation="{{ hoverStopPropagation }}"
|
||||
hover-start-time="{{ hoverStartTime }}"
|
||||
hover-stay-time="{{ hoverStayTime }}"
|
||||
session-from="{{ sessionFrom }}"
|
||||
send-message-title="{{ sendMessageTitle }}"
|
||||
send-message-path="{{ sendMessagePath }}"
|
||||
send-message-img="{{ sendMessageImg }}"
|
||||
show-message-card="{{ showMessageCard }}"
|
||||
bindcontact="openTypeEvent"
|
||||
bindgetuserinfo="openTypeEvent"
|
||||
bindgetphonenumber="openTypeEvent"
|
||||
bindopensetting="openTypeEvent"
|
||||
bindchooseavatar="openTypeEvent">
|
||||
</button>
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
<wxs src="./index.wxs" module="computed"></wxs>
|
||||
|
||||
<template name="calendar">
|
||||
<view class="calendar-container">
|
||||
<header showTitle="{{ showTitle }}" showSubtitle="{{ showSubtitle }}" title="{{ title }}" subTitle="{{ subTitle }}"></header>
|
||||
<scroll-view class="calendar-body-wrap" scroll-y scroll-into-view="{{ scrollIntoViewIndex }}">
|
||||
<mounth
|
||||
wx:for="{{ computed.getMonths(minDate, maxDate) }}"
|
||||
wx:key="index"
|
||||
id="month{{ index }}"
|
||||
class="month"
|
||||
data-date="{{ item }}"
|
||||
date="{{ item }}"
|
||||
minDate="{{ minDate }}"
|
||||
maxDate="{{ maxDate }}"
|
||||
currentDate="{{ currentDate }}"
|
||||
type="{{ type }}"
|
||||
bind:clickDay="clickDay"
|
||||
showMonthTitle="{{ index !== 0 }}"
|
||||
formatter="{{ formatter }}"
|
||||
color="{{ color }}"
|
||||
>
|
||||
</mounth>
|
||||
</scroll-view>
|
||||
<view>
|
||||
<l-button type="default" l-class="bottom-button" size="long" bind:lintap="onClickConfirm" bg-color="{{ color }}">{{confirmText}}</l-button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
Component({
|
||||
data: {},
|
||||
properties: {
|
||||
text: null,
|
||||
topInfo: null,
|
||||
bottomInfo: null,
|
||||
type: null,
|
||||
color: {
|
||||
type: String,
|
||||
value: ''
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
}
|
||||
});
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
{
|
||||
"component": true
|
||||
}
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
@import "../../../styles/_base.less";
|
||||
.calendar-day-container{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
color: #666;
|
||||
&.selected{
|
||||
background-color: @default-color;
|
||||
color: #ffffff;
|
||||
border-radius: 8rpx;
|
||||
}
|
||||
&.start{
|
||||
background-color: @default-color;
|
||||
color: #ffffff;
|
||||
border-radius: 8rpx;
|
||||
}
|
||||
&.end{
|
||||
background-color: @default-color;
|
||||
color: #ffffff;
|
||||
border-radius: 8rpx;
|
||||
}
|
||||
&.disabled{
|
||||
color: #c8c9cc;
|
||||
cursor: default;
|
||||
background: #ffffff;
|
||||
}
|
||||
&.middle{
|
||||
color: @default-color;
|
||||
&::after{
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
background-color: currentColor;
|
||||
opacity: 0.1;
|
||||
content: '';
|
||||
}
|
||||
}
|
||||
// background-color: red;
|
||||
// color: #eff9f0;
|
||||
.top{
|
||||
height: 24rpx;
|
||||
line-height: 24rpx;
|
||||
font-size: 16rpx;
|
||||
}
|
||||
.text{
|
||||
flex: 1;
|
||||
font-size: 32rpx;
|
||||
}
|
||||
.bottom{
|
||||
height: 24rpx;
|
||||
line-height: 24rpx;
|
||||
font-size: 16rpx;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
<wxs src="./index.wxs" module="computed"></wxs>
|
||||
<view class="calendar-day-container {{ type }}"
|
||||
style="{{ computed.getDayStyle(type, color) }}"
|
||||
>
|
||||
<view class="top">{{ topInfo }}</view>
|
||||
<view class="text">{{ text }}</view>
|
||||
<view class="bottom">{{ bottomInfo }}</view>
|
||||
</view>
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
function getDayStyle(type, color) {
|
||||
var style = [];
|
||||
|
||||
if (color) {
|
||||
if (
|
||||
type === 'start' ||
|
||||
type === 'end' ||
|
||||
type === 'selected'
|
||||
) {
|
||||
style.push(['background', color]);
|
||||
} else if (type === 'middle') {
|
||||
style.push(['color', color]);
|
||||
// style.push(['background', color]);
|
||||
// style.push(['opacity', '0.1']);
|
||||
}
|
||||
}
|
||||
|
||||
return style
|
||||
.map(function(item) {
|
||||
return item.join(':');
|
||||
})
|
||||
.join(';');
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getDayStyle: getDayStyle,
|
||||
};
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
Component({
|
||||
data: {
|
||||
weekdays: ['日', '一', '二', '三', '四', '五', '六']
|
||||
},
|
||||
properties: {
|
||||
title: {
|
||||
type: String,
|
||||
value: '日期选择'
|
||||
},
|
||||
subTitle: String,
|
||||
showTitle: Boolean,
|
||||
showSubtitle: Boolean
|
||||
},
|
||||
methods: {}
|
||||
});
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
{
|
||||
"component": true
|
||||
}
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
.calendar-header-container{
|
||||
.calendar-header-container_title{
|
||||
text-align: center;
|
||||
padding: 20rpx 0;
|
||||
font-size: 36rpx;
|
||||
line-height: 44rpx;
|
||||
}
|
||||
.calendar-header-container_subtitle{
|
||||
text-align: center;
|
||||
font-size: 36rpx;
|
||||
line-height: 44rpx;
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
.calendar-header__weekdays{
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin: 0 20rpx;
|
||||
padding: 10rpx 0;
|
||||
border-bottom: 1rpx solid #F3F3F3;
|
||||
.calendar-header__weekday{
|
||||
width: 14.285%;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
<view class="calendar-header-container">
|
||||
<block wx:if="{{ showTitle }}">
|
||||
<!-- <view class="calendar-header-container_title">
|
||||
<slot name="title"></slot>
|
||||
</view> -->
|
||||
<view class="calendar-header-container_title">
|
||||
{{ title }}
|
||||
</view>
|
||||
</block>
|
||||
|
||||
<view wx:if="{{ showSubtitle }}" class="calendar-header-container_subtitle">
|
||||
{{ subTitle }}
|
||||
</view>
|
||||
|
||||
<view class="calendar-header__weekdays">
|
||||
<view wx:for="{{ weekdays }}" wx:key="index" class="calendar-header__weekday">
|
||||
{{ item }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
|
@ -1,195 +0,0 @@
|
|||
import { compareDay, getMonthEndDay } from '../../util';
|
||||
import * as config from '../../config';
|
||||
Component({
|
||||
data: {
|
||||
days: []
|
||||
},
|
||||
properties: {
|
||||
minDate: {
|
||||
type: Object,
|
||||
optionalTypes: [String, null],
|
||||
},
|
||||
maxDate: {
|
||||
type: Object,
|
||||
optionalTypes: [String, null],
|
||||
},
|
||||
formatter: {
|
||||
type: null,
|
||||
observer: 'setDays'
|
||||
},
|
||||
date: {
|
||||
type: null,
|
||||
observer: 'setDays'
|
||||
},
|
||||
currentDate: {
|
||||
type: Array,
|
||||
optionalTypes: [null],
|
||||
observer() {
|
||||
this.setDays();
|
||||
}
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
observer: 'setDays'
|
||||
},
|
||||
showMonthTitle: Boolean,
|
||||
color: {
|
||||
type: String,
|
||||
value: ''
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
/**
|
||||
* 某一天的点击事件
|
||||
*/
|
||||
onClick(event) {
|
||||
const { item } = event.currentTarget.dataset;
|
||||
if (item.type !== 'disabled' && item.type !== 'empty') {
|
||||
this.triggerEvent('clickDay', item);
|
||||
}
|
||||
},
|
||||
debounce(fn) {
|
||||
let timer;
|
||||
return () => {
|
||||
let that = this;
|
||||
let args = arguments;
|
||||
if(timer) clearTimeout(timer);
|
||||
timer = setTimeout(function() {
|
||||
fn.apply(that, args);
|
||||
}, 300);
|
||||
};
|
||||
},
|
||||
setDays() {
|
||||
this.debounce(this.setDay)();
|
||||
},
|
||||
/**
|
||||
* 设置某月分的天数
|
||||
*/
|
||||
setDay() {
|
||||
let days = [];
|
||||
const startDate = new Date(this.data.date);
|
||||
const year = startDate.getFullYear();
|
||||
const month = startDate.getMonth();
|
||||
const day = new Date(year, month, 1).getDay();
|
||||
|
||||
const totalDay = getMonthEndDay(year, month + 1);
|
||||
|
||||
for (let day = 1; day <= totalDay; day++) {
|
||||
const date = new Date(year, month, day).getTime();
|
||||
const type = this.getDayType(date);
|
||||
|
||||
|
||||
let config = {
|
||||
date,
|
||||
type,
|
||||
text: day,
|
||||
bottomInfo: this.getBottomInfo(type),
|
||||
topInfo: ''
|
||||
};
|
||||
|
||||
if (this.data.formatter) {
|
||||
config = this.data.formatter(config);
|
||||
}
|
||||
days.push(config);
|
||||
}
|
||||
|
||||
for(let i = 0; i < day; i++) {
|
||||
days.unshift({
|
||||
type: 'empty'
|
||||
});
|
||||
}
|
||||
|
||||
this.setData({
|
||||
days
|
||||
});
|
||||
},
|
||||
|
||||
isDateInCurrent(date) {
|
||||
const { currentDate } = this.data;
|
||||
return currentDate.some(item => {
|
||||
return compareDay(item, date) === 0;
|
||||
});
|
||||
},
|
||||
|
||||
getMultipleDayType(date) {
|
||||
const { currentDate } = this.data;
|
||||
|
||||
if (!Array.isArray(currentDate)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (this.isDateInCurrent(date)) {
|
||||
return 'selected';
|
||||
}
|
||||
|
||||
return '';
|
||||
},
|
||||
|
||||
getRangeDayType(day) {
|
||||
const { currentDate } = this.data;
|
||||
if (!Array.isArray(currentDate)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const [startDay, endDay] = currentDate;
|
||||
|
||||
if (!startDay) {
|
||||
return;
|
||||
}
|
||||
const compareToStart = compareDay(day, startDay);
|
||||
|
||||
if (!endDay) {
|
||||
return compareToStart === 0 ? 'start' : '';
|
||||
}
|
||||
|
||||
const compareToEnd = compareDay(day, endDay);
|
||||
|
||||
if (compareToStart === 0) {
|
||||
return 'start';
|
||||
}
|
||||
|
||||
if (compareToEnd === 0) {
|
||||
return 'end';
|
||||
}
|
||||
|
||||
if (compareToStart > 0 && compareToEnd < 0) {
|
||||
return 'middle';
|
||||
}
|
||||
},
|
||||
|
||||
// date 循环的某一天
|
||||
getDayType(date) {
|
||||
const { type, minDate, maxDate, currentDate } = this.data;
|
||||
|
||||
if (compareDay(date, minDate) < 0 || compareDay(date, maxDate) > 0) {
|
||||
return 'disabled';
|
||||
}
|
||||
|
||||
if (type === config.TYPE_SINGLE) {
|
||||
return compareDay(date, currentDate) === 0 ? 'selected' : '';
|
||||
}
|
||||
|
||||
if (type === config.TYPE_MULTIPLE) {
|
||||
return this.getMultipleDayType(date);
|
||||
}
|
||||
|
||||
if (type === config.TYPE_RANGE) {
|
||||
return this.getRangeDayType(date);
|
||||
}
|
||||
},
|
||||
|
||||
getBottomInfo(type) {
|
||||
if (this.data.type === config.TYPE_RANGE) {
|
||||
if (type === 'start') {
|
||||
return '开始';
|
||||
}
|
||||
if (type === 'end') {
|
||||
return '结束';
|
||||
}
|
||||
return '';
|
||||
}
|
||||
return '';
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"day":"../day/index"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
.calendar-mounth-container{
|
||||
color:#333;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.title{
|
||||
text-align: center;
|
||||
font-weight: 800;
|
||||
}
|
||||
.calendar-day-container{
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
.calendar-day-wrap{
|
||||
width: 14.285%;
|
||||
// height: 110rpx;
|
||||
// padding: 10rpx 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
<wxs src="./index.wxs" module="computed"></wxs>
|
||||
|
||||
<view class="calendar-mounth-container">
|
||||
<view class="title" wx:if="{{ showMonthTitle }}">
|
||||
{{ computed.formatMonthTitle(date) }}
|
||||
</view>
|
||||
<view class="calendar-day-container">
|
||||
<view class="calendar-day-wrap"
|
||||
wx:for="{{ days }}"
|
||||
wx:key="index"
|
||||
>
|
||||
<day
|
||||
bind:tap="onClick"
|
||||
data-item="{{ item }}"
|
||||
wx:if="{{ item.type !== 'empty' }}"
|
||||
text="{{ item.text }}"
|
||||
topInfo="{{ item.topInfo }}"
|
||||
bottomInfo="{{ item.bottomInfo }}"
|
||||
type="{{ item.type }}"
|
||||
color=" {{ color }}"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
/* eslint-disable */
|
||||
|
||||
function formatMonthTitle(date) {
|
||||
date = getDate(date);
|
||||
return date.getFullYear() + '年' + (date.getMonth() + 1) + '月';
|
||||
}
|
||||
|
||||
|
||||
|
||||
module.exports = {
|
||||
formatMonthTitle: formatMonthTitle
|
||||
};
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
export const TYPE_SINGLE = 'single';
|
||||
export const TYPE_RANGE = 'range';
|
||||
export const TYPE_MULTIPLE = 'multiple';
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
const formatFlags = {
|
||||
format: function (format, date) {
|
||||
date = new Date(date);
|
||||
let ret;
|
||||
const opt = {
|
||||
'y+': date.getFullYear().toString(), // 年
|
||||
'M+': (date.getMonth() + 1).toString(), // 月
|
||||
'd+': date.getDate().toString(), // 日
|
||||
};
|
||||
for (let k in opt) {
|
||||
ret = new RegExp('(' + k + ')').exec(format);
|
||||
if (ret) {
|
||||
format = format.replace(ret[1], (ret[1].length === 1) ? opt[k] : this.padZero(opt[k], ret[1].length));
|
||||
}
|
||||
}
|
||||
return format;
|
||||
},
|
||||
|
||||
/**
|
||||
* PC 端微信不支持 padStart,这里写一个补 0 函数
|
||||
* 如果测试已兼容,则可使用原生 padStart
|
||||
* issue #1277
|
||||
*/
|
||||
padZero(str, length) {
|
||||
let res = str;
|
||||
for (let i = 0; i < length - str; i++) {
|
||||
res = '0' + res;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
};
|
||||
|
||||
formatFlags.format('yyyy/MM/dd', new Date());
|
||||
formatFlags.format('yyyy-MM-dd', new Date());
|
||||
formatFlags.format('yyyy-M-dd', new Date());
|
||||
formatFlags.format('yyyy-M-d', new Date());
|
||||
// formatFlags.format('yy-M-dd', new Date())
|
||||
formatFlags.format('M-dd', new Date());
|
||||
formatFlags.format('MM-dd', new Date());
|
||||
|
||||
|
||||
export default formatFlags;
|
||||
|
|
@ -1,346 +0,0 @@
|
|||
import eventBus from '../core/utils/event-bus.js';
|
||||
import validator from '../behaviors/validator';
|
||||
import rules from '../behaviors/rules';
|
||||
import * as config from './config';
|
||||
import formatFlags from './dete';
|
||||
|
||||
import { getDayByOffset, getDate, compareDay, calcDateNum, copyDates, getTime, formatMonthTitle, compareMonth, getMonths } from './util';
|
||||
|
||||
Component({
|
||||
externalClasses: [
|
||||
'l-class'
|
||||
],
|
||||
behaviors: ['wx://form-field', validator, rules],
|
||||
properties: {
|
||||
show: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
observer(val) {
|
||||
if (val) {
|
||||
this.initRect();
|
||||
this.scrollIntoView();
|
||||
}
|
||||
}
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
value: config.TYPE_SINGLE,
|
||||
options: [config.TYPE_SINGLE, config.TYPE_MULTIPLE, config.TYPE_RANGE],
|
||||
observer() {
|
||||
this.setData({ currentDate: this.initCurrentDate() });
|
||||
}
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
value: ''
|
||||
},
|
||||
defaultDate: {
|
||||
optionalTypes: [String, Number, Date, Array],
|
||||
value: '',
|
||||
observer() {
|
||||
this.setData({ currentDate: this.initCurrentDate() });
|
||||
}
|
||||
},
|
||||
format: {
|
||||
type: String,
|
||||
value: 'timestamp'
|
||||
},
|
||||
formatter: {
|
||||
type: Function,
|
||||
optionalTypes: [null],
|
||||
value: null
|
||||
},
|
||||
minDate: {
|
||||
type: String,
|
||||
optionalTypes: [null, Number],
|
||||
value: Date.now()
|
||||
},
|
||||
maxDate: {
|
||||
type: String,
|
||||
optionalTypes: [null, Number],
|
||||
value: new Date(
|
||||
new Date().getFullYear(),
|
||||
new Date().getMonth() + 6,
|
||||
new Date().getDate()
|
||||
).getTime()
|
||||
},
|
||||
minSelect: {
|
||||
type: Number,
|
||||
optionalTypes: [null],
|
||||
value: null
|
||||
},
|
||||
maxSelect: {
|
||||
type: Number,
|
||||
optionalTypes: [null],
|
||||
value: null
|
||||
},
|
||||
allowSameDay: Boolean,
|
||||
showConfirm: {
|
||||
type: Boolean,
|
||||
value: true
|
||||
},
|
||||
confirmText: {
|
||||
type: String,
|
||||
value: '确认'
|
||||
},
|
||||
maxLimitMessage: {
|
||||
type: String
|
||||
},
|
||||
minLimitMessage: {
|
||||
type: String
|
||||
},
|
||||
showTitle: {
|
||||
type: Boolean,
|
||||
value: true
|
||||
},
|
||||
showSubtitle: {
|
||||
type: Boolean,
|
||||
value: true
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
value: '日期选择'
|
||||
}
|
||||
|
||||
},
|
||||
lifetimes: {
|
||||
attached() {
|
||||
this.setData({
|
||||
currentDate: this.initCurrentDate()
|
||||
});
|
||||
},
|
||||
ready() {
|
||||
if (this.data.show) {
|
||||
this.initRect();
|
||||
this.scrollIntoView();
|
||||
}
|
||||
}
|
||||
},
|
||||
data: {
|
||||
currentDate: null,
|
||||
types: config,
|
||||
subTitle: '',
|
||||
scrollIntoViewIndex: ''
|
||||
},
|
||||
methods: {
|
||||
clickDay(event) {
|
||||
const { type, currentDate, maxLimitMessage, maxSelect, allowSameDay } = this.data;
|
||||
const { date } = event.detail;
|
||||
if(type === config.TYPE_SINGLE) {
|
||||
this.setData({
|
||||
currentDate: getTime(date)
|
||||
});
|
||||
this.triggerEvent('linclickday', copyDates(date));
|
||||
this.triggerEvent('linselect', copyDates(date));
|
||||
}
|
||||
if(type === config.TYPE_MULTIPLE) {
|
||||
let _index = null;
|
||||
const isSelected = currentDate.some((item, index) => {
|
||||
const res = compareDay(item, date) === 0;
|
||||
if(res) {
|
||||
_index = index;
|
||||
}
|
||||
return res;
|
||||
});
|
||||
|
||||
if(isSelected) {
|
||||
// 取消选择
|
||||
currentDate.splice(_index, 1);
|
||||
this.setData({
|
||||
currentDate: getTime(currentDate)
|
||||
});
|
||||
this.triggerEvent('linunselect', copyDates(currentDate));
|
||||
} else {
|
||||
if(maxSelect && currentDate.length >= maxSelect) {
|
||||
wx.lin.showToast({
|
||||
title: maxLimitMessage || `选择天数不能超过 ${ maxSelect } 天`
|
||||
});
|
||||
this.triggerEvent('linclickday', copyDates(date));
|
||||
return;
|
||||
}
|
||||
// 添加
|
||||
this.setData({
|
||||
currentDate: getTime([...currentDate, date])
|
||||
});
|
||||
this.triggerEvent('linselect', copyDates([...currentDate, date]));
|
||||
}
|
||||
this.triggerEvent('linclickday', copyDates(date));
|
||||
}
|
||||
|
||||
if(type === config.TYPE_RANGE) {
|
||||
const [startDay, endDay] = currentDate;
|
||||
if (startDay && !endDay) {
|
||||
const compareToStart = compareDay(date, startDay);
|
||||
if (compareToStart === 1) {
|
||||
if(this.checkSelectRange([startDay, date])) {
|
||||
this.setData({
|
||||
currentDate: getTime([startDay, date])
|
||||
});
|
||||
this.triggerEvent('linselect', copyDates([startDay, date]));
|
||||
}
|
||||
}
|
||||
else if (compareToStart === -1) {
|
||||
// 选择结束日期在开始日期之前 重新开始选择
|
||||
this.setData({
|
||||
currentDate: getTime([date, null])
|
||||
});
|
||||
} else if(allowSameDay){
|
||||
this.setData({
|
||||
currentDate: getTime([date, date])
|
||||
});
|
||||
}
|
||||
}
|
||||
else {
|
||||
// 重新开始选择
|
||||
this.setData({
|
||||
currentDate: getTime([date, null])
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
checkSelectRange(date) {
|
||||
const { maxSelect, maxLimitMessage, minSelect, minLimitMessage } = this.data;
|
||||
if (maxSelect && calcDateNum(date) > maxSelect) {
|
||||
|
||||
wx.lin.showToast({
|
||||
title: maxLimitMessage || `选择天数不能超过 ${ maxSelect } 天`
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
if (minSelect && calcDateNum(date) < minSelect) {
|
||||
wx.lin.showToast({
|
||||
title: minLimitMessage || `选择天数不能少于 ${ minSelect } 天`
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
initCurrentDate() {
|
||||
|
||||
const { type, minDate, defaultDate, maxDate } = this.data;
|
||||
const defaultDateIsArr = Array.isArray(defaultDate);
|
||||
|
||||
if (type === config.TYPE_SINGLE) {
|
||||
if(!defaultDate) {
|
||||
return minDate;
|
||||
}
|
||||
if(defaultDateIsArr) {
|
||||
return minDate;
|
||||
}
|
||||
if(compareDay(defaultDate, minDate) === -1) {
|
||||
return minDate;
|
||||
}
|
||||
if(compareDay(defaultDate, maxDate) === 1) {
|
||||
return maxDate;
|
||||
}
|
||||
return defaultDate;
|
||||
}
|
||||
|
||||
if(type === config.TYPE_MULTIPLE) {
|
||||
if(!defaultDate) {
|
||||
return [];
|
||||
}
|
||||
if(defaultDateIsArr) {
|
||||
return defaultDate.filter(item => {
|
||||
return compareDay(item, minDate) === 1 && compareDay(item, maxDate) === -1;
|
||||
});
|
||||
}
|
||||
if(compareDay(defaultDate, minDate) === -1) {
|
||||
return [minDate];
|
||||
}
|
||||
if(compareDay(defaultDate, maxDate) === 1) {
|
||||
return [maxDate];
|
||||
}
|
||||
return [minDate];
|
||||
}
|
||||
|
||||
if(type === config.TYPE_RANGE) {
|
||||
if(defaultDateIsArr) {
|
||||
let [startDay = minDate, endDay] = defaultDate;
|
||||
if(compareDay(startDay, minDate) === -1 || compareDay(startDay, maxDate) !== -1) {
|
||||
startDay = minDate;
|
||||
}
|
||||
if(!endDay) {
|
||||
endDay = getDayByOffset(getDate(startDay), 1).getTime();
|
||||
}
|
||||
if(compareDay(endDay, maxDate) === 1 || compareDay(endDay, minDate) === -1) {
|
||||
endDay = getDayByOffset(getDate(startDay), 1).getTime();
|
||||
}
|
||||
return [
|
||||
startDay,
|
||||
endDay
|
||||
];
|
||||
}
|
||||
return [
|
||||
minDate,
|
||||
getDayByOffset(getDate(minDate), 1).getTime()
|
||||
];
|
||||
}
|
||||
},
|
||||
initRect() {
|
||||
if (!this.contentObserver !== null && this.contentObserver !== undefined) {
|
||||
this.contentObserver.disconnect();
|
||||
}
|
||||
const contentObserver = this.createIntersectionObserver({
|
||||
thresholds: [0, 0.1, 0.9, 1],
|
||||
observeAll: true
|
||||
});
|
||||
this.contentObserver = contentObserver;
|
||||
contentObserver.relativeTo('.calendar-body-wrap');
|
||||
contentObserver.observe('.month', res => {
|
||||
if (res.boundingClientRect.top <= res.relativeRect.top) {
|
||||
// @ts-ignore
|
||||
this.setData({ subTitle: formatMonthTitle(res.dataset.date) });
|
||||
}
|
||||
});
|
||||
},
|
||||
scrollIntoView() {
|
||||
setTimeout(() => {
|
||||
const { currentDate, type, show, minDate, maxDate } = this.data;
|
||||
const targetDate = type === 'single' ? currentDate : currentDate[0];
|
||||
const displayed = show;
|
||||
if (!targetDate || !displayed) {
|
||||
return;
|
||||
}
|
||||
const months = getMonths(minDate, maxDate);
|
||||
months.some((month, index) => {
|
||||
if (compareMonth(month, targetDate) === 0) {
|
||||
this.setData({ scrollIntoViewIndex: `month${index}` });
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}, 100);
|
||||
},
|
||||
closePicker() {
|
||||
this.setData({
|
||||
show: false
|
||||
});
|
||||
},
|
||||
onClickConfirm() {
|
||||
const {format, type, currentDate} = this.data;
|
||||
eventBus.emit(`lin-form-blur-${this.id}`, this.id);
|
||||
let value = null;
|
||||
if(type === 'single') {
|
||||
value = format !== 'timestamp' ? formatFlags.format('yyyy-MM-dd', currentDate) : currentDate;
|
||||
} else {
|
||||
value = currentDate.map(item => {
|
||||
return format !== 'timestamp' ? formatFlags.format('yyyy-MM-dd', item) : item;
|
||||
});
|
||||
}
|
||||
this.triggerEvent('linconfirm', value);
|
||||
},
|
||||
getValues() {
|
||||
return this.data.currentDate;
|
||||
},
|
||||
reset() {
|
||||
this.setData({
|
||||
currentDate: null
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"header":"./components/header/index",
|
||||
"mounth":"./components/mounth/index",
|
||||
"l-toast": "../toast/index",
|
||||
"l-popup": "../popup/index",
|
||||
"l-button": "../button/index"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
@import "../styles/_theme.less";
|
||||
@import "../styles/_mixins.less";
|
||||
|
||||
.calendar-container{
|
||||
display: flex;
|
||||
height: 1000rpx;
|
||||
flex-direction: column;
|
||||
background-color: #ffffff;
|
||||
.calendar-body-wrap{
|
||||
flex: 1;
|
||||
overflow: auto;
|
||||
padding: 0 20rpx;
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
|
||||
// .bottom {
|
||||
// width: 100%;
|
||||
// background: #fff;
|
||||
// height: 300rpx;
|
||||
// overflow: hidden;
|
||||
// text-align: center;
|
||||
// line-height: 300rpx;
|
||||
// font-size: 28rpx;
|
||||
// color: #555;
|
||||
// border-top-left-radius: 12rpx;
|
||||
// border-top-right-radius: 12rpx;
|
||||
// }
|
||||
|
||||
.bottom-button {
|
||||
padding: 0 !important;
|
||||
.safe-area-inset-bottom();
|
||||
box-sizing: content-box !important;
|
||||
}
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
<import src="./calendar.wxml" />
|
||||
|
||||
<l-popup content-align="bottom" show="{{ show }}" bind:lintap="closePicker">
|
||||
<template
|
||||
is="calendar"
|
||||
data="{{ currentDate, type, color, defaultDate, format, formatter, minDate, maxDate, minSelect, maxSelect, showConfirm, confirmText, maxLimitMessage, minLimitMessage, showTitle, showSubtitle, title, subTitle, scrollIntoViewIndex, color }}"
|
||||
/>
|
||||
</l-popup>
|
||||
|
||||
<l-toast></l-toast>
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
/* eslint-disable */
|
||||
var utils = require('./utils.wxs');
|
||||
|
||||
function getMonths(minDate, maxDate) {
|
||||
var months = [];
|
||||
var cursor = getDate(minDate);
|
||||
|
||||
cursor.setDate(1);
|
||||
|
||||
do {
|
||||
months.push(cursor.getTime());
|
||||
cursor.setMonth(cursor.getMonth() + 1);
|
||||
} while (utils.compareMonth(cursor, getDate(maxDate)) !== 1);
|
||||
|
||||
return months;
|
||||
}
|
||||
|
||||
function getButtonDisabled(type, currentDate) {
|
||||
if (currentDate == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (type === 'range') {
|
||||
return !currentDate[0] || !currentDate[1];
|
||||
}
|
||||
|
||||
if (type === 'multiple') {
|
||||
return !currentDate.length;
|
||||
}
|
||||
|
||||
return !currentDate;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getMonths: getMonths,
|
||||
getButtonDisabled: getButtonDisabled
|
||||
};
|
||||
|
|
@ -1,113 +0,0 @@
|
|||
export function getMonthEndDay(year, month) {
|
||||
return new Date(year, month, 0).getDate();
|
||||
}
|
||||
|
||||
export function isTimeTemp(data) {
|
||||
var reg = /^\d+(\.\d+)?$/;
|
||||
return reg.test(data);
|
||||
}
|
||||
|
||||
export function getDate(str) {
|
||||
if (isTimeTemp(str)) {
|
||||
str = parseInt(str);
|
||||
}
|
||||
str = new Date(str);
|
||||
return str;
|
||||
}
|
||||
|
||||
export function getDayByOffset(date, number) {
|
||||
date = new Date(date);
|
||||
date.setDate(date.getDate() + number);
|
||||
return date;
|
||||
}
|
||||
|
||||
export function compareMonth(date1, date2) {
|
||||
if (!(date1 instanceof Date)) {
|
||||
date1 = getDate(date1);
|
||||
}
|
||||
|
||||
if (!(date2 instanceof Date)) {
|
||||
date2 = getDate(date2);
|
||||
}
|
||||
|
||||
const year1 = date1.getFullYear();
|
||||
const year2 = date2.getFullYear();
|
||||
const month1 = date1.getMonth();
|
||||
const month2 = date2.getMonth();
|
||||
|
||||
if (year1 === year2) {
|
||||
return month1 === month2 ? 0 : month1 > month2 ? 1 : -1;
|
||||
}
|
||||
|
||||
return year1 > year2 ? 1 : -1;
|
||||
}
|
||||
|
||||
export function compareDay(date1, date2) {
|
||||
if (!(date1 instanceof Date)) {
|
||||
date1 = getDate(date1);
|
||||
}
|
||||
|
||||
if (!(date2 instanceof Date)) {
|
||||
date2 = getDate(date2);
|
||||
}
|
||||
|
||||
const compareMonthResult = compareMonth(date1, date2);
|
||||
|
||||
if (compareMonthResult === 0) {
|
||||
const _date1 = date1.getDate();
|
||||
const _date2 = date2.getDate();
|
||||
|
||||
return _date1 === _date2 ? 0 : _date1 > _date2 ? 1 : -1;
|
||||
}
|
||||
|
||||
return compareMonthResult;
|
||||
}
|
||||
|
||||
export function calcDateNum(date) {
|
||||
const day1 = new Date(date[0]).getTime();
|
||||
const day2 = new Date(date[1]).getTime();
|
||||
return (day2 - day1) / (1000 * 60 * 60 * 24) + 1;
|
||||
}
|
||||
|
||||
export function copyDates(dates) {
|
||||
if (Array.isArray(dates)) {
|
||||
return dates.map(date => {
|
||||
if (date === null) {
|
||||
return date;
|
||||
}
|
||||
return new Date(date);
|
||||
});
|
||||
}
|
||||
return new Date(dates);
|
||||
}
|
||||
|
||||
export function getTime (dates) {
|
||||
if (Array.isArray(dates)) {
|
||||
return dates.map(date => {
|
||||
if (date instanceof Date) {
|
||||
return date.getTime();
|
||||
}
|
||||
return date;
|
||||
});
|
||||
}
|
||||
return (dates instanceof Date ? dates.getTime() : dates);
|
||||
}
|
||||
|
||||
export function formatMonthTitle(date) {
|
||||
if (!(date instanceof Date)) {
|
||||
date = new Date(date);
|
||||
}
|
||||
return `${date.getFullYear()}年${date.getMonth() + 1}月`;
|
||||
}
|
||||
|
||||
export function getMonths(minDate, maxDate) {
|
||||
const months = [];
|
||||
const cursor = new Date(minDate);
|
||||
cursor.setDate(1);
|
||||
do {
|
||||
months.push(cursor.getTime());
|
||||
cursor.setMonth(cursor.getMonth() + 1);
|
||||
} while (compareMonth(cursor, maxDate) !== 1);
|
||||
return months;
|
||||
}
|
||||
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
/* eslint-disable */
|
||||
function getMonthEndDay(year, month) {
|
||||
return getDate(year, month - 1, 0).getDate();
|
||||
}
|
||||
function compareMonth(date1, date2) {
|
||||
date1 = getDate(date1);
|
||||
date2 = getDate(date2);
|
||||
|
||||
var year1 = date1.getFullYear();
|
||||
var year2 = date2.getFullYear();
|
||||
var month1 = date1.getMonth();
|
||||
var month2 = date2.getMonth();
|
||||
|
||||
if (year1 === year2) {
|
||||
return month1 === month2 ? 0 : month1 > month2 ? 1 : -1;
|
||||
}
|
||||
|
||||
return year1 > year2 ? 1 : -1;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getMonthEndDay: getMonthEndDay,
|
||||
compareMonth: compareMonth
|
||||
};
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 550 B |
Binary file not shown.
|
Before Width: | Height: | Size: 552 B |
Binary file not shown.
|
Before Width: | Height: | Size: 591 B |
Binary file not shown.
|
Before Width: | Height: | Size: 600 B |
|
|
@ -1,179 +0,0 @@
|
|||
import deviceUtil from '../utils/device-util';
|
||||
import validator from '../behaviors/validator';
|
||||
import eventUtil from '../core/utils/event-util';
|
||||
|
||||
Component({
|
||||
options: {
|
||||
multipleSlots: true
|
||||
},
|
||||
behaviors: [validator],
|
||||
externalClasses: ['l-title-class'],
|
||||
properties: {
|
||||
// 胶囊栏颜色
|
||||
bgColor: {
|
||||
type: String,
|
||||
value: 'white'
|
||||
},
|
||||
// 状态栏颜色
|
||||
statusBarColor: {
|
||||
type: String,
|
||||
value: 'transparent'
|
||||
},
|
||||
// 标题栏颜色
|
||||
titleBarColor: {
|
||||
type: String,
|
||||
value: 'transparent'
|
||||
},
|
||||
// 标题颜色
|
||||
titleColor: {
|
||||
type: String,
|
||||
value: 'black'
|
||||
},
|
||||
// 胶囊按钮颜色
|
||||
capsuleColor: {
|
||||
type: String,
|
||||
value: 'black',
|
||||
options: ['white', 'black']
|
||||
},
|
||||
// 禁用左侧按钮返回上一页
|
||||
disableBack: {
|
||||
type: Boolean,
|
||||
value: false
|
||||
},
|
||||
// 禁用右侧按钮返回主页
|
||||
disableHome: {
|
||||
type: Boolean,
|
||||
value: false
|
||||
},
|
||||
// 隐藏胶囊按钮
|
||||
hiddenCapsule: {
|
||||
type: Boolean,
|
||||
value: false
|
||||
},
|
||||
// 主页路径
|
||||
homePage: {
|
||||
type: String,
|
||||
value: ''
|
||||
},
|
||||
// 页面标题
|
||||
title: {
|
||||
type: String,
|
||||
value: ''
|
||||
},
|
||||
// 顶部填充
|
||||
hasPadding: {
|
||||
type: Boolean,
|
||||
value: true
|
||||
},
|
||||
// 隐藏标题
|
||||
hiddenTitle: {
|
||||
type: Boolean,
|
||||
value: false
|
||||
},
|
||||
// 左侧胶囊按钮左侧图标路径
|
||||
capsuleLeftIconPath: {
|
||||
type: String,
|
||||
value: null
|
||||
},
|
||||
// 左侧胶囊按钮左侧图标宽度,单位:rpx
|
||||
capsuleLeftIconWidth: {
|
||||
type: Number,
|
||||
value: null
|
||||
},
|
||||
// 左侧胶囊按钮左侧图标高度,单位:rpx
|
||||
capsuleLeftIconHeight: {
|
||||
type: Number,
|
||||
value: null
|
||||
},
|
||||
// 左侧胶囊按钮右侧图标路径
|
||||
capsuleRightIconPath: {
|
||||
type: String,
|
||||
value: null
|
||||
},
|
||||
// 左侧胶囊按钮右侧图标宽度,单位:rpx
|
||||
capsuleRightIconWidth: {
|
||||
type: Number,
|
||||
value: null
|
||||
},
|
||||
// 左侧胶囊按钮右侧图标高度,单位:rpx
|
||||
capsuleRightIconHeight: {
|
||||
type: Number,
|
||||
value: null
|
||||
}
|
||||
},
|
||||
|
||||
data: {
|
||||
// 标题栏高度(单位px)
|
||||
titleBarHeight: deviceUtil.getTitleBarHeight(),
|
||||
// 状态栏高度(单位px)
|
||||
statusBarHeight: deviceUtil.getStatusBarHeight(),
|
||||
// 左侧胶囊按钮信息
|
||||
capsuleButtonInfo: null
|
||||
},
|
||||
|
||||
lifetimes: {
|
||||
ready: function () {
|
||||
this.setData({
|
||||
capsuleButtonInfo: this.getCapsuleButtonInfo()
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
||||
/**
|
||||
* 获取左侧胶囊按钮信息
|
||||
*/
|
||||
getCapsuleButtonInfo() {
|
||||
const screenWidth = wx.getSystemInfoSync().screenWidth;
|
||||
const capsuleButtonInfo = wx.getMenuButtonBoundingClientRect();
|
||||
capsuleButtonInfo.left = screenWidth - capsuleButtonInfo.right;
|
||||
capsuleButtonInfo.right = capsuleButtonInfo.left + capsuleButtonInfo.width;
|
||||
return capsuleButtonInfo;
|
||||
},
|
||||
|
||||
/**
|
||||
* 监听:点击左侧按钮
|
||||
*/
|
||||
onTapLeftButton() {
|
||||
eventUtil.emit(this, 'linlefttap');
|
||||
|
||||
if (!this.data.disableBack) {
|
||||
wx.navigateBack();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 监听:长按左侧按钮
|
||||
*/
|
||||
onLongPressLeftButton() {
|
||||
eventUtil.emit(this, 'linleftlongpress');
|
||||
},
|
||||
|
||||
/**
|
||||
* 监听:点击右侧按钮
|
||||
*/
|
||||
async onTapRightButton() {
|
||||
eventUtil.emit(this, 'linrighttap');
|
||||
|
||||
const homePage = this.data.homePage;
|
||||
if (!this.data.disableHome) {
|
||||
wx.switchTab({
|
||||
url: homePage,
|
||||
fail() {
|
||||
wx.navigateTo({
|
||||
url: homePage
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 监听:长按右侧按钮
|
||||
*/
|
||||
onLongPressRightButton() {
|
||||
eventUtil.emit(this, 'linrightlongpress');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
{
|
||||
"component": true
|
||||
}
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
.container{
|
||||
position: relative;
|
||||
.capsule-bar{
|
||||
width: 100%;
|
||||
position: fixed;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 999;
|
||||
|
||||
.status-bar{
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.title-bar{
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-top: -4rpx;
|
||||
padding-top: 4rpx;
|
||||
box-sizing: border-box;
|
||||
|
||||
.title{
|
||||
font-size: 36rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
.capsule-button{
|
||||
border-radius: 99999px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border: 1px solid rgba(0,0,0,0.1);
|
||||
position: fixed;
|
||||
|
||||
.icon-wrapper-hover-black{
|
||||
background-color: rgba(0,0,0,0.36);
|
||||
}
|
||||
|
||||
.icon-wrapper-hover-white{
|
||||
background-color: rgba(255,255,255,0.339);
|
||||
}
|
||||
|
||||
.icon-wrapper{
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
.icon-left{
|
||||
display: block;
|
||||
width: 20rpx;
|
||||
height: 34rpx;
|
||||
}
|
||||
.icon-right{
|
||||
display: block;
|
||||
width: 38rpx;
|
||||
height: 34rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.line{
|
||||
height: 18px;
|
||||
width: 1px;
|
||||
line-height: 1;
|
||||
background-color: rgba(255,255,255,0.25);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.content-container{
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
<!--为什么没有设置一个cover-image用来承载背景图?因为CapsuleBar在不同机型上大小是动态变化的-->
|
||||
<!--cover-image又不能设置填充方式,所以将此部分开放给用户处理是最佳的选择-->
|
||||
<view class="container" style="padding-top: {{hasPadding?titleBarHeight+statusBarHeight:'0'}}rpx">
|
||||
<!--胶囊栏-->
|
||||
<cover-view class="capsule-bar" style="background-color: {{bgColor}};">
|
||||
<!--状态栏-->
|
||||
<!--这里加4是因为不加4的时候statusBar和titleBar之间容易出现一条白线,所以加上4让两部分重叠,消除白线-->
|
||||
<cover-view
|
||||
class="status-bar"
|
||||
style="height: {{statusBarHeight+4}}rpx;background-color: {{statusBarColor}};"
|
||||
></cover-view>
|
||||
|
||||
<!--标题栏-->
|
||||
<cover-view
|
||||
class="title-bar"
|
||||
style="height: {{titleBarHeight}}rpx;background-color: {{titleBarColor}};"
|
||||
>
|
||||
<cover-view wx:if="{{!hiddenTitle}}" class="title l-title-class" style="color: {{titleColor}};">{{title}}</cover-view>
|
||||
<slot name="title"/>
|
||||
</cover-view>
|
||||
|
||||
<!--胶囊按钮-->
|
||||
<cover-view
|
||||
wx:if="{{!hiddenCapsule}}"
|
||||
class="capsule-button"
|
||||
style="border-color: rgba({{capsuleColor==='black'?'0,0,0,0.1':'255,255,255,0.25'}});background-color: rgba({{capsuleColor==='black'?'255,255,255,0.6':'0,0,0,0.15'}});width: {{capsuleButtonInfo.width}}px;height: {{capsuleButtonInfo.height}}px;left: {{capsuleButtonInfo.left}}px;top: {{capsuleButtonInfo.top}}px;"
|
||||
>
|
||||
<!--左侧按钮-->
|
||||
<cover-view mut-bind:tap="onTapLeftButton"
|
||||
catch:longpress="onLongPressLeftButton"
|
||||
hover-class="icon-wrapper-hover-{{capsuleColor}}"
|
||||
class="icon-wrapper"
|
||||
style="width: {{capsuleButtonInfo.width/2}}px;height: {{capsuleButtonInfo.height}}px;">
|
||||
<cover-image
|
||||
class="icon-left"
|
||||
style="width:{{capsuleLeftIconWidth?capsuleLeftIconWidth+'rpx':''}};height:{{capsuleLeftIconHeight?capsuleLeftIconHeight+'rpx':''}};"
|
||||
src="{{capsuleLeftIconPath?capsuleLeftIconPath:'icons/capsule-left-'+capsuleColor+'.png'}}"></cover-image>
|
||||
</cover-view>
|
||||
|
||||
<!--分割线-->
|
||||
<cover-view class="line"></cover-view>
|
||||
|
||||
<!--右侧按钮-->
|
||||
<cover-view mut-bind:tap="onTapRightButton"
|
||||
catch:longpress="onLongPressRightButton"
|
||||
hover-class="icon-wrapper-hover-{{capsuleColor}}"
|
||||
class="icon-wrapper"
|
||||
style="width: {{capsuleButtonInfo.width/2}}px;height: {{capsuleButtonInfo.height}}px;">
|
||||
<cover-image
|
||||
class="icon-right"
|
||||
style="width:{{capsuleRightIconWidth?capsuleRightIconWidth+'rpx':''}};height:{{capsuleRightIconHeight?capsuleRightIconHeight+'rpx':''}}"
|
||||
src="{{capsuleRightIconPath?capsuleRightIconPath:'icons/capsule-right-'+capsuleColor+'.png'}}"></cover-image>
|
||||
</cover-view>
|
||||
</cover-view>
|
||||
</cover-view>
|
||||
|
||||
<view class="content-container">
|
||||
<slot></slot>
|
||||
</view>
|
||||
</view>
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
import validator from '../behaviors/validator';
|
||||
|
||||
Component({
|
||||
/**
|
||||
* 组件的属性列表
|
||||
*/
|
||||
externalClasses: ['l-class', 'l-img-class', 'l-title-class'],
|
||||
options: {
|
||||
multipleSlots: true // 在组件定义时的选项中启用多slot支持
|
||||
},
|
||||
behaviors: [validator],
|
||||
properties: {
|
||||
image: String,
|
||||
title: String,
|
||||
describe: String,
|
||||
plaintext: Boolean,
|
||||
full: Boolean,
|
||||
position: {
|
||||
type: String,
|
||||
value: 'left',
|
||||
options: ['left', 'right']
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
value: 'primary',
|
||||
options: ['primary', 'avatar','cover']
|
||||
},
|
||||
imageMode: {
|
||||
type: String,
|
||||
value: 'scaleToFill'
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 组件的初始数据
|
||||
*/
|
||||
data: {
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 组件的方法列表
|
||||
*/
|
||||
methods: {
|
||||
|
||||
}
|
||||
});
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
{
|
||||
"component": true,
|
||||
"usingComponents": {}
|
||||
}
|
||||
|
|
@ -1,132 +0,0 @@
|
|||
.card-container {
|
||||
margin: 0 auto;
|
||||
padding: 30rpx;
|
||||
box-sizing: border-box;
|
||||
background: #fff;
|
||||
display: flex;
|
||||
|
||||
&-full{
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&-unfull{
|
||||
width: 92%;
|
||||
box-shadow: 0 4rpx 20rpx 0 rgba(212, 217, 223, 0.5);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
&-primary-left {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
&-primary-right {
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
|
||||
&-avatar {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
&-cover {
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
|
||||
.cover-img{
|
||||
&-full{
|
||||
width: 100%;
|
||||
height: 260rpx;
|
||||
}
|
||||
|
||||
&-unfull{
|
||||
width: 100%;
|
||||
height: 260rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.card-img {
|
||||
&-primary{
|
||||
height: 240rpx;
|
||||
width: 240rpx;
|
||||
overflow: hidden;
|
||||
|
||||
&-left{
|
||||
margin-right: 40rpx;
|
||||
}
|
||||
|
||||
&-right{
|
||||
margin-left: 40rpx;
|
||||
}
|
||||
}
|
||||
|
||||
&-avatar{
|
||||
height: 60rpx;
|
||||
width: 60rpx;
|
||||
border-radius: 50%;
|
||||
margin-right: 30rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.card-img-avatar {
|
||||
height: 60rpx;
|
||||
width: 60rpx;
|
||||
border-radius: 50%;
|
||||
margin-right: 30rpx;
|
||||
}
|
||||
|
||||
.card-content {
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.card-title {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
color: #333;
|
||||
|
||||
&-primary{
|
||||
font-size: 32rpx;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
}
|
||||
|
||||
&-avatar{
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
&-cover{
|
||||
font-size: 30rpx;
|
||||
margin-top: 10rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.card-title-avatar {
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.card-avatar-top {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
height: 100rpx;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.card-avatar-left {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.card-avatar{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.describe {
|
||||
color: #666;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
<view class="l-class card-container {{'card-container-' + type}} {{'card-container-' + type + '-' + position}} {{full?'card-container-full':'card-container-unfull'}}">
|
||||
<block wx:if="{{type ==='primary' || type ==='cover'}}">
|
||||
<image wx:if="{{!plaintext}}" class="l-img-class {{full?'cover-img-full':'cover-img-unfull'}} {{ 'card-img-' + type }} {{ 'card-img-' + type + '-' + position }}" mode="{{imageMode}}" lazy-load src="{{image}}"></image>
|
||||
<view class="card-content">
|
||||
<text class="l-title-class card-title {{'card-title-' + type}}">{{title}}</text>
|
||||
<slot />
|
||||
</view>
|
||||
</block>
|
||||
<block wx:if="{{type ==='avatar'}}">
|
||||
<view class="card-avatar-top">
|
||||
<view class="card-avatar-left">
|
||||
<image mode="aspectFill" class="l-img-class {{ 'card-img-' + type }}" src="{{image}}" mode="{{imageMode}}" lazy-load></image>
|
||||
<view class="card-avatar">
|
||||
<text class="l-title-class card-title {{'card-title-' + type}}">{{title}}</text>
|
||||
<text class="describe">{{describe}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<slot name="more" />
|
||||
</view>
|
||||
<slot />
|
||||
</block>
|
||||
</view>
|
||||
|
|
@ -1,120 +0,0 @@
|
|||
import eventBus from '../core/utils/event-bus';
|
||||
import rules from '../behaviors/rules';
|
||||
|
||||
|
||||
Component({
|
||||
behaviors: ['wx://form-field',rules],
|
||||
externalClasses: ['l-class', 'l-error-text', 'l-error-text-class'],
|
||||
relations: {
|
||||
'../checkbox/index': {
|
||||
type: 'child',
|
||||
linked(target) {
|
||||
this.init(target);
|
||||
},
|
||||
linkChanged() {
|
||||
},
|
||||
unlinked() {
|
||||
// this.init(target);
|
||||
}
|
||||
}
|
||||
},
|
||||
properties: {
|
||||
// 选项的排列方式 一行显示 or 多行显示
|
||||
placement: {
|
||||
type: String,
|
||||
value: 'column', //column row
|
||||
},
|
||||
// 最多选中值
|
||||
maxSelected: {
|
||||
type: Number,
|
||||
value: null
|
||||
},
|
||||
minSelected: {
|
||||
type: Number,
|
||||
value: null
|
||||
},
|
||||
},
|
||||
data: {
|
||||
},
|
||||
attached() {
|
||||
let { minSelected, maxSelected} = this.properties;
|
||||
this.checkMax(minSelected, maxSelected);
|
||||
},
|
||||
methods: {
|
||||
|
||||
init(target) {
|
||||
if(this._keys === undefined) this._keys = {};
|
||||
if(this._selected === undefined) this._selected = {};
|
||||
this.checkDefaultItem(target);
|
||||
this.checkedKeyRepeat(target);
|
||||
},
|
||||
|
||||
checkedKeyRepeat(target) {
|
||||
let { key } = target.properties;
|
||||
if(this._keys[key]) {
|
||||
throw new Error(`keys有重复元素, checkbox的key属性不能重复:${key}`);
|
||||
} else {
|
||||
this._keys[key] = true;
|
||||
}
|
||||
},
|
||||
|
||||
checkDefaultItem(target) {
|
||||
const { key, checked, cell } = target.properties;
|
||||
if(checked) {
|
||||
this._selected[key] = {...cell,checked:true, value: key};
|
||||
}
|
||||
},
|
||||
|
||||
checkMax(min, max) {
|
||||
if(min !== null && min < 0) {
|
||||
throw new Error('最小选择个数必须大于等于0');
|
||||
}
|
||||
if(max !== null && max < 0) {
|
||||
throw new Error('最多选择个数必须大于0');
|
||||
}
|
||||
if(max !== null && min !== null && min >= max) {
|
||||
throw new Error('最多选择个数必须大于最小选择个数');
|
||||
}
|
||||
},
|
||||
|
||||
onEmitEventHandle(currentItem) {
|
||||
currentItem.checked ? this.addSelect (currentItem):this.removeSelect(currentItem.key);
|
||||
|
||||
this.validatorData({
|
||||
[this.data.name]: Object.values(this._selected)
|
||||
});
|
||||
|
||||
this.triggerEvent('linchange', currentItem, {
|
||||
bubbles: true,
|
||||
composed: true
|
||||
});
|
||||
eventBus.emit(`lin-form-change-${this.id}`,this.id);
|
||||
},
|
||||
onEmitOverflowHandle(data){
|
||||
this.triggerEvent('linout', data, {
|
||||
bubbles: true,
|
||||
composed: true
|
||||
});
|
||||
},
|
||||
removeSelect(key) {
|
||||
delete this._selected[key];
|
||||
},
|
||||
addSelect(currentItem) {
|
||||
let {key, ...obj} = currentItem;
|
||||
this._selected[key] = {...obj, value: key};
|
||||
},
|
||||
getValues() {
|
||||
return Object.values(this._selected);
|
||||
},
|
||||
reset() {
|
||||
this._selected = {};
|
||||
const list = this.getRelationNodes('../checkbox/index');
|
||||
return list.forEach(item => {
|
||||
return item.setData({
|
||||
checked: false
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"l-error-tip":"../error-tip/index",
|
||||
"l-checkbox": "../checkbox/index"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
|
||||
.checkbox-group{
|
||||
flex-wrap: wrap;
|
||||
&-row{
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
&-column{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
// .checkbox-group-button{
|
||||
// display: flex;
|
||||
// flex-direction: row !important;
|
||||
// flex-wrap: wrap;
|
||||
// }
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
<view class="l-class checkbox-group checkbox-group-{{placement}} ">
|
||||
<slot></slot>
|
||||
</view>
|
||||
<l-error-tip l-error-text-class="l-error-text l-error-text-class" errorText="{{errorText}}" wx:if="{{errorText}}"/>
|
||||
|
|
@ -1,114 +0,0 @@
|
|||
Component({
|
||||
behaviors: ['wx://form-field'],
|
||||
externalClasses: ['l-class', 'l-disabled-class', 'l-icon-class'],
|
||||
relations: {
|
||||
'../checkbox-group/index': {
|
||||
type: 'parent'
|
||||
}
|
||||
},
|
||||
options: {
|
||||
multipleSlots: true
|
||||
},
|
||||
properties: {
|
||||
// checkbox 按钮的位置
|
||||
placement: {
|
||||
type: String,
|
||||
value: 'left'
|
||||
},
|
||||
// 是否自定义图标内容
|
||||
custom: {
|
||||
type: Boolean,
|
||||
value: false
|
||||
},
|
||||
key: {
|
||||
type: String,
|
||||
value: ''
|
||||
},
|
||||
cell: {
|
||||
type: Object,
|
||||
value: {}
|
||||
},
|
||||
// checkbox的大小
|
||||
size: {
|
||||
type: String,
|
||||
value: '38rpx'
|
||||
},
|
||||
// 不可选状态
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
value: false
|
||||
},
|
||||
// 选中后的颜色
|
||||
selectColor: {
|
||||
type: String,
|
||||
value: '#3963BC'
|
||||
},
|
||||
disabledColor: {
|
||||
type: String,
|
||||
value: '#ccc'
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
value: '#ccc'
|
||||
},
|
||||
checked: {
|
||||
type: Boolean,
|
||||
value: false
|
||||
}
|
||||
},
|
||||
data: {
|
||||
parentPlacement: ''
|
||||
},
|
||||
ready() {
|
||||
const parent = this.getRelationNodes('../checkbox-group/index')[0];
|
||||
let {placement: parentPlacement} = parent.properties;
|
||||
this.setData({parentPlacement});
|
||||
},
|
||||
methods: {
|
||||
// 点击checkbox
|
||||
onCheckboxChangeTap() {
|
||||
if (this.properties.disabled || this.data.parentDisabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
const parent = this.getRelationNodes('../checkbox-group/index')[0];
|
||||
|
||||
if (this.properties.checked) {
|
||||
if (this.isOverflow('minSelected')) return;
|
||||
} else {
|
||||
if (this.isOverflow('maxSelected')) return;
|
||||
}
|
||||
|
||||
const item = {
|
||||
checked: !this.properties.checked,
|
||||
key: this.properties.key,
|
||||
cell: this.properties.cell
|
||||
};
|
||||
if (parent) {
|
||||
parent.onEmitEventHandle(item);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {*} type (max/min)
|
||||
*/
|
||||
isOverflow(type) {
|
||||
const parent = this.getRelationNodes('../checkbox-group/index')[0];
|
||||
|
||||
const limit = parent.properties[type];
|
||||
if (!limit) return false;
|
||||
const selectedLength = Object.values(parent._selected).length;
|
||||
let isOverflow = type === 'minSelected' ? selectedLength <= limit : selectedLength >= limit;
|
||||
if (isOverflow) {
|
||||
let backType = type === 'minSelected' ? 'min_selected' : 'max_selected';
|
||||
parent.onEmitOverflowHandle && parent.onEmitOverflowHandle({
|
||||
key: this.properties.key,
|
||||
limitNumber: limit,
|
||||
type: `overflow_${backType}`
|
||||
});
|
||||
}
|
||||
return isOverflow;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"l-button": "../button/index"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
@import "../styles/_theme.less";
|
||||
|
||||
.label{
|
||||
display : flex;
|
||||
flex : 1;
|
||||
align-items : center;
|
||||
font-size : 30rpx;
|
||||
color : #333333;
|
||||
width : 100%;
|
||||
box-sizing : border-box;
|
||||
|
||||
&-left{
|
||||
flex-direction : row;
|
||||
}
|
||||
|
||||
&-right{
|
||||
flex-direction : row-reverse;
|
||||
justify-content : space-between;
|
||||
}
|
||||
|
||||
&-disabled{
|
||||
color : #CCCCCC;
|
||||
}
|
||||
|
||||
&-placement-row{
|
||||
padding-right : 30rpx;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.checkbox-left{
|
||||
margin-right : 20rpx;
|
||||
}
|
||||
|
||||
.checkbox-right{
|
||||
margin-left : 20rpx;
|
||||
}
|
||||
|
||||
.iconfont{
|
||||
font-family : "iconfont" !important;
|
||||
display : inline-flex;
|
||||
font-style : normal;
|
||||
-webkit-font-smoothing : antialiased;
|
||||
-moz-osx-font-smoothing : grayscale;
|
||||
}
|
||||
|
||||
@font-face{
|
||||
font-family : "iconfont";
|
||||
src : url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAAMMAAsAAAAABxgAAAK9AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCDBgqBeIFdATYCJAMMCwgABCAFhG0HQBstBlGUzMkA2c8E020e0uBCKA1ReoTOr2jhX60Fez8evvb7nbu7X40GSTTS8S6aRBOpkCB1plMyIWkJb/+nLTemUXn+tjy1proDbGd+u9OXhuW20ygDQoJwOPhjfw50kxP0dlsW4tKSEtLyKhWqIpT/3MKy5KTZgMvpr8TnWZbTWts2jgmYYEBjDHuKrEQCzjUF2R2BWvJ9Am0LeioHm9MVtBXOskC8RIED7VJMUaRiU6i37C3iHV4zvaZPKG/x5+OfLdoktcxZe/S89mH27bv8VD0phAT5ch5Ih8jYBApx3eq7Uktzm2rahqZu1oO6IqSlklVFLDMN9YP+8RJR55R2wSrNJ775IoLvWEgggzoKDoFYipp4U38JhsVnsZqMDSLDTR9O5v6lxM+emWKnJ0j1WkJfv81PpvtdvqfbrTPuXw1+/Yswbx81bvFu4GNdLq7/WnYQrkR7OT7DTrwSHIOw0QhHGI+BEQb/TCiV/n/7MQFAQ9mO3iwSi9Gz9MCEpIu0tWgZiFkilLN8tRFgA1SnfMgz8o0Kgo9Q+Gcx3f/tTgFfe45JtDoVFO7QvAt/8FflYE8xlY49F13my+xAtjTRk6ASOahCOaGxn+mGGVxKaJrlSBrmkTUtkoWziZqOLdQ1baNtw/Zwx4SoidLCuneCMPSBpO8T2dAXWTjfqJnzi7ph1NB2EdwzO5Yj6oaEHCUf3UeMPM6N59RuUn6m4DZ1pKiMuTckZZTE8WBULW4pJ1liQ3kXTFQNGuEMN+QxSlPGQjgmTwehajEdDk3biwYeZ9C1TxCHIj7keoQiHpYz4XDVrb3/jARupRzS09AQv0FEKRodjQ2MAHKry6GGR2FTuhOYUMpAhmAZtCEekro5hor2WTHiUQPhhExhasgGGVQ32N6Q/UCp1ILzXI4UOYrOQ0he4vKDxXk7twIAAAAA') format('woff2'),
|
||||
}
|
||||
|
||||
.icon-unselect:before{
|
||||
content : "\e727";
|
||||
}
|
||||
|
||||
.icon-select:before{
|
||||
content : "\e725";
|
||||
}
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
<view mut-bind:lintap="onCheckboxChangeTap" mut-bind:tap="onCheckboxChangeTap"
|
||||
class="label label-{{placement}} label-placement-{{parentPlacement}} {{disabled ? 'label-disabled l-disabled-class' : 'l-class'}}">
|
||||
<view class="checkbox-{{placement}} l-icon-class" style="color:{{checked ? selectColor : (disabled ? disabledColor : color)}};font-size: {{size}}">
|
||||
<slot wx:if="{{custom}}" name="icon"/>
|
||||
<view wx:else class="iconfont {{checked? 'icon-select': 'icon-unselect'}}"></view>
|
||||
</view>
|
||||
<slot />
|
||||
</view>
|
||||
|
|
@ -1,133 +0,0 @@
|
|||
// miniprogram_npm/lin-ui/circle/index.js
|
||||
Component({
|
||||
/**
|
||||
* 组件的属性列表
|
||||
*/
|
||||
externalClasses: ['l-value-class'],
|
||||
properties: {
|
||||
percent: {
|
||||
type: Number,
|
||||
value: 0
|
||||
},
|
||||
outerDiameter: {
|
||||
type: Number,
|
||||
value: 220
|
||||
},
|
||||
innerDiameter: {
|
||||
type: Number,
|
||||
value: 170
|
||||
},
|
||||
activeColor: {
|
||||
type: String
|
||||
},
|
||||
backgroundColor: {
|
||||
type: String,
|
||||
value: '#EBEBEB',
|
||||
},
|
||||
innerColor: {
|
||||
type: String,
|
||||
value: '#FFFFFF',
|
||||
},
|
||||
active: {
|
||||
type: Boolean,
|
||||
value: false
|
||||
},
|
||||
duration: {
|
||||
type: Number,
|
||||
value: 30
|
||||
},
|
||||
showValue: {
|
||||
type: Boolean,
|
||||
value: false
|
||||
},
|
||||
valueColor: {
|
||||
type: String,
|
||||
},
|
||||
valueSize: {
|
||||
type: Number,
|
||||
value: 25
|
||||
}
|
||||
},
|
||||
|
||||
options: {
|
||||
multipleSlots: true,
|
||||
pureDataPattern: /^_/ // 指定所有 _ 开头的数据字段为纯数据字段
|
||||
},
|
||||
|
||||
/**
|
||||
* 组件的初始数据
|
||||
*/
|
||||
data: {
|
||||
displayPercent: 0,
|
||||
},
|
||||
|
||||
observers: {
|
||||
'percent': async function (percent) {
|
||||
if (percent > 100) {
|
||||
this.setData({
|
||||
percent: 100
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (percent < 0) {
|
||||
this.setData({
|
||||
percent: 0
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (this.data.active) {
|
||||
let displayPercent = this.data.displayPercent;
|
||||
|
||||
if (displayPercent < percent) {
|
||||
while (displayPercent < percent) {
|
||||
await this.sleep(this.data.duration);
|
||||
displayPercent += 1;
|
||||
this.setData({
|
||||
displayPercent: displayPercent
|
||||
});
|
||||
}
|
||||
} else if (displayPercent > percent) {
|
||||
while (displayPercent > percent) {
|
||||
await this.sleep(this.data.duration);
|
||||
displayPercent -= 1;
|
||||
this.setData({
|
||||
displayPercent
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.setData({
|
||||
displayPercent: percent
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
'outerDiameter': function (outerDiameter) {
|
||||
if (outerDiameter < this.data.innerDiameter) {
|
||||
outerDiameter = this.data.innerDiameter;
|
||||
this.setData({
|
||||
outerDiameter
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
'innerDiameter': function (innerDiameter) {
|
||||
if (innerDiameter < 0) {
|
||||
this.setData({
|
||||
innerDiameter: 0
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 组件的方法列表
|
||||
*/
|
||||
methods: {
|
||||
sleep(milSec) {
|
||||
return new Promise(resolve => {
|
||||
setTimeout(resolve, milSec);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
{
|
||||
"component": true,
|
||||
"usingComponents": {}
|
||||
}
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
/* miniprogram_npm/lin-ui/circle/index.wxss */
|
||||
@import "../styles/_base.less";
|
||||
|
||||
.sector {
|
||||
position: relative;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.sx1,
|
||||
.sx2 {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.sx1 {
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.sx2 {
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.sx_t {
|
||||
border-radius: 50%;
|
||||
z-index: 3;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.sector1 {
|
||||
background: @progress-active-color;
|
||||
}
|
||||
|
||||
.sector2 .sx1,
|
||||
.sector2 .sx2 {
|
||||
background: @progress-active-color;
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
<view class="sector {{((displayPercent < 50 && displayPercent !== 0) || displayPercent === 100) ? 'sector1' : 'sector2'}}" style="height:{{outerDiameter}}rpx;width:{{outerDiameter}}rpx;{{((displayPercent < 50 && displayPercent !== 0) || displayPercent === 100) ?activeColor?'background:'+activeColor:'':'background:'+backgroundColor}}">
|
||||
<view wx:if="{{displayPercent !== 0 && displayPercent !== 100}}" class="sx1" style="height:{{outerDiameter}}rpx;width:{{outerDiameter}}rpx;clip: rect(0rpx, {{outerDiameter/2}}rpx, {{outerDiameter}}rpx, 0rpx);background:{{((displayPercent < 50 && displayPercent !== 0) || displayPercent === 100) ?backgroundColor:activeColor?activeColor:''}}"></view>
|
||||
<view wx:if="{{displayPercent !== 50 && displayPercent !== 0 && displayPercent !== 100}}" class="sx2" style="transform: rotate({{displayPercent < 50 ? ((360 * displayPercent / 100) - 180):(360 * (displayPercent - 100) / 100)}}deg);height:{{outerDiameter}}rpx;width:{{outerDiameter}}rpx;clip: rect(0rpx, {{outerDiameter/2}}rpx, {{outerDiameter}}rpx, 0rpx);background:{{((displayPercent < 50 && displayPercent !== 0) || displayPercent === 100) ?backgroundColor:activeColor}}"></view>
|
||||
<view class="sx_t" style="width:{{innerDiameter}}rpx;height:{{innerDiameter}}rpx;background:{{innerColor}}">
|
||||
<view wx:if="{{showValue}}" class="l-value-class" style="color:{{valueColor?valueColor:''}};font-size:{{valueSize}}rpx">
|
||||
{{displayPercent}}%
|
||||
</view>
|
||||
<slot></slot>
|
||||
</view>
|
||||
</view>
|
||||
|
|
@ -1,137 +0,0 @@
|
|||
import nodeUtil from '../core/utils/node-util';
|
||||
|
||||
Component({
|
||||
|
||||
externalClasses: ['l-class', 'l-title-class', 'l-body-class'],
|
||||
|
||||
relations: {
|
||||
'../collapse/index': {
|
||||
type: 'parent'
|
||||
}
|
||||
},
|
||||
|
||||
options: {
|
||||
multipleSlots: true,
|
||||
pureDataPattern: /^_/
|
||||
},
|
||||
|
||||
properties: {
|
||||
/**
|
||||
* 折叠面板子项自定义id
|
||||
*/
|
||||
itemId: {
|
||||
type: String,
|
||||
value: 'default'
|
||||
},
|
||||
/**
|
||||
* 标题文字
|
||||
*/
|
||||
title: {
|
||||
type: String,
|
||||
value: '默认标题'
|
||||
},
|
||||
/**
|
||||
* 是否开启自定义标题
|
||||
*/
|
||||
customTitle: {
|
||||
type: Boolean,
|
||||
value: false
|
||||
},
|
||||
/**
|
||||
* 是否禁用内容区展开
|
||||
*/
|
||||
disable: {
|
||||
type: Boolean,
|
||||
value: false
|
||||
},
|
||||
/**
|
||||
* 内容区域展开动画速度
|
||||
*/
|
||||
animationTime: {
|
||||
type: String,
|
||||
value: '0.3'
|
||||
}
|
||||
},
|
||||
data: {
|
||||
/**
|
||||
* 内容区高度
|
||||
*/
|
||||
bodyHeight: '0',
|
||||
/**
|
||||
* 内容区是否展开
|
||||
*/
|
||||
isExpandContent: false,
|
||||
/**
|
||||
* 默认id
|
||||
*/
|
||||
_idDefault: -1,
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* 点击标题
|
||||
*/
|
||||
async onTapTitle() {
|
||||
if (this.data.disable) {
|
||||
return;
|
||||
}
|
||||
let parents = this.getRelationNodes('../collapse/index');
|
||||
await parents[0].onTapCollapseItem(this);
|
||||
},
|
||||
|
||||
/**
|
||||
* 折叠内容区
|
||||
*/
|
||||
async foldContent() {
|
||||
// 获取 container-body-wrapper 的 css 属性信息
|
||||
const containerBodyWrapperRect =
|
||||
await nodeUtil.getNodeRectFromComponent(this, '.container-body-wrapper');
|
||||
|
||||
// 这里很重要,先把高度改为固定高度,transition 才会生效
|
||||
if (this.data.isExpandContent) {
|
||||
this.setData({
|
||||
bodyHeight: containerBodyWrapperRect.height + 'px'
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
this.setData({
|
||||
isExpandContent: false,
|
||||
bodyHeight: '0px'
|
||||
});
|
||||
}, 20);
|
||||
} else {
|
||||
this.setData({
|
||||
isExpandContent: false,
|
||||
bodyHeight: '0px'
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
},
|
||||
|
||||
/**
|
||||
* 展开内容区
|
||||
*/
|
||||
async expandContent() {
|
||||
// 获取 container-body-wrapper 的 css 属性信息
|
||||
const containerBodyWrapperRect =
|
||||
await nodeUtil.getNodeRectFromComponent(this, '.container-body-wrapper');
|
||||
|
||||
this.setData({
|
||||
isExpandContent: true,
|
||||
bodyHeight: containerBodyWrapperRect.height + 'px'
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* 过渡效果结束后,把高度改为 auto
|
||||
* 不然内容改变时,由于高度固定,内容会显示不全
|
||||
*/
|
||||
onTransitionend() {
|
||||
if (this.data.isExpandContent) {
|
||||
this.setData({
|
||||
bodyHeight: 'auto'
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"l-list": "../list/index",
|
||||
"l-icon": "../icon/index"
|
||||
}
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
.container{display:flex;flex-direction:column;width:100%;box-sizing:border-box}.container-title{display:flex;justify-content:space-between;padding:10rpx;align-items:center;font-size:32rpx;color:#333}.container-title-l-icon{transition:.3s}.container-body{width:100%;color:#888;box-sizing:border-box;font-size:28rpx;transition:height .3s ease-in-out;overflow:hidden}.container-body-wrapper{position:relative;padding:10rpx}
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
<view class="container l-class">
|
||||
<view mut-bind:tap="onTapTitle" class="container-title l-title-class">
|
||||
<view style="{{disable?'color:#DEE2E6':''}}" wx:if="{{!customTitle}}">{{title}}</view>
|
||||
<l-icon class="container-title-icon" wx:if="{{!customTitle}}" style="{{isExpandContent?'transform:rotate(-180deg);':''}}" name="down" size="28"
|
||||
color="{{disable?'#DEE2E6':'#333'}}"></l-icon>
|
||||
<slot name="title"></slot>
|
||||
</view>
|
||||
<view catch:transitionend="onTransitionend" class="container-body" style="height:{{bodyHeight}};transition-duration:{{animationTime}}s">
|
||||
<view class="container-body-wrapper l-body-class">
|
||||
<slot></slot>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
|
@ -1,133 +0,0 @@
|
|||
Component({
|
||||
|
||||
options: {
|
||||
pureDataPattern: /^_/
|
||||
},
|
||||
|
||||
relations: {
|
||||
'../collapse-item/index': {
|
||||
type: 'child',
|
||||
linked: function () {
|
||||
this._setAllItemId();
|
||||
},
|
||||
linkChanged: function () {
|
||||
this._setAllItemId();
|
||||
},
|
||||
unlinked: function () {
|
||||
this._setAllItemId();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
lifetimes: {
|
||||
ready: function () {
|
||||
this.updateView();
|
||||
}
|
||||
},
|
||||
|
||||
properties: {
|
||||
/**
|
||||
* 折叠面板类型
|
||||
*/
|
||||
type: {
|
||||
type: String,
|
||||
value: 'normal'
|
||||
},
|
||||
|
||||
/**
|
||||
* 需要展开的 collapse-item 的id
|
||||
*/
|
||||
expandItemId: {
|
||||
type: Array,
|
||||
value: []
|
||||
}
|
||||
},
|
||||
data: {
|
||||
/**
|
||||
* 当前展开的collapse-item节点列表
|
||||
*/
|
||||
_expandItems: []
|
||||
},
|
||||
observers: {
|
||||
'expandItemId': function () {
|
||||
this.updateView();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async updateView() {
|
||||
let expandItemId;
|
||||
if (this.data.type === 'accordion') {
|
||||
expandItemId = this.data.expandItemId.slice(0, 1);
|
||||
} else {
|
||||
expandItemId = this.data.expandItemId;
|
||||
}
|
||||
|
||||
let children = this.getRelationNodes('../collapse-item/index');
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
let item = children[i];
|
||||
let id = item.data.itemId === 'default' ? i : item.data.itemId;
|
||||
if (expandItemId.indexOf(id) > -1 && !item.isExpandContent) {
|
||||
await this.setCollapseItemStatus(item, true);
|
||||
} else if (item.isExpandContent || this.data.type === 'accordion') {
|
||||
await this.setCollapseItemStatus(item, false);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 点击折叠面板子项回调函数
|
||||
* @param collapseItem
|
||||
*/
|
||||
async onTapCollapseItem(collapseItem) {
|
||||
if (this.data.type === 'accordion') {
|
||||
await this.foldAllExpandItem(collapseItem);
|
||||
}
|
||||
this.setCollapseItemStatus(collapseItem, !collapseItem.data.isExpandContent);
|
||||
|
||||
if (!collapseItem.data.isExpandContent) {
|
||||
this.triggerEvent('linexpand', { id: collapseItem.data.itemId ? collapseItem.data.itemId : collapseItem.data._idDefault });
|
||||
} else {
|
||||
this.triggerEvent('linfold', { id: collapseItem.data.itemId ? collapseItem.data.itemId : collapseItem.data._idDefault });
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 设置子组件状态
|
||||
*/
|
||||
async setCollapseItemStatus(collapseItem, isExpand) {
|
||||
if (isExpand) {
|
||||
collapseItem.expandContent();
|
||||
this.data._expandItems.push(collapseItem);
|
||||
} else {
|
||||
await collapseItem.foldContent();
|
||||
for (let i = 0; i < this.data._expandItems.length; i++) {
|
||||
if (this.data._expandItems[i] === collapseItem) {
|
||||
this.data._expandItems.splice(i, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 关闭所有打开的collapse-item
|
||||
*/
|
||||
foldAllExpandItem(collapseItem) {
|
||||
for (let i = 0; i < this.data._expandItems.length; i++) {
|
||||
if (collapseItem !== this.data._expandItems[i]) {
|
||||
this.data._expandItems[i].foldContent();
|
||||
}
|
||||
}
|
||||
this.data._expandItems = [];
|
||||
},
|
||||
|
||||
/**
|
||||
* 重新设置子项组件的默认id
|
||||
*/
|
||||
_setAllItemId() {
|
||||
let children = this.getRelationNodes('../collapse-item/index');
|
||||
children.forEach((item, index) => {
|
||||
item.data._idDefault = index;
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
<view class="container">
|
||||
<slot></slot>
|
||||
</view>
|
||||
|
|
@ -1,256 +0,0 @@
|
|||
import nodeUtil from '../core/utils/node-util';
|
||||
|
||||
Component({
|
||||
externalClasses: [
|
||||
'l-class-header',
|
||||
'l-class-active',
|
||||
'l-class-inactive',
|
||||
'l-class-line',
|
||||
'l-class-tabimage',
|
||||
'l-header-class',
|
||||
'l-active-class',
|
||||
'l-inactive-class',
|
||||
'l-line-class',
|
||||
'l-tabimage-class',
|
||||
'l-content-class'
|
||||
],
|
||||
relations: {
|
||||
'../tabpanel/index': {
|
||||
type: 'child'
|
||||
},
|
||||
linked() {
|
||||
// 每次有子节点被插入时执行,target是该节点实例对象,触发在该节点attached生命周期之后
|
||||
this.initTabs();
|
||||
}
|
||||
},
|
||||
options: {
|
||||
multipleSlots: true // 在组件定义时的选项中启用多slot支持
|
||||
},
|
||||
/**
|
||||
* 组件的属性列表
|
||||
*/
|
||||
properties: {
|
||||
activeKey: {
|
||||
type: String,
|
||||
value: '',
|
||||
observer: 'changeCurrent'
|
||||
},
|
||||
placement: {
|
||||
type: String,
|
||||
value: 'top'
|
||||
},
|
||||
aminmated: Boolean,
|
||||
scrollable: Boolean,
|
||||
swipeable: {
|
||||
type: Boolean,
|
||||
value: true
|
||||
},
|
||||
hasLine: {
|
||||
type: Boolean,
|
||||
value: true
|
||||
},
|
||||
activeColor: {
|
||||
type: String,
|
||||
value: '#333333'
|
||||
},
|
||||
inactiveColor: {
|
||||
type: String,
|
||||
value: '#bbbbbb'
|
||||
}
|
||||
},
|
||||
|
||||
data: {
|
||||
tabList: [],
|
||||
currentIndex: 0,
|
||||
transformX: 0,
|
||||
transformY: 0
|
||||
},
|
||||
|
||||
ready() {
|
||||
this.initTabs();
|
||||
},
|
||||
|
||||
/**
|
||||
* 组件的方法列表
|
||||
*/
|
||||
methods: {
|
||||
initTabs() {
|
||||
this.initTabList();
|
||||
this.initActiveIndex();
|
||||
},
|
||||
initActiveIndex(val = this.data.activeKey) {
|
||||
let activeKey = val,
|
||||
currentIndex = this.data.currentIndex;
|
||||
this.data.tabList.forEach((item, index) => {
|
||||
activeKey = !val && index === 0 ? item.key : activeKey;
|
||||
currentIndex = item.key === activeKey ? index : currentIndex;
|
||||
});
|
||||
this.setData(
|
||||
{
|
||||
activeKey,
|
||||
currentIndex
|
||||
},
|
||||
() => {
|
||||
if (this.data.scrollable) {
|
||||
this.queryMultipleNodes();
|
||||
}
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
initTabList() {
|
||||
let items = this.getRelationNodes('../tabpanel/index');
|
||||
if (items.length > 0) {
|
||||
const tabList = [];
|
||||
items.forEach(item => {
|
||||
const tabIndex = tabList.findIndex(
|
||||
tabItem => tabItem.tab === item.data.tab
|
||||
);
|
||||
let tab = {};
|
||||
if (tabIndex === -1) {
|
||||
tab = {
|
||||
tab: item.data.tab,
|
||||
key: item.data.key,
|
||||
icon: item.data.icon,
|
||||
iconStyle: item.data.iconStyle,
|
||||
image: item.data.image,
|
||||
subTabs: []
|
||||
};
|
||||
tabList.push(tab);
|
||||
}
|
||||
const targetTab = tabIndex === -1 ? tab : tabList[tabIndex];
|
||||
if (item.data.subTab) {
|
||||
targetTab.subTabs = targetTab.subTabs || [];
|
||||
const subTabItem = {
|
||||
tab: item.data.subTab,
|
||||
key: item.data.subKey
|
||||
};
|
||||
targetTab.subTabs.push(subTabItem);
|
||||
targetTab.activeSubKey =
|
||||
this.data.subActiveKey || targetTab.subTabs[0].key;
|
||||
targetTab.subCurrentIndex = 0;
|
||||
}
|
||||
});
|
||||
this.setData({
|
||||
tabList
|
||||
});
|
||||
}
|
||||
},
|
||||
swiperChange(e) {
|
||||
const {source, current} = e.detail;
|
||||
if (source === 'touch') {
|
||||
const currentIndex = current;
|
||||
const activeKey = this.data.tabList[current].key;
|
||||
const subCurrentIndex = this.data.tabList[currentIndex].subCurrentIndex;
|
||||
const activeSubKey = this.data.tabList[currentIndex].activeSubKey;
|
||||
this._setChangeData({
|
||||
activeKey,
|
||||
currentIndex,
|
||||
subCurrentIndex,
|
||||
activeSubKey
|
||||
});
|
||||
}
|
||||
},
|
||||
subSwiperChange(e) {
|
||||
const {source, current} = e.detail;
|
||||
if (source === 'touch') {
|
||||
const {currentIndex, activeKey} = this.data;
|
||||
const subCurrentIndex = current;
|
||||
const activeSubKey = this.data.tabList[currentIndex].subTabs[
|
||||
subCurrentIndex
|
||||
].key;
|
||||
const tabs = this.data.tabList[currentIndex];
|
||||
tabs.activeSubKey = activeSubKey;
|
||||
tabs.subCurrentIndex = subCurrentIndex;
|
||||
|
||||
this.setData({
|
||||
[`tabList[${currentIndex}]`]: tabs
|
||||
});
|
||||
|
||||
this._setChangeData({
|
||||
activeKey,
|
||||
currentIndex,
|
||||
activeSubKey,
|
||||
subCurrentIndex
|
||||
});
|
||||
}
|
||||
},
|
||||
handleChange(e) {
|
||||
const isSubHeader = e.currentTarget.dataset.headerType === 'subTab';
|
||||
const {currentIndex, activeKey} = this.data;
|
||||
|
||||
const clickIndex = e.currentTarget.dataset.index;
|
||||
const subCurrentIndex = isSubHeader
|
||||
? clickIndex
|
||||
: this.data.tabList[clickIndex].subCurrentIndex;
|
||||
const activeSubKey = isSubHeader
|
||||
? this.data.tabList[currentIndex].subTabs[subCurrentIndex].key
|
||||
: this.data.tabList[clickIndex].activeSubKey;
|
||||
if (isSubHeader) {
|
||||
const tabs = this.data.tabList[currentIndex];
|
||||
tabs.activeSubKey = activeSubKey;
|
||||
tabs.subCurrentIndex = subCurrentIndex;
|
||||
this.setData({
|
||||
[`tabList[${currentIndex}]`]: tabs
|
||||
});
|
||||
this._setChangeData({
|
||||
activeKey,
|
||||
currentIndex,
|
||||
activeSubKey,
|
||||
subCurrentIndex
|
||||
});
|
||||
} else {
|
||||
const activeKey = e.currentTarget.dataset.key;
|
||||
this._setChangeData({
|
||||
activeKey,
|
||||
currentIndex: clickIndex,
|
||||
subCurrentIndex,
|
||||
activeSubKey
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
_setChangeData({
|
||||
activeKey,
|
||||
currentIndex,
|
||||
activeSubKey = '',
|
||||
subCurrentIndex = null
|
||||
}) {
|
||||
this.setData(
|
||||
{
|
||||
activeKey,
|
||||
currentIndex
|
||||
},
|
||||
() => {
|
||||
if (this.data.scrollable) {
|
||||
this.queryMultipleNodes();
|
||||
}
|
||||
}
|
||||
);
|
||||
this.triggerEvent('linchange', {
|
||||
activeKey,
|
||||
currentIndex,
|
||||
activeSubKey,
|
||||
subCurrentIndex
|
||||
});
|
||||
},
|
||||
|
||||
async queryMultipleNodes() {
|
||||
const {placement, activeKey, tabList} = this.data;
|
||||
const res = await nodeUtil.getNodeRectFromComponent(this, '#' + activeKey);
|
||||
if (['top', 'bottom'].indexOf(placement) !== -1) {
|
||||
this.setData({
|
||||
transformX: res.left - (tabList.length / 2) * res.width,
|
||||
transformY: 0
|
||||
});
|
||||
} else {
|
||||
const navRect = await nodeUtil.getNodeRectFromComponent(this, '.l-tabs-header');
|
||||
const transformY = res.top - navRect.top - navRect.height / 2;
|
||||
this.setData({
|
||||
transformX: 0,
|
||||
transformY: transformY
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"l-icon":"../icon/index",
|
||||
"l-badge":"../badge/index"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,252 +0,0 @@
|
|||
/* components/tabs/index.wxss */
|
||||
.l-tabs {
|
||||
display: flex;
|
||||
border-radius: 8rpx;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
flex-direction: column;
|
||||
background: #fff;
|
||||
height: 100%;
|
||||
|
||||
.l-tabs-header {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
flex-direction: row;
|
||||
background: rgba(255, 255, 255, 1);
|
||||
align-items: center;
|
||||
|
||||
.l-tabs-item {
|
||||
flex: 1;
|
||||
font-size: 28rpx;
|
||||
text-align: center;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.l-icon-active,
|
||||
.l-tabs-active {
|
||||
color: #333333;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.l-icon-inactive,
|
||||
.l-tabs-inactive {
|
||||
font-size: 28rpx;
|
||||
color: #bbbbbb;
|
||||
}
|
||||
|
||||
.l-tabsitems-row {
|
||||
flex-direction: row;
|
||||
.l-icon-inactive,
|
||||
.l-icon-active {
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.l-tabsitems-row-reverse {
|
||||
flex-direction: row-reverse;
|
||||
.l-icon-inactive,
|
||||
.l-icon-active {
|
||||
margin-left: 10rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.l-placement-top {
|
||||
.l-tabs-header {
|
||||
height: 80rpx;
|
||||
.l-tabs-item {
|
||||
min-height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.l-sub-placement-left {
|
||||
flex-direction: row;
|
||||
.l-tabs-header {
|
||||
flex-direction: column;
|
||||
width: 160rpx;
|
||||
& > .l-tabs-item {
|
||||
width: 100%;
|
||||
height: 80rpx;
|
||||
background: #f6f8fa;
|
||||
}
|
||||
& > .l-tabs-active {
|
||||
background: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.l-sub-placement-left .l-tabs-main .l-tabpanel-content{
|
||||
width: 100%;
|
||||
flex-direction: column;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-box-direction: normal;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
will-change: transform;
|
||||
will-change: transform;
|
||||
transition: transform 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
|
||||
}
|
||||
|
||||
.l-placement-top .l-tabpanel-content {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: -webkit-box;
|
||||
display: -webkit-flex;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-webkit-box-orient: horizontal;
|
||||
-webkit-box-direction: normal;
|
||||
-webkit-flex-direction: row;
|
||||
-ms-flex-direction: row;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.l-subpanel-content {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.l-tabpanel {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
-webkit-flex-shrink: 0;
|
||||
-ms-flex-negative: 0;
|
||||
flex-shrink: 0;
|
||||
-webkit-transition: opacity 0.45s;
|
||||
transition: opacity 0.45s;
|
||||
opacity: 1;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.l-tabpanel-inactive {
|
||||
opacity: 0;
|
||||
height: 0;
|
||||
padding: 0 !important;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.l-subpanel {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
// 滚动标签栏-水平
|
||||
.l-tabs-scroll.l-tabs-horizontal {
|
||||
.l-tabs-header {
|
||||
-webkit-overflow-scrolling: touch;
|
||||
white-space: nowrap;
|
||||
.l-tabs-item {
|
||||
overflow: visible;
|
||||
min-width: 160rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.l-tabpanel-content {
|
||||
height: 150px;
|
||||
}
|
||||
}
|
||||
|
||||
.l-tabs-vertical {
|
||||
.l-tabsscroll {
|
||||
width: 160rpx;
|
||||
}
|
||||
.l-tabs-header {
|
||||
height: 100%;
|
||||
min-height: 80rpx;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
white-space: nowrap;
|
||||
.l-tabs-item {
|
||||
overflow: visible;
|
||||
min-height: 80rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 下划线
|
||||
.l-tabs-item {
|
||||
position: relative;
|
||||
}
|
||||
.l-tab-line {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
width: 0;
|
||||
background: #000;
|
||||
}
|
||||
.l-tabs-horizontal {
|
||||
.l-tab-line {
|
||||
height: 4rpx;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.l-tabs-active {
|
||||
.l-tab-line {
|
||||
width: 100%;
|
||||
transition-delay: 0.1s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.l-placement-top {
|
||||
.l-tab-line {
|
||||
bottom: 0
|
||||
}
|
||||
|
||||
.l-tabs-header-line {
|
||||
border-bottom: 1px solid #F3F3F3
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.l-tabs-vertical {
|
||||
.l-tabs-active {
|
||||
.l-tab-line {
|
||||
width: 6rpx !important;
|
||||
height: 40rpx !important;
|
||||
border-radius: 0 6rpx 6rpx 0;
|
||||
top: 0;
|
||||
left: 0;
|
||||
margin: auto 0;
|
||||
transition-delay: 0.1s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.l-sub-placement-left {
|
||||
.l-tab-line {
|
||||
left: 0;
|
||||
right: auto;
|
||||
}
|
||||
|
||||
.l-tabs-header-line {
|
||||
border-right: 1px solid #F3F3F3
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.l-tab-image {
|
||||
width: 100rpx;
|
||||
height: 100rpx;
|
||||
}
|
||||
|
||||
.l-tab-image-placement-top {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
|
||||
.l-tab-image-placement-left {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
|
||||
.l-tabs-main {
|
||||
flex:1;
|
||||
}
|
||||
|
||||
.l-combined-tabs-main {
|
||||
display: flex
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue