main
JING 9 months ago
commit fee01f75c0
  1. 73
      App.vue
  2. 2
      README.md
  3. 90
      config/access/index.js
  4. 200
      config/api.js
  5. 268
      config/com.js
  6. 34
      config/env.js
  7. 701
      config/jssdk.js
  8. 31
      config/map/amap-wx.130.js
  9. 1122
      config/map/qqmap-wx-jssdk.js
  10. 257
      config/md5.js
  11. 0
      config/qqmap.js
  12. 114
      config/request.js
  13. 88
      config/user.js
  14. 228
      config/wechat.js
  15. 20
      index.html
  16. 23
      locale/en.json
  17. 8
      locale/index.js
  18. 36
      locale/uni-app.en.json
  19. 36
      locale/uni-app.zh-Hans.json
  20. 36
      locale/uni-app.zh-Hant.json
  21. 39
      locale/zh-Hans.json
  22. 20
      locale/zh-Hant.json
  23. 57
      main.js
  24. 100
      manifest.json
  25. 82
      pages.json
  26. 482
      pages/index/index.vue
  27. 275
      pages/user/account/index.vue
  28. 176
      pages/user/auth/login.vue
  29. 205
      pages/user/auth/regist.vue
  30. 536
      pages/user/index.vue
  31. 220
      pages/user/setting/index.vue
  32. 77
      pages/web/index.vue
  33. 53
      pages/web/video.vue
  34. 2281
      static/css/iconfont.css
  35. BIN
      static/img/common/home.png
  36. BIN
      static/img/common/home_HL.png
  37. BIN
      static/img/common/lang.png
  38. BIN
      static/img/common/user.png
  39. BIN
      static/img/common/user_HL.png
  40. BIN
      static/img/index/aixz.png
  41. BIN
      static/img/index/banner.png
  42. BIN
      static/img/index/kthf.png
  43. BIN
      static/img/index/liucheng.png
  44. BIN
      static/img/index/notice.png
  45. BIN
      static/img/index/pic.png
  46. BIN
      static/img/index/right.png
  47. BIN
      static/img/index/scan.png
  48. BIN
      static/img/index/title_kt.png
  49. BIN
      static/img/index/title_xz.png
  50. BIN
      static/img/index/title_zj.png
  51. BIN
      static/img/index/zj_icon.png
  52. BIN
      static/img/index/zjgs.png
  53. BIN
      static/img/index/zjhc.png
  54. BIN
      static/img/user/account.png
  55. BIN
      static/img/user/avatar.png
  56. BIN
      static/img/user/banner.jpg
  57. BIN
      static/img/user/chat.png
  58. BIN
      static/img/user/code.png
  59. BIN
      static/img/user/img.png
  60. BIN
      static/img/user/link.png
  61. BIN
      static/img/user/money_log.png
  62. BIN
      static/img/user/noshop.png
  63. BIN
      static/img/user/order_all.png
  64. BIN
      static/img/user/order_finish.png
  65. BIN
      static/img/user/order_ing.png
  66. BIN
      static/img/user/topbg.png
  67. 7904
      static/json/city.json
  68. BIN
      static/logo.png
  69. 78
      uni.scss
  70. 21
      uni_modules/uview-ui/LICENSE
  71. 66
      uni_modules/uview-ui/README.md
  72. 344
      uni_modules/uview-ui/changelog.md
  73. 78
      uni_modules/uview-ui/components/u--form/u--form.vue
  74. 47
      uni_modules/uview-ui/components/u--image/u--image.vue
  75. 72
      uni_modules/uview-ui/components/u--input/u--input.vue
  76. 44
      uni_modules/uview-ui/components/u--text/u--text.vue
  77. 47
      uni_modules/uview-ui/components/u--textarea/u--textarea.vue
  78. 54
      uni_modules/uview-ui/components/u-action-sheet/props.js
  79. 278
      uni_modules/uview-ui/components/u-action-sheet/u-action-sheet.vue
  80. 59
      uni_modules/uview-ui/components/u-album/props.js
  81. 259
      uni_modules/uview-ui/components/u-album/u-album.vue
  82. 44
      uni_modules/uview-ui/components/u-alert/props.js
  83. 243
      uni_modules/uview-ui/components/u-alert/u-alert.vue
  84. 52
      uni_modules/uview-ui/components/u-avatar-group/props.js
  85. 103
      uni_modules/uview-ui/components/u-avatar-group/u-avatar-group.vue
  86. 78
      uni_modules/uview-ui/components/u-avatar/props.js
  87. 172
      uni_modules/uview-ui/components/u-avatar/u-avatar.vue
  88. 54
      uni_modules/uview-ui/components/u-back-top/props.js
  89. 129
      uni_modules/uview-ui/components/u-back-top/u-back-top.vue
  90. 72
      uni_modules/uview-ui/components/u-badge/props.js
  91. 171
      uni_modules/uview-ui/components/u-badge/u-badge.vue
  92. 46
      uni_modules/uview-ui/components/u-button/nvue.scss
  93. 161
      uni_modules/uview-ui/components/u-button/props.js
  94. 490
      uni_modules/uview-ui/components/u-button/u-button.vue
  95. 80
      uni_modules/uview-ui/components/u-button/vue.scss
  96. 99
      uni_modules/uview-ui/components/u-calendar/header.vue
  97. 579
      uni_modules/uview-ui/components/u-calendar/month.vue
  98. 144
      uni_modules/uview-ui/components/u-calendar/props.js
  99. 383
      uni_modules/uview-ui/components/u-calendar/u-calendar.vue
  100. 85
      uni_modules/uview-ui/components/u-calendar/util.js
  101. Some files were not shown because too many files have changed in this diff Show More

@ -0,0 +1,73 @@
<style lang="scss">
/* 注意要写在第一行,同时给style标签加入lang="scss"属性 */
@import "@/uni_modules/uview-ui/index.scss";
@import "@/static/css/iconfont.css";
</style>
<script>
export default {
onLaunch: function(options) {
console.log('App Launch');
var _this =this;
//
uni.getSystemInfo({
success:(res) => {
console.log(res);
_this.$user.session('app_system_info',res);
//
_this.$user.session('app_system',res.platform);
}
});
// #ifdef APP-PLUS
//
plus.screen.lockOrientation('portrait-primary'); //
// #endif
},
onShow: function() {
console.log('App Show')
var _this =this;
// #ifdef MP
//
uni.getProvider({
service: 'oauth',
success: function (res) {
console.log(res.provider)
var provider = res.provider[0];
uni.login({
provider:provider,
scopes:'auth_base',
success: function (rs) {
console.log(rs);
//
var post = {loginCode: rs.code};
_this.$api.post('ycl/user/wx-login', post,function(res){
console.log(res);
_this.$user.session('openid',res.wxOpenid);
_this.$user.session('user_id',res.id);
if(!_this.$com.isNull(res.token))
{
_this.$user.session('token',res.token);
}
});
},
fail:function(rs){
console.log('登录失败'+rs.errMsg);
}
});
}
});
// #endif
},
onHide: function() {
console.log('App Hide')
}
}
</script>

@ -0,0 +1,2 @@
# kjc_uni2

@ -0,0 +1,90 @@
var access = {
getAccess:function(k,userinfo){
if (userinfo && userinfo.access) {
return userinfo.access.indexOf(k) != -1;
}
return false;
},
hasAccess:function(arr,userinfo) {
if (userinfo && userinfo.access) {
return userinfo.access.some(_ => arr.indexOf(_) > -1);
}
return false;
},
/** 是否一级商户 */
isSuperType:function(userinfo){
if (this.getAccess(1002,userinfo)) {
return userinfo.userType == 2
}
if (this.getAccess(1003,userinfo) || this.getAccess(1004,userinfo)) {
return userinfo.userType == 1
}
return false;
},
/** 是否区级商户 */
isAreaType:function(userinfo){
if (this.getAccess(1002,userinfo)) {
return userinfo.userType == 1
}
if (this.getAccess(1003,userinfo) || this.getAccess(1004,userinfo)) {
return userinfo.userType == 2
}
return false;
},
/** 是否员工 */
isYuangongType:function(userinfo){
if (this.getAccess(1002,userinfo)) {
return userinfo.userType == 3
}
if (this.getAccess(1004,userinfo)) {
return userinfo.userType == 4
}
return false;
},
/** 是否三级 */
isThirdType:function(userinfo){
if (this.getAccess(1004,userinfo)) {
return userinfo.userType == 3
}
return false;
},
// 判断身份
checkidentity:function(userinfo) {
var res = {}
if (this.isSuperType(userinfo)) {
res = {
levelTxt: '一级',
levelVal: 1
}
} else if (this.isAreaType(userinfo)) {
res = {
levelTxt: '二级',
levelVal: 2
}
} else if (this.isThirdType(userinfo)) {
res = {
levelTxt: '店长',
levelVal: 3
}
/* } else if (this.isYuangongType(userinfo)) {
res = {
levelTxt: '员工',
levelVal: 3
} */
} else {
res = {
levelTxt: '用户',
levelVal: 4
}
}
return res
}
}
module.exports = access

@ -0,0 +1,200 @@
const md5 = require('./md5.js');
const ENV = require('./env.js');
var api = {
/**
* post 请求数据
*
* @param string urlName url地址
* @param {object} data 数据对象
* @param function thenFun then回调
* @param function catchFun catch回调
*/
post:function(urlName, data, thenFun,catchFun) {
//数据组合
var newData = Object.assign(api.setSign(data), ENV.appData());
uni.$u.http.post(urlName, newData).then(res => {
if(thenFun) thenFun(res);
}).catch((rs) =>{
if(catchFun) catchFun(rs);
});
},
/**
* get 请求数据
*
* @param string urlName url地址
* @param {object} data 数据对象
* @param function thenFun then回调
* @param function catchFun catch回调
*/
get:function(urlName, data, thenFun,catchFun) {
//数据组合
var newData = Object.assign(api.setSign(data), ENV.appData());
uni.$u.http.get(urlName,{params:newData}).then(res => {
if(thenFun) thenFun(res);
}).catch((rs) =>{
if(catchFun) catchFun(rs);
});
},
/**
* put 请求数据
*
* @param string urlName url地址
* @param {object} data 数据对象
* @param function thenFun then回调
* @param function catchFun catch回调
*/
put:function(urlName, data, thenFun,catchFun) {
//数据组合
var newData = Object.assign(api.setSign(data), ENV.appData());
uni.$u.http.put(urlName, newData).then(res => {
if(thenFun) thenFun(res);
}).catch((rs) =>{
if(catchFun) catchFun(rs);
});
},
/**
* delete 请求数据
*
* @param string urlName url地址
* @param {object} data 数据对象
* @param function thenFun then回调
* @param function catchFun catch回调
*/
delete:function(urlName, data, thenFun,catchFun) {
//数据组合
var newData = Object.assign(api.setSign(data), ENV.appData());
uni.$u.http.delete(urlName, newData).then(res => {
if(thenFun) thenFun(res);
}).catch((rs) =>{
if(catchFun) catchFun(rs);
});
},
/**
* upload 请求数据
*
* @param string urlName url地址
* @param {object} data 数据对象 {filePath:'',fileType:'image'}
* @param function thenFun then回调
* @param function catchFun catch回调
*/
upload:function(urlName, data, thenFun,catchFun){
var newData = data;
uni.$u.http.upload(urlName, {
params: {}, /* 会加在url上 */
// #ifdef MP-ALIPAY
fileType: newData.fileType, // 仅支付宝小程序,且必填。image/video/audio
// #endif
filePath: newData.filePath, // 要上传文件资源的路径。
// 注:如果局部custom与全局custom有同名属性,则后面的属性会覆盖前面的属性,相当于Object.assign(全局,局部)
custom: {auth:true,toast:true,}, // 可以加一些自定义参数,在拦截器等地方使用。比如这里我加了一个auth,可在拦截器里拿到,如果true就传token
name: 'files', // 文件对应的 key , 开发者在服务器端通过这个 key 可以获取到文件二进制内容
// #ifdef H5 || APP-PLUS
timeout: 60000, // H5(HBuilderX 2.9.9+)、APP(HBuilderX 2.9.9+)
// #endif
header: {
"Content-Type": "multipart/form-data"
}, /* 会与全局header合并,如有同名属性,局部覆盖全局 */
formData: {}, // HTTP 请求中其他额外的 form data
// 返回当前请求的task, options。请勿在此处修改options。非必填
getTask: (task, options) => {
task.onProgressUpdate((res) => {
console.log('上传进度' + res.progress);
console.log('已经上传的数据长度' + res.totalBytesSent);
console.log('预期需要上传的数据总长度' + res.totalBytesExpectedToSend);
});
},
}).then(res => {
if(thenFun) thenFun(res);
}).catch((rs) =>{
if(catchFun) catchFun(rs);
});
},
setSign:function(data) {
const date = parseInt(new Date().getTime() / 1000);
const str = date + 'xingzhi&&2021';
data.i_app_timestamp = date;
data.i_app_key = md5(str);
//判断登录 openid 和 unionid 的来源
// #ifdef APP-PLUS
data.i_app_platform = 'APP-PLUS';
// #endif
// #ifdef MP
//微信小程序
// #ifdef MP-WEIXIN
data.i_app_platform = 'MP-WEIXIN';
// #endif
//支付宝小程序
// #ifdef MP-ALIPAY
data.i_app_platform = 'MP-ALIPAY';
// #endif
//百度小程序
// #ifdef MP-BAIDU
data.i_app_platform = 'MP-BAIDU';
// #endif
//头条小程序
// #ifdef MP-TOUTIAO
data.i_app_platform = 'MP-TOUTIAO';
// #endif
//QQ小程序
// #ifdef MP-QQ
data.i_app_platform = 'MP-QQ';
// #endif
//360小程序
// #ifdef MP-360
data.i_app_platform = 'MP-360';
// #endif
// #endif
// #ifdef H5
data.i_app_platform = 'H5';
// #endif
//语言包
data.i_app_lang ='zh';
//系统
data.i_app_system = uni.getStorageSync('app_system');
//这里是token 如果登录每个接口都需要这个
const token = uni.getStorageSync('token');
if(token.length > 0)
{
data.token = token;
}
return data;
},
/**
* 返回域名
*
*/
domain:function() {
return ENV.CdnUrl;
},
/**
* 返回接口地址
*
*/
api:function() {
return ENV.ApiUrl;
},
/**
* 返回接口环境
*
*/
env:function(){
return ENV.EnvShow;
},
}
module.exports = api;

@ -0,0 +1,268 @@
const u_check = uni.$u.test;
var com = {
/**************uview集成********************************/
/**
* 验证检测
*
* @param array || obj || ... value 需要验证的值(可以是 array || obj || ... )
* @param string type 需要验证的类型(可以是 array || obj || ...)
*/
check:function(value,type)
{
switch(type) {
//数组
case 'array':
return u_check.array(value);
break;
//json字符串
case 'json':
return u_check.jsonString(value);
break;
//object对象
case 'object':
return u_check.object(value);
break;
//email 邮箱号
case 'email':
return u_check.email(value);
break;
//mobile 手机号
case 'mobile':
return u_check.mobile(value);
break;
//url 地址
case 'url':
return u_check.url(value);
break;
//empty 是否为空
case 'empty':
return u_check.isEmpty(value);
break;
//注解
//总的来说,年月日之间可以用"/"或者"-"分隔(不能用中文分隔),时分秒之间用":"分隔,数值不能超出范围,如月份不能为13,则检验成功,否则失败。
//date 日期时间
case 'date':
return u_check.date(value);
break;
//number 是否十进制数值
case 'number':
return u_check.number(value);
break;
//digits 是否整数
case 'digits':
return u_check.digits(value);
break;
//idCard 是否身份证号
case 'id_card':
return u_check.idCard(value);
break;
//是否车牌号 (例:京A88888)
case 'car_no':
return u_check.carNo(value);
break;
//amount 金额字符串
case 'amount':
return u_check.amount(value);
break;
//zh 是否汉字
case 'zh':
return u_check.chinese(value);
break;
//en 是否字母 letter
case 'en':
return u_check.letter(value);
break;
//str 是否字母或者数字
case 'str':
return u_check.enOrNum(value);
break;
default:
return false;
}
},
//是否为空
isNull:function(value)
{
if(value != null || value != 'null')
{
return u_check.isEmpty(value);
}
else
{
return true;
}
},
/********************反馈信息****************************************************/
alert: function(info) {
uni.showModal({
title: '提示',
content: info,
showCancel: false
});
},
alertDo: function(info, callback) {
uni.showModal({
title: '提示',
content: info,
showCancel: false,
success() {
callback();
}
});
},
confirm: function(info, callback, title) {
uni.showModal({
title: title ? title : '提示',
content: info,
success: function(res) {
if (res.confirm) {
callback();
}
}
});
},
// 加载信息,带遮罩
showLoading: function(title = '', mask = true) {
uni.showLoading({
title,
mask
});
},
// 隐藏遮罩
hideLoading:function () {
uni.hideLoading();
},
showSuccess: function(info) {
uni.showToast({
title: info,
icon: 'success',
duration: 3000
});
},
showError: function(info) {
uni.showToast({
title: info,
icon: 'none',
duration: 3000
});
},
showSuccessDo: function(info, time, callback) {
uni.showToast({
title: info,
icon: 'success',
duration: time,
success: function() {
callback();
}
});
},
/******************加减乘除****************************************************/
/**
* 加法精度计算
*
* @param {Object} number 数字
*/
bcadd: function(a, b){
var c, d, e;
try {
c = a.toString().split(".")[1].length
} catch(f) {
c = 0
}
try {
d = b.toString().split(".")[1].length
} catch(f) {
d = 0
}
return e = Math.pow(10, Math.max(c, d)),(this.bcmul(a, e) + this.bcmul(b, e)) / e
},
/**
* 减法精度计算
*
* @param {Object} number 数字
*/
bcsub: function(a, b){
var c, d, e;
try {
c = a.toString().split(".")[1].length
} catch(f) {
c = 0
}
try {
d = b.toString().split(".")[1].length
} catch(f) {
d = 0
}
return e = Math.pow(10, Math.max(c, d)),(this.bcmul(a, e) - this.bcmul(b, e)) / e
},
/**
* 乘法精度计算
*
* @param {Object} number 数字
*/
bcmul: function(a, b){
var c = 0,
d = a.toString(),
e = b.toString();
try {
c += d.split(".")[1].length
} catch(f) {}
try {
c += e.split(".")[1].length
} catch(f) {}
return Number(d.replace(".", "")) * Number(e.replace(".", "")) / Math.pow(10, c)
},
/**
* 除法精度计算
*
* @param {Object} number 数字
*/
bcdiv: function(a, b){
var c, d, e = 0,
f = 0;
try {
e = a.toString().split(".")[1].length
} catch(g) {}
try {
f = b.toString().split(".")[1].length
} catch(g) {}
return c = Number(a.toString().replace(".", "")),d = Number(b.toString().replace(".", "")),this.bcmul(c / d, Math.pow(10, f - e))
},
/**
* 隐藏手机号
* @param phone string 数值1
*/
hidephone:function (phone){
var reg = /^(\d{3})\d{4}(\d{4})$/;
return phone.replace(reg, "$1****$2")
},
removeObserver(arr) {
return arr.map((item) => {
if (Array.isArray(item)) return removeObserver(item)
else if (typeof item === 'object') {
const target = {}
for (let key in item) {
if (key !== '__ob__') {
target[key] = item[key]
}
}
return target
}
return item
})
}
}
module.exports = com

@ -0,0 +1,34 @@
//api接口环境配置
// production正式/development线上测试/local本地开发
var NowENV = 'development';
var ENV_API_URL = {
production:'https://netcharge.spacechong.com/', //正式环境
development:'https://devnetcharge.spacechong.com/', //开发测试环境
local:'http://192.168.10.123:8901/',//本地调试环境
}
//CdnUrl 环境配置[都默认为线上都行]
var ENV_BASE_URL = {
production:'https://netcharge.spacechong.com', //正式环境
development:'https://netcharge.spacechong.com', //开发测试环境
local:'https://netcharge.spacechong.com',//本地调试环境
}
var ENV = {
EnvShow:NowENV,//当前环境
ApiUrl:ENV_API_URL[NowENV], //正式
CdnUrl:ENV_BASE_URL[NowENV], //正式
appData:function() {
var data = {}; //版本号
data.i_app_version = '2.1.2';
return data;
},
QQmapkey:'2EBBZ-RAL33-TLM3A-3KVVR-V2LMO-3TFQ4',
}
module.exports = ENV

@ -0,0 +1,701 @@
! function(e, n) {
"function" == typeof define && (define.amd || define.cmd) ? define(function() {
return n(e)
}) : n(e, !0)
}(window, function(o, e) {
if (!o.jWeixin) {
var n, c = {
config: "preVerifyJSAPI",
onMenuShareTimeline: "menu:share:timeline",
onMenuShareAppMessage: "menu:share:appmessage",
onMenuShareQQ: "menu:share:qq",
onMenuShareWeibo: "menu:share:weiboApp",
onMenuShareQZone: "menu:share:QZone",
previewImage: "imagePreview",
getLocation: "geoLocation",
openProductSpecificView: "openProductViewWithPid",
addCard: "batchAddCard",
openCard: "batchViewCard",
chooseWXPay: "getBrandWCPayRequest",
openEnterpriseRedPacket: "getRecevieBizHongBaoRequest",
startSearchBeacons: "startMonitoringBeacons",
stopSearchBeacons: "stopMonitoringBeacons",
onSearchBeacons: "onBeaconsInRange",
consumeAndShareCard: "consumedShareCard",
openAddress: "editAddress"
},
a = function() {
var e = {};
for (var n in c) e[c[n]] = n;
return e
}(),
i = o.document,
t = i.title,
r = navigator.userAgent.toLowerCase(),
s = navigator.platform.toLowerCase(),
d = !(!s.match("mac") && !s.match("win")),
u = -1 != r.indexOf("wxdebugger"),
l = -1 != r.indexOf("micromessenger"),
p = -1 != r.indexOf("android"),
f = -1 != r.indexOf("iphone") || -1 != r.indexOf("ipad"),
m = (n = r.match(/micromessenger\/(\d+\.\d+\.\d+)/) || r.match(/micromessenger\/(\d+\.\d+)/)) ? n[1] : "",
g = {
initStartTime: L(),
initEndTime: 0,
preVerifyStartTime: 0,
preVerifyEndTime: 0
},
h = {
version: 1,
appId: "",
initTime: 0,
preVerifyTime: 0,
networkType: "",
isPreVerifyOk: 1,
systemType: f ? 1 : p ? 2 : -1,
clientVersion: m,
url: encodeURIComponent(location.href)
},
v = {},
S = {
_completes: []
},
y = {
state: 0,
data: {}
};
O(function() {
g.initEndTime = L()
});
var I = !1,
_ = [],
w = {
config: function(e) {
B("config", v = e);
var t = !1 !== v.check;
O(function() {
if (t) M(c.config, {
verifyJsApiList: C(v.jsApiList),
verifyOpenTagList: C(v.openTagList)
}, function() {
S._complete = function(e) {
g.preVerifyEndTime = L(), y.state = 1, y.data = e
}, S.success = function(e) {
h.isPreVerifyOk = 0
}, S.fail = function(e) {
S._fail ? S._fail(e) : y.state = -1
};
var t = S._completes;
return t.push(function() {
! function() {
if (!(d || u || v.debug || m < "6.0.2" || h.systemType < 0)) {
var i = new Image;
h.appId = v.appId, h.initTime = g.initEndTime - g.initStartTime, h.preVerifyTime = g.preVerifyEndTime - g.preVerifyStartTime, w.getNetworkType({
isInnerInvoke: !0,
success: function(e) {
h.networkType = e.networkType;
var n = "https://open.weixin.qq.com/sdk/report?v=" + h.version + "&o=" + h.isPreVerifyOk + "&s=" + h.systemType + "&c=" + h.clientVersion + "&a=" + h.appId + "&n=" + h.networkType + "&i=" + h.initTime + "&p=" + h.preVerifyTime + "&u=" + h.url;
i.src = n
}
})
}
}()
}), S.complete = function(e) {
for (var n = 0, i = t.length; n < i; ++n) t[n]();
S._completes = []
}, S
}()), g.preVerifyStartTime = L();
else {
y.state = 1;
for (var e = S._completes, n = 0, i = e.length; n < i; ++n) e[n]();
S._completes = []
}
}), w.invoke || (w.invoke = function(e, n, i) {
o.WeixinJSBridge && WeixinJSBridge.invoke(e, x(n), i)
}, w.on = function(e, n) {
o.WeixinJSBridge && WeixinJSBridge.on(e, n)
})
},
ready: function(e) {
0 != y.state ? e() : (S._completes.push(e), !l && v.debug && e())
},
error: function(e) {
m < "6.0.2" || (-1 == y.state ? e(y.data) : S._fail = e)
},
checkJsApi: function(e) {
M("checkJsApi", {
jsApiList: C(e.jsApiList)
}, (e._complete = function(e) {
if (p) {
var n = e.checkResult;
n && (e.checkResult = JSON.parse(n))
}
e = function(e) {
var n = e.checkResult;
for (var i in n) {
var t = a[i];
t && (n[t] = n[i], delete n[i])
}
return e
}(e)
}, e))
},
onMenuShareTimeline: function(e) {
P(c.onMenuShareTimeline, {
complete: function() {
M("shareTimeline", {
title: e.title || t,
desc: e.title || t,
img_url: e.imgUrl || "",
link: e.link || location.href,
type: e.type || "link",
data_url: e.dataUrl || ""
}, e)
}
}, e)
},
onMenuShareAppMessage: function(n) {
P(c.onMenuShareAppMessage, {
complete: function(e) {
"favorite" === e.scene ? M("sendAppMessage", {
title: n.title || t,
desc: n.desc || "",
link: n.link || location.href,
img_url: n.imgUrl || "",
type: n.type || "link",
data_url: n.dataUrl || ""
}) : M("sendAppMessage", {
title: n.title || t,
desc: n.desc || "",
link: n.link || location.href,
img_url: n.imgUrl || "",
type: n.type || "link",
data_url: n.dataUrl || ""
}, n)
}
}, n)
},
onMenuShareQQ: function(e) {
P(c.onMenuShareQQ, {
complete: function() {
M("shareQQ", {
title: e.title || t,
desc: e.desc || "",
img_url: e.imgUrl || "",
link: e.link || location.href
}, e)
}
}, e)
},
onMenuShareWeibo: function(e) {
P(c.onMenuShareWeibo, {
complete: function() {
M("shareWeiboApp", {
title: e.title || t,
desc: e.desc || "",
img_url: e.imgUrl || "",
link: e.link || location.href
}, e)
}
}, e)
},
onMenuShareQZone: function(e) {
P(c.onMenuShareQZone, {
complete: function() {
M("shareQZone", {
title: e.title || t,
desc: e.desc || "",
img_url: e.imgUrl || "",
link: e.link || location.href
}, e)
}
}, e)
},
updateTimelineShareData: function(e) {
M("updateTimelineShareData", {
title: e.title,
link: e.link,
imgUrl: e.imgUrl
}, e)
},
updateAppMessageShareData: function(e) {
M("updateAppMessageShareData", {
title: e.title,
desc: e.desc,
link: e.link,
imgUrl: e.imgUrl
}, e)
},
startRecord: function(e) {
M("startRecord", {}, e)
},
stopRecord: function(e) {
M("stopRecord", {}, e)
},
onVoiceRecordEnd: function(e) {
P("onVoiceRecordEnd", e)
},
playVoice: function(e) {
M("playVoice", {
localId: e.localId
}, e)
},
pauseVoice: function(e) {
M("pauseVoice", {
localId: e.localId
}, e)
},
stopVoice: function(e) {
M("stopVoice", {
localId: e.localId
}, e)
},
onVoicePlayEnd: function(e) {
P("onVoicePlayEnd", e)
},
uploadVoice: function(e) {
M("uploadVoice", {
localId: e.localId,
isShowProgressTips: 0 == e.isShowProgressTips ? 0 : 1
}, e)
},
downloadVoice: function(e) {
M("downloadVoice", {
serverId: e.serverId,
isShowProgressTips: 0 == e.isShowProgressTips ? 0 : 1
}, e)
},
translateVoice: function(e) {
M("translateVoice", {
localId: e.localId,
isShowProgressTips: 0 == e.isShowProgressTips ? 0 : 1
}, e)
},
chooseImage: function(e) {
M("chooseImage", {
scene: "1|2",
count: e.count || 9,
sizeType: e.sizeType || ["original", "compressed"],
sourceType: e.sourceType || ["album", "camera"]
}, (e._complete = function(e) {
if (p) {
var n = e.localIds;
try {
n && (e.localIds = JSON.parse(n))
} catch (e) {}
}
}, e))
},
getLocation: function(e) {},
previewImage: function(e) {
M(c.previewImage, {
current: e.current,
urls: e.urls
}, e)
},
uploadImage: function(e) {
M("uploadImage", {
localId: e.localId,
isShowProgressTips: 0 == e.isShowProgressTips ? 0 : 1
}, e)
},
downloadImage: function(e) {
M("downloadImage", {
serverId: e.serverId,
isShowProgressTips: 0 == e.isShowProgressTips ? 0 : 1
}, e)
},
getLocalImgData: function(e) {
!1 === I ? (I = !0, M("getLocalImgData", {
localId: e.localId
}, (e._complete = function(e) {
if (I = !1, 0 < _.length) {
var n = _.shift();
wx.getLocalImgData(n)
}
}, e))) : _.push(e)
},
getNetworkType: function(e) {
M("getNetworkType", {}, (e._complete = function(e) {
e = function(e) {
var n = e.errMsg;
e.errMsg = "getNetworkType:ok";
var i = e.subtype;
if (delete e.subtype, i) e.networkType = i;
else {
var t = n.indexOf(":"),
o = n.substring(t + 1);
switch (o) {
case "wifi":
case "edge":
case "wwan":
e.networkType = o;
break;
default:
e.errMsg = "getNetworkType:fail"
}
}
return e
}(e)
}, e))
},
openLocation: function(e) {
M("openLocation", {
latitude: e.latitude,
longitude: e.longitude,
name: e.name || "",
address: e.address || "",
scale: e.scale || 28,
infoUrl: e.infoUrl || ""
}, e)
},
getLocation: function(e) {
M(c.getLocation, {
type: (e = e || {}).type || "wgs84"
}, (e._complete = function(e) {
delete e.type
}, e))
},
hideOptionMenu: function(e) {
M("hideOptionMenu", {}, e)
},
showOptionMenu: function(e) {
M("showOptionMenu", {}, e)
},
closeWindow: function(e) {
M("closeWindow", {}, e = e || {})
},
hideMenuItems: function(e) {
M("hideMenuItems", {
menuList: e.menuList
}, e)
},
showMenuItems: function(e) {
M("showMenuItems", {
menuList: e.menuList
}, e)
},
hideAllNonBaseMenuItem: function(e) {
M("hideAllNonBaseMenuItem", {}, e)
},
showAllNonBaseMenuItem: function(e) {
M("showAllNonBaseMenuItem", {}, e)
},
scanQRCode: function(e) {
M("scanQRCode", {
needResult: (e = e || {}).needResult || 0,
scanType: e.scanType || ["qrCode", "barCode"]
}, (e._complete = function(e) {
if (f) {
var n = e.resultStr;
if (n) {
var i = JSON.parse(n);
e.resultStr = i && i.scan_code && i.scan_code.scan_result
}
}
}, e))
},
openAddress: function(e) {
M(c.openAddress, {}, (e._complete = function(e) {
e = function(e) {
return e.postalCode = e.addressPostalCode, delete e.addressPostalCode, e.provinceName = e.proviceFirstStageName, delete e.proviceFirstStageName, e.cityName = e.addressCitySecondStageName, delete e.addressCitySecondStageName, e.countryName = e.addressCountiesThirdStageName, delete e.addressCountiesThirdStageName, e.detailInfo = e.addressDetailInfo, delete e.addressDetailInfo, e
}(e)
}, e))
},
openProductSpecificView: function(e) {
M(c.openProductSpecificView, {
pid: e.productId,
view_type: e.viewType || 0,
ext_info: e.extInfo
}, e)
},
addCard: function(e) {
for (var n = e.cardList, i = [], t = 0, o = n.length; t < o; ++t) {
var r = n[t],
a = {
card_id: r.cardId,
card_ext: r.cardExt
};
i.push(a)
}
M(c.addCard, {
card_list: i
}, (e._complete = function(e) {
var n = e.card_list;
if (n) {
for (var i = 0, t = (n = JSON.parse(n)).length; i < t; ++i) {
var o = n[i];
o.cardId = o.card_id, o.cardExt = o.card_ext, o.isSuccess = !!o.is_succ, delete o.card_id, delete o.card_ext, delete o.is_succ
}
e.cardList = n, delete e.card_list
}
}, e))
},
chooseCard: function(e) {
M("chooseCard", {
app_id: v.appId,
location_id: e.shopId || "",
sign_type: e.signType || "SHA1",
card_id: e.cardId || "",
card_type: e.cardType || "",
card_sign: e.cardSign,
time_stamp: e.timestamp + "",
nonce_str: e.nonceStr
}, (e._complete = function(e) {
e.cardList = e.choose_card_info, delete e.choose_card_info
}, e))
},
openCard: function(e) {
for (var n = e.cardList, i = [], t = 0, o = n.length; t < o; ++t) {
var r = n[t],
a = {
card_id: r.cardId,
code: r.code
};
i.push(a)
}
M(c.openCard, {
card_list: i
}, e)
},
consumeAndShareCard: function(e) {
M(c.consumeAndShareCard, {
consumedCardId: e.cardId,
consumedCode: e.code
}, e)
},
chooseWXPay: function(e) {
M(c.chooseWXPay, V(e), e)
},
openEnterpriseRedPacket: function(e) {
M(c.openEnterpriseRedPacket, V(e), e)
},
startSearchBeacons: function(e) {
M(c.startSearchBeacons, {
ticket: e.ticket
}, e)
},
stopSearchBeacons: function(e) {
M(c.stopSearchBeacons, {}, e)
},
onSearchBeacons: function(e) {
P(c.onSearchBeacons, e)
},
openEnterpriseChat: function(e) {
M("openEnterpriseChat", {
useridlist: e.userIds,
chatname: e.groupName
}, e)
},
launchMiniProgram: function(e) {
M("launchMiniProgram", {
targetAppId: e.targetAppId,
path: function(e) {
if ("string" == typeof e && 0 < e.length) {
var n = e.split("?")[0],
i = e.split("?")[1];
return n += ".html", void 0 !== i ? n + "?" + i : n
}
}(e.path),
envVersion: e.envVersion
}, e)
},
openBusinessView: function(e) {
M("openBusinessView", {
businessType: e.businessType,
queryString: e.queryString || "",
envVersion: e.envVersion
}, (e._complete = function(n) {
if (p) {
var e = n.extraData;
if (e) try {
n.extraData = JSON.parse(e)
} catch (e) {
n.extraData = {}
}
}
}, e))
},
miniProgram: {
navigateBack: function(e) {
e = e || {}, O(function() {
M("invokeMiniProgramAPI", {
name: "navigateBack",
arg: {
delta: e.delta || 1
}
}, e)
})
},
navigateTo: function(e) {
O(function() {
M("invokeMiniProgramAPI", {
name: "navigateTo",
arg: {
url: e.url
}
}, e)
})
},
redirectTo: function(e) {
O(function() {
M("invokeMiniProgramAPI", {
name: "redirectTo",
arg: {
url: e.url
}
}, e)
})
},
switchTab: function(e) {
O(function() {
M("invokeMiniProgramAPI", {
name: "switchTab",
arg: {
url: e.url
}
}, e)
})
},
reLaunch: function(e) {
O(function() {
M("invokeMiniProgramAPI", {
name: "reLaunch",
arg: {
url: e.url
}
}, e)
})
},
postMessage: function(e) {
O(function() {
M("invokeMiniProgramAPI", {
name: "postMessage",
arg: e.data || {}
}, e)
})
},
getEnv: function(e) {
O(function() {
e({
miniprogram: "miniprogram" === o.__wxjs_environment
})
})
}
}
},
T = 1,
k = {};
return i.addEventListener("error", function(e) {
if (!p) {
var n = e.target,
i = n.tagName,
t = n.src;
if ("IMG" == i || "VIDEO" == i || "AUDIO" == i || "SOURCE" == i)
if (-1 != t.indexOf("wxlocalresource://")) {
e.preventDefault(), e.stopPropagation();
var o = n["wx-id"];
if (o || (o = T++, n["wx-id"] = o), k[o]) return;
k[o] = !0, wx.ready(function() {
wx.getLocalImgData({
localId: t,
success: function(e) {
n.src = e.localData
}
})
})
}
}
}, !0), i.addEventListener("load", function(e) {
if (!p) {
var n = e.target,
i = n.tagName;
n.src;
if ("IMG" == i || "VIDEO" == i || "AUDIO" == i || "SOURCE" == i) {
var t = n["wx-id"];
t && (k[t] = !1)
}
}
}, !0), e && (o.wx = o.jWeixin = w), w
}
function M(n, e, i) {
o.WeixinJSBridge ? WeixinJSBridge.invoke(n, x(e), function(e) {
A(n, e, i)
}) : B(n, i)
}
function P(n, i, t) {
o.WeixinJSBridge ? WeixinJSBridge.on(n, function(e) {
t && t.trigger && t.trigger(e), A(n, e, i)
}) : B(n, t || i)
}
function x(e) {
return (e = e || {}).appId = v.appId, e.verifyAppId = v.appId, e.verifySignType = "sha1", e.verifyTimestamp = v.timestamp + "", e.verifyNonceStr = v.nonceStr, e.verifySignature = v.signature, e
}
function V(e) {
return {
timeStamp: e.timestamp + "",
nonceStr: e.nonceStr,
package: e.package,
paySign: e.paySign,
signType: e.signType || "SHA1"
}
}
function A(e, n, i) {
"openEnterpriseChat" != e && "openBusinessView" !== e || (n.errCode = n.err_code), delete n.err_code, delete n.err_desc, delete n.err_detail;
var t = n.errMsg;
t || (t = n.err_msg, delete n.err_msg, t = function(e, n) {
var i = e,
t = a[i];
t && (i = t);
var o = "ok";
if (n) {
var r = n.indexOf(":");
"confirm" == (o = n.substring(r + 1)) && (o = "ok"), "failed" == o && (o = "fail"), -1 != o.indexOf("failed_") && (o = o.substring(7)), -1 != o.indexOf("fail_") && (o = o.substring(5)), "access denied" != (o = (o = o.replace(/_/g, " ")).toLowerCase()) && "no permission to execute" != o || (o = "permission denied"), "config" == i && "function not exist" == o && (o = "ok"), "" == o && (o = "fail")
}
return n = i + ":" + o
}(e, t), n.errMsg = t), (i = i || {})._complete && (i._complete(n), delete i._complete), t = n.errMsg || "", v.debug && !i.isInnerInvoke && alert(JSON.stringify(n));
var o = t.indexOf(":");
switch (t.substring(o + 1)) {
case "ok":
i.success && i.success(n);
break;
case "cancel":
i.cancel && i.cancel(n);
break;
default:
i.fail && i.fail(n)
}
i.complete && i.complete(n)
}
function C(e) {
if (e) {
for (var n = 0, i = e.length; n < i; ++n) {
var t = e[n],
o = c[t];
o && (e[n] = o)
}
return e
}
}
function B(e, n) {
if (!(!v.debug || n && n.isInnerInvoke)) {
var i = a[e];
i && (e = i), n && n._complete && delete n._complete, console.log('"' + e + '",', n || "")
}
}
function L() {
return (new Date).getTime()
}
function O(e) {
l && (o.WeixinJSBridge ? e() : i.addEventListener && i.addEventListener("WeixinJSBridgeReady", e, !1))
}
});

@ -0,0 +1,31 @@
function AMapWX(a){this.key=a.key;this.requestConfig={key:a.key,s:"rsx",platform:"WXJS",appname:a.key,sdkversion:"1.2.0",logversion:"2.0"};this.MeRequestConfig={key:a.key,serviceName:"https://restapi.amap.com/rest/me"}}
AMapWX.prototype.getWxLocation=function(a,b){wx.getLocation({type:"gcj02",success:function(c){c=c.longitude+","+c.latitude;wx.setStorage({key:"userLocation",data:c});b(c)},fail:function(c){wx.getStorage({key:"userLocation",success:function(d){d.data&&b(d.data)}});a.fail({errCode:"0",errMsg:c.errMsg||""})}})};
AMapWX.prototype.getMEKeywordsSearch=function(a){if(!a.options)return a.fail({errCode:"0",errMsg:"\u7f3a\u5c11\u5fc5\u8981\u53c2\u6570"});var b=a.options,c=this.MeRequestConfig,d={key:c.key,s:"rsx",platform:"WXJS",appname:a.key,sdkversion:"1.2.0",logversion:"2.0"};b.layerId&&(d.layerId=b.layerId);b.keywords&&(d.keywords=b.keywords);b.city&&(d.city=b.city);b.filter&&(d.filter=b.filter);b.sortrule&&(d.sortrule=b.sortrule);b.pageNum&&(d.pageNum=b.pageNum);b.pageSize&&(d.pageSize=b.pageSize);b.sig&&(d.sig=
b.sig);wx.request({url:c.serviceName+"/cpoint/datasearch/local",data:d,method:"GET",header:{"content-type":"application/json"},success:function(e){(e=e.data)&&e.status&&"1"===e.status&&0===e.code?a.success(e.data):a.fail({errCode:"0",errMsg:e})},fail:function(e){a.fail({errCode:"0",errMsg:e.errMsg||""})}})};
AMapWX.prototype.getMEIdSearch=function(a){if(!a.options)return a.fail({errCode:"0",errMsg:"\u7f3a\u5c11\u5fc5\u8981\u53c2\u6570"});var b=a.options,c=this.MeRequestConfig,d={key:c.key,s:"rsx",platform:"WXJS",appname:a.key,sdkversion:"1.2.0",logversion:"2.0"};b.layerId&&(d.layerId=b.layerId);b.id&&(d.id=b.id);b.sig&&(d.sig=b.sig);wx.request({url:c.serviceName+"/cpoint/datasearch/id",data:d,method:"GET",header:{"content-type":"application/json"},success:function(e){(e=e.data)&&e.status&&"1"===e.status&&
0===e.code?a.success(e.data):a.fail({errCode:"0",errMsg:e})},fail:function(e){a.fail({errCode:"0",errMsg:e.errMsg||""})}})};
AMapWX.prototype.getMEPolygonSearch=function(a){if(!a.options)return a.fail({errCode:"0",errMsg:"\u7f3a\u5c11\u5fc5\u8981\u53c2\u6570"});var b=a.options,c=this.MeRequestConfig,d={key:c.key,s:"rsx",platform:"WXJS",appname:a.key,sdkversion:"1.2.0",logversion:"2.0"};b.layerId&&(d.layerId=b.layerId);b.keywords&&(d.keywords=b.keywords);b.polygon&&(d.polygon=b.polygon);b.filter&&(d.filter=b.filter);b.sortrule&&(d.sortrule=b.sortrule);b.pageNum&&(d.pageNum=b.pageNum);b.pageSize&&(d.pageSize=b.pageSize);
b.sig&&(d.sig=b.sig);wx.request({url:c.serviceName+"/cpoint/datasearch/polygon",data:d,method:"GET",header:{"content-type":"application/json"},success:function(e){(e=e.data)&&e.status&&"1"===e.status&&0===e.code?a.success(e.data):a.fail({errCode:"0",errMsg:e})},fail:function(e){a.fail({errCode:"0",errMsg:e.errMsg||""})}})};
AMapWX.prototype.getMEaroundSearch=function(a){if(!a.options)return a.fail({errCode:"0",errMsg:"\u7f3a\u5c11\u5fc5\u8981\u53c2\u6570"});var b=a.options,c=this.MeRequestConfig,d={key:c.key,s:"rsx",platform:"WXJS",appname:a.key,sdkversion:"1.2.0",logversion:"2.0"};b.layerId&&(d.layerId=b.layerId);b.keywords&&(d.keywords=b.keywords);b.center&&(d.center=b.center);b.radius&&(d.radius=b.radius);b.filter&&(d.filter=b.filter);b.sortrule&&(d.sortrule=b.sortrule);b.pageNum&&(d.pageNum=b.pageNum);b.pageSize&&
(d.pageSize=b.pageSize);b.sig&&(d.sig=b.sig);wx.request({url:c.serviceName+"/cpoint/datasearch/around",data:d,method:"GET",header:{"content-type":"application/json"},success:function(e){(e=e.data)&&e.status&&"1"===e.status&&0===e.code?a.success(e.data):a.fail({errCode:"0",errMsg:e})},fail:function(e){a.fail({errCode:"0",errMsg:e.errMsg||""})}})};
AMapWX.prototype.getGeo=function(a){var b=this.requestConfig,c=a.options;b={key:this.key,extensions:"all",s:b.s,platform:b.platform,appname:this.key,sdkversion:b.sdkversion,logversion:b.logversion};c.address&&(b.address=c.address);c.city&&(b.city=c.city);c.batch&&(b.batch=c.batch);c.sig&&(b.sig=c.sig);wx.request({url:"https://restapi.amap.com/v3/geocode/geo",data:b,method:"GET",header:{"content-type":"application/json"},success:function(d){(d=d.data)&&d.status&&"1"===d.status?a.success(d):a.fail({errCode:"0",
errMsg:d})},fail:function(d){a.fail({errCode:"0",errMsg:d.errMsg||""})}})};
AMapWX.prototype.getRegeo=function(a){function b(d){var e=c.requestConfig;wx.request({url:"https://restapi.amap.com/v3/geocode/regeo",data:{key:c.key,location:d,extensions:"all",s:e.s,platform:e.platform,appname:c.key,sdkversion:e.sdkversion,logversion:e.logversion},method:"GET",header:{"content-type":"application/json"},success:function(g){if(g.data.status&&"1"==g.data.status){g=g.data.regeocode;var h=g.addressComponent,f=[],k=g.roads[0].name+"\u9644\u8fd1",m=d.split(",")[0],n=d.split(",")[1];if(g.pois&&
g.pois[0]){k=g.pois[0].name+"\u9644\u8fd1";var l=g.pois[0].location;l&&(m=parseFloat(l.split(",")[0]),n=parseFloat(l.split(",")[1]))}h.provice&&f.push(h.provice);h.city&&f.push(h.city);h.district&&f.push(h.district);h.streetNumber&&h.streetNumber.street&&h.streetNumber.number?(f.push(h.streetNumber.street),f.push(h.streetNumber.number)):f.push(g.roads[0].name);f=f.join("");a.success([{iconPath:a.iconPath,width:a.iconWidth,height:a.iconHeight,name:f,desc:k,longitude:m,latitude:n,id:0,regeocodeData:g}])}else a.fail({errCode:g.data.infocode,
errMsg:g.data.info})},fail:function(g){a.fail({errCode:"0",errMsg:g.errMsg||""})}})}var c=this;a.location?b(a.location):c.getWxLocation(a,function(d){b(d)})};
AMapWX.prototype.getWeather=function(a){function b(g){var h="base";a.type&&"forecast"==a.type&&(h="all");wx.request({url:"https://restapi.amap.com/v3/weather/weatherInfo",data:{key:d.key,city:g,extensions:h,s:e.s,platform:e.platform,appname:d.key,sdkversion:e.sdkversion,logversion:e.logversion},method:"GET",header:{"content-type":"application/json"},success:function(f){if(f.data.status&&"1"==f.data.status)if(f.data.lives){if((f=f.data.lives)&&0<f.length){f=f[0];var k={city:{text:"\u57ce\u5e02",data:f.city},
weather:{text:"\u5929\u6c14",data:f.weather},temperature:{text:"\u6e29\u5ea6",data:f.temperature},winddirection:{text:"\u98ce\u5411",data:f.winddirection+"\u98ce"},windpower:{text:"\u98ce\u529b",data:f.windpower+"\u7ea7"},humidity:{text:"\u6e7f\u5ea6",data:f.humidity+"%"}};k.liveData=f;a.success(k)}}else f.data.forecasts&&f.data.forecasts[0]&&a.success({forecast:f.data.forecasts[0]});else a.fail({errCode:f.data.infocode,errMsg:f.data.info})},fail:function(f){a.fail({errCode:"0",errMsg:f.errMsg||""})}})}
function c(g){wx.request({url:"https://restapi.amap.com/v3/geocode/regeo",data:{key:d.key,location:g,extensions:"all",s:e.s,platform:e.platform,appname:d.key,sdkversion:e.sdkversion,logversion:e.logversion},method:"GET",header:{"content-type":"application/json"},success:function(h){if(h.data.status&&"1"==h.data.status){h=h.data.regeocode;if(h.addressComponent)var f=h.addressComponent.adcode;else h.aois&&0<h.aois.length&&(f=h.aois[0].adcode);b(f)}else a.fail({errCode:h.data.infocode,errMsg:h.data.info})},
fail:function(h){a.fail({errCode:"0",errMsg:h.errMsg||""})}})}var d=this,e=d.requestConfig;a.city?b(a.city):d.getWxLocation(a,function(g){c(g)})};
AMapWX.prototype.getPoiAround=function(a){function b(e){e={key:c.key,location:e,s:d.s,platform:d.platform,appname:c.key,sdkversion:d.sdkversion,logversion:d.logversion};a.querytypes&&(e.types=a.querytypes);a.querykeywords&&(e.keywords=a.querykeywords);wx.request({url:"https://restapi.amap.com/v3/place/around",data:e,method:"GET",header:{"content-type":"application/json"},success:function(g){if(g.data.status&&"1"==g.data.status){if((g=g.data)&&g.pois){for(var h=[],f=0;f<g.pois.length;f++){var k=0==
f?a.iconPathSelected:a.iconPath;h.push({latitude:parseFloat(g.pois[f].location.split(",")[1]),longitude:parseFloat(g.pois[f].location.split(",")[0]),iconPath:k,width:22,height:32,id:f,name:g.pois[f].name,address:g.pois[f].address})}a.success({markers:h,poisData:g.pois})}}else a.fail({errCode:g.data.infocode,errMsg:g.data.info})},fail:function(g){a.fail({errCode:"0",errMsg:g.errMsg||""})}})}var c=this,d=c.requestConfig;a.location?b(a.location):c.getWxLocation(a,function(e){b(e)})};
AMapWX.prototype.getStaticmap=function(a){function b(e){c.push("location="+e);a.zoom&&c.push("zoom="+a.zoom);a.size&&c.push("size="+a.size);a.scale&&c.push("scale="+a.scale);a.markers&&c.push("markers="+a.markers);a.labels&&c.push("labels="+a.labels);a.paths&&c.push("paths="+a.paths);a.traffic&&c.push("traffic="+a.traffic);e="https://restapi.amap.com/v3/staticmap?"+c.join("&");a.success({url:e})}var c=[];c.push("key="+this.key);var d=this.requestConfig;c.push("s="+d.s);c.push("platform="+d.platform);
c.push("appname="+d.appname);c.push("sdkversion="+d.sdkversion);c.push("logversion="+d.logversion);a.location?b(a.location):this.getWxLocation(a,function(e){b(e)})};
AMapWX.prototype.getInputtips=function(a){var b=Object.assign({},this.requestConfig);a.location&&(b.location=a.location);a.keywords&&(b.keywords=a.keywords);a.type&&(b.type=a.type);a.city&&(b.city=a.city);a.citylimit&&(b.citylimit=a.citylimit);wx.request({url:"https://restapi.amap.com/v3/assistant/inputtips",data:b,method:"GET",header:{"content-type":"application/json"},success:function(c){c&&c.data&&c.data.tips&&a.success({tips:c.data.tips})},fail:function(c){a.fail({errCode:"0",errMsg:c.errMsg||
""})}})};
AMapWX.prototype.getDrivingRoute=function(a){var b=Object.assign({},this.requestConfig);a.origin&&(b.origin=a.origin);a.destination&&(b.destination=a.destination);a.strategy&&(b.strategy=a.strategy);a.waypoints&&(b.waypoints=a.waypoints);a.avoidpolygons&&(b.avoidpolygons=a.avoidpolygons);a.avoidroad&&(b.avoidroad=a.avoidroad);wx.request({url:"https://restapi.amap.com/v3/direction/driving",data:b,method:"GET",header:{"content-type":"application/json"},success:function(c){c&&c.data&&c.data.route&&a.success({paths:c.data.route.paths,
taxi_cost:c.data.route.taxi_cost||""})},fail:function(c){a.fail({errCode:"0",errMsg:c.errMsg||""})}})};
AMapWX.prototype.getWalkingRoute=function(a){var b=Object.assign({},this.requestConfig);a.origin&&(b.origin=a.origin);a.destination&&(b.destination=a.destination);wx.request({url:"https://restapi.amap.com/v3/direction/walking",data:b,method:"GET",header:{"content-type":"application/json"},success:function(c){c&&c.data&&c.data.route&&a.success({paths:c.data.route.paths})},fail:function(c){a.fail({errCode:"0",errMsg:c.errMsg||""})}})};
AMapWX.prototype.getTransitRoute=function(a){var b=Object.assign({},this.requestConfig);a.origin&&(b.origin=a.origin);a.destination&&(b.destination=a.destination);a.strategy&&(b.strategy=a.strategy);a.city&&(b.city=a.city);a.cityd&&(b.cityd=a.cityd);wx.request({url:"https://restapi.amap.com/v3/direction/transit/integrated",data:b,method:"GET",header:{"content-type":"application/json"},success:function(c){c&&c.data&&c.data.route&&(c=c.data.route,a.success({distance:c.distance||"",taxi_cost:c.taxi_cost||
"",transits:c.transits}))},fail:function(c){a.fail({errCode:"0",errMsg:c.errMsg||""})}})};
AMapWX.prototype.getRidingRoute=function(a){var b=Object.assign({},this.requestConfig);a.origin&&(b.origin=a.origin);a.destination&&(b.destination=a.destination);wx.request({url:"https://restapi.amap.com/v3/direction/riding",data:b,method:"GET",header:{"content-type":"application/json"},success:function(c){c&&c.data&&c.data.route&&a.success({paths:c.data.route.paths})},fail:function(c){a.fail({errCode:"0",errMsg:c.errMsg||""})}})};module.exports.AMapWX=AMapWX;

File diff suppressed because it is too large Load Diff

@ -0,0 +1,257 @@
/*
* A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
* Digest Algorithm, as defined in RFC 1321.
* Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
* Distributed under the BSD License
* See http://pajhome.org.uk/crypt/md5 for more info.
*/
/*
* Configurable variables. You may need to tweak these to be compatible with
* the server-side, but the defaults work in most cases.
*/
var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */
var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */
/*
* These are the functions you'll usually want to call
* They take string arguments and return either hex or base-64 encoded strings
*/
function hex_md5(s){ return binl2hex(core_md5(str2binl(s), s.length * chrsz));}
function b64_md5(s){ return binl2b64(core_md5(str2binl(s), s.length * chrsz));}
function str_md5(s){ return binl2str(core_md5(str2binl(s), s.length * chrsz));}
function hex_hmac_md5(key, data) { return binl2hex(core_hmac_md5(key, data)); }
function b64_hmac_md5(key, data) { return binl2b64(core_hmac_md5(key, data)); }
function str_hmac_md5(key, data) { return binl2str(core_hmac_md5(key, data)); }
/*
* Perform a simple self-test to see if the VM is working
*/
function md5_vm_test()
{
return hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72";
}
/*
* Calculate the MD5 of an array of little-endian words, and a bit length
*/
function core_md5(x, len)
{
/* append padding */
x[len >> 5] |= 0x80 << ((len) % 32);
x[(((len + 64) >>> 9) << 4) + 14] = len;
var a = 1732584193;
var b = -271733879;
var c = -1732584194;
var d = 271733878;
for(var i = 0; i < x.length; i += 16)
{
var olda = a;
var oldb = b;
var oldc = c;
var oldd = d;
a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
c = md5_ff(c, d, a, b, x[i+ 2], 17, 606105819);
b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
d = md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426);
c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
a = md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416);
d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
a = md5_ff(a, b, c, d, x[i+12], 7 , 1804603682);
d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329);
a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
c = md5_gg(c, d, a, b, x[i+11], 14, 643717713);
b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
d = md5_gg(d, a, b, c, x[i+10], 9 , 38016083);
c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
a = md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438);
d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
b = md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501);
a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473);
b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);
a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
c = md5_hh(c, d, a, b, x[i+11], 16, 1839030562);
b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
d = md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353);
c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
a = md5_hh(a, b, c, d, x[i+13], 4 , 681279174);
d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
b = md5_hh(b, c, d, a, x[i+ 6], 23, 76029189);
a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
c = md5_hh(c, d, a, b, x[i+15], 16, 530742520);
b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);
a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415);
c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
a = md5_ii(a, b, c, d, x[i+12], 6 , 1700485571);
d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
a = md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359);
d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
b = md5_ii(b, c, d, a, x[i+13], 21, 1309151649);
a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259);
b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);
a = safe_add(a, olda);
b = safe_add(b, oldb);
c = safe_add(c, oldc);
d = safe_add(d, oldd);
}
return Array(a, b, c, d);
}
/*
* These functions implement the four basic operations the algorithm uses.
*/
function md5_cmn(q, a, b, x, s, t)
{
return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
}
function md5_ff(a, b, c, d, x, s, t)
{
return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
}
function md5_gg(a, b, c, d, x, s, t)
{
return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
}
function md5_hh(a, b, c, d, x, s, t)
{
return md5_cmn(b ^ c ^ d, a, b, x, s, t);
}
function md5_ii(a, b, c, d, x, s, t)
{
return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
}
/*
* Calculate the HMAC-MD5, of a key and some data
*/
function core_hmac_md5(key, data)
{
var bkey = str2binl(key);
if(bkey.length > 16) bkey = core_md5(bkey, key.length * chrsz);
var ipad = Array(16), opad = Array(16);
for(var i = 0; i < 16; i++)
{
ipad[i] = bkey[i] ^ 0x36363636;
opad[i] = bkey[i] ^ 0x5C5C5C5C;
}
var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * chrsz);
return core_md5(opad.concat(hash), 512 + 128);
}
/*
* Add integers, wrapping at 2^32. This uses 16-bit operations internally
* to work around bugs in some JS interpreters.
*/
function safe_add(x, y)
{
var lsw = (x & 0xFFFF) + (y & 0xFFFF);
var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
return (msw << 16) | (lsw & 0xFFFF);
}
/*
* Bitwise rotate a 32-bit number to the left.
*/
function bit_rol(num, cnt)
{
return (num << cnt) | (num >>> (32 - cnt));
}
/*
* Convert a string to an array of little-endian words
* If chrsz is ASCII, characters >255 have their hi-byte silently ignored.
*/
function str2binl(str)
{
var bin = Array();
var mask = (1 << chrsz) - 1;
for(var i = 0; i < str.length * chrsz; i += chrsz)
bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32);
return bin;
}
/*
* Convert an array of little-endian words to a string
*/
function binl2str(bin)
{
var str = "";
var mask = (1 << chrsz) - 1;
for(var i = 0; i < bin.length * 32; i += chrsz)
str += String.fromCharCode((bin[i>>5] >>> (i % 32)) & mask);
return str;
}
/*
* Convert an array of little-endian words to a hex string.
*/
function binl2hex(binarray)
{
var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
var str = "";
for(var i = 0; i < binarray.length * 4; i++)
{
str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) +
hex_tab.charAt((binarray[i>>2] >> ((i%4)*8 )) & 0xF);
}
return str;
}
/*
* Convert an array of little-endian words to a base-64 string
*/
function binl2b64(binarray)
{
var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var str = "";
for(var i = 0; i < binarray.length * 4; i += 3)
{
var triplet = (((binarray[i >> 2] >> 8 * ( i %4)) & 0xFF) << 16)
| (((binarray[i+1 >> 2] >> 8 * ((i+1)%4)) & 0xFF) << 8 )
| ((binarray[i+2 >> 2] >> 8 * ((i+2)%4)) & 0xFF);
for(var j = 0; j < 4; j++)
{
if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;
else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);
}
}
return str;
}
module.exports = hex_md5;

@ -0,0 +1,114 @@
const ENV = require('./env.js');
/*
{
baseUrl: '',
header: {},
method: 'GET',
dataType: 'json',
// #ifndef MP-ALIPAY || APP-PLUS
responseType: 'text',
// #endif
// 注:如果局部custom与全局custom有同名属性,则后面的属性会覆盖前面的属性,相当于Object.assign(全局,局部)
custom: {}, // 全局自定义参数默认值
// #ifdef MP-ALIPAY || MP-WEIXIN
timeout: 30000,
// #endif
// #ifdef APP-PLUS
sslVerify: true,
// #endif
// #ifdef H5
// 跨域请求时是否携带凭证(cookies)仅H5支持(HBuilderX 2.6.15+)
withCredentials: false,
// #endif
// 局部优先级高于全局,返回当前请求的task,options。请勿在此处修改options。非必填
// getTask: (task, options) => {
// 相当于设置了请求超时时间500ms
// setTimeout(() => {
// task.abort()
// }, 500)
// }
}*/
// 此vm参数为页面的实例,可以通过它引用vuex中的变量
module.exports = (vm) => {
// 初始化请求配置
uni.$u.http.setConfig((config) => {
//console.log(config);
/* config 为默认全局配置*/
config.baseURL = ENV.ApiUrl; /* 根域名 */
config.custom = {
auth:true,
toast:true,
};
return config
})
// 请求拦截
uni.$u.http.interceptors.request.use((config) => { // 可使用async await 做异步操作
// 初始化请求拦截器时,会执行此方法,此时data为undefined,赋予默认{}
config.data = config.data || {}
// 根据custom参数中配置的是否需要token,添加对应的请求头
if(config?.custom?.auth) {
const token = uni.getStorageSync('token');
if(token.length > 0)
{
config.header.token = token;
}
}
return config
}, config => { // 可使用async await 做异步操作
return Promise.reject(config)
})
// 响应拦截
uni.$u.http.interceptors.response.use((response) => { /* 对响应成功做点什么 可使用async await 做异步操作*/
const data = response.data
// 自定义参数
const custom = response.config?.custom
if (data.result !== 1) {
// 如果没有显式定义custom的toast参数为false的话,默认对报错进行toast弹出提示
if (custom.toast !== false) {
uni.$u.toast(data.msg)
}
// 如果需要catch返回,则进行reject
if (custom?.catch) {
return Promise.reject(data)
} else {
// 否则返回一个pending中的promise,请求不会进入catch中
return new Promise(() => { })
}
}
return data.data === undefined ? {} : data.data
}, (response) => {
//console.log(response);
// 对响应错误做点什么 (statusCode !== 200)
if(response.statusCode == 401)
{
// 假设201为token失效,这里跳转登录
uni.$u.toast('用户信息验证失败,请重新登录');
setTimeout(() => {
// 此为uView的方法,详见路由相关文档
//uni.$u.route('/pages/user/auth/login')
}, 1500)
}
else if(response.statusCode == 500)
{
// 假设201为token失效,这里跳转登录
uni.$u.toast('当前接口出错');
}
else
{
// 如果返回false,则会调用Promise的reject回调,
// 并将进入this.$u.post(url).then().catch(res=>{})的catch回调中,res为服务端的返回值
uni.$u.toast('当前接口状态码'+response.statusCode);
}
return Promise.reject(response)
})
}

@ -0,0 +1,88 @@
var user = {
/**
* 本算法来源于简书开源代码详见https://www.jianshu.com/p/fdbf293d0a85
* 全局唯一标识符uuidGlobally Unique Identifier,也称作 uuid(Universally Unique IDentifier)
* 一般用于多个组件之间,给它一个唯一的标识符,或者v-for循环的时候,如果使用数组的index可能会导致更新列表出现问题
* 最可能的情况是左滑删除item或者对某条信息流"不喜欢"并去掉它的时候,会导致组件内的数据可能出现错乱
* v-for的时候,推荐使用后端返回的id而不是循环的index
* @param {Number} len uuid的长度
* @param {Boolean} firstU 将返回的首字母置为"u"
* @param {Nubmer} radix 生成uuid的基数(意味着返回的字符串都是这个基数),2-二进制,8-八进制,10-十进制,16-十六进制
*/
guid:function (len = 32, firstU = true, radix = null) {
let chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
let uuid = [];
radix = radix || chars.length;
if (len) {
// 如果指定uuid长度,只是取随机的字符,0|x为位运算,能去掉x的小数位,返回整数位
for (let i = 0; i < len; i++) uuid[i] = chars[0 | Math.random() * radix];
} else {
let r;
// rfc4122标准要求返回的uuid中,某些位为固定的字符
uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
uuid[14] = '4';
for (let i = 0; i < 36; i++) {
if (!uuid[i]) {
r = 0 | Math.random() * 16;
uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r];
}
}
}
// 移除第一个字符,并用u替代,因为第一个字符为数值时,该guuid不能用作id或者class
if (firstU) {
uuid.shift();
return 'u' + uuid.join('');
} else {
return uuid.join('');
}
},
//设置用户本地信息
session: function(key, val) {
if (typeof(val) == 'undefined') {
var res = uni.getStorageSync(key);
return res;
} else {
uni.setStorageSync(key, val);
}
},
//删除用户本地所有信息
clearSession: function() {
var keys = uni.getStorageInfoSync().keys;
var session_id = uni.getStorageSync('session_id');
for (var key in keys) {
uni.removeStorageSync(keys[key]);
}
uni.setStorageSync('session_id', session_id);
},
isLogin: function() {
var res = uni.getStorageSync('token');
if (typeof(res) == 'undefined' || res == '') {
return false;
} else {
return res;
}
},
getUserInfo: function() {
var res = uni.getStorageSync('token');
if (typeof(res) == 'undefined' || res == '') {
return false;
} else {
var userInfo = {};
userInfo.nickName = uni.getStorageSync('nickName');
userInfo.phone = uni.getStorageSync('phone');
userInfo.userId = uni.getStorageSync('userId');
userInfo.token = uni.getStorageSync('token');
userInfo.avatar = uni.getStorageSync('avatar');
userInfo.realName = uni.getStorageSync('realName');
return userInfo;
}
}
}
module.exports = user

@ -0,0 +1,228 @@
// /common/wechat.js
//https://zhuanlan.zhihu.com/p/512790783?utm_id=0
import Vue from "vue"
var jweixin = require('./jssdk.js')
export default {
// 调试模式
debug: false,
// api列表
jsApiList: [
'updateAppMessageShareData',
'updateTimelineShareData',
'closeWindow',
'getLocation',
'openLocation',
'openAddress',
'scanQRCode',
'chooseImage',
'chooseWXPay'
],
// 判断是否在微信中
isWechat: function() {
var ua = window.navigator.userAgent.toLowerCase()
return ua.match(/micromessenger/i) == 'micromessenger' ? true : false
},
// 初始化sdk配置
initJssdk: function(callback) {
var url = window.location.href;
var post = {url:url};
if (this.isWechat()) {
Vue.prototype.$u.post('login/getApi', post).then(res => {
console.log('getApi : ');
console.log(res);
var share = JSON.parse(res.data);
console.log('getApi-share : ');
console.log(share);
jweixin.config({
debug: share.debug || this.debug,
appId: share.appId,
timestamp:share.timestamp,
nonceStr: share.nonceStr,
signature: share.signature,
jsApiList: share.jsApiList || this.jsApiList
})
if (typeof callback === 'function') {
console.log('getApi-callback : ');
console.log(share);
callback(share);
}
})
}
},
// 关闭页面事件
closeWindow: function(callback) {
if (this.isWechat()) {
this.initJssdk(function(init) {
jweixin.ready(function(wx) {
wx.closeWindow()
if (typeof callback === 'function') {
callback(jweixin)
}
})
})
}
},
// 微信分享
share: function(data, callback) {
if (this.isWechat()) {
this.initJssdk(function(init) {
jweixin.ready(function() {
var shareData = {
title: data.title,
desc: data.desc,
link: window.location.href,
imgUrl: data.image,
success: function(res) {
callback(res)
},
cancel: function(res) {
callback(res)
}
}
jweixin.updateAppMessageShareData(shareData)
jweixin.updateTimelineShareData(shareData)
})
})
}
},
// 获取位置信息
getLocation: function(callback) {
if (this.isWechat()) {
this.initJssdk(function(init) {
jweixin.ready(function() {
jweixin.getLocation({
type: 'gcj02',
success: function(res) {
callback(res)
},
fail: function(err) {
callback(err)
}
})
})
})
}
},
// 查看位置信息
openLocation: function(data, callback) {
if (this.isWechat()) {
this.initJssdk(function(init) {
jweixin.ready(function() {
jweixin.openLocation({
latitude: data.latitude,
longitude: data.longitude
})
})
})
}
},
// 获取微信收货地址
openAddress: function(callback) {
if (this.isWechat()) {
this.initJssdk(function(init) {
jweixin.ready(function() {
jweixin.openAddress({
success: function(res) {
callback(res)
},
fail: function(err) {
callback(err)
}
})
})
})
}
},
// 微信扫码
scanQRCode: function(callback) {
if (this.isWechat()) {
this.initJssdk(function(init) {
jweixin.ready(function() {
jweixin.scanQRCode({
needResult: 1, // 0:微信处理|1:返回扫描结果
scanType: ["qrCode", "barCode"],
success: function(res) {
let durl = /https:\/\/([^\/]+)\//i
let domain
res.resultStr.replace(durl, (e) => {
domain = e
})
callback(res)
},
fail: function(err) {
callback(err)
}
})
})
})
}
},
// 选择图片
chooseImage: function(callback) {
if (this.isWechat()) {
this.initJssdk(function(init) {
jweixin.ready(function() {
jweixin.chooseImage({
count: 1,
sizeType: ['compressed'],
sourceType: ['album'],
success: function(res) {
callback(res)
}
})
})
})
}
},
// 微信支付
wxpay: function(data, callback) {
if (this.isWechat()) {
this.initJssdk(function(init) {
jweixin.ready(function() {
jweixin.chooseWXPay({
timestamp: data.timeStamp,
nonceStr: data.nonceStr,
package: data.package,
signType: data.signType,
paySign: data.paySign,
success: function(res) {
callback(res)
},
cancel: function(res) {
callback(res)
},
fail: function(err) {
callback(err)
}
})
})
})
}
},
// 微信支付 另一种方式
wxpayBridge: function(data, callback) {
if (this.isWechat()) {
this.initJssdk(function(init) {
jweixin.ready(function() {
WeixinJSBridge.invoke(
'getBrandWCPayRequest', {
"appId": data.appId,
"timeStamp": data.timeStamp,
"nonceStr": data.nonceStr,
"package": data.package,
"signType": "MD5",
"paySign": data.paySign
},
function(res) {
callback(res)
}
)
})
})
}
}
}

@ -0,0 +1,20 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<script>
var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') ||
CSS.supports('top: constant(a)'))
document.write(
'<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
(coverSupport ? ', viewport-fit=cover' : '') + '" />')
</script>
<title></title>
<!--preload-links-->
<!--app-context-->
</head>
<body>
<div id="app"><!--app-html--></div>
<script type="module" src="/main.js"></script>
</body>
</html>

@ -0,0 +1,23 @@
{
"app.name": "空间充",
"tabbar.home": "HOME",
"tabbar.list": "NEARBY",
"tabbar.user": "USER",
"page.list.index.title": "NEARBY",
"page.user.index.title": "User Center",
"pages.user.setting.index.title":"Setting",
"pages.user.setting.index.setLang":"Language",
"locale.auto": "System",
"locale.en": "English",
"locale.zh-hans": "简体中文",
"locale.zh-hant": "繁体中文",
"locale.language-change-confirm": "Applying this setting will restart the app"
}

@ -0,0 +1,8 @@
import zhHans from './zh-Hans.json'
import zhHant from './zh-Hant.json'
import en from './en.json'
export default {
'zh-Hans': zhHans,
'zh-Hant': zhHant,
en
}

@ -0,0 +1,36 @@
{
"common": {
"uni.app.quit": "Press again to quit the app",
"uni.async.error": "The connection to the server timed out, click the screen to retry",
"uni.showActionSheet.cancel": "Cancel",
"uni.showToast.unpaired": "Please note that showToast and hideToast must be paired",
"uni.showLoading.unpaired": "Please note that showLoading and hideLoading must be paired",
"uni.showModal.cancel": "Cancel",
"uni.showModal.confirm": "OK",
"uni.chooseImage.cancel": "Cancel",
"uni.chooseImage.sourceType.album": "Choose from Album",
"uni.chooseImage.sourceType.camera": "shoot",
"uni.chooseVideo.cancel": "Cancel",
"uni.chooseVideo.sourceType.album": "Choose from Album",
"uni.chooseVideo.sourceType.camera": "Camera",
"uni.previewImage.cancel": "Cancel",
"uni.previewImage.button.save": "Save Image",
"uni.previewImage.save.success": "Successful saving image to album",
"uni.previewImage.save.fail": "Failed to save image to album",
"uni.setClipboardData.success": "Content copied",
"uni.scanCode.title": "scan",
"uni.scanCode.album": "Album",
"uni.scanCode.fail": "Recognition failed",
"uni.scanCode.flash.on": "Light touch to light",
"uni.scanCode.flash.off": "Flick Off",
"uni.startSoterAuthentication.authContent": "Fingerprint identification...",
"uni.picker.done": "Done",
"uni.picker.cancel": "Cancel",
"uni.video.danmu": "Barrage",
"uni.video.volume": "Volume",
"uni.button.feedback.title": "Problem Feedback",
"uni.button.feedback.send": "send"
},
"ios": {},
"android": {}
}

@ -0,0 +1,36 @@
{
"common": {
"uni.app.quit": "再按一次退出应用",
"uni.async.error": "连接服务器超时,点击屏幕重试",
"uni.showActionSheet.cancel": "取消",
"uni.showToast.unpaired": "请注意 showToast 与 hideToast 必须配对使用",
"uni.showLoading.unpaired": "请注意 showLoading 与 hideLoading 必须配对使用",
"uni.showModal.cancel": "取消",
"uni.showModal.confirm": "确定",
"uni.chooseImage.cancel": "取消",
"uni.chooseImage.sourceType.album": "从相册选择",
"uni.chooseImage.sourceType.camera": "拍摄",
"uni.chooseVideo.cancel": "取消",
"uni.chooseVideo.sourceType.album": "从相册选择",
"uni.chooseVideo.sourceType.camera": "拍摄",
"uni.previewImage.cancel": "取消",
"uni.previewImage.button.save": "保存图像",
"uni.previewImage.save.success": "保存图像到相册成功",
"uni.previewImage.save.fail": "保存图像到相册失败",
"uni.setClipboardData.success": "内容已复制",
"uni.scanCode.title": "扫码",
"uni.scanCode.album": "相册",
"uni.scanCode.fail": "识别失败",
"uni.scanCode.flash.on": "轻触照亮",
"uni.scanCode.flash.off": "轻触关闭",
"uni.startSoterAuthentication.authContent": "指纹识别中...",
"uni.picker.done": "完成",
"uni.picker.cancel": "取消",
"uni.video.danmu": "弹幕",
"uni.video.volume": "音量",
"uni.button.feedback.title": "问题反馈",
"uni.button.feedback.send": "发送"
},
"ios": {},
"android": {}
}

@ -0,0 +1,36 @@
{
"common": {
"uni.app.quit": "再按一次退出應用",
"uni.async.error": "連接服務器超時,點擊屏幕重試",
"uni.showActionSheet.cancel": "取消",
"uni.showToast.unpaired": "請註意 showToast 與 hideToast 必須配對使用",
"uni.showLoading.unpaired": "請註意 showLoading 與 hideLoading 必須配對使用",
"uni.showModal.cancel": "取消",
"uni.showModal.confirm": "確定",
"uni.chooseImage.cancel": "取消",
"uni.chooseImage.sourceType.album": "從相冊選擇",
"uni.chooseImage.sourceType.camera": "拍攝",
"uni.chooseVideo.cancel": "取消",
"uni.chooseVideo.sourceType.album": "從相冊選擇",
"uni.chooseVideo.sourceType.camera": "拍攝",
"uni.previewImage.cancel": "取消",
"uni.previewImage.button.save": "保存圖像",
"uni.previewImage.save.success": "保存圖像到相冊成功",
"uni.previewImage.save.fail": "保存圖像到相冊失敗",
"uni.setClipboardData.success": "內容已復製",
"uni.scanCode.title": "掃碼",
"uni.scanCode.album": "相冊",
"uni.scanCode.fail": "識別失敗",
"uni.scanCode.flash.on": "輕觸照亮",
"uni.scanCode.flash.off": "輕觸關閉",
"uni.startSoterAuthentication.authContent": "指紋識別中...",
"uni.picker.done": "完成",
"uni.picker.cancel": "取消",
"uni.video.danmu": "彈幕",
"uni.video.volume": "音量",
"uni.button.feedback.title": "問題反饋",
"uni.button.feedback.send": "發送"
},
"ios": {},
"android": {}
}

@ -0,0 +1,39 @@
{
"app.name": "合成照相馆",
"tabbar.home": "首页",
"tabbar.list": "附近",
"tabbar.user": "我的",
"page.list.index.title": "附近",
"page.user.index.title": "用户中心",
"pages.user.setting.index.title":"设置",
"pages.user.setting.index.setLang":"多语言",
"locale.auto": "系统",
"locale.en": "English",
"locale.zh-hans": "简体中文",
"locale.zh-hant": "繁体中文",
"locale.language-change-confirm": "应用此设置将重启App",
"locale.tips": "提示",
"locale.login": "登录账号",
"locale.regist": "账号注册",
"locale.logout": "退出登录",
"pages.user.auth.login.login":"登录页面",
"pages.user.auth.login.mobile":"手机号码",
"pages.user.auth.login.input_mobile":"请输入手机号码",
"pages.user.auth.login.mobile_must":"手机号码格式不正确",
"pages.user.auth.login.email":"邮箱地址",
"pages.user.auth.login.input_email":"请输入Email地址",
"pages.user.auth.login.email_must":"Email格式不正确",
"pages.user.auth.login.password":"账号密码",
"pages.user.auth.login.input_password":"请输入账号密码",
"pages.user.auth.login.password_must":"密码不小于6位",
"pages.user.auth.regist.regist":"注册页面",
"pages.user.auth.regist.regist_success":"注册成功"
}

@ -0,0 +1,20 @@
{
"app.name": "空间充",
"tabbar.home": "首頁",
"tabbar.list": "附近",
"tabbar.user": "我的",
"page.list.index.title": "附近",
"page.user.index.title": "用戶中心",
"pages.user.setting.index.title":"設置",
"pages.user.setting.index.setLang":"多語言",
"locale.auto": "系統",
"locale.en": "English",
"locale.zh-hans": "简体中文",
"locale.zh-hant": "繁體中文",
"locale.language-change-confirm": "應用此設置將重啟App"
}

@ -0,0 +1,57 @@
import App from './App'
import messages from './locale/index'
// main.js
import uView from '@/uni_modules/uview-ui';
Vue.use(uView);
let i18nConfig = {
locale: uni.getLocale(),
messages
}
// 引入请求封装,将app参数传递到配置中
require('@/config/request.js')(app); //uview js
//自己封装的部分
import api from '@/config/api.js';
Vue.prototype.$api = api;
import user from '@/config/user.js';
Vue.prototype.$user = user;
import com from '@/config/com.js';
Vue.prototype.$com = com;
import access from '@/config/access/index.js';
Vue.prototype.$access = access;
// #ifdef H5
import wechat from '@/config/wechat.js'
Vue.prototype.$wechat =wechat;
// #endif
// #ifndef VUE3
import Vue from 'vue'
import VueI18n from 'vue-i18n'
Vue.use(VueI18n)
const i18n = new VueI18n(i18nConfig)
Vue.config.productionTip = false
App.mpType = 'app'
const app = new Vue({
i18n,
...App
})
app.$mount();
// #endif
// #ifdef VUE3
import { createSSRApp } from 'vue'
import { createI18n } from 'vue-i18n'
const i18n = createI18n(i18nConfig)
export function createApp() {
const app = createSSRApp(App)
app.use(i18n)
return {
app
}
}
// #endif

@ -0,0 +1,100 @@
{
"name" : "合成照相馆",
"appid" : "__UNI__304D8B8",
"description" : "",
"versionName" : "2.1.2",
"versionCode" : 212,
"transformPx" : false,
/* 5+App */
"app-plus" : {
"usingComponents" : true,
"nvueStyleCompiler" : "uni-app",
"compilerVersion" : 3,
"splashscreen" : {
"alwaysShowBeforeRender" : true,
"waiting" : true,
"autoclose" : true,
"delay" : 0
},
/* */
"modules" : {},
/* */
"distribute" : {
/* android */
"android" : {
"permissions" : [
"<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
"<uses-permission android:name=\"android.permission.VIBRATE\"/>",
"<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
"<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
"<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
"<uses-permission android:name=\"android.permission.CAMERA\"/>",
"<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
"<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
"<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
"<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
"<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
"<uses-feature android:name=\"android.hardware.camera\"/>",
"<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
]
},
/* ios */
"ios" : {},
/* SDK */
"sdkConfigs" : {}
}
},
/* */
"quickapp" : {},
/* */
"mp-weixin" : {
"appid" : "wx19306460077082e9",
"setting" : {
"urlCheck" : false,
"es6" : true,
"postcss" : true,
"minified" : true
},
"usingComponents" : true,
"permission" : {
"scope.userLocation" : {
"desc" : "你的位置信息将用于小程序位置接口的效果展示"
}
},
"requiredPrivateInfos" : [ "getLocation", "chooseLocation" ],
"libVersion" : "latest"
},
"mp-alipay" : {
"usingComponents" : true
},
"mp-baidu" : {
"usingComponents" : true
},
"mp-toutiao" : {
"usingComponents" : true
},
"uniStatistics" : {
"enable" : false
},
"vueVersion" : "2",
"locale" : "zh-Hans",
"fallbackLocale" : "zh-Hans",
"h5" : {
"title" : "空间充",
"router" : {
"mode" : "history",
"base" : "/h5/"
},
"template" : "",
"devServer" : {
"https" : false
},
"optimization" : {
"treeShaking" : {
"enable" : false
}
}
}
}

@ -0,0 +1,82 @@
{
"pages": [ //pageshttps://uniapp.dcloud.io/collocation/pages
{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "%app.name%",
"navigationStyle": "custom"
}
}
,{
"path" : "pages/user/index",
"style" :
{
"navigationBarTitleText": "%page.user.index.title%",
"enablePullDownRefresh": false
}
}
,{
"path" : "pages/user/setting/index",
"style" :
{
"navigationBarTitleText": "%pages.user.setting.index.setLang%",
"enablePullDownRefresh": false
}
},
{
"path" : "pages/user/account/index",
"style" :
{
"navigationBarTitleText" : "账户设置",
"enablePullDownRefresh" : false
}
},
{
"path" : "pages/web/index",
"style" :
{
"navigationBarTitleText" : "外部页面",
"enablePullDownRefresh" : false
}
},
{
"path" : "pages/web/video",
"style" :
{
"navigationBarTitleText" : "视频",
"enablePullDownRefresh" : false
}
}
],
"subPackages": [],
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "%app.name%",
"navigationBarBackgroundColor": "#FFFFFF",
"backgroundColor": "#FFFFFF"
},
"tabBar": {
"color": "#AFB1DB",
"selectedColor": "#7A74F0",
"borderStyle": "black",
"backgroundColor": "#FFFFFF",
"list": [{
"pagePath": "pages/index/index",
"iconPath": "static/img/common/home.png",
"selectedIconPath": "static/img/common/home_HL.png",
"text": "%tabbar.home%"
},
{
"pagePath": "pages/user/index",
"iconPath": "static/img/common/user.png",
"selectedIconPath": "static/img/common/user_HL.png",
"text": "%tabbar.user%"
}
]
},
"uniIdRouter": {}
}

@ -0,0 +1,482 @@
<template>
<view class="container">
<view class="bannerBox">
<u-swiper
:list="banner"
keyName="adImg"
:showTitle="false"
:autoplay="true"
circular
height="280"
radius="0"
@click="openAd"
></u-swiper>
</view>
<view class="contentBox">
<view class="navBox">
<view class="navItem">
<image src="/static/img/index/zjhc.png" mode="widthFix"></image>
</view>
<view class="navItem">
<image src="/static/img/index/zjgs.png" mode="widthFix"></image>
</view>
<view class="navItem">
<image src="/static/img/index/aixz.png" mode="widthFix"></image>
</view>
<view class="navItem">
<image src="/static/img/index/kthf.png" mode="widthFix"></image>
</view>
</view>
<view class="indexTitle">
<image src="/static/img/index/title_zj.png" mode="widthFix"></image>
</view>
<view class="listBox">
<view class="photoBox">
<view class="photoTop">
<view class="topLeft">
<image src="/static/img/index/zj_icon.png" mode="widthFix"></image>
</view>
<view class="topCenter">
<view class="title">一寸照</view>
<view class="desc">25×35mm | 413×579px</view>
</view>
<view class="topRight">
<view class="distance">
<image src="/static/img/index/right.png" mode="widthFix"></image>
</view>
</view>
</view>
</view>
<view class="photoBox">
<view class="photoTop">
<view class="topLeft">
<image src="/static/img/index/zj_icon.png" mode="widthFix"></image>
</view>
<view class="topCenter">
<view class="title">二寸照</view>
<view class="desc">25×35mm | 413×579px</view>
</view>
<view class="topRight">
<view class="distance">
<image src="/static/img/index/right.png" mode="widthFix"></image>
</view>
</view>
</view>
</view>
<view class="photoBox">
<view class="photoTop">
<view class="topLeft">
<image src="/static/img/index/zj_icon.png" mode="widthFix"></image>
</view>
<view class="topCenter">
<view class="title">大一寸照</view>
<view class="desc">25×35mm | 413×579px</view>
</view>
<view class="topRight">
<view class="distance">
<image src="/static/img/index/right.png" mode="widthFix"></image>
</view>
</view>
</view>
</view>
<view class="photoBox">
<view class="photoTop">
<view class="topLeft">
<image src="/static/img/index/zj_icon.png" mode="widthFix"></image>
</view>
<view class="topCenter">
<view class="title">小一寸照</view>
<view class="desc">25×35mm | 413×579px</view>
</view>
<view class="topRight">
<view class="distance">
<image src="/static/img/index/right.png" mode="widthFix"></image>
</view>
</view>
</view>
</view>
</view>
<view class="indexTitle">
<image src="/static/img/index/title_xz.png" mode="widthFix"></image>
</view>
<view class="picList">
<scroll-view class="scrollBox" scroll-x="true" @scroll="scroll1" scroll-left="0">
<view class="picBox">
<view class="pic">
<image src="/static/img/index/pic.png" mode="widthFix"></image>
</view>
<view class="pic_title">风格名称</view>
</view>
<view class="picBox">
<view class="pic">
<image src="/static/img/index/pic.png" mode="widthFix"></image>
</view>
<view class="pic_title">风格名称</view>
</view>
<view class="picBox">
<view class="pic">
<image src="/static/img/index/pic.png" mode="widthFix"></image>
</view>
<view class="pic_title">风格名称</view>
</view>
<view class="picBox">
<view class="pic">
<image src="/static/img/index/pic.png" mode="widthFix"></image>
</view>
<view class="pic_title">风格名称</view>
</view>
</scroll-view>
</view>
<view class="indexTitle">
<image src="/static/img/index/title_kt.png" mode="widthFix"></image>
</view>
<view class="picList">
<scroll-view class="scrollBox" scroll-x="true" @scroll="scroll2" scroll-left="0">
<view class="picBox">
<view class="pic">
<image src="/static/img/index/pic.png" mode="widthFix"></image>
</view>
<view class="pic_title">风格名称</view>
</view>
<view class="picBox">
<view class="pic">
<image src="/static/img/index/pic.png" mode="widthFix"></image>
</view>
<view class="pic_title">风格名称</view>
</view>
<view class="picBox">
<view class="pic">
<image src="/static/img/index/pic.png" mode="widthFix"></image>
</view>
<view class="pic_title">风格名称</view>
</view>
<view class="picBox">
<view class="pic">
<image src="/static/img/index/pic.png" mode="widthFix"></image>
</view>
<view class="pic_title">风格名称</view>
</view>
</scroll-view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
banner: [
{
adImg:'/static/img/index/banner.png',
}
],
notice:'',
}
},
computed:{
},
onLoad() {
this.getHomeInfo();
},
onShareAppMessage() {
return {
title: '空间充-首页',
path: uni.$u.page(),
}
},
onShareTimeline() {
return {
title: '空间充-首页',
path: uni.$u.page(),
}
},
methods: {
//
getHomeInfo(){
var _this =this;
//post
_this.$api.post('ycl/home', {},function(res){
console.log(res);
var d = res;
var banner = d.adList
banner.forEach((item, index) => {
item.title = item.adName;
})
//_this.banner = banner;
//_this.notice = d.notice;
//_this.$user.session('servicePhone',d.servicePhone);
});
},
//
scroll1(e) {
console.log(e);
},
scroll2(e) {
console.log(e);
},
//
scanQrcode()
{
var _this =this;
_this.$com.showLoading('识别中...');
uni.scanCode({
onlyFromCamera: false,
success: function (res) {
console.log(res);
console.log('条码类型:' + res.scanType);
console.log('条码内容:' + res.result);
if (res.scanType == 'QR_CODE')
{
var url = res.result;
var codeTypeArr = ['deviceKey', 'deviceCode', 'qrcode', 'code']; //
var url_str = '';
codeTypeArr.forEach(function(item) {
if(url.indexOf(item) != -1 )
{
var keyindex = item;
var deviceKey = _this.getParameterByName(url,item);
if(!_this.$com.isNull(deviceKey))
{
if(['qrcode', 'code'].includes(item)) {
keyindex = 'deviceCode';
}
console.log(keyindex+'='+deviceKey);
url_str = `${keyindex}=${deviceKey}`;
return;
}
}
});
if(!_this.$com.isNull(url_str))
{
uni.$u.route({
url: '/pages/order/order?'+url_str,
});
}
else
{
_this.$com.alert('二维码格式有误');
}
}
else
{
_this.$com.alert('暂不支持此种条码类型');
}
},
fail:function(err){
_this.$com.alert('扫码失败,请重试');
},
complete:function(end){
_this.$com.hideLoading();
}
});
},
//url
getParameterByName(url,name) {
name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
var regexS = "[\\?&]" + name + "=([^&#]*)";
var regex = new RegExp(regexS);
var results = regex.exec(url);
if (results == null) return "";
else return decodeURIComponent(results[1].replace(/\+/g, " "));
},
openAd(index)
{
var _this =this;
var item = _this.banner[index];
console.log(item);
if(!_this.$com.isNull(item.jumpUrl))
{
console.log(item.jumpUrl);
var url = '';
switch(item.jumpType)
{
case 0:
url=item.jumpUrl;
break;
case 1:
url='/pages/web/index?title='+item.adName+'&url='+encodeURIComponent(item.jumpUrl);
break;
case 2:
url='/pages/web/video?title='+item.adName+'&url='+encodeURIComponent(item.jumpUrl);
break;
default:
url = '';
}
if(!_this.$com.isNull(url))
{
uni.navigateTo({
url:url,
})
}
}
},
}
}
</script>
<style lang="scss">
.container{width: 100%;}
.bannerBox{
width: 100%;
background: #082436;
height: auto;
position: relative;
}
::v-deep .u-swiper{background-color: inherit !important;}
.contentBox{
width:746rpx;
height: 500rpx;
background: linear-gradient( 180deg, #DBD9FF 0%, #F5F6FB 100%);
border-radius: 28rpx 28rpx 0rpx 0rpx;
border: 2rpx solid #FFFFFF;
margin-top: -80rpx;
position: relative;
z-index: 2;
}
.navBox{ width: 100%; height: auto; display: flex;}
.navBox .navItem{ width: 164rpx; height: 140rpx; margin: 40rpx 20rpx 20rpx 20rpx;}
.navBox .navItem image{ width: 100%; height: auto;}
.indexTitle {width: 730rpx; height: auto; margin: 20rpx auto; padding-left: 20rpx; }
.indexTitle image{ width: 226rpx; height: auto;}
.listBox{ width: 100%; height: auto;}
.photoBox{
padding:20rpx 10rpx 10rpx 10rpx;
height: auto;
border-radius: 24rpx 24rpx 24rpx 24rpx;
opacity: 1;
background: #FFFFFF;
width: 670rpx;
margin: 15rpx auto;
}
.photoTop{width: 100%; height: auto; display: flex;
}
.photoTop .topLeft{
width: 100rpx;
height: 88rpx;
}
.topLeft image{ width: 60rpx; height: auto; margin-left: 14rpx;}
.photoTop .topCenter{
width: 400rpx;
height: auto;
padding-left: 18rpx;
}
.topCenter .title{
font-size: 30rpx;
font-weight: 400;
color:#333333;
line-height: 50rpx;
width: 100%;
overflow: hidden; //
white-space: nowrap; //
text-overflow: ellipsis; //
}
.topCenter .desc{
font-size: 24rpx;
color:#999999;
line-height: 30rpx;
width: 100%;
overflow: hidden; //
white-space: nowrap; //
text-overflow: ellipsis; //
}
.photoTop .topRight{
width: 160rpx;
height: auto;
text-align: right;
}
.topRight .distance{ color: #90A1AA; font-size: 24rpx; font-family: PingFang SC-Regular; padding-top: 20rpx;}
.topRight .distance image{ width: 32rpx; height: 32rpx; margin-right: 24rpx;}
.picList{ width: 100%; height: 360rpx;}
.scrollBox {
margin-top: 20rpx;
width: 100%;
height: 360rpx;
white-space: nowrap;
}
.picBox {
display: inline-block;
width:260rpx;
height: 360rpx;
text-align: center;
position: relative;
margin-left: 20rpx;
}
.picBox .pic{
position: absolute;
width:100%;
height: 360rpx;
}
.picBox .pic image{
width:260rpx;
height: 360rpx;
border-radius:24rpx;
}
.picBox .pic_title{
position: absolute;
width:240rpx;
height: 72rpx;
bottom: 0;
z-index: 2;
font-size: 24rpx; line-height: 72rpx;
padding-left: 20rpx;
color: #FFFFFF;
text-align: left;
overflow: hidden; //
white-space: nowrap; //
text-overflow: ellipsis; //
}
</style>

@ -0,0 +1,275 @@
<template>
<view class="container">
<view class="form">
<!--input box start-->
<view class='input_box'>
<view class='i_box_1'>头像</view>
<view class='i_box_2'></view>
<view class='i_box_3'>
</view>
<view class='i_box_4'></view>
<view class='i_box_5'>
<view class="up">
<view class="img">
<u-upload
:fileList="wxAvatar"
@afterRead="afterRead"
@delete="deletePic"
name="avatar"
width="26"
height="26"
:sizeType="['compressed']"
:deletable="true"
:maxCount="1"
:previewFullImage="false"
>
</u-upload>
</view>
<view class="icon" @click="clearImg">
<u-icon name="arrow-right" top="5"></u-icon>
</view>
</view>
</view>
</view>
<!--input box end-->
<!--input box start-->
<view class='input_box'>
<view class='i_box_1'>昵称</view>
<view class='i_box_2'></view>
<view class='i_box_3x'>
<u--input
placeholder="请输入昵称"
inputAlign="right"
border="none"
color="#FFFFFF"
maxlength="10"
v-model="info.wxName"
></u--input>
</view>
</view>
<!--input box end-->
<!--input box start-->
<view class='input_box'>
<view class='i_box_1'>手机号</view>
<view class='i_box_2'></view>
<view class='i_box_3x'>
<u--input
v-if="!this.$com.isNull(info.phoneNumber)"
inputAlign="right"
border="none"
color="#FFFFFF"
maxlength="11"
v-model="info.phoneNumber"
:readonly="true"
></u--input>
<u-button v-else :text="info.phoneNumber || '点击获取手机号'" openType="getPhoneNumber" @getphonenumber="getPhoneNumber"></u-button>
</view>
</view>
<!--input box end-->
</view>
<view class="btn-big"><u-button type="info" :loading="btn_loading" loadingText="加载中" :disabled="btn_disabled" text="保存" @click="add"></u-button></view>
</view>
</template>
<script>
export default {
data() {
return {
//form
info: {
wxName:'',
wxAvatar:'',
phoneNumber:'点击获取手机号',
},
wxAvatar: [],
//
btn_loading:false,
btn_disabled:false,
}
},
onLoad(option) {
var _this = this;
_this.getUserInfo();
},
methods: {
//
getUserInfo()
{
var _this =this;
var post ={};
_this.$api.post('ycl/user/wx-info',post,function(rs){
console.log(rs);
_this.info = rs;
_this.wxAvatar =[{url:rs.wxAvatar}];
});
},
//
deletePic(event) {
var _this = this;
_this.wxAvatar = [];
},
//
afterRead(event) {
var _this = this
console.log('event',event);
var edetail = event.file.thumb;
if (edetail.indexOf('http://tmp') != -1 || edetail.indexOf('wxfile://tmp') != -1)
{
var FSM = uni.getFileSystemManager();
FSM.readFile({
filePath: edetail,
encoding: "base64",
success: function(data) {
_this.info.imgBase64 = "data:image/png;base64," + data.data
_this.wxAvatar = [{url:edetail}];
},
fail: function(err){
console.log('http://tmp',err)
}
})
}
},
uploadFilePromise(url) {
},
loadData(){
},
getPhoneNumber(e){
var _this =this;
var detail = e.detail;
console.log(detail);
if (detail.errMsg === 'getPhoneNumber:ok') {
_this.getPhoneApi(detail);
} else {
_this.$com.alert('授权失败')
}
},
getPhoneApi(detail){
var _this = this;
var post ={
code: detail.code,
};
_this.$api.post('ycl/user/wx-phone',post,function(rs){
console.log(rs);
_this.info.phoneNumber = rs;
},function(err){
console.log(err);
});
},
//
add(){
var _this =this;
var info = _this.info;
if(_this.$com.isNull(info.wxName))
{
_this.$com.showError('请输入昵称');
return;
}
if(_this.$com.isNull(info.wxAvatar) && _this.$com.isNull(info.imgBase64))
{
_this.$com.showError('请上传头像');
return;
}
if(_this.$com.isNull(info.phoneNumber))
{
_this.$com.showError('手机号必须');
return;
}
_this.btn_loading = true;
_this.btn_disabled = true;
var post = info;
_this.$api.put('ycl/user/wx-update',post,function(rs){
console.log('更新token');
_this.$user.session('token',rs.token);
_this.$com.alert('更新成功');
setTimeout(function(){
uni.$u.route({
type:'navigateBack',
delta:1,
});
},1000);
});
//
_this.btn_loading = false;
_this.btn_disabled = false;
},
}
}
</script>
<style lang="scss">
.container{padding:10rpx 20rpx;}
.form{ padding: 20rpx;
background: #082436;
border-radius: 24rpx 24rpx 24rpx 24rpx;
}
/*form基本元素*/
/*input_box*/
.input_box{ display: flex;flex-direction:row; height: 100rpx; line-height: 100rpx;
border-radius: 15rpx;box-shadow: 0 2rpx 2rpx rgba(0, 0, 0, 0.05); margin: 20rpx auto; color:#FFFFFF;}
.i_box_1{ width: 25%;height: 100rpx; font-size: 28rpx; text-align: left; }
.i_box_2{width: 0.3%;height: 80rpx; margin-top: 10rpx;}
.i_box_3{ height: 100rpx;min-width: 49.4%; width: auto;font-size: 26rpx;}
/*特殊的 改变部分*/
.i_box_3x{height: 100rpx;min-width: 74.7%; width: auto;font-size: 26rpx;}
::v-deep .u-input{ border:none !important; color:#FFFFFF !important; margin-top: 10rpx;}
.up{ width: 100%; height: auto; display: flex; margin-top: 20rpx;}
.up .img{width:80%; }
.up .img .u-upload{ margin-left: 80rpx;}
.up .icon{ width:20%;}
::v-deep .i_box_3x .u-button--info{ background-color: transparent !important; border: none !important; color: #FFFFFF !important; text-align: right !important;}
::v-deep .i_box_3x .u-button{display: block !important; padding:0rpx !important;}
::v-deep .u-upload__button{border-radius: 50% !important;}
::v-deep .u-upload__wrap__preview{border-radius: 50% !important;}
.btn-big{ width:100%;
height: 92rpx;
line-height: 92rpx;
margin:30rpx auto;
display:block;
border-radius:56rpx;
background:#00F0E2;
font-size:28rpx;
color:#fff;text-align: center;}
::v-deep .btn-big .u-button--info{ background-color: transparent !important; border: none !important; color: #FFFFFF !important; }
</style>

@ -0,0 +1,176 @@
<template>
<view class="container">
<view class="input_box">
<text class="input_title">{{$t('pages.user.auth.login.mobile')}}</text>
<view class="input_content">
<u--input
:placeholder="$t('pages.user.auth.login.input_mobile')"
prefixIcon="phone"
prefixIconStyle="font-size: 24rpx;color: #909399"
v-model="form.mobile"
@change="mobileChange"
></u--input>
</view>
</view>
<view class="input_box">
<text class="input_title">{{$t('pages.user.auth.login.password')}}</text>
<view class="input_content">
<u--input
:placeholder="$t('pages.user.auth.login.input_password')"
prefixIcon="lock"
prefixIconStyle="font-size: 24rpx;color: #909399"
border="surround"
password
clearable
v-model="form.password"
@change="pwdChange"
></u--input>
</view>
</view>
<view class="button_box">
<view class="submit">
<u-button type="primary" :plain="true" :hairline="true" :text="$t('locale.login')" size="normal" @click="login"></u-button>
</view>
</view>
<view class="footer">
<!-- <text class="footer-text">找回密码</text> -->
<text class="footer-text" @click="regist">{{$t('locale.regist')}}</text>
<!-- <text class="footer-text">投诉建议</text> -->
</view>
</view>
</template>
<script>
export default {
components: {
},
data() {
return {
form:{
mobile:'',
password:'',
},
};
},
onShow() {
var _this =this;
},
methods:{
//
regist(){
uni.$u.route({
type:'redirectTo',
url: 'pages/user/auth/regist',
params: {}
});
},
//
mobileChange(e)
{
var _this = this;
_this.form['mobile'] = e;
},
//
pwdChange(e)
{
var _this = this;
_this.form['password'] = e;
},
login(){
var _this =this;
var form = _this.form;
if(!_this.$com.check(form.mobile,'mobile'))
{
uni.$u.toast(_this.$t('pages.user.auth.login.mobile_must'));
return false;
}
if(form.password.length < 6)
{
uni.$u.toast(_this.$t('pages.user.auth.login.password_must'));
return false;
}
var post = form;
_this.$api.post('user/log',post,function(rs){
console.log(rs);
_this.$user.session('userInfo',rs.userinfo);
_this.$user.session('token',rs.token);
uni.$u.route({
type:'navigateBack',
delta:2,
params: {}
});
},function(err){
console.log(err);
});
},
},
};
</script>
<style scoped lang="scss">
/*输入框*/
.input_box{
width: 90%;
margin: 40rpx auto 40rpx auto;
height: auto;
}
.input_title{
font-size: 30rpx;
color: #ABABAB;
height: 50rpx;
line-height: 50rpx;
margin: 10rpx auto;
display: block;
}
.button_box {
width: 90%;
margin: 40rpx auto 20rpx auto;
}
.submit {
width: 100%;
background-color: #4CAF50;
justify-content: center;
align-items: center;
border-radius: 10rpx;
}
.submit-text {
color: white;
padding: 30rpx;
}
.submit:active {
background-color: green;
opacity: 0.5;
}
.footer {
flex-direction: row;
justify-content: center;
text-align: center;
align-items: center;
margin-top: 100rpx;
}
.footer-text {
font-size: 28rpx;
color: #296db5;
padding: 30rpx;
}
</style>

@ -0,0 +1,205 @@
<template>
<view class="container">
<view class="input_box">
<text class="input_title">{{$t('pages.user.auth.login.mobile')}}</text>
<view class="input_content">
<u--input
:placeholder="$t('pages.user.auth.login.input_mobile')"
prefixIcon="phone"
prefixIconStyle="font-size: 24rpx;color: #909399"
type="number"
v-model="form.mobile"
@change="mobileChange"
></u--input>
</view>
</view>
<view class="input_box">
<text class="input_title">{{$t('pages.user.auth.login.password')}}</text>
<view class="input_content">
<u--input
:placeholder="$t('pages.user.auth.login.input_password')"
prefixIcon="lock"
prefixIconStyle="font-size: 24rpx;color: #909399"
border="surround"
password
clearable
v-model="form.password"
@change="pwdChange"
></u--input>
</view>
</view>
<view class="input_box">
<text class="input_title">{{$t('pages.user.auth.login.email')}}</text>
<view class="input_content">
<u--input
:placeholder="$t('pages.user.auth.login.input_email')"
prefixIcon="email"
prefixIconStyle="font-size: 24rpx;color: #909399"
v-model="form.email"
@change="emailChange"
></u--input>
</view>
</view>
<view class="button_box">
<view class="submit">
<u-button type="primary" :plain="true" :hairline="true" :text="$t('locale.regist')" size="normal" @click="regist"></u-button>
</view>
</view>
<view class="footer">
<!-- <text class="footer-text">找回密码</text> -->
<text class="footer-text" @click="login">{{$t('locale.login')}}</text>
<!-- <text class="footer-text">投诉建议</text> -->
</view>
</view>
</template>
<script>
export default {
components: {
},
data() {
return {
form:{
mobile:'',
password:'',
email:'',
},
};
},
onShow() {
var _this =this;
},
methods:{
//
login(){
uni.$u.route({
type:'redirectTo',
url: 'pages/user/auth/login',
params: {}
});
},
//
mobileChange(e)
{
var _this = this;
_this.form['mobile'] = e;
},
//
pwdChange(e)
{
var _this = this;
_this.form['password'] = e;
},
//email
emailChange(e)
{
var _this = this;
_this.form['email'] = e;
},
regist()
{
var _this =this;
var form = _this.form;
if(!_this.$com.check(form.mobile,'mobile'))
{
uni.$u.toast(_this.$t('pages.user.auth.login.mobile_must'));
return false;
}
if(form.password.length < 6)
{
uni.$u.toast(_this.$t('pages.user.auth.login.password_must'));
return false;
}
if(!_this.$com.check(form.email,'email'))
{
uni.$u.toast(_this.$t('pages.user.auth.login.email_must'));
return false;
}
var post = form;
_this.$api.post('user/reg',post,function(rs){
console.log(rs);
uni.showModal({
title: _this.$t('locale.tips'),
content: _this.$t('pages.user.auth.regist.regist_success'),
success: function (res) {
if (res.confirm) {
console.log('用户点击确定');
_this.login();
} else if (res.cancel) {
console.log('用户点击取消');
}
}
});
},function(err){
console.log(err);
});
},
},
};
</script>
<style scoped lang="scss">
/*输入框*/
.input_box{
width: 90%;
margin: 40rpx auto 40rpx auto;
height: auto;
}
.input_title{
font-size: 30rpx;
color: #ABABAB;
height: 50rpx;
line-height: 50rpx;
margin: 10rpx auto;
display: block;
}
.button_box {
width: 90%;
margin: 40rpx auto 20rpx auto;
}
.submit {
width: 100%;
background-color: #4CAF50;
justify-content: center;
align-items: center;
border-radius: 10rpx;
}
.submit-text {
color: white;
padding: 30rpx;
}
.submit:active {
background-color: green;
opacity: 0.5;
}
.footer {
flex-direction: row;
justify-content: center;
text-align: center;
align-items: center;
margin-top: 100rpx;
}
.footer-text {
font-size: 28rpx;
color: #296db5;
padding: 30rpx;
}
</style>

@ -0,0 +1,536 @@
<template>
<view>
<view class="header">
<image class='background' src="/static/img/user/topbg.png" mode="aspectFill"></image>
<view class="userInfo">
<view class="uleft">
<u-image :src="userInfo.wxAvatar" width="60px" height="60px" radius="30px" @error="imgErr"></u-image>
</view>
<view class="ucenter">
<view class="name"><text class="username">{{userInfo.wxName}}</text><text class="level">{{identityinfo.levelTxt}}</text></view>
</view>
<view class="uright">
<view class="change" v-if="!this.$com.isNull(userInfo.phoneNumber)">
<u-button text="切换" openType="getPhoneNumber" @getphonenumber="getPhoneNumber"></u-button>
</view>
</view>
</view>
<view class="userItem">
<view class="uItemBox">
<view class="num">{{userInfo.totalAmount > 0 ? userInfo.totalAmount / 100 : '0.00'}}</view>
<view class="text">消费金额()</view>
</view>
<view class="uItemBox">
<view class="num">{{userInfo.totalDur > 0 ? userInfo.totalDur : 0}}</view>
<view class="text">使用时长()</view>
</view>
</view>
</view>
<view class="orderBox">
<view class="orderBoxTitle">我的订单</view>
<view class="orderItem">
<view class="oItemBox" v-for="(item,key) in ordermenu" :key="key" @click="goTo(item.url)">
<view class="image">
<image :src="item.icon" mode="widthFix"></image>
</view>
<view class="order_text">{{item.label}}</view>
</view>
</view>
</view>
<view class="moneyBox" v-if="identityinfo.levelVal < 4">
<view class="moneyBoxTitle">收入抽成</view>
<view class="moneyBoxItem">
<view class="mItemBox">
<view class="money">
<text class="unit"></text><text class="num">{{userInfo.todayIncome > 0 ? userInfo.todayIncome / 100 :'0.00'}}</text>
</view>
<view class="order_text">今日收入</view>
</view>
<view class="mItemBox">
<view class="money">
<text class="unit"></text><text class="num">{{userInfo.totalIncome > 0 ? userInfo.totalIncome / 100 :'0.00'}}</text>
</view>
<view class="order_text">总收入</view>
</view>
<view class="mItemBox">
<view class="money">
<text class="unit"></text><text class="num">{{userInfo.todayLevelIncome > 0 ? userInfo.todayLevelIncome / 100 :'0.00'}}</text>
</view>
<view class="order_text">今日抽成</view>
</view>
<view class="mItemBox">
<view class="money">
<text class="unit"></text><text class="num">{{userInfo.totalLevelIncome > 0 ? userInfo.totalLevelIncome / 100 :'0.00'}}</text>
</view>
<view class="order_text">总抽成</view>
</view>
</view>
</view>
<view class="serviceBox">
<view class="serviceBoxTitle">我的服务</view>
<view class="serviceItem">
<view class="sItemBox" v-for="(item,key) in shopmenu" :key="key" v-if="item.level >= identityinfo.levelVal" @click="goTo(item.url)">
<view class="image">
<image :src="item.icon" mode="widthFix"></image>
</view>
<view class="order_text">{{item.label}}</view>
</view>
</view>
<view class="ad">
<image src="@/static/img/user/banner.jpg" mode="widthFix" @click="openVideo"></image>
</view>
</view>
<view class="serviceBox">
<view class="serviceBoxTitle">我的工具</view>
<view class="serviceItem">
<view class="sItemBox" v-for="(item,key) in setmenu" :key="key" @click="tools(item)">
<view class="image">
<image :src="item.icon" mode="widthFix"></image>
</view>
<view class="order_text">{{item.label}}</view>
</view>
</view>
</view>
<view class="nowENV" v-if="this.$api.env() == 'development' || this.$api.env() == 'local'">
<u-tag v-if="this.$api.env() == 'development'" text="线上测试环境" type="warning" plain plainFill></u-tag>
<u-tag v-if="this.$api.env() == 'local'" text="本地开发环境" type="error" plain plainFill></u-tag>
</view>
<view class="empty">
</view>
<u-popup :show="video_show" :round="10" mode="center" :closeable="true" customStyle="{width:750rpx,height:auto}" @close="closeVideo">
<view class="videoBox">
<video id="myVideo" :src="video_src" @error="videoErrorCallback" :autoplay="false" controls></video>
</view>
</u-popup>
</view>
</template>
<script>
export default {
data() {
return {
isLogin:false, //
userInfo:{
wxAvatar:'/static/img/user/avatar.png',
wxName:'点击登录',
totalAmount:0.00,
totalDur:0,
},
isShop:false, //
ordermenu: [
{ label: '全部', icon: '/static/img/user/order_all.png', url: '/pages/order/list?tab=0'},
{ label: '进行中', icon: '/static/img/user/order_ing.png', url: '/pages/order/list?tab=1'},
{ label: '已完成', icon: '/static/img/user/order_finish.png', url: '/pages/order/list?tab=2'},
],
shopmenu: [
{ label: '店铺管理', icon: '/static/img/order/store.png', url: '/pages/user/shop/shopmanage', level: 3},
{ label: '收入记录', icon: '/static/img/user/money_log.png', url: '/pages/user/mine/income', level: 3},
{ label: '提现申请', icon: '/static/img/user/withdraw.png', url: '/pages/user/mine/withdraw', level: 3},
{ label: '我的下级', icon: '/static/img/user/link.png', url: '/pages/user/mine/leveluser', level: 2},
{ label: '查看码值', icon: '/static/img/user/code.png', url: '/pages/user/shop/lookcode', level: 3},
{ label: '提现记录', icon: '/static/img/user/withdraw_log.png', url: '/pages/user/mine/withdrawrecord', level: 3},
],
setmenu: [
{ label: '账户设置', icon: '/static/img/user/account.png', type: 'normal',url: '/pages/user/account/index'},
{ label: '联系客服', icon: '/static/img/user/chat.png', type: 'service',url:''},
{ label: '代理入驻', icon: '/static/img/user/settled.png', type: 'normal',url: '/pages/user/mine/settled'}
],
//
identityinfo:'',
//
video_show:false,
video_src:'https://kjc.oss-cn-shenzhen.aliyuncs.com/video/demo.mp4',
};
},
onReady: function (res) {
this.videoContext = uni.createVideoContext('myVideo')
},
onShow() {
var _this =this;
var openid = _this.$user.session('openid');
if(!_this.$com.isNull(openid))
{
_this.isLogin = true;
_this.getUserInfo();
}
},
onShareAppMessage() {
return {
title: '空间充-我的',
path: uni.$u.page(),
}
},
onShareTimeline() {
return {
title: '空间充-我的',
path: uni.$u.page(),
}
},
methods:{
//
imgErr(){
this.userInfo.wxAvatar = '/static/img/user/avatar.png';
},
//
getUserInfo()
{
var _this =this;
var post ={};
_this.$api.post('ycl/user/wx-info',post,function(rs){
console.log(rs);
_this.userInfo = rs;
_this.$user.session('lifeData',rs);
var identityinfo = _this.$access.checkidentity(rs);
console.log(identityinfo);
_this.identityinfo = identityinfo;
_this.$user.session('identityinfo',identityinfo);
if(identityinfo.levelVal != 4)
{
var setmenu = _this.setmenu;
var updatedSetmenu = setmenu.filter(item => item.label !== '代理入驻');
_this.setmenu = updatedSetmenu;
}
},function(err){
console.log(err);
});
},
goTo(url)
{
uni.$u.route({
type:'navigateTo',
url: url,
});
},
tools(item)
{
var _this =this;
if(item.type == 'service')
{
var phone = _this.$user.session('servicePhone');
uni.makePhoneCall({
phoneNumber: phone,
success(res) {
console.log(res);
},
fail(err) {
console.log(err);
},
});
}
else
{
uni.$u.route({
type:'navigateTo',
url: item.url,
});
}
},
//
openVideo(){
var _this =this;
_this.video_show = true;
},
videoErrorCallback(e)
{
console.log(e);
},
closeVideo(){
var _this =this;
_this.video_show = false;
_this.videoContext.pause = true;
},
getPhoneNumber(e){
var _this =this;
var detail = e.detail;
console.log(detail);
if (detail.errMsg === 'getPhoneNumber:ok') {
_this.getPhoneApi(detail);
} else {
_this.$com.alert('授权失败')
}
},
getPhoneApi(detail){
var _this = this;
var openid = _this.$user.session('openid');
var post ={
code: detail.code,
};
_this.$api.post('ycl/user/wx-phone',post,function(rs){
console.log(rs);
var phoneNumber = rs;
_this.userInfo.phoneNumber = phoneNumber;
if(_this.$com.isNull(openid))
{
_this.$com.alert('切换失败,请退出并重新进入小程序重试');
}
// #ifdef MP
//
uni.getProvider({
service: 'oauth',
success: function (res) {
console.log(res.provider)
var provider = res.provider[0];
uni.login({
provider:provider,
scopes:'auth_base',
success: function (login) {
console.log(login);
//
var xpost = {
loginCode: login.code,
phoneNumber:phoneNumber,
};
_this.$api.post('ycl/user/wx-login', xpost,function(resx){
console.log(resx);
_this.$user.session('openid',resx.wxOpenid);
_this.$user.session('user_id',resx.id);
if(!_this.$com.isNull(resx.token))
{
_this.$user.session('token',resx.token);
}
_this.isLogin = true;
_this.getUserInfo();
});
},
fail:function(rs){
console.log('登录失败'+rs.errMsg);
}
});
}
});
// #endif
},function(err){
console.log(err);
});
},
},
};
</script>
<style lang="scss">
page{ height:100%; width: 100%;}
.container{padding:10rpx 20rpx;}
.header{ width: 100%; height: 500rpx; overflow: hidden; position: relative;}
.background {
width: 100%;
height: 100%;
position:absolute;
background-size:100% 100%;
z-index: -1;
}
.userInfo{ width: 670rpx; height: auto; display: flex; margin: 100rpx auto 50rpx auto;}
.userInfo .uleft{ width: 120rpx; height: 120rpx;}
.userInfo .ucenter{ width: 430rpx; height: 120rpx; line-height: 120rpx;}
.userInfo .ucenter .name{ width: 100%; height: 120rpx;}
.userInfo .ucenter .name .username{font-size: 36rpx; color:#FFFFFF; margin-left:20rpx;}
.userInfo .ucenter .name .level{width: auto; padding: 2rpx 10rpx;
height: 44rpx;
background: #095E59; text-align: center; font-size: 24rpx;color: #FFFFFF;
border-radius: 42rpx 42rpx 42rpx 42rpx;
border: 1rpx solid #00F0E2; margin-left: 20rpx;}
.userInfo .uright{ width: 120rpx; height: 120rpx;}
.userInfo .uright .change{width: 104rpx;
height: 50rpx;
background: #00F0E2;
border-radius: 42rpx 42rpx 42rpx 42rpx; color: #1E2629; font-size: 28rpx; line-height: 50rpx; text-align: center;}
::v-deep .change .u-button{display: block !important; padding:0rpx !important; background-color: inherit !important; height:auto !important; border: none !important; border-radius: 42rpx !important;}
.userItem{
color: #FFFFFF;
width: 100%;
height: auto;
display: flex;
}
.uItemBox{ width:50%; text-align: center;}
.uItemBox .num{
font-size: 40rpx;
font-family: DIN, DIN;
font-weight: bold;
}
.uItemBox .text{
font-size: 24rpx;
font-family: PingFang SC, PingFang SC;
font-weight: 400;
line-height: 28rpx;
}
/*订单部分*/
.orderBox{
width: 670rpx;
height: auto;
background: #082436;
border-radius: 24rpx 24rpx 24rpx 24rpx;
opacity: 1;
margin: 0rpx auto;
padding: 20rpx;
}
.orderBoxTitle{
font-size: 28rpx;
font-weight: bold;
color:#FFFFFF;
line-height: 60rpx;
}
.orderItem{
width: 100%; height: auto;
display: flex;
text-align: center;
}
.oItemBox{
width: 33.33%;
}
.oItemBox .image{ width: 100%; text-align: center; margin-top: 20rpx;}
.oItemBox .image image{width: 64rpx; height: auto; margin: 0rpx auto; }
.oItemBox .order_text{
text-align: center;
font-size: 24rpx;
font-weight: 400;
line-height: 30rpx;
color: #FFFFFF;
}
/*收入部分*/
.moneyBox{
width: 670rpx;
height: auto;
background: #082436;
border-radius: 24rpx 24rpx 24rpx 24rpx;
opacity: 1;
margin: 20rpx auto;
padding: 20rpx;
}
.moneyBoxTitle{
font-size: 28rpx;
font-weight: bold;
color:#FFFFFF;
line-height: 40rpx;
}
.moneyBoxItem{
margin-top: 20rpx;
width: 100%; height: auto;
display: flex;
text-align: center;
gap:20rpx;
}
.mItemBox{
width: 152rpx;
height: 128rpx;
background: linear-gradient(180deg, rgba(49,156,255,0) 0%, rgba(0,255,240,0.5) 100%);
border-radius: 16rpx 16rpx 16rpx 16rpx;
opacity: 1;
border: 1rpx solid #00F0E2;
}
.mItemBox .money{ width: 100%; text-align: center; color: #FFFFFF; line-height: 80rpx;}
.mItemBox .money .unit{ font-size: 24rpx;
font-family: PingFang SC, PingFang SC;
font-weight: bold;}
.mItemBox .money .num{ font-size: 30rpx;
font-family: DIN, DIN;
font-weight: 400;
}
.mItemBox .order_text{
text-align: center;
font-size: 24rpx;
font-weight: 400;
line-height: 30rpx;
color: #FFECAA;
}
/*服务*/
.serviceBox{
width: 670rpx;
height: auto;
background: #082436;
border-radius: 24rpx 24rpx 24rpx 24rpx;
opacity: 1;
margin: 20rpx auto;
padding: 20rpx;
}
.serviceBoxTitle{
font-size: 28rpx;
font-weight: bold;
color:#FFFFFF;
line-height: 60rpx;
}
.serviceItem{
width: 100%; height: auto;
display: flex;
text-align: center;
flex-wrap:wrap;
}
.sItemBox{
width: 25%;
}
.sItemBox .image{ width: 100%; text-align: center; margin-top: 20rpx;}
.sItemBox .image image{width: 48rpx; height: auto; margin: 0rpx auto; }
.sItemBox .order_text{
text-align: center;
font-size: 24rpx;
font-weight: 400;
line-height: 30rpx;
color: #FFFFFF;
}
.nowENV{ width: 200rpx; height: 60rpx; margin: 10rpx auto; text-align: center;}
.empty{width: 100%; height: 20rpx;}
.ad{ width: 100%; height: auto; text-align: center; margin:0rpx auto;}
.ad image{ width:100%; margin-top:20rpx;border-radius: 30rpx;}
.videoBox{ width: 750rpx; height: 900rpx;}
.videoBox video{ width: 100%; height: 100%;}
</style>

@ -0,0 +1,220 @@
<template>
<view class="u-page">
<view class="empty-select">
<u-cell
:titleStyle="{fontWeight: 500}"
@click="changeLang"
:title="$t('pages.user.setting.index.setLang')"
:value="nowLang"
isLink
>
<image
slot="icon"
class="u-cell-icon"
src="@/static/img/common/lang.png"
mode="widthFix"
></image>
</u-cell>
</view>
<view class="btn_box">
<u-button type="primary" :plain="true" :hairline="true" :text="$t('locale.logout')" size="normal" @click="logout"></u-button>
</view>
<u-action-sheet
:show="changeLangShow"
@close="changeLangShow = false"
:actions="langList"
@select="confirmLang"
cancelText="取消"
>
</u-action-sheet>
</view>
</template>
<script>
export default {
data() {
return {
systemLocale: '',
applicationLocale: '',
nowLang:'',//
// list: [{
// imgName: 'lang',
// title: this.$t('pages.user.setting.index.setLang'),
// iconUrl: '/static/img/common/lang.png',
// },
// ],
changeLangShow:false,
langList: [
{
name: this.$t('locale.zh-hans'),
val:'zh-Hans',
},
{
name: this.$t('locale.zh-hant'),
val:'zh-Hant',
},
{
name: this.$t('locale.en'),
val:'en'
}],
langListVal:['zh-Hans','zh-Hant','en'],
}
},
onLoad() {
var _this =this;
_this.loadData();
},
methods: {
loadData(){
var _this =this;
let systemInfo = uni.getSystemInfoSync();
_this.systemLocale = systemInfo.language;
var lang = uni.getLocale();
console.log('lang:'+lang);
_this.applicationLocale =lang;
_this.returnLang(lang);
_this.isAndroid = systemInfo.platform.toLowerCase() === 'android';
uni.onLocaleChange((e) => {
_this.applicationLocale = e.locale;
_this.returnLang(e.locale);
})
},
returnLang(code)
{
var _this =this;
var list = _this.langListVal;
list.forEach((item, $index, arr) => {
//console.log(`${item} => ${$index} => ${arr}`);
if(item == code)
{
console.log(_this.langList[$index].name);
_this.nowLang = _this.langList[$index].name;
return;
}
})
},
//
changeLang() {
//this[`show${index}`] = true
this[`changeLangShow`] = true;
},
confirmLang(e){
console.log(e);
var _this =this;
_this.onLocaleChange(e.val);
},
onLocaleChange(code) {
var _this =this;
_this[`changeLangShow`] = false;
uni.showModal({
content: _this.$t('locale.language-change-confirm'),
success: (res) => {
if (res.confirm) {
uni.setLocale(code);
_this.$i18n.locale = code;
_this.returnLang(code);
uni.switchTab({
url:'pages/index/index'
})
}
}
})
},
//退
logout(){
var _this =this;
var post = {};
_this.$api.post('user/logout',post,function(rs){
console.log(rs);
uni.removeStorageSync('userInfo');
uni.removeStorageSync('token');
uni.$u.route({
type:'switchTab',
url:'pages/index/index',
params: {}
});
},function(err){
console.log(err);
});
uni.$u.toast(_this.$t('locale.logout'));
},
}
}
</script>
<style lang="scss">
.u-block{
padding: 14px;
&__section{
margin-bottom:10px;
}
&__title {
margin-top:10px;
font-size: 15px;
color: $u-content-color;
margin-bottom:10px;
}
&__flex{
/* #ifndef APP-NVUE */
display: flex;
/* #endif */
}
}
// 使cellicon
.u-cell-icon {
width: 36rpx;
height: 36rpx;
margin-right: 8rpx;
}
.u-page {
padding: 15px 15px 40px 15px;
}
.u-demo-block {
flex: 1;
margin-bottom: 23px;
&__content {
@include flex(column);
}
&__title {
font-size: 14px;
color: rgb(143, 156, 162);
margin-bottom: 8px;
@include flex;
}
}
.u-page {
padding: 40rpx 0px;
&__top-box {
padding-left: 40rpx;
}
}
.empty-select {
margin-top: 0px;
}
.btn_box{ width: 80%; margin: 120rpx auto 20rpx auto;}
</style>

@ -0,0 +1,77 @@
<template>
<view>
<web-view ref="webview" :src="xurl" :update-title="true" :webview-styles="webviewStyles" @message="getMessage"></web-view>
</view>
</template>
<script>
var wv;//webview
export default {
data() {
return {
xurl: '',
old_url:'',
webviewStyles: {
progress: {
color: '#FF3333'
}
},
};
},
onReady() {
},
onLoad(option) {
//
var _this =this;
var url = option.url;
var title = option.title;
if(_this.$com.isNull(url))
{
uni.navigateBack({
delta:1,
})
}
_this.old_url = url;
_this.xurl = decodeURIComponent(url);
if(!_this.$com.isNull(title))
{
var pageTitle = title;
}
else
{
var pages = getCurrentPages();
var page = pages[pages.length - 1];
// #ifndef APP-PLUS
var pageTitle = page.$page.meta.navigationBar.titleText;
// #endif
// #ifdef APP-PLUS
var webView = currentPage.$getAppWebview();
var pageTitle = webView.getStyle().name;
// #endif
if(_this.$com.isNull(pageTitle))
{
pageTitle = 'webview';
}
}
uni.setNavigationBarTitle({
title:pageTitle,
})
},
methods: {
getMessage(event) {
// #ifdef APP-PLUS
console.log('event', event);
// #endif
},
},
};
</script>
<style>
</style>

@ -0,0 +1,53 @@
<template>
<view class="container">
<view class="videoBox">
<video id="myVideo" :style="{width: '100%', height: '100%'}"
:src="video_src" @error="videoErrorCallback" :autoplay="false" controls></video>
</view>
</view>
</template>
<script>
export default {
data() {
return {
old_url:'',
video_src:'',
}
},
onLoad(option) {
//
var _this =this;
var url = option.url;
var title = option.title;
if(_this.$com.isNull(url))
{
uni.navigateBack({
delta:1,
})
}
_this.old_url = url;
_this.video_src = decodeURIComponent(url);
if(!_this.$com.isNull(title))
{
var pageTitle = title;
uni.setNavigationBarTitle({
title:pageTitle,
})
}
},
methods: {
videoErrorCallback(e)
{
console.log(e);
},
}
}
</script>
<style lang="scss">
page{ height:100%; width: 100%;}
.container{width: 100%; height: 100%;}
.videoBox{ width: 100%; height: 100%;}
</style>

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 865 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 866 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 211 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 805 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

@ -0,0 +1,78 @@
/**
* 这里是uni-app内置的常用样式变量
*
* uni-app 官方扩展插件及插件市场https://ext.dcloud.net.cn上很多三方插件均使用了这些样式变量
* 如果你是插件开发者建议你使用scss预处理并在插件代码中直接使用这些变量无需 import 这个文件方便用户通过搭积木的方式开发整体风格一致的App
*
*/
@import '@/uni_modules/uview-ui/theme.scss';
/**
* 如果你是App开发者插件使用者你可以通过修改这些变量来定制自己的插件主题实现自定义主题功能
*
* 如果你的项目同样使用了scss预处理你也可以直接在你的 scss 代码中使用如下变量同时无需 import 这个文件
*/
/* 颜色变量 */
/* 行为相关颜色 */
$uni-color-primary: #007aff;
$uni-color-success: #4cd964;
$uni-color-warning: #f0ad4e;
$uni-color-error: #dd524d;
/* 文字基本颜色 */
$uni-text-color:#333;//基本色
$uni-text-color-inverse:#fff;//反色
$uni-text-color-grey:#999;//辅助灰色如加载更多的提示信息
$uni-text-color-placeholder: #808080;
$uni-text-color-disable:#c0c0c0;
/* 背景颜色 */
$uni-bg-color:#ffffff;
$uni-bg-color-grey:#f8f8f8;
$uni-bg-color-hover:#f1f1f1;//点击状态颜色
$uni-bg-color-mask:rgba(0, 0, 0, 0.4);//遮罩颜色
/* 边框颜色 */
$uni-border-color:#c8c7cc;
/* 尺寸变量 */
/* 文字尺寸 */
$uni-font-size-sm:12px;
$uni-font-size-base:14px;
$uni-font-size-lg:16;
/* 图片尺寸 */
$uni-img-size-sm:20px;
$uni-img-size-base:26px;
$uni-img-size-lg:40px;
/* Border Radius */
$uni-border-radius-sm: 2px;
$uni-border-radius-base: 3px;
$uni-border-radius-lg: 6px;
$uni-border-radius-circle: 50%;
/* 水平间距 */
$uni-spacing-row-sm: 5px;
$uni-spacing-row-base: 10px;
$uni-spacing-row-lg: 15px;
/* 垂直间距 */
$uni-spacing-col-sm: 4px;
$uni-spacing-col-base: 8px;
$uni-spacing-col-lg: 12px;
/* 透明度 */
$uni-opacity-disabled: 0.3; // 组件禁用态的透明度
/* 文章场景相关 */
$uni-color-title: #2C405A; // 文章标题颜色
$uni-font-size-title:20px;
$uni-color-subtitle: #555555; // 二级标题颜色
$uni-font-size-subtitle:26px;
$uni-color-paragraph: #3F536E; // 文章段落颜色
$uni-font-size-paragraph:15px;
page{background-color: #F5F6FB;}

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

@ -0,0 +1,66 @@
<p align="center">
<img alt="logo" src="https://uviewui.com/common/logo.png" width="120" height="120" style="margin-bottom: 10px;">
</p>
<h3 align="center" style="margin: 30px 0 30px;font-weight: bold;font-size:40px;">uView 2.0</h3>
<h3 align="center">多平台快速开发的UI框架</h3>
[![stars](https://img.shields.io/github/stars/umicro/uView2.0?style=flat-square&logo=GitHub)](https://github.com/umicro/uView2.0)
[![forks](https://img.shields.io/github/forks/umicro/uView2.0?style=flat-square&logo=GitHub)](https://github.com/umicro/uView2.0)
[![issues](https://img.shields.io/github/issues/umicro/uView2.0?style=flat-square&logo=GitHub)](https://github.com/umicro/uView2.0/issues)
[![Website](https://img.shields.io/badge/uView-up-blue?style=flat-square)](https://uviewui.com)
[![release](https://img.shields.io/github/v/release/umicro/uView2.0?style=flat-square)](https://gitee.com/umicro/uView2.0/releases)
[![license](https://img.shields.io/github/license/umicro/uView2.0?style=flat-square)](https://en.wikipedia.org/wiki/MIT_License)
## 说明
uView UI,是[uni-app](https://uniapp.dcloud.io/)全面兼容nvue的uni-app生态框架,全面的组件和便捷的工具会让您信手拈来,如鱼得水
## [官方文档:https://uviewui.com](https://uviewui.com)
## 预览
您可以通过**微信**扫码,查看最佳的演示效果。
<br>
<br>
<img src="https://uviewui.com/common/weixin_mini_qrcode.png" width="220" height="220" >
## 链接
- [官方文档](https://www.uviewui.com/)
- [更新日志](https://www.uviewui.com/components/changelog.html)
- [升级指南](https://www.uviewui.com/components/changeGuide.html)
- [关于我们](https://www.uviewui.com/cooperation/about.html)
## 交流反馈
欢迎加入我们的QQ群交流反馈:[点此跳转](https://www.uviewui.com/components/addQQGroup.html)
## 关于PR
> 我们非常乐意接受各位的优质PR,但在此之前我希望您了解uView2.0是一个需要兼容多个平台的(小程序、h5、ios app、android app)包括nvue页面、vue页面。
> 所以希望在您修复bug并提交之前尽可能的去这些平台测试一下兼容性。最好能携带测试截图以方便审核。非常感谢!
## 安装
#### **uni-app插件市场链接** —— [https://ext.dcloud.net.cn/plugin?id=1593](https://ext.dcloud.net.cn/plugin?id=1593)
请通过[官网安装文档](https://www.uviewui.com/components/install.html)了解更详细的内容
## 快速上手
请通过[快速上手](https://uviewui.com/components/quickstart.html)了解更详细的内容
## 使用方法
配置easycom规则后,自动按需引入,无需`import`组件,直接引用即可。
```html
<template>
<u-button text="按钮"></u-button>
</template>
```
## 版权信息
uView遵循[MIT](https://en.wikipedia.org/wiki/MIT_License)开源协议,意味着您无需支付任何费用,也无需授权,即可将uView应用到您的产品中。

@ -0,0 +1,344 @@
## 2.0.33(2022-06-17)
# uView2.0重磅发布,利剑出鞘,一统江湖
1. 修复`loadmore`组件`lineColor`类型错误问题
2. 修复`u-parse`组件`imgtap`、`linktap`不生效问题
## 2.0.32(2022-06-16)
# uView2.0重磅发布,利剑出鞘,一统江湖
1. `u-loadmore`新增自定义颜色、虚/实线
2. 修复`u-swiper-action`组件部分平台不能上下滑动的问题
3. 修复`u-list`回弹问题
4. 修复`notice-bar`组件动画在低端安卓机可能会抖动的问题
5. `u-loading-page`添加控制图标大小的属性`iconSize`
6. 修复`u-tooltip`组件`color`参数不生效的问题
7. 修复`u--input`组件使用`blur`事件输出为`undefined`的bug
8. `u-code-input`组件新增键盘弹起时,是否自动上推页面参数`adjustPosition`
9. 修复`image`组件`load`事件无回调对象问题
10. 修复`button`组件`loadingSize`设置无效问题
10. 其他修复
## 2.0.31(2022-04-19)
# uView2.0重磅发布,利剑出鞘,一统江湖
1. 修复`upload`在`vue`页面上传成功后没有成功标志的问题
2. 解决演示项目中微信小程序模拟上传图片一直出于上传中问题
3. 修复`u-code-input`组件在`nvue`页面编译到`app`平台上光标异常问题(`app`去除此功能)
4. 修复`actionSheet`组件标题关闭按钮点击事件名称错误的问题
5. 其他修复
## 2.0.30(2022-04-04)
# uView2.0重磅发布,利剑出鞘,一统江湖
1. `u-rate`增加`readonly`属性
2. `tabs`滑块支持设置背景图片
3. 修复`u-subsection` `mode`为`subsection`时,滑块样式不正确的问题
4. `u-code-input`添加光标效果动画
5. 修复`popup`的`open`事件不触发
6. 修复`u-flex-column`无效的问题
7. 修复`u-datetime-picker`索引在特定场合异常问题
8. 修复`u-datetime-picker`最小时间字符串模板错误问题
9. `u-swiper`添加`m3u8`验证
10. `u-swiper`修改判断image和video逻辑
11. 修复`swiper`无法使用本地图片问题,增加`type`参数
12. 修复`u-row-notice`格式错误问题
13. 修复`u-switch`组件当`unit`为`rpx`时,`nodeStyle`消失的问题
14. 修复`datetime-picker`组件`showToolbar`与`visibleItemCount`属性无效的问题
15. 修复`upload`组件条件编译位置判断错误,导致`previewImage`属性设置为`false`时,整个组件都会被隐藏的问题
16. 修复`u-checkbox-group`设置`shape`属性无效的问题
17. 修复`u-upload`的`capture`传入字符串的时候不生效的问题
18. 修复`u-action-sheet`组件,关闭事件逻辑错误的问题
19. 修复`u-list`触顶事件的触发错误的问题
20. 修复`u-text`只有手机号可拨打的问题
21. 修复`u-textarea`不能换行的问题
22. 其他修复
## 2.0.29(2022-03-13)
# uView2.0重磅发布,利剑出鞘,一统江湖
1. 修复`u--text`组件设置`decoration`属性未生效的问题
2. 修复`u-datetime-picker`使用`formatter`后返回值不正确
3. 修复`u-datetime-picker` `intercept` 可能为undefined
4. 修复已设置单位 uni..config.unit = 'rpx'时,线型指示器 `transform` 的位置翻倍,导致指示器超出宽度
5. 修复mixin中bem方法生成的类名在支付宝和字节小程序中失效
6. 修复默认值传值为空的时候,打开`u-datetime-picker`报错,不能选中第一列时间的bug
7. 修复`u-datetime-picker`使用`formatter`后返回值不正确
8. 修复`u-image`组件`loading`无效果的问题
9. 修复`config.unit`属性设为`rpx`时,导航栏占用高度不足导致塌陷的问题
10. 修复`u-datetime-picker`组件`itemHeight`无效问题
11. 其他修复
## 2.0.28(2022-02-22)
# uView2.0重磅发布,利剑出鞘,一统江湖
1. search组件新增searchIconSize属性
2. 兼容Safari/Webkit中传入时间格式如2022-02-17 12:00:56
3. 修复text value.js 判断日期出format错误问题
4. priceFormat格式化金额出现精度错误
5. priceFormat在部分情况下出现精度损失问题
6. 优化表单rules提示
7. 修复avatar组件src为空时,展示状态不对
8. 其他修复
## 2.0.27(2022-01-28)
# uView2.0重磅发布,利剑出鞘,一统江湖
1.样式修复
## 2.0.26(2022-01-28)
# uView2.0重磅发布,利剑出鞘,一统江湖
1.样式修复
## 2.0.25(2022-01-27)
# uView2.0重磅发布,利剑出鞘,一统江湖
1. 修复text组件mode=price时,可能会导致精度错误的问题
2. 添加$u.setConfig()方法,可设置uView内置的config, props, zIndex, color属性,详见:[修改uView内置配置方案](https://uviewui.com/components/setting.html#%E9%BB%98%E8%AE%A4%E5%8D%95%E4%BD%8D%E9%85%8D%E7%BD%AE)
3. 优化form组件在errorType=toast时,如果输入错误页面会有抖动的问题
4. 修复$u.addUnit()对配置默认单位可能无效的问题
## 2.0.24(2022-01-25)
# uView2.0重磅发布,利剑出鞘,一统江湖
1. 修复swiper在current指定非0时缩放有误
2. 修复u-icon添加stop属性的时候报错
3. 优化遗留的通过正则判断rpx单位的问题
4. 优化Layout布局 vue使用gutter时,会超出固定区域
5. 优化search组件高度单位问题(rpx -> px)
6. 修复u-image slot 加载和错误的图片失去了高度
7. 修复u-index-list中footer插槽与header插槽存在性判断错误
8. 修复部分机型下u-popup关闭时会闪烁
9. 修复u-image在nvue-app下失去宽高
10. 修复u-popup运行报错
11. 修复u-tooltip报错
12. 修复box-sizing在app下的警告
13. 修复u-navbar在小程序中报运行时错误
14. 其他修复
## 2.0.23(2022-01-24)
# uView2.0重磅发布,利剑出鞘,一统江湖
1. 修复image组件在hx3.3.9的nvue下可能会显示异常的问题
2. 修复col组件gutter参数带rpx单位处理不正确的问题
3. 修复text组件单行时无法显示省略号的问题
4. navbar添加titleStyle参数
5. 升级到hx3.3.9可消除nvue下控制台样式警告的问题
## 2.0.22(2022-01-19)
# uView2.0重磅发布,利剑出鞘,一统江湖
1. $u.page()方法优化,避免在特殊场景可能报错的问题
2. picker组件添加immediateChange参数
3. 新增$u.pages()方法
## 2.0.21(2022-01-19)
# uView2.0重磅发布,利剑出鞘,一统江湖
1. 优化:form组件在用户设置rules的时候提示用户model必传
2. 优化遗留的通过正则判断rpx单位的问题
3. 修复微信小程序环境中tabbar组件开启safeAreaInsetBottom属性后,placeholder高度填充不正确
4. 修复swiper在current指定非0时缩放有误
5. 修复u-icon添加stop属性的时候报错
6. 修复upload组件在accept=all的时候没有作用
7. 修复在text组件mode为phone时call属性无效的问题
8. 处理u-form clearValidate方法
9. 其他修复
## 2.0.20(2022-01-14)
# uView2.0重磅发布,利剑出鞘,一统江湖
1. 修复calendar默认会选择一个日期,如果直接点确定的话,无法取到值的问题
2. 修复Slider缺少disabled props 还有注释
3. 修复u-notice-bar点击事件无法拿到index索引值的问题
4. 修复u-collapse-item在vue文件下,app端自定义插槽不生效的问题
5. 优化头像为空时显示默认头像
6. 修复图片地址赋值后判断加载状态为完成问题
7. 修复日历滚动到默认日期月份区域
8. search组件暴露点击左边icon事件
9. 修复u-form clearValidate方法不生效
10. upload h5端增加返回文件参数(文件的name参数)
11. 处理upload选择文件后url为blob类型无法预览的问题
12. u-code-input 修复输入框没有往左移出一半屏幕
13. 修复Upload上传 disabled为true时,控制台报hoverClass类型错误
14. 临时处理ios app下grid点击坍塌问题
15. 其他修复
## 2.0.19(2021-12-29)
# uView2.0重磅发布,利剑出鞘,一统江湖
1. 优化微信小程序包体积可在微信中预览,请升级HbuilderX3.3.4,同时在“运行->运行到小程序模拟器”中勾选“运行时是否压缩代码”
2. 优化微信小程序setData性能,处理某些方法如$u.route()无法在模板中使用的问题
3. navbar添加autoBack参数
4. 允许avatar组件的事件冒泡
5. 修复cell组件报错问题
6. 其他修复
## 2.0.18(2021-12-28)
# uView2.0重磅发布,利剑出鞘,一统江湖
1. 修复app端编译报错问题
2. 重新处理微信小程序端setData过大的性能问题
3. 修复边框问题
4. 修复最大最小月份不大于0则没有数据出现的问题
5. 修复SwipeAction微信小程序端无法上下滑动问题
6. 修复input的placeholder在小程序端默认显示为true问题
7. 修复divider组件click事件无效问题
8. 修复u-code-input maxlength 属性值为 String 类型时显示异常
9. 修复当 grid只有 1到2时 在小程序端algin设置无效的问题
10. 处理form-item的label为top时,取消错误提示的左边距
11. 其他修复
## 2.0.17(2021-12-26)
## uView正在参与开源中国的“年度最佳项目”评选,之前投过票的现在也可以投票,恳请同学们投一票,[点此帮助uView](https://www.oschina.net/project/top_cn_2021/?id=583)
# uView2.0重磅发布,利剑出鞘,一统江湖
1. 解决HBuilderX3.3.3.20211225版本导致的样式问题
2. calendar日历添加monthNum参数
3. navbar添加center slot
## 2.0.16(2021-12-25)
## uView正在参与开源中国的“年度最佳项目”评选,之前投过票的现在也可以投票,恳请同学们投一票,[点此帮助uView](https://www.oschina.net/project/top_cn_2021/?id=583)
# uView2.0重磅发布,利剑出鞘,一统江湖
1. 解决微信小程序setData性能问题
2. 修复count-down组件change事件不触发问题
## 2.0.15(2021-12-21)
## uView正在参与开源中国的“年度最佳项目”评选,之前投过票的现在也可以投票,恳请同学们投一票,[点此帮助uView](https://www.oschina.net/project/top_cn_2021/?id=583)
# uView2.0重磅发布,利剑出鞘,一统江湖
1. 修复Cell单元格titleWidth无效
2. 修复cheakbox组件ischecked不更新
3. 修复keyboard是否显示"."按键默认值问题
4. 修复number-keyboard是否显示键盘的"."符号问题
5. 修复Input输入框 readonly无效
6. 修复u-avatar 导致打包app、H5时候报错问题
7. 修复Upload上传deletable无效
8. 修复upload当设置maxSize时无效的问题
9. 修复tabs lineWidth传入带单位的字符串的时候偏移量计算错误问题
10. 修复rate组件在有padding的view内,显示的星星位置和可触摸区域不匹配,无法正常选中星星
## 2.0.13(2021-12-14)
## [点击加群交流反馈:364463526](https://jq.qq.com/?_chanwv=1027&k=mCxS3TGY)
# uView2.0重磅发布,利剑出鞘,一统江湖
1. 修复配置默认单位为rpx可能会导致自定义导航栏高度异常的问题
## 2.0.12(2021-12-14)
## [点击加群交流反馈:364463526](https://jq.qq.com/?_chanwv=1027&k=mCxS3TGY)
# uView2.0重磅发布,利剑出鞘,一统江湖
1. 修复tabs组件在vue环境下划线消失的问题
2. 修复upload组件在安卓小程序无法选择视频的问题
3. 添加uni.$u.config.unit配置,用于配置参数默认单位,详见:[默认单位配置](https://www.uviewui.com/components/setting.html#%E9%BB%98%E8%AE%A4%E5%8D%95%E4%BD%8D%E9%85%8D%E7%BD%AE)
4. 修复textarea组件在没绑定v-model时,字符统计不生效问题
5. 修复nvue下控制是否出现滚动条失效问题
## 2.0.11(2021-12-13)
## [点击加群交流反馈:364463526](https://jq.qq.com/?_chanwv=1027&k=mCxS3TGY)
# uView2.0重磅发布,利剑出鞘,一统江湖
1. text组件align参数无效的问题
2. subsection组件添加keyName参数
3. upload组件无法判断[Object file]类型的问题
4. 处理notify层级过低问题
5. codeInput组件添加disabledDot参数
6. 处理actionSheet组件round参数无效的问题
7. calendar组件添加round参数用于控制圆角值
8. 处理swipeAction组件在vue环境下默认被打开的问题
9. button组件的throttleTime节流参数无效的问题
10. 解决u-notify手动关闭方法close()无效的问题
11. input组件readonly不生效问题
12. tag组件type参数为info不生效问题
## 2.0.10(2021-12-08)
## [点击加群交流反馈:364463526](https://jq.qq.com/?_chanwv=1027&k=mCxS3TGY)
# uView2.0重磅发布,利剑出鞘,一统江湖
1. 修复button sendMessagePath属性不生效
2. 修复DatetimePicker选择器title无效
3. 修复u-toast设置loading=true不生效
4. 修复u-text金额模式传0报错
5. 修复u-toast组件的icon属性配置不生效
6. button的icon在特殊场景下的颜色优化
7. IndexList优化,增加#
## 2.0.9(2021-12-01)
## [点击加群交流反馈:232041042](https://jq.qq.com/?_wv=1027&k=KnbeceDU)
# uView2.0重磅发布,利剑出鞘,一统江湖
1. 优化swiper的height支持100%值(仅vue有效),修复嵌入视频时click事件无法触发的问题
2. 优化tabs组件对list值为空的判断,或者动态变化list时重新计算相关尺寸的问题
3. 优化datetime-picker组件逻辑,让其后续打开的默认值为上一次的选中值,需要通过v-model绑定值才有效
4. 修复upload内嵌在其他组件中,选择图片可能不会换行的问题
## 2.0.8(2021-12-01)
## [点击加群交流反馈:232041042](https://jq.qq.com/?_wv=1027&k=KnbeceDU)
# uView2.0重磅发布,利剑出鞘,一统江湖
1. 修复toast的position参数无效问题
2. 处理input在ios nvue上无法获得焦点的问题
3. avatar-group组件添加extraValue参数,让剩余展示数量可手动控制
4. tabs组件添加keyName参数用于配置从对象中读取的键名
5. 处理text组件名字脱敏默认配置无效的问题
6. 处理picker组件item文本太长换行问题
## 2.0.7(2021-11-30)
## [点击加群交流反馈:232041042](https://jq.qq.com/?_wv=1027&k=KnbeceDU)
# uView2.0重磅发布,利剑出鞘,一统江湖
1. 修复radio和checkbox动态改变v-model无效的问题。
2. 优化form规则validator在微信小程序用法
3. 修复backtop组件mode参数在微信小程序无效的问题
4. 处理Album的previewFullImage属性无效的问题
5. 处理u-datetime-picker组件mode='time'在选择改变时间时,控制台报错的问题
## 2.0.6(2021-11-27)
## [点击加群交流反馈:232041042](https://jq.qq.com/?_wv=1027&k=KnbeceDU)
# uView2.0重磅发布,利剑出鞘,一统江湖
1. 处理tag组件在vue下边框无效的问题。
2. 处理popup组件圆角参数可能无效的问题。
3. 处理tabs组件lineColor参数可能无效的问题。
4. propgress组件在值很小时,显示异常的问题。
## 2.0.5(2021-11-25)
## [点击加群交流反馈:232041042](https://jq.qq.com/?_wv=1027&k=KnbeceDU)
# uView2.0重磅发布,利剑出鞘,一统江湖
1. calendar在vue下显示异常问题。
2. form组件labelPosition和errorType参数无效的问题
3. input组件inputAlign无效的问题
4. 其他一些修复
## 2.0.4(2021-11-23)
## [点击加群交流反馈:232041042](https://jq.qq.com/?_wv=1027&k=KnbeceDU)
# uView2.0重磅发布,利剑出鞘,一统江湖
0. input组件缺失@confirm事件,以及subfix和prefix无效问题
1. component.scss文件样式在vue下干扰全局布局问题
2. 修复subsection在vue环境下表现异常的问题
3. tag组件的bgColor等参数无效的问题
4. upload组件不换行的问题
5. 其他的一些修复处理
## 2.0.3(2021-11-16)
## [点击加群交流反馈:1129077272](https://jq.qq.com/?_wv=1027&k=KnbeceDU)
# uView2.0重磅发布,利剑出鞘,一统江湖
1. uView2.0已实现全面兼容nvue
2. uView2.0对1.x进行了架构重构,细节和性能都有极大提升
3. 目前uView2.0为公测阶段,相关细节可能会有变动
4. 我们写了一份与1.x的对比指南,详见[对比1.x](https://www.uviewui.com/components/diff1.x.html)
5. 处理modal的confirm回调事件拼写错误问题
6. 处理input组件@input事件参数错误问题
7. 其他一些修复
## 2.0.2(2021-11-16)
## [点击加群交流反馈:1129077272](https://jq.qq.com/?_wv=1027&k=KnbeceDU)
# uView2.0重磅发布,利剑出鞘,一统江湖
1. uView2.0已实现全面兼容nvue
2. uView2.0对1.x进行了架构重构,细节和性能都有极大提升
3. 目前uView2.0为公测阶段,相关细节可能会有变动
4. 我们写了一份与1.x的对比指南,详见[对比1.x](https://www.uviewui.com/components/diff1.x.html)
5. 修复input组件formatter参数缺失问题
6. 优化loading-icon组件的scss写法问题,防止不兼容新版本scss
## 2.0.0(2020-11-15)
## [点击加群交流反馈:1129077272](https://jq.qq.com/?_wv=1027&k=KnbeceDU)
# uView2.0重磅发布,利剑出鞘,一统江湖
1. uView2.0已实现全面兼容nvue
2. uView2.0对1.x进行了架构重构,细节和性能都有极大提升
3. 目前uView2.0为公测阶段,相关细节可能会有变动
4. 我们写了一份与1.x的对比指南,详见[对比1.x](https://www.uviewui.com/components/diff1.x.html)
5. 修复input组件formatter参数缺失问题

@ -0,0 +1,78 @@
<template>
<uvForm
ref="uForm"
:model="model"
:rules="rules"
:errorType="errorType"
:borderBottom="borderBottom"
:labelPosition="labelPosition"
:labelWidth="labelWidth"
:labelAlign="labelAlign"
:labelStyle="labelStyle"
:customStyle="customStyle"
>
<slot />
</uvForm>
</template>
<script>
/**
* 此组件存在的理由是在nvue下u-form被uni-app官方占用了u-form在nvue中相当于form组件
* 所以在nvue下取名为u--form内部其实还是u-form.vue只不过做一层中转
*/
import uvForm from '../u-form/u-form.vue';
import props from '../u-form/props.js'
export default {
// #ifdef MP-WEIXIN
name: 'u-form',
// #endif
// #ifndef MP-WEIXIN
name: 'u--form',
// #endif
mixins: [uni.$u.mpMixin, props, uni.$u.mixin],
components: {
uvForm
},
created() {
this.children = []
},
methods: {
//
setRules(rules) {
this.$refs.uForm.setRules(rules)
},
validate() {
/**
* 在微信小程序中通过this.$parent拿到的父组件是u--form而不是其内嵌的u-form
* 导致在u-form组件中拿不到对应的children数组从而校验无效所以这里每次调用u-form组件中的
* 对应方法的时候在小程序中都先将u--form的children赋值给u-form中的children
*/
// #ifdef MP-WEIXIN
this.setMpData()
// #endif
return this.$refs.uForm.validate()
},
validateField(value, callback) {
// #ifdef MP-WEIXIN
this.setMpData()
// #endif
return this.$refs.uForm.validateField(value, callback)
},
resetFields() {
// #ifdef MP-WEIXIN
this.setMpData()
// #endif
return this.$refs.uForm.resetFields()
},
clearValidate(props) {
// #ifdef MP-WEIXIN
this.setMpData()
// #endif
return this.$refs.uForm.clearValidate(props)
},
setMpData() {
this.$refs.uForm.children = this.children
}
},
}
</script>

@ -0,0 +1,47 @@
<template>
<uvImage
:src="src"
:mode="mode"
:width="width"
:height="height"
:shape="shape"
:radius="radius"
:lazyLoad="lazyLoad"
:showMenuByLongpress="showMenuByLongpress"
:loadingIcon="loadingIcon"
:errorIcon="errorIcon"
:showLoading="showLoading"
:showError="showError"
:fade="fade"
:webp="webp"
:duration="duration"
:bgColor="bgColor"
:customStyle="customStyle"
@click="$emit('click')"
@error="$emit('error')"
@load="$emit('load')"
>
<template v-slot:loading>
<slot name="loading"></slot>
</template>
<template v-slot:error>
<slot name="error"></slot>
</template>
</uvImage>
</template>
<script>
/**
* 此组件存在的理由是在nvue下u-image被uni-app官方占用了u-image在nvue中相当于image组件
* 所以在nvue下取名为u--image内部其实还是u-iamge.vue只不过做一层中转
*/
import uvImage from '../u-image/u-image.vue';
import props from '../u-image/props.js';
export default {
name: 'u--image',
mixins: [uni.$u.mpMixin, props, uni.$u.mixin],
components: {
uvImage
},
}
</script>

@ -0,0 +1,72 @@
<template>
<uvInput
:value="value"
:type="type"
:fixed="fixed"
:disabled="disabled"
:disabledColor="disabledColor"
:clearable="clearable"
:password="password"
:maxlength="maxlength"
:placeholder="placeholder"
:placeholderClass="placeholderClass"
:placeholderStyle="placeholderStyle"
:showWordLimit="showWordLimit"
:confirmType="confirmType"
:confirmHold="confirmHold"
:holdKeyboard="holdKeyboard"
:focus="focus"
:autoBlur="autoBlur"
:disableDefaultPadding="disableDefaultPadding"
:cursor="cursor"
:cursorSpacing="cursorSpacing"
:selectionStart="selectionStart"
:selectionEnd="selectionEnd"
:adjustPosition="adjustPosition"
:inputAlign="inputAlign"
:fontSize="fontSize"
:color="color"
:prefixIcon="prefixIcon"
:suffixIcon="suffixIcon"
:suffixIconStyle="suffixIconStyle"
:prefixIconStyle="prefixIconStyle"
:border="border"
:readonly="readonly"
:shape="shape"
:customStyle="customStyle"
:formatter="formatter"
@focus="$emit('focus')"
@blur="e => $emit('blur', e)"
@keyboardheightchange="$emit('keyboardheightchange')"
@change="e => $emit('change', e)"
@input="e => $emit('input', e)"
@confirm="e => $emit('confirm', e)"
@clear="$emit('clear')"
@click="$emit('click')"
>
<!-- #ifdef MP -->
<slot name="prefix"></slot>
<slot name="suffix"></slot>
<!-- #endif -->
<!-- #ifndef MP -->
<slot name="prefix" slot="prefix"></slot>
<slot name="suffix" slot="suffix"></slot>
<!-- #endif -->
</uvInput>
</template>
<script>
/**
* 此组件存在的理由是在nvue下u-input被uni-app官方占用了u-input在nvue中相当于input组件
* 所以在nvue下取名为u--input内部其实还是u-input.vue只不过做一层中转
*/
import uvInput from '../u-input/u-input.vue';
import props from '../u-input/props.js'
export default {
name: 'u--input',
mixins: [uni.$u.mpMixin, props, uni.$u.mixin],
components: {
uvInput
},
}
</script>

@ -0,0 +1,44 @@
<template>
<uvText
:type="type"
:show="show"
:text="text"
:prefixIcon="prefixIcon"
:suffixIcon="suffixIcon"
:mode="mode"
:href="href"
:format="format"
:call="call"
:openType="openType"
:bold="bold"
:block="block"
:lines="lines"
:color="color"
:decoration="decoration"
:size="size"
:iconStyle="iconStyle"
:margin="margin"
:lineHeight="lineHeight"
:align="align"
:wordWrap="wordWrap"
:customStyle="customStyle"
@click="$emit('click')"
></uvText>
</template>
<script>
/**
* 此组件存在的理由是在nvue下u-text被uni-app官方占用了u-text在nvue中相当于input组件
* 所以在nvue下取名为u--input内部其实还是u-text.vue只不过做一层中转
* 不使用v-bind="$attrs"而是分开独立写传参是因为微信小程序不支持此写法
*/
import uvText from "../u-text/u-text.vue";
import props from "../u-text/props.js";
export default {
name: "u--text",
mixins: [uni.$u.mpMixin, props, uni.$u.mixin],
components: {
uvText,
},
};
</script>

@ -0,0 +1,47 @@
<template>
<uvTextarea
:value="value"
:placeholder="placeholder"
:height="height"
:confirmType="confirmType"
:disabled="disabled"
:count="count"
:focus="focus"
:autoHeight="autoHeight"
:fixed="fixed"
:cursorSpacing="cursorSpacing"
:cursor="cursor"
:showConfirmBar="showConfirmBar"
:selectionStart="selectionStart"
:selectionEnd="selectionEnd"
:adjustPosition="adjustPosition"
:disableDefaultPadding="disableDefaultPadding"
:holdKeyboard="holdKeyboard"
:maxlength="maxlength"
:border="border"
:customStyle="customStyle"
:formatter="formatter"
@focus="e => $emit('focus')"
@blur="e => $emit('blur')"
@linechange="e => $emit('linechange', e)"
@confirm="e => $emit('confirm')"
@input="e => $emit('input', e)"
@keyboardheightchange="e => $emit('keyboardheightchange')"
></uvTextarea>
</template>
<script>
/**
* 此组件存在的理由是在nvue下u--textarea被uni-app官方占用了u-textarea在nvue中相当于textarea组件
* 所以在nvue下取名为u--textarea内部其实还是u-textarea.vue只不过做一层中转
*/
import uvTextarea from '../u-textarea/u-textarea.vue';
import props from '../u-textarea/props.js'
export default {
name: 'u--textarea',
mixins: [uni.$u.mpMixin, props, uni.$u.mixin],
components: {
uvTextarea
},
}
</script>

@ -0,0 +1,54 @@
export default {
props: {
// 操作菜单是否展示 (默认false)
show: {
type: Boolean,
default: uni.$u.props.actionSheet.show
},
// 标题
title: {
type: String,
default: uni.$u.props.actionSheet.title
},
// 选项上方的描述信息
description: {
type: String,
default: uni.$u.props.actionSheet.description
},
// 数据
actions: {
type: Array,
default: uni.$u.props.actionSheet.actions
},
// 取消按钮的文字,不为空时显示按钮
cancelText: {
type: String,
default: uni.$u.props.actionSheet.cancelText
},
// 点击某个菜单项时是否关闭弹窗
closeOnClickAction: {
type: Boolean,
default: uni.$u.props.actionSheet.closeOnClickAction
},
// 处理底部安全区(默认true)
safeAreaInsetBottom: {
type: Boolean,
default: uni.$u.props.actionSheet.safeAreaInsetBottom
},
// 小程序的打开方式
openType: {
type: String,
default: uni.$u.props.actionSheet.openType
},
// 点击遮罩是否允许关闭 (默认true)
closeOnClickOverlay: {
type: Boolean,
default: uni.$u.props.actionSheet.closeOnClickOverlay
},
// 圆角值
round: {
type: [Boolean, String, Number],
default: uni.$u.props.actionSheet.round
}
}
}

@ -0,0 +1,278 @@
<template>
<u-popup
:show="show"
mode="bottom"
@close="closeHandler"
:safeAreaInsetBottom="safeAreaInsetBottom"
:round="round"
>
<view class="u-action-sheet">
<view
class="u-action-sheet__header"
v-if="title"
>
<text class="u-action-sheet__header__title u-line-1">{{title}}</text>
<view
class="u-action-sheet__header__icon-wrap"
@tap.stop="cancel"
>
<u-icon
name="close"
size="17"
color="#c8c9cc"
bold
></u-icon>
</view>
</view>
<text
class="u-action-sheet__description"
:style="[{
marginTop: `${title && description ? 0 : '18px'}`
}]"
v-if="description"
>{{description}}</text>
<slot>
<u-line v-if="description"></u-line>
<view class="u-action-sheet__item-wrap">
<template v-for="(item, index) in actions">
<!-- #ifdef MP -->
<button
:key="index"
class="u-reset-button"
:openType="item.openType"
@getuserinfo="onGetUserInfo"
@contact="onContact"
@getphonenumber="onGetPhoneNumber"
@error="onError"
@launchapp="onLaunchApp"
@opensetting="onOpenSetting"
:lang="lang"
:session-from="sessionFrom"
:send-message-title="sendMessageTitle"
:send-message-path="sendMessagePath"
:send-message-img="sendMessageImg"
:show-message-card="showMessageCard"
:app-parameter="appParameter"
@tap="selectHandler(index)"
:hover-class="!item.disabled && !item.loading ? 'u-action-sheet--hover' : ''"
>
<!-- #endif -->
<view
class="u-action-sheet__item-wrap__item"
@tap.stop="selectHandler(index)"
:hover-class="!item.disabled && !item.loading ? 'u-action-sheet--hover' : ''"
:hover-stay-time="150"
>
<template v-if="!item.loading">
<text
class="u-action-sheet__item-wrap__item__name"
:style="[itemStyle(index)]"
>{{ item.name }}</text>
<text
v-if="item.subname"
class="u-action-sheet__item-wrap__item__subname"
>{{ item.subname }}</text>
</template>
<u-loading-icon
v-else
custom-class="van-action-sheet__loading"
size="18"
mode="circle"
/>
</view>
<!-- #ifdef MP -->
</button>
<!-- #endif -->
<u-line v-if="index !== actions.length - 1"></u-line>
</template>
</view>
</slot>
<u-gap
bgColor="#eaeaec"
height="6"
v-if="cancelText"
></u-gap>
<view hover-class="u-action-sheet--hover">
<text
@touchmove.stop.prevent
:hover-stay-time="150"
v-if="cancelText"
class="u-action-sheet__cancel-text"
@tap="cancel"
>{{cancelText}}</text>
</view>
</view>
</u-popup>
</template>
<script>
import openType from '../../libs/mixin/openType'
import button from '../../libs/mixin/button'
import props from './props.js';
/**
* ActionSheet 操作菜单
* @description 本组件用于从底部弹出一个操作菜单供用户选择并返回结果本组件功能类似于uni的uni.showActionSheetAPI配置更加灵活所有平台都表现一致
* @tutorial https://www.uviewui.com/components/actionSheet.html
*
* @property {Boolean} show 操作菜单是否展示 默认 false
* @property {String} title 操作菜单标题
* @property {String} description 选项上方的描述信息
* @property {Array<Object>} actions 按钮的文字数组见官方文档示例
* @property {String} cancelText 取消按钮的提示文字,不为空时显示按钮
* @property {Boolean} closeOnClickAction 点击某个菜单项时是否关闭弹窗 默认 true
* @property {Boolean} safeAreaInsetBottom 处理底部安全区 默认 true
* @property {String} openType 小程序的打开方式 (contact | launchApp | getUserInfo | openSetting getPhoneNumber error )
* @property {Boolean} closeOnClickOverlay 点击遮罩是否允许关闭 (默认 true )
* @property {Number|String} round 圆角值默认无圆角 (默认 0 )
* @property {String} lang 指定返回用户信息的语言zh_CN 简体中文zh_TW 繁体中文en 英文
* @property {String} sessionFrom 会话来源openType="contact"时有效
* @property {String} sendMessageTitle 会话内消息卡片标题openType="contact"时有效
* @property {String} sendMessagePath 会话内消息卡片点击跳转小程序路径openType="contact"时有效
* @property {String} sendMessageImg 会话内消息卡片图片openType="contact"时有效
* @property {Boolean} showMessageCard 是否显示会话内消息卡片设置此参数为 true用户进入客服会话会在右下角显示"可能要发送的小程序"提示用户点击后可以快速发送小程序消息openType="contact"时有效 默认 false
* @property {String} appParameter 打开 APP APP 传递的参数openType=launchApp 时有效
*
* @event {Function} select 点击ActionSheet列表项时触发
* @event {Function} close 点击取消按钮时触发
* @event {Function} getuserinfo 用户点击该按钮时会返回获取到的用户信息回调的 detail 数据与 wx.getUserInfo 返回的一致openType="getUserInfo"时有效
* @event {Function} contact 客服消息回调openType="contact"时有效
* @event {Function} getphonenumber 获取用户手机号回调openType="getPhoneNumber"时有效
* @event {Function} error 当使用开放能力时发生错误的回调openType="error"时有效
* @event {Function} launchapp 打开 APP 成功的回调openType="launchApp"时有效
* @event {Function} opensetting 在打开授权设置页后回调openType="openSetting"时有效
* @example <u-action-sheet :actions="list" :title="title" :show="show"></u-action-sheet>
*/
export default {
name: "u-action-sheet",
// propsmethodsmixin
mixins: [openType, button, uni.$u.mixin, props],
data() {
return {
}
},
computed: {
//
itemStyle() {
return (index) => {
let style = {};
if (this.actions[index].color) style.color = this.actions[index].color
if (this.actions[index].fontSize) style.fontSize = uni.$u.addUnit(this.actions[index].fontSize)
//
if (this.actions[index].disabled) style.color = '#c0c4cc'
return style;
}
},
},
methods: {
closeHandler() {
// close
if(this.closeOnClickOverlay) {
this.$emit('close')
}
},
//
cancel() {
this.$emit('close')
},
selectHandler(index) {
const item = this.actions[index]
if (item && !item.disabled && !item.loading) {
this.$emit('select', item)
if (this.closeOnClickAction) {
this.$emit('close')
}
}
},
}
}
</script>
<style lang="scss" scoped>
@import "../../libs/css/components.scss";
$u-action-sheet-reset-button-width:100% !default;
$u-action-sheet-title-font-size: 16px !default;
$u-action-sheet-title-padding: 12px 30px !default;
$u-action-sheet-title-color: $u-main-color !default;
$u-action-sheet-header-icon-wrap-right:15px !default;
$u-action-sheet-header-icon-wrap-top:15px !default;
$u-action-sheet-description-font-size:13px !default;
$u-action-sheet-description-color:14px !default;
$u-action-sheet-description-margin: 18px 15px !default;
$u-action-sheet-item-wrap-item-padding:15px !default;
$u-action-sheet-item-wrap-name-font-size:16px !default;
$u-action-sheet-item-wrap-subname-font-size:13px !default;
$u-action-sheet-item-wrap-subname-color: #c0c4cc !default;
$u-action-sheet-item-wrap-subname-margin-top:10px !default;
$u-action-sheet-cancel-text-font-size:16px !default;
$u-action-sheet-cancel-text-color:$u-content-color !default;
$u-action-sheet-cancel-text-font-size:15px !default;
$u-action-sheet-cancel-text-hover-background-color:rgb(242, 243, 245) !default;
.u-reset-button {
width: $u-action-sheet-reset-button-width;
}
.u-action-sheet {
text-align: center;
&__header {
position: relative;
padding: $u-action-sheet-title-padding;
&__title {
font-size: $u-action-sheet-title-font-size;
color: $u-action-sheet-title-color;
font-weight: bold;
text-align: center;
}
&__icon-wrap {
position: absolute;
right: $u-action-sheet-header-icon-wrap-right;
top: $u-action-sheet-header-icon-wrap-top;
}
}
&__description {
font-size: $u-action-sheet-description-font-size;
color: $u-tips-color;
margin: $u-action-sheet-description-margin;
text-align: center;
}
&__item-wrap {
&__item {
padding: $u-action-sheet-item-wrap-item-padding;
@include flex;
align-items: center;
justify-content: center;
flex-direction: column;
&__name {
font-size: $u-action-sheet-item-wrap-name-font-size;
color: $u-main-color;
text-align: center;
}
&__subname {
font-size: $u-action-sheet-item-wrap-subname-font-size;
color: $u-action-sheet-item-wrap-subname-color;
margin-top: $u-action-sheet-item-wrap-subname-margin-top;
text-align: center;
}
}
}
&__cancel-text {
font-size: $u-action-sheet-cancel-text-font-size;
color: $u-action-sheet-cancel-text-color;
text-align: center;
padding: $u-action-sheet-cancel-text-font-size;
}
&--hover {
background-color: $u-action-sheet-cancel-text-hover-background-color;
}
}
</style>

@ -0,0 +1,59 @@
export default {
props: {
// 图片地址,Array<String>|Array<Object>形式
urls: {
type: Array,
default: uni.$u.props.album.urls
},
// 指定从数组的对象元素中读取哪个属性作为图片地址
keyName: {
type: String,
default: uni.$u.props.album.keyName
},
// 单图时,图片长边的长度
singleSize: {
type: [String, Number],
default: uni.$u.props.album.singleSize
},
// 多图时,图片边长
multipleSize: {
type: [String, Number],
default: uni.$u.props.album.multipleSize
},
// 多图时,图片水平和垂直之间的间隔
space: {
type: [String, Number],
default: uni.$u.props.album.space
},
// 单图时,图片缩放裁剪的模式
singleMode: {
type: String,
default: uni.$u.props.album.singleMode
},
// 多图时,图片缩放裁剪的模式
multipleMode: {
type: String,
default: uni.$u.props.album.multipleMode
},
// 最多展示的图片数量,超出时最后一个位置将会显示剩余图片数量
maxCount: {
type: [String, Number],
default: uni.$u.props.album.maxCount
},
// 是否可以预览图片
previewFullImage: {
type: Boolean,
default: uni.$u.props.album.previewFullImage
},
// 每行展示图片数量,如设置,singleSize和multipleSize将会无效
rowCount: {
type: [String, Number],
default: uni.$u.props.album.rowCount
},
// 超出maxCount时是否显示查看更多的提示
showMore: {
type: Boolean,
default: uni.$u.props.album.showMore
}
}
}

@ -0,0 +1,259 @@
<template>
<view class="u-album">
<view
class="u-album__row"
ref="u-album__row"
v-for="(arr, index) in showUrls"
:forComputedUse="albumWidth"
:key="index"
>
<view
class="u-album__row__wrapper"
v-for="(item, index1) in arr"
:key="index1"
:style="[imageStyle(index + 1, index1 + 1)]"
@tap="previewFullImage ? onPreviewTap(getSrc(item)) : ''"
>
<image
:src="getSrc(item)"
:mode="
urls.length === 1
? imageHeight > 0
? singleMode
: 'widthFix'
: multipleMode
"
:style="[
{
width: imageWidth,
height: imageHeight
}
]"
></image>
<view
v-if="
showMore &&
urls.length > rowCount * showUrls.length &&
index === showUrls.length - 1 &&
index1 === showUrls[showUrls.length - 1].length - 1
"
class="u-album__row__wrapper__text"
>
<u--text
:text="`+${urls.length - maxCount}`"
color="#fff"
:size="multipleSize * 0.3"
align="center"
customStyle="justify-content: center"
></u--text>
</view>
</view>
</view>
</view>
</template>
<script>
import props from './props.js'
// #ifdef APP-NVUE
// weexKPIdom
const dom = uni.requireNativePlugin('dom')
// #endif
/**
* Album 相册
* @description 本组件提供一个类似相册的功能让开发者开发起来更加得心应手减少重复的模板代码
* @tutorial https://www.uviewui.com/components/album.html
*
* @property {Array} urls 图片地址列表 Array<String>|Array<Object>形式
* @property {String} keyName 指定从数组的对象元素中读取哪个属性作为图片地址
* @property {String | Number} singleSize 单图时图片长边的长度 默认 180
* @property {String | Number} multipleSize 多图时图片边长 默认 70
* @property {String | Number} space 多图时图片水平和垂直之间的间隔 默认 6
* @property {String} singleMode 单图时图片缩放裁剪的模式 默认 'scaleToFill'
* @property {String} multipleMode 多图时图片缩放裁剪的模式 默认 'aspectFill'
* @property {String | Number} maxCount 取消按钮的提示文字 默认 9
* @property {Boolean} previewFullImage 是否可以预览图片 默认 true
* @property {String | Number} rowCount 每行展示图片数量如设置singleSize和multipleSize将会无效 默认 3
* @property {Boolean} showMore 超出maxCount时是否显示查看更多的提示 默认 true
*
* @event {Function} albumWidth 某些特殊的情况下需要让文字与相册的宽度相等这里事件的形式对外发送 回调参数 width
* @example <u-album :urls="urls2" @albumWidth="width => albumWidth = width" multipleSize="68" ></u-album>
*/
export default {
name: 'u-album',
mixins: [uni.$u.mpMixin, uni.$u.mixin, props],
data() {
return {
//
singleWidth: 0,
//
singleHeight: 0,
//
singlePercent: 0.6
}
},
watch: {
urls: {
immediate: true,
handler(newVal) {
if (newVal.length === 1) {
this.getImageRect()
}
}
}
},
computed: {
imageStyle() {
return (index1, index2) => {
const { space, rowCount, multipleSize, urls } = this,
{ addUnit, addStyle } = uni.$u,
rowLen = this.showUrls.length,
allLen = this.urls.length
const style = {
marginRight: addUnit(space),
marginBottom: addUnit(space)
}
//
if (index1 === rowLen) style.marginBottom = 0
//
if (
index2 === rowCount ||
(index1 === rowLen &&
index2 === this.showUrls[index1 - 1].length)
)
style.marginRight = 0
return style
}
},
//
showUrls() {
const arr = []
this.urls.map((item, index) => {
//
if (index + 1 <= this.maxCount) {
//
const itemIndex = Math.floor(index / this.rowCount)
//
if (!arr[itemIndex]) {
arr[itemIndex] = []
}
arr[itemIndex].push(item)
}
})
return arr
},
imageWidth() {
return uni.$u.addUnit(
this.urls.length === 1 ? this.singleWidth : this.multipleSize
)
},
imageHeight() {
return uni.$u.addUnit(
this.urls.length === 1 ? this.singleHeight : this.multipleSize
)
},
// computedurls
//
albumWidth() {
let width = 0
if (this.urls.length === 1) {
width = this.singleWidth
} else {
width =
this.showUrls[0].length * this.multipleSize +
this.space * (this.showUrls[0].length - 1)
}
this.$emit('albumWidth', width)
return width
}
},
methods: {
//
onPreviewTap(url) {
const urls = this.urls.map((item) => {
return this.getSrc(item)
})
uni.previewImage({
current: url,
urls
})
},
//
getSrc(item) {
return uni.$u.test.object(item)
? (this.keyName && item[this.keyName]) || item.src
: item
},
//
// download
// (singlePercent)
getImageRect() {
const src = this.getSrc(this.urls[0])
uni.getImageInfo({
src,
success: (res) => {
//
const isHorizotal = res.width >= res.height
this.singleWidth = isHorizotal
? this.singleSize
: (res.width / res.height) * this.singleSize
this.singleHeight = !isHorizotal
? this.singleSize
: (res.height / res.width) * this.singleWidth
},
fail: () => {
this.getComponentWidth()
}
})
},
//
async getComponentWidth() {
// dom
await uni.$u.sleep(30)
// #ifndef APP-NVUE
this.$uGetRect('.u-album__row').then((size) => {
this.singleWidth = size.width * this.singlePercent
})
// #endif
// #ifdef APP-NVUE
// ref="u-album__row"forthis.$refs['u-album__row']
const ref = this.$refs['u-album__row'][0]
ref &&
dom.getComponentRect(ref, (res) => {
this.singleWidth = res.size.width * this.singlePercent
})
// #endif
}
}
}
</script>
<style lang="scss" scoped>
@import '../../libs/css/components.scss';
.u-album {
@include flex(column);
&__row {
@include flex(row);
flex-wrap: wrap;
&__wrapper {
position: relative;
&__text {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.3);
@include flex(row);
justify-content: center;
align-items: center;
}
}
}
}
</style>

@ -0,0 +1,44 @@
export default {
props: {
// 显示文字
title: {
type: String,
default: uni.$u.props.alert.title
},
// 主题,success/warning/info/error
type: {
type: String,
default: uni.$u.props.alert.type
},
// 辅助性文字
description: {
type: String,
default: uni.$u.props.alert.description
},
// 是否可关闭
closable: {
type: Boolean,
default: uni.$u.props.alert.closable
},
// 是否显示图标
showIcon: {
type: Boolean,
default: uni.$u.props.alert.showIcon
},
// 浅或深色调,light-浅色,dark-深色
effect: {
type: String,
default: uni.$u.props.alert.effect
},
// 文字是否居中
center: {
type: Boolean,
default: uni.$u.props.alert.center
},
// 字体大小
fontSize: {
type: [String, Number],
default: uni.$u.props.alert.fontSize
}
}
}

@ -0,0 +1,243 @@
<template>
<u-transition
mode="fade"
:show="show"
>
<view
class="u-alert"
:class="[`u-alert--${type}--${effect}`]"
@tap.stop="clickHandler"
:style="[$u.addStyle(customStyle)]"
>
<view
class="u-alert__icon"
v-if="showIcon"
>
<u-icon
:name="iconName"
size="18"
:color="iconColor"
></u-icon>
</view>
<view
class="u-alert__content"
:style="[{
paddingRight: closable ? '20px' : 0
}]"
>
<text
class="u-alert__content__title"
v-if="title"
:style="[{
fontSize: $u.addUnit(fontSize),
textAlign: center ? 'center' : 'left'
}]"
:class="[effect === 'dark' ? 'u-alert__text--dark' : `u-alert__text--${type}--light`]"
>{{ title }}</text>
<text
class="u-alert__content__desc"
v-if="description"
:style="[{
fontSize: $u.addUnit(fontSize),
textAlign: center ? 'center' : 'left'
}]"
:class="[effect === 'dark' ? 'u-alert__text--dark' : `u-alert__text--${type}--light`]"
>{{ description }}</text>
</view>
<view
class="u-alert__close"
v-if="closable"
@tap.stop="closeHandler"
>
<u-icon
name="close"
:color="iconColor"
size="15"
></u-icon>
</view>
</view>
</u-transition>
</template>
<script>
import props from './props.js';
/**
* Alert 警告提示
* @description 警告提示展现需要关注的信息
* @tutorial https://www.uviewui.com/components/alertTips.html
*
* @property {String} title 显示的文字
* @property {String} type 使用预设的颜色 默认 'warning'
* @property {String} description 辅助性文字颜色比title浅一点字号也小一点可选
* @property {Boolean} closable 关闭按钮(默认为叉号icon图标) 默认 false
* @property {Boolean} showIcon 是否显示左边的辅助图标 默认 false
* @property {String} effect 多图时图片缩放裁剪的模式 默认 'light'
* @property {Boolean} center 文字是否居中 默认 false
* @property {String | Number} fontSize 字体大小 默认 14
* @property {Object} customStyle 定义需要用到的外部样式
* @event {Function} click 点击组件时触发
* @example <u-alert :title="title" type = "warning" :closable="closable" :description = "description"></u-alert>
*/
export default {
name: 'u-alert',
mixins: [uni.$u.mpMixin, uni.$u.mixin, props],
data() {
return {
show: true
}
},
computed: {
iconColor() {
return this.effect === 'light' ? this.type : '#fff'
},
//
iconName() {
switch (this.type) {
case 'success':
return 'checkmark-circle-fill';
break;
case 'error':
return 'close-circle-fill';
break;
case 'warning':
return 'error-circle-fill';
break;
case 'info':
return 'info-circle-fill';
break;
case 'primary':
return 'more-circle-fill';
break;
default:
return 'error-circle-fill';
}
}
},
methods: {
//
clickHandler() {
this.$emit('click')
},
//
closeHandler() {
this.show = false
}
}
}
</script>
<style lang="scss" scoped>
@import "../../libs/css/components.scss";
.u-alert {
position: relative;
background-color: $u-primary;
padding: 8px 10px;
@include flex(row);
align-items: center;
border-top-left-radius: 4px;
border-top-right-radius: 4px;
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
&--primary--dark {
background-color: $u-primary;
}
&--primary--light {
background-color: #ecf5ff;
}
&--error--dark {
background-color: $u-error;
}
&--error--light {
background-color: #FEF0F0;
}
&--success--dark {
background-color: $u-success;
}
&--success--light {
background-color: #f5fff0;
}
&--warning--dark {
background-color: $u-warning;
}
&--warning--light {
background-color: #FDF6EC;
}
&--info--dark {
background-color: $u-info;
}
&--info--light {
background-color: #f4f4f5;
}
&__icon {
margin-right: 5px;
}
&__content {
@include flex(column);
flex: 1;
&__title {
color: $u-main-color;
font-size: 14px;
font-weight: bold;
color: #fff;
margin-bottom: 2px;
}
&__desc {
color: $u-main-color;
font-size: 14px;
flex-wrap: wrap;
color: #fff;
}
}
&__title--dark,
&__desc--dark {
color: #FFFFFF;
}
&__text--primary--light,
&__text--primary--light {
color: $u-primary;
}
&__text--success--light,
&__text--success--light {
color: $u-success;
}
&__text--warning--light,
&__text--warning--light {
color: $u-warning;
}
&__text--error--light,
&__text--error--light {
color: $u-error;
}
&__text--info--light,
&__text--info--light {
color: $u-info;
}
&__close {
position: absolute;
top: 11px;
right: 10px;
}
}
</style>

@ -0,0 +1,52 @@
export default {
props: {
// 头像图片组
urls: {
type: Array,
default: uni.$u.props.avatarGroup.urls
},
// 最多展示的头像数量
maxCount: {
type: [String, Number],
default: uni.$u.props.avatarGroup.maxCount
},
// 头像形状
shape: {
type: String,
default: uni.$u.props.avatarGroup.shape
},
// 图片裁剪模式
mode: {
type: String,
default: uni.$u.props.avatarGroup.mode
},
// 超出maxCount时是否显示查看更多的提示
showMore: {
type: Boolean,
default: uni.$u.props.avatarGroup.showMore
},
// 头像大小
size: {
type: [String, Number],
default: uni.$u.props.avatarGroup.size
},
// 指定从数组的对象元素中读取哪个属性作为图片地址
keyName: {
type: String,
default: uni.$u.props.avatarGroup.keyName
},
// 头像之间的遮挡比例
gap: {
type: [String, Number],
validator(value) {
return value >= 0 && value <= 1
},
default: uni.$u.props.avatarGroup.gap
},
// 需额外显示的值
extraValue: {
type: [Number, String],
default: uni.$u.props.avatarGroup.extraValue
}
}
}

@ -0,0 +1,103 @@
<template>
<view class="u-avatar-group">
<view
class="u-avatar-group__item"
v-for="(item, index) in showUrl"
:key="index"
:style="{
marginLeft: index === 0 ? 0 : $u.addUnit(-size * gap)
}"
>
<u-avatar
:size="size"
:shape="shape"
:mode="mode"
:src="$u.test.object(item) ? keyName && item[keyName] || item.url : item"
></u-avatar>
<view
class="u-avatar-group__item__show-more"
v-if="showMore && index === showUrl.length - 1 && (urls.length > maxCount || extraValue > 0)"
@tap="clickHandler"
>
<u--text
color="#ffffff"
:size="size * 0.4"
:text="`+${extraValue || urls.length - showUrl.length}`"
align="center"
customStyle="justify-content: center"
></u--text>
</view>
</view>
</view>
</template>
<script>
import props from './props.js';
/**
* AvatarGroup 头像组
* @description 本组件一般用于展示头像的地方如个人中心或者评论列表页的用户头像展示等场所
* @tutorial https://www.uviewui.com/components/avatar.html
*
* @property {Array} urls 头像图片组 默认 []
* @property {String | Number} maxCount 最多展示的头像数量 默认 5
* @property {String} shape 头像形状 'circle' (默认) | 'square'
* @property {String} mode 图片裁剪模式默认 'scaleToFill'
* @property {Boolean} showMore 超出maxCount时是否显示查看更多的提示 默认 true
* @property {String | Number} size 头像大小 默认 40
* @property {String} keyName 指定从数组的对象元素中读取哪个属性作为图片地址
* @property {String | Number} gap 头像之间的遮挡比例0.4代表遮挡40% 默认 0.5
* @property {String | Number} extraValue 需额外显示的值
* @event {Function} showMore 头像组更多点击
* @example <u-avatar-group:urls="urls" size="35" gap="0.4" ></u-avatar-group:urls=>
*/
export default {
name: 'u-avatar-group',
mixins: [uni.$u.mpMixin, uni.$u.mixin, props],
data() {
return {
}
},
computed: {
showUrl() {
return this.urls.slice(0, this.maxCount)
}
},
methods: {
clickHandler() {
this.$emit('showMore')
}
},
}
</script>
<style lang="scss" scoped>
@import "../../libs/css/components.scss";
.u-avatar-group {
@include flex;
&__item {
margin-left: -10px;
position: relative;
&--no-indent {
// 使:first-childnvue
margin-left: 0;
}
&__show-more {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-color: rgba(0, 0, 0, 0.3);
@include flex;
align-items: center;
justify-content: center;
border-radius: 100px;
}
}
}
</style>

@ -0,0 +1,78 @@
export default {
props: {
// 头像图片路径(不能为相对路径)
src: {
type: String,
default: uni.$u.props.avatar.src
},
// 头像形状,circle-圆形,square-方形
shape: {
type: String,
default: uni.$u.props.avatar.shape
},
// 头像尺寸
size: {
type: [String, Number],
default: uni.$u.props.avatar.size
},
// 裁剪模式
mode: {
type: String,
default: uni.$u.props.avatar.mode
},
// 显示的文字
text: {
type: String,
default: uni.$u.props.avatar.text
},
// 背景色
bgColor: {
type: String,
default: uni.$u.props.avatar.bgColor
},
// 文字颜色
color: {
type: String,
default: uni.$u.props.avatar.color
},
// 文字大小
fontSize: {
type: [String, Number],
default: uni.$u.props.avatar.fontSize
},
// 显示的图标
icon: {
type: String,
default: uni.$u.props.avatar.icon
},
// 显示小程序头像,只对百度,微信,QQ小程序有效
mpAvatar: {
type: Boolean,
default: uni.$u.props.avatar.mpAvatar
},
// 是否使用随机背景色
randomBgColor: {
type: Boolean,
default: uni.$u.props.avatar.randomBgColor
},
// 加载失败的默认头像(组件有内置默认图片)
defaultUrl: {
type: String,
default: uni.$u.props.avatar.defaultUrl
},
// 如果配置了randomBgColor为true,且配置了此值,则从默认的背景色数组中取出对应索引的颜色值,取值0-19之间
colorIndex: {
type: [String, Number],
// 校验参数规则,索引在0-19之间
validator(n) {
return uni.$u.test.range(n, [0, 19]) || n === ''
},
default: uni.$u.props.avatar.colorIndex
},
// 组件标识符
name: {
type: String,
default: uni.$u.props.avatar.name
}
}
}

@ -0,0 +1,172 @@
<template>
<view
class="u-avatar"
:class="[`u-avatar--${shape}`]"
:style="[{
backgroundColor: (text || icon) ? (randomBgColor ? colors[colorIndex !== '' ? colorIndex : $u.random(0, 19)] : bgColor) : 'transparent',
width: $u.addUnit(size),
height: $u.addUnit(size),
}, $u.addStyle(customStyle)]"
@tap="clickHandler"
>
<slot>
<!-- #ifdef MP-WEIXIN || MP-QQ || MP-BAIDU -->
<open-data
v-if="mpAvatar && allowMp"
type="userAvatarUrl"
:style="[{
width: $u.addUnit(size),
height: $u.addUnit(size)
}]"
/>
<!-- #endif -->
<!-- #ifndef MP-WEIXIN && MP-QQ && MP-BAIDU -->
<template v-if="mpAvatar && allowMp"></template>
<!-- #endif -->
<u-icon
v-else-if="icon"
:name="icon"
:size="fontSize"
:color="color"
></u-icon>
<u--text
v-else-if="text"
:text="text"
:size="fontSize"
:color="color"
align="center"
customStyle="justify-content: center"
></u--text>
<image
class="u-avatar__image"
v-else
:class="[`u-avatar__image--${shape}`]"
:src="avatarUrl || defaultUrl"
:mode="mode"
@error="errorHandler"
:style="[{
width: $u.addUnit(size),
height: $u.addUnit(size)
}]"
></image>
</slot>
</view>
</template>
<script>
import props from './props.js';
const base64Avatar =
"data:image/jpg;base64,/9j/4QAYRXhpZgAASUkqAAgAAAAAAAAAAAAAAP/sABFEdWNreQABAAQAAAA8AAD/4QMraHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLwA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/PiA8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJBZG9iZSBYTVAgQ29yZSA1LjMtYzAxMSA2Ni4xNDU2NjEsIDIwMTIvMDIvMDYtMTQ6NTY6MjcgICAgICAgICI+IDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+IDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bXA6Q3JlYXRvclRvb2w9IkFkb2JlIFBob3Rvc2hvcCBDUzYgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjREMEQwRkY0RjgwNDExRUE5OTY2RDgxODY3NkJFODMxIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjREMEQwRkY1RjgwNDExRUE5OTY2RDgxODY3NkJFODMxIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6NEQwRDBGRjJGODA0MTFFQTk5NjZEODE4Njc2QkU4MzEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6NEQwRDBGRjNGODA0MTFFQTk5NjZEODE4Njc2QkU4MzEiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7/7gAOQWRvYmUAZMAAAAAB/9sAhAAGBAQEBQQGBQUGCQYFBgkLCAYGCAsMCgoLCgoMEAwMDAwMDBAMDg8QDw4MExMUFBMTHBsbGxwfHx8fHx8fHx8fAQcHBw0MDRgQEBgaFREVGh8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx//wAARCADIAMgDAREAAhEBAxEB/8QAcQABAQEAAwEBAAAAAAAAAAAAAAUEAQMGAgcBAQAAAAAAAAAAAAAAAAAAAAAQAAIBAwICBgkDBQAAAAAAAAABAhEDBCEFMVFBYXGREiKBscHRMkJSEyOh4XLxYjNDFBEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEQMRAD8A/fAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHbHFyZ/Dam+yLA+Z2L0Pjtyj2poD4AAAAAAAAAAAAAAAAAAAAAAAAKWFs9y6lcvvwQeqj8z9wFaziY1n/HbUX9XF97A7QAGXI23EvJ1goyfzR0YEfN269jeZ+a03pNe0DIAAAAAAAAAAAAAAAAAAAACvtO3RcVkXlWutuL9YFYAAAAAOJRjKLjJVi9GmB5/csH/mu1h/in8PU+QGMAAAAAAAAAAAAAAAAAAaMDG/6MmMH8C80+xAelSSVFolwQAAAAAAAHVlWI37ErUulaPk+hgeYnCUJuElSUXRrrQHAAAAAAAAAAAAAAAAABa2Oz4bM7r4zdF2ICmAAAAAAAAAg7zZ8GX41wuJP0rRgYAAAAAAAAAAAAAAAAAD0m2R8ODaXU33tsDSAAAAAAAAAlb9HyWZcnJd9PcBHAAAAAAAAAAAAAAAAAPS7e64Vn+KA0AAAAAAAAAJm+v8Ftf3ewCKAAAAAAAAAAAAAAAAAX9muqeGo9NttP06+0DcAAAAAAAAAjb7dTu2ra+VOT9P8AQCWAAAAAAAAAAAAAAAAAUNmyPt5Ltv4bui/kuAF0AAAAAAADiUlGLlJ0SVW+oDzOXfd/Ind6JPRdS0QHSAAAAAAAAAAAAAAAAAE2nVaNcGB6Lbs6OTao9LsF51z60BrAAAAAABJ3jOVHjW3r/sa9QEgAAAAAAAAAAAAAAAAAAAPu1duWriuW34ZR4MC9hbnZyEoy8l36XwfYBsAAADaSq9EuLAlZ+7xSdrGdW9Hc5dgEdtt1erfFgAAAAAAAAAAAAAAAAADVjbblX6NR8MH80tEBRs7HYivyzlN8lovaBPzduvY0m6eK10TXtAyAarO55lpJK54orolr+4GqO/Xaea1FvqbXvA+Z77kNeW3GPbV+4DJfzcm/pcm3H6Vou5AdAFLC2ed2Pjv1txa8sV8T6wOL+yZEKu1JXFy4MDBOE4ScZxcZLinoB8gAAAAAAAAAAAB242LeyJ+C3GvN9C7QLmJtePYpKS+5c+p8F2IDYAANJqj1T4oCfk7Nj3G5Wn9qXJax7gJ93Z82D8sVNc4v30A6Xg5i42Z+iLfqARwcyT0sz9MWvWBps7LlTf5Grce9/oBTxdtxseklHxT+uWr9AGoAB138ezfj4bsFJdD6V2MCPm7RdtJzs1uW1xXzL3gTgAAAAAAAAADRhYc8q74I6RWs5ckB6GxYtWLat21SK731sDsAAAAAAAAAAAAAAAASt021NO/YjrxuQXT1oCOAAAAAAABzGLlJRSq26JAelwsWONYjbXxcZvmwO8AAAAAAAAAAAAAAAAAAef3TEWPkVivx3NY9T6UBiAAAAAABo2+VmGXblddIJ8eivRUD0oAAAAAAAAAAAAAAAAAAAYt4tKeFKVNYNSXfRgefAAAAAAAAr7VuSSWPedKaW5v1MCsAAAAAAAAAAAAAAAAAAIe6bj96Ts2n+JPzSXzP3ATgAAAAAAAAFbbt1UUrOQ9FpC4/UwK6aaqtU+DAAAAAAAAAAAAAAA4lKMIuUmoxWrb4ARNx3R3q2rLpa4Sl0y/YCcAAAAAAAAAAANmFud7G8r89r6X0dgFvGzLGRGtuWvTF6NAdwAAAAAAAAAAAy5W442PVN+K59EePp5ARMvOv5MvO6QXCC4AZwAAAAAAAAAAAAAcxlKLUotprg1owN+PvORborq+7Hnwl3gUbO74VzRydt8pKn68ANcJwmqwkpLmnUDkAAAAfNy9atqtyagut0AxXt5xIV8Fbj6lRd7Am5G65V6qUvtwfyx94GMAAAAAAAAAAAAAAAAAAAOU2nVOj5gdsc3LiqRvTpyqwOxbnnrhdfpSfrQB7pnv/AGvuS9gHXPMy5/Fem1yq0v0A6W29XqwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf//Z";
/**
* Avatar 头像
* @description 本组件一般用于展示头像的地方如个人中心或者评论列表页的用户头像展示等场所
* @tutorial https://www.uviewui.com/components/avatar.html
*
* @property {String} src 头像路径如加载失败将会显示默认头像(不能为相对路径)
* @property {String} shape 头像形状 circle (默认) | square
* @property {String | Number} size 头像尺寸可以为指定字符串(large, default, mini)或者数值 默认 40
* @property {String} mode 头像图片的裁剪类型与uni的image组件的mode参数一致如效果达不到需求可尝试传widthFix值 默认 'scaleToFill'
* @property {String} text 用文字替代图片级别优先于src
* @property {String} bgColor 背景颜色一般显示文字时用 默认 '#c0c4cc'
* @property {String} color 文字颜色 默认 '#ffffff'
* @property {String | Number} fontSize 文字大小 默认 18
* @property {String} icon 显示的图标
* @property {Boolean} mpAvatar 显示小程序头像只对百度微信QQ小程序有效 默认 false
* @property {Boolean} randomBgColor 是否使用随机背景色 默认 false
* @property {String} defaultUrl 加载失败的默认头像(组件有内置默认图片)
* @property {String | Number} colorIndex 如果配置了randomBgColor为true且配置了此值则从默认的背景色数组中取出对应索引的颜色值取值0-19之间
* @property {String} name 组件标识符 默认 'level'
* @property {Object} customStyle 定义需要用到的外部样式
*
* @event {Function} click 点击组件时触发 index: 用户传递的标识符
* @example <u-avatar :src="src" mode="square"></u-avatar>
*/
export default {
name: 'u-avatar',
mixins: [uni.$u.mpMixin, uni.$u.mixin, props],
data() {
return {
// randomBgColortrue
colors: ['#ffb34b', '#f2bba9', '#f7a196', '#f18080', '#88a867', '#bfbf39', '#89c152', '#94d554', '#f19ec2',
'#afaae4', '#e1b0df', '#c38cc1', '#72dcdc', '#9acdcb', '#77b1cc', '#448aca', '#86cefa', '#98d1ee',
'#73d1f1',
'#80a7dc'
],
avatarUrl: this.src,
allowMp: false
}
},
watch: {
// srcavatarUrlsrc
// props
src: {
immediate: true,
handler(newVal) {
this.avatarUrl = newVal
// srcerrorsrc''
if(!newVal) {
this.errorHandler()
}
}
}
},
computed: {
imageStyle() {
const style = {}
return style
}
},
created() {
this.init()
},
methods: {
init() {
// open-data
// uni.getUserInfo()
//
// #ifdef MP-WEIXIN || MP-QQ || MP-BAIDU
this.allowMp = true
// #endif
},
// name"/"
isImg() {
return this.src.indexOf('/') !== -1
},
//
errorHandler() {
this.avatarUrl = this.defaultUrl || base64Avatar
},
clickHandler() {
this.$emit('click', this.name)
}
}
}
</script>
<style lang="scss" scoped>
@import "../../libs/css/components.scss";
.u-avatar {
@include flex;
align-items: center;
justify-content: center;
&--circle {
border-radius: 100px;
}
&--square {
border-radius: 4px;
}
&__image {
&--circle {
border-radius: 100px;
}
&--square {
border-radius: 4px;
}
}
}
</style>

@ -0,0 +1,54 @@
export default {
props: {
// 返回顶部的形状,circle-圆形,square-方形
mode: {
type: String,
default: uni.$u.props.backtop.mode
},
// 自定义图标
icon: {
type: String,
default: uni.$u.props.backtop.icon
},
// 提示文字
text: {
type: String,
default: uni.$u.props.backtop.text
},
// 返回顶部滚动时间
duration: {
type: [String, Number],
default: uni.$u.props.backtop.duration
},
// 滚动距离
scrollTop: {
type: [String, Number],
default: uni.$u.props.backtop.scrollTop
},
// 距离顶部多少距离显示,单位px
top: {
type: [String, Number],
default: uni.$u.props.backtop.top
},
// 返回顶部按钮到底部的距离,单位px
bottom: {
type: [String, Number],
default: uni.$u.props.backtop.bottom
},
// 返回顶部按钮到右边的距离,单位px
right: {
type: [String, Number],
default: uni.$u.props.backtop.right
},
// 层级
zIndex: {
type: [String, Number],
default: uni.$u.props.backtop.zIndex
},
// 图标的样式,对象形式
iconStyle: {
type: Object,
default: uni.$u.props.backtop.iconStyle
}
}
}

@ -0,0 +1,129 @@
<template>
<u-transition
mode="fade"
:customStyle="backTopStyle"
:show="show"
>
<view
class="u-back-top"
:style="[contentStyle]"
v-if="!$slots.default && !$slots.$default"
@click="backToTop"
>
<u-icon
:name="icon"
:custom-style="iconStyle"
></u-icon>
<text
v-if="text"
class="u-back-top__text"
>{{text}}</text>
</view>
<slot v-else />
</u-transition>
</template>
<script>
import props from './props.js';
// #ifdef APP-NVUE
const dom = weex.requireModule('dom')
// #endif
/**
* backTop 返回顶部
* @description 本组件一个用于长页面滑动一定距离后出现返回顶部按钮方便快速返回顶部的场景
* @tutorial https://uviewui.com/components/backTop.html
*
* @property {String} mode 返回顶部的形状circle-圆形square-方形 默认 'circle'
* @property {String} icon 自定义图标 默认 'arrow-upward' 见官方文档示例
* @property {String} text 提示文字
* @property {String | Number} duration 返回顶部滚动时间 默认 100
* @property {String | Number} scrollTop 滚动距离 默认 0
* @property {String | Number} top 距离顶部多少距离显示单位px 默认 400
* @property {String | Number} bottom 返回顶部按钮到底部的距离单位px 默认 100
* @property {String | Number} right 返回顶部按钮到右边的距离单位px 默认 20
* @property {String | Number} zIndex 层级 默认 9
* @property {Object<Object>} iconStyle 图标的样式对象形式 默认 {color: '#909399',fontSize: '19px'}
* @property {Object} customStyle 定义需要用到的外部样式
*
* @example <u-back-top :scrollTop="scrollTop"></u-back-top>
*/
export default {
name: 'u-back-top',
mixins: [uni.$u.mpMixin, uni.$u.mixin,props],
computed: {
backTopStyle() {
//
const style = {
bottom: uni.$u.addUnit(this.bottom),
right: uni.$u.addUnit(this.right),
width: '40px',
height: '40px',
position: 'fixed',
zIndex: 10,
}
return style
},
show() {
return uni.$u.getPx(this.scrollTop) > uni.$u.getPx(this.top)
},
contentStyle() {
const style = {}
let radius = 0
//
if(this.mode === 'circle') {
radius = '100px'
} else {
radius = '4px'
}
// nvue
style.borderTopLeftRadius = radius
style.borderTopRightRadius = radius
style.borderBottomLeftRadius = radius
style.borderBottomRightRadius = radius
return uni.$u.deepMerge(style, uni.$u.addStyle(this.customStyle))
}
},
methods: {
backToTop() {
// #ifdef APP-NVUE
if (!this.$parent.$refs['u-back-top']) {
uni.$u.error(`nvue页面需要给页面最外层元素设置"ref='u-back-top'`)
}
dom.scrollToElement(this.$parent.$refs['u-back-top'], {
offset: 0
})
// #endif
// #ifndef APP-NVUE
uni.pageScrollTo({
scrollTop: 0,
duration: this.duration
});
// #endif
this.$emit('click')
}
}
}
</script>
<style lang="scss" scoped>
@import '../../libs/css/components.scss';
$u-back-top-flex:1 !default;
$u-back-top-height:100% !default;
$u-back-top-background-color:#E1E1E1 !default;
$u-back-top-tips-font-size:12px !default;
.u-back-top {
@include flex;
flex-direction: column;
align-items: center;
flex:$u-back-top-flex;
height: $u-back-top-height;
justify-content: center;
background-color: $u-back-top-background-color;
&__tips {
font-size:$u-back-top-tips-font-size;
transform: scale(0.8);
}
}
</style>

@ -0,0 +1,72 @@
export default {
props: {
// 是否显示圆点
isDot: {
type: Boolean,
default: uni.$u.props.badge.isDot
},
// 显示的内容
value: {
type: [Number, String],
default: uni.$u.props.badge.value
},
// 是否显示
show: {
type: Boolean,
default: uni.$u.props.badge.show
},
// 最大值,超过最大值会显示 '{max}+'
max: {
type: [Number, String],
default: uni.$u.props.badge.max
},
// 主题类型,error|warning|success|primary
type: {
type: String,
default: uni.$u.props.badge.type
},
// 当数值为 0 时,是否展示 Badge
showZero: {
type: Boolean,
default: uni.$u.props.badge.showZero
},
// 背景颜色,优先级比type高,如设置,type参数会失效
bgColor: {
type: [String, null],
default: uni.$u.props.badge.bgColor
},
// 字体颜色
color: {
type: [String, null],
default: uni.$u.props.badge.color
},
// 徽标形状,circle-四角均为圆角,horn-左下角为直角
shape: {
type: String,
default: uni.$u.props.badge.shape
},
// 设置数字的显示方式,overflow|ellipsis|limit
// overflow会根据max字段判断,超出显示`${max}+`
// ellipsis会根据max判断,超出显示`${max}...`
// limit会依据1000作为判断条件,超出1000,显示`${value/1000}K`,比如2.2k、3.34w,最多保留2位小数
numberType: {
type: String,
default: uni.$u.props.badge.numberType
},
// 设置badge的位置偏移,格式为 [x, y],也即设置的为top和right的值,absolute为true时有效
offset: {
type: Array,
default: uni.$u.props.badge.offset
},
// 是否反转背景和字体颜色
inverted: {
type: Boolean,
default: uni.$u.props.badge.inverted
},
// 是否绝对定位
absolute: {
type: Boolean,
default: uni.$u.props.badge.absolute
}
}
}

@ -0,0 +1,171 @@
<template>
<text
v-if="show && ((Number(value) === 0 ? showZero : true) || isDot)"
:class="[isDot ? 'u-badge--dot' : 'u-badge--not-dot', inverted && 'u-badge--inverted', shape === 'horn' && 'u-badge--horn', `u-badge--${type}${inverted ? '--inverted' : ''}`]"
:style="[$u.addStyle(customStyle), badgeStyle]"
class="u-badge"
>{{ isDot ? '' :showValue }}</text>
</template>
<script>
import props from './props.js';
/**
* badge 徽标数
* @description 该组件一般用于图标右上角显示未读的消息数量提示用户点击有圆点和圆包含文字两种形式
* @tutorial https://uviewui.com/components/badge.html
*
* @property {Boolean} isDot 是否显示圆点 默认 false
* @property {String | Number} value 显示的内容
* @property {Boolean} show 是否显示 默认 true
* @property {String | Number} max 最大值超过最大值会显示 '{max}+' 默认999
* @property {String} type 主题类型error|warning|success|primary 默认 'error'
* @property {Boolean} showZero 当数值为 0 是否展示 Badge 默认 false
* @property {String} bgColor 背景颜色优先级比type高如设置type参数会失效
* @property {String} color 字体颜色 默认 '#ffffff'
* @property {String} shape 徽标形状circle-四角均为圆角horn-左下角为直角 默认 'circle'
* @property {String} numberType 设置数字的显示方式overflow|ellipsis|limit 默认 'overflow'
* @property {Array}} offset 设置badge的位置偏移格式为 [x, y]也即设置的为top和right的值absolute为true时有效
* @property {Boolean} inverted 是否反转背景和字体颜色默认 false
* @property {Boolean} absolute 是否绝对定位默认 false
* @property {Object} customStyle 定义需要用到的外部样式
* @example <u-badge :type="type" :count="count"></u-badge>
*/
export default {
name: 'u-badge',
mixins: [uni.$u.mpMixin, props, uni.$u.mixin],
computed: {
// badge
boxStyle() {
let style = {};
return style;
},
//
badgeStyle() {
const style = {}
if(this.color) {
style.color = this.color
}
if (this.bgColor && !this.inverted) {
style.backgroundColor = this.bgColor
}
if (this.absolute) {
style.position = 'absolute'
// offset
if(this.offset.length) {
// toprightoffsetrighttop
const top = this.offset[0]
const right = this.offset[1] || top
style.top = uni.$u.addUnit(top)
style.right = uni.$u.addUnit(right)
}
}
return style
},
showValue() {
switch (this.numberType) {
case "overflow":
return Number(this.value) > Number(this.max) ? this.max + "+" : this.value
break;
case "ellipsis":
return Number(this.value) > Number(this.max) ? "..." : this.value
break;
case "limit":
return Number(this.value) > 999 ? Number(this.value) >= 9999 ?
Math.floor(this.value / 1e4 * 100) / 100 + "w" : Math.floor(this.value /
1e3 * 100) / 100 + "k" : this.value
break;
default:
return Number(this.value)
}
},
}
}
</script>
<style lang="scss" scoped>
@import "../../libs/css/components.scss";
$u-badge-primary: $u-primary !default;
$u-badge-error: $u-error !default;
$u-badge-success: $u-success !default;
$u-badge-info: $u-info !default;
$u-badge-warning: $u-warning !default;
$u-badge-dot-radius: 100px !default;
$u-badge-dot-size: 8px !default;
$u-badge-dot-right: 4px !default;
$u-badge-dot-top: 0 !default;
$u-badge-text-font-size: 11px !default;
$u-badge-text-right: 10px !default;
$u-badge-text-padding: 2px 5px !default;
$u-badge-text-align: center !default;
$u-badge-text-color: #FFFFFF !default;
.u-badge {
border-top-right-radius: $u-badge-dot-radius;
border-top-left-radius: $u-badge-dot-radius;
border-bottom-left-radius: $u-badge-dot-radius;
border-bottom-right-radius: $u-badge-dot-radius;
@include flex;
line-height: $u-badge-text-font-size;
text-align: $u-badge-text-align;
font-size: $u-badge-text-font-size;
color: $u-badge-text-color;
&--dot {
height: $u-badge-dot-size;
width: $u-badge-dot-size;
}
&--inverted {
font-size: 13px;
}
&--not-dot {
padding: $u-badge-text-padding;
}
&--horn {
border-bottom-left-radius: 0;
}
&--primary {
background-color: $u-badge-primary;
}
&--primary--inverted {
color: $u-badge-primary;
}
&--error {
background-color: $u-badge-error;
}
&--error--inverted {
color: $u-badge-error;
}
&--success {
background-color: $u-badge-success;
}
&--success--inverted {
color: $u-badge-success;
}
&--info {
background-color: $u-badge-info;
}
&--info--inverted {
color: $u-badge-info;
}
&--warning {
background-color: $u-badge-warning;
}
&--warning--inverted {
color: $u-badge-warning;
}
}
</style>

@ -0,0 +1,46 @@
$u-button-active-opacity:0.75 !default;
$u-button-loading-text-margin-left:4px !default;
$u-button-text-color: #FFFFFF !default;
$u-button-text-plain-error-color:$u-error !default;
$u-button-text-plain-warning-color:$u-warning !default;
$u-button-text-plain-success-color:$u-success !default;
$u-button-text-plain-info-color:$u-info !default;
$u-button-text-plain-primary-color:$u-primary !default;
.u-button {
&--active {
opacity: $u-button-active-opacity;
}
&--active--plain {
background-color: rgb(217, 217, 217);
}
&__loading-text {
margin-left:$u-button-loading-text-margin-left;
}
&__text,
&__loading-text {
color:$u-button-text-color;
}
&__text--plain--error {
color:$u-button-text-plain-error-color;
}
&__text--plain--warning {
color:$u-button-text-plain-warning-color;
}
&__text--plain--success{
color:$u-button-text-plain-success-color;
}
&__text--plain--info {
color:$u-button-text-plain-info-color;
}
&__text--plain--primary {
color:$u-button-text-plain-primary-color;
}
}

@ -0,0 +1,161 @@
/*
* @Author : LQ
* @Description :
* @version : 1.0
* @Date : 2021-08-16 10:04:04
* @LastAuthor : LQ
* @lastTime : 2021-08-16 10:04:24
* @FilePath : /u-view2.0/uview-ui/components/u-button/props.js
*/
export default {
props: {
// 是否细边框
hairline: {
type: Boolean,
default: uni.$u.props.button.hairline
},
// 按钮的预置样式,info,primary,error,warning,success
type: {
type: String,
default: uni.$u.props.button.type
},
// 按钮尺寸,large,normal,small,mini
size: {
type: String,
default: uni.$u.props.button.size
},
// 按钮形状,circle(两边为半圆),square(带圆角)
shape: {
type: String,
default: uni.$u.props.button.shape
},
// 按钮是否镂空
plain: {
type: Boolean,
default: uni.$u.props.button.plain
},
// 是否禁止状态
disabled: {
type: Boolean,
default: uni.$u.props.button.disabled
},
// 是否加载中
loading: {
type: Boolean,
default: uni.$u.props.button.loading
},
// 加载中提示文字
loadingText: {
type: [String, Number],
default: uni.$u.props.button.loadingText
},
// 加载状态图标类型
loadingMode: {
type: String,
default: uni.$u.props.button.loadingMode
},
// 加载图标大小
loadingSize: {
type: [String, Number],
default: uni.$u.props.button.loadingSize
},
// 开放能力,具体请看uniapp稳定关于button组件部分说明
// https://uniapp.dcloud.io/component/button
openType: {
type: String,
default: uni.$u.props.button.openType
},
// 用于 <form> 组件,点击分别会触发 <form> 组件的 submit/reset 事件
// 取值为submit(提交表单),reset(重置表单)
formType: {
type: String,
default: uni.$u.props.button.formType
},
// 打开 APP 时,向 APP 传递的参数,open-type=launchApp时有效
// 只微信小程序、QQ小程序有效
appParameter: {
type: String,
default: uni.$u.props.button.appParameter
},
// 指定是否阻止本节点的祖先节点出现点击态,微信小程序有效
hoverStopPropagation: {
type: Boolean,
default: uni.$u.props.button.hoverStopPropagation
},
// 指定返回用户信息的语言,zh_CN 简体中文,zh_TW 繁体中文,en 英文。只微信小程序有效
lang: {
type: String,
default: uni.$u.props.button.lang
},
// 会话来源,open-type="contact"时有效。只微信小程序有效
sessionFrom: {
type: String,
default: uni.$u.props.button.sessionFrom
},
// 会话内消息卡片标题,open-type="contact"时有效
// 默认当前标题,只微信小程序有效
sendMessageTitle: {
type: String,
default: uni.$u.props.button.sendMessageTitle
},
// 会话内消息卡片点击跳转小程序路径,open-type="contact"时有效
// 默认当前分享路径,只微信小程序有效
sendMessagePath: {
type: String,
default: uni.$u.props.button.sendMessagePath
},
// 会话内消息卡片图片,open-type="contact"时有效
// 默认当前页面截图,只微信小程序有效
sendMessageImg: {
type: String,
default: uni.$u.props.button.sendMessageImg
},
// 是否显示会话内消息卡片,设置此参数为 true,用户进入客服会话会在右下角显示"可能要发送的小程序"提示,
// 用户点击后可以快速发送小程序消息,open-type="contact"时有效
showMessageCard: {
type: Boolean,
default: uni.$u.props.button.showMessageCard
},
// 额外传参参数,用于小程序的data-xxx属性,通过target.dataset.name获取
dataName: {
type: String,
default: uni.$u.props.button.dataName
},
// 节流,一定时间内只能触发一次
throttleTime: {
type: [String, Number],
default: uni.$u.props.button.throttleTime
},
// 按住后多久出现点击态,单位毫秒
hoverStartTime: {
type: [String, Number],
default: uni.$u.props.button.hoverStartTime
},
// 手指松开后点击态保留时间,单位毫秒
hoverStayTime: {
type: [String, Number],
default: uni.$u.props.button.hoverStayTime
},
// 按钮文字,之所以通过props传入,是因为slot传入的话
// nvue中无法控制文字的样式
text: {
type: [String, Number],
default: uni.$u.props.button.text
},
// 按钮图标
icon: {
type: String,
default: uni.$u.props.button.icon
},
// 按钮图标
iconColor: {
type: String,
default: uni.$u.props.button.icon
},
// 按钮颜色,支持传入linear-gradient渐变色
color: {
type: String,
default: uni.$u.props.button.color
}
}
}

@ -0,0 +1,490 @@
<template>
<!-- #ifndef APP-NVUE -->
<button
:hover-start-time="Number(hoverStartTime)"
:hover-stay-time="Number(hoverStayTime)"
:form-type="formType"
:open-type="openType"
:app-parameter="appParameter"
:hover-stop-propagation="hoverStopPropagation"
:send-message-title="sendMessageTitle"
:send-message-path="sendMessagePath"
:lang="lang"
:data-name="dataName"
:session-from="sessionFrom"
:send-message-img="sendMessageImg"
:show-message-card="showMessageCard"
@getphonenumber="getphonenumber"
@getuserinfo="getuserinfo"
@error="error"
@opensetting="opensetting"
@launchapp="launchapp"
:hover-class="!disabled && !loading ? 'u-button--active' : ''"
class="u-button u-reset-button"
:style="[baseColor, $u.addStyle(customStyle)]"
@tap="clickHandler"
:class="bemClass"
>
<template v-if="loading">
<u-loading-icon
:mode="loadingMode"
:size="loadingSize * 1.15"
:color="loadingColor"
></u-loading-icon>
<text
class="u-button__loading-text"
:style="[{ fontSize: textSize + 'px' }]"
>{{ loadingText || text }}</text
>
</template>
<template v-else>
<u-icon
v-if="icon"
:name="icon"
:color="iconColorCom"
:size="textSize * 1.35"
:customStyle="{ marginRight: '2px' }"
></u-icon>
<slot>
<text
class="u-button__text"
:style="[{ fontSize: textSize + 'px' }]"
>{{ text }}</text
>
</slot>
</template>
</button>
<!-- #endif -->
<!-- #ifdef APP-NVUE -->
<view
:hover-start-time="Number(hoverStartTime)"
:hover-stay-time="Number(hoverStayTime)"
class="u-button"
:hover-class="
!disabled && !loading && !color && (plain || type === 'info')
? 'u-button--active--plain'
: !disabled && !loading && !plain
? 'u-button--active'
: ''
"
@tap="clickHandler"
:class="bemClass"
:style="[baseColor, $u.addStyle(customStyle)]"
>
<template v-if="loading">
<u-loading-icon
:mode="loadingMode"
:size="loadingSize * 1.15"
:color="loadingColor"
></u-loading-icon>
<text
class="u-button__loading-text"
:style="[nvueTextStyle]"
:class="[plain && `u-button__text--plain--${type}`]"
>{{ loadingText || text }}</text
>
</template>
<template v-else>
<u-icon
v-if="icon"
:name="icon"
:color="iconColorCom"
:size="textSize * 1.35"
></u-icon>
<text
class="u-button__text"
:style="[
{
marginLeft: icon ? '2px' : 0,
},
nvueTextStyle,
]"
:class="[plain && `u-button__text--plain--${type}`]"
>{{ text }}</text
>
</template>
</view>
<!-- #endif -->
</template>
<script>
import button from "../../libs/mixin/button.js";
import openType from "../../libs/mixin/openType.js";
import props from "./props.js";
/**
* button 按钮
* @description Button 按钮
* @tutorial https://www.uviewui.com/components/button.html
*
* @property {Boolean} hairline 是否显示按钮的细边框 (默认 true )
* @property {String} type 按钮的预置样式infoprimaryerrorwarningsuccess (默认 'info' )
* @property {String} size 按钮尺寸largenormalmini 默认 normal
* @property {String} shape 按钮形状circle两边为半圆square带圆角 默认 'square'
* @property {Boolean} plain 按钮是否镂空背景色透明 默认 false
* @property {Boolean} disabled 是否禁用 默认 false
* @property {Boolean} loading 按钮名称前是否带 loading 图标(App-nvue 平台 ios 上为雪花Android上为圆圈) 默认 false
* @property {String | Number} loadingText 加载中提示文字
* @property {String} loadingMode 加载状态图标类型 默认 'spinner'
* @property {String | Number} loadingSize 加载图标大小 默认 15
* @property {String} openType 开放能力具体请看uniapp稳定关于button组件部分说明
* @property {String} formType 用于 <form> 组件点击分别会触发 <form> 组件的 submit/reset 事件
* @property {String} appParameter 打开 APP APP 传递的参数open-type=launchApp时有效 只微信小程序QQ小程序有效
* @property {Boolean} hoverStopPropagation 指定是否阻止本节点的祖先节点出现点击态微信小程序有效默认 true
* @property {String} lang 指定返回用户信息的语言zh_CN 简体中文zh_TW 繁体中文en 英文默认 en
* @property {String} sessionFrom 会话来源openType="contact"时有效
* @property {String} sendMessageTitle 会话内消息卡片标题openType="contact"时有效
* @property {String} sendMessagePath 会话内消息卡片点击跳转小程序路径openType="contact"时有效
* @property {String} sendMessageImg 会话内消息卡片图片openType="contact"时有效
* @property {Boolean} showMessageCard 是否显示会话内消息卡片设置此参数为 true用户进入客服会话会在右下角显示"可能要发送的小程序"提示用户点击后可以快速发送小程序消息openType="contact"时有效默认false
* @property {String} dataName 额外传参参数用于小程序的data-xxx属性通过target.dataset.name获取
* @property {String | Number} throttleTime 节流一定时间内只能触发一次 默认 0 )
* @property {String | Number} hoverStartTime 按住后多久出现点击态单位毫秒 默认 0 )
* @property {String | Number} hoverStayTime 手指松开后点击态保留时间单位毫秒 默认 200 )
* @property {String | Number} text 按钮文字之所以通过props传入是因为slot传入的话nvue中无法控制文字的样式
* @property {String} icon 按钮图标
* @property {String} iconColor 按钮图标颜色
* @property {String} color 按钮颜色支持传入linear-gradient渐变色
* @property {Object} customStyle 定义需要用到的外部样式
*
* @event {Function} click 非禁止并且非加载中才能点击
* @event {Function} getphonenumber open-type="getPhoneNumber"时有效
* @event {Function} getuserinfo 用户点击该按钮时会返回获取到的用户信息从返回参数的detail中获取到的值同uni.getUserInfo
* @event {Function} error 当使用开放能力时发生错误的回调
* @event {Function} opensetting 在打开授权设置页并关闭后回调
* @event {Function} launchapp 打开 APP 成功的回调
* @example <u-button>月落</u-button>
*/
export default {
name: "u-button",
// #ifdef MP
mixins: [uni.$u.mpMixin, uni.$u.mixin, button, openType, props],
// #endif
// #ifndef MP
mixins: [uni.$u.mpMixin, uni.$u.mixin, props],
// #endif
data() {
return {};
},
computed: {
// bem
bemClass() {
// this.bemcomputedmixin
if (!this.color) {
return this.bem(
"button",
["type", "shape", "size"],
["disabled", "plain", "hairline"]
);
} else {
// nvuecolortypetype
return this.bem(
"button",
["shape", "size"],
["disabled", "plain", "hairline"]
);
}
},
loadingColor() {
if (this.plain) {
// colorcolor使type
return this.color
? this.color
: uni.$u.config.color[`u-${this.type}`];
}
if (this.type === "info") {
return "#c9c9c9";
}
return "rgb(200, 200, 200)";
},
iconColorCom() {
// colorcolor使
// u-iconcolor
if (this.iconColor) return this.iconColor;
if (this.plain) {
return this.color ? this.color : this.type;
} else {
return this.type === "info" ? "#000000" : "#ffffff";
}
},
baseColor() {
let style = {};
if (this.color) {
// color
style.color = this.plain ? this.color : "white";
if (!this.plain) {
// 使
style["background-color"] = this.color;
}
if (this.color.indexOf("gradient") !== -1) {
// backgroundImage
// weexborderWidth
// weex西
style.borderTopWidth = 0;
style.borderRightWidth = 0;
style.borderBottomWidth = 0;
style.borderLeftWidth = 0;
if (!this.plain) {
style.backgroundImage = this.color;
}
} else {
//
style.borderColor = this.color;
style.borderWidth = "1px";
style.borderStyle = "solid";
}
}
return style;
},
// nvuetext
nvueTextStyle() {
let style = {};
// color
if (this.type === "info") {
style.color = "#323233";
}
if (this.color) {
style.color = this.plain ? this.color : "white";
}
style.fontSize = this.textSize + "px";
return style;
},
//
textSize() {
let fontSize = 14,
{ size } = this;
if (size === "large") fontSize = 16;
if (size === "normal") fontSize = 14;
if (size === "small") fontSize = 12;
if (size === "mini") fontSize = 10;
return fontSize;
},
},
methods: {
clickHandler() {
//
if (!this.disabled && !this.loading) {
// this.throttle
uni.$u.throttle(() => {
this.$emit("click");
}, this.throttleTime);
}
},
// uniapp
getphonenumber(res) {
this.$emit("getphonenumber", res);
},
getuserinfo(res) {
this.$emit("getuserinfo", res);
},
error(res) {
this.$emit("error", res);
},
opensetting(res) {
this.$emit("opensetting", res);
},
launchapp(res) {
this.$emit("launchapp", res);
},
},
};
</script>
<style lang="scss" scoped>
@import "../../libs/css/components.scss";
/* #ifndef APP-NVUE */
@import "./vue.scss";
/* #endif */
/* #ifdef APP-NVUE */
@import "./nvue.scss";
/* #endif */
$u-button-u-button-height: 40px !default;
$u-button-text-font-size: 15px !default;
$u-button-loading-text-font-size: 15px !default;
$u-button-loading-text-margin-left: 4px !default;
$u-button-large-width: 100% !default;
$u-button-large-height: 50px !default;
$u-button-normal-padding: 0 12px !default;
$u-button-large-padding: 0 15px !default;
$u-button-normal-font-size: 14px !default;
$u-button-small-min-width: 60px !default;
$u-button-small-height: 30px !default;
$u-button-small-padding: 0px 8px !default;
$u-button-mini-padding: 0px 8px !default;
$u-button-small-font-size: 12px !default;
$u-button-mini-height: 22px !default;
$u-button-mini-font-size: 10px !default;
$u-button-mini-min-width: 50px !default;
$u-button-disabled-opacity: 0.5 !default;
$u-button-info-color: #323233 !default;
$u-button-info-background-color: #fff !default;
$u-button-info-border-color: #ebedf0 !default;
$u-button-info-border-width: 1px !default;
$u-button-info-border-style: solid !default;
$u-button-success-color: #fff !default;
$u-button-success-background-color: $u-success !default;
$u-button-success-border-color: $u-button-success-background-color !default;
$u-button-success-border-width: 1px !default;
$u-button-success-border-style: solid !default;
$u-button-primary-color: #fff !default;
$u-button-primary-background-color: $u-primary !default;
$u-button-primary-border-color: $u-button-primary-background-color !default;
$u-button-primary-border-width: 1px !default;
$u-button-primary-border-style: solid !default;
$u-button-error-color: #fff !default;
$u-button-error-background-color: $u-error !default;
$u-button-error-border-color: $u-button-error-background-color !default;
$u-button-error-border-width: 1px !default;
$u-button-error-border-style: solid !default;
$u-button-warning-color: #fff !default;
$u-button-warning-background-color: $u-warning !default;
$u-button-warning-border-color: $u-button-warning-background-color !default;
$u-button-warning-border-width: 1px !default;
$u-button-warning-border-style: solid !default;
$u-button-block-width: 100% !default;
$u-button-circle-border-top-right-radius: 100px !default;
$u-button-circle-border-top-left-radius: 100px !default;
$u-button-circle-border-bottom-left-radius: 100px !default;
$u-button-circle-border-bottom-right-radius: 100px !default;
$u-button-square-border-top-right-radius: 3px !default;
$u-button-square-border-top-left-radius: 3px !default;
$u-button-square-border-bottom-left-radius: 3px !default;
$u-button-square-border-bottom-right-radius: 3px !default;
$u-button-icon-min-width: 1em !default;
$u-button-plain-background-color: #fff !default;
$u-button-hairline-border-width: 0.5px !default;
.u-button {
height: $u-button-u-button-height;
position: relative;
align-items: center;
justify-content: center;
@include flex;
/* #ifndef APP-NVUE */
box-sizing: border-box;
/* #endif */
flex-direction: row;
&__text {
font-size: $u-button-text-font-size;
}
&__loading-text {
font-size: $u-button-loading-text-font-size;
margin-left: $u-button-loading-text-margin-left;
}
&--large {
/* #ifndef APP-NVUE */
width: $u-button-large-width;
/* #endif */
height: $u-button-large-height;
padding: $u-button-large-padding;
}
&--normal {
padding: $u-button-normal-padding;
font-size: $u-button-normal-font-size;
}
&--small {
/* #ifndef APP-NVUE */
min-width: $u-button-small-min-width;
/* #endif */
height: $u-button-small-height;
padding: $u-button-small-padding;
font-size: $u-button-small-font-size;
}
&--mini {
height: $u-button-mini-height;
font-size: $u-button-mini-font-size;
/* #ifndef APP-NVUE */
min-width: $u-button-mini-min-width;
/* #endif */
padding: $u-button-mini-padding;
}
&--disabled {
opacity: $u-button-disabled-opacity;
}
&--info {
color: $u-button-info-color;
background-color: $u-button-info-background-color;
border-color: $u-button-info-border-color;
border-width: $u-button-info-border-width;
border-style: $u-button-info-border-style;
}
&--success {
color: $u-button-success-color;
background-color: $u-button-success-background-color;
border-color: $u-button-success-border-color;
border-width: $u-button-success-border-width;
border-style: $u-button-success-border-style;
}
&--primary {
color: $u-button-primary-color;
background-color: $u-button-primary-background-color;
border-color: $u-button-primary-border-color;
border-width: $u-button-primary-border-width;
border-style: $u-button-primary-border-style;
}
&--error {
color: $u-button-error-color;
background-color: $u-button-error-background-color;
border-color: $u-button-error-border-color;
border-width: $u-button-error-border-width;
border-style: $u-button-error-border-style;
}
&--warning {
color: $u-button-warning-color;
background-color: $u-button-warning-background-color;
border-color: $u-button-warning-border-color;
border-width: $u-button-warning-border-width;
border-style: $u-button-warning-border-style;
}
&--block {
@include flex;
width: $u-button-block-width;
}
&--circle {
border-top-right-radius: $u-button-circle-border-top-right-radius;
border-top-left-radius: $u-button-circle-border-top-left-radius;
border-bottom-left-radius: $u-button-circle-border-bottom-left-radius;
border-bottom-right-radius: $u-button-circle-border-bottom-right-radius;
}
&--square {
border-bottom-left-radius: $u-button-square-border-top-right-radius;
border-bottom-right-radius: $u-button-square-border-top-left-radius;
border-top-left-radius: $u-button-square-border-bottom-left-radius;
border-top-right-radius: $u-button-square-border-bottom-right-radius;
}
&__icon {
/* #ifndef APP-NVUE */
min-width: $u-button-icon-min-width;
line-height: inherit !important;
vertical-align: top;
/* #endif */
}
&--plain {
background-color: $u-button-plain-background-color;
}
&--hairline {
border-width: $u-button-hairline-border-width !important;
}
}
</style>

@ -0,0 +1,80 @@
// nvue下hover-class无效
$u-button-before-top:50% !default;
$u-button-before-left:50% !default;
$u-button-before-width:100% !default;
$u-button-before-height:100% !default;
$u-button-before-transform:translate(-50%, -50%) !default;
$u-button-before-opacity:0 !default;
$u-button-before-background-color:#000 !default;
$u-button-before-border-color:#000 !default;
$u-button-active-before-opacity:.15 !default;
$u-button-icon-margin-left:4px !default;
$u-button-plain-u-button-info-color:$u-info;
$u-button-plain-u-button-success-color:$u-success;
$u-button-plain-u-button-error-color:$u-error;
$u-button-plain-u-button-warning-color:$u-error;
.u-button {
width: 100%;
&__text {
white-space: nowrap;
line-height: 1;
}
&:before {
position: absolute;
top:$u-button-before-top;
left:$u-button-before-left;
width:$u-button-before-width;
height:$u-button-before-height;
border: inherit;
border-radius: inherit;
transform:$u-button-before-transform;
opacity:$u-button-before-opacity;
content: " ";
background-color:$u-button-before-background-color;
border-color:$u-button-before-border-color;
}
&--active {
&:before {
opacity: .15
}
}
&__icon+&__text:not(:empty),
&__loading-text {
margin-left:$u-button-icon-margin-left;
}
&--plain {
&.u-button--primary {
color: $u-primary;
}
}
&--plain {
&.u-button--info {
color:$u-button-plain-u-button-info-color;
}
}
&--plain {
&.u-button--success {
color:$u-button-plain-u-button-success-color;
}
}
&--plain {
&.u-button--error {
color:$u-button-plain-u-button-error-color;
}
}
&--plain {
&.u-button--warning {
color:$u-button-plain-u-button-warning-color;
}
}
}

@ -0,0 +1,99 @@
<template>
<view class="u-calendar-header u-border-bottom">
<text
class="u-calendar-header__title"
v-if="showTitle"
>{{ title }}</text>
<text
class="u-calendar-header__subtitle"
v-if="showSubtitle"
>{{ subtitle }}</text>
<view class="u-calendar-header__weekdays">
<text class="u-calendar-header__weekdays__weekday"></text>
<text class="u-calendar-header__weekdays__weekday"></text>
<text class="u-calendar-header__weekdays__weekday"></text>
<text class="u-calendar-header__weekdays__weekday"></text>
<text class="u-calendar-header__weekdays__weekday"></text>
<text class="u-calendar-header__weekdays__weekday"></text>
<text class="u-calendar-header__weekdays__weekday"></text>
</view>
</view>
</template>
<script>
export default {
name: 'u-calendar-header',
mixins: [uni.$u.mpMixin, uni.$u.mixin],
props: {
//
title: {
type: String,
default: ''
},
//
subtitle: {
type: String,
default: ''
},
//
showTitle: {
type: Boolean,
default: true
},
//
showSubtitle: {
type: Boolean,
default: true
},
},
data() {
return {
}
},
methods: {
name() {
}
},
}
</script>
<style lang="scss" scoped>
@import "../../libs/css/components.scss";
.u-calendar-header {
padding-bottom: 4px;
&__title {
font-size: 16px;
color: $u-main-color;
text-align: center;
height: 42px;
line-height: 42px;
font-weight: bold;
}
&__subtitle {
font-size: 14px;
color: $u-main-color;
height: 40px;
text-align: center;
line-height: 40px;
font-weight: bold;
}
&__weekdays {
@include flex;
justify-content: space-between;
&__weekday {
font-size: 13px;
color: $u-main-color;
line-height: 30px;
flex: 1;
text-align: center;
}
}
}
</style>

@ -0,0 +1,579 @@
<template>
<view class="u-calendar-month-wrapper" ref="u-calendar-month-wrapper">
<view v-for="(item, index) in months" :key="index" :class="[`u-calendar-month-${index}`]"
:ref="`u-calendar-month-${index}`" :id="`month-${index}`">
<text v-if="index !== 0" class="u-calendar-month__title">{{ item.year }}{{ item.month }}</text>
<view class="u-calendar-month__days">
<view v-if="showMark" class="u-calendar-month__days__month-mark-wrapper">
<text class="u-calendar-month__days__month-mark-wrapper__text">{{ item.month }}</text>
</view>
<view class="u-calendar-month__days__day" v-for="(item1, index1) in item.date" :key="index1"
:style="[dayStyle(index, index1, item1)]" @tap="clickHandler(index, index1, item1)"
:class="[item1.selected && 'u-calendar-month__days__day__select--selected']">
<view class="u-calendar-month__days__day__select" :style="[daySelectStyle(index, index1, item1)]">
<text class="u-calendar-month__days__day__select__info"
:class="[item1.disabled && 'u-calendar-month__days__day__select__info--disabled']"
:style="[textStyle(item1)]">{{ item1.day }}</text>
<text v-if="getBottomInfo(index, index1, item1)"
class="u-calendar-month__days__day__select__buttom-info"
:class="[item1.disabled && 'u-calendar-month__days__day__select__buttom-info--disabled']"
:style="[textStyle(item1)]">{{ getBottomInfo(index, index1, item1) }}</text>
<text v-if="item1.dot" class="u-calendar-month__days__day__select__dot"></text>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
// #ifdef APP-NVUE
// nvue
const dom = uni.requireNativePlugin('dom')
// #endif
import dayjs from '../../libs/util/dayjs.js';
export default {
name: 'u-calendar-month',
mixins: [uni.$u.mpMixin, uni.$u.mixin],
props: {
//
showMark: {
type: Boolean,
default: true
},
//
color: {
type: String,
default: '#3c9cff'
},
//
months: {
type: Array,
default: () => []
},
//
mode: {
type: String,
default: 'single'
},
//
rowHeight: {
type: [String, Number],
default: 58
},
// mode=multiple
maxCount: {
type: [String, Number],
default: Infinity
},
// mode=range
startText: {
type: String,
default: '开始'
},
// mode=range
endText: {
type: String,
default: '结束'
},
// modemultiplerange
defaultDate: {
type: [Array, String, Date],
default: null
},
//
minDate: {
type: [String, Number],
default: 0
},
//
maxDate: {
type: [String, Number],
default: 0
},
// maxDate
maxMonth: {
type: [String, Number],
default: 2
},
//
readonly: {
type: Boolean,
default: uni.$u.props.calendar.readonly
},
// mode = range
maxRange: {
type: [Number, String],
default: Infinity
},
// mode = range
rangePrompt: {
type: String,
default: ''
},
// mode = range
showRangePrompt: {
type: Boolean,
default: true
},
// mode = range
allowSameDay: {
type: Boolean,
default: false
}
},
data() {
return {
//
width: 0,
// item
item: {},
selected: []
}
},
watch: {
selectedChange: {
immediate: true,
handler(n) {
this.setDefaultDate()
}
}
},
computed: {
//
selectedChange() {
return [this.minDate, this.maxDate, this.defaultDate]
},
dayStyle(index1, index2, item) {
return (index1, index2, item) => {
const style = {}
let week = item.week
// 2
const dayWidth = Number(parseFloat(this.width / 7).toFixed(3).slice(0, -1))
//
// #ifdef APP-NVUE
style.width = uni.$u.addUnit(dayWidth)
// #endif
style.height = uni.$u.addUnit(this.rowHeight)
if (index2 === 0) {
// 0item
week = (week === 0 ? 7 : week) - 1
style.marginLeft = uni.$u.addUnit(week * dayWidth)
}
if (this.mode === 'range') {
// DCloudiOSbug
style.paddingLeft = 0
style.paddingRight = 0
style.paddingBottom = 0
style.paddingTop = 0
}
return style
}
},
daySelectStyle() {
return (index1, index2, item) => {
let date = dayjs(item.date).format("YYYY-MM-DD"),
style = {}
// dateselected0使dateSameincludes
if (this.selected.some(item => this.dateSame(item, date))) {
style.backgroundColor = this.color
}
if (this.mode === 'single') {
if (date === this.selected[0]) {
// nvue
style.borderTopLeftRadius = '3px'
style.borderBottomLeftRadius = '3px'
style.borderTopRightRadius = '3px'
style.borderBottomRightRadius = '3px'
}
} else if (this.mode === 'range') {
if (this.selected.length >= 2) {
const len = this.selected.length - 1
//
if (this.dateSame(date, this.selected[0])) {
style.borderTopLeftRadius = '3px'
style.borderBottomLeftRadius = '3px'
}
//
if (this.dateSame(date, this.selected[len])) {
style.borderTopRightRadius = '3px'
style.borderBottomRightRadius = '3px'
}
//
if (dayjs(date).isAfter(dayjs(this.selected[0])) && dayjs(date).isBefore(dayjs(this
.selected[len]))) {
style.backgroundColor = uni.$u.colorGradient(this.color, '#ffffff', 100)[90]
// mark
style.opacity = 0.7
}
} else if (this.selected.length === 1) {
// DCloudiOSbug
// nvueiOSuni-appbug
style.borderTopLeftRadius = '3px'
style.borderBottomLeftRadius = '3px'
}
} else {
if (this.selected.some(item => this.dateSame(item, date))) {
style.borderTopLeftRadius = '3px'
style.borderBottomLeftRadius = '3px'
style.borderTopRightRadius = '3px'
style.borderBottomRightRadius = '3px'
}
}
return style
}
},
//
textStyle() {
return (item) => {
const date = dayjs(item.date).format("YYYY-MM-DD"),
style = {}
//
if (this.selected.some(item => this.dateSame(item, date))) {
style.color = '#ffffff'
}
if (this.mode === 'range') {
const len = this.selected.length - 1
//
if (dayjs(date).isAfter(dayjs(this.selected[0])) && dayjs(date).isBefore(dayjs(this
.selected[len]))) {
style.color = this.color
}
}
return style
}
},
//
getBottomInfo() {
return (index1, index2, item) => {
const date = dayjs(item.date).format("YYYY-MM-DD")
const bottomInfo = item.bottomInfo
// 0
if (this.mode === 'range' && this.selected.length > 0) {
if (this.selected.length === 1) {
//
if (this.dateSame(date, this.selected[0])) return this.startText
else return bottomInfo
} else {
const len = this.selected.length - 1
// 2
if (this.dateSame(date, this.selected[0]) && this.dateSame(date, this.selected[1]) &&
len === 1) {
// 2item
return `${this.startText}/${this.endText}`
} else if (this.dateSame(date, this.selected[0])) {
return this.startText
} else if (this.dateSame(date, this.selected[len])) {
return this.endText
} else {
return bottomInfo
}
}
} else {
return bottomInfo
}
}
}
},
mounted() {
this.init()
},
methods: {
init() {
//
this.$emit('monthSelected', this.selected)
this.$nextTick(() => {
//
// nvue$nextTick100%
uni.$u.sleep(10).then(() => {
this.getWrapperWidth()
this.getMonthRect()
})
})
},
//
dateSame(date1, date2) {
return dayjs(date1).isSame(dayjs(date2))
},
// nvuecssitem
getWrapperWidth() {
// #ifdef APP-NVUE
dom.getComponentRect(this.$refs['u-calendar-month-wrapper'], res => {
this.width = res.size.width
})
// #endif
// #ifndef APP-NVUE
this.$uGetRect('.u-calendar-month-wrapper').then(size => {
this.width = size.width
})
// #endif
},
getMonthRect() {
// scroll-view
const promiseAllArr = this.months.map((item, index) => this.getMonthRectByPromise(
`u-calendar-month-${index}`))
//
Promise.all(promiseAllArr).then(
sizes => {
let height = 1
const topArr = []
for (let i = 0; i < this.months.length; i++) {
// monthsscroll-view
topArr[i] = height
height += sizes[i].height
}
// this.months[i].top()monthtop使
this.$emit('updateMonthTop', topArr)
})
},
//
getMonthRectByPromise(el) {
// #ifndef APP-NVUE
// $uGetRectuViewhttps://www.uviewui.com/js/getRect.html
// this.$uGetRectuni.$u.getRect
return new Promise(resolve => {
this.$uGetRect(`.${el}`).then(size => {
resolve(size)
})
})
// #endif
// #ifdef APP-NVUE
// nvue使dom
// promise使then
return new Promise(resolve => {
dom.getComponentRect(this.$refs[el][0], res => {
resolve(res.size)
})
})
// #endif
},
//
clickHandler(index1, index2, item) {
if (this.readonly) {
return;
}
this.item = item
const date = dayjs(item.date).format("YYYY-MM-DD")
if (item.disabled) return
//
let selected = uni.$u.deepClone(this.selected)
if (this.mode === 'single') {
//
selected = [date]
} else if (this.mode === 'multiple') {
if (selected.some(item => this.dateSame(item, date))) {
//
const itemIndex = selected.findIndex(item => item === date)
selected.splice(itemIndex, 1)
} else {
//
if (selected.length < this.maxCount) selected.push(date)
}
} else {
//
if (selected.length === 0 || selected.length >= 2) {
// 02
selected = [date]
} else if (selected.length === 1) {
//
const existsDate = selected[0]
//
if (dayjs(date).isBefore(existsDate)) {
selected = [date]
} else if (dayjs(date).isAfter(existsDate)) {
//
if(dayjs(dayjs(date).subtract(this.maxRange, 'day')).isAfter(dayjs(selected[0])) && this.showRangePrompt) {
if(this.rangePrompt) {
uni.$u.toast(this.rangePrompt)
} else {
uni.$u.toast(`选择天数不能超过 ${this.maxRange}`)
}
return
}
//
selected.push(date)
const startDate = selected[0]
const endDate = selected[1]
const arr = []
let i = 0
do {
//
arr.push(dayjs(startDate).add(i, 'day').format("YYYY-MM-DD"))
i++
//
} while (dayjs(startDate).add(i, 'day').isBefore(dayjs(endDate)))
// computedarr
arr.push(endDate)
selected = arr
} else {
//
if (selected[0] === date && !this.allowSameDay) return
selected.push(date)
}
}
}
this.setSelected(selected)
},
//
setDefaultDate() {
if (!this.defaultDate) {
//
const selected = [dayjs().format("YYYY-MM-DD")]
return this.setSelected(selected, false)
}
let defaultDate = []
const minDate = this.minDate || dayjs().format("YYYY-MM-DD")
const maxDate = this.maxDate || dayjs(minDate).add(this.maxMonth - 1, 'month').format("YYYY-MM-DD")
if (this.mode === 'single') {
// Date
if (!uni.$u.test.array(this.defaultDate)) {
defaultDate = [dayjs(this.defaultDate).format("YYYY-MM-DD")]
} else {
defaultDate = [this.defaultDate[0]]
}
} else {
//
if (!uni.$u.test.array(this.defaultDate)) return
defaultDate = this.defaultDate
}
//
defaultDate = defaultDate.filter(item => {
return dayjs(item).isAfter(dayjs(minDate).subtract(1, 'day')) && dayjs(item).isBefore(dayjs(
maxDate).add(1, 'day'))
})
this.setSelected(defaultDate, false)
},
setSelected(selected, event = true) {
this.selected = selected
event && this.$emit('monthSelected', this.selected)
}
}
}
</script>
<style lang="scss" scoped>
@import "../../libs/css/components.scss";
.u-calendar-month-wrapper {
margin-top: 4px;
}
.u-calendar-month {
&__title {
font-size: 14px;
line-height: 42px;
height: 42px;
color: $u-main-color;
text-align: center;
font-weight: bold;
}
&__days {
position: relative;
@include flex;
flex-wrap: wrap;
&__month-mark-wrapper {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
@include flex;
justify-content: center;
align-items: center;
&__text {
font-size: 155px;
color: rgba(231, 232, 234, 0.83);
}
}
&__day {
@include flex;
padding: 2px;
/* #ifndef APP-NVUE */
// vue使cssjs
width: calc(100% / 7);
box-sizing: border-box;
/* #endif */
&__select {
flex: 1;
@include flex;
align-items: center;
justify-content: center;
position: relative;
&__dot {
width: 7px;
height: 7px;
border-radius: 100px;
background-color: $u-error;
position: absolute;
top: 12px;
right: 7px;
}
&__buttom-info {
color: $u-content-color;
text-align: center;
position: absolute;
bottom: 5px;
font-size: 10px;
text-align: center;
left: 0;
right: 0;
&--selected {
color: #ffffff;
}
&--disabled {
color: #cacbcd;
}
}
&__info {
text-align: center;
font-size: 16px;
&--selected {
color: #ffffff;
}
&--disabled {
color: #cacbcd;
}
}
&--selected {
background-color: $u-primary;
@include flex;
justify-content: center;
align-items: center;
flex: 1;
border-radius: 3px;
}
&--range-selected {
opacity: 0.3;
border-radius: 0;
}
&--range-start-selected {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
&--range-end-selected {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
}
}
}
}
</style>

@ -0,0 +1,144 @@
export default {
props: {
// 日历顶部标题
title: {
type: String,
default: uni.$u.props.calendar.title
},
// 是否显示标题
showTitle: {
type: Boolean,
default: uni.$u.props.calendar.showTitle
},
// 是否显示副标题
showSubtitle: {
type: Boolean,
default: uni.$u.props.calendar.showSubtitle
},
// 日期类型选择,single-选择单个日期,multiple-可以选择多个日期,range-选择日期范围
mode: {
type: String,
default: uni.$u.props.calendar.mode
},
// mode=range时,第一个日期底部的提示文字
startText: {
type: String,
default: uni.$u.props.calendar.startText
},
// mode=range时,最后一个日期底部的提示文字
endText: {
type: String,
default: uni.$u.props.calendar.endText
},
// 自定义列表
customList: {
type: Array,
default: uni.$u.props.calendar.customList
},
// 主题色,对底部按钮和选中日期有效
color: {
type: String,
default: uni.$u.props.calendar.color
},
// 最小的可选日期
minDate: {
type: [String, Number],
default: uni.$u.props.calendar.minDate
},
// 最大可选日期
maxDate: {
type: [String, Number],
default: uni.$u.props.calendar.maxDate
},
// 默认选中的日期,mode为multiple或range是必须为数组格式
defaultDate: {
type: [Array, String, Date, null],
default: uni.$u.props.calendar.defaultDate
},
// mode=multiple时,最多可选多少个日期
maxCount: {
type: [String, Number],
default: uni.$u.props.calendar.maxCount
},
// 日期行高
rowHeight: {
type: [String, Number],
default: uni.$u.props.calendar.rowHeight
},
// 日期格式化函数
formatter: {
type: [Function, null],
default: uni.$u.props.calendar.formatter
},
// 是否显示农历
showLunar: {
type: Boolean,
default: uni.$u.props.calendar.showLunar
},
// 是否显示月份背景色
showMark: {
type: Boolean,
default: uni.$u.props.calendar.showMark
},
// 确定按钮的文字
confirmText: {
type: String,
default: uni.$u.props.calendar.confirmText
},
// 确认按钮处于禁用状态时的文字
confirmDisabledText: {
type: String,
default: uni.$u.props.calendar.confirmDisabledText
},
// 是否显示日历弹窗
show: {
type: Boolean,
default: uni.$u.props.calendar.show
},
// 是否允许点击遮罩关闭日历
closeOnClickOverlay: {
type: Boolean,
default: uni.$u.props.calendar.closeOnClickOverlay
},
// 是否为只读状态,只读状态下禁止选择日期
readonly: {
type: Boolean,
default: uni.$u.props.calendar.readonly
},
// 是否展示确认按钮
showConfirm: {
type: Boolean,
default: uni.$u.props.calendar.showConfirm
},
// 日期区间最多可选天数,默认无限制,mode = range时有效
maxRange: {
type: [Number, String],
default: uni.$u.props.calendar.maxRange
},
// 范围选择超过最多可选天数时的提示文案,mode = range时有效
rangePrompt: {
type: String,
default: uni.$u.props.calendar.rangePrompt
},
// 范围选择超过最多可选天数时,是否展示提示文案,mode = range时有效
showRangePrompt: {
type: Boolean,
default: uni.$u.props.calendar.showRangePrompt
},
// 是否允许日期范围的起止时间为同一天,mode = range时有效
allowSameDay: {
type: Boolean,
default: uni.$u.props.calendar.allowSameDay
},
// 圆角值
round: {
type: [Boolean, String, Number],
default: uni.$u.props.calendar.round
},
// 最多展示月份数量
monthNum: {
type: [Number, String],
default: 3
}
}
}

@ -0,0 +1,383 @@
<template>
<u-popup
:show="show"
mode="bottom"
closeable
@close="close"
:round="round"
:closeOnClickOverlay="closeOnClickOverlay"
>
<view class="u-calendar">
<uHeader
:title="title"
:subtitle="subtitle"
:showSubtitle="showSubtitle"
:showTitle="showTitle"
></uHeader>
<scroll-view
:style="{
height: $u.addUnit(listHeight)
}"
scroll-y
@scroll="onScroll"
:scroll-top="scrollTop"
:scrollIntoView="scrollIntoView"
>
<uMonth
:color="color"
:rowHeight="rowHeight"
:showMark="showMark"
:months="months"
:mode="mode"
:maxCount="maxCount"
:startText="startText"
:endText="endText"
:defaultDate="defaultDate"
:minDate="innerMinDate"
:maxDate="innerMaxDate"
:maxMonth="monthNum"
:readonly="readonly"
:maxRange="maxRange"
:rangePrompt="rangePrompt"
:showRangePrompt="showRangePrompt"
:allowSameDay="allowSameDay"
ref="month"
@monthSelected="monthSelected"
@updateMonthTop="updateMonthTop"
></uMonth>
</scroll-view>
<slot name="footer" v-if="showConfirm">
<view class="u-calendar__confirm">
<u-button
shape="circle"
:text="
buttonDisabled ? confirmDisabledText : confirmText
"
:color="color"
@click="confirm"
:disabled="buttonDisabled"
></u-button>
</view>
</slot>
</view>
</u-popup>
</template>
<script>
import uHeader from './header.vue'
import uMonth from './month.vue'
import props from './props.js'
import util from './util.js'
import dayjs from '../../libs/util/dayjs.js'
import Calendar from '../../libs/util/calendar.js'
/**
* Calendar 日历
* @description 此组件用于单个选择日期范围选择日期等日历被包裹在底部弹起的容器中.
* @tutorial https://www.uviewui.com/components/calendar.html
*
* @property {String} title 标题内容 (默认 日期选择 )
* @property {Boolean} showTitle 是否显示标题 (默认 true )
* @property {Boolean} showSubtitle 是否显示副标题 (默认 true )
* @property {String} mode 日期类型选择 single-选择单个日期multiple-可以选择多个日期range-选择日期范围 默认 'single' )
* @property {String} startText mode=range时第一个日期底部的提示文字 (默认 '开始' )
* @property {String} endText mode=range时最后一个日期底部的提示文字 (默认 '结束' )
* @property {Array} customList 自定义列表
* @property {String} color 主题色对底部按钮和选中日期有效 (默认 #3c9cff' )
* @property {String | Number} minDate 最小的可选日期 (默认 0 )
* @property {String | Number} maxDate 最大可选日期 (默认 0 )
* @property {Array | String| Date} defaultDate 默认选中的日期mode为multiple或range是必须为数组格式
* @property {String | Number} maxCount mode=multiple时最多可选多少个日期 (默认 Number.MAX_SAFE_INTEGER )
* @property {String | Number} rowHeight 日期行高 (默认 56 )
* @property {Function} formatter 日期格式化函数
* @property {Boolean} showLunar 是否显示农历 (默认 false )
* @property {Boolean} showMark 是否显示月份背景色 (默认 true )
* @property {String} confirmText 确定按钮的文字 (默认 '确定' )
* @property {String} confirmDisabledText 确认按钮处于禁用状态时的文字 (默认 '确定' )
* @property {Boolean} show 是否显示日历弹窗 (默认 false )
* @property {Boolean} closeOnClickOverlay 是否允许点击遮罩关闭日历 (默认 false )
* @property {Boolean} readonly 是否为只读状态只读状态下禁止选择日期 (默认 false )
* @property {String | Number} maxRange 日期区间最多可选天数默认无限制mode = range时有效
* @property {String} rangePrompt 范围选择超过最多可选天数时的提示文案mode = range时有效
* @property {Boolean} showRangePrompt 范围选择超过最多可选天数时是否展示提示文案mode = range时有效 (默认 true )
* @property {Boolean} allowSameDay 是否允许日期范围的起止时间为同一天mode = range时有效 (默认 false )
* @property {Number|String} round 圆角值默认无圆角 (默认 0 )
* @property {Number|String} monthNum 最多展示的月份数量 (默认 3 )
*
* @event {Function()} confirm 点击确定按钮时触发 选择日期相关的返回参数
* @event {Function()} close 日历关闭时触发 可定义页面关闭时的回调事件
* @example <u-calendar :defaultDate="defaultDateMultiple" :show="show" mode="multiple" @confirm="confirm">
</u-calendar>
* */
export default {
name: 'u-calendar',
mixins: [uni.$u.mpMixin, uni.$u.mixin, props],
components: {
uHeader,
uMonth
},
data() {
return {
//
months: [],
// index
monthIndex: 0,
//
listHeight: 0,
// month
selected: [],
scrollIntoView: '',
scrollTop:0,
//
innerFormatter: (value) => value
}
},
watch: {
selectedChange: {
immediate: true,
handler(n) {
this.setMonth()
}
},
//
show: {
immediate: true,
handler(n) {
this.setMonth()
}
}
},
computed: {
// maxDateminDate(2021-10-10)()dayjs
innerMaxDate() {
return uni.$u.test.number(this.maxDate)
? Number(this.maxDate)
: this.maxDate
},
innerMinDate() {
return uni.$u.test.number(this.minDate)
? Number(this.minDate)
: this.minDate
},
//
selectedChange() {
return [this.innerMinDate, this.innerMaxDate, this.defaultDate]
},
subtitle() {
// this.months
if (this.months.length) {
return `${this.months[this.monthIndex].year}${
this.months[this.monthIndex].month
}`
} else {
return ''
}
},
buttonDisabled() {
// range1disabled
if (this.mode === 'range') {
if (this.selected.length <= 1) {
return true
} else {
return false
}
} else {
return false
}
}
},
mounted() {
this.start = Date.now()
this.init()
},
methods: {
// propsref
setFormatter(e) {
this.innerFormatter = e
},
// month
monthSelected(e) {
this.selected = e
if (!this.showConfirm) {
// 2
if (
this.mode === 'multiple' ||
this.mode === 'single' ||
(this.mode === 'range' && this.selected.length >= 2)
) {
this.$emit('confirm', this.selected)
}
}
},
init() {
// maxDate
if (
this.innerMaxDate &&
new Date(this.innerMaxDate).getTime() <= Date.now()
) {
return uni.$u.error('maxDate不能小于当前时间')
}
//
this.listHeight = this.rowHeight * 5 + 30
this.setMonth()
},
close() {
this.$emit('close')
},
//
confirm() {
if (!this.buttonDisabled) {
this.$emit('confirm', this.selected)
}
},
//
getMonths(minDate, maxDate) {
const minYear = dayjs(minDate).year()
const minMonth = dayjs(minDate).month() + 1
const maxYear = dayjs(maxDate).year()
const maxMonth = dayjs(maxDate).month() + 1
return (maxYear - minYear) * 12 + (maxMonth - minMonth) + 1
},
//
setMonth() {
//
const minDate = this.innerMinDate || dayjs().valueOf()
// 3
const maxDate =
this.innerMaxDate ||
dayjs(minDate)
.add(this.monthNum - 1, 'month')
.valueOf()
//
const months = uni.$u.range(
1,
this.monthNum,
this.getMonths(minDate, maxDate)
)
//
this.months = []
for (let i = 0; i < months; i++) {
this.months.push({
date: new Array(
dayjs(minDate).add(i, 'month').daysInMonth()
)
.fill(1)
.map((item, index) => {
// 1-31
let day = index + 1
// 0-60
const week = dayjs(minDate)
.add(i, 'month')
.date(day)
.day()
const date = dayjs(minDate)
.add(i, 'month')
.date(day)
.format('YYYY-MM-DD')
let bottomInfo = ''
if (this.showLunar) {
//
const lunar = Calendar.solar2lunar(
dayjs(date).year(),
dayjs(date).month() + 1,
dayjs(date).date()
)
bottomInfo = lunar.IDayCn
}
let config = {
day,
week,
// disabled
disabled:
dayjs(date).isBefore(
dayjs(minDate).format('YYYY-MM-DD')
) ||
dayjs(date).isAfter(
dayjs(maxDate).format('YYYY-MM-DD')
),
// formatter
date: new Date(date),
bottomInfo,
dot: false,
month:
dayjs(minDate).add(i, 'month').month() + 1
}
const formatter =
this.formatter || this.innerFormatter
return formatter(config)
}),
//
month: dayjs(minDate).add(i, 'month').month() + 1,
//
year: dayjs(minDate).add(i, 'month').year()
})
}
},
//
scrollIntoDefaultMonth(selected) {
//
const _index = this.months.findIndex(({
year,
month
}) => {
month = uni.$u.padZero(month)
return `${year}-${month}` === selected
})
if (_index !== -1) {
// #ifndef MP-WEIXIN
this.$nextTick(() => {
this.scrollIntoView = `month-${_index}`
})
// #endif
// #ifdef MP-WEIXIN
this.scrollTop = this.months[_index].top || 0;
// #endif
}
},
// scroll-view
onScroll(event) {
// 0scroll-view
const scrollTop = Math.max(0, event.detail.scrollTop)
//
for (let i = 0; i < this.months.length; i++) {
if (scrollTop >= (this.months[i].top || this.listHeight)) {
this.monthIndex = i
}
}
},
// top
updateMonthTop(topArr = []) {
// toponScroll
topArr.map((item, index) => {
this.months[index].top = item
})
//
if (!this.defaultDate) {
//
const selected = dayjs().format("YYYY-MM")
this.scrollIntoDefaultMonth(selected)
return
}
let selected = dayjs().format("YYYY-MM");
// Date
if (!uni.$u.test.array(this.defaultDate)) {
selected = dayjs(this.defaultDate).format("YYYY-MM")
} else {
selected = dayjs(this.defaultDate[0]).format("YYYY-MM");
}
this.scrollIntoDefaultMonth(selected)
}
}
}
</script>
<style lang="scss" scoped>
@import '../../libs/css/components.scss';
.u-calendar {
&__confirm {
padding: 7px 18px;
}
}
</style>

@ -0,0 +1,85 @@
export default {
methods: {
// 设置月份数据
setMonth() {
// 月初是周几
const day = dayjs(this.date).date(1).day()
const start = day == 0 ? 6 : day - 1
// 本月天数
const days = dayjs(this.date).endOf('month').format('D')
// 上个月天数
const prevDays = dayjs(this.date).endOf('month').subtract(1, 'month').format('D')
// 日期数据
const arr = []
// 清空表格
this.month = []
// 添加上月数据
arr.push(
...new Array(start).fill(1).map((e, i) => {
const day = prevDays - start + i + 1
return {
value: day,
disabled: true,
date: dayjs(this.date).subtract(1, 'month').date(day).format('YYYY-MM-DD')
}
})
)
// 添加本月数据
arr.push(
...new Array(days - 0).fill(1).map((e, i) => {
const day = i + 1
return {
value: day,
date: dayjs(this.date).date(day).format('YYYY-MM-DD')
}
})
)
// 添加下个月
arr.push(
...new Array(42 - days - start).fill(1).map((e, i) => {
const day = i + 1
return {
value: day,
disabled: true,
date: dayjs(this.date).add(1, 'month').date(day).format('YYYY-MM-DD')
}
})
)
// 分割数组
for (let n = 0; n < arr.length; n += 7) {
this.month.push(
arr.slice(n, n + 7).map((e, i) => {
e.index = i + n
// 自定义信息
const custom = this.customList.find((c) => c.date == e.date)
// 农历
if (this.lunar) {
const {
IDayCn,
IMonthCn
} = this.getLunar(e.date)
e.lunar = IDayCn == '初一' ? IMonthCn : IDayCn
}
return {
...e,
...custom
}
})
)
}
}
}
}

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

Loading…
Cancel
Save