提交 4681984b 编写于 作者: D devil_gong

微信小程序初始化

上级 7ce4586f
App({
data: {
// 用户信息缓存key
cache_user_info_key: "cache_shop_user_info_key",
// 用户站点信息缓存key
cache_user_merchant_key: "cache_shop_user_merchant_key",
// 设备信息缓存key
cache_system_info_key: "cache_shop_system_info_key",
// 用户地址选择缓存key
cache_buy_user_address_select_key: "cache_buy_user_address_select_key",
// 用户传入信息缓存key
cache_launch_info_key: "cache_shop_launch_info_key",
// 默认用户头像
default_user_head_src: "/images/default-user.png",
// 成功圆形提示图片
default_round_success_icon: "/images/default-round-success-icon.png",
// 错误圆形提示图片
default_round_error_icon: "/images/default-round-error-icon.png",
// 页面标题
common_pages_title: {
"goods_search": "商品搜索",
"goods_detail": "商品详情",
"goods_attribute": "属性",
"user_address": "我的地址",
"user_address_save_add": "新增地址",
"user_address_save_edit": "编辑地址",
"buy": "订单确认",
"user_order": "我的订单",
"user_order_detail": "订单详情",
"user_favor": "我的收藏",
"answer_form": "留言",
"answer_list": "问答",
"user_answer_list": "我的留言",
"user": "用户中心",
"goods_category": "分类",
"cart": "购物车",
"message": "消息",
"user_integral": "我的积分",
"user_goods_browse": "我的足迹",
},
// 请求地址
//request_url: "{{request_url}}",
//request_url: "http://test.shopxo.net/",
request_url: 'https://test.shopxo.net/',
// 基础信息
application_title: "{{application_title}}",
application_describe: "{{application_describe}}",
},
/**
* 小程序初始化
*/
onLaunch(options) {
// 设置设备信息
this.set_system_info();
// 初始化用户信息、未授权用户唤醒授权操作
let user = this.GetUserCacheInfo();
// // 用户缓存不存在则唤醒用户授权
if (user == false) {
// 用户信息为空则唤醒授权
this.UserAuthCode();
}
// 启动query参数处理
this.startup_query(options);
},
/**
* 启动query参数处理
*/
startup_query(options) {
// 没有启动参数则返回
if ((options.query || null) == null) {
return false;
}
// 启动处理类型
var type = options.query.type || null;
switch (type) {
// type=page
case 'page':
// 页面
var page = options.query.page || null;
// 参数值
var value = options.query.value || null;
// 附带参数值
var params = null;
// 进入逻辑处理
switch (page) {
// 进入店铺 page=shop
case 'shop':
// 进入项目详情 page=detail
case 'detail':
if (value != null) {
params = 'id=' + value;
}
break;
// 店铺买单 page=shoppay
case 'shoppay':
if (value != null) {
params = 'shop_id=' + value;
}
break;
default:
break;
}
break;
default:
break;
}
// 是否需要进行页面跳转
if (params != null) {
wx.navigateTo({
url: '/pages/' + page + '/' + page + '?' + params
});
}
},
/**
* 获取设备信息
*/
get_system_info() {
let system_info = wx.getStorageSync(this.data.cache_system_info_key);
if ((system_info.data || null) == null) {
return this.set_system_info();
}
return system_info.data;
},
/**
* 设置设备信息
*/
set_system_info() {
var system_info = wx.getSystemInfoSync();
wx.setStorage({
key: this.data.cache_system_info_key,
data: system_info
});
return system_info;
},
/**
/**
* 请求地址生成
*/
get_request_url(a, c, m, params) {
a = a || "index";
c = c || "index";
m = m || "api";
params = params || "";
if (params != "" && params.substr(0, 1) != "&") {
params = "&" + params;
}
var user = this.GetUserCacheInfo();
var app_client_user_id = user == false ? "" : user.wechat_openid;
var user_id = user == false ? 0 : user.id;
return (
this.data.request_url +
"index.php?s=/" + m + "/" + c + "/" + a +
"&application_client=default&&application=app&application_client_type=wechat&application_user_id=" +
app_client_user_id +
"&user_id=" +
user_id +
"&ajax=ajax" +
params
);
},
/**
* 获取平台用户信息
* object 回调操作对象
* method 回调操作对象的函数
* return 有用户数据直接返回, 则回调调用者
*/
GetUserInfo(object, method) {
var user = this.GetUserCacheInfo();
if (user == false) {
// 唤醒用户授权
this.UserAuthCode(object, method);
return false;
} else {
return user;
}
},
/**
* 获取本系统用户信息
*/
GetMyUserInfo() {
var user = this.GetUserCacheInfo();
if (user == false) {
return null;
} else {
return user.my_user || null;
}
},
/**
* 从缓存获取用户信息
*/
GetUserCacheInfo() {
let user = wx.getStorageSync(this.data.cache_user_info_key);
if ((user || null) == null) {
return false;
}
if ((user.my_user || null) == null) {
user.my_user = null;
}
return user;
},
/**
* 从缓存获美啦取用户信息
*/
GetMeiLaUserCacheInfo() {
let user = wx.getStorageSync(this.data.cache_user_info_key);
if ((user || null) == null) {
return null;
}
if ((user.my_user || null) == null) {
return null;
}
return user.my_user;
},
/**
* 用户授权
* object 回调操作对象
* method 回调操作对象的函数
*/
UserAuthCode(object, method) {
// 加载loding
wx.showLoading({ title: '授权中...' });
var $this = this;
// 请求授权接口
wx.getSetting({
success(res) {
if (!res.authSetting['scope.userInfo']) {
wx.authorize({
scope: 'scope.userInfo',
success() {
$this.user_auth_login(object, method);
},
fail: (e) => {
wx.hideLoading();
$this.showToast('授权失败');
}
});
} else {
$this.user_auth_login(object, method);
}
},
fail: (e) => {
wx.hideLoading();
$this.showToast('授权校验失败');
}
});
},
/**
* 用户登录
* object 回调操作对象
* method 回调操作对象的函数
*/
user_auth_login(object, method) {
var $this = this;
wx.checkSession({
success: function () {
var openid = wx.getStorageSync($this.data.cache_user_login_key);
if ((openid || null) == null)
{
$this.user_login(object, method);
} else {
$this.get_user_login_info(object, method, openid);
}
},
fail: function () {
$this.user_login(object, method);
}
});
},
/**
* 用户登录
* object 回调操作对象
* method 回调操作对象的函数
*/
user_login(object, method) {
var $this = this;
wx.login({
success: (res) => {
if (res.code) {
wx.request({
url: $this.get_request_url('GetWechatUserLogin', 'User'),
method: 'POST',
data: { authcode: res.code },
dataType: 'json',
header: { 'content-type': 'application/x-www-form-urlencoded' },
success: (res) => {
if (res.data.state == 'ok') {
wx.setStorage({
key: $this.data.cache_user_login_key,
data: res.data.data
});
$this.get_user_login_info(object, method, res.data.data);
} else {
wx.hideLoading();
$this.showToast(res.data.text);
}
},
fail: () => {
wx.hideLoading();
$this.showToast('服务器请求出错');
},
});
}
},
fail: (e) => {
wx.hideLoading();
$this.showToast('授权失败');
}
});
},
/**
* 获取用户授权信息
* object 回调操作对象
* method 回调操作对象的函数
* openid 用户openid
*/
get_user_login_info(object, method, openid) {
var $this = this;
wx.getUserInfo({
withCredentials: true,
success: function (res) {
// 远程解密数据
wx.request({
url: $this.get_request_url('GetWechatUserInfo', 'User'),
method: 'POST',
data: { encrypted_data: res.encryptedData, iv: res.iv, openid: openid },
dataType: 'json',
header: { 'content-type': 'application/x-www-form-urlencoded' },
success: (res) => {
wx.hideLoading();
if (res.data.state == 'ok') {
wx.setStorage({
key: $this.data.cache_user_info_key,
data: res.data.data
});
if (typeof object === 'object' && (method || null) != null) {
object[method]();
}
} else {
$this.showToast(res.data.text);
}
},
fail: () => {
wx.hideLoading();
$this.showToast('服务器请求出错');
},
});
},
fail: (e) => {
wx.hideLoading();
$this.showToast('获取用户信息失败');
}
});
},
/**
* 字段数据校验
* data 待校验的数据, 一维json对象
* validation 待校验的字段, 格式 [{fields: 'mobile', msg: '请填写手机号码'}, ...]
*/
fields_check(data, validation) {
for (var i in validation) {
if ((data[validation[i]['fields']] || null) == null) {
this.showToast(validation[i]['msg']);
return false;
}
}
return true;
},
/**
* 获取当前时间戳
*/
get_timestamp() {
return parseInt(new Date().getTime() / 1000);
},
/**
* 获取日期
* format 日期格式(默认 yyyy-MM-dd h:m:s)
* timestamp 时间戳(默认当前时间戳)
*/
get_date(format, timestamp) {
var d = new Date((timestamp || this.get_timestamp()) * 1000);
var date = {
"M+": d.getMonth() + 1,
"d+": d.getDate(),
"h+": d.getHours(),
"m+": d.getMinutes(),
"s+": d.getSeconds(),
"q+": Math.floor((d.getMonth() + 3) / 3),
"S+": d.getMilliseconds()
};
if (/(y+)/i.test(format)) {
format = format.replace(RegExp.$1, (d.getFullYear() + '').substr(4 - RegExp.$1.length));
}
for (var k in date) {
if (new RegExp("(" + k + ")").test(format)) {
format = format.replace(RegExp.$1, RegExp.$1.length == 1 ? date[k] : ("00" + date[k]).substr(("" + date[k]).length));
}
}
return format;
},
/**
* 获取对象、数组的长度、元素个数
* obj 要计算长度的元素(object、array、string)
*/
get_length(obj) {
var obj_type = typeof obj;
if (obj_type == "string") {
return obj.length;
} else if (obj_type == "object") {
var obj_len = 0;
for (var i in obj) {
obj_len++;
}
return obj_len;
}
return false;
},
/**
* 价格保留两位小数
* price 价格保留两位小数
*/
price_two_decimal(x) {
var f_x = parseFloat(x);
if (isNaN(f_x)) {
return 0;
}
var f_x = Math.round(x * 100) / 100;
var s_x = f_x.toString();
var pos_decimal = s_x.indexOf('.');
if (pos_decimal < 0) {
pos_decimal = s_x.length;
s_x += '.';
}
while (s_x.length <= pos_decimal + 2) {
s_x += '0';
}
return s_x;
},
/**
* 默认弱提示方法
* msg [string] 提示信息
* status [string] 状态 默认error [正确success, 错误error]
*/
showToast(msg, status)
{
if ((status || 'error') == 'success')
{
wx.showToast({
title: msg,
duration: 3000
});
} else {
wx.showToast({
image: '/images/default-toast-error.png',
title: msg,
duration: 3000
});
}
}
});
\ No newline at end of file
{
"pages": [
"pages/index/index",
"pages/goods-category/goods-category",
"pages/cart/cart",
"pages/user/user",
"pages/web-view/web-view",
"pages/login/login",
"pages/paytips/paytips",
"pages/goods-search/goods-search",
"pages/goods-detail/goods-detail",
"pages/goods-attribute/goods-attribute",
"pages/buy/buy",
"pages/user-address/user-address",
"pages/user-address-save/user-address-save",
"pages/user-order/user-order",
"pages/user-order-detail/user-order-detail",
"pages/user-faovr/user-faovr",
"pages/user-answer-list/user-answer-list",
"pages/answer-list/answer-list",
"pages/answer-form/answer-form",
"pages/message/message",
"pages/user-integral/user-integral",
"pages/user-goods-browse/user-goods-browse"
],
"window": {
"navigationBarTitleText": "{{application_title}}",
"navigationBarBackgroundColor": "#d2364c"
},
"tabBar": {
"color": "#8a8a8a",
"selectedColor": "#d2364c",
"backgroundColor": "#fff",
"list": [
{
"pagePath": "pages/index/index",
"iconPath": "/images/nav-icon-home.png",
"selectedIconPath": "/images/nav-icon-home-active.png",
"text": "首页"
},
{
"pagePath": "pages/goods-category/goods-category",
"iconPath": "/images/nav-icon-category.png",
"selectedIconPath": "/images/nav-icon-category-active.png",
"text": "分类"
},
{
"pagePath": "pages/cart/cart",
"iconPath": "/images/nav-icon-cart.png",
"selectedIconPath": "/images/nav-icon-cart-active.png",
"text": "购物车"
},
{
"pagePath": "pages/user/user",
"iconPath": "/images/nav-icon-user.png",
"selectedIconPath": "/images/nav-icon-user-active.png",
"text": "我的"
}
]
},
"networkTimeout": {
"request": 10000,
"downloadFile": 10000
},
"debug": true
}
/* 框架样式覆盖 */
.a-textarea-control textarea { font-size: 12px; }
/* 公共样式 */
page {
background: #f5f5f5;
color: #4a4a4a;
}
page, textarea {
font-size: 28rpx;
}
input[type="text"],
input[type="number"],
input[type="idcard"],
input[type="digit"],
textarea {
-webkit-appearance: none;
border-radius: 5px;
}
/* 导航分割 */
.spacing-nav-title {
position: relative;
color: #d2364c;
text-align: center;
background-color: #ffffff;
height: 80rpx;
line-height: 80rpx;
}
.spacing-nav-title .line {
display: inline-block;
width: 50%;
height: 1px;
background: #d2364c;
position: absolute;
left: 50%;
top: 50%;
-webkit-transform: translate(-50%,-50%);
-ms-transform: translate(-50%,-50%);
transform: translate(-50%,-50%);
}
.spacing-nav-title .text-wrapper {
position: relative;
display: inline-block;
padding: 0 8px;
background-color: #ffffff;
font-size: 36rpx;
font-weight: bold;
}
/* 模块分割间距 */
.spacing { padding-top: 20rpx; }
.spacing-10 { padding-top: 10rpx; }
.spacing-mb { margin-bottom: 20rpx; }
.spacing-mt { margin-top: 20rpx; }
/* 在线客服 */
.customer-service {
position: fixed;
bottom: 100rpx;
right: 0;
}
.customer-service image {
width: 80rpx;
height: 80rpx;
margin-right: 20rpx;
}
.drift { position: fixed; left: -1000px; }
.nav-submit-fixed { background: #eee; height: 46px; position: fixed; bottom: 0; z-index: 10; }
.tips { background: #ffffeb url('/images/tips.png') no-repeat 5rpx 12rpx; background-size: 35rpx 35rpx; color: #f7b240; border: 1px solid #faebd2; line-height: 36rpx; padding: 5px 5px 5px 20px; font-size: 26rpx; border-radius: 2px; display: block; }
.data-loding image { width: 60px; height: 60px; background-size: 80% 80% !important; }
/* 边框 */
.br { border: solid 1px #efefef; }
.br-b { border-bottom: solid 1px #efefef; }
.br-t { border-top: solid 1px #efefef; }
.br-l { border-left: solid 1px #efefef; }
.br-r { border-right: solid 1px #efefef; }
/* 虚线边框 */
.br-b-dashed { border-bottom: dashed 1px #efefef; }
.br-t-dashed { border-top: dashed 1px #efefef; }
.br-l-dashed { border-left: dashed 1px #efefef; }
.br-r-dashed { border-right: dashed 1px #efefef; }
/* 箭头符号 */
.arrow-right { background-image: url('data:image/svg+xml;charset=utf-8,<svg width="16" height="26" viewBox="0 0 16 26" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><g id="UI-KIT_基础元件" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd"><g id="9.9基础元件" transform="translate(-5809.000000, -8482.000000)" fill="#C7C7CC"><polygon id="Disclosure-Indicator" points="5811 8482 5809 8484 5820.5 8495 5809 8506 5811 8508 5825 8495"></polygon></g></g></svg>'); background-size: 15px 10px; background-repeat: no-repeat; background-position: center right; }
/* 常用样式 */
.fl { float: left; }
.fr { float: right; }
.bg-white { background-color: #fff; }
.wh-auto { width: 100%; }
.tc { text-align: center; }
.tl { text-align: left; }
.tr { text-align: right; }
.oh { overflow: hidden; }
.dis-none { display: none; }
.dis-block { display: block; }
.cr-main { color: #d2364c; }
.cr-666 { color: #666; }
.cr-888 { color: #888; }
.cr-ccc { color: #ccc; }
.cr-fff { color: #fff; }
.my-btn-default{
font-size: 38rpx;
color: #fff;
border: none;
background-color:#d2364c;
border-radius: 2px;
}
.my-btn-default.btn-disabled{
background-color: #a6a6a6;
color: #fff;
}
.my-btn-gray{
font-size: 30rpx;
color: #fff;
border: none;
background-color:#a6a6a6;
border-radius: 2px;
}
/* 文字超出部分使用省略号 */
.single-text {
-o-text-overflow: ellipsis;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
max-width: 100%;
}
.multi-text {
max-width: 100%;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
/* 没有数据状态/处理错误/加载中 */
.no-data-box {
padding: 80rpx 0;
}
.no-data-box image {
width: 160rpx;
margin-bottom: 30rpx;
}
.no-data-box .no-data-tips {
font-size: 28rpx;
color: #a6a6a6;
}
.no-data-loding {
padding-top: 15%;
padding-bottom: 10px;
}
/* 底线 */
.data-bottom-line{
padding: 40rpx;
overflow: hidden;
}
.data-bottom-line view {
width: 33.3%;
}
.data-bottom-line .left, .data-bottom-line .right{
margin-top: 5px;
border-bottom: 1px solid #e1e1e1;
}
.data-bottom-line .msg{
color: #999;
text-align: center;
font-size: 24rpx;
}
/* 业务公共 */
.copyright {
color: #a5a5a5;
text-align: center;
padding: 20rpx 0;
}
.copyright .title {
font-size: 30rpx;
font-weight: 500;
margin-bottom: 5rpx;
}
.copyright .text {
font-size: 26rpx;
font-weight: 400;
}
.sales-price {
color: #f40;
font-weight: bold;
font-size: 32rpx;
}
.original-price {
color: #888;
font-size: 26rpx;
text-decoration: line-through;
margin-left: 10rpx;
}
.submit-fixed {
position: fixed;
left: 0;
bottom: 0;
background: #d2364c;
color: #fff;
border: none;
width: 100%;
}
.bg-main, .bg-primary, .bg-warning {
color: #fff;
border: 0;
font-size: 34rpx;
}
.bg-main {
background: #d2364c;
}
.bg-primary {
background: #ed6977;
}
.bg-warning {
background: #F37B1D;
}
.bg-active-main {
background: #d2364c !important;
color: #fff !important;
}
.submit-bottom {
height: 85rpx;
line-height: 85rpx;
font-size: 32rpx;
border-radius: 0;
}
.bg-main.a-button-disabled {
background: #fbe0e5;
color: #f7b6c2;
}
.bg-warning.a-button-disabled {
background: #ffcda6;
color: #fdae70;
}
.bg-primary.a-button-disabled {
background: #ffd2d7;
color: #ffa0ab;
}
.nav-back {
position: fixed;
left: 0;
bottom: 10%;
}
/*
滚动标签高度
*/
.scroll-box {
height: 100vh;
}
\ No newline at end of file
const app = getApp();
Component({
mixins: [],
data: {
indicator_dots: false,
indicator_color: 'rgba(0, 0, 0, .3)',
indicator_active_color: '#e31c55',
autoplay: true,
circular: true,
data_list_loding_status: 1,
data_bottom_line_status: false,
data_list: [],
},
props: {},
didMount() {
this.init();
},
didUpdate() {},
didUnmount() {},
methods: {
// 获取数
init() {
// 加载loding
this.setData({
data_list_loding_status: 1,
});
// 加载loding
wx.request({
url: app.get_request_url("index", "banner"),
method: "POST",
data: {},
dataType: "json",
header: { 'content-type': 'application/x-www-form-urlencoded' },
success: res => {
if (res.data.code == 0) {
var data = res.data.data;
this.setData({
data_list: data,
indicator_dots: (data.length > 1),
autoplay: (data.length > 1),
data_list_loding_status: data.length == 0 ? 0 : 3,
data_bottom_line_status: true,
});
} else {
this.setData({
data_list_loding_status: 0,
data_bottom_line_status: true,
});
wx.showToast({
type: "fail",
content: res.data.msg
});
}
},
fail: () => {
this.setData({
data_list_loding_status: 2,
data_bottom_line_status: true,
});
wx.showToast({
type: "fail",
content: "服务器请求出错"
});
}
});
},
// 操作事件
banner_event(e) {
app.operation_event(e);
},
},
});
{
"component": true
}
\ No newline at end of file
<swiper
indicator-dots="{{indicator_dots}}"
indicator-color="{{indicator_color}}"
indicator-active-color="{{indicator_active_color}}"
autoplay="{{autoplay}}"
circular="{{circular}}"
class="banner bg-white spacing-mb"
wx:if="{{data_list.length > 0}}">
<block wx:for="{{data_list}}">
<swiper-item>
<image class="wh-auto" src="{{item.images_url}}" mode="widthFix" data-value="{{item.event_value}}" data-type="{{item.event_type}}" bindtap="banner_event" />
</swiper-item>
</block>
</swiper>
<view wx:if="{{data_list_loding_status == 2}}">
<import src="/pages/common/nodata.wxml" />
<template is="nodata" data="{{status: data_list_loding_status}}"></template>
</view>
\ No newline at end of file
.banner {
height: 320rpx!important;
}
\ No newline at end of file
const app = getApp();
Component({
mixins: [],
props: {},
data: {
data_list_loding_status: 1,
data_bottom_line_status: false,
data_list: [],
},
didMount() {
this.init();
},
didUpdate(){},
didUnmount(){},
methods:{
init() {
// 加载loding
this.setData({
data_list_loding_status: 1,
});
// 加载loding
wx.request({
url: app.get_request_url("index", "navigation"),
method: "POST",
data: {},
dataType: "json",
header: { 'content-type': 'application/x-www-form-urlencoded' },
success: res => {
if (res.data.code == 0) {
var data = res.data.data;
this.setData({
data_list: data,
data_list_loding_status: data.length == 0 ? 0 : 3,
data_bottom_line_status: true,
});
} else {
this.setData({
data_list_loding_status: 0,
data_bottom_line_status: true,
});
wx.showToast({
type: "fail",
content: res.data.msg
});
}
},
fail: () => {
this.setData({
data_list_loding_status: 2,
data_bottom_line_status: true,
});
wx.showToast({
type: "fail",
content: "服务器请求出错"
});
}
});
},
// 操作事件
nav_event(e) {
app.operation_event(e);
},
}
});
{
"component": true
}
\ No newline at end of file
<view wx:if="{{data_list.length > 0}}">
<view class="data-list bg-white spacing-mb">
<view class="items" wx:for="{{data_list}}">
<view class="items-content tc" style="background-color:{{item.bg_color}}" data-value="{{item.event_value}}" data-type="{{item.event_type}}" bindtap="nav_event">
<image class="wh-auto" src="{{item.images_url}}" mode="aspectFit" />
</view>
<view class="title tc single-text">{{item.name}}</view>
</view>
</view>
</view>
<view wx:if="{{data_list_loding_status == 2}}">
<import src="/pages/common/nodata.wxml" />
<template is="nodata" data="{{status: data_list_loding_status}}"></template>
</view>
.data-list {
overflow: hidden;
}
.data-list .items {
width: calc(25% - 60rpx);
float: left;
padding: 30rpx;
}
.items-content {
border-radius: 50%;
padding: 20rpx;
}
.data-list .items image {
width: 80rpx !important;
height: 80rpx !important;
}
.data-list .items .title {
margin-top: 10rpx;
font-size: 32rpx;
}
\ No newline at end of file
## 0.4.3
`2018-11-07`
- **Enhancement**
- `tabs`新增`tabBarCls`tabBar自定义样式class
- `tabs`新增`duration`控制滑动动画时长
- `calendar`date参数兼容IOS格式要求
## 0.4.2
`2018-10-31`
- **Enhancement**
- `amount-input`组件type属性新增`digit`类型
- `vtabs`新增`activeTab``onTabClick``onChange`属性([#125](https://github.com/ant-mini-program/mini-antui/issues/125))
## 0.4.1
`2018-10-29`
- **Enhancement**
- `notice`新增`enableMarquee``marqueeProps`属性([#140](https://github.com/ant-mini-program/mini-antui/issues/140))
- **Bug Fix**
- 修复`message`type为`fail`时的白屏问题([#152](https://github.com/ant-mini-program/mini-antui/issues/152))
## 0.4.0
`2018-10-23`
- **Feature**
- 新增`am-checkbox`组件
- 新增`badge`组件
- **Enhancement**
- `calendar`组件`tabs`属性新增`disable`字段,新增`onSelectHasDisableDat`属性([#108](https://github.com/ant-mini-program/mini-antui/issues/108))
- **Bug Fix**
- 修复`vtabs`在安卓下出现滚动误差的问题
- 修复`tabs``tabs`属性变化时没有重新计算宽度导致的滚动不正常问题
## 0.3.13
`2018-10-18`
- **Bug Fix**
- 修复`swipe-action`在didUpdate时陷入死循环的问题
- 修复`vtabs`tabs数据变化没有响应的问题
## 0.3.12
`2018-10-12`
- **Enhancement**
- `vtabs`新增`badgeType``badgeText`属性([#92](https://github.com/ant-mini-program/mini-antui/issues/92))
## 0.3.11
`2018-10-10`
- **Bug Fix**
- 修复`search-bar`在IPhone X下面出现滚动的问题([#113](https://github.com/ant-mini-program/mini-antui/issues/113))
- 修复`stepper`在重置初始值时操作按钮状态不改变的bug([#111](https://github.com/ant-mini-program/mini-antui/issues/111))
- **Enhancement**
- `page-result`图标升级到最新版本
- `input-item`增大清除icon点击响应范围
## 0.3.10
`2018-10-08`
- **Enhancement**
- 解决`list``input-item`在安卓下线条较粗的问题
## 0.3.9
`2018-09-27`
- **Bug Fix**
- 修复`input-item`在失去焦点时清除按钮仍旧显示的问题
## 0.3.8
`2018-09-26`
- **Bug Fix**
- 修复`filter`组件单选时需要反选取消选择的问题
- **Feature**
- 新增`picker-item`组件
- **Enhancement**
- `tabs`新增`activeCls`属性,用来表示激活tabbar的自定义class([#87](https://github.com/ant-mini-program/mini-antui/issues/87))
- `input-item`新增`clear``onClear`属性,组件内支持清除输入功能([#84](https://github.com/ant-mini-program/mini-antui/issues/84))
- `list-item` onClick回调新增target参数,用来支持自定义dataset([#85](https://github.com/ant-mini-program/mini-antui/issues/85))
## 0.3.7
`2018-09-25`
- **Bug Fix**
- 修复了`input-item`组件在失去焦点等事件中无dataset的问题([#66](https://github.com/ant-mini-program/mini-antui/issues/66))
- 修复`popup`组件mask定位为absolut导致的页面滚动时mask跟着滚动的bug
- **Enhancement**
- `popup`新增disableScroll属性以适应不同业务场景
- 完善`swipe-action`的示例代码
- 文档更新,添加体验二维码
## 0.3.6
`2018-09-13`
- **Enhancement**
- 新增tips组件的类型
## 0.3.5
`2018-08-29`
- **Bug Fix**
- 修复`search-bar`点击icon无效的bug
- 修复`search-bar`苹果输入法中间态无法清除placeholder的bug
- **Enhancement**
- 优化`list`组件样式
## 0.3.4
`2018-08-16`
- **Enhancement**
- 优化`tabs`组件闪烁问题
- `face-detection`组件增加最小旋转角度属性
## 0.3.3
`2018-08-10`
- **Feature**
- `tabs`组件新增`activeTab`属性,用来指定当前激活tab
## 0.3.2
`2018-08-07`
- **Feature**
- 新增`popup`弹出菜单组件
- `face-detection`组件新增活体检测功能
## 0.3.1
`2018-07-27`
- **Feature**
- `face-detection`组件新增`appName``serviceName`字段
## 0.3.0
`2018-07-26`
- **Feature**
- 新增`face-detection`组件
- 新增`footer`组件
- `page-result`组件增加slot,方便开发者个性化定制区域内容
- **Enhancement**
- 优化`calendar`组件在初次渲染时的闪烁问题
- 优化`swipe-action`右侧按钮宽度自适应文本内容
## 0.2.0
`2018-07-11`
- **Feature**
- 新增`vtab组件`
- **Enhancement**
- 优化`swipe-action`组件性能
- 解决`tabs`组件在初次渲染时的页面闪烁问题
## 0.1.0
`2018-06-21`
- **Feature**
- 新增`steps``popover``amount-input``calendar`组件;
- `tabs`组件`tabs`属性新增`badgeType`属性、新增`showPlus``onPlusClick`属性
- `modal`组件新增`closeType`属性,以适应不同的背景颜色
- **Bug Fix**
- 修复`grid``modal``input-item`组件样式问题
## 0.0.13
`2018-05-09`
首次发布小程序版antui组件库
MIT LICENSE
Copyright (c) 2018-present Alipay.com, https://www.alipay.com/
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
<p align="center">
<img width="320" src="https://gw.alipayobjects.com/zos/rmsportal/CsCzHzlOkLDKyyRadsdD.png">
</p>
# mini-antui
## 链接
- [mini-antui官网文档](https://docs.alipay.com/mini/component-ext/overview-ext-common)
- [支付宝小程序](https://mini.open.alipay.com/channel/miniIndex.htm)
- [开发工具](https://docs.alipay.com/mini/ide/overview)
## 特性
- 基于`Advance Design`设计规范
- 使用[支付宝小程序](https://mini.open.alipay.com/channel/miniIndex.htm)开发
## 预览
[小程序开发者工具](https://docs.alipay.com/mini/ide/overview)打开项目
## 安装
```bash
$ npm install mini-antui --save
```
## 使用
在页面json中文件中进行注册,如card组件的注册如下所示:
```json
{
"usingComponents": {
"card": "mini-antui/es/card/index",
}
}
```
在axml文件中进行调用:
```html
<card
thumb="{{thumb}}"
title="卡片标题2"
subTitle="副标题非必填2"
onClick="onCardClick"
info="点击了第二个card"
/>
```
## 贡献
如果你有好的意见或建议,欢迎给我们提[issue](https://github.com/ant-mini-program/mini-antui/issues)
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
export default function fmtEvent(props, e) {
var dataset = {};
for (var key in props) {
if (/data-/gi.test(key)) {
dataset[key.replace(/data-/gi, '')] = props[key];
}
}
return _extends({}, e, {
currentTarget: { dataset: dataset },
target: { dataset: dataset, targetDataset: dataset }
});
}
\ No newline at end of file
.am-checkbox {
position: relative;
height: 22px;
width: 22px;
display: inline-block;
}
.am-checkbox-value {
position: absolute;
z-index: 1;
border-radius: 50%;
opacity: 0;
}
.am-checkbox-synthetic {
position: absolute;
z-index: 2;
pointer-events: none;
top: 0;
left: 0;
border-radius: 50%;
height: 100%;
width: 100%;
}
.am-checkbox-synthetic::before {
position: absolute;
left: 0;
top: 0;
height: 200%;
width: 200%;
display: block;
box-sizing: border-box;
border-radius: 50%;
content: '';
transform-origin: 0 0;
transform: scale(0.5);
border: 1px solid #c9c9c9;
}
.am-checkbox-value.a-checkbox-checked + .am-checkbox-synthetic::before {
background-color: #108ee9;
border-color: #108ee9;
border-width: 0;
}
.am-checkbox-value.a-checkbox-checked + .am-checkbox-synthetic::after {
position: absolute;
display: block;
z-index: 999;
content: '';
top: 4px;
right: 8px;
width: 5px;
height: 10px;
border: 2px solid #fff;
border-width: 0 1px 1px 0;
transform: rotate(45deg);
}
.am-checkbox-value.a-checkbox-disabled + .am-checkbox-synthetic::before {
border: 1px solid #ccc;
background-color: #e1e1e1;
}
.am-checkbox-value.a-checkbox-disabled + .am-checkbox-synthetic::after {
border-color: #adadad;
}
\ No newline at end of file
<view class="am-checkbox">
<checkbox
class="am-checkbox-value"
value="{{value}}"
checked="{{checked}}"
disabled="{{disabled}}"
onChange="onChange"
id="{{id}}"
/>
<view class="am-checkbox-synthetic"></view>
</view>
\ No newline at end of file
import fmtEvent from '../_util/fmtEvent';
Component({
props: {
value: '',
checked: false,
disabled: false,
onChange: function onChange() {},
id: ''
},
methods: {
onChange: function onChange(e) {
var event = fmtEvent(this.props, e);
this.props.onChange(event);
}
}
});
\ No newline at end of file
.am-amount {
box-sizing: border-box;
height: 173px;
width: 100%;
padding: 16px;
background: #fff;
}
.am-amount-title {
height: 24px;
line-height: 24px;
color: #333;
font-size: 17px;
}
.am-amount-synthetic {
position: absolute;
top: 0;
left: 0;
display: flex;
}
.am-amount-input {
margin-top: 16px;
padding-bottom: 16px;
display: flex;
align-items: center;
width: 100%;
height: 48px;
position: relative;
line-height: 48px;
border-bottom: 1rpx solid #eee;
}
.am-amount-symbol {
width: 18px;
font-family: PingFang SC;
font-size: 30px;
color: #333;
}
.am-amount-placeholder {
margin-left: 6px;
color: #ccc;
font-size: 24px;
}
.am-amount-value {
padding: 0 0 0 24px;
box-sizing: border-box;
z-index: 2;
height: 48px;
line-height: 48px;
vertical-align: middle;
background-color: transparent;
font-size: 48px;
font-weight: 500;
}
.am-amount-clear {
visibility: hidden;
width: 28px;
height: 28px;
}
.am-amount-clear icon {
display: flex;
height: 100%;
justify-content: center;
align-items: center;
}
.am-amount-clear-show {
visibility: visible;
}
.am-amount-footer {
padding: 16px 0;
display: flex;
}
.am-amount-extra {
flex: 1;
height: 20px;
line-height: 20px;
color: #999;
font-size: 14px;
}
.am-amount-btn {
width: 120px;
text-align: right;
color: #108ee9;
font-size: 14px;
}
\ No newline at end of file
<view class="am-amount {{className}}">
<view class="am-amount-title">{{title}}</view>
<view class="am-amount-input">
<view class="am-amount-synthetic">
<text class="am-amount-symbol">¥</text>
<text class="am-amount-placeholder" style="{{ visibility: value.length == 0 ? 'visible': 'hidden'}}">{{placeholder}}</text>
</view>
<input
type="{{type === 'digit' ? 'digit' : 'number'}}"
maxlength="{{maxLength}}"
class="am-amount-value"
value="{{value}}"
focus="{{focus}}"
onInput="onInput"
onConfirm="onConfirm"
onFocus="onFocus"
onBlur="onBlur" />
<view class="am-amount-clear {{ value.length > 0 && _focus ? 'am-amount-clear-show' : '' }}" onTap="onClearTap">
<icon type="clear" size="22" />
</view>
</view>
<view class="am-amount-footer">
<text class="am-amount-extra">{{extra}}</text>
<view class="am-amount-btn" onTap="onButtonClick">{{btnText}}</view>
</view>
</view>
\ No newline at end of file
import fmtEvent from '../_util/fmtEvent';
Component({
props: {
type: 'number',
className: '',
focus: false,
placeholder: '',
value: ''
},
data: {
_focus: false
},
methods: {
onInput: function onInput(e) {
var event = fmtEvent(this.props, e);
if (this.props.onInput) {
this.props.onInput(event);
}
},
onConfirm: function onConfirm(e) {
var event = fmtEvent(this.props, e);
if (this.props.onConfirm) {
this.props.onConfirm(event);
}
},
onButtonClick: function onButtonClick() {
if (this.onButtonClick) {
this.props.onButtonClick();
}
},
onFocus: function onFocus(e) {
this.setData({
_focus: true
});
var event = fmtEvent(this.props, e);
if (this.props.onFocus) {
this.props.onFocus(event);
}
},
onBlur: function onBlur(e) {
this.setData({
_focus: false
});
var event = fmtEvent(this.props, e);
if (this.props.onBlur) {
this.props.onBlur(event);
}
},
onClearTap: function onClearTap() {
if (this.props.onClear) {
this.props.onClear('');
}
}
}
});
\ No newline at end of file
.am-badge {
display: inline-block;
position: relative;
vertical-align: middle;
line-height: 1;
}
.am-badge-text {
display: inline-block;
position: absolute;
right: 0;
transform: translate(50%, -50%);
top: 0px;
min-width: 16px;
padding: 0;
height: 16px;
line-height: 16px;
text-align: center;
background-color: #FF3B30;
border-radius: 16px;
color: #fff;
font-size: 10px;
}
.am-badge-text.am-badge-double {
padding: 0 4px;
}
.am-badge-not-a-wrapper .am-badge-text {
position: relative;
top: auto;
right: auto;
transform: translateX(0);
}
.am-badge-text.is-dot {
padding: 0;
width: 10px;
min-width: 10px;
height: 10px;
}
<view class="am-badge {{className}} {{!$slots.inner ? 'am-badge-not-a-wrapper' : ''}}">
<view
class="am-badge-text
{{ text.toString().length > 1 ? 'am-badge-double' : ''}}"
a:if="{{!dot}}">
<text>{{typeof text === 'number' && text > overflowCount ? overflowCount + '+' : text }}</text>
</view>
<view class="am-badge-text is-dot" a:if="{{dot}}"></view>
<slot name="inner" />
</view>
\ No newline at end of file
Component({
props: {
className: '',
overflowCount: 99,
text: '',
dot: false
}
});
\ No newline at end of file
.am-calendar {
background-color: #fff;
padding-top: 10px;
}
.am-calendar-months {
display: flex;
box-sizing: border-box;
padding: 0 26px;
align-items: center;
height: 28px;
}
.am-calendar-prev-month,
.am-calendar-next-month {
display: flex;
width: 40px;
font-size: 20px;
}
.am-calendar-prev-month {
justify-content: flex-start;
}
.am-calendar-next-month {
justify-content: flex-end;
}
.am-calendar-arrow {
height: 28px;
width: 12px;
background-image: url('https://gw.alipayobjects.com/zos/rmsportal/vYcMhkfyHRIOeVXWdcPe.png');
background-size: 8px 14px;
background-position: left center;
background-repeat: no-repeat;
}
.am-calendar-arrow.next {
transform: rotate(180deg);
}
.am-calendar-selected-month {
flex: 1;
text-align: center;
font-size: 20px;
font-weight: 600;
color: #333;
}
.am-calendar-days {
display: flex;
padding: 14px 10px 9px;
border-bottom: 1rpx solid #eee;
height: 20px;
line-height: 20px;
}
.am-calendar-day {
flex: 1;
text-align: center;
color: #333;
font-size: 14px;
}
.am-calendar-dates {
display: flex;
flex-direction: column;
}
.am-calendar-week {
margin-bottom: 17px;
display: flex;
flex-direction: row;
padding: 0 10px;
}
.am-calendar-week:first-child {
margin-top: 12px;
}
.am-calendar-date-wrap {
position: relative;
text-align: center;
display: flex;
flex-direction: column;
align-items: center;
height: 42px;
flex: 1;
}
.am-calendar-date {
text-align: center;
height: 23px;
line-height: 23px;
font-size: 19px;
font-family: 'Helvetica';
color: #333;
}
.am-calendar-tag {
position: absolute;
top: 21px;
width: 42px;
overflow: hidden;
text-overflow: hidden;
white-space: nowrap;
color: #f5a623;
font-size: 10px;
font-weight: 500;
}
.am-calendar-today {
color: #108ee9;
}
.am-calendar-gray {
color: #ccc;
}
.am-calendar-selected .am-calendar-block {
position: absolute;
left: calc(50% - 21px);
top: calc(50% - 10px);
transform: translateY(-50%);
width: 42px;
height: 42px;
background: #309EF2;
border-radius: 2px;
}
.am-calendar-middle.is-range .am-calendar-block {
position: absolute;
left: 0;
top: calc(50% - 10px);
transform: translateY(-50%);
height: 42px;
background: #309EF2;
width: 100%;
border-radius: 0;
}
.am-calendar-start.is-range .am-calendar-block {
position: absolute;
left: calc(50% - 21px);
top: calc(50% - 10px);
transform: translateY(-50%);
width: 100%;
height: 42px;
background: #309EF2;
border-radius: 2px 0 0 2px;
}
.am-calendar-end.is-range .am-calendar-block {
position: absolute;
left: 0;
top: calc(50% - 10px);
transform: translateY(-50%);
width: calc(50% + 21px);
height: 42px;
background: #309EF2;
border-radius: 0 2px 2px 0;
}
.am-calendar-selected .am-calendar-block.has-tag,
.am-calendar-start .am-calendar-block.has-tag,
.am-calendar-middle .am-calendar-block.has-tag,
.am-calendar-end .am-calendar-block.has-tag {
top: calc(50% - 7px);
}
.am-calendar-selected .am-calendar-date,
.am-calendar-start .am-calendar-date,
.am-calendar-middle .am-calendar-date,
.am-calendar-end .am-calendar-date {
position: relative;
color: #fff;
}
.am-calendar-selected .am-calendar-tag,
.am-calendar-start .am-calendar-tag,
.am-calendar-middle .am-calendar-tag,
.am-calendar-end .am-calendar-tag {
color: #fff;
}
.am-calendar-disable .am-calendar-date {
color: #999;
}
\ No newline at end of file
<view class="am-calendar {{className}}" a:if="{{dates.length > 0}}">
<view class="am-calendar-months">
<view class="am-calendar-prev-month" onTap="onPrevMonthTap">
<view class="am-calendar-arrow"></view>
</view>
<view class="am-calendar-selected-month">{{selectedYear}}年{{selectedMonth + 1}}月</view>
<view class="am-calendar-next-month" onTap="onNextMonthTap">
<view class="am-calendar-arrow next"></view>
</view>
</view>
<view class="am-calendar-days">
<block a:for="{{['日', '一', '二', '三', '四', '五', '六']}}">
<view class="am-calendar-day">{{item}}</view>
</block>
</view>
<view class="am-calendar-dates">
<block a:for="{{dates}}">
<view class="am-calendar-week">
<block a:for="{{item}}">
<view
class="am-calendar-date-wrap
{{ item.isSelected ? 'am-calendar-selected': '' }}
{{ item.isStart ? 'am-calendar-start': '' }}
{{ item.isMiddle ? 'am-calendar-middle': '' }}
{{ item.isEnd ? 'am-calendar-end': '' }}
{{ item.disable ? 'am-calendar-disable': '' }}
{{ type === 'range' ? 'is-range' : '' }}"
data-year="{{item.year}}"
data-month="{{item.month}}"
data-date="{{item.date}}"
onTap="onDateTap"
>
<view
class="am-calendar-block {{ blockType === 2 ? 'has-tag': '' }}"
></view>
<view
class="am-calendar-date {{ item.isGray ? 'am-calendar-gray': '' }} {{ item.isToday ? 'am-calendar-today': ''}}"
>{{item.date}}</view>
<view class="am-calendar-tag" style="{{
color: item.isSelected || item.isMiddle || item.isStart || item.isEnd ? '#fff' : (item.disable ? '#999' : item.color)
}}">{{item.disable ? 'disable' : item.tag}}</view>
</view>
</block>
</view>
</block>
</view>
</view>
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
/* eslint-disable complexity, no-param-reassign */
/* eslint max-depth: [2, 7] */
var leapYear = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
var commonYear = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
var FIRST_MONTH = 0;
var LAST_MONTH = 11;
var DAYS_PER_ROW = 7;
var COLOR_MAP = {
1: '#f5a911',
2: '#e8541e',
3: '#07a89b',
4: '#108ee9',
5: 'rgba(51, 51, 51, 0.4)'
};
// 获取某月第某天是星期几
function getDay(month, year, index) {
return new Date(year, month, index).getDay();
}
// 获取某月有几天
function getMonthLength(month, year) {
if (year % 400 === 0 || year % 100 !== 0 && year % 4 === 0) {
return leapYear[month];
} else {
return commonYear[month];
}
}
// 数字补位 1 -> 01
function prefixNum(num) {
if (num < 10) {
return '0' + num;
} else {
return '' + num;
}
}
Component({
data: {
selectedYear: 0,
selectedMonth: 0,
currentDate: null,
dates: [],
blockType: 1 // 1.没有待办纯数字 2.有待办 用于区分不同类型日期块的样式。
},
props: {
className: '',
tagData: [],
type: 'single'
},
didMount: function didMount() {
this.tapTimes = 1;
var date = new Date();
date.setHours(0);
date.setMinutes(0);
date.setSeconds(0);
date.setMilliseconds(0);
var year = date.getFullYear();
var month = date.getMonth();
this.setData({
selectedYear: year,
selectedMonth: month,
currentDate: date
});
this.refreshdates(month, year);
},
didUpdate: function didUpdate() {
var dates = this.data.dates;
var blockType = 1;
for (var i = 0; i < dates.length; i++) {
for (var j = 0; j < dates[i].length; j++) {
if (this.hasTag(dates[i][j])) {
blockType = 2;
}
}
}
this.setData({
dates: dates,
blockType: blockType
});
},
methods: {
onPrevMonthTap: function onPrevMonthTap() {
var _data = this.data,
selectedMonth = _data.selectedMonth,
selectedYear = _data.selectedYear;
var year = selectedYear;
var month = selectedMonth;
// 如果当前选中是一月份,前一月是去年的12月
if (selectedMonth === FIRST_MONTH) {
year = selectedYear - 1;
month = LAST_MONTH;
} else {
month = selectedMonth - 1;
}
if (this.props.onMonthChange) {
this.props.onMonthChange(month, selectedMonth);
}
this.setData({
selectedYear: year,
selectedMonth: month
});
this.refreshdates(month, year);
},
onNextMonthTap: function onNextMonthTap() {
var _data2 = this.data,
selectedMonth = _data2.selectedMonth,
selectedYear = _data2.selectedYear;
var year = selectedYear;
var month = selectedMonth;
// 如果当前选中是十二月份,下一月是去年的12月
if (selectedMonth === LAST_MONTH) {
year = selectedYear + 1;
month = FIRST_MONTH;
} else {
month = selectedMonth + 1;
}
if (this.props.onMonthChange) {
this.props.onMonthChange(month, selectedMonth);
}
this.setData({
selectedYear: year,
selectedMonth: month
});
this.refreshdates(month, year);
},
refreshdates: function refreshdates(month, year) {
this.tapTimes = 1;
var _data3 = this.data,
selectedYear = _data3.selectedYear,
selectedMonth = _data3.selectedMonth,
currentDate = _data3.currentDate;
var firstDay = getDay(month, year, 1);
var days = getMonthLength(month, year);
var datesArray = [];
var currentDateTimeStamp = +currentDate;
var num = 0;
for (var i = 0; i < firstDay; i++) {
num += 1;
// 如果当前选中的是一月份,前一个月是去年的12月
var _year = selectedYear;
var _month = selectedMonth;
if (selectedMonth === 0) {
_year = selectedYear - 1;
_month = LAST_MONTH;
} else {
_year = selectedYear;
_month = selectedMonth - 1;
}
var date = getMonthLength(_month, _year) - i;
datesArray.unshift({
year: _year,
month: _month,
date: date,
isToday: false,
isGray: true,
isSelected: false,
tag: ''
});
}
for (var _i = 0; _i < days; _i++) {
num += 1;
var _date = _i + 1;
var dateTimeStamp = +new Date(selectedYear, selectedMonth, _date);
datesArray.push({
year: selectedYear,
month: selectedMonth,
date: _date,
isToday: dateTimeStamp === currentDateTimeStamp,
isGray: false,
isSelected: dateTimeStamp === currentDateTimeStamp,
tag: ''
});
}
var nextDate = 0;
var daysPerPage = 35;
if (num > 35) {
daysPerPage = 42;
}
for (var _i2 = 0; _i2 < daysPerPage - days - firstDay; _i2++) {
// 如果是12月,下月是第二年的1月份
nextDate += 1;
var _year2 = selectedYear;
var _month2 = selectedMonth;
if (selectedMonth === LAST_MONTH) {
_year2 = selectedYear + 1;
_month2 = FIRST_MONTH;
} else {
_year2 = selectedYear;
_month2 = selectedMonth + 1;
}
datesArray.push({
year: _year2,
month: _month2,
date: nextDate,
isToday: false,
isGray: true,
isSelected: false,
tag: ''
});
}
var blockType = 1;
for (var _i3 = 0; _i3 < datesArray.length; _i3++) {
if (this.hasTag(datesArray[_i3])) {
blockType = 2;
}
}
var dates = [];
var weekDates = [];
for (var _i4 = 0; _i4 < datesArray.length; _i4++) {
weekDates.push(datesArray[_i4]);
if ((_i4 + 1) % DAYS_PER_ROW === 0) {
dates.push([].concat(_toConsumableArray(weekDates)));
weekDates = [];
}
}
this.setData({
dates: dates,
blockType: blockType
});
},
hasTag: function hasTag(dateObj) {
var tagData = this.props.tagData;
// 去重由调用者处理
if (tagData.length === 0) {
dateObj.tag = '';
return false;
}
return tagData.some(function (item) {
var dateArr = item.date.split('-');
var dateStr = [];
// 兼容ios下new Date('2018-1-1')格式返回invalid Date的问题
for (var i = 0; i < dateArr.length; i++) {
dateStr.push(dateArr[i].length > 1 ? dateArr[i] : '0' + dateArr[i]);
}
var date = new Date(dateStr.join('-'));
if (dateObj.year === date.getFullYear() && dateObj.month === date.getMonth() && dateObj.date === date.getDate()) {
dateObj.tag = item.tag;
dateObj.color = COLOR_MAP[item.tagColor];
dateObj.disable = item.disable;
return true;
} else {
dateObj.tag = '';
return false;
}
});
},
getDateGap: function getDateGap(day1, day2) {
var date1 = +new Date(day1.year, prefixNum(day1.month), prefixNum(day1.date));
var date2 = +new Date(day2.year, prefixNum(day2.month), prefixNum(day2.date));
return (date1 - date2) / (24 * 3600 * 1000);
},
makeDate: function makeDate(dateObj) {
return new Date(dateObj.year + '-' + prefixNum(dateObj.month + 1) + '-' + prefixNum(dateObj.date));
},
onDateTap: function onDateTap(event) {
var dates = this.data.dates;
var _event$currentTarget$ = event.currentTarget.dataset,
year = _event$currentTarget$.year,
month = _event$currentTarget$.month,
date = _event$currentTarget$.date;
var type = this.props.type;
if (type === 'range') {
if (this.tapTimes % 2 === 0) {
this.tapTimes += 1;
this.endDate = { year: year, month: month, date: date };
var dateGap = this.getDateGap(this.startDate, this.endDate);
if (dateGap > 0) {
var _ref = [this.endDate, this.startDate];
this.startDate = _ref[0];
this.endDate = _ref[1];
}
var hasDisable = false;
for (var i = 0; i < dates.length; i++) {
for (var j = 0; j < dates[i].length; j++) {
var dateObj = dates[i][j];
dateObj.isStart = false;
dateObj.isMiddle = false;
dateObj.isEnd = false;
var startDateGap = this.getDateGap(dateObj, this.startDate);
var endDateGap = this.getDateGap(dateObj, this.endDate);
if (dateObj.year === year && dateObj.month === month && dateObj.date === date && dateObj.disable) {
hasDisable = true;
}
if (startDateGap > 0 && endDateGap < 0) {
if (dateObj.disable) {
hasDisable = true;
}
if (dateGap !== 0) {
if (j === 0) {
dateObj.isStart = true;
} else if (j === 6) {
dateObj.isEnd = true;
} else {
dateObj.isMiddle = true;
}
} else {
dateObj.isSelected = true;
}
}
if (this.startDate.year === dateObj.year && this.startDate.month === dateObj.month && this.startDate.date === dateObj.date && dateGap !== 0) {
if (j === 6) {
dateObj.isSelected = true;
} else {
dateObj.isStart = true;
}
}
if (this.endDate.year === dateObj.year && this.endDate.month === dateObj.month && this.endDate.date === dateObj.date && dateGap !== 0) {
if (j === 0) {
dateObj.isSelected = true;
} else {
dateObj.isEnd = true;
}
}
}
}
if (hasDisable) {
this.props.onSelectHasDisableDate([this.makeDate(this.startDate), this.makeDate(this.endDate)]);
return;
}
if (this.props.onSelect) {
this.props.onSelect([this.makeDate(this.startDate), this.makeDate(this.endDate)]);
}
} else {
var isDisable = false;
for (var _i5 = 0; _i5 < dates.length; _i5++) {
for (var _j = 0; _j < dates[_i5].length; _j++) {
var _dateObj = dates[_i5][_j];
if (_dateObj.year === year && _dateObj.month === month && _dateObj.date === date) {
if (_dateObj.disable) {
console.log(1111);
isDisable = true;
_dateObj.isSelected = false;
} else {
_dateObj.isSelected = true;
}
_dateObj.isStart = false;
_dateObj.isMiddle = false;
_dateObj.isEnd = false;
} else {
_dateObj.isSelected = false;
_dateObj.isStart = false;
_dateObj.isMiddle = false;
_dateObj.isEnd = false;
}
}
}
if (!isDisable) {
this.tapTimes += 1;
}
this.startDate = { year: year, month: month, date: date };
}
this.setData({
dates: dates
});
} else {
var _isDisable = false;
for (var _i6 = 0; _i6 < dates.length; _i6++) {
for (var _j2 = 0; _j2 < dates[_i6].length; _j2++) {
var _dateObj2 = dates[_i6][_j2];
if (_dateObj2.year === year && _dateObj2.month === month && _dateObj2.date === date) {
_dateObj2.isSelected = true;
if (_dateObj2.disable) {
_isDisable = true;
}
} else {
_dateObj2.isSelected = false;
}
}
}
if (_isDisable) {
return;
}
this.setData({
dates: dates
});
if (this.props.onSelect) {
this.props.onSelect([this.makeDate({ year: year, month: month, date: date }), undefined]);
}
}
}
}
});
\ No newline at end of file
.am-card {
display: flex;
background-color: #fff;
border-radius: 4px;
margin: 6px 10px;
align-items: center;
min-height: 81px;
flex-direction: column;
padding: 0 16px;
}
.am-card.am-card-active {
background: #D9D9D9;
}
.am-card-body {
display: flex;
align-items: center;
width: 100%;
padding: 16px 0;
}
.am-card-content {
flex: 1;
min-width: 100px;
}
.am-card-title {
font-size: 18px;
line-height: 25px;
color: #333;
margin-bottom: 4px;
}
.am-card-subtitle {
font-size: 14px;
line-height: 20px;
color: #999;
margin-bottom: 2px;
}
.am-card-thumb {
margin-right: 10px;
width: 48px;
height: 48px;
border-radius: 2px;
}
.am-card-arrow {
width: 13px;
height: 13px;
background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAaCAYAAAC+aNwHAAAAkElEQVR4AWJwL/BhAJRWByYAgkAUhmdpkDZxlJZqD9UpXCPyBUTEga9+4IkI94F1XaWUTdH+a67inPOhjP2OgD+IFoTcm1GY3khrbfGAGFG6kBmAkPCw1rq6iBYb0VkEzJD+hHQWAz6iJBtQdP8YiQEbUQNiAF0BP0T+Gnkj8VbmHxMq5gOFjzQ+VPlYxz+WEyrVzhdMcxADAAAAAElFTkSuQmCC") center center no-repeat;
background-size: 8px 13px;
}
.am-card-footer {
display: flex;
width: 100%;
align-items: center;
border-top: 1rpx solid #eee;
padding: 10px 0;
margin: -4px 0 0;
font-size: 14px;
line-height: 20px;
color: #999;
}
.am-card-footer image {
width: 14px;
height: 14px;
margin-right: 4px;
}
<view
class="am-card"
hover-class="am-card-active"
onTap="onCardClick"
>
<view class="am-card-body">
<image a:if="{{thumb}}" src="{{thumb}}" class="am-card-thumb" />
<view class="am-card-content">
<view a:if="{{!thumb || (thumb && footer)}}" class="am-card-title">{{title}}</view>
<view class="am-card-subtitle">{{subTitle}}</view>
<view a:if="{{!footer && thumb}}" class="am-card-title">{{title}}</view>
</view>
<view class="am-card-arrow" aria-hidden="true" />
</view>
<view a:if="{{footer}}" class="am-card-footer">
<image a:if="{{footerImg}}" src="{{footerImg}}" />
{{footer}}
</view>
</view>
Component({
props: {
title: '',
onClick: function onClick() {},
info: ''
},
methods: {
onCardClick: function onCardClick() {
var _props = this.props,
info = _props.info,
onClick = _props.onClick;
onClick({ info: info });
}
}
});
\ No newline at end of file
<web-view
a:if="{{appName && serviceName}}"
src="https://render.alipay.com/p/s/tiny-webar-online/www/faceDetect.html?facing={{facing}}&appName={{appName}}&serviceName={{serviceName}}&useLiveFaceCheck={{useLiveFaceCheck}}&resignSuccessBtnText={{btnText}}"
id="am-face-detection"
onMessage="onMessage"
enableWK="{{false}}"
/>
<view a:else style="color: red; text-align: center; font-size: 14px; padding: 10px">appName and serviceName is required</view>
\ No newline at end of file
Component({
props: {
facing: 'front',
appName: '',
serviceName: '',
useLiveFaceCheck: false,
minRotate: -1
},
didMount: function didMount() {
this.webViewContext = wx.createWebViewContext('am-face-detection');
this.doFaceLeftResolve = null;
this.isDidFaceLeftResolve = false;
this.doFaceRightResolve = null;
this.isDidFaceRightResolve = false;
},
didUnMount: function didUnMount() {
this.webViewContext.postMessage({ action: 'releaseCamera' });
},
methods: {
doLeftFaceCheck: function doLeftFaceCheck() {
var _this = this;
return new Promise(function (resolve, reject) {
_this.isDidFaceLeftResolve = false;
_this.webViewContext.postMessage({ action: 'doFaceLeft', data: { minRotate: _this.props.minRotate } });
_this.doFaceLeftResolve = resolve;
setTimeout(function () {
if (!_this.isDidFaceLeftResolve) {
reject();
}
}, 30000);
});
},
doRightFaceCheck: function doRightFaceCheck() {
var _this2 = this;
return new Promise(function (resolve, reject) {
_this2.isDidFaceRightResolve = false;
_this2.webViewContext.postMessage({ action: 'doFaceRight', data: { minRotate: _this2.props.minRotate } });
_this2.doFaceRightResolve = resolve;
setTimeout(function () {
if (!_this2.isDidFaceRightResolve) {
reject();
}
}, 30000);
});
},
onMessage: function onMessage(e) {
var _this3 = this;
var _props = this.props,
onFaceStatusChange = _props.onFaceStatusChange,
onFail = _props.onFail,
onSuccessBtnTap = _props.onSuccessBtnTap;
var _e$detail = e.detail,
action = _e$detail.action,
data = _e$detail.data;
if (action === 'resignSuccessBtnClick') {
if (onSuccessBtnTap) {
onSuccessBtnTap();
}
}
if (action === 'faceRotated' && data.forward === 'left') {
this.isDidFaceLeftResolve = true;
this.doFaceLeftResolve(data.imageBase64);
return;
}
if (action === 'faceRotated' && data.forward === 'right') {
this.isDidFaceRightResolve = true;
this.doFaceRightResolve(data.imageBase64);
return;
}
if (action === 'captureImage') {
if (onFaceStatusChange) {
var promise = onFaceStatusChange({
imageBase64: data.imageBase64,
faceRect: data.faceRect
}, {
doLeftFaceCheck: this.doLeftFaceCheck.bind(this),
doRightFaceCheck: this.doRightFaceCheck.bind(this)
});
if (promise instanceof Promise) {
promise.then(function () {
_this3.webViewContext.postMessage({ action: 'requestSuccess' });
})['catch'](function () {
_this3.webViewContext.postMessage({ action: 'requestFailure' });
});
} else {
this.webViewContext.postMessage({ action: 'requestSuccess' });
}
}
} else {
/* eslint-disable */
if (onFail) {
onFail({ code: data.code, message: data.message });
}
}
}
}
});
\ No newline at end of file
.am-filter-item-wrap {
padding: 7px 6px;
min-width: 33.3%;
max-width: 180px;
overflow: hidden;
float: left;
display: list-item;
box-sizing: border-box;
}
.am-filter-item {
font-size: 14px;
height: 36px;
line-height: 36px;
background: #f5f5f5;
border-radius: 2px;
text-align: center;
padding: 0 20px;
box-sizing: border-box;
}
.am-filter-click {
color: #108EE9;
background: #e1f2fe url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACYAAAAfCAYAAACLSL/LAAAEgElEQVRYhc2Xa0wcVRTH/2cXdi2F0pe29RWMNbHBpLWf2qQmWqma4Ftj1ZBqfcQYjUmlobESP2hDfTT9ILGaaEEECQ0qjy5uNgUDRGiatsG0JNpStaAujy6wsO+d2Xv8MDN3ZhekSHndZLObe+fO/Oac//nfs8TMWEyj3SvS3jnuLU5baBDrqL+kZO1p8JZf9sWeWjRgpWeit773o7fJH1HvAoBFAbbHM7rlSOeoK64kVhlzCwp2sl9QSYtvl+vXQBnANuvagoGd6FMdha7Bg+e90bdBABgAEUAABIMWoioru2PLi9xDNQPjyoMAAIOBWf6e94h90BFa/1Grzx2KifU6TfIFRADmGezFRv99VV3jjQnBmRKCoaXPGHrU5gWsY1DQfrfv9fbLkc/kpKErKxCg64zmHqz+kurc6/GV/u6Lv6pFyALALFOn0+mwcyz+I13R1cXNI3WjEXWb8dwkoUseAYD0b8xtKvf+FNxQemrsRFwVN0kRUWoQjAhKv5ArcwL2eK0/v/Fi+HtmdspUTZZCZg3IWgT6dbbJbjzT0dInbHcf9e1ruBh2MeBM0g+R/uSJn5wVaViXaTevI5o9sOrflIxdx4erfhlSPpQZMTJHeqpInySzJDetc+Dky2uxeqk96X6zksqDp6JrSzrGm4IxsTkZRE8RA6bOIFN5/21O1O28HllOm/kC+to1g73iCW/6+lzQk0iIG7SHUnLFGSPFKp7PXYLyx1bBYScMBBIYDCd0drr2qry3xv9MW2+sGiC7WVl6ytgSIcOf9AgWbsnEJ3nZICL0janI+2YIQyHTw2asMdefqv2Oo/4DbX8px0BklzoGmYZpzFm6BgLj8APZOLRjOYgIPcMK7ikfRM+IKkU/47Pyi24ls7gt+O1wWH1UEsgUWUAAXS/aT4edUPHICjybmwEA6B6KY0flFQyEdFOVkdbf7/84f9HP0Vs+PRPyxFTeICf1/SXbMlCQex0AoOJ8BO93BKEktLVl6UDd0yuxPccJADjtjeOh6isYiZhtjqlLbW7aYE82BLfW98TcDM5OhtJe08ZARX4mCnKXAADODigoaPRjLCrg3rkSG9ekAwDa+2J4uGYYgbgw9yfBaVqbFtjmqrHdXQPKV5jMkOVNARsYFfnLZOQiCmM0KnBjluZRnj+ieKJ2GBHVstey31rNU4Idu6CmF7YGDv0TSLx1VXrjKGFGRX6WjJwxfrgQwXN1o4iLVAhLNcr5Kezi47Ox7AOdoe8CMZF3VSgJBwgivNAUAAAJV9kdwW6XHwlhORKsp4O1N5uqKl9rjtxedi7crArOmTaU4fYMCEDCBeKMNzzjYCbT07QNgEhpX4nl8oRU5tWOb2/pUxrBvHTaUMZIqTCbDmn2WfiPFBpFIK2jX4rZ3SvozrKxN1t6480zggKSTZIIwnpoG3/NpBnD7DisZysRQLZWYmZ82a049rcHPveFxUszAkodk3apk3gWW6Jlin8ETtqY9m5nfM3h04G6qMJbZwUKmNgMSj6yCD2130c/QK1woAj7bv77X8e4TyVCc9zHAAAAAElFTkSuQmCC') right bottom no-repeat;
background-size: 17px 13px;
}
<view class="am-filter-item-wrap {{className}}" onTap="handleClick">
<view class="am-filter-item {{confirmStyle !=='' ? 'am-filter-click':''}}">{{value}}</view>
</view>
import lifecycle from '../mixins/lifecycle';
Component({
mixins: [lifecycle],
data: {
confirmStyle: ''
},
props: {
className: '',
item: '',
id: '',
value: '',
selected: false,
onChange: function onChange() {}
},
didMount: function didMount() {
var _data = this.data,
results = _data.results,
items = _data.items;
var _props = this.props,
selected = _props.selected,
id = _props.id,
value = _props.value;
if (selected) {
results.push({ id: id, value: value });
items.push(this);
this.setData({
confirmStyle: true
});
}
},
methods: {
handleClick: function handleClick() {
var _props2 = this.props,
id = _props2.id,
value = _props2.value,
onChange = _props2.onChange;
var confirmStyle = this.data.confirmStyle;
var _data2 = this.data,
results = _data2.results,
items = _data2.items,
commonProps = _data2.commonProps;
if (commonProps.max === 1) {
if (confirmStyle === '') {
items.forEach(function (element) {
element.setData({
confirmStyle: ''
});
});
results.splice(0, results.length);
confirmStyle = true;
results.push({ id: id, value: value });
items.push(this);
onChange(results);
}
this.setData({
confirmStyle: confirmStyle
});
return;
}
if (confirmStyle === '' && results.length < commonProps.max) {
confirmStyle = true;
results.push({ id: id, value: value });
items.push(this);
} else {
confirmStyle = '';
results.some(function (key, index) {
if (JSON.stringify(key) === JSON.stringify({ id: id, value: value })) {
results.splice(index, 1);
return true;
} else {
return false;
}
});
}
this.setData({
confirmStyle: confirmStyle
});
}
}
});
\ No newline at end of file
.am-filter-show {
height: 100vh;
display: block;
position: relative;
}
.am-filter-hide {
display: none;
}
.am-filter-mask, .am-filter-document {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.am-filter-mask {
background: rgba(0, 0, 0, 0.65);
}
.am-filter-content {
background: #ffffff;
display: flex;
flex-direction: column;
overflow-x: hidden;
overflow-y: scroll;
}
.am-filter-list {
flex: 1;
padding: 10px 5px 23px;
overflow-x: hidden;
min-height: 200px;
overflow-y: scroll;
max-height: 515px;
box-sizing: border-box;
}
.am-filter-btn {
width: 100%;
display: flex;
}
.am-filter-default, .am-filter-primary {
flex: 1;
height: 48px;
font-size: 18px;
box-sizing: border-box;
width: 50%;
border: 0;
border-radius: 0;
}
.am-filter-default {
border-top: 1px solid #eeeeee;
border-right: none;
}
<view class="am-filter-{{show ? 'show' : 'hide'}} {{className}}" disable-scroll="{{false}}">
<view class="am-filter-mask" />
<view class="am-filter-document">
<view class="am-filter-content" onChange="{{callBackFn}}">
<view class="am-filter-list">
<slot/>
</view>
<view class="am-filter-btn" a:if="{{max !== 1}}">
<button type="default" class="am-filter-default" onTap="resetFn">重置</button>
<button type="primary" class="am-filter-primary" onTap="confirmFn">确定</button>
</view>
</view>
</view>
</view>
import lifecycle from './mixins/lifecycle';
Component({
mixins: [lifecycle],
data: {
maxHeight: 0
},
props: {
className: '',
onChange: function onChange() {},
max: 10000
},
didMount: function didMount() {
var commonProps = this.data.commonProps;
var max = this.props.max;
commonProps.max = max;
},
methods: {
resetFn: function resetFn() {
var _data = this.data,
items = _data.items,
results = _data.results;
items.forEach(function (element) {
element.setData({
confirmStyle: ''
});
});
results.splice(0, results.length);
},
confirmFn: function confirmFn() {
var onChange = this.props.onChange;
var results = this.data.results;
onChange(results);
}
}
});
\ No newline at end of file
export default {
data: {
results: [],
items: [],
commonProps: {
max: 10000
}
},
didUnmount: function didUnmount() {
var _data = this.data,
items = _data.items,
results = _data.results;
results.splice(0, results.length);
items.splice(0, items.length);
}
};
\ No newline at end of file
.am-footer-links {
display: flex;
justify-content: center;
}
.am-footer-link {
height: 17px;
line-height: 17px;
color: #108ee9;
font-size: 12px;
}
.am-footer-link::after {
content: '|';
padding: 0 5px;
height: 17px;
color: #ccc;
}
.am-footer-link:last-child::after {
display: none;
}
.am-footer-copyright {
margin-top: 3px;
height: 17px;
line-height: 17px;
color: #ccc;
font-size: 14px;
text-align: center;
}
\ No newline at end of file
<view class="am-footer {{className}}">
<view class="am-footer-links" a:if="{{links && links.length > 0}}">
<block a:for="{{links}}">
<navigator class="am-footer-link" url="{{item.url}}">{{item.text}}</navigator>
</block>
</view>
<view class="am-footer-copyright" a:if="{{copyright}}">{{copyright}}</view>
</view>
\ No newline at end of file
Component({
props: {
className: ''
}
});
\ No newline at end of file
.am-grid {
display: flex;
flex-direction: row;
flex-wrap: wrap;
background-color: white;
}
.am-grid-4 {
padding-top: 7px;
padding-bottom: 7px;
}
.am-grid-5 {
padding-top: 6px;
padding-bottom: 7px;
}
.am-grid-item {
text-align: center;
position: relative;
}
.am-grid-3 .am-grid-border {
position: absolute;
left: 0;
bottom: 0;
width: 100%;
height: 100%;
border-bottom: 1rpx solid #eee;
border-right: 1rpx solid #eee;
box-sizing: border-box;
}
.am-grid-3 .am-grid-right {
border-right: none;
}
.am-grid-3 .am-grid-bottom {
border-bottom: none;
}
.am-grid-3 .am-grid-top {
height: calc(100% - 15px);
}
.am-grid-item-wrapper {
position: absolute;
left: 0;
bottom: 0;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
.am-grid-2 .am-grid-item-wrapper {
flex-direction: row;
justify-content: flex-start;
}
.am-grid-icon-container {
display: flex;
justify-content: center;
align-items: center;
}
.am-grid-icon {
flex: 1;
width: 36px;
height: 36px;
}
.am-grid-text-wrapper {
display: flex;
flex-direction: column;
align-items: flex-start;
}
.am-grid-3 .am-grid-text-wrapper {
align-items: center;
}
.am-grid-3 .am-grid-text {
height: 20px;
line-height: 20px;
}
.am-grid-3 .am-grid-desc {
height: 17px;
line-height: 17px;
}
.am-grid-text {
color: #333;
font-size: 14px;
line-height: 1;
margin-top: 14px;
}
.am-grid-desc {
color: #999;
font-size: 12px;
}
.am-grid-2 .am-grid-item.has-desc {
padding-top: 70px;
}
.am-grid-3 .am-grid-item {
padding-top: 125px;
}
.am-grid-3.am-grid-no-line {
padding: 8px 16px 0 16px;
}
.am-grid-no-line .am-grid-item {
padding-top: 110px;
}
.am-grid-2 .am-grid-item {
padding-top: 64px;
}
.am-grid-4 .am-grid-item {
padding-top: 68px;
}
.am-grid-4.circular .am-grid-item {
padding-top: 82px;
}
.am-grid-3 {
padding: 0 16px;
}
.am-grid-3 .am-grid-text {
margin-top: 12px;
}
.am-grid-no-line .am-grid-border {
border-right: none;
border-bottom: none;
}
.am-grid-4.circular {
padding-top: 3px;
}
.am-grid-4.circular .am-grid-icon-container {
margin-top: 13px;
padding: 8px;
border-radius: 50%;
background-color: #D8D8D8;
}
.am-grid-2 .am-grid-icon-container {
margin-left: 16px;
}
.am-grid-2 .am-grid-icon {
width: 28px;
height: 28px;
}
.am-grid-4 .am-grid-icon-container {
margin-top: 7px;
}
.am-grid-4 .am-grid-icon {
height: 28px;
width: 28px;
}
.am-grid-4.circular .am-grid-icon {
width: 26px;
height: 26px;
flex: 1;
}
.am-grid-4.circular .am-grid-text {
height: 16px;
line-height: 16px;
}
.am-grid-5 .am-grid-item {
padding-top: 75px;
}
.am-grid-5 .am-grid-icon {
border-radius: 50%;
width: 43px;
height: 43px;
}
.am-grid-2 .am-grid-text {
margin-top: 0;
margin-left: 12px;
height: 24px;
line-height: 24px;
font-size: 17px;
}
.am-grid-2 .am-grid-desc {
margin-left: 12px;
height: 16px;
line-height: 16px;
}
.am-grid-4 .am-grid-text {
font-size: 13px;
height: 13px;
line-height: 13px;
margin-top: 7px;
}
.am-grid-5 .am-grid-text {
font-size: 12px;
margin-top: 7px;
}
<view class="am-grid am-grid-{{columnNum}} {{circular && columnNum === 4 ? 'circular' : ''}} {{hasLine ? '' : 'am-grid-no-line'}}" >
<block a:for="{{list}}">
<view
style="width:{{100/(columnNum)}}%;"
class="am-grid-item {{list.some(item => item.desc && item.desc) ? 'has-desc' : ''}}"
onTap="onGridItemClick"
data-index={{index}}
key="grid-item-{{index}}"
>
<view class="am-grid-border {{index < 2 ? 'am-grid-top' : ''}} {{index >= bottomIndex ? 'am-grid-bottom' : ''}} {{(index + 1) % columnNum === 0 ? 'am-grid-right' : ''}}" />
<view class="am-grid-item-wrapper">
<view class="am-grid-icon-container">
<image src="{{item.icon}}" class="am-grid-icon" mode="aspectFit" />
</view>
<view class="am-grid-text-wrapper">
<text class="am-grid-text">{{item.text}}</text>
<text class="am-grid-desc" a:if="{{(columnNum === 2 || columnNum === 3) && item.desc && item.desc !== ''}}">{{item.desc}}</text>
</view>
</view>
</view>
</block>
</view>
\ No newline at end of file
Component({
data: {
bottomIndex: 0
},
props: {
columnNum: 3,
circular: false,
list: [],
onGridItemClick: function onGridItemClick() {},
hasLine: true
},
didMount: function didMount() {
var _props = this.props,
list = _props.list,
columnNum = _props.columnNum;
var rows = list.length / columnNum;
this.setData({
bottomIndex: Math.floor(rows) === rows ? (rows - 1) * columnNum : Math.floor(rows) * columnNum
});
},
methods: {
onGridItemClick: function onGridItemClick(e) {
this.props.onGridItemClick({
detail: {
index: e.target.dataset.index
}
});
}
}
});
\ No newline at end of file
.am-input-item {
display: flex;
align-items: center;
background: #fff;
padding-left: 15px;
}
.am-input-item .a-input-content {
padding-left: 2px;
}
.am-input-line {
position: relative;
flex: 1;
display: flex;
align-items: center;
padding-right: 15px;
min-height: 47px;
overflow: hidden;
}
.am-input-label {
min-width: 80px;
margin-right: 2px;
color: #333;
}
.am-input-content {
flex: 1;
display: flex;
height: 33px;
color: #000;
text-align: left;
}
.am-input-content .a-input-wrap {
flex: 1;
}
.am-input-clear {
display: flex;
height: 33px;
width: 33px;
justify-content: center;
align-items: center;
}
.am-input-clear.show {
visibility: visible;
}
.am-input-clear.hidden {
visibility: hidden;
pointer-events: none;
}
.am-input-line-bottom::after {
content: '';
display: block;
position: absolute;
width: 100%;
height: 1px;
transform: scaleY(0.5);
left: 0;
bottom: 0;
right: auto;
top: auto;
background-color: #eee;
}
/* 最后一行 */
.am-input-item.last .am-input-line-bottom::after {
display: none;
}
\ No newline at end of file
<view
class="am-input-item {{last ? 'last': ''}} {{className}}"
>
<view class="am-input-line">
<view a:if="{{$slots.$default}}" class="am-input-label {{labelCls}}">
<slot />
</view>
<input
enableNative="{{enableNative}}"
sync-input="{{syncInput}}"
class="am-input-content {{inputCls}}"
value="{{value}}"
name="{{name}}"
type="{{type}}"
password="{{password}}"
placeholder="{{placeholder}}"
placeholderClass="{{placeholderClass}}"
placeholderStyle="{{placeholderStyle}}"
disabled="{{disabled}}"
maxlength="{{maxlength}}"
focus="{{focus}}"
onInput="onInput"
onConfirm="onConfirm"
onFocus="onFocus"
onBlur="onBlur"
/>
<view class="am-input-clear {{clear && value.length > 0 && !disabled && _focus ? 'show' : 'hidden'}}" onTap="onClear">
<icon size="18" type="clear" />
</view>
<slot name="extra" />
<view class="am-input-line-bottom" />
</view>
</view>
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册