Browse Source

首次提交

master
liutong 1 year ago
parent
commit
733264caa2
  1. 13
      .gitignore
  2. BIN
      69c4b45540483f32c0978e50a63ba275.keystore
  3. 392
      App.vue
  4. 9
      README.md
  5. 23
      androidPrivacy.json
  6. 4
      apis/http.js
  7. 18
      apis/request.js
  8. 3
      apis/shell.js
  9. 0
      apis/shop.js
  10. BIN
      ci/69c4b45540483f32c0978e50a63ba275.keystore
  11. 76
      ci/config.mjs
  12. 27
      ci/private.wxf53bc93b7fc90601.key
  13. BIN
      ci/shenbeitang(2).mobileprovision
  14. BIN
      ci/shenbeitang(2).p12
  15. BIN
      common/css/custom.ttf
  16. 124
      common/css/diy.scss
  17. 1288
      common/css/goods_detail.scss
  18. 69
      common/css/icon_extend/diy_default1.css
  19. 7350
      common/css/icondiy.css
  20. 427
      common/css/iconfont.css
  21. 603
      common/css/main.scss
  22. 1424
      common/css/order_parment.scss
  23. 94
      common/js/JPush.js
  24. 47
      common/js/auth.js
  25. 7
      common/js/bus.js
  26. 24
      common/js/config.js
  27. 412
      common/js/diy.js
  28. 3
      common/js/event.js
  29. 128
      common/js/golbalConfig.js
  30. 379
      common/js/goods_detail_base.js
  31. 188
      common/js/http.js
  32. 30
      common/js/jweixin-module/README.md
  33. 1
      common/js/jweixin-module/out/index.js
  34. 60
      common/js/jweixin-module/package.json
  35. 129
      common/js/lang.js
  36. 1123
      common/js/map-wx-jssdk.js
  37. 11
      common/js/map/message.js
  38. 107
      common/js/map/openMap.js
  39. 124
      common/js/map/transformCoordinate.js
  40. 10
      common/js/pc.js
  41. 51
      common/js/prompt-ui.js
  42. 28
      common/js/scroll-view.js
  43. 207
      common/js/socketTest.js
  44. 387
      common/js/style_color.js
  45. 8
      common/js/timesfm.js
  46. 1036
      common/js/util.js
  47. 166
      common/js/validate.js
  48. 115
      common/js/wx-jssdk.js
  49. 185
      components/ay-operate/del_slideLeft.vue
  50. 252
      components/ay-operate/iconfont.css
  51. 498
      components/bind-mobile/bind-mobile.vue
  52. 233
      components/cut_account.vue
  53. 1184
      components/directionGoodsItem.vue
  54. 1811
      components/diy-components/div-categoyr.vue
  55. 183
      components/diy-components/diy-article.vue
  56. 310
      components/diy-components/diy-bottom-nav.vue
  57. 1391
      components/diy-components/diy-category-item.vue
  58. 2086
      components/diy-components/diy-category.vue
  59. 30
      components/diy-components/diy-comp-extend.vue
  60. 1103
      components/diy-components/diy-coupon.vue
  61. 102
      components/diy-components/diy-float-btn.vue
  62. 127
      components/diy-components/diy-goods-brand.vue
  63. 1256
      components/diy-components/diy-goods-list.vue
  64. 563
      components/diy-components/diy-goods-recommend.vue
  65. 313
      components/diy-components/diy-graphic-nav.vue
  66. 262
      components/diy-components/diy-group.vue
  67. 416
      components/diy-components/diy-groupbuy.vue
  68. 36
      components/diy-components/diy-horz-blank.vue
  69. 21
      components/diy-components/diy-horz-line.vue
  70. 84
      components/diy-components/diy-icon.vue
  71. 356
      components/diy-components/diy-img-ads.vue
  72. 692
      components/diy-components/diy-index-page.vue
  73. 249
      components/diy-components/diy-many-goods-list.vue
  74. 1080
      components/diy-components/diy-member-info.vue
  75. 340
      components/diy-components/diy-member-my-order.vue
  76. 184
      components/diy-components/diy-notice.vue
  77. 536
      components/diy-components/diy-rubik-cube.vue
  78. 250
      components/diy-components/diy-search.vue
  79. 24
      components/diy-components/diy-text-extend.vue
  80. 116
      components/diy-components/diy-text-nav.vue
  81. 980
      components/diy-components/diy-text.vue
  82. 108
      components/diy-components/diy-video.vue
  83. 127
      components/egg.vue
  84. 1523
      components/goods-item/index.vue
  85. 39
      components/goodsPrice.vue
  86. 992
      components/horizontalGoodsItem.vue
  87. 56
      components/l-time/l-time.vue
  88. 161
      components/l-time/time.js
  89. 336
      components/load-refresh/load-refresh.vue
  90. 113
      components/loading-cover/loading-cover.vue
  91. 228
      components/ls-dom-video/ls-dom-video.vue
  92. 326
      components/mTikTok.vue
  93. 55
      components/mescroll/components/mescroll-down.css
  94. 52
      components/mescroll/components/mescroll-down.vue
  95. 90
      components/mescroll/components/mescroll-empty.vue
  96. 81
      components/mescroll/components/mescroll-top.vue
  97. 47
      components/mescroll/components/mescroll-up.css
  98. 39
      components/mescroll/components/mescroll-up.vue
  99. 15
      components/mescroll/mescroll-body.css
  100. 298
      components/mescroll/mescroll-body.vue

13
.gitignore

@ -0,0 +1,13 @@
/unpackage
/.hbuilderx
/.idea
node_modules/
dist/**
.project
unpackage/*
!unpackage/res/icons/*
.DS_Store
wxcomponents/**/*.vue
wxcomponents/**/*.css
.hbuilderx/
*.rar

BIN
69c4b45540483f32c0978e50a63ba275.keystore

Binary file not shown.

392
App.vue

@ -0,0 +1,392 @@
<script>
import auth from 'common/js/auth.js';
import { Weixin } from 'common/js/wx-jssdk.js';
// #ifdef APP-PLUS
import appUpdate from "@/config/appUpdate"
var jpushModule = uni.requireNativePlugin('JG-JPush');
// #endif
function getQueryParams(url) {
const paramArr = url.slice(url.indexOf("?") + 1).split("&");
const params = {};
paramArr.forEach((param) => {
const [key, val] = param.split("=");
params[key] = decodeURIComponent(val);
});
return params;
}
export default {
mixins: [auth],
// onLoad() {
// //
// if (!uni.getStorageSync('token')) {
// this.$util.redirectTo('/pages_tool/login/login');
// }
// },
onLaunch: function(e) {
// #ifdef MP-ALIPAY
console.log(e, 'onLaunchonLaunchonLaunch');
uni.removeStorageSync('schemeData')
if (e.path == "pages_tool/pay/index") {
uni.setStorageSync('schemeData', e.query);
}
// #endif
// #ifdef APP-PLUS
if (!this.$isIOS)
setTimeout(() => {
if (jpushModule) {
jpushModule.initJPushService();
jpushModule.setLoggerEnable(true);
var registerID;
jpushModule.getRegistrationID(result => {
registerID = result.registerID;
console.log(registerID, `registerID`);
if (registerID) {
this.$api.sendRequest({
url: '/api/jpush/setRegistrationId',
data: {
registration_id: registerID
},
success: res => {
console.log(res, `registerID_res`);
}
});
}
});
}
}, 30000);
// #endif
uni.hideTabBar();
uni.setStorageSync('DIY_VIEW_INDEX_popwindow_count', 1);
// #ifdef MP
const updateManager = uni.getUpdateManager();
updateManager.onCheckForUpdate(function(res) {
//
});
updateManager.onUpdateReady(function(res) {
uni.showModal({
title: '更新提示',
content: '新版本已经准备好,是否重启应用?',
success(res) {
if (res.confirm) {
// applyUpdate
updateManager.applyUpdate();
}
}
});
});
updateManager.onUpdateFailed(function(res) {
//
});
// #endif
// #ifdef H5
if (uni.getSystemInfoSync().platform == 'ios') {
uni.setStorageSync('initUrl', location.href);
}
// #endif
uni.onNetworkStatusChange(function(res) {
if (!res.isConnected) {
uni.showModal({
title: '网络失去链接',
content: '请检查网络链接',
showCancel: false
});
}
});
this.$store.dispatch('init');
// #ifdef APP-PLUS || H5 || MP-WEIXIN
const userType = uni.getStorageSync('user_type');
if (userType && Number(userType) === 2) {
//
if (!uni.getStorageSync('token')) {
this.getAuthInfo();
} else {
// /app
this.$api.sendRequest({
url: '/api/login/loginLog',
success(res) {}
})
this.$api.sendRequest({
url: '/api/member/info',
complete: () => {
if (!uni.getStorageSync('token')) this.getAuthInfo();
}
});
}
}
// #endif
// #ifdef APP-PLUS
// ios
setTimeout(() => {
if (jpushModule) {
jpushModule.addNotificationListener(result => {
let notificationEventType = result.notificationEventType
let extras = result.extras
if (notificationEventType === 'notificationOpened' && extras.schemes) {
this.checkArgs(extras.schemes);
}
})
}
}, 30000);
// #endif
},
onLoad() {
console.log('onLoad');
},
onShow(e) {
uni.removeStorageSync('schemeData')
if (e.path == "pages_tool/pay/index") {
uni.setStorageSync('schemeData', e.query);
}
console.log('onShow', e);
// #ifdef APP-PLUS
setTimeout(() => {
//
if (jpushModule)
jpushModule.setBadge(0)
//
plus.runtime.setBadgeNumber(0);
this.checkArgs(this.getArgs());
}, 0);
// #endif
},
onHide: function() {},
methods: {
getArgs() {
// console.log(plus.runtime.launcher, plus.runtime.arguments, 'plus.runtime.launcher')
// const urlSchemeArgs = uni.getStorageSync('urlSchemeArgs')
// if (urlSchemeArgs === plus.runtime.arguments) return
if (plus.runtime.launcher === 'default') return
// uni.setStorageSync('urlSchemeArgs', plus.runtime.arguments)
plus.runtime.launcher = 'default'
return plus.runtime.arguments
},
checkArgs(args) {
if (!args) return
const runtimeArguments = args.split('://')
if (runtimeArguments.length < 1) return
// const scheme = runtimeArguments[0]
const url = runtimeArguments[1]
let path = url.split('?')
if (path.length < 0) return
path = path[0]
const params = getQueryParams(decodeURIComponent(url))
if (path === 'target') {
// TODO
if (!uni.getStorageSync('token')) {
this.$util.showToast({
title: '您尚未登录,请先进行登录',
icon: 'none',
});
setTimeout(() => {
this.$util.redirectTo('/pages_tool/login/login');
}, 1000)
return
}
console.log(params, 'params')
//
this.$util.redirectTo(params.path, params);
}
},
/**
* 获取授权信息
*/
getAuthInfo() {
// #ifdef H5
if (this.$util.isWeiXin()) {
this.$util.getUrlCode(urlParams => {
if (urlParams.source_member)
uni.setStorageSync('source_member', urlParams.source_member);
if (urlParams.code == undefined) {
this.$api.sendRequest({
url: '/wechat/api/wechat/authcode',
data: {
redirect_url: location.href,
scopes: 'snsapi_userinfo'
},
success: res => {
if (res.code >= 0) {
location.href = res.data;
}
}
});
} else {
this.$api.sendRequest({
url: '/wechat/api/wechat/authcodetoopenid',
data: {
code: urlParams.code
},
success: res => {
if (res.code >= 0) {
let data = {};
if (res.data.openid) data.wx_openid = res.data.openid;
if (res.data.unionid) data.wx_unionid = res.data.unionid;
if (res.data.userinfo) Object.assign(data, res.data.userinfo);
this.authLogin(data);
}
}
});
}
});
}
// #endif
// #ifdef MP
this.getCode(data => {
this.authLogin(data, 'authOnlyLogin');
});
// #endif
},
/**
* 授权登录
*/
authLogin(data, type = 'authLogin') {
if (uni.getStorageSync('source_member'))
data.source_member = uni.getStorageSync('source_member');
uni.setStorage({
key: 'authInfo',
data: data
});
this.$api.sendRequest({
url: type == 'authLogin' ? '/api/login/auth' : '/api/login/authonlylogin',
data,
success: res => {
if (res.code >= 0) {
uni.setStorage({
key: 'token',
data: res.data.token,
success: () => {
this.$store.dispatch('getCartNumber');
this.$store.commit('setToken', res.data.token);
}
});
}
}
});
},
/**
* 公众号分享设置
*/
shareConfig() {
this.$api.sendRequest({
url: '/wechat/api/wechat/share',
data: {
url: window.location.href
},
success: res => {
if (res.code == 0) {
var wxJS = new Weixin();
wxJS.init(res.data.jssdk_config);
let share_data = JSON.parse(JSON.stringify(res.data.share_config.data));
if (share_data) {
wxJS.setShareData({
title: share_data.title,
desc: share_data.desc,
link: share_data.link,
imgUrl: this.$util.img(share_data.imgUrl)
},
res => {
console.log(res);
}
);
}
let hideOptionMenu = res.data.share_config.permission.hideOptionMenu;
let hideMenuItems = res.data.share_config.permission.hideMenuItems;
if (hideOptionMenu) {
wxJS.weixin.hideOptionMenu(); //
} else {
wxJS.weixin.showOptionMenu(); //
}
}
},
fail: err => {}
});
}
},
watch: {
$route: {
handler(newName, oldName) {
if (this.$util.isWeiXin()) {
this.shareConfig();
}
},
// wacthfirstNamehandler
immediate: true
}
}
};
</script>
<style lang="scss">
// @import 'uview-ui/index.scss';
@import "@/uni_modules/uview-ui/index.scss";
@import './common/css/iconfont.css';
@import './common/css/icondiy.css'; //
@import './common/css/main.scss';
// ********** **********
@import './common/css/icon_extend/diy_default1.css';
.df {
display: flex;
}
.aic {
align-items: center;
}
.jcsb {
justify-content: space-between;
}
.jcsa {
justify-content: space-around;
}
.jcc {
justify-content: center;
}
.f1 {
flex: 1;
}
.fn {
flex: none;
}
.fdc {
flex-direction: column;
}
.fw {
flex-wrap: wrap;
}
.jcf {
justify-content: flex-end;
}
</style>

9
README.md

@ -1,3 +1,6 @@
# H5_QiCaiYao
H5端齐采药项目,uniapp框架
## 暂时注释的功能
2024年10月25日需要打包一个apk到线上, 但是当前代码包含了一些不稳定的二期需求,所以对其进行注释,只保留支付功能的修改
1. tabbar-视频 value.list = value.list.filter(item => item.text !=='视频')
2. 首页 —— 常购清单 value.list 改为 value.list.slice(0, value.list.length - 1)
3. 顺手购 , 只注释了html (搜索"顺手买一件")

23
androidPrivacy.json

@ -0,0 +1,23 @@
{
"version": "3",
"prompt": "template",
"title": "用户协议和隐私政策",
"message": "  请你务必审慎阅读、充分理解“用户协议”和“隐私政策”各条款,包括但不限于:为了更好的向你提供服务,我们需要收集你的设备标识、操作日志等信息用于分析、优化应用性能。<br/>  你可阅读<a href=\"https://cbtadmin.jtyqt.com/h5/#/pages_tool/agreement/agreement?title=%E7%94%A8%E6%88%B7%E5%8D%8F%E8%AE%AE\">《用户协议》</a>和<a href=\"https://cbtadmin.jtyqt.com/h5/#/pages_tool/agreement/agreement?title=%E9%9A%90%E7%A7%81%E6%94%BF%E7%AD%96\">《隐私政策》</a>了解详细信息。如果你同意,请点击下面按钮开始接受我们的服务。",
"buttonAccept": "同意并接受",
"buttonRefuse": "不同意",
"hrefLoader": "system|default",
"backToExit": "false",
"disagreeMode": {
"support": false,
"loadNativePlugins": false,
"visitorEntry": false,
"showAlways": false
},
"styles": {
"backgroundColor": "#ffffff",
"borderRadius": "5px",
"buttonAccept": {
"color": "#56a4e1"
}
}
}

4
apis/http.js

@ -0,0 +1,4 @@
// 服务器基本路径设置
export const SERVERIP = ''

18
apis/request.js

@ -0,0 +1,18 @@
import {
SERVERIP
} from './http'
export const req = (url, data = {}, method = 'GET') => {
return new Promise((resolve, reject) => {
uni.request({
url: SERVERIP + url,
data: data,
method: method,
success(res) {
resolve(res)
},
fail(err) {
reject(err)
}
})
})
}

3
apis/shell.js

@ -0,0 +1,3 @@
import { req } from './request'
// export const $_login = (data) => req('/WeiXin/login',data,'post')

0
apis/shop.js

BIN
ci/69c4b45540483f32c0978e50a63ba275.keystore

Binary file not shown.

76
ci/config.mjs

@ -0,0 +1,76 @@
export default {
// 全局version,
"globalVersionName": "1.000.176",
"globalVersionCode": "10001202", // 全局配置
// app相关参数
"app-plus": {
//项目名字或项目绝对路径
project: "",
//打包平台 默认值android 值有"android","ios" 如果要打多个逗号隔开打包平台
platform: "android",
//是否使用自定义基座 默认值false true自定义基座 false自定义证书
iscustom: false,
//打包方式是否为安心打包默认值false,true安心打包,false传统打包
safemode: true,
//android打包参数
android: {
versionName: "",
versionCode: "",
//安卓包名
packagename: "com.shenbeitang.www",
// "packagename": "com.anguoyaochang.www",
//安卓打包类型 默认值0 0 使用自有证书 1 使用公共证书 2 使用老版证书
androidpacktype: "0",
//安卓使用自有证书自有打包证书参数
//安卓打包证书别名,自有证书打包填写的参数
certalias: "__uni__9009737",
//安卓打包证书文件路径,自有证书打包填写的参数
certfile: "ci/69c4b45540483f32c0978e50a63ba275.keystore",
//安卓打包证书密码,自有证书打包填写的参数
certpassword: "EFoe4kFv",
//安卓平台要打的渠道包 取值有"google","yyb","360","huawei","xiaomi","oppo","vivo",如果要打多个逗号隔开
channels: "",
},
//ios打包参数
ios: {
versionName: "1.000.165",
versionCode: "1000169",
//ios appid
bundle: "com.shenbeitang.www",
//ios打包支持的设备类型 默认值iPhone 值有"iPhone","iPad" 如果要打多个逗号隔开打包平台
supporteddevice: "iPhone",
//iOS使用自定义证书打包的profile文件路径
profile: "ci/shenbeitang.mobileprovision",
// "profile": "ci/test.mobileprovision",
//iOS使用自定义证书打包的p12文件路径
certfile: "ci/shenbeitang_Chuxueyun.p12",
//iOS使用自定义证书打包的证书密码
certpassword: "123456",
},
//是否混淆 true混淆 false关闭
isconfusion: true,
//开屏广告 true打开 false关闭
splashads: false,
//悬浮红包广告true打开 false关闭
rpads: false,
//push广告 true打开 false关闭
pushads: false,
//加入换量联盟 true加入 false不加入
exchange: false,
},
// 小程序相关参数
miniprogram: {
"mp-weixin": {
versionName: "",
versionCode: "",
appId: "wxf53bc93b7fc90601",
privateKeyPath: "./ci/private.wxf53bc93b7fc90601.key",
},
},
h5: {
domain: "cbtadmin.jtyqt.com",
path: "/",
distfilename: 'h5',
dist: '/www/wwwroot/cbtadmin.jtyqt.com/yaochang_php_v2/h5'
},
};

27
ci/private.wxf53bc93b7fc90601.key

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpgIBAAKCAQEAuhQjNsrTDVvy4ibKNrZLNNpG+IWsPHVGDQmD/o//ydv4TFFF
fz9aSIEFw6ZCZTJnqJwQGYHjVVnUbCEdF3CSgPwY/aFSzbsaiAB7XQmAUHoyUTLv
eGhhw2wMNH6SRNzjJXBD8nHR+1WnePsLEe6azmbFqEJCyFwbCqZoAPVyolsU+IAk
jZaDDdn6TpZox+dQK88Mv+jdhtdhOmuS1tbESRdboaBDdHIWhU54QlvMQEouDK2V
deM114tL1D1JJYqHT+5UBZgrJ6mRtv+albsxsXxWP3uuqjISEsc+x8qPnXRrSctB
VibdgXNLmWbwiFfQpPPCG+KAOhbWRQSr1hks7wIDAQABAoIBAQCFu8VXMsweVNAp
4xD/42IHuTy6jm+r/+j5o7YetWVzsUkxqFNXUbPUWg5Hf+1GB8TiNE+J1YUKKYZ2
tBHRb9GLLCPV3STCwU8fIaGHyzVSIZCaNQ5QrkxdBAF9lN4Q6ePCW34p982fYf77
/wkEuUS/RLOX6w9OKowwykoDLmRV8/6seg8vtdphhNGWp+D0DHTs2AR02pOpsq6U
fylZITLgiqys9KwKtzfOZMoxgZQii9+SoLmq0sLcOk7MhfjdA+h53VZguXAWdq28
O6d1W11rB7Fymrr9iXO7jX8qbPdWApaHNNYiKnYRWNDacwF++2x251koHmX1I421
fYMfMKzhAoGBAPHZSrtzylt0uR7bx+zKe8dMLeaFqy5XzFWD/+wMUwL48L1gQ/V0
RmU9sIneAZel/EuPvXjyzwwZkm4e4frU4mFvG9JK/ZU4L4ZMq5PhunkxQgzpEyZz
MMkl03R+mdP2RyE+sd4c4XHz0crY7sKLauhLRotCuoEmgnc12PfZ02LRAoGBAMT3
c74QX2ynpmGma+SqW7JkD+kBxRCsE4+jdAy1gqbZ0dWdNlywkP1V6z+IC8zeARBf
xXtoCWMM1b59bjDeG3fFQZ8HhHGpdQ3XAythG3Dm284WxHbMnCbm018ExE2x8Fpj
Tcv0BNrfBGIV3IzrAvz1Yhm2o+D9eN1uYzVuGgO/AoGBAKhRDSTW2k+6NZhXZ5XR
+kFjMFLOVqujKS+e9X8nuKJJ9Oon1ERAzzlorLPW0Y7kU2mXOUuy2QxXw8RmM+op
PQCInnlF/aRbfR/fvk3mfKwZ7xkjIVPSOXLUo4zhC1gsf6aQhqPJv9FZ2nltbwXw
l8/hi9Ah+cEmtwgWbtFYRTjxAoGBAI56bZgsIcroTxvOFbf4X5JgfX3QkOupfhDm
bPkQh60IXZiHO566/nazIxP25opQgTaGAMVvEXM8ApXkB8SDthzibMCL4IuTyB+1
zA4iFYaLCK9AmudQxRgC2x2dxh5pu/K2aL1DDAwDTRlitQKesa+oFUmCa3NCB58t
zcgFl/3jAoGBAKLqX2u3S9QhahdA4QKixYy3t4twsgeS5Z8X5k40j5sTip3VqvmH
UDWB6q5CA3NrhK2wa6A6cJjXug86cGcPAbGAXuzMae6F/K4czsQL/fdqHgEXFLsN
OkloythGbiXHpVfRZytdfYHa8WNC3oUI+rMSxEYqcKqcipDuyDMcbgTY
-----END RSA PRIVATE KEY-----

BIN
ci/shenbeitang(2).mobileprovision

Binary file not shown.

BIN
ci/shenbeitang(2).p12

Binary file not shown.

BIN
common/css/custom.ttf

Binary file not shown.

124
common/css/diy.scss

@ -0,0 +1,124 @@
.collectPopupWindow {
position: relative;
height: 113rpx;
width: 510rpx;
margin-left: calc(100% - 530rpx);
image {
width: 100%;
height: 100%;
}
text {
color: #ff4544 !important;
font-size: 24rpx !important;
position: absolute;
top: 48rpx;
right: 25rpx;
}
}
.zhezhao {
width: 100vw;
height: 100vh;
background-color: transparent;
}
image {
max-width: 100% !important;
max-height: 100% !important;
}
.diy-wrap {
/* #ifdef H5 */
height: calc(100vh - 88rpx);
/* #endif */
/* #ifdef MP-WEIXIN || MP-ALIPAY*/
height: 100vh;
/* #endif */
}
.page-img {
background-size: contain !important;
background-repeat: no-repeat !important;
}
.page-header {
background-size: contain !important;
background-repeat: no-repeat !important;
background-position: top center;
background-attachment: fixed;
}
.bg-index {
width: 100%;
height: 100%;
box-sizing: border-box;
background-size: contain !important;
background-repeat: no-repeat !important;
}
.wap-floating {
text {
display: block;
font-size: 60rpx;
color: #ffffff;
text-align: center;
}
}
.wap-floating-collect .uni-popup__mask {
background: transparent;
}
::-webkit-scrollbar {
width: 0;
height: 0;
color: transparent;
}
.popup-box {
width: 450rpx;
background: #ffffff;
border-radius: $border-radius;
overflow: hidden;
.close_title {
width: 100%;
text-align: center;
height: 70rpx;
line-height: 70rpx;
font-size: $font-size-base;
}
.close_content {
width: 100%;
max-height: 500rpx;
padding: $padding;
box-sizing: border-box;
}
.close_content_box {
width: 100%;
max-height: 460rpx;
line-height: 1.3;
}
}
.noStore-text {
color: #000000 !important;
}
.isStore-top {
margin-bottom: 10rpx;
}
.keep-on-record {
text-align: center;
padding-bottom: 20rpx;
image {
width: 150rpx;
height: 60rpx;
}
}
.padding-bottom{
padding-bottom: 40rpx !important;
}

1288
common/css/goods_detail.scss

File diff suppressed because it is too large

69
common/css/icon_extend/diy_default1.css

@ -0,0 +1,69 @@
@font-face {
font-family: "icondiy-my-template";
src: url('https://cdn3.codesign.qq.com/icons/r2nL6jg1z80pJXV/latest/iconfont.eot?t=20d1e70f3aeb7dcbee56c813164786bc'); /* IE9 */
src: url('https://cdn3.codesign.qq.com/icons/r2nL6jg1z80pJXV/latest/iconfont.eot?t=20d1e70f3aeb7dcbee56c813164786bc#iefix') format('embedded-opentype'), /* IE6-IE8 */
url('https://cdn3.codesign.qq.com/icons/r2nL6jg1z80pJXV/latest/iconfont.woff?t=20d1e70f3aeb7dcbee56c813164786bc') format('woff2'),
url('https://cdn3.codesign.qq.com/icons/r2nL6jg1z80pJXV/latest/iconfont.woff?t=20d1e70f3aeb7dcbee56c813164786bc') format('woff'), /* chrome、firefox */
url('https://cdn3.codesign.qq.com/icons/r2nL6jg1z80pJXV/latest/iconfont.ttf?t=20d1e70f3aeb7dcbee56c813164786bc') format('truetype'), /* chrome、firefox、opera、Safari, Android, iOS 4.2+*/
url('https://cdn3.codesign.qq.com/icons/r2nL6jg1z80pJXV/latest/iconfont.svg?t=20d1e70f3aeb7dcbee56c813164786bc#icondiy-my-template') format('svg'); /* iOS 4.1- */
}
.icondiy-my-template {
font-family: "icondiy-my-template" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-furniture-taideng:before {
content: "\e001";
}
.icon-furniture-deng:before {
content: "\e002";
}
.icon-furniture-szt:before {
content: "\e003";
}
.icon-furniture-safa:before {
content: "\e004";
}
.icon-furniture-bed:before {
content: "\e005";
}
.icon-furniture-yaoyi:before {
content: "\e006";
}
.icon-furniture-guizi:before {
content: "\e007";
}
.icon-furniture-lunyi:before {
content: "\e008";
}
.icon-furniture-fj:before {
content: "\e009";
}
.icon-furniture-xicaichi:before {
content: "\e00a";
}
.icon-building-glou:before {
content: "\e00b";
}
.icon-building-gaolou:before {
content: "\e00c";
}
.icon-building-glt:before {
content: "\e00d";
}
.icon-animal-hippo:before {
content: "\e00e";
}
.icon-animal-pig:before {
content: "\e00f";
}
.icon-animal-dolphin:before {
content: "\e010";
}
.icon-animal-duck:before {
content: "\e011";
}

7350
common/css/icondiy.css

File diff suppressed because it is too large

427
common/css/iconfont.css

@ -0,0 +1,427 @@
@font-face {
font-family: "iconfont";
src: url('https://cdn3.codesign.qq.com/icons/1Yyg5Zpxm6Z2lKv/latest/iconfont.eot?t=1a4474d1fa0fe7c3cdff9aa0cc9c7258'); /* IE9 */
src: url('https://cdn3.codesign.qq.com/icons/1Yyg5Zpxm6Z2lKv/latest/iconfont.eot?t=1a4474d1fa0fe7c3cdff9aa0cc9c7258#iefix') format('embedded-opentype'), /* IE6-IE8 */
url('https://cdn3.codesign.qq.com/icons/1Yyg5Zpxm6Z2lKv/latest/iconfont.woff?t=1a4474d1fa0fe7c3cdff9aa0cc9c7258') format('woff2'),
url('https://cdn3.codesign.qq.com/icons/1Yyg5Zpxm6Z2lKv/latest/iconfont.woff?t=1a4474d1fa0fe7c3cdff9aa0cc9c7258') format('woff'), /* chrome、firefox */
url('https://cdn3.codesign.qq.com/icons/1Yyg5Zpxm6Z2lKv/latest/iconfont.ttf?t=1a4474d1fa0fe7c3cdff9aa0cc9c7258') format('truetype'), /* chrome、firefox、opera、Safari, Android, iOS 4.2+*/
url('https://cdn3.codesign.qq.com/icons/1Yyg5Zpxm6Z2lKv/latest/iconfont.svg?t=1a4474d1fa0fe7c3cdff9aa0cc9c7258#iconfont') format('svg'); /* iOS 4.1- */
}
.iconfont {
font-family: "iconfont" !important;
font-size: 16px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.icon-futou:before {
content: "\e003";
}
.icon-chenggong:before {
content: "\e004";
}
.icon-dingdan4:before {
content: "\e005";
}
.icon-fuxuankuang1:before {
content: "\e006";
}
.icon-gantanhao:before {
content: "\e007";
}
.icon-fuxuankuang2:before {
content: "\e008";
}
.icon-kefu:before {
content: "\e009";
}
.icon-kanjia:before {
content: "\e00a";
}
.icon-kanjiachenggong:before {
content: "\e00b";
}
.icon-qrcode:before {
content: "\e00c";
}
.icon-gonggao:before {
content: "\e00d";
}
.icon-pintuan2:before {
content: "\e00e";
}
.icon-shangpin:before {
content: "\e00f";
}
.icon-right1:before {
content: "\e010";
}
.icon-sousuo3:before {
content: "\e011";
}
.icon-tutechan:before {
content: "\e012";
}
.icon-tuangou:before {
content: "\e013";
}
.icon-xiangshangzhanhang:before {
content: "\e014";
}
.icon-yaoqinghaoyou:before {
content: "\e015";
}
.icon-biaoqing_nanguo:before {
content: "\e016";
}
.icon-fenxiang4:before {
content: "\e017";
}
.icon-fold:before {
content: "\e018";
}
.icon-gantanhao1:before {
content: "\e019";
}
.icon-icon:before {
content: "\e01a";
}
.icon-huiyuan:before {
content: "\e01b";
}
.icon-jian:before {
content: "\e01c";
}
.icon-pintuanfanli:before {
content: "\e01d";
}
.icon-jia:before {
content: "\e01e";
}
.icon-seckill:before {
content: "\e01f";
}
.icon-wode-tuangou:before {
content: "\e020";
}
.icon-shuaxin:before {
content: "\e021";
}
.icon-wodeyushou:before {
content: "\e022";
}
.icon-youhuiquan1:before {
content: "\e023";
}
.icon-zhuantihuodong:before {
content: "\e024";
}
.icon-ziyuan1:before {
content: "\e025";
}
.icon-yonghu3:before {
content: "\e026";
}
.icon-caidan:before {
content: "\e027";
}
.icon-erweima:before {
content: "\e028";
}
.icon-danxuan-xuanzhong:before {
content: "\e029";
}
.icon-dingdan2:before {
content: "\e02a";
}
.icon-sanjiao:before {
content: "\e02b";
}
.icon-shangpin-:before {
content: "\e02c";
}
.icon-shouye1:before {
content: "\e02d";
}
.icon-shangsanjiao-copy:before {
content: "\e02e";
}
.icon-tedianquanchangbaoyou:before {
content: "\e02f";
}
.icon-wenhao:before {
content: "\e030";
}
.icon-weixin1:before {
content: "\e031";
}
.icon-yue:before {
content: "\e032";
}
.icon-zhekou:before {
content: "\e033";
}
.icon-fangkuai-fill:before {
content: "\e034";
}
.icon-zhibojieshu:before {
content: "\e035";
}
.icon-gouwuche2:before {
content: "\e036";
}
.icon-ellipsis:before {
content: "\e037";
}
.icon-guanzhu:before {
content: "\e038";
}
.icon-jifen-:before {
content: "\e039";
}
.icon-dianhua2:before {
content: "\e03a";
}
.icon-hongbao:before {
content: "\e03b";
}
.icon-qiandao1:before {
content: "\e03c";
}
.icon-jifen2:before {
content: "\e03d";
}
.icon-jifen3:before {
content: "\e03e";
}
.icon-fuzhilianjie:before {
content: "\e03f";
}
.icon-jiahao01:before {
content: "\e040";
}
.icon-like:before {
content: "\e041";
}
.icon-likefill:before {
content: "\e042";
}
.icon-list:before {
content: "\e043";
}
.icon-right:before {
content: "\e044";
}
.icon-round-close:before {
content: "\e045";
}
.icon-shangchuan:before {
content: "\e046";
}
.icon-tupian:before {
content: "\e047";
}
.icon-xuanzhuan:before {
content: "\e048";
}
.icon-add1:before {
content: "\e049";
}
.icon-weizhi:before {
content: "\e04a";
}
.icon-close-guanbi:before {
content: "\e04b";
}
.icon-apps:before {
content: "\e04c";
}
.icon-biaoqing:before {
content: "\e04d";
}
.icon-bianji:before {
content: "\e04e";
}
.icon-cart-on:before {
content: "\e04f";
}
.icon-close:before {
content: "\e050";
}
.icon-checkboxblank:before {
content: "\e051";
}
.icon-dianzan:before {
content: "\e052";
}
.icon-dingwei1:before {
content: "\e053";
}
.icon-iconangledown:before {
content: "\e055";
}
.icon-dizhi:before {
content: "\e056";
}
.icon-shouji:before {
content: "\e058";
}
.icon-icon7:before {
content: "\e059";
}
.icon-iconangledown-copy:before {
content: "\e05a";
}
.icon-youhuiquan:before {
content: "\e05c";
}
.icon-ziyuan:before {
content: "\e05d";
}
.icon-zhaoxiangji:before {
content: "\e05e";
}
.icon-yuan_checkbox:before {
content: "\e05f";
}
.icon-back_light:before {
content: "\e060";
}
.icon-yuan_checked:before {
content: "\e061";
}
.icon-bangzhu:before {
content: "\e062";
}
.icon-delete:before {
content: "\e064";
}
.icon-dianzan1:before {
content: "\e065";
}
.icon-dianpu:before {
content: "\e066";
}
.icon-mendian:before {
content: "\e067";
}
.icon-shaixuan:before {
content: "\e069";
}
.icon-shijian:before {
content: "\e06a";
}
.icon-shijian1:before {
content: "\e06b";
}
.icon-sousuo:before {
content: "\e06c";
}
.icon-shezhi:before {
content: "\e06d";
}
.icon-dianhua:before {
content: "\e06e";
}
.icon-dui:before {
content: "\e06f";
}
.icon-yaoqing:before {
content: "\e070";
}
.icon-zhongchaping:before {
content: "\e071";
}
.icon-fenxiang:before {
content: "\e072";
}
.icon-fuzhi:before {
content: "\e073";
}
.icon-hexiao:before {
content: "\e074";
}
.icon-share:before {
content: "\e075";
}
.icon-haoping1:before {
content: "\e076";
}
.icon-gouwuche:before {
content: "\e077";
}
.icon-share-friend:before {
content: "\e078";
}
.icon-jiang-copy:before {
content: "\e079";
}
.icon-location:before {
content: "\e07a";
}
.icon-jianshao:before {
content: "\e07b";
}
.icon-guanbi:before {
content: "\e07c";
}
.icon-gz:before {
content: "\e07d";
}
.icon-haowuquan:before {
content: "\e07e";
}
.icon-search:before {
content: "\e07f";
}
.icon-jilu:before {
content: "\e080";
}
.icon-pengyouquan:before {
content: "\e081";
}
.icon-saoma:before {
content: "\e083";
}
.icon-shouji1:before {
content: "\e084";
}
.icon-shurutianxiebi:before {
content: "\e085";
}
.icon-tiaoxingmasaomiao:before {
content: "\e087";
}
.icon-shuru:before {
content: "\e088";
}
.icon-unfold:before {
content: "\e089";
}
.icon-dianhua1:before {
content: "\e08a";
}
.icon-weixin:before {
content: "\e08b";
}
.icon-yonghu:before {
content: "\e08c";
}
.icon-bangzhu1:before {
content: "\e08d";
}
.icon-zhifubaozhifu-:before {
content: "\e08e";
}
.icon-add-fill:before {
content: "\e08f";
}
.icon-zhibozhong:before {
content: "\e090";
}
.icon-warn:before {
content: "\e091";
}

603
common/css/main.scss

File diff suppressed because one or more lines are too long

1424
common/css/order_parment.scss

File diff suppressed because it is too large

94
common/js/JPush.js

@ -0,0 +1,94 @@
var jpushModule = uni.requireNativePlugin("JG-JPush")
export default {
onLaunch: function() {
console.log('App Launch')
if (uni.getSystemInfoSync().platform == "ios") {
// 请求定位权限
let locationServicesEnabled = jpushModule.locationServicesEnabled()
let locationAuthorizationStatus = jpushModule.getLocationAuthorizationStatus()
console.log('locationAuthorizationStatus', locationAuthorizationStatus)
if (locationServicesEnabled == true && locationAuthorizationStatus < 3) {
jpushModule.requestLocationAuthorization((result) => {
console.log('定位权限', result.status)
})
}
jpushModule.requestNotificationAuthorization((result) => {
let status = result.status
if (status < 2) {
uni.showToast({
icon: 'none',
title: '您还没有打开通知权限',
duration: 3000
})
}
})
jpushModule.addGeofenceListener(result => {
let code = result.code
let type = result.type
let geofenceId = result.geofenceId
let userInfo = result.userInfo
uni.showToast({
icon: 'none',
title: '触发地理围栏',
duration: 3000
})
})
}
jpushModule.initJPushService();
jpushModule.setLoggerEnable(true);
jpushModule.addConnectEventListener(result => {
let connectEnable = result.connectEnable
uni.$emit('connectStatusChange', connectEnable)
});
jpushModule.addNotificationListener(result => {
let notificationEventType = result.notificationEventType
let messageID = result.messageID
let title = result.title
let content = result.content
let extras = result.extras
uni.showToast({
icon: 'none',
title: JSON.stringify(result),
duration: 3000
})
});
jpushModule.addCustomMessageListener(result => {
let type = result.type
let messageType = result.messageType
let content = result.content
uni.showToast({
icon: 'none',
title: JSON.stringify(result),
duration: 3000
})
})
jpushModule.addLocalNotificationListener(result => {
let messageID = result.messageID
let title = result.title
let content = result.content
let extras = result.extras
uni.showToast({
icon: 'none',
title: JSON.stringify(result),
duration: 3000
})
})
},
onShow: function() {
console.log('App Show')
},
onHide: function() {
console.log('App Hide')
}
}

47
common/js/auth.js

@ -0,0 +1,47 @@
export default {
data() {
return {
authInfo: {}
}
},
methods: {
/**
* 获取用户登录凭证code
*/
getCode(callback) {
// 微信小程序
// #ifdef MP-WEIXIN
uni.login({
provider: 'weixin',
timeout: 3000,
success: res => {
if (res.code) {
this.$api.sendRequest({
url: '/weapp/api/weapp/authcodetoopenid',
data: {
code: res.code
},
success: res => {
if (res.code >= 0) {
if (res.data.openid) this.authInfo.weapp_openid = res.data.openid;
if (res.data.unionid) this.authInfo.wx_unionid = res.data.unionid;
typeof callback == 'function' && callback(this.authInfo);
} else {
this.$util.showToast({
title: '小程序配置错误'
});
}
}
})
}
},
fail: () => {
this.$util.showToast({
title: '请求失败'
});
}
})
// #endif
}
}
}

7
common/js/bus.js

@ -0,0 +1,7 @@
import Vue from 'vue'
/**
* 定义空的vue实例作为 eventbus实现非父子组件之间的通信(vue2.x中去掉了broadcast)
*/
var eventBus = new Vue({});
export default eventBus;

24
common/js/config.js

@ -0,0 +1,24 @@
import Config from '@/config/index.js';
var config = {
// api请求地址
baseUrl: Config.baseUrl,
// 图片域名
imgDomain: Config.imgDomain,
// H5端域名
h5Domain: '{{$h5Domain}}',
// 腾讯地图key
mpKey: '{{$mpKey}}',
//客服地址
webSocket: '{{$webSocket}}',
//本地端主动给服务器ping的时间, 0 则不开启 , 单位秒
pingInterval: 1500,
};
export default config;

412
common/js/diy.js

@ -0,0 +1,412 @@
import WxMap from 'common/js/map-wx-jssdk.js';
let systemInfo = uni.getSystemInfoSync();
export default {
data() {
return {
diyData: {
global: {
title: '',
popWindow: {
imageUrl: '',
count: -1,
link: {},
imgWidth: '',
imgHeight: ''
}
}
},
memberId: 0,
name: '',
isDefault: '',
store: {}, //首页展示的门店详情
storeId: 0, //首页展示的门店id
pageHeight: '0',
headerHeight: '0',
bottomHeight: '0',
topIndexValue: null,
statusBarHeight: systemInfo.statusBarHeight,
collectTop: 44,
showTip: false,
mpCollect: false,
mpShareData: null, //小程序分享数据
scrollTop: 0, // 滚动位置
paddingTop: (44 + systemInfo.statusBarHeight) + 'px',
marginTop: -(44 + systemInfo.statusBarHeight) + 'px'
};
},
onLoad(data) {
this.name = data.name || '';
this.isDefault = data.is_default || '';
this.storeId = data.store_id || 0;
if (data.source_member) uni.setStorageSync('source_member', data.source_member);
// 小程序扫码进入
if (data.scene) {
var sceneParams = decodeURIComponent(data.scene);
sceneParams = sceneParams.split('&');
if (sceneParams.length) {
sceneParams.forEach(item => {
if (item.indexOf('m') != -1) uni.setStorageSync('source_member', item.split('-')[1]);
});
}
}
// 监听同步购物车
uni.$on('syncCartList', () => {
try {
this.$nextTick(() => {
if (this.$refs.diyGroup.$refs.ManyGoodsList[0].$refs.diyGoodsList) {
this.$refs.diyGroup.$refs.ManyGoodsList[0].$refs.diyGoodsList.syncCartList();
}
})
} catch (error) {
console.log(error, 'error');
}
})
},
mounted() {
this.init();
},
onShow() {
try {
this.$nextTick(() => {
this.$refs.diyGroup.$refs.ManyGoodsList[0].$refs.diyGoodsList.syncCartList();
})
} catch (error) {
console.log(error, 'error');
}
},
computed: {
bgColor() {
let str = '';
if (this.diyData && this.diyData.global) {
str = this.diyData.global.pageBgColor;
}
return str;
},
bgImg() {
let str = '';
if (this.diyData && this.diyData.global) {
str = this.diyData.global.topNavBg ? 'url(' + this.$util.img(this.diyData.global.bgUrl) + ')' : this
.diyData.global.pageBgColor;
}
return str;
},
bgUrl() {
let str = '';
if (this.diyData && this.diyData.global) {
str = this.diyData.global.topNavBg ? 'transparent' : this.diyData.global.bgUrl;
}
return str;
},
bgNav() {
if (this.diyData.global.topNavColor) {
return {
background: this.diyData.global.topNavColor
};
} else {
return {
background: '#ffffff'
};
}
},
backgroundUrl() {
var str = this.diyData.global.bgUrl && this.diyData.global.bgUrl != 'transparent' ? 'url(' + this.$util.img(
this.diyData.global.bgUrl) + ') ' : '';
return str;
},
textNavColor() {
if (this.diyData && this.diyData.global && this.diyData.global.textNavColor) {
return this.diyData.global.textNavColor;
} else {
return '#ffffff';
}
},
openBottomNav() {
let str = false;
if (this.diyData && this.diyData.global) {
str = this.diyData.global.openBottomNav;
}
return str;
},
globalS() {
return this.diyData.global;
},
//计算首页弹框的显示宽高
popWindowStyle() {
// 做大展示宽高
let max_width = 290;
let max_height = 410;
// 参照宽高
let refer_width = 290;
let refer_height = 290;
let scale = this.diyData.global.popWindow.imgHeight / this.diyData.global.popWindow.imgWidth;
let width, height;
if (scale < refer_height / refer_width) {
width = max_width;
height = width * scale;
} else {
height = max_height;
width = height / scale;
}
let obj = '';
if (this.diyData.global.popWindow && this.diyData.global.popWindow.count != -1 && this.diyData.global
.popWindow.imageUrl) {
obj += 'height:' + (height * 2) + 'rpx;';
obj += 'width:' + (width * 2) + 'rpx;';
}
return obj;
},
scrollHeight() {
if (this.pageHeight != undefined && this.headerHeight != undefined && this.bottomHeight != undefined) {
return 'calc(' + this.pageHeight * 2 + 'rpx - ' + this.headerHeight + ' - ' + this.bottomHeight + ')';
} else {
return '100vh';
}
},
scrollTopHeight() {
if (this.pageHeight != undefined && this.headerHeight != undefined && this.bottomHeight != undefined) {
return 'calc(' + this.pageHeight * 2 + 'rpx - ' + this.headerHeight + ' - ' + this.bottomHeight +
' - 80rpx)';
} else {
return '100vh';
}
}
},
methods: {
init() {
//首页
if (uni.getStorageSync('token')) {
this.$util.getMemberId().then(resolve => {
this.memberId = resolve;
});
}
this.store = uni.getStorageSync('store') ? uni.getStorageSync('store') : null;
if (this.store) this.storeId = this.store.store_id;
this.getDiyInfo();
// this.getHeight();
if (this.route == "pages/member/index") {
uni.$on('changeStore', data => {
if (data) {
this.getDiyInfo();
}
});
}
console.log(this.diyData.global.popWindow, 123);
//记录分享关系
if (uni.getStorageSync('token') && uni.getStorageSync('source_member')) {
this.$util.onSourceMember(uni.getStorageSync('source_member'));
}
//小程序分享
// #ifdef MP-WEIXIN
this.$util.getMpShare().then(res => {
this.mpShareData = res;
});
// #endif
},
// scroll(e) {
// this.scrollTop = e.detail.scrollTop;
// },
callback() {
if (this.$refs.indexPage) {
this.$refs.indexPage.initPageIndex();
}
},
//计算高度
getHeight() {
var self = this;
//获取页面可用区域的高度
uni.getSystemInfo({
success: res => {
this.pageHeight = res.screenHeight;
}
});
// #ifdef MP || APP-PLUS
this.$nextTick(() => {
const query = uni.createSelectorQuery().in(this);
query
.select('.page-header')
.boundingClientRect(data => {
if (data) {
this.headerHeight = data.height * 2 + 'rpx';
// 从状态栏高度开始算
this.paddingTop = data.height + 'px';
this.marginTop = -data.height + 'px';
}
})
.exec();
});
// #endif
this.$nextTick(() => {
const query = uni.createSelectorQuery().in(this);
query
.select('.page-bottom')
.boundingClientRect(data => {
this.bottomHeight = 110 + 'rpx';
})
.exec();
});
},
getDiyInfo() {
this.$api.sendRequest({
url: '/api/diyview/info',
data: {
name: this.name,
is_default: this.isDefault
},
success: res => {
// console.log(JSON.parse(res.data.value));
// console.log(JSON.parse(res.data.value),`diy`);
if (res.code != 0 || !res.data) {
if (this.$refs.loadingCover) this.$refs.loadingCover.hide();
this.diyData = {};
return;
}
let diyDatavalue = res.data;
// console.log(JSON.parse(diyDatavalue.value))
//处理后台组件input输入单引号问题 -- 英文状态下
// diyDatavalue.value = diyDatavalue.value.replace(/\@/g, "'");
if (diyDatavalue.value) {
// uni.setStorageSync(this.name, diyDatavalue.value);
this.diyData = JSON.parse(diyDatavalue.value);
console.log(this.diyData);
this.diyData.compExtend = diyDatavalue.comp_extend; // 自定义扩展组件
this.$langConfig.title(this.diyData.global.title);
this.mpCollect = this.diyData.global.mpCollect;
if (this.diyData.global.popWindow && this.diyData.global.popWindow.imageUrl) {
// 弹框形式,首次弹出 1,每次弹出 0
setTimeout(() => {
if (this.diyData.global.popWindow.count == 1) {
var popwindow_count = uni.getStorageSync(this.name +
'_popwindow_count');
if ((this.$refs.uniPopupWindow && popwindow_count == '') || (
this.$refs.uniPopupWindow && popwindow_count == 1)) {
this.$refs.uniPopupWindow.open();
uni.setStorageSync(this.name + '_popwindow_count', 1);
}
} else if (this.diyData.global.popWindow.count == 0) {
this.$refs.uniPopupWindow.open();
uni.setStorageSync(this.name + '_popwindow_count', 0);
}
}, 500);
}
for (var i = 0; i < this.diyData.value.length; i++) {
if (this.diyData.value[i].componentName == 'TopCategory') {
this.topIndexValue = this.diyData.value[i];
break;
}
}
// #ifdef MP
//小程序收藏
if (!uni.getStorageSync('isCollect') && this.diyData.global.mpCollect) {
this.$refs.collectPopupWindow.open();
this.showTip = true;
}
// #endif
if (this.diyData.value) {
this.diyData.value.forEach(item => {
if (item.componentName == "FloatBtn") {
this.floatData = item
// console.log('this.floatData', this.floatData);
uni.setStorageSync('floatData', this.floatData);
}
})
}
}
setTimeout(() => {
if (this.$refs.loadingCover) this.$refs.loadingCover.hide();
}, 150);
}
});
},
closePopupWindow() {
this.$refs.uniPopupWindow.close();
uni.setStorageSync(this.name + '_popwindow_count', -1);
},
closeCollectPopupWindow() {
this.$refs.collectPopupWindow.close();
uni.setStorageSync('isCollect', true);
},
uniPopupWindowFn() {
if (this.diyData.global.popWindow.adv_id > 0) {
this.advpoint(this.diyData.global.popWindow.adv_id)
}
this.$util.diyRedirectTo(this.diyData.global.popWindow.link);
this.closePopupWindow();
},
advpoint(adv_id) {
this.$api.sendRequest({
url: '/api/adv/advpoint',
data: {
adv_id,
},
success: res => {}
})
}
},
onPageScroll(e) {
if (this.$refs.topNav) {
if (e.scrollTop >= 20) {
this.$refs.topNav.navTopBg();
} else {
this.$refs.topNav.unSetnavTopBg();
}
}
e.scrollTop > 20 ? this.$store.state.navbarBgColor = '#fff' : this.$store.state.navbarBgColor = 'transparent'
},
//分享给好友
onShareAppMessage() {
return this.mpShareData.appMessage;
},
//分享到朋友圈
onShareTimeline() {
return this.mpShareData.timeLine;
},
onPullDownRefresh() {
if (this.route == "pages/member/index") {
console.log(`我的下拉刷新啦`);
this.memberView = false
this.$nextTick(() => {
this.memberView = true
uni.stopPullDownRefresh();
})
} else {
this.divTrue = true;
console.log(`首页下拉刷新啦`);
this.$nextTick(() => {
uni.stopPullDownRefresh();
this.getDiyInfo();
this.$refs.diyGroup.$refs.ManyGoodsList[0].$refs.diyGoodsList.getGoodsList();
})
this.$refs.uniPopupWindow.open();
}
},
onReachBottom() {
this.$refs.diyGroup.$refs.ManyGoodsList[0].$refs.diyGoodsList0 && this.$refs.diyGroup.$refs.ManyGoodsList[0]
.$refs.diyGoodsList0.nextGoodsList();
this.$refs.diyGroup.$refs.ManyGoodsList[0].$refs.diyGoodsList1 && this.$refs.diyGroup.$refs.ManyGoodsList[0]
.$refs.diyGoodsList1.nextGoodsList();
this.$refs.diyGroup.$refs.ManyGoodsList[0].$refs.diyGoodsList2 && this.$refs.diyGroup.$refs.ManyGoodsList[0]
.$refs.diyGoodsList2.nextGoodsList();
this.$refs.diyGroup.$refs.ManyGoodsList[0].$refs.diyGoodsList3 && this.$refs.diyGroup.$refs.ManyGoodsList[0]
.$refs.diyGoodsList3.nextGoodsList();
this.$refs.diyGroup.$refs.ManyGoodsList[0].$refs.diyGoodsList4 && this.$refs.diyGroup.$refs.ManyGoodsList[0]
.$refs.diyGoodsList4.nextGoodsList();
this.$refs.diyGroup.$refs.ManyGoodsList[0].$refs.diyGoodsList5 && this.$refs.diyGroup.$refs.ManyGoodsList[0]
.$refs.diyGoodsList5.nextGoodsList();
}
}

3
common/js/event.js

@ -0,0 +1,3 @@
import Vue from 'vue'
export const EventBus = new Vue()
export default EventBus;

128
common/js/golbalConfig.js

@ -0,0 +1,128 @@
export default {
data() {
return {
// 页面样式,动态设置主色调
themeColor: '' ,//''--base-color:#fa5d14;--base-help-color:#ff7e00;'
tabBarHeight: '0px'
}
},
onLoad() {
},
onShow() {
// 刷新多语言
this.$langConfig.refresh();
let time = setInterval(() => {
let theme = uni.getStorageSync('theme_style');
if (theme.main_color) {
this.themeColorSet()
clearInterval(time);
}
}, 50);
if (this.themeColor) this.getTabbarHeight();
if(uni.getStorageSync('token')){
this.$store.dispatch('getUserInfo')
}
},
computed: {
themeStyle() {
return uni.getStorageSync('theme_style');
},
//插件是否存在
addonIsExist() {
return uni.getStorageSync('addon_is_exist');
},
tabBarList() {
return this.$store.state.tabBarList
},
siteInfo() {
return uni.getStorageSync('siteInfo');
},
storeToken() {
return this.$store.state.token;
}
},
methods: {
themeColorSet(){
let theme = uni.getStorageSync('theme_style');
this.themeColor = `--base-color:${theme.main_color};--base-help-color:${theme.aux_color};--tab-bar-height:${this.tabBarHeight};`;
Object.keys(theme).forEach(key => {
let data = theme[key];
if(typeof(data) == "object"){
Object.keys(data).forEach(k => {
this.themeColor += '--'+k.replace(/_/g, "-")+':'+data[k]+';';
});
}else if(typeof(key) == "string" && key){
this.themeColor += '--'+key.replace(/_/g, "-")+':'+data+';';
}
});
for(let i = 9; i >= 5; i--) {
let color = this.$util.colourBlend(theme.main_color, '#ffffff', (i / 10));
this.themeColor += `--base-color-light-${i}:${color};`;
}
},
// 颜色变浅(>0)、变深函数(<0)
lightenDarkenColor(color, amount) {
var usePound = false;
if (color[0] == "#") {
color = color.slice(1);
usePound = true;
}
var num = parseInt(color, 16);
var r = (num >> 16) + amount;
if (r > 255) r = 255;
else if (r < 0) r = 0;
var b = ((num >> 8) & 0x00FF) + amount;
if (b > 255) b = 255;
else if (b < 0) b = 0;
var g = (num & 0x0000FF) + amount;
if (g > 255) g = 255;
else if (g < 0) g = 0;
return (usePound ? "#" : "") + (g | (b << 8) | (r << 16)).toString(16);
},
/**
* 获取tabbar高度
*/
getTabbarHeight(){
try {
const query = uni.createSelectorQuery().in(this);
query.select('#tab-bar').boundingClientRect(data => {
if (data) {
this.tabBarHeight = data.height + 'px'
this.themeColorSet();
}
}).exec();
} catch(e) {
}
}
},
filters: {
/**
* 金额格式化输出
* @param {Object} money
*/
moneyFormat(money) {
if (isNaN(parseFloat(money))) return money;
return parseFloat(money).toFixed(2);
}
},
onReady(){
let num = 0;
let timer = setInterval(() => {
this.getTabbarHeight()
num += 1;
if (this.tabBarHeight != '0px' || num == 10) clearInterval(timer)
}, 100)
}
}

379
common/js/goods_detail_base.js

@ -0,0 +1,379 @@
// 商品详情业务
// import htmlParser from '@/common/js/html-parser';
export default {
data() {
return {
skuId: 0,
goodsId: 0,
// 商品详情
goodsSkuDetail: {
goods_id: 0,
goods_service: []
},
preview: 0, //是否开启预览,0:不开启,1:开启
token: "",
//评价
contactData: {
title: '',
path: '',
img: ''
},
shareQuery: '', // 分享参数
shareUrl: '', // 分享链接
source_member: 0, //分享人的id
chatRoomParams: {}, // 联系客服参数
isIphoneX: false, //判断手机是否是iphoneX以上
// cartCount: 0, // 购物车商品数量
whetherCollection: 0,
memberId: 0,
posterParams: {}, //海报所需参数
shareImg: '',
deliveryType: null
}
},
onLoad(data) {
this.preview = data.preview || 0;
this.token = uni.getStorageSync('token');
this.isIphoneX = this.$util.uniappIsIPhoneX();
if (data.source_member) {
uni.setStorageSync('source_member', data.source_member);
this.source_member = data.source_member;
}
//记录分享关系
if (this.token && uni.getStorageSync('source_member')) {
this.$util.onSourceMember(uni.getStorageSync('source_member'));
}
// 小程序扫码进入
if (data.scene) {
var sceneParams = decodeURIComponent(data.scene);
sceneParams = sceneParams.split('&');
if (sceneParams.length) {
sceneParams.forEach(item => {
if (item.indexOf('m') != -1) uni.setStorageSync('source_member', item.split('-')[1]);
if (item.indexOf('is_test') != -1) uni.setStorageSync('is_test', 1);
});
}
}
},
computed: {
cartCount() {
return this.$store.state.cartNumber;
},
},
onShow() {
if (this.token) {
this.getCartCount();
this.$util.getMemberId().then(resolve => {
this.memberId = resolve;
});
}
},
watch: {
memberId: function() {
if (this.goodsSkuDetail.goods_id) this.setPublicShare();
}
},
methods: {
// 处理商品详情数据
handleGoodsSkuData() {
this.$langConfig.title(this.goodsSkuDetail.goods_name);
if (uni.getStorageSync('token')) {
this.getWhetherCollection();
this.modifyGoodsInfo();
}
// 初始化商品详情视图数据
this.$refs.goodsDetailView.init({
sku_id: this.skuId,
goods_id: this.goodsSkuDetail.goods_id,
preview: this.preview,
source_member: this.source_member,
posterParams: this.posterParams,
posterApi: this.posterApi,
shareUrl: this.shareUrl,
memberId: this.memberId,
goodsRoute: this.goodsRoute
});
//媒体
if (this.goodsSkuDetail.video_url) this.switchMedia = "video";
if (!Array.isArray(this.goodsSkuDetail.sku_images)) {
if (this.goodsSkuDetail.sku_images) this.goodsSkuDetail.sku_images = this.goodsSkuDetail.sku_images
.split(",");
else this.goodsSkuDetail.sku_images = [];
}
// 多规格时合并主图
if (this.goodsSkuDetail.goods_spec_format && this.goodsSkuDetail.goods_image) {
if (!Array.isArray(this.goodsSkuDetail.goods_image)) this.goodsSkuDetail.goods_image = this
.goodsSkuDetail.goods_image.split(",");
this.goodsSkuDetail.sku_images = this.goodsSkuDetail
.goods_image.concat(this.goodsSkuDetail.sku_images);
}
this.goodsSkuDetail.unit = this.goodsSkuDetail.unit || "件";
// 当前商品SKU规格
if (this.goodsSkuDetail.sku_spec_format) this.goodsSkuDetail.sku_spec_format = JSON.parse(this
.goodsSkuDetail.sku_spec_format);
// 商品属性
if (this.goodsSkuDetail.goods_attr_format) {
let goods_attr_format = JSON.parse(this.goodsSkuDetail.goods_attr_format);
this.goodsSkuDetail.goods_attr_format = this.$util.unique(goods_attr_format, "attr_id");
for (var i = 0; i < this.goodsSkuDetail.goods_attr_format.length; i++) {
for (var j = 0; j < goods_attr_format.length; j++) {
if (this.goodsSkuDetail.goods_attr_format[i].attr_id == goods_attr_format[j].attr_id &&
this.goodsSkuDetail.goods_attr_format[
i].attr_value_id != goods_attr_format[j].attr_value_id) {
this.goodsSkuDetail.goods_attr_format[i].attr_value_name += "、" + goods_attr_format[
j].attr_value_name;
}
}
}
}
// 商品SKU格式
if (this.goodsSkuDetail.goods_spec_format) this.goodsSkuDetail.goods_spec_format = JSON.parse(this
.goodsSkuDetail.goods_spec_format);
// 商品详情
// if (this.goodsSkuDetail.goods_content) this.goodsSkuDetail.goods_content = htmlParser(this
// .goodsSkuDetail.goods_content);
//商品服务
if (this.goodsSkuDetail.goods_service) {
for (let i in this.goodsSkuDetail.goods_service) {
this.goodsSkuDetail.goods_service[i]['icon'] = this.goodsSkuDetail.goods_service[i]['icon'] ? JSON
.parse(this.goodsSkuDetail.goods_service[i]['icon']) : '';
}
}
this.contactData = {
title: this.goodsSkuDetail.sku_name,
path: this.shareUrl,
img: this.$util.img(this.goodsSkuDetail.sku_image, {
size: 'big'
})
}
if (this.$refs.goodsPromotion) this.$refs.goodsPromotion.refresh(this.goodsSkuDetail
.goods_promotion);
if (this.goodsRoute != '/page_goods/detail/detail') this.setPublicShare();
this.getBarrageData();
if (this.goodsSkuDetail.is_virtual == 0) this.getEnabledExpressType();
},
/**
* 刷新商品详情数据
* @param {Object} goodsSkuDetail
*/
refreshGoodsSkuDetail(data) {
this.goodsSkuDetail = Object.assign({}, this.goodsSkuDetail, data);
if (this.$refs.goodsPromotion) this.$refs.goodsPromotion.refresh(this.goodsSkuDetail.goods_promotion);
if (this.$refs.goodsDetailView) {
// 初始化商品详情视图数据
this.goodsSkuDetail.unit = this.goodsSkuDetail.unit || "件";
// 解决轮播图数量不一致时,切换到第一个
if (this.swiperCurrent > this.goodsSkuDetail.sku_images.length) {
this.swiperAutoplay = true;
this.swiperCurrent = 1;
setTimeout(() => {
this.swiperAutoplay = false;
}, 40);
}
}
this.$langConfig.title(this.goodsSkuDetail.sku_name);
},
goodsDetailViewInit() {
// 初始化商品详情视图数据
this.$refs.goodsDetailView.init({
sku_id: this.skuId,
goods_id: this.goodsSkuDetail.goods_id,
preview: this.preview,
source_member: this.source_member,
posterParams: this.posterParams,
posterApi: this.posterApi,
shareUrl: this.shareUrl,
memberId: this.memberId,
goodsRoute: this.goodsRoute
});
},
goHome() {
if (this.preview) return; // 开启预览,禁止任何操作和跳转
this.$util.redirectTo('/pages/index/index');
},
goCart() {
if (this.preview) return; // 开启预览,禁止任何操作和跳转
// this.$util.redirectTo('/pages/goods/cart');
uni.navigateTo({
url: '/pages/goods/cartCopy'
})
},
//获取购物车数量
getCartCount() {
// console.log(1212);
this.$store.dispatch('getCartNumber');
},
//-------------------------------------关注-------------------------------------
//更新商品信息
modifyGoodsInfo() {
if (this.preview) return; // 开启预览,禁止任何操作和跳转
//更新商品点击量
this.$api.sendRequest({
url: "/api/goods/modifyclicks",
data: {
sku_id: this.skuId
},
success: res => {}
});
//添加足迹
this.$api.sendRequest({
url: "/api/goodsbrowse/add",
data: {
goods_id: this.goodsSkuDetail.goods_id,
sku_id: this.skuId
},
success: res => {}
});
},
//-------------------------------------关注-------------------------------------
//获取用户是否关注
getWhetherCollection() {
this.$api.sendRequest({
url: "/api/goodscollect/iscollect",
data: {
goods_id: this.goodsSkuDetail.goods_id
},
success: res => {
this.whetherCollection = res.data;
}
});
},
editCollection() {
if (this.$refs.goodsDetailView) {
this.whetherCollection = this.$refs.goodsDetailView.collection();
}
},
openSharePopup() {
if (this.$refs.goodsDetailView) {
this.$refs.goodsDetailView.openSharePopup();
}
},
getMemberId() {
this.$api.sendRequest({
url: "/api/member/id",
success: res => {
if (res.code >= 0) {
this.memberId = res.data;
}
}
});
},
//弹幕
getBarrageData() {
this.$api.sendRequest({
url: '/api/goods/goodsbarrage',
data: {
goods_id: this.goodsSkuDetail.goods_id
},
success: res => {
if (res.code == 0 && res.data) {
let barrageData = [];
for (let i in res.data.list) {
if (res.data.list[i]['title']) {
let title = res.data.list[i]['title'].substr(0, 1) + '*' + res.data.list[i][
'title'
].substr(res.data.list[i]['title'].length - 1, 1)
barrageData.push({
'img': res.data.list[i]['img'] ? res.data.list[i]['img'] : this
.$util.getDefaultImage().head,
'title': title + '已下单'
});
}
}
this.goodsSkuDetail.barrageData = barrageData;
}
}
});
},
/**
* 设置公众号分享
*/
setPublicShare() {
let shareUrl = this.$config.h5Domain + this.shareUrl;
if (this.memberId) shareUrl += '&source_member=' + this.memberId;
this.$util.setPublicShare({
title: this.goodsSkuDetail.goods_name,
desc: '',
link: shareUrl,
imgUrl: typeof this.goodsSkuDetail.goods_image == 'object' ? this.goodsSkuDetail.goods_image[
0] : this.goodsSkuDetail.goods_image.split(',')[0]
})
},
/**
* 查询启用的配送方式
*/
getEnabledExpressType() {
this.$api.sendRequest({
url: "/api/config/enabledexpresstype",
success: res => {
if (res.code == 0 && res.data) this.deliveryType = res.data;
}
});
}
},
/**
* 自定义分享内容
* @param {Object} res
*/
onShareAppMessage(res) {
var path = this.shareUrl;
if (this.memberId) path += '&source_member=' + this.memberId;
return {
title: this.goodsSkuDetail.sku_name,
imageUrl: this.shareImg ? this.$util.img(this.shareImg) : this.$util.img(this.goodsSkuDetail.sku_image, {
size: 'big'
}),
path: path,
success: res => {},
fail: res => {}
};
},
// 分享到微信朋友圈
// #ifdef MP-WEIXIN
onShareTimeline() {
let query = this.shareQuery;
if (this.memberId) query += '&source_member=' + this.memberId;
return {
title: this.goodsSkuDetail.sku_name,
query: query,
imageUrl: this.$util.img(this.goodsSkuDetail.sku_image, {
size: 'big'
})
};
}
// #endif
}

188
common/js/http.js

@ -0,0 +1,188 @@
import Config from './config.js'
import Util from './util.js'
import store from '@/store/index.js'
import { showLoading, hideLoading } from "./prompt-ui.js"
// #ifdef H5
const app_type = Util.isWeiXin() ? 'wechat' : 'h5';
const app_type_name = Util.isWeiXin() ? '微信公众号' : 'H5';
// #endif
// #ifdef MP-WEIXIN
const app_type = 'wechat';
const app_type_name = 'WECHAT';
// #endif
// #ifdef MP-ALIPAY
const app_type = 'aliapp';
const app_type_name = '支付宝小程序';
// #endif
// #ifdef MP-BAIDU
const app_type = 'baiduapp';
const app_type_name = '百度小程序';
// #endif
// #ifdef MP-TOUTIAO
const app_type = 'MP-TOUTIAO';
const app_type_name = '头条小程序';
// #endif
// #ifdef MP-QQ
const app_type = 'MP-QQ';
const app_type_name = 'QQ小程序';
// #endif
// #ifdef APP-PLUS
const app_type = 'weapp';
const app_type_name = 'WEAPP';
// #endif
const createLog = (url, req, res) => {
console.log(
`%c ${url}`,
'padding: 2px 4px; border-radius: 3px 0 0 3px; color: #fff; background: #b23ff7; font-weight: bold;',
req,
res
)
}
export default {
sendRequest(params) {
var method = params.data != undefined ? 'POST' : 'GET', // 请求方式
url = Config.baseUrl + params.url, // 请求路径
data = {
app_type,
app_type_name
};
// token
if (uni.getStorageSync('token')) data.token = uni.getStorageSync('token');
// 店铺id
if (uni.getStorageSync('myStore')) data.store_id = uni.getStorageSync('myStore').id;
// 参数
if (params.data != undefined) Object.assign(data, params.data);
showLoading();
if (params.async === false) {
//同步
return new Promise((resolve, reject) => {
uni.request({
url: url,
method: method,
data: data,
header: params.header || {
'Accept': 'application/json',
'content-type': 'application/x-www-form-urlencoded;application/json'
},
dataType: params.dataType || 'json',
responseType: params.responseType || 'text',
success: (res) => {
try {
res.data = JSON.parse(res.data);
createLog(params.url, data, res.data)
} catch (e) {
}
if (res.data.code == -3 && store.state.siteState > 0) {
store.commit('setSiteState', -3)
Util.redirectTo('/pages_tool/storeclose/storeclose', {}, 'reLaunch');
return;
}
if (res.data.refreshtoken) {
uni.setStorage({
key: 'token',
data: res.data.refreshtoken
});
}
if (res.data.code == -10009 || res.data.code == -10010) {
uni.removeStorage({
key: 'token'
})
}
resolve(res.data);
},
fail: (res) => {
reject(res);
},
complete: (res) => {
hideLoading();
reject(res);
}
});
});
} else {
//异步
uni.request({
url: url,
method: method,
data: data,
header: params.header || {
'Accept': 'application/json',
'content-type': 'application/x-www-form-urlencoded;application/json'
},
dataType: params.dataType || 'json',
responseType: params.responseType || 'text',
success: (res) => {
try {
res.data = JSON.parse(res.data);
createLog(params.url, data, res.data)
} catch (e) {
//TODO handle the exception
// console.log('api error:', e);
}
if (res.data.code != 0) {
console.log('-------', url)
}
if (res.data.code == -3 && store.state.siteState > 0) {
store.commit('setSiteState', -3)
Util.redirectTo('/pages_tool/storeclose/storeclose', {}, 'reLaunch');
return;
}
if (res.data.refreshtoken) {
uni.setStorage({
key: 'token',
data: res.data.refreshtoken
});
}
if (res.data.code == -10009 || res.data.code == -10010) {
uni.removeStorage({
key: 'token'
})
}
if (res.data.code == 8 || res.data.code == 1) {
return
}
if (res.data.code == -1 && res.data.message == "您尚未登录,请先进行登录") {
uni.showToast({
title: res.data.message || '您尚未登录,请先进行登录',
icon: "none",
})
setTimeout(() => {
Util.redirectTo('/pages_tool/login/login');
}, 1000)
}
if (res.data.code != 0 || res.data.code == -1) {
uni.showToast({
title: res.data.message || '系统错误',
icon: "none",
})
return
}
typeof params.success == 'function' && params.success(res.data);
},
fail: (res) => {
typeof params.fail == 'function' && params.fail(res);
},
complete: (res) => {
hideLoading();
typeof params.complete == 'function' && params.complete(res);
}
});
}
}
}

30
common/js/jweixin-module/README.md

@ -0,0 +1,30 @@
# jweixin-module
微信JS-SDK
## 安装
### NPM
```shell
npm install jweixin-module --save
```
### UMD
```http
https://unpkg.com/jweixin-module/out/index.js
```
## 使用
```js
var wx = require('jweixin-module')
wx.ready(function(){
// TODO
});
```
## 完整API
>[微信JS-SDK说明文档](https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115)

1
common/js/jweixin-module/out/index.js

File diff suppressed because one or more lines are too long

60
common/js/jweixin-module/package.json

@ -0,0 +1,60 @@
{
"_from": "jweixin-module",
"_id": "jweixin-module@1.4.1",
"_inBundle": false,
"_integrity": "sha512-2R2oa1lYhAsclfjKSf3DP4ZiP1dcrQUbM7aklbeJA+UAg/LS7MqoA6UbTy1cs4sbB34z62K4bKW0Z9iazD8ejg==",
"_location": "/jweixin-module",
"_phantomChildren": {},
"_requested": {
"type": "tag",
"registry": true,
"raw": "jweixin-module",
"name": "jweixin-module",
"escapedName": "jweixin-module",
"rawSpec": "",
"saveSpec": null,
"fetchSpec": "latest"
},
"_requiredBy": [
"#USER",
"/"
],
"_resolved": "https://registry.npmjs.org/jweixin-module/-/jweixin-module-1.4.1.tgz",
"_shasum": "1fc8fa42622243f6c35651d272cd587debf56cd1",
"_spec": "jweixin-module",
"_where": "E:\\demo\\niushop_uniapp",
"author": {
"name": "Shengqiang Guo"
},
"bugs": {
"url": "https://github.com/zhetengbiji/jweixin-module/issues"
},
"bundleDependencies": false,
"deprecated": false,
"description": "微信JS-SDK",
"devDependencies": {
"textfile": "^1.2.0",
"uglify-js": "^3.4.9"
},
"homepage": "https://github.com/zhetengbiji/jweixin-module#readme",
"keywords": [
"wxjssdk",
"weixin",
"jweixin",
"wechat",
"jssdk",
"wx"
],
"license": "ISC",
"main": "out/index.js",
"name": "jweixin-module",
"repository": {
"type": "git",
"url": "git+https://github.com/zhetengbiji/jweixin-module.git"
},
"scripts": {
"build": "node build",
"prepublish": "npm run build"
},
"version": "1.4.1"
}

129
common/js/lang.js

@ -0,0 +1,129 @@
const langList = ['zh-cn', 'en-us'];
var locale ="zh-cn"; //设置语言
// uni.getStorageSync('lang') ||
export default {
langList: ['zh-cn', 'en-us'],
/**
* * 解析多语言
* @param {Object} field
*/
lang(field) {
let _this = getCurrentPages()[getCurrentPages().length - 1];
if (!_this) return;
var value = '';
let newRoute;
try {
//公共语言包
var lang = require('../../lang/' + locale + '/common.js').lang;
//当前页面语言包
let route = _this.route.split("/");
newRoute = route.slice(1, route.length);
let currentPageLang = require('../../lang/' + locale + '/' + newRoute.join("/") + '.js').lang;
for (let f in currentPageLang) {
lang[f] = currentPageLang[f];
}
var arr = field.split(".");
if (arr.length > 1) {
for (let i in arr) {
var next = parseInt(i) + 1;
if (next < arr.length) {
value = lang[arr[i]][arr[next]];
}
}
} else {
value = lang[field];
}
} catch (e) {
if (field.indexOf("common.") != -1 || field.indexOf("tabBar.") != -1) {
value = lang[field];
} else {
value = field;
}
}
if (arguments.length > 1) {
//有参数,需要替换
for (var i = 1; i < arguments.length; i++) {
value = value.replace("{" + (i - 1) + "}", arguments[i]);
}
}
if (value == undefined || (value == 'title' && field == 'title')) value = ''; // field
return value;
},
//切换语言
change(value) {
let _this = getCurrentPages()[getCurrentPages().length - 1];
if (!_this) return;
uni.setStorageSync("lang", value);
locale ="zh-cn"; //设置语言
// uni.getStorageSync('lang') ||
this.refresh();
uni.reLaunch({
url: '/pages/member/index'
});
},
//刷新标题、tabbar
refresh() {
let _this = getCurrentPages()[getCurrentPages().length - 1];
if (!_this) return;
this.title(this.lang("title"));
//设置tabbar的文字语言
uni.setTabBarItem({
index: 0,
text: '首页'
});
uni.setTabBarItem({
index: 1,
text: '分类'
});
uni.setTabBarItem({
index: 2,
text: '购物车'
});
uni.setTabBarItem({
index: 3,
text: '我的'
});
},
title(str) {
if (str) {
uni.setNavigationBarTitle({
title: str,
success: function(res){
},
fail: function(err){
}
});
}
},
// 获取语言包列表
list() {
var list = [];
try {
//公共语言包
for (var i = 0; i < langList.length; i++) {
let item = require('../../lang/' + langList[i] + '/common.js').lang
list.push({
name: item.common.name,
value: langList[i]
});
}
} catch (e) {
// "没有找到语言包:", '../../lang/' + locale + '/common.js'
}
return list;
}
}

1123
common/js/map-wx-jssdk.js

File diff suppressed because it is too large

11
common/js/map/message.js

@ -0,0 +1,11 @@
function timesfm(num){
let now=new Date(num)
let n=now.getFullYear()
let y=now.getMonth()+1
let r =now.getDate();
let s=now.getHours()>=10?now.getHours():0+''+now.getHours();
let f=now.getMinutes()>=10?now.getMinutes():0+''+now.getMinutes();
let m=now.getSeconds()>=10?now.getSeconds():0+''+now.getSeconds();
return n+'-'+y+'-'+r+' '+s+':'+f+':'+m
}
module.exports = timesfm;

107
common/js/map/openMap.js

@ -0,0 +1,107 @@
import TransformCoordinate from './transformCoordinate.js'
function openMapByDefault(latitude, longitude, name) {
uni.openLocation({
latitude: latitude,
longitude: longitude,
name: name,
fail: (e) => {
uni.showModal({
content: '打开地图失败,请稍后重试'
})
},
})
}
function openMapByAndroid(latitude, longitude, name) {
let url = ''; // 回调地址
let identity = ''; // 程序名称
if (plus.runtime.isApplicationExist({
pname: 'com.baidu.BaiduMap'
})) { // baidumap
url =
`baidumap://map/marker?location=${latitude},${longitude}&title=${name}&coord_type=gcj02&src=andr.baidu.openAPIdemo`
identity = 'com.baidu.BaiduMap'
openURL(url, identity)
} else if (plus.runtime.isApplicationExist({
pname: 'com.autonavi.minimap'
})) { // 高德
url = `androidamap://viewMap?sourceApplication=appname&poiname=${name}&lat=${latitude}&lon=${longitude}&dev=0`
identity = 'com.autonavi.minimap'
openURL(url, identity)
} else {
openMapByDefault(latitude, longitude, name)
}
}
function openMapByIos(latitude, longitude, name) {
let url = ''; // 回调地址
let errorCB = ''; // url失败的回调地址
let identity = ''; // 程序名称
if (plus.runtime.isApplicationExist({
action: 'baidumap://'
})) { // baidumap
url =
`baidumap://map/marker?location=${latitude},${longitude}&title=${name}&content=${name}&src=ios.baidu.openAPIdemo&coord_type=gcj02`;
openURL(url, identity)
} else if (plus.runtime.isApplicationExist({
action: 'iosamap://'
})) { // 高德
url = `iosamap://viewMap?sourceApplication=applicationName&poiname=${name}&lat=${latitude}&lon=${longitude}&dev=0`
openURL(url, identity)
} else {
openMapByDefault(latitude, longitude, name)
}
}
function openURL(url, identity) {
let newurl = encodeURI(url);
plus.runtime.openURL(newurl, function(res) {
uni.showModal({
content: res.message
})
}, identity);
}
function getCoordByType(longitude, latitude, coord_type) {
switch (coord_type) {
case 'gcj02':
return [longitude, latitude]
break;
case 'bd09':
return TransformCoordinate.bd09togcj02(longitude, latitude)
break;
case 'wgs84':
return TransformCoordinate.wgs84togcj02(longitude, latitude)
break;
default:
return [longitude, latitude]
break;
}
}
export default {
/* 打开地图 */
openMap(latitude, longitude, name, coord_type = 'gcj02') {
let arr = getCoordByType(longitude, latitude, coord_type)
// #ifdef APP-PLUS
switch (uni.getSystemInfoSync().platform) {
case 'android':
console.log('运行Android上')
openMapByAndroid(arr[1], arr[0], name)
break;
case 'ios':
console.log('运行iOS上')
openMapByIos(arr[1], arr[0], name)
break;
default:
openMapByDefault(arr[1], arr[0], name)
console.log('运行在开发者工具上')
break;
}
// #endif
// #ifndef APP-PLUS
openMapByDefault(arr[1], arr[0], name)
// #endif
}
}

124
common/js/map/transformCoordinate.js

@ -0,0 +1,124 @@
/**
* Created by Wandergis on 2015/7/8.
* 提供了百度坐标BD09国测局坐标火星坐标GCJ02和WGS84坐标系之间的转换
*/
//定义一些常量
var x_PI = 3.14159265358979324 * 3000.0 / 180.0;
var PI = 3.1415926535897932384626;
var a = 6378245.0;
var ee = 0.00669342162296594323;
/**
* 百度坐标系 (BD-09) 火星坐标系 (GCJ-02)的转换
* 百度 谷歌高德
* @param bd_lon
* @param bd_lat
* @returns {*[]}
*/
function bd09togcj02(bd_lon, bd_lat) {
var x_pi = 3.14159265358979324 * 3000.0 / 180.0;
var x = bd_lon - 0.0065;
var y = bd_lat - 0.006;
var z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi);
var theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi);
var gg_lng = z * Math.cos(theta);
var gg_lat = z * Math.sin(theta);
return [gg_lng, gg_lat]
}
/**
* 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换
* 即谷歌高德 百度
* @param lng
* @param lat
* @returns {*[]}
*/
function gcj02tobd09(lng, lat) {
var z = Math.sqrt(lng * lng + lat * lat) + 0.00002 * Math.sin(lat * x_PI);
var theta = Math.atan2(lat, lng) + 0.000003 * Math.cos(lng * x_PI);
var bd_lng = z * Math.cos(theta) + 0.0065;
var bd_lat = z * Math.sin(theta) + 0.006;
return [bd_lng, bd_lat]
}
/**
* WGS84转GCj02
* @param lng
* @param lat
* @returns {*[]}
*/
function wgs84togcj02(lng, lat) {
if (out_of_china(lng, lat)) {
return [lng, lat]
} else {
var dlat = transformlat(lng - 105.0, lat - 35.0);
var dlng = transformlng(lng - 105.0, lat - 35.0);
var radlat = lat / 180.0 * PI;
var magic = Math.sin(radlat);
magic = 1 - ee * magic * magic;
var sqrtmagic = Math.sqrt(magic);
dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * PI);
dlng = (dlng * 180.0) / (a / sqrtmagic * Math.cos(radlat) * PI);
var mglat = lat + dlat;
var mglng = lng + dlng;
return [mglng, mglat]
}
}
/**
* GCJ02 转换为 WGS84
* @param lng
* @param lat
* @returns {*[]}
*/
function gcj02towgs84(lng, lat) {
if (out_of_china(lng, lat)) {
return [lng, lat]
} else {
var dlat = transformlat(lng - 105.0, lat - 35.0);
var dlng = transformlng(lng - 105.0, lat - 35.0);
var radlat = lat / 180.0 * PI;
var magic = Math.sin(radlat);
magic = 1 - ee * magic * magic;
var sqrtmagic = Math.sqrt(magic);
dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * PI);
dlng = (dlng * 180.0) / (a / sqrtmagic * Math.cos(radlat) * PI);
mglat = lat + dlat;
mglng = lng + dlng;
return [lng * 2 - mglng, lat * 2 - mglat]
}
}
function transformlat(lng, lat) {
var ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + 0.1 * lng * lat + 0.2 * Math.sqrt(Math.abs(lng));
ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0;
ret += (20.0 * Math.sin(lat * PI) + 40.0 * Math.sin(lat / 3.0 * PI)) * 2.0 / 3.0;
ret += (160.0 * Math.sin(lat / 12.0 * PI) + 320 * Math.sin(lat * PI / 30.0)) * 2.0 / 3.0;
return ret
}
function transformlng(lng, lat) {
var ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + 0.1 * lng * lat + 0.1 * Math.sqrt(Math.abs(lng));
ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0;
ret += (20.0 * Math.sin(lng * PI) + 40.0 * Math.sin(lng / 3.0 * PI)) * 2.0 / 3.0;
ret += (150.0 * Math.sin(lng / 12.0 * PI) + 300.0 * Math.sin(lng / 30.0 * PI)) * 2.0 / 3.0;
return ret
}
/**
* 判断是否在国内不在国内则不做偏移
* @param lng
* @param lat
* @returns {boolean}
*/
function out_of_china(lng, lat) {
return (lng < 72.004 || lng > 137.8347) || ((lat < 0.8293 || lat > 55.8271) || false);
}
export default {
bd09togcj02: bd09togcj02, // 百度坐标系 (BD-09) 与 火星坐标系 (GCJ-02)的转换
gcj02tobd09: gcj02tobd09, // 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换
wgs84togcj02: wgs84togcj02, //
gcj02towgs84: gcj02towgs84,
}

10
common/js/pc.js

@ -0,0 +1,10 @@
(function() {
var u = navigator.userAgent,
w = window.innerWidth;
if (w >= 960) {
window.innerWidth = 960;
window.onload = function() {
window.innerWidth = 960;
}
}
})();

51
common/js/prompt-ui.js

@ -0,0 +1,51 @@
let loadingCount = 0;
let timer = null; // 避免多次loading
let loadingTimer = null;
let custom = false;
// 开启loading
export const showLoading = () => {
return
// 设置加载动画区域
if (loadingCount === 0 && !timer) {
// TODO locale
if (custom) {
app.$emit("showLoading");
} else {
uni.showLoading({ title: '加载中...' })
}
// if (loadingTimer) clearTimeout(loadingTimer);
// // 3秒超时 关闭loading
// loadingTimer = setTimeout(() => {
// hideLoading()
// }, 3000)
}
if (timer) clearTimeout(timer);
loadingCount++;
};
// 隐藏loading
export const hideLoading = () => {
return
if (loadingCount <= 0) return;
loadingCount--;
if (loadingCount === 0) {
timer = setTimeout(() => {
// TODO locale
if (custom) {
app.$emit("hideLoading");
} else {
uni.hideLoading()
}
timer = null;
}, 500);
}
};
// 清空loading
export const clearLoading = () => {
loadingCount = 0;
uni.hideLoading()
};

28
common/js/scroll-view.js

@ -0,0 +1,28 @@
export default {
data() {
return {
showTop: false,
scrollTop: 0,
oldLocation: 0
}
},
methods: {
scrollToTopNative() {
uni.pageScrollTo({
duration: 200,
scrollTop: 0
});
}
},
onReachBottom() {
if(this.$refs.goodrecommend) this.$refs.goodrecommend.getLikeList(10)
},
onPageScroll(e) {
this.oldLocation = e.scrollTop;
if (e.scrollTop > 400) {
this.showTop = true;
} else {
this.showTop = false;
}
}
}

207
common/js/socketTest.js

@ -0,0 +1,207 @@
import config from './config.js'
export default {
data() {
return {
timeoutObj: null, //ping定时器
servicer_id: null, //绑定
pingInterval: config.pingInterval //本地端主动给服务器ping的时间, 0 则不开启
}
},
onLoad() {
let that = this;
// 因为图片上传,所以不能onhide关闭长链接,但是每次打开客服都会有重复请求,所以优先关闭再去打开长链接
uni.closeSocket();
// .判断是否已连接
that.checkOpenSocket();
// uni.onSocketClose(function(res) {
// console.log('WebSocket 已关闭!');
// });
},
methods: {
// 判断是否已连接
checkOpenSocket() {
console.log('判断是否已连接')
// alert('判断是否已连接')
let self = this;
uni.sendSocketMessage({
data: 'ping',
success: (res) => {
console.log('连接成功,检查')
// alert('连接成功,检查')
// self.getChatList();
return;
},
fail: (err) => { // 未连接打开websocket连接
console.log('连接失败')
// alert('连接失败')
self.openConnection();
}
});
},
openConnection() { // 打开连接
console.log('打开连接')
// alert('打开连接')
// uni.closeSocket(); // 确保已经关闭后再重新打开
uni.connectSocket({
url: config.webSocket,
method: 'POST',
success(res) {
console.log('连接成功 connectSocket=', res);
// alert('连接成功 connectSocket=', res);
},
fail(err) {
console.log('连接失败 connectSocket=', err);
}
});
// uni.onSocketOpen((res) => {
// console.log('连接成功', res);
// });
this.onSocketMessage(); // 打开成功监听服务器返回的消息
},
// 打开成功监听服务器返回的消息
onSocketMessage() { // 消息
console.log("开始监听");
let that = this;
this.pingInterval = config.pingInterval;
this.timeoutObj = null;
uni.onSocketMessage((res) => { //type:init,connect,close,string,order,goods
let msg = JSON.parse(res.data);
console.log("监听该服务器消息", res)
if (msg.type == 'close') {
clearInterval(that.timeoutObj);
that.timeoutObj = null;
uni.closeSocket();
return;
}
this.reset();
this.getSocketMsg(res.data); // 监听到有新服务器消息
});
},
// 监听到有新服务器消息
getSocketMsg(reData) { // 监听到服务器消息
let that = this;
// console.log(reData)
let giveMsg = JSON.parse(reData);
let data = {
isItMe: false,
};
data.contentType = giveMsg.type;
// alert(data.contentType)
if (giveMsg.type == 'init') {
// alert(123)
that.$api.sendRequest({
url: '/servicer/api/chat/bind',
data: {
client_id: giveMsg.data.client_id,
site_id: that.siteId
},
success(res) {
if (res.code == 0) {
that.servicer_id = res.data.servicer_id;
} else {
that.servicer_id = 0;
}
that.getChatList();
}
})
} else if (giveMsg.type == 'connect') {
// that.servicer_id = giveMsg.data.servicer_id;
// let NewArr = that.messageList;
// let index = null;
// for (let i = 0; i < NewArr.length; i++) {
// if (NewArr[i].contentType == 'online' || NewArr[i].contentType == 'noline') {
// index = i;
// }
// }
// NewArr.splice(index, 1)
// that.messageList = NewArr;
// let obj = {}
// if (that.servicer_id > 0) {
// obj.contentType = 'online';
// } else if (that.servicer_id == 0) {
// obj.contentType = 'noline';
// }
// that.messageList.push(obj);
return false;
} else if (giveMsg.type == 'string') {
data.content = giveMsg.data.servicer_say;
} else if (giveMsg.type == 'image') {
data.image = giveMsg.data.servicer_say;
} else if (giveMsg.type == 'order') {
data.order_id = giveMsg.data.order_id;
} else if (giveMsg.type == 'goodssku') {
data.sku_id = giveMsg.data.goods_sku_id;
}
if (giveMsg.type == 'init') return;
that.messageList.push(data);
that.$nextTick(() => {
that.setPageScrollTo()
})
},
// 检测心跳reset
reset() {
console.log("检测心跳")
clearInterval(this.timeoutObj);
this.start(); // 启动心跳
},
// 启动心跳 start
start() {
console.log("启动心跳")
let self = this;
this.timeoutObj = setInterval(function() {
uni.sendSocketMessage({
data: 'ping',
success: (res) => {
console.log('连接中....');
},
fail: (err) => {
console.log('连接失败重新连接....');
self.openConnection();
}
});
}, this.pingInterval);
}
},
// onHide() {
// // alert("关闭")
// // 改之前的
// // console.log("我出发了")
// // this.checkOpenSocket();
// clearInterval(this.timeoutObj);
// this.timeoutObj = null;
// this.$api.sendRequest({
// url: '/servicer/api/chat/bye',
// data: {
// servicer_id: this.servicer_id,
// site_id: this.siteId
// },
// success(res) {
// uni.closeSocket();
// },
// fail: (err) => {
// uni.closeSocket();
// }
// });
// },
onUnload() {
// alert("关闭")
clearInterval(this.timeoutObj);
this.timeoutObj = null;
this.$api.sendRequest({
url: '/servicer/api/chat/bye',
data: {
servicer_id: this.servicer_id,
site_id: this.siteId
},
success(res) {
// alert("关闭1")
uni.closeSocket();
},
fail: (err) => {
// alert("关闭2")
uni.closeSocket();
}
});
}
}

387
common/js/style_color.js

@ -0,0 +1,387 @@
export default {
'default':{
//红色
name:'default',
main_color : '#F4391c',
aux_color : '#F7B500',
bg_color: '#FF4646',//主题背景
bg_color_shallow: '#FF4646',//主题背景渐变浅色
promotion_color: '#FF4646',//活动背景
promotion_aux_color: '#F7B500',//活动背景辅色
main_color_shallow: '#FFF4F4',//淡背景
price_color: 'rgb(252,82,39)',//价格颜色
btn_text_color: '#FFFFFF',//按钮文字颜色
goods_detail : {
goods_price : 'rgb(252,82,39,1)',//价格
promotion_tag:'#FF4646',
goods_card_bg:'#201A18',//会员卡背景
goods_card_bg_shallow:'#7C7878',//会员卡背景浅色
goods_card_color:'#FFD792',
goods_coupon:'#FC5227',
goods_cart_num_corner :'#FC5227',//购物车数量角标
goods_btn_color:'#FF4646',//按钮颜色
goods_btn_color_shallow:'#F7B500',//副按钮颜色
},
pintuan:{
pintuan_label_bg:'#F7B500',
pintuan_label_color:'#FFFFFF',
pintuan_color:'#FA6400',
pintuan_promotion_color: '#FA3A1D',//活动背景
pintuan_promotion_aux_color: '#FD9A01',//活动背景辅色
},
super_member: {
super_member_start_bg: '#7c7878',
super_member_end_bg: '#201a18',
super_member_start_text_color: '#FFDBA6',
super_member_end_text_color: '#FFEBCA',
},
bargain:{
bargain_promotion_color: '#F0353E',//活动背景
bargain_promotion_aux_color: '#FD9A01',//活动辅色
},
seckill:{
seckill_promotion_color: '#F83530',//活动背景
seckill_promotion_aux_color: '#FD9A01',//活动辅色
},
giftcard:{
giftcard_promotion_color: '#FF3369',//活动背景
giftcard_promotion_aux_color: '#F7B500',//活动辅色
},
},
'green':{
name:'green',
main_color : '#19C650',
aux_color : '#FA6400',
bg_color: '#19C650',
bg_color_shallow: '#19C650',
promotion_color: '#19C650',
promotion_aux_color: '#FA6400',
main_color_shallow: '#F0FFF5',//淡背景
price_color: 'rgba(252,82,39,1)',//价格颜色
btn_text_color: '#FFFFFF',//按钮文字颜色
goods_detail : {
goods_price : 'rgba(252,82,39,1)',//价格
promotion_tag:'#19C650',
goods_card_bg:'#201A18',//会员卡背景
goods_card_bg_shallow:'#7C7878',//会员卡背景浅色
goods_card_color:'#FFD792',
goods_coupon:'#FC5227',
goods_cart_num_corner :'#FC5227',//购物车数量角标
goods_btn_color:'#19C650',//按钮颜色
goods_btn_color_shallow:'#FA6400',//副按钮颜色
},
pintuan:{
pintuan_label_bg:'#F7B500',
pintuan_label_color:'#FFFFFF',
pintuan_color:'#FA6400',
pintuan_promotion_color: '#FA3A1D',//活动背景
pintuan_promotion_aux_color: '#FD9A01',//活动背景辅色
},
super_member: {
super_member_start_bg: '#7c7878',
super_member_end_bg: '#201a18',
super_member_start_text_color: '#FFDBA6',
super_member_end_text_color: '#FFEBCA',
},
bargain:{
bargain_promotion_color: '#F0353E',//活动背景
bargain_promotion_aux_color: '#FD9A01',//活动辅色
},
seckill:{
seckill_promotion_color: '#F83530',//活动背景
seckill_promotion_aux_color: '#FD9A01',//活动辅色
},
giftcard:{
giftcard_promotion_color: '#FF3369',//活动背景
giftcard_promotion_aux_color: '#F7B500',//活动辅色
},
},
'blue':{
name:'blue',
main_color : '#21BBF3',
aux_color : '#FA6400',
bg_color: '#21BBF3',
bg_color_shallow: '#21BBF3',
promotion_color: '#21BBF3 ',
promotion_aux_color: '#FA6400',
main_color_shallow: '#E2F3FF',
price_color: 'rgba(252,82,39,1)',//价格颜色
btn_text_color: '#FFFFFF',//按钮文字颜色
goods_detail : {
goods_price : 'rgba(252,82,39,1)',//价格
promotion_tag:'#21BBF3',
goods_card_bg:'#201A18',//会员卡背景
goods_card_bg_shallow:'#7C7878',//会员卡背景浅色
goods_card_color:'#FFD792',
goods_coupon:'#FC5227',
goods_cart_num_corner :'#FC5227',//购物车数量角标
goods_btn_color:'#36ABFF',//按钮颜色
goods_btn_color_shallow:'#FA6400',//副按钮颜色
},
pintuan:{
pintuan_label_bg:'#F7B500',
pintuan_label_color:'#FFFFFF',
pintuan_color:'#FA6400',
pintuan_promotion_color: '#FA3A1D',//活动背景
pintuan_promotion_aux_color: '#FD9A01',//活动背景辅色
},
super_member: {
super_member_start_bg: '#7c7878',
super_member_end_bg: '#201a18',
super_member_start_text_color: '#FFDBA6',
super_member_end_text_color: '#FFEBCA',
},
bargain:{
bargain_promotion_color: '#F0353E',//活动背景
bargain_promotion_aux_color: '#FD9A01',//活动辅色
},
seckill:{
seckill_promotion_color: '#F83530',//活动背景
seckill_promotion_aux_color: '#FD9A01',//活动辅色
},
giftcard:{
giftcard_promotion_color: '#FF3369',//活动背景
giftcard_promotion_aux_color: '#F7B500',//活动辅色
},
},
'pink':{
name:'pink',
main_color : '#FF407E',
aux_color : '#F7B500',
bg_color: '#FF407E',//主题背景
bg_color_shallow: '#FF407E',//主题背景渐变浅色
promotion_color: '#FF407E',//活动背景
promotion_aux_color: '#F7B500',//活动背景辅色
main_color_shallow: '#FFF5F8',//淡背景
price_color: 'rgba(252,82,39,1)',//价格颜色
btn_text_color: '#FFFFFF',//按钮文字颜色
goods_detail : {
goods_price : 'rgba(252,82,39,1)',//价格
promotion_tag:'#FF407E',
goods_card_bg:'#201A18',//会员卡背景
goods_card_bg_shallow:'#7C7878',//会员卡背景浅色
goods_card_color:'#FFD792',
goods_coupon:'#FC5227',
goods_cart_num_corner :'#FC5227',//购物车数量角标
goods_btn_color:'#FF407E',//按钮颜色
goods_btn_color_shallow:'#F7B500',//副按钮颜色
},
pintuan:{
pintuan_label_bg:'#F7B500',
pintuan_label_color:'#FFFFFF',
pintuan_color:'#FA6400',
pintuan_promotion_color: '#FA3A1D',//活动背景
pintuan_promotion_aux_color: '#FD9A01',//活动背景辅色
},
super_member: {
super_member_start_bg: '#7c7878',
super_member_end_bg: '#201a18',
super_member_start_text_color: '#FFDBA6',
super_member_end_text_color: '#FFEBCA',
},
bargain:{
bargain_promotion_color: '#F0353E',//活动背景
bargain_promotion_aux_color: '#FD9A01',//活动辅色
},
seckill:{
seckill_promotion_color: '#F83530',//活动背景
seckill_promotion_aux_color: '#FD9A01',//活动辅色
},
giftcard:{
giftcard_promotion_color: '#FF3369',//活动背景
giftcard_promotion_aux_color: '#F7B500',//活动辅色
},
},
'gold':{
name:'gold',
main_color : '#CFAF70',
aux_color : '#444444',
bg_color: '#CFAF70',//主题背景
bg_color_shallow: '#CFAF70',//主题背景渐变浅色
promotion_color: '#CFAF70',//活动背景
promotion_aux_color: '#444444',//活动背景辅色
main_color_shallow: '#FFFAF1',//淡背景
price_color: 'rgba(252,82,39,1)',//价格颜色
btn_text_color: '#FFFFFF',//按钮文字颜色
goods_detail : {
goods_price : 'rgba(252,82,39,1)',//价格
promotion_tag:'#CFAF70',
goods_card_bg:'#201A18',//会员卡背景
goods_card_bg_shallow:'#7C7878',//会员卡背景浅色
goods_card_color:'#FFD792',
goods_coupon:'#FC5227',
goods_cart_num_corner :'#FC5227',//购物车数量角标
goods_btn_color:'#CFAF70',//按钮颜色
goods_btn_color_shallow:'#444444',//副按钮颜色
},
pintuan:{
pintuan_label_bg:'#F7B500',
pintuan_label_color:'#FFFFFF',
pintuan_color:'#FA6400',
pintuan_promotion_color: '#FA3A1D',//活动背景
pintuan_promotion_aux_color: '#FD9A01',//活动背景辅色
},
super_member: {
super_member_start_bg: '#7c7878',
super_member_end_bg: '#201a18',
super_member_start_text_color: '#FFDBA6',
super_member_end_text_color: '#FFEBCA',
},
bargain:{
bargain_promotion_color: '#F0353E',//活动背景
bargain_promotion_aux_color: '#FD9A01',//活动辅色
},
seckill:{
seckill_promotion_color: '#F83530',//活动背景
seckill_promotion_aux_color: '#FD9A01',//活动辅色
},
giftcard:{
giftcard_promotion_color: '#FF3369',//活动背景
giftcard_promotion_aux_color: '#F7B500',//活动辅色
},
},
'purple':{
name:'purple',
main_color : '#A253FF',
aux_color : '#222222',
bg_color: '#A253FF',//主题背景
bg_color_shallow: '#A253FF',//主题背景渐变浅色
promotion_color: '#A253FF',//活动背景
promotion_aux_color: '#222222',//活动背景辅色
main_color_shallow: '#F8F3FF',//淡背景
price_color: 'rgba(252,82,39,1)',//价格颜色
btn_text_color: '#FFFFFF',//按钮文字颜色
goods_detail : {
goods_price : 'rgba(252,82,39,1)',//价格
promotion_tag:'#A253FF',
goods_card_bg:'#201A18',//会员卡背景
goods_card_bg_shallow:'#7C7878',//会员卡背景浅色
goods_card_color:'#FFD792',
goods_coupon:'#FC5227',
goods_cart_num_corner :'#FC5227',//购物车数量角标
goods_btn_color:'#A253FF',//按钮颜色
goods_btn_color_shallow:'#222222',//副按钮颜色
},
pintuan:{
pintuan_label_bg:'#F7B500',
pintuan_label_color:'#FFFFFF',
pintuan_color:'#FA6400',
pintuan_promotion_color: '#FA3A1D',//活动背景
pintuan_promotion_aux_color: '#FD9A01',//活动背景辅色
},
super_member: {
super_member_start_bg: '#7c7878',
super_member_end_bg: '#201a18',
super_member_start_text_color: '#FFDBA6',
super_member_end_text_color: '#FFEBCA',
},
bargain:{
bargain_promotion_color: '#F0353E',//活动背景
bargain_promotion_aux_color: '#FD9A01',//活动辅色
},
seckill:{
seckill_promotion_color: '#F83530',//活动背景
seckill_promotion_aux_color: '#FD9A01',//活动辅色
},
giftcard:{
giftcard_promotion_color: '#FF3369',//活动背景
giftcard_promotion_aux_color: '#F7B500',//活动辅色
},
},
'yellow':{
name:'yellow',
main_color : '#FFD009',
aux_color : '#1D262E',
bg_color: '#FFD009',//主题背景
bg_color_shallow: '#FFD009',//主题背景渐变浅色
promotion_color: '#FFD009',//活动背景
promotion_aux_color: '#1D262E',//活动背景辅色
main_color_shallow: '#FFFBEF',//淡背景
price_color: 'rgba(252,82,39,1)',//价格颜色
btn_text_color: '#303133',//按钮文字颜色
goods_detail : {
goods_price : 'rgba(252,82,39,1)',//价格
promotion_tag:'#FFD009',
goods_card_bg:'#201A18',//会员卡背景
goods_card_bg_shallow:'#7C7878',//会员卡背景浅色
goods_card_color:'#FFD792',
goods_coupon:'#FC5227',
goods_cart_num_corner :'#FC5227',//购物车数量角标
goods_btn_color:'#FFD009',//按钮颜色
goods_btn_color_shallow:'#1D262E',//副按钮颜色
},
pintuan:{
pintuan_label_bg:'#F7B500',
pintuan_label_color:'#FFFFFF',
pintuan_color:'#FA6400',
pintuan_promotion_color: '#FA3A1D',//活动背景
pintuan_promotion_aux_color: '#FD9A01',//活动背景辅色
},
super_member: {
super_member_start_bg: '#7c7878',
super_member_end_bg: '#201a18',
super_member_start_text_color: '#FFDBA6',
super_member_end_text_color: '#FFEBCA',
},
bargain:{
bargain_promotion_color: '#F0353E',//活动背景
bargain_promotion_aux_color: '#FD9A01',//活动辅色
},
seckill:{
seckill_promotion_color: '#F83530',//活动背景
seckill_promotion_aux_color: '#FD9A01',//活动辅色
},
giftcard:{
giftcard_promotion_color: '#FF3369',//活动背景
giftcard_promotion_aux_color: '#F7B500',//活动辅色
},
},
'black':{
name:'black',
main_color : '#222222',
aux_color : '#FFFFFF',
bg_color: '#222222',//主题背景
bg_color_shallow: '#333333',//主题背景渐变浅色
promotion_color: '#222222',//活动背景
promotion_aux_color: '#FA8B00',//活动背景辅色
main_color_shallow: '#efefef',//淡背景
price_color: 'rgba(255,0,0,1)',//价格颜色
btn_text_color: '#FFFFFF',//按钮文字颜色
goods_detail : {
goods_price : 'rgba(255,0,0,1)',//价格
promotion_tag:'#222222',
goods_card_bg:'#201A18',//会员卡背景
goods_card_bg_shallow:'#7C7878',//会员卡背景浅色
goods_card_color:'#FFD792',
goods_coupon:'#222222',
goods_cart_num_corner :'#FF0000',//购物车数量角标
goods_btn_color:'#222222',//按钮颜色
goods_btn_color_shallow:'#FA8B00',//副按钮颜色
},
pintuan:{
pintuan_label_bg:'#F7B500',
pintuan_label_color:'#FFFFFF',
pintuan_color:'#FA6400',
pintuan_promotion_color: '#FA3A1D',//活动背景
pintuan_promotion_aux_color: '#FD9A01',//活动背景辅色
},
super_member: {
super_member_start_bg: '#fadcb5',
super_member_end_bg: '#f6bd74',
super_member_start_text_color: '#ab6126',
super_member_end_text_color: '#d19336',
},
bargain:{
bargain_promotion_color: '#F0353E',//活动背景
bargain_promotion_aux_color: '#FD9A01',//活动辅色
},
seckill:{
seckill_promotion_color: '#F83530',//活动背景
seckill_promotion_aux_color: '#FD9A01',//活动辅色
},
giftcard:{
giftcard_promotion_color: '#FF3369',//活动背景
giftcard_promotion_aux_color: '#F7B500',//活动辅色
},
}
}

8
common/js/timesfm.js

@ -0,0 +1,8 @@
function times(num){
let now=new Date(num)
let n=now.getFullYear()
let y=now.getMonth()+1>=10?now.getMonth()+1:0+''+(now.getMonth()+1);
var r =now.getDate()>=10?now.getDate():0+''+now.getDate();
return n+'-'+y+'-'+r
}
module.exports = times;

1036
common/js/util.js

File diff suppressed because it is too large

166
common/js/validate.js

@ -0,0 +1,166 @@
/**
数据验证表单验证
*/
module.exports = {
error: '',
check: function(data, rule) {
for (var i = 0; i < rule.length; i++) {
if (!rule[i].checkType) {
return true;
}
if (!rule[i].name) {
return true;
}
if (!rule[i].errorMsg) {
return true;
}
if (!data[rule[i].name]) {
this.error = rule[i].errorMsg;
return false;
}
switch (rule[i].checkType) {
case 'custom':
if (typeof rule[i].validate == 'function') {
if (!rule[i].validate(data[rule[i].name])) {
this.error = rule[i].errorMsg;
return false;
}
}
break;
case 'required':
var reg = new RegExp('/[\S]+/');
if (reg.test(data[rule[i].name])) {
this.error = rule[i].errorMsg;
return false;
}
break;
case 'string':
var reg = new RegExp('^.{' + rule[i].checkRule + '}$');
if (!reg.test(data[rule[i].name])) {
this.error = rule[i].errorMsg;
return false;
}
break;
case 'int':
var reg = new RegExp('^(-[1-9]|[1-9])[0-9]{' + rule[i].checkRule + '}$');
if (!reg.test(data[rule[i].name])) {
this.error = rule[i].errorMsg;
return false;
}
break;
break;
case 'between':
if (!this.isNumber(data[rule[i].name])) {
this.error = rule[i].errorMsg;
return false;
}
var minMax = rule[i].checkRule.split(',');
minMax[0] = Number(minMax[0]);
minMax[1] = Number(minMax[1]);
if (data[rule[i].name] > minMax[1] || data[rule[i].name] < minMax[0]) {
this.error = rule[i].errorMsg;
return false;
}
break;
case 'betweenD':
var reg = /^-?[1-9][0-9]?$/;
if (!reg.test(data[rule[i].name])) {
this.error = rule[i].errorMsg;
return false;
}
var minMax = rule[i].checkRule.split(',');
minMax[0] = Number(minMax[0]);
minMax[1] = Number(minMax[1]);
if (data[rule[i].name] > minMax[1] || data[rule[i].name] < minMax[0]) {
this.error = rule[i].errorMsg;
return false;
}
break;
case 'betweenF':
var reg = /^-?[0-9][0-9]?.+[0-9]+$/;
if (!reg.test(data[rule[i].name])) {
this.error = rule[i].errorMsg;
return false;
}
var minMax = rule[i].checkRule.split(',');
minMax[0] = Number(minMax[0]);
minMax[1] = Number(minMax[1]);
if (data[rule[i].name] > minMax[1] || data[rule[i].name] < minMax[0]) {
this.error = rule[i].errorMsg;
return false;
}
break;
case 'same':
if (data[rule[i].name] != rule[i].checkRule) {
this.error = rule[i].errorMsg;
return false;
}
break;
case 'notsame':
if (data[rule[i].name] == rule[i].checkRule) {
this.error = rule[i].errorMsg;
return false;
}
break;
case 'email':
var reg = /^[a-z0-9]+([._\\-]*[a-z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+$/;
if (!reg.test(data[rule[i].name])) {
this.error = rule[i].errorMsg;
return false;
}
break;
case 'phoneno':
var reg = /^[1](([3][0-9])|([4][5-9])|([5][0-3,5-9])|([6][5,6])|([7][0-8])|([8][0-9])|([9][0-9]))[0-9]{8}$/;
if (!reg.test(data[rule[i].name])) {
this.error = rule[i].errorMsg;
return false;
}
break;
case 'zipcode':
var reg = /^[0-9]{6}$/;
if (!reg.test(data[rule[i].name])) {
this.error = rule[i].errorMsg;
return false;
}
break;
case 'reg':
var reg = new RegExp(rule[i].checkRule);
if (!reg.test(data[rule[i].name])) {
this.error = rule[i].errorMsg;
return false;
}
break;
case 'in':
if (rule[i].checkRule.indexOf(data[rule[i].name]) == -1) {
this.error = rule[i].errorMsg;
return false;
}
break;
case 'notnull':
if (data[rule[i].name] == 0 || data[rule[i].name] == undefined || data[rule[i].name] == null || data[rule[i].name]
.length < 1) {
this.error = rule[i].errorMsg;
return false;
}
break;
case 'lengthMin':
if (data[rule[i].name].length < rule[i].checkRule) {
this.error = rule[i].errorMsg;
return false;
}
break;
case 'lengthMax':
if (data[rule[i].name].length > rule[i].checkRule) {
this.error = rule[i].errorMsg;
return false;
}
break;
}
}
return true;
},
isNumber: function(checkVal) {
var reg = /^-?[1-9][0-9]?.?[0-9]*$/;
return reg.test(checkVal);
}
}

115
common/js/wx-jssdk.js

@ -0,0 +1,115 @@
/**
* 微信jssdk调用
*/
let Weixin = function() {
var wx = require('./jweixin-module');
this.weixin = wx;
this.init = function(params) {
wx.config({
debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: params.appId, // 必填,公众号的唯一标识
timestamp: params.timestamp, // 必填,生成签名的时间戳
nonceStr: params.nonceStr, // 必填,生成签名的随机串
signature: params.signature, // 必填,签名
jsApiList: ['chooseWXPay', 'openAddress', 'updateAppMessageShareData', 'updateTimelineShareData', 'scanQRCode','hideMenuItems'] // 必填,需要使用的JS接口列表
});
}
/**
* 发起支付
* @param {Object} jsApiParame
* @param {Object} callback
*/
this.pay = function(jsApiParame, callback, cancel) {
wx.ready(function() {
wx.chooseWXPay({
timestamp: jsApiParame.timestamp, // 支付签名时间戳,注意微信jssdk中的所有使用timestamp字段均为小写。但最新版的支付后台生成签名使用的timeStamp字段名需大写其中的S字符
nonceStr: jsApiParame.nonceStr, // 支付签名随机串,不长于 32 位
package: jsApiParame.package, // 统一支付接口返回的prepay_id参数值,提交格式如:prepay_id=\*\*\*)
signType: jsApiParame.signType, // 签名方式,默认为'SHA1',使用新版支付需传入'MD5'
paySign: jsApiParame.paySign, // 支付签名
success: function(res) {
typeof callback == 'function' && callback(res);
},
cancel: function(res){
typeof cancel == 'function' && cancel(res);
}
});
})
}
/**
* 获取收货地址
* @param {Object} callback
*/
this.openAddress = function(callback) {
wx.ready(function() {
wx.openAddress({
success: function(res) {
typeof callback == 'function' && callback(res);
},
fail: (res) => {
alert(JSON.stringify(res))
}
});
})
}
/**
* 分享给好友
* @param {Object} params
* @param {Object} callback
*/
this.setShareData = function(params, callback) {
wx.ready(function() {
// 自定义“分享给朋友”及“分享到QQ”按钮的分享内容
wx.updateAppMessageShareData({
title: params.title || '', // 分享标题
desc: params.desc || '', // 分享描述
link: params.link || '', // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
imgUrl: params.imgUrl || '', // 分享图标
success: function(res) {
typeof callback == 'function' && callback(res);
},
fail:function(err){
}
})
// 自定义“分享到朋友圈”及“分享到QQ空间”按钮的分享内容
wx.updateTimelineShareData({
title: params.title || '', // 分享标题
link: params.link || '', // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
imgUrl: params.imgUrl || '', // 分享图标
success: function(res) {
typeof callback == 'function' && callback(res);
}
})
});
}
/**
* 扫一扫
* @param {Object} callback
*/
this.scanQRCode = function(callback) {
wx.ready(function() {
wx.scanQRCode({
needResult: 1,
scanType: ["qrCode"],
success: function(res) {
typeof callback == 'function' && callback(res);
}
});
})
}
}
export {
Weixin
}

185
components/ay-operate/del_slideLeft.vue

@ -0,0 +1,185 @@
<template>
<view>
<view class="box-slideLeft" >
<view class="touch-item touch-slideLeft " @touchstart="touchS" @touchmove="touchM" @touchend="touchE" :style="item_show.txtStyle">
<slot />
</view>
<view class="touch-item del-box-touch-slideLeft cf-shuCenter" @click="delItem(item_show)">
<view class="iconfont icon-shanchu"></view>
</view>
</view>
</view>
</template>
<script>
export default {
components: {
},
props: {
data_transit: {
type: Object,
default () {
return {}
}
},
//
item: {
type: Object,
default () {
return {}
}
},
},
computed: {
},
data() {
return {
item_show : {},
delBtnWidth: 60, //rpx
startX: '',
};
},
created:function(){
// true false
let that = this ;
let item = that.item ;
if(!item.hasOwnProperty("txtStyle")){
this.$set(this.item,'txtStyle','');//
}
this.item_show = this.item ;
},
watch: {
item(e){
this.item_show = e ;
},
},
methods: {
//
delItem: function(e) {
let that = this;
let data ={
item : e ,
data : that.data_transit ,
};
this.$emit('delItem', data);
},
touchS: function(e) {
let that = this;
if (e.touches.length == 1) {
//
this.startX = e.touches[0].clientX
}
},
touchM: function(e) {
let that = this;
if (e.touches.length == 1) {
//
var moveX = e.touches[0].clientX;
//
var disX = this.startX - moveX;
var delBtnWidth = this.delBtnWidth;
var txtStyle = "";
if (disX == 0 || disX < 0) { //0
txtStyle = "left:0px";
} else if (disX > 0) { //0left
txtStyle = "left:-" + disX + "px";
if (disX >= delBtnWidth) {
//
txtStyle = "left:-" + delBtnWidth + "px";
}
}
//
that.item_show.txtStyle = txtStyle;
}
},
touchE: function(e) {
let that = this;
if (e.changedTouches.length == 1) {
//
var endX = e.changedTouches[0].clientX;
//
var disX = this.startX - endX;
var delBtnWidth = this.delBtnWidth;
//1/2
var txtStyle = disX > delBtnWidth / 2 ? "left:-" + delBtnWidth + "px" : "left:0px";
//
that.item_show.txtStyle = txtStyle;
}
},
}
}
</script>
<style lang="scss">
@import './iconfont.css';//便
.box-slideLeft {
view {
box-sizing: border-box;
}
position: relative;
overflow: hidden;
.touch-item {
position: absolute;
top: 0;
padding: 10px 10px 10px;
background-color: #FFFFFF;
// border-radius: 10px;
overflow: hidden;
}
.touch-slideLeft {
position: relative;
width: 100%;
z-index: 5;
transition: left 0.2s ease-in-out;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.del-box-touch-slideLeft {
right: 0;
float: left;
width: 70px;
height: 100%;
line-height: 101px;
background-color: #EA5863;
border-radius: 0 10px 10px 0;
color: #fff;
font-size: 18px;
font-weight: lighter;
text-align: center;
}
.icon-shanchu{
font-size: 44upx;
}
.cf-shuCenter{
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
}
</style>

252
components/ay-operate/iconfont.css

File diff suppressed because one or more lines are too long

498
components/bind-mobile/bind-mobile.vue

@ -0,0 +1,498 @@
<template>
<view>
<view @touchmove.prevent.stop>
<uni-popup ref="bindMobile" :custom="true" :mask-click="true">
<view class="bind-wrap">
<!-- #ifdef H5 -->
<view class="head">检测到您还未绑定手机号码</view>
<view class="form-wrap">
<view class="label">手机号码</view>
<view class="form-item">
<view class="input-wrap">
<input
type="number"
placeholder="请输入您的手机号码"
placeholder-class="placeholder"
v-model="formData.mobile"
/>
</view>
</view>
<block v-if="captchaConfig">
<view class="label">验证码</view>
<view class="form-item">
<view class="input-wrap">
<input
type="number"
placeholder="请输入验证码"
placeholder-class="placeholder"
v-model="formData.vercode"
/>
</view>
<image
:src="captcha.img"
class="captcha"
@click="getCaptcha"
></image>
</view>
</block>
<view class="label">动态码</view>
<view class="form-item">
<view class="input-wrap">
<input
type="number"
placeholder="请输入动态码"
placeholder-class="placeholder"
v-model="formData.dynacode"
/>
</view>
<view class="send color-base-text" @click="sendMobileCode">
{{ dynacodeData.codeText }}
</view>
</view>
</view>
<view class="footer">
<view class="confirm" @click="confirm">确定</view>
<view @click="cancel" class="cancel">取消</view>
</view>
<!-- #endif -->
<!-- #ifdef MP-WEIXIN || MP-QQ || MP-BAIDU -->
<view class="bind-tip-icon">
<image
:src="$util.img('public/uniapp/member/login.png')"
mode="widthFix"
></image>
</view>
<view class="bind-tips">为了方便您接收订单等信息需要绑定您的手机号码</view>
<button
open-type="getPhoneNumber"
class="auth-login ns-btn-default-all color-base-bg"
@getphonenumber="mobileAuthLogin"
>
<text>点击绑定手机号码</text>
</button>
<!-- #endif -->
</view>
</uni-popup>
</view>
<register-reward ref="registerReward"></register-reward>
</view>
</template>
<script>
import uniPopup from '../uni-popup/uni-popup.vue';
import validate from 'common/js/validate.js';
import registerReward from '../register-reward/register-reward.vue';
export default {
name: 'bind-mobile',
components: {
uniPopup,
registerReward
},
mixins: [validate],
data() {
return {
captchaConfig: 0,
captcha: {
id: '',
img: ''
},
dynacodeData: {
seconds: 120,
timer: null,
codeText: '获取动态码',
isSend: false
},
formData: {
key: '',
mobile: '',
vercode: '',
dynacode: ''
},
isSub: false
};
},
created() {
this.getCaptchaConfig();
},
methods: {
open() {
this.$refs.bindMobile.open();
},
cancel() {
this.$refs.bindMobile.close();
},
confirm() {
let authData = uni.getStorageSync('authInfo');
let data = {
mobile: this.formData.mobile,
key: this.formData.key,
code: this.formData.dynacode
};
if (this.captcha.id != '') {
data.captcha_id = this.captcha.id;
data.captcha_code = this.formData.vercode;
}
if (authData) Object.assign(data, authData);
if (authData.avatarUrl) data.headimg = authData.avatarUrl;
if (authData.nickName) data.nickname = authData.nickName;
if (uni.getStorageSync('source_member'))
data.source_member = uni.getStorageSync('source_member');
if (this.verify(data)) {
if (this.isSub) return;
this.isSub = true;
this.$api.sendRequest({
url: '/api/tripartite/mobile',
data,
success: res => {
if (res.code >= 0) {
uni.setStorage({
key: 'token',
data: res.data.token,
success: () => {
this.$store.commit('setToken', res.data.token);
this.$store.dispatch('getCartNumber');
}
});
this.$refs.bindMobile.close();
if (res.data.is_register && this.$refs.registerReward.getReward()) {
this.$refs.registerReward.open();
}
} else {
this.isSub = false;
this.getCaptcha();
this.$util.showToast({ title: res.message });
}
},
fail: res => {
this.isSub = false;
this.getCaptcha();
}
});
}
},
/**
* 表单验证
* @param {Object} data
*/
verify(data) {
let rule = [
{ name: 'mobile', checkType: 'required', errorMsg: '请输入手机号' },
{ name: 'mobile', checkType: 'phoneno', errorMsg: '请输入正确的手机号' }
];
if (this.captchaConfig == 1) {
if (this.captcha.id != '')
rule.push({
name: 'captcha_code',
checkType: 'required',
errorMsg: this.$lang('captchaPlaceholder')
});
}
rule.push({
name: 'code',
checkType: 'required',
errorMsg: this.$lang('dynacodePlaceholder')
});
var checkRes = validate.check(data, rule);
if (checkRes) {
return true;
} else {
this.$util.showToast({ title: validate.error });
return false;
}
},
/**
* 获取验证码配置
*/
getCaptchaConfig() {
this.$api.sendRequest({
url: '/api/config/getCaptchaConfig',
success: res => {
if (res.code >= 0) {
this.captchaConfig = res.data.data.value.shop_reception_login;
if (this.captchaConfig) this.getCaptcha();
}
}
});
},
/**
* 获取验证码
*/
getCaptcha() {
this.$api.sendRequest({
url: '/api/captcha/captcha',
data: {
captcha_id: this.captcha.id
},
success: res => {
if (res.code >= 0) {
this.captcha = res.data;
this.captcha.img = this.captcha.img.replace(/\r\n/g, '');
}
}
});
},
/**
* 发送手机动态码
*/
sendMobileCode() {
if (this.dynacodeData.seconds != 120 || this.dynacodeData.isSend) return;
var data = {
mobile: this.formData.mobile,
captcha_id: this.captcha.id,
captcha_code: this.formData.vercode
};
var rule = [
{ name: 'mobile', checkType: 'required', errorMsg: '请输入手机号' },
{ name: 'mobile', checkType: 'phoneno', errorMsg: '请输入正确的手机号' }
];
if (this.captchaConfig == 1) {
rule.push({
name: 'captcha_code',
checkType: 'required',
errorMsg: '请输入验证码'
});
}
var checkRes = validate.check(data, rule);
if (!checkRes) {
this.$util.showToast({ title: validate.error });
return;
}
this.dynacodeData.isSend = true;
if (this.dynacodeData.seconds == 120) {
this.dynacodeData.timer = setInterval(() => {
this.dynacodeData.seconds--;
this.dynacodeData.codeText = this.dynacodeData.seconds + 's后可重新获取';
}, 1000);
}
this.$api.sendRequest({
url: '/api/tripartite/mobileCode',
data: data,
success: res => {
if (res.code >= 0) {
this.formData.key = res.data.key;
} else {
this.$util.showToast({ title: res.message });
this.refreshDynacodeData();
}
},
fail: () => {
this.$util.showToast({ title: 'request:fail' });
this.refreshDynacodeData();
}
});
},
mobileAuthLogin(e) {
if (e.detail.errMsg == 'getPhoneNumber:ok') {
let authData = uni.getStorageSync('authInfo');
var data = {
iv: e.detail.iv,
encryptedData: e.detail.encryptedData
};
if (authData) Object.assign(data, authData);
if (authData.avatarUrl) data.headimg = authData.avatarUrl;
if (authData.nickName) data.nickname = authData.nickName;
if (uni.getStorageSync('source_member'))
data.source_member = uni.getStorageSync('source_member');
if (this.isSub) return;
this.isSub = true;
this.$api.sendRequest({
url: '/api/tripartite/mobileauth',
data,
success: res => {
if (res.code >= 0) {
uni.setStorage({
key: 'token',
data: res.data.token,
success: () => {
this.$store.dispatch('getCartNumber');
this.$store.commit('setToken', res.data.token);
}
});
this.$refs.bindMobile.close();
if (res.data.is_register && this.$refs.registerReward.getReward()) {
this.$refs.registerReward.open();
}
} else {
this.isSub = false;
this.$util.showToast({ title: res.message });
}
},
fail: res => {
this.isSub = false;
this.$util.showToast({ title: 'request:fail' });
}
});
}
},
refreshDynacodeData() {
this.getCaptcha();
clearInterval(this.dynacodeData.timer);
this.dynacodeData = {
seconds: 120,
timer: null,
codeText: '获取动态码',
isSend: false
};
}
},
watch: {
'dynacodeData.seconds': {
handler(newValue, oldValue) {
if (newValue == 0) {
this.refreshDynacodeData();
}
},
immediate: true,
deep: true
}
}
};
</script>
<style lang="scss">
.bind-wrap {
background: #fff;
box-sizing: border-box;
border-radius: 20rpx;
overflow: hidden;
width: calc(100vw - 168rpx);
margin: 0 auto;
.head {
text-align: center;
height: 118rpx;
line-height: 118rpx;
background-color: #f6f6f6;
color: #333333;
font-size: 36rpx;
font-weight: 600;
}
.form-wrap {
padding: 30rpx 70rpx;
.label {
color: #000;
font-size: $font-size-base;
line-height: 1.3;
font-weight: bold;
}
.form-item {
margin: 24rpx 0;
display: flex;
align-items: flex-end;
.input-wrap {
padding-bottom: 30rpx;
border-bottom: 2rpx solid #f2f2f2;
flex: 1;
width: 0;
margin-right: 20rpx;
&:last-child {
margin-right: 0;
}
}
.placeholder {
font-size: $font-size-tag;
color: #a3a3a3;
height: 100%;
}
input {
font-size: $font-size-tag;
}
.send {
border: 2rpx solid $base-color;
height: 60rpx;
line-height: 60rpx;
border-radius: 60rpx;
font-size: $font-size-tag;
text-align: center;
padding: 0 40rpx;
}
.captcha {
margin: 4rpx;
height: 52rpx;
width: 140rpx;
}
}
}
.footer {
.confirm {
height: 78rpx;
line-height: 78rpx;
border-radius: 78rpx;
text-align: center;
background: $base-color;
color: #fff;
margin: 0 54rpx;
}
.cancel {
text-align: center;
padding: 30rpx 0;
font-size: 24rpx;
line-height: 1;
color: #666;
}
}
.bind-tips {
color: #aaa;
font-size: $font-size-base;
padding: 20rpx 50rpx;
text-align: center;
}
.auth-login {
width: calc(100% - 100rpx);
margin: 20rpx auto 50rpx auto;
height: 80rpx;
line-height: 80rpx;
border-radius: 80rpx;
}
.bind-tip-icon {
padding-top: 80rpx;
width: 100%;
text-align: center;
image {
width: 300rpx;
}
}
}
.ns-btn-default-all {
width: 100%;
height: 70rpx;
border-radius: $border-radius;
text-align: center;
line-height: 70rpx;
color: #ffffff;
font-size: $font-size-base;
}
</style>
<style scoped>
/deep/ .reward-popup .uni-popup__wrapper-box {
background: none !important;
max-width: unset !important;
max-height: unset !important;
overflow: unset !important;
}
</style>

233
components/cut_account.vue

@ -0,0 +1,233 @@
<template>
<u-overlay :show="cutShow">
<div class="view">
<div class="box">
<ns-empty
text="暂无通过的店铺~"
:isIndex="false"
v-if="!storeList.length && !loading"
></ns-empty>
<div
:class="active == item.id ? 'row_active' : 'row'"
v-for="(item, index) in storeList"
:key="index"
@click="changeActive(item)"
>
<!-- <image class="avatar" :src="$util.img('/upload/weapp/user/wx.png')"></image> -->
<div class="name">{{ item.title }}</div>
<div class="label" v-if="item.label">{{ item.label }}</div>
<image
class="gou"
:src="$util.img('/upload/weapp/user/gou2.png')"
mode=""
></image>
</div>
<div class="btn_box">
<div class="cancel" @click="cutShow = false">取消</div>
<div class="look_all" @click="look_all">查看全部</div>
</div>
</div>
</div>
</u-overlay>
</template>
<script>
export default {
data() {
return {
cutShow: false,
data: [],
active: '',
storeList: [],
loading: false
};
},
methods: {
start() {
this.cutShow = true;
this.getStoreList();
},
//
getStoreList() {
this.loading = true;
this.$api.sendRequest({
url: '/api/member/getStoreList',
data: {
status: 1
},
success: ({ data }) => {
this.storeList = data;
if (data.length) {
let myStore = uni.getStorageSync('myStore');
if (myStore) {
this.active = myStore.id;
} else {
this.active = data[0].id;
uni.setStorageSync('myStore', data[0]);
console.log(this.active, 111111);
}
}
else {
let storeObj = {
id: 0,
}
uni.setStorageSync('myStore', storeObj);
}
},
complete: res => {
this.loading = false;
}
});
},
//
changeActive(item) {
uni.setStorageSync('myStore', item);
this.active = item.id;
this.cutShow = false;
// this.$parent.$parent.init();
uni.$emit('changeStore', true);
},
close() {
this.$emit('close');
},
look_all() {
this.cutShow = false;
uni.navigateTo({
url: '/pages_tool/member/store/all_store'
});
}
}
};
</script>
<style lang="scss" scoped>
.view {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
line-height: 1;
.box {
width: 540rpx;
background-color: #fff;
border-radius: 24rpx;
padding: 24rpx;
max-height: 700rpx;
overflow: auto;
.row_active {
margin-top: 24rpx;
height: 92rpx;
background: rgba(33, 187, 243, 0.08);
border-radius: 16rpx;
border: 2rpx solid $base-color;
display: flex;
align-items: center;
position: relative;
.avatar {
width: 48rpx;
height: 48rpx;
margin-left: 24rpx;
}
.name {
margin-left: 16rpx;
}
.label {
margin-left: 20rpx;
border-radius: 8rpx;
border: 1rpx solid rgba(33, 187, 243, 0.2);
height: 32rpx;
font-size: 22rpx;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: $base-color;
line-height: 32rpx;
}
.gou {
width: 32rpx;
height: 32rpx;
position: absolute;
right: 0rpx;
bottom: -3rpx;
}
}
.row {
margin-top: 24rpx;
border: 2rpx solid #fff;
height: 92rpx;
background: #f7f7f7;
border-radius: 16rpx;
display: flex;
align-items: center;
.avatar {
width: 48rpx;
height: 48rpx;
margin-left: 24rpx;
}
.name {
margin-left: 16rpx;
}
.label {
margin-left: 20rpx;
border-radius: 8rpx;
border: 1rpx solid rgba(33, 187, 243, 0.2);
height: 32rpx;
font-size: 22rpx;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: $base-color;
line-height: 32rpx;
}
.gou {
width: 32rpx;
height: 32rpx;
display: none;
}
}
.btn_box {
margin-top: 56rpx;
display: flex;
justify-content: space-evenly;
.cancel {
width: 206rpx;
height: 72rpx;
border-radius: 40rpx;
border: 2rpx solid #e8e8e8;
display: flex;
justify-content: center;
align-items: center;
font-size: 28rpx;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #222222;
}
.look_all {
width: 206rpx;
height: 72rpx;
background: $base-color;
border-radius: 40rpx;
display: flex;
justify-content: center;
align-items: center;
font-size: 28rpx;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #ffffff;
}
}
}
}
</style>

1184
components/directionGoodsItem.vue

File diff suppressed because it is too large

1811
components/diy-components/div-categoyr.vue

File diff suppressed because it is too large

183
components/diy-components/diy-article.vue

@ -0,0 +1,183 @@
<template>
<view class="article-wrap" :style="warpCss" v-if="list.length > 0">
<view :class="['list-wrap', value.style]" :style="warpCss">
<view :class="['item', value.ornament.type]" v-for="(item, index) in list" :key="index" @click="toDetail(item)" :style="itemCss">
<view class="article-img">
<image class="cover-img" :src="$util.img(item.cover_img)" mode="widthFix" @error="imgError(index)"></image>
</view>
<view class="info-wrap">
<text class="title">{{ item.article_title }}</text>
<view class="read-wrap">
<block v-if="item.category_name">
<text class="category-icon"></text>
<text>{{ item.category_name }}</text>
</block>
<text class="date">{{ $util.timeStampTurnTime(item.create_time, 'date') }}</text>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
//
export default {
name: 'diy-article',
props: {
value: {
type: Object
}
},
data() {
return {
list: []
};
},
created() {
this.getBrandList();
},
computed: {
warpCss() {
var obj = '';
obj += 'background-color:' + this.value.componentBgColor + ';';
if (this.value.componentAngle == 'round') {
obj += 'border-top-left-radius:' + this.value.topAroundRadius * 2 + 'rpx;';
obj += 'border-top-right-radius:' + this.value.topAroundRadius * 2 + 'rpx;';
obj += 'border-bottom-left-radius:' + this.value.bottomAroundRadius * 2 + 'rpx;';
obj += 'border-bottom-right-radius:' + this.value.bottomAroundRadius * 2 + 'rpx;';
}
return obj;
},
//
itemCss() {
var obj = '';
obj += 'background-color:' + this.value.elementBgColor + ';';
if (this.value.elementAngle == 'round') {
obj += 'border-top-left-radius:' + this.value.topElementAroundRadius * 2 + 'rpx;';
obj += 'border-top-right-radius:' + this.value.topElementAroundRadius * 2 + 'rpx;';
obj += 'border-bottom-left-radius:' + this.value.bottomElementAroundRadius * 2 + 'rpx;';
obj += 'border-bottom-right-radius:' + this.value.bottomElementAroundRadius * 2 + 'rpx;';
}
if (this.value.ornament.type == 'shadow') {
obj += 'box-shadow:' + '0 0 10rpx ' + this.value.ornament.color;
}
if (this.value.ornament.type == 'stroke') {
obj += 'border:' + '2rpx solid ' + this.value.ornament.color;
}
return obj;
}
},
methods: {
getBrandList() {
var data = {
page: 1,
page_size: this.value.count
};
if (this.value.sources == 'diy') {
data.page_size = 0;
data.article_id_arr = this.value.articleIds.toString();
}
this.$api.sendRequest({
url: '/api/article/page',
data: data,
success: res => {
if (res.code == 0 && res.data) {
let data = res.data;
this.list = data.list;
}
}
});
},
toDetail(item) {
this.$util.redirectTo('/pages_tool/article/detail', {
article_id: item.article_id
});
},
imgError(index) {
if (this.list[index]) this.list[index].cover_img = this.$util.getDefaultImage().article;
}
}
};
</script>
<style lang="scss">
.article-wrap {
.list-wrap {
&.style-1 {
.item {
display: flex;
padding: 20rpx;
margin: 24rpx 0;
.article-img {
margin-right: 20rpx;
width: 160rpx;
height: 160rpx;
overflow: hidden;
display: flex;
align-items: center;
justify-content: center;
image {
width: 100%;
}
}
.info-wrap {
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
.title {
font-weight: bold;
margin-bottom: 10rpx;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
font-size: 30rpx;
line-height: 1.5;
}
.abstract {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
font-size: $font-size-tag;
}
.read-wrap {
display: flex;
color: #999ca7;
justify-content: flex-start;
align-items: center;
margin-top: 10rpx;
line-height: 1;
text {
font-size: $font-size-tag;
}
.iconfont {
font-size: 36rpx;
vertical-align: bottom;
margin-right: 10rpx;
}
.category-icon {
width: 8rpx;
height: 8rpx;
border-radius: 50%;
background: $base-color;
margin-right: 10rpx;
}
.date {
margin-left: 20rpx;
}
}
}
}
}
}
}
</style>

310
components/diy-components/diy-bottom-nav.vue

@ -0,0 +1,310 @@
<template>
<view v-if="tabBarList">
<view class="tab-bar" :style="{ backgroundColor: tabBarList.backgroundColor }">
<view class="tabbar-border"></view>
<view class="item" v-for="(item, index) in tabBarList.list" :key="index" @click="redirectTo(item.link)">
<view class="bd">
<block v-if="item.link.wap_url == '/pages/goods/cart'">
<view class="icon" v-if="tabBarList.type == 1 || tabBarList.type == 2"
:animation="cartAnimation">
<block v-if="verify(item.link)">
<image v-if="item.selected_icon_type == 'img'"
:src="$util.img(item.selectedIconPath)" />
<diy-icon v-if="item.selected_icon_type == 'icon'" :icon="item.selectedIconPath"
:value="item.selected_style ? item.selected_style : null"></diy-icon>
</block>
<block v-else>
<image v-if="item.icon_type == 'img'" :src="$util.img(item.iconPath)" />
<diy-icon v-if="item.icon_type == 'icon'" :icon="item.iconPath"
:value="item.style ? item.style : null"></diy-icon>
</block>
<view class="cartNumberBtn font-size-activity-tag" :class="{
max: item.link.wap_url == '/pages/goods/cart' && cartNumber > 99
}" :style="{ background: 'var(--price-color)' }"
v-if="item.link.wap_url == '/pages/goods/cart' && cartNumber > 0">
{{ cartNumber > 99 ? '99+' : cartNumber }}
</view>
</view>
</block>
<block v-else>
<view class="icon" v-if="tabBarList.type == 1 || tabBarList.type == 2">
<block v-if="verify(item.link)">
<image v-if="item.selected_icon_type == 'img'"
:src="$util.img(item.selectedIconPath)" />
<diy-icon v-if="item.selected_icon_type == 'icon'" :icon="item.selectedIconPath"
:value="item.selected_style ? item.selected_style : null"></diy-icon>
</block>
<block v-else>
<image v-if="item.icon_type == 'img'" :src="$util.img(item.iconPath)" />
<diy-icon v-if="item.icon_type == 'icon'" :icon="item.iconPath"
:value="item.style ? item.style : null"></diy-icon>
</block>
</view>
</block>
<view class="label" v-if="
(tabBarList.type == 1 || tabBarList.type == 3) &&
tabBarList.theme == 'diy'
" :style="{
color: verify(item.link)
? tabBarList.textHoverColor
: tabBarList.textColor
}">
{{ item.text }}
</view>
<view class="label" v-if="
(tabBarList.type == 1 || tabBarList.type == 3) &&
tabBarList.theme == 'default'
" :style="{ color: verify(item.link) ? 'var(--base-color)' : '#999' }">
{{ item.text }}
</view>
</view>
</view>
</view>
<!-- 解决fixed定位后底部导航栏塌陷问题 -->
<view class="tab-bar-placeholder"></view>
</view>
</template>
<script>
export default {
name: 'diy-bottom-nav',
props: {
value: {
type: Object
},
name: {
type: String,
default: ''
}
},
data() {
return {
currentRoute: '', //
jumpFlag: true, //
cartAnimation: {}
};
},
mounted() {
let currentPage = getCurrentPages()[getCurrentPages().length - 1];
this.currentRoute = currentPage.route;
this.$store.dispatch('getCartNumber');
},
computed: {
cartNumber() {
return this.$store.state.cartNumber;
},
cartChange() {
return this.$store.state.cartChange;
}
},
watch: {
cartChange: function(nval, oval) {
if (nval > oval) {
let animation = uni.createAnimation({
duration: 200,
timingFunction: 'ease'
});
animation.scale(1.2).step();
this.cartAnimation = animation.export();
setTimeout(() => {
animation.scale(1).step();
this.cartAnimation = animation.export();
}, 300);
}
}
},
methods: {
redirectTo(link) {
console.log(link.wap_url);
//
if (!uni.getStorageSync('token')) {
// ||link.wap_url =='/page_video/video/index'
if ((link.wap_url == '/pages/goods/cart') || link.wap_url == '/pages/member/index') {
this.$util.redirectTo('/pages_tool/login/login');
} else {
uni.switchTab({
url: link.wap_url
});
}
} else {
this.$emit('callback');
this.$util.diyRedirectTo(link);
}
},
verify(link) {
if (link == null || link == '' || !link.wap_url) return false;
if (this.name) {
var url = this.currentRoute + '?name=' + this.name;
} else {
var url = this.currentRoute;
}
//
if (link.wap_url == '/pages/index/index' && this.name == 'DIY_VIEW_INDEX') {
return true;
} else if (link.wap_url.indexOf(url) != -1) {
return true;
}
return false;
}
}
};
</script>
<style lang="scss">
.placeholder {
height: 112rpx;
&.bluge {
height: 180rpx;
}
}
.safe-area {
padding-bottom: 0;
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
}
.tab-bar {
background-color: #fff;
box-sizing: border-box;
position: fixed;
left: 0;
bottom: 0;
width: 100%;
z-index: 9999999;
display: flex;
border-top: 2rpx solid #f5f5f5;
padding-bottom: 0;
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
.tabbar-border {
background-color: rgba(255, 255, 255, 0.329412);
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 2rpx;
-webkit-transform: scaleY(0.5);
transform: scaleY(0.5);
}
.item {
display: flex;
align-items: center;
-webkit-box-orient: vertical;
-webkit-box-direction: normal;
flex: 1;
flex-direction: column;
padding-bottom: 10rpx;
box-sizing: border-box;
.bd {
position: relative;
height: 100rpx;
flex-direction: column;
text-align: center;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.icon {
position: relative;
display: inline-block;
margin-top: 10rpx;
width: 40rpx;
height: 40rpx;
font-size: 40rpx;
image {
width: 100%;
height: 100%;
}
>view {
height: inherit;
display: flex;
align-items: center;
}
.bar-icon {
font-size: 42rpx;
}
}
.label {
position: relative;
text-align: center;
font-size: 24rpx;
line-height: 1;
margin-top: 12rpx;
}
}
&.bulge {
.bd {
position: relative;
height: 100rpx;
flex-direction: column;
text-align: center;
.icon {
margin-top: -60rpx;
margin-bottom: 4rpx;
border-radius: 50%;
width: 100rpx;
height: 102rpx;
padding: 10rpx;
border-top: 2rpx solid #f5f5f5;
background-color: #fff;
box-sizing: border-box;
image {
width: 100%;
height: 100%;
border-radius: 50%;
}
}
.label {
position: relative;
text-align: center;
font-size: 24rpx;
line-height: 1.6;
height: 40rpx;
line-height: 40rpx;
}
}
}
.cartNumberBtn {
position: absolute;
top: -8rpx;
right: -18rpx;
width: 24rpx;
height: 24rpx !important;
display: flex;
justify-content: center;
align-items: center;
color: #fff;
padding: 6rpx;
border-radius: 50%;
z-index: 99;
&.max {
width: 40rpx;
border-radius: 24rpx;
right: -28rpx;
}
}
}
}
.tab-bar-placeholder {
padding-bottom: calc(constant(safe-area-inset-bottom) + 112rpx);
padding-bottom: calc(env(safe-area-inset-bottom) + 112rpx);
}
</style>

1391
components/diy-components/diy-category-item.vue

File diff suppressed because it is too large

2086
components/diy-components/diy-category.vue

File diff suppressed because it is too large

30
components/diy-components/diy-comp-extend.vue

@ -0,0 +1,30 @@
<template>
<view>
<!-- 扩展组件 -->
<!-- 扩展标题 -->
<template v-if="value.componentName == 'TextExtend'">
<diy-text-extend :value="value"></diy-text-extend>
</template>
</view>
</template>
<script>
//
export default {
name: 'diy-comp-extend',
props: {
value: {
type: Object
}
},
data() {
return {};
},
computed: {},
created() {},
methods: {}
};
</script>
<style></style>

1103
components/diy-components/diy-coupon.vue

File diff suppressed because it is too large

102
components/diy-components/diy-float-btn.vue

@ -0,0 +1,102 @@
<template>
<view class="float-btn"
:class="{'left_top': value.bottomPosition == 1, 'right_top': value.bottomPosition == 2, 'left_bottom': value.bottomPosition == 3, 'right_bottom': value.bottomPosition == 4}"
:style="style">
<block v-for="(item, index) in value.list" :key="index">
<view class="button-box" @click="$util.diyRedirectTo(item.link)">
<image :src="$util.img(item.imageUrl)" mode="aspectFit" v-if="!item.iconType || item.iconType == 'img'"></image>
<diy-icon v-else-if="item.iconType && item.iconType == 'icon'" :icon="item.icon" :value="item.style ? item.style : null"></diy-icon>
</view>
</block>
</view>
</template>
<script>
//
let systemInfo = uni.getSystemInfoSync();
export default {
name: 'diy-float-btn',
props: {
value: {
type: Object,
default: () => {
return {};
}
}
},
data() {
return {
navHeight: 0,
statusBarHeight: systemInfo.statusBarHeight
};
},
created() {},
components: {},
methods: {},
computed:{
style(){
let style = {}, height = 54;
// #ifdef MP
height = systemInfo.platform == 'ios' ? 54 : 58;
// #endif
switch (this.value.bottomPosition) {
case 1:
style.top = (this.navHeight + this.statusBarHeight + parseInt(value.btnBottom)) * 2 + 'rpx !important'
break;
case 2:
style.top = (this.navHeight + this.statusBarHeight + parseInt(value.btnBottom)) * 2 + 'rpx !important'
break;
case 3:
style.bottom = (100 + parseInt(value.btnBottom)) * 2 + 'rpx !important'
break;
case 4:
style.bottom = (100 + parseInt(value.btnBottom)) * 2 + 'rpx !important'
break;
}
return this.$util.objToStyle(style);
}
}
};
</script>
<style lang="scss">
.float-btn {
position: fixed;
bottom: 20%;
right: 40rpx;
z-index: 999;
&.right_top {
top: 100rpx;
right: 30rpx;
}
&.left_top {
top: 100rpx;
left: 30rpx;
}
&.right_bottom {
bottom: 200rpx;
right: 30rpx;
padding-bottom: constant(safe-area-inset-bottom); /*兼容 IOS<11.2*/
padding-bottom: env(safe-area-inset-bottom); /*兼容 IOS>11.2*/
}
&.left_bottom {
bottom: 200rpx;
left: 30rpx;
padding-bottom: constant(safe-area-inset-bottom); /*兼容 IOS<11.2*/
padding-bottom: env(safe-area-inset-bottom); /*兼容 IOS>11.2*/
}
.button-box {
margin-bottom: 20rpx;
width: 80rpx;
height: 80rpx;
font-size: 80rpx;
&:last-child {
margin-bottom: 0;
}
image {
width: 100%;
height: 100%;
}
}
}
</style>

127
components/diy-components/diy-goods-brand.vue

@ -0,0 +1,127 @@
<template>
<view :class="['brand-wrap', value.ornament.type]" :style="warpCss" v-if="list.length > 0">
<view :class="[value.style]">
<view class="title-wrap" v-show="value.title" :style="{ color: value.textColor, fontWeight: value.fontWeight ? 'bold' : '' }">{{ value.title }}</view>
<view class="ul-wrap">
<uni-grid :column="4" :showBorder="!1">
<uni-grid-item v-for="(item, index) in list" :key="index" index="index">
<image class="brand-pic" :src="$util.img(item.image_url)" mode="aspectFit" @click="toDetail(item)" @error="imgError(index)" :style="itemCss"></image>
</uni-grid-item>
</uni-grid>
</view>
</view>
</view>
</template>
<script>
//
import uniGrid from '@/components/uni-grid/uni-grid.vue';
import uniGridItem from '@/components/uni-grid-item/uni-grid-item.vue';
export default {
name: 'diy-goods-brand',
props: {
value: {
type: Object
}
},
components: {
uniGrid,
uniGridItem
},
data() {
return {
list: []
};
},
created() {
this.getBrandList();
},
computed: {
warpCss() {
var obj = '';
obj += 'background-color:' + this.value.componentBgColor + ';';
if (this.value.componentAngle == 'round') {
obj += 'border-top-left-radius:' + this.value.topAroundRadius * 2 + 'rpx;';
obj += 'border-top-right-radius:' + this.value.topAroundRadius * 2 + 'rpx;';
obj += 'border-bottom-left-radius:' + this.value.bottomAroundRadius * 2 + 'rpx;';
obj += 'border-bottom-right-radius:' + this.value.bottomAroundRadius * 2 + 'rpx;';
}
if (this.value.ornament.type == 'shadow') {
obj += 'box-shadow:' + '0 0 10rpx ' + this.value.ornament.color;
}
if (this.value.ornament.type == 'stroke') {
obj += 'border:' + '2rpx solid ' + this.value.ornament.color;
}
return obj;
},
//
itemCss() {
var obj = '';
if (this.value.elementAngle == 'round') {
obj += 'border-top-left-radius:' + this.value.topElementAroundRadius * 2 + 'rpx;';
obj += 'border-top-right-radius:' + this.value.topElementAroundRadius * 2 + 'rpx;';
obj += 'border-bottom-left-radius:' + this.value.bottomElementAroundRadius * 2 + 'rpx;';
obj += 'border-bottom-right-radius:' + this.value.bottomElementAroundRadius * 2 + 'rpx;';
}
return obj;
}
},
methods: {
getBrandList() {
var data = {
page: 1,
page_size: this.value.count
};
if (this.value.sources == 'diy') {
data.page_size = 0;
data.brand_id_arr = this.value.brandIds.toString();
}
this.$api.sendRequest({
url: '/api/goodsbrand/page',
data: data,
success: res => {
if (res.code == 0 && res.data) {
let data = res.data;
this.list = data.list;
}
}
});
},
toDetail(item) {
this.$util.redirectTo('/page_goods/goodsList/goodsList', {
brand_id: item.brand_id
});
},
imgError(index) {
if (this.list[index]) this.list[index].image_url = this.$util.getDefaultImage().goods;
}
}
};
</script>
<style lang="scss">
.brand-wrap {
&.shadow {
margin-left: 8rpx;
margin-right: 8rpx;
margin-top: 8rpx;
margin-bottom: 8rpx;
}
.style-1 {
.title-wrap {
text-align: center;
padding: 20rpx 0 10rpx;
}
.ul-wrap {
padding: 20rpx;
.brand-pic {
width: 90%;
}
.uni-grid-item{
width: calc(100% / 4) !important;
}
}
}
}
</style>

1256
components/diy-components/diy-goods-list.vue

File diff suppressed because it is too large

563
components/diy-components/diy-goods-recommend.vue

@ -0,0 +1,563 @@
<template>
<view v-if="list.length" :class="['goods-list', goodsValue.style]" :style="goodsListWarpCss">
<view class="top-wrap">
<text :class="['js-icon', goodsValue.topStyle.icon.value]" :style="{
backgroundColor: goodsValue.topStyle.icon.bgColor,
color: goodsValue.topStyle.icon.color
}"></text>
<text class="title" :style="{ color: goodsValue.topStyle.color }">
{{ goodsValue.topStyle.title }}
</text>
<text class="line" :style="{ color: goodsValue.topStyle.subColor }"></text>
<text class="sub" :style="{ color: goodsValue.topStyle.subColor }">
{{ goodsValue.topStyle.subTitle }}
</text>
</view>
<swiper :autoplay="false" class="swiper" :style="{ height: swiperHeight }">
<swiper-item v-for="(item, index) in page" :key="index"
:class="['swiper-item', [list[index].length / 3] >= 1 && 'flex-between']">
<view class="goods-item" v-for="(dataItem, dataIndex) in list[index]" :key="dataIndex" @click="toDetail(dataItem)"
:class="[goodsValue.ornament.type]" :style="goodsItemCss">
<image class="goods-img" :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }"
:src="$util.img(dataItem.goods_image, { size: 'mid' })" mode="widthFix" @error="imgError(dataIndex)"
:lazy-load="true"></image>
<view :class="[
'info-wrap',
{ 'multi-content': value.nameLineMode == 'multiple' }
]" v-if="
goodsValue.goodsNameStyle.control ||
goodsValue.priceStyle.mainControl ||
goodsValue.priceStyle.lineControl
">
<view v-if="goodsValue.goodsNameStyle.control" class="goods-name" :style="{
color:
goodsValue.theme == 'diy'
? goodsValue.goodsNameStyle.color
: '',
fontWeight: goodsValue.goodsNameStyle.fontWeight ? 'bold' : ''
}" :class="[
{ 'using-hidden': goodsValue.nameLineMode == 'single' },
{ 'multi-hidden': goodsValue.nameLineMode == 'multiple' }
]">
{{ dataItem.goods_name }}
</view>
<view class="pro-info">
<view class="discount-price">
<!-- <view class="price-wrap" v-if="goodsValue.priceStyle.mainControl">
<text class="unit price-style small" :style="{
color:
goodsValue.theme == 'diy'
? goodsValue.priceStyle.mainColor + '!important'
: ''
}">
</text>
<text class="price price-style large" :style="{
color:
goodsValue.theme == 'diy'
? goodsValue.priceStyle.mainColor + '!important'
: ''
}">
{{ showPrice(dataItem).split('.')[0] }}
</text>
<text class="unit price-style small" :style="{
color:
goodsValue.theme == 'diy'
? goodsValue.priceStyle.mainColor + '!important'
: ''
}">
{{ '.' + showPrice(dataItem).split('.')[1] }}
</text>
</view> -->
<view v-if="goodsValue.priceStyle.mainControl" style="color: #f33b50;">
<goodsPrice :goodsSkuDetail="dataItem"></goodsPrice>
</view>
<!-- <view
v-if="goodsValue.priceStyle.lineControl"
class="delete-price price-font"
:style="{
color:
goodsValue.theme == 'diy'
? goodsValue.priceStyle.lineColor
: ''
}"
>
{{
dataItem.market_price > 0
? dataItem.market_price
: dataItem.price
}}
</view> -->
<view v-if="goodsValue.priceStyle.lineControl" style="color: #f33b50;">
<goodsPrice :goodsSkuDetail="dataItem"></goodsPrice>
</view>
<view class="sale" v-if="goodsValue.saleStyle.control" :style="{
color:
goodsValue.theme == 'diy'
? goodsValue.saleStyle.color
: ''
}">
{{ dataItem.sale_num
}}{{ dataItem.unit ? dataItem.unit : '件' }}
</view>
</view>
</view>
</view>
</view>
</swiper-item>
</swiper>
</view>
</template>
<script>
import goodsPrice from "@/components/goodsPrice.vue"
export default {
name: 'diy-goods-recommend',
components: {
goodsPrice
},
props: {
value: {
type: Object,
default: () => {
return {};
}
}
},
data() {
return {
list: [],
goodsValue: {},
page: 1
};
},
created() {
this.goodsValue = this.value;
this.getGoodsList();
},
computed: {
goodsListWarpCss() {
var obj = '';
obj += 'background-color:' + this.goodsValue.componentBgColor + ';';
if (this.goodsValue.componentAngle == 'round') {
obj += 'border-top-left-radius:' + this.goodsValue.topAroundRadius * 2 + 'rpx;';
obj += 'border-top-right-radius:' + this.goodsValue.topAroundRadius * 2 + 'rpx;';
obj +=
'border-bottom-left-radius:' + this.goodsValue.bottomAroundRadius * 2 + 'rpx;';
obj +=
'border-bottom-right-radius:' + this.goodsValue.bottomAroundRadius * 2 + 'rpx;';
}
if (this.goodsValue.bgUrl) {
obj += `background-image: url('${this.$util.img(this.goodsValue.bgUrl)}');`;
}
return obj;
},
//
goodsItemCss() {
var obj = '';
obj += 'background-color:' + this.value.elementBgColor + ';';
if (this.goodsValue.elementAngle == 'round') {
obj +=
'border-top-left-radius:' + this.goodsValue.topElementAroundRadius * 2 + 'rpx;';
obj +=
'border-top-right-radius:' +
this.goodsValue.topElementAroundRadius * 2 +
'rpx;';
obj +=
'border-bottom-left-radius:' +
this.goodsValue.bottomElementAroundRadius * 2 +
'rpx;';
obj +=
'border-bottom-right-radius:' +
this.goodsValue.bottomElementAroundRadius * 2 +
'rpx;';
}
if (this.goodsValue.ornament.type == 'shadow') {
obj += 'box-shadow:' + '0 0 10rpx ' + this.goodsValue.ornament.color + ';';
}
if (this.goodsValue.ornament.type == 'stroke') {
obj += 'border:' + '2rpx solid ' + this.goodsValue.ornament.color + ';';
}
const screenWidth =
uni.getSystemInfoSync().safeArea.width || uni.getSystemInfoSync().screenWidth;
var width = '';
if (this.goodsValue.style != 'style-2') {
width =
[
screenWidth -
this.rpxUpPx(20) * 2 -
this.rpxUpPx(200) * 3 -
this.rpxUpPx(this.value.margin.both * 2) * 2
] / 6;
} else {
width =
[
screenWidth -
this.rpxUpPx(20) * 2 -
this.rpxUpPx(20) * 2 -
this.rpxUpPx(200) * 3 -
this.rpxUpPx(this.value.margin.both * 2) * 2
] / 6;
}
obj += 'margin-left:' + width + 'px;';
obj += 'margin-right:' + width + 'px;';
return obj;
},
swiperHeight() {
if (this.goodsValue.style != 'style-2') {
if (this.value.nameLineMode == 'multiple') {
return '348rpx';
}
return '312rpx';
} else {
if (this.value.nameLineMode == 'multiple') {
return '360rpx';
}
return '320rpx';
}
}
},
methods: {
rpxUpPx(res) {
const screenWidth =
uni.getSystemInfoSync().safeArea.width || uni.getSystemInfoSync().screenWidth;
var data = (screenWidth * parseInt(res)) / 750;
return Math.floor(data);
},
getGoodsList() {
var data = {
page: 1,
page_size: this.goodsValue.count,
cate_name: 6
};
if (this.goodsValue.sources == 'category') {
data.category_id = this.goodsValue.categoryId;
data.category_level = 1;
} else if (this.goodsValue.sources == 'diy') {
data.page_size = 0;
data.goods_id_arr = this.goodsValue.goodsId.toString();
}
data.order = this.goodsValue.sortWay;
this.$api.sendRequest({
url: '/api/goodssku/pagecomponents',
data: data,
success: res => {
if (res.code == 0 && res.data) {
let data = res.data;
this.list = data.list;
//
let size = 3;
let temp = [];
this.page = Math.ceil(this.list.length / size);
for (var i = 0; i < this.page; i++) {
temp[i] = [];
for (var j = i * size; j < this.list.length; j++) {
if (temp[i].length == size) break;
temp[i].push(this.list[j]);
}
}
this.list = temp;
}
}
});
},
toDetail(item) {
this.$util.redirectTo('/page_goods/detail/detail', {
goods_id: item.goods_id
});
},
imgError(index) {
if (this.list[index]) this.list[index].goods_image = this.$util.getDefaultImage().goods;
},
showPrice(data) {
let price = data.discount_price;
if (data.member_price && parseFloat(data.member_price) < parseFloat(price))
price = data.member_price;
return price;
}
}
};
</script>
<style lang="scss" scoped>
.goods-list {
.goods-item {
line-height: 1;
.sale {
line-height: 1;
color: $color-tip;
font-size: $font-size-activity-tag;
}
.info-wrap {
.goods-name {
margin-bottom: 10rpx;
line-height: 1.3;
}
}
}
}
//
.goods-list.style-1 {
width: 100%;
white-space: nowrap;
background-repeat: round;
.top-wrap {
display: flex;
align-items: center;
padding: 20rpx 0;
.js-icon {
border-radius: 50%;
font-size: 40rpx;
margin-right: 10rpx;
width: 70rpx;
height: 70rpx;
text-align: center;
line-height: 70rpx;
}
.line {
height: 28rpx;
margin: 0 10rpx;
border: 2rpx solid;
}
.title {
font-weight: bold;
font-size: $font-size-toolbar;
}
.sub {
font-size: $font-size-tag;
}
}
.flex-between {
justify-content: space-between;
}
.swiper {
display: flex;
flex-wrap: wrap;
margin: 0 20rpx;
.swiper-item {
display: flex;
align-items: center;
}
}
.goods-item {
overflow: hidden;
width: 200rpx;
display: inline-block;
box-sizing: border-box;
&:nth-child(3n + 3) {
width: 198rpx;
}
&.shadow {
margin-top: 8rpx;
}
.goods-img {
width: 100%;
height: 196rpx;
}
.info-wrap {
display: flex;
flex-direction: column;
padding: 10rpx;
&.multi-content {
height: 130rpx;
box-sizing: border-box;
}
.goods-name {
font-size: $font-size-sub;
&.using-hidden {
display: block;
}
&.multi-hidden {
white-space: break-spaces;
}
}
.pro-info {
margin-top: auto;
display: flex;
flex-direction: column;
justify-content: space-between;
.discount-price {
display: flex;
justify-content: space-between;
align-items: center;
.price-wrap {
line-height: 1;
white-space: nowrap;
.unit {
font-size: $font-size-tag;
color: $base-color;
}
.price {
font-size: $font-size-toolbar;
}
text {
font-weight: bold;
color: $base-color;
}
}
}
.delete-price {
margin-left: 10rpx;
text-decoration: line-through;
flex: 1;
line-height: 28rpx;
color: $color-tip;
font-size: $font-size-activity-tag;
}
}
}
}
}
//
.goods-list.style-2 {
width: 100%;
white-space: nowrap;
background-repeat: round;
padding-bottom: 20rpx;
.top-wrap {
display: flex;
align-items: center;
padding: 20rpx;
.js-icon {
border-radius: 50%;
font-size: 40rpx;
margin-right: 20rpx;
width: 70rpx;
height: 70rpx;
text-align: center;
line-height: 70rpx;
}
.line {
height: 28rpx;
margin: 0 10rpx;
border: 2rpx solid;
}
.title {
font-weight: bold;
font-size: $font-size-toolbar;
}
.sub {
font-size: $font-size-tag;
}
}
.swiper {
display: flex;
flex-wrap: wrap;
margin: 0 20rpx;
padding: 20rpx;
border-radius: 20rpx;
background-color: #fff;
}
.goods-item {
overflow: hidden;
width: 200rpx;
display: inline-block;
box-sizing: border-box;
&.shadow {
margin-top: 8rpx;
width: 200rpx;
}
.goods-img {
width: 100%;
height: 200rpx;
}
.info-wrap {
padding: 10rpx;
.goods-name {
line-height: 1;
&.using-hidden {
display: block;
}
&.multi-hidden {
line-height: 1.3;
height: 68rpx;
white-space: break-spaces;
}
}
.pro-info {
display: flex;
flex-direction: column;
justify-content: space-between;
.discount-price {
display: flex;
justify-content: space-between;
align-items: center;
.price-wrap {
line-height: 1.3;
.unit {
font-size: $font-size-tag;
color: $base-color;
}
text {
font-weight: bold;
color: $base-color;
&:last-of-type {
font-size: 32rpx;
}
}
}
}
.delete-price {
margin-left: 10rpx;
text-decoration: line-through;
flex: 1;
line-height: 28rpx;
color: $color-tip;
font-size: $font-size-activity-tag;
}
}
}
}
}
</style>

313
components/diy-components/diy-graphic-nav.vue

@ -0,0 +1,313 @@
<template>
<div class="graphic_BOX">
<view :style="componentStyle">
<scroll-view :scroll-x="value.showStyle == 'singleSlide'" :class="['graphic-nav', value.showStyle]">
<!-- #ifdef MP -->
<view class="uni-scroll-view-content">
<!-- #endif -->
<view class="graphic-nav-item" v-for="(item, index) in value.list" :key="index"
:style="{ width: 100 / value.rowCount + '%' }" @click="redirectTo(item.link)">
<view class="graphic-img" v-show="value.mode != 'text'" :style="{
fontSize: value.imageSize * 2 + 'rpx',
width: value.imageSize * 2 + 'rpx',
height: value.imageSize * 2 + 'rpx'
}">
<image v-if="item.iconType == 'img'" :src="
$util.img(item.imageUrl) ||
$util.img('public/uniapp/default_img/goods.png')
" mode="aspectFill" :style="{
maxWidth: value.imageSize * 2 + 'rpx',
maxHeight: value.imageSize * 2 + 'rpx',
borderRadius: value.aroundRadius * 2 + 'rpx'
}"></image>
<diy-icon v-if="item.iconType == 'icon'" :icon="item.icon"
:value="item.style ? item.style : null" :style="{
maxWidth: value.imageSize * 2 + 'rpx',
maxHeight: value.imageSize * 2 + 'rpx',
width: '100%',
height: '100%'
}"></diy-icon>
<text :class="['tag', { alone: value.mode == 'text' }]" v-if="item.label.control" :style="{
color: item.label.textColor,
backgroundImage:
'linear-gradient(' +
item.label.bgColorStart +
',' +
item.label.bgColorEnd +
')'
}">
{{ item.label.text }}
</text>
</view>
<text v-show="value.mode != 'img'" class="graphic-text" :style="{
fontSize: value.font.size * 2 + 'rpx',
fontWeight: value.font.weight,
color: value.font.color
}">
{{ item.title }}
</text>
</view>
<!-- #ifdef MP -->
</view>
<!-- #endif -->
</scroll-view>
</view>
</div>
</template>
<script>
export default {
name: 'diy-graphic-nav',
props: {
value: {
type: Object
}
},
data() {
return {
pageWidth: '',
indicatorDots: false,
swiperCurrent: 0
};
},
created() {
// console.log('----------------------------------------')
},
computed: {
componentStyle() {
var css = '';
css += 'background-color:' + this.value.componentBgColor + ';';
if (this.value.componentAngle == 'round') {
css += 'border-top-left-radius:' + this.value.topAroundRadius * 2 + 'rpx;';
css += 'border-top-right-radius:' + this.value.topAroundRadius * 2 + 'rpx;';
css += 'border-bottom-left-radius:' + this.value.bottomAroundRadius * 2 + 'rpx;';
css += 'border-bottom-right-radius:' + this.value.bottomAroundRadius * 2 + 'rpx;';
}
css +=
'box-shadow:' +
(this.value.ornament.type == 'shadow' ?
'0 0 10rpx ' + this.value.ornament.color :
'') +
';';
css +=
'border:' +
(this.value.ornament.type == 'stroke' ?
'2rpx solid ' + this.value.ornament.color :
'') +
';';
return css;
},
//
swiperHeight() {
var css = '';
var height = 88 * this.value.pageCount; // 88 = +
if (this.value.mode == 'img') height -= 21 * this.value.pageCount; // 21 =
if (this.value.mode == 'text') height -= 50 * this.value.pageCount; // 21 =
css += 'height:' + height * 2 + 'rpx';
return css;
},
//
isIndicatorDots() {
var bool = true;
bool =
this.value.carousel.type == 'hide' ||
Math.ceil(this.value.list.length / (this.value.pageCount * this.value.rowCount)) ==
1 ?
false :
true;
return bool;
}
},
methods: {
redirectTo(link) {
console.log(link);
if (![
'/pages_tool/quality_test/quality_test',
"/pages_tool/article/list",
"/pages_tool/goods/coupon",
"/page_goods/goodsList/goodsList"
].includes(link.wap_url)) {
if (!uni.getStorageSync('token')) {
this.$util.showToast({
title: '您尚未登录,请先进行登录',
icon: 'none',
});
setTimeout(() => {
this.$util.redirectTo('/pages_tool/login/login');
}, 1000)
return
}
}
this.$util.diyRedirectTo(link);
},
swiperChange(e) {
this.swiperCurrent = e.detail.current;
}
}
};
</script>
<style lang="scss" scoped>
.graphic_BOX {
/* 固定显示 */
.graphic-nav.fixed {
/deep/ .uni-scroll-view-content {
display: flex;
flex-wrap: wrap;
}
}
/* #ifdef MP-ALIPAY*/
.fixed {
position: relative;
left: 0;
top: 0;
}
/* #endif */
/* 单行滑动 */
.graphic-nav.singleSlide {
/deep/ .uni-scroll-view-content {
display: flex;
}
}
.graphic-nav.pageSlide {
/deep/.uni-swiper-dots-horizontal {
bottom: 0rpx;
}
}
.graphic-nav.pageSlide.straightLine {
/deep/.uni-swiper-dot {
width: 30rpx;
border-radius: 0;
height: 8rpx;
}
}
.graphic-nav.pageSlide.circle {
/deep/.uni-swiper-dot {
width: 14rpx;
height: 14rpx;
}
}
}
</style>
<style lang="scss">
.graphic-nav {
padding: 16rpx;
box-sizing: border-box;
// border-radius: 0rpx 0rpx 0rpx 0rpx;
// box-shadow: 0 0 4rpx rgba(100, 100, 100, 0.3);
&.singleSlide {
.graphic-nav-item {
flex-shrink: 0;
}
}
&.pageSlide {
position: relative;
.graphic-nav-wrap {
display: flex;
flex-wrap: wrap;
width: 100%;
height: 100%;
}
}
.graphic-nav-item {
display: flex;
flex-direction: column;
align-items: center;
padding: 14rpx 0;
box-sizing: border-box;
.graphic-text {
padding-top: 12rpx;
line-height: 1.5;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
width: 100%;
text-align: center;
&.alone {
padding-top: 0;
}
}
.graphic-img {
position: relative;
display: flex;
align-items: center;
justify-content: center;
width: 100rpx;
height: 100rpx;
font-size: 90rpx;
.tag {
position: absolute;
top: -10rpx;
right: -36rpx;
color: #fff;
border-radius: 24rpx;
border-bottom-left-radius: 0;
transform: scale(0.8);
padding: 8rpx 16rpx;
line-height: 1;
font-size: 24rpx;
}
.icon {
font-size: 50rpx;
color: $color-sub;
}
}
}
}
.swiper-dot-box {
width: 100%;
display: flex;
align-items: center;
justify-content: center;
margin-top: -20rpx;
padding-bottom: 8rpx;
.swiper-dot {
background-color: rgba(0, 0, 0, 0.3);
margin: 8rpx;
&.active {
background-color: rgba(0, 0, 0, 1);
}
}
&.straightLine {
.swiper-dot {
width: 30rpx;
border-radius: 0;
height: 8rpx;
}
}
&.circle {
.swiper-dot {
width: 15rpx;
border-radius: 50%;
height: 15rpx;
}
}
}
</style>

262
components/diy-components/diy-group.vue

@ -0,0 +1,262 @@
<template>
<view class="diy-group" v-if="showFlag">
<view v-for="(item, index) in diyGlobalData.value" :key="index" :style="item.pageStyle">
<template v-if="item.componentName == 'Text'">
<!-- 文本 -->
<diy-text :value="item"></diy-text>
</template>
<template v-if="item.componentName == 'TextNav'">
<!-- 文本导航 -->
<diy-text-nav :value="item"></diy-text-nav>
</template>
<template v-if="item.componentName == 'Notice'">
<!-- 公告 -->
<diy-notice :value="item"></diy-notice>
</template>
<template v-if="item.componentName == 'GraphicNav'">
<!-- 图文导航 -->
<diy-graphic-nav :value="item"></diy-graphic-nav>
</template>
<template v-if="item.componentName == 'ImageAds'">
<!-- 图片广告 -->
<view :class="!showStore || !addonIsExist.store ? 'noStore-bg' : ''">
<diy-img-ads :value="item"></diy-img-ads>
</view>
</template>
<template v-if="item.componentName == 'Search'">
<!-- 搜索 -->
<view class="box" :class="!showStore || !addonIsExist.store ? 'noStore-bg' : ''">
<diy-search :value="item"></diy-search>
</view>
<!-- <view :class="!showStore || !addonIsExist.store ? 'noStore-bg' : 'isStore-top'">
<diy-search :value="item"></diy-search>
</view> -->
</template>
<template v-if="item.componentName == 'RichText'">
<!-- 富文本 -->
<u-parse :content="item.html"></u-parse>
</template>
<template v-if="item.componentName == 'HorzLine'">
<!-- 辅助线 -->
<diy-horz-line :value="item"></diy-horz-line>
</template>
<template v-if="item.componentName == 'HorzBlank'">
<!-- 辅助空白 -->
<diy-horz-blank :value="item"></diy-horz-blank>
</template>
<template v-if="item.componentName == 'Coupon' && addonIsExist.coupon">
<!-- 优惠券 -->
<diy-coupon :value="item"></diy-coupon>
</template>
<template v-if="item.componentName == 'GoodsList'">
<!-- 商品列表 -->
<diy-goods-list :value="item"></diy-goods-list>
</template>
<template v-if="item.componentName == 'ManyGoodsList'">
<!-- 多商品组 -->
<diy-many-goods-list ref="ManyGoodsList" :value="item"
:manyGoodsList='manyGoodsListData'></diy-many-goods-list>
</template>
<template v-if="item.componentName == 'RubikCube'">
<!-- 魔方橱窗 -->
<diy-rubik-cube :value="item"></diy-rubik-cube>
</template>
<template v-if="item.componentName == 'Video'">
<!-- 视频 -->
<diy-video :value="item" ref="diyVideo"></diy-video>
</template>
<view class="diy-goods-level-wrap" v-if="item.componentName == 'GoodsCategory'">
<!-- 商品分类 使用view替代template目的是限制商品分类在自定义首页的高度-->
<!-- <diy-category :value="item"></diy-category> -->
</view>
<template v-if="item.componentName == 'FloatBtn'">
<!-- 浮动按钮 -->
<!-- <diy-float-btn :value="item"></diy-float-btn> -->
</template>
<template v-if="item.componentName == 'GoodsRecommend'">
<!-- 商品推荐 -->
<diy-goods-recommend :value="item"></diy-goods-recommend>
</template>
<template v-if="item.componentName == 'GoodsBrand'">
<!-- 商品品牌 -->
<diy-goods-brand :value="item"></diy-goods-brand>
</template>
<template v-if="item.componentName == 'Article'">
<!-- 文章 -->
<diy-article :value="item"></diy-article>
</template>
<template v-if="item.componentName == 'MemberInfo'">
<!-- 自定义会员中心会员信息 -->
<diy-member-info ref="diyMemberIndex" :value="item" :token="token"></diy-member-info>
</template>
<template v-if="item.componentName == 'MemberMyOrder'">
<!-- 自定义会员中心我的订单 -->
<diy-member-my-order ref="diyMemberMyOrder" :value="item" :token="token"></diy-member-my-order>
</template>
<!-- 自定义扩展组件 -->
<template v-if="diyGlobalData.compExtend.indexOf(item.componentName) != -1">
<!-- <diy-comp-extend :value="item"></diy-comp-extend> -->
</template>
</view>
</view>
</template>
<script>
export default {
components: {},
props: {
diyData: {
type: Object
},
storeId: {
type: [String, Number]
},
token: {
type: String
},
height: {
type: String,
default () {
return '100vh';
}
}
},
data() {
return {
showStore: false,
diyGlobalData: null,
showFlag: true,
manyGoodsListData: [],
};
},
watch: {
diyData: {
deep: true,
handler() {
this.showFlag = false
this.$nextTick(() => {
this.showFlag = true
this.diyGlobalData = JSON.parse(JSON.stringify(this.diyData));
this.setPagestyle();
})
}
}
},
created() {
this.diyGlobalData = JSON.parse(JSON.stringify(this.diyData));
this.setPagestyle();
},
computed: {
bgColor() {
let str = '';
if (this.diyData && this.diyData.global) {
str = this.diyData.global.bgColor;
}
return str;
},
bgUrl() {
let str = '';
if (this.diyData && this.diyData.global) {
str = this.diyData.global.bgUrl;
}
return str;
}
},
mounted() {
if (this.diyData != undefined) {
this.dealData();
}
// this.getHomeIndexList()
},
methods: {
setPagestyle() {
this.diyGlobalData.value.forEach((item, index) => {
item.pageStyle = '';
item.pageStyle += 'background-color:' + item.pageBgColor + ';';
if (item.margin) {
item.pageStyle += 'padding-top:' + item.margin.top * 2 + 'rpx' + ';';
item.pageStyle += 'padding-bottom:' + item.margin.bottom * 2 + 'rpx' + ';';
item.pageStyle += 'padding-right:' + item.margin.both * 2 + 'rpx' + ';';
item.pageStyle += 'padding-left:' + item.margin.both * 2 + 'rpx' + ';';
}
if (item.componentName == 'Search') {
item.pageStyle +=
'position: sticky;top:0;padding-top: var(--status-bar-height); background: #f7f7f7;z-index: 999;'
// background: linear-gradient(#ceebfa, #ceebfa, #f7f7f7);'
}
});
},
//
refresh(data) {
this.diyGlobalData = {}; //
setTimeout(() => {
this.diyGlobalData = data;
this.setPagestyle();
}, 1);
},
dealData() {
if (Array.isArray(this.diyData.value)) {
for (var i = 0; i < this.diyData.value.length; i++) {
if (this.diyData.value[i].componentName == 'StoreShow') {
this.showStore = true;
}
}
}
},
getHomeIndexList() {
this.$api.sendRequest({
url: '/api/goodssku/homeIndexList',
success: res => {
this.manyGoodsListData = res.data
console.log(this.manyGoodsListData);
},
fail: err => {
}
})
},
}
};
</script>
<style lang="scss">
.diy-group {
width: 100%;
}
:has(.box) {
z-index: 999 !important;
}
// .diy-goods-level-wrap {
// position: relative;
// height: 60vh;
// }
</style>

416
components/diy-components/diy-groupbuy.vue

@ -0,0 +1,416 @@
<template>
<view class="diy-groupbuy" v-if="list.length" :class="[value.template, value.style]" :style="warpCss">
<template v-if="value.template == 'row1-of1'">
<view class="item" v-for="(item, index) in list" :key="index" @click="toDetail(item)" :class="[value.ornament.type]" :style="goodsItemCss">
<view class="img-wrap" :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }">
<image :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }" :src="$util.img(item.goods_image,{size: 'mid'})" mode="widthFix" @error="imageError(index)"></image>
</view>
<view class="content" v-if="value.goodsNameStyle.control || value.priceStyle.mainControl || value.priceStyle.lineControl || value.btnStyle.control">
<view
v-if="value.goodsNameStyle.control"
class="goods-name"
:style="{ color: value.theme == 'diy' ? value.goodsNameStyle.color : '', fontWeight: value.goodsNameStyle.fontWeight ? 'bold' : '' }"
:class="[{ 'using-hidden': value.nameLineMode == 'single' }, { 'multi-hidden': value.nameLineMode == 'multiple' }]"
>
{{ item.goods_name }}
</view>
<view class="discount-price" v-if="value.priceStyle.mainControl">
<text class="unit price-style small" :style="{ color: value.theme == 'diy' ? value.priceStyle.mainColor +'!important' : '' }">¥</text>
<text class="price price-style large" :style="{ color: value.theme == 'diy' ? value.priceStyle.mainColor +'!important' : '' }">{{ item.groupbuy_price.split(".")[0] }}</text>
<text class="unit price-style small" :style="{ color: value.theme == 'diy' ? value.priceStyle.mainColor +'!important' : '' }">{{ "."+item.groupbuy_price.split(".")[1] }}</text>
</view>
<button
v-if="value.btnStyle.control"
:style="{
background: value.btnStyle.theme == 'diy' ? 'linear-gradient(to right,' + value.btnStyle.bgColorStart + ',' + value.btnStyle.bgColorEnd + ')' : '',
color: value.btnStyle.theme == 'diy' ? value.btnStyle.textColor : '',
borderRadius: value.btnStyle.aroundRadius * 2 + 'rpx'
}"
>
{{ value.btnStyle.text }}
</button>
</view>
</view>
</template>
<template v-if="value.template == 'horizontal-slide'">
<scroll-view v-if="value.slideMode == 'scroll'" class="scroll" :scroll-x="true" :show-scrollbar="false">
<view class="item" v-for="(item, index) in list" :key="index" @click="toDetail(item)" :class="[value.ornament.type]" :style="goodsItemCss">
<view class="img-wrap" :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }">
<image :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }" :src="$util.img(item.goods_image,{size: 'mid'})" mode="widthFix" @error="imageError(index)"></image>
<image class="bg" v-if="value.saleStyle.control" :src="$util.img('public/uniapp/groupbuy/bg.png')" mode="widthFix"></image>
<view class="num" v-if="value.saleStyle.control" :style="{ color: value.theme == 'diy' ? value.saleStyle.color : '' }">已团{{ item.sell_num }}</view>
</view>
<view :class="['content', { 'multi-content': value.nameLineMode == 'multiple' }]" v-if="value.goodsNameStyle.control || value.priceStyle.mainControl || value.priceStyle.lineControl">
<view
v-if="value.goodsNameStyle.control"
class="goods-name"
:style="{ color: value.theme == 'diy' ? value.goodsNameStyle.color : '', fontWeight: value.goodsNameStyle.fontWeight ? 'bold' : '' }"
:class="[{ 'using-hidden': value.nameLineMode == 'single' }, { 'multi-hidden': value.nameLineMode == 'multiple' }]"
>
{{ item.goods_name }}
</view>
<view class="discount-price" v-if="value.priceStyle.mainControl">
<text class="unit price-style small" :style="{ color: value.theme == 'diy' ? value.priceStyle.mainColor +'!important': '' }">¥</text>
<text class="price price-style large" :style="{ color: value.theme == 'diy' ? value.priceStyle.mainColor +'!important' : '' }">{{ item.groupbuy_price.split(".")[0] }}</text>
<text class="unit price-style small" :style="{ color: value.theme == 'diy' ? value.priceStyle.mainColor +'!important' : '' }">{{ "."+item.groupbuy_price.split(".")[1] }}</text>
</view>
<view class="original-price price-font" v-if="value.priceStyle.lineControl" :style="{ color: value.theme == 'diy' ? value.priceStyle.lineColor : '' }">
¥{{ item.price }}
</view>
</view>
</view>
</scroll-view>
<swiper v-if="value.slideMode == 'slide'" :autoplay="false" class="swiper" :style="{ height: swiperHeight }">
<swiper-item v-for="(pageItem,pageIndex) in page" :key="pageIndex" :class="['swiper-item', [list[pageIndex].length / 3] >= 1 && 'flex-between']">
<view class="item" v-for="(item, dataIndex) in list[pageIndex]" :key="dataIndex" @click="toDetail(item)" :class="[value.ornament.type]" :style="goodsItemCss">
<view class="img-wrap" :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }">
<image
:style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }"
:src="$util.img(item.goods_image,{size: 'mid'})"
mode="widthFix"
@error="imageError(dataIndex)"
></image>
<image class="bg" v-if="value.saleStyle.control" :src="$util.img('public/uniapp/groupbuy/bg.png')" mode="widthFix"></image>
<view class="num" v-if="value.saleStyle.control" :style="{ color: value.theme == 'diy' ? value.saleStyle.color : '' }">已团{{ item.sell_num }}</view>
</view>
<view :class="['content', { 'multi-content': value.nameLineMode == 'multiple' }]" v-if="value.goodsNameStyle.control || value.priceStyle.mainControl || value.priceStyle.lineControl">
<view
v-if="value.goodsNameStyle.control"
class="goods-name"
:style="{ color: value.theme == 'diy' ? value.goodsNameStyle.color : '', fontWeight: value.goodsNameStyle.fontWeight ? 'bold' : '' }"
:class="[{ 'using-hidden': value.nameLineMode == 'single' }, { 'multi-hidden': value.nameLineMode == 'multiple' }]"
>
{{ item.goods_name }}
</view>
<view class="discount-price" v-if="value.priceStyle.mainControl">
<text class="unit price-style small" :style="{ color: value.theme == 'diy' ? value.priceStyle.mainColor +'!important' : '' }">¥</text>
<text class="price price-style large" :style="{ color: value.theme == 'diy' ? value.priceStyle.mainColor +'!important' : '' }">{{ item.groupbuy_price.split(".")[1] }}</text>
<text class="unit price-style small" :style="{ color: value.theme == 'diy' ? value.priceStyle.mainColor +'!important' : '' }">{{ "."+item.groupbuy_price.split(".")[1] }}</text>
</view>
<view class="original-price price-font" v-if="value.priceStyle.lineControl" :style="{ color: value.theme == 'diy' ? value.priceStyle.lineColor : '' }">
¥{{ item.price }}
</view>
</view>
</view>
</swiper-item>
</swiper>
</template>
</view>
</template>
<script>
export default {
name: 'diy-groupbuy',
props: {
value: {
type: Object
}
},
data() {
return {
list: [],
page: 1
};
},
created() {
this.getData();
},
computed: {
warpCss() {
var obj = '';
obj += 'background-color:' + this.value.componentBgColor + ';';
if (this.value.componentAngle == 'round') {
obj += 'border-top-left-radius:' + this.value.topAroundRadius * 2 + 'rpx;';
obj += 'border-top-right-radius:' + this.value.topAroundRadius * 2 + 'rpx;';
obj += 'border-bottom-left-radius:' + this.value.bottomAroundRadius * 2 + 'rpx;';
obj += 'border-bottom-right-radius:' + this.value.bottomAroundRadius * 2 + 'rpx;';
}
return obj;
},
//
goodsItemCss() {
var obj = '';
obj += 'background-color:' + this.value.elementBgColor + ';';
if (this.value.elementAngle == 'round') {
obj += 'border-top-left-radius:' + this.value.topElementAroundRadius * 2 + 'rpx;';
obj += 'border-top-right-radius:' + this.value.topElementAroundRadius * 2 + 'rpx;';
obj += 'border-bottom-left-radius:' + this.value.bottomElementAroundRadius * 2 + 'rpx;';
obj += 'border-bottom-right-radius:' + this.value.bottomElementAroundRadius * 2 + 'rpx;';
}
if (this.value.ornament.type == 'shadow') {
obj += 'box-shadow:' + '0 0 10rpx ' + this.value.ornament.color + ';';
}
if (this.value.ornament.type == 'stroke') {
obj += 'border:' + '2rpx solid ' + this.value.ornament.color + ';';
}
const screenWidth = uni.getSystemInfoSync().safeArea.width || uni.getSystemInfoSync().screenWidth;
if(this.value.template == 'horizontal-slide'){
var width = "";
if(this.value.slideMode == 'scroll' && this.value.goodsMarginType=='diy')
width = this.rpxUpPx(this.value.goodsMarginNum*2);
else
width = [screenWidth - (this.rpxUpPx(20)*2) - (this.rpxUpPx(200)*3) - (this.rpxUpPx(this.value.margin.both*2)*2)]/6;
obj += 'margin-left:' + width + "px;";
obj += 'margin-right:' + width + "px;";
}
return obj;
},
swiperHeight() {
if (this.value.nameLineMode == 'multiple')
return this.value.ornament.type == 'shadow' ? '404rpx': '392rpx';
return this.value.ornament.type == 'shadow' ? '376rpx': '368rpx';
}
},
methods: {
rpxUpPx(res){
const screenWidth = uni.getSystemInfoSync().safeArea.width || uni.getSystemInfoSync().screenWidth;
var data = screenWidth * parseInt(res) / 750;
return Math.floor(data);
},
getData() {
var data = {
page: 1,
page_size: this.value.count
};
if (this.value.sources == 'diy') {
data.page_size = 0;
data.goods_id_arr = this.value.goodsId.toString();
}
this.$api.sendRequest({
url: '/groupbuy/api/goods/page',
data: data,
success: res => {
if (res.code == 0) {
this.list = res.data.list;
//
if (this.value.template == 'horizontal-slide' && this.value.slideMode == 'slide') {
let size = 3;
let temp = [];
this.page = Math.ceil(this.list.length / size);
for (var i = 0; i < this.page; i++) {
temp[i] = [];
for (var j = i * size; j < this.list.length; j++) {
if (temp[i].length == size) break;
temp[i].push(this.list[j]);
}
}
this.list = temp;
}
}
}
});
},
toDetail(e) {
this.$util.redirectTo('/pages_promotion/groupbuy/detail', {
groupbuy_id: e.groupbuy_id
});
},
imageError(index) {
this.list[index].goods_image = this.$util.getDefaultImage().goods;
this.$forceUpdate();
}
}
};
</script>
<style lang="scss">
/deep/.uni-scroll-view ::-webkit-scrollbar {
/* 隐藏滚动条,但依旧具备可以滚动的功能 */
display: none;
width: 0;
height: 0;
color: transparent;
background: transparent;
}
/deep/::-webkit-scrollbar {
display: none;
width: 0;
height: 0;
color: transparent;
background: transparent;
}
scroll-view ::-webkit-scrollbar {
width: 0;
height: 0;
background-color: transparent;
touch-action: none;
}
.diy-groupbuy {
&.row1-of1 {
.item {
display: flex;
margin-bottom: 20rpx;
padding: 16rpx;
&.shadow {
margin: 8rpx 8rpx 20rpx 8rpx;
}
&:last-child {
margin-bottom: 0;
padding-bottom: 20rpx;
}
.img-wrap {
width: 200rpx;
height: 200rpx;
> image {
width: 200rpx;
}
}
.goods-name{
margin-top: 6rpx;
line-height: 1.5;
}
.content {
flex: 1;
margin-left: 20rpx;
position: relative;
.discount-price {
white-space: nowrap;
font-weight: bold;
position: absolute;
bottom: 20rpx;
left: 0;
display: flex;
align-items: baseline;
line-height: 1;
.unit {
font-size: $font-size-tag;
margin-right: 4rpx;
color: $base-color;
}
.price {
font-size: $font-size-toolbar;
color: $base-color;
}
}
button {
position: absolute;
bottom: 10rpx;
right: 20rpx;
margin: 0;
padding: 0 20rpx;
background-color: $base-color;
color: #fff;
min-width: 112rpx;
height: 52rpx;
line-height: 52rpx;
font-size: $font-size-tag;
}
}
}
}
&.horizontal-slide {
.scroll {
width: calc(100% - 40rpx);
padding: 20rpx;
line-height: 1;
white-space: nowrap;
.item.shadow {
margin-bottom: 8rpx;
}
}
.flex-between {
justify-content: space-between;
}
.item {
display: inline-block;
width: 200rpx;
overflow: hidden;
box-sizing: border-box;
&:nth-child(3n+3){
width: 198rpx;
}
&.shadow {
margin-top: 8rpx;
}
.img-wrap {
width: 200rpx;
height: 200rpx;
position: relative;
overflow: hidden;
margin: 0 auto;
> image {
width: 200rpx;
}
.bg {
position: absolute;
width: 100%;
height: 60rpx;
bottom: 0;
left: 0;
z-index: 2;
}
.num {
width: 180rpx;
position: absolute;
bottom: 10rpx;
padding-left: 20rpx;
font-size: 20rpx;
line-height: 1;
color: #ffffff;
z-index: 3;
}
}
.content {
padding: 10rpx;
display: flex;
flex-direction: column;
justify-content: space-between;
&.multi-content{
height: 158rpx;
box-sizing: border-box;
}
.goods-name {
line-height: 1.3;
&.using-hidden{
display: block;
}
&.multi-hidden {
white-space: break-spaces;
}
}
.discount-price {
white-space: nowrap;
margin-top: auto;
font-weight: bold;
line-height: 1;
.unit {
font-size: $font-size-tag;
margin-right: 4rpx;
color: $base-color;
}
.price {
font-size: $font-size-toolbar;
color: $base-color;
}
}
.original-price {
font-size: $font-size-tag;
color: $color-tip;
line-height: 1;
text-decoration: line-through;
}
}
}
.swiper {
width: 100%;
white-space: nowrap;
padding: 20rpx;
box-sizing: border-box;
.swiper-item{
display: flex;
align-items: center;
}
.item {
width: 200rpx;
}
}
}
}
</style>

36
components/diy-components/diy-horz-blank.vue

@ -0,0 +1,36 @@
<template>
<view :style="horzBlankGaugeWrap"></view>
</template>
<script>
//
export default {
name: 'diy-horz-blank',
props: {
value: {
type: Object
}
},
data() {
return {};
},
computed: {
horzBlankGaugeWrap: function() {
var obj = '';
obj += 'background-color:' + this.value.componentBgColor + ';';
if (this.value.componentAngle == 'round') {
obj += 'border-top-left-radius:' + this.value.topAroundRadius * 2 + 'rpx;';
obj += 'border-top-right-radius:' + this.value.topAroundRadius * 2 + 'rpx;';
obj += 'border-bottom-left-radius:' + this.value.bottomAroundRadius * 2 + 'rpx;';
obj += 'border-bottom-right-radius:' + this.value.bottomAroundRadius * 2 + 'rpx;';
}
obj += 'height:' + this.value.height * 2 + 'rpx';
return obj;
}
},
created() {},
methods: {}
};
</script>
<style></style>

21
components/diy-components/diy-horz-line.vue

@ -0,0 +1,21 @@
<template>
<view :style="{ borderTop: '2rpx ' + value.borderStyle + ' ' + value.color }"></view>
</template>
<script>
// 线
export default {
name: 'diy-horz-line',
props: {
value: {
type: Object
}
},
data() {
return {};
},
methods: {}
};
</script>
<style></style>

84
components/diy-components/diy-icon.vue

@ -0,0 +1,84 @@
<template>
<view class="diy-icon" :style="iconBgStyle">
<text class="js-icon" :class="iconClass" :style="iconStyle"></text>
</view>
</template>
<script>
export default {
name: 'diy-icon',
props: {
icon: {
type: String,
default: ''
},
value: {
type: Object,
default: function () {
return null;
}
}
},
computed: {
iconClass(){
var _class = ' ' + this.icon;
if (this.value && this.value.iconColor.length > 1) _class += ' gradient';
return _class;
},
iconBgStyle(){
if (!this.value) return {};
var style = {
'border-radius': this.value.bgRadius + '%',
'background': ''
};
if (this.value.iconBgImg) style['background'] += 'url('+ this.$util.img(this.value.iconBgImg) +') no-repeat bottom / contain'
if (this.value.iconBgColor.length) {
if (style.background) style.background += ',';
if (this.value.iconBgColor.length == 1) {
style.background += this.value.iconBgColor[0];
} else {
style['background'] += 'linear-gradient('+ this.value.iconBgColorDeg +'deg, '+ this.value.iconBgColor.join(',') +')';
}
}
return this.$util.objToStyle(style);
},
iconStyle(){
if (!this.value) return {};
var style = {
'font-size': this.value.fontSize + '%'
}
if (this.value.iconColor.length == 1) {
style.color = this.value.iconColor[0];
} else {
style['background'] = 'linear-gradient('+ this.value.iconColorDeg +'deg, '+ this.value.iconColor.join(',') +')';
}
return this.$util.objToStyle(style);
}
}
}
</script>
<style lang="scss">
.diy-icon {
width: 100%;
height: 100%;
font-size: 100%;
color: #000;
display: flex;
align-items: center;
justify-content: center;
.js-icon {
font-size: 50%;
line-height:1;
padding: 1rpx;
&.gradient {
-webkit-background-clip:text!important;
-webkit-text-fill-color:transparent;
}
}
}
</style>

356
components/diy-components/diy-img-ads.vue

@ -0,0 +1,356 @@
<template>
<view class="single-graph">
<view :style="imgAdsMarginWarp" class="swiper-box">
<!-- <block v-if="imgAdsValue.list.length == 1">
<view class="simple-graph-wrap" :style="imgAdsSwiper" @click="goAdsItem(imgAdsValue.list[0])">
<image :style="{ height: imgAdsValue.list[0].imgHeight }"
:src="$util.img(imgAdsValue.list[0].imageUrl)" mode="widthFix"></image>
<view v-if="imgAdsValue.list[0].heatMapData">
<view class="heat-map" v-for="(mapItem, mapIndex) in imgAdsValue.list[0].heatMapData"
:key="mapIndex" :style="{
width: mapItem.width + '%',
height: mapItem.height + '%',
left: mapItem.left + '%',
top: mapItem.top + '%'
}" @click.stop="$util.diyRedirectTo(mapItem.link)"></view>
</view>
</view>
</block> v-else -->
<swiper class="swiper" :style="{ height: swiperHeight }" :class="{
'swiper-left': imgAdsValue.indicatorLocation == 'left',
'swiper-right': imgAdsValue.indicatorLocation == 'right',
'ns-indicator-dots': imgAdsValue.carouselStyle == 'line'
}" circular="true" :indicator-dots="isDots" indicator-color="rgba(130, 130, 130, .5)"
:indicator-active-color="imgAdsValue.indicatorColor" @change="swiperChange">
<swiper-item class="swiper-item" :style="imgAdsSwiper" v-for="(item, index) in imgAdsValue.list" :key="index"
v-if="item.imageUrl" @click="goAdsItem(item)">
<view class="item" style="display: flex;">
<image :style="{ with: item.imgWidth + 'rpx', height: item.imgHeight + 'rpx' }" :src="$util.img(item.imageUrl)"
mode="scaleToFill"></image>
<!-- <img :src="$util.img(item.imageUrl)" alt="" /> -->
<!-- 热区功能 -->
<view v-if="item.heatMapData">
<view class="heat-map" v-for="(mapItem, mapIndex) in item.heatMapData" :key="mapIndex" :style="{
width: mapItem.width + '%',
height: mapItem.height + '%',
left: mapItem.left + '%',
top: mapItem.top + '%'
}" @click.stop="$util.diyRedirectTo(mapItem.link)"></view>
</view>
</view>
</swiper-item>
</swiper>
<!-- #ifdef MP-WEIXIN || MP-ALIPAY -->
<view v-if="imgAdsValue.list.length > 1" :class="[
'swiper-dot-box',
{ straightLine: imgAdsValue.carouselStyle == 'line' },
{ 'swiper-left': imgAdsValue.indicatorLocation == 'left' },
{ 'swiper-right': imgAdsValue.indicatorLocation == 'right' }
]">
<view v-for="(numItem, numIndex) in imgAdsValue.list.length" :key="numIndex"
:class="['swiper-dot', { active: numIndex == swiperIndex }]"
:style="[numIndex == swiperIndex && { backgroundColor: imgAdsValue.indicatorColor }]"></view>
</view>
<!-- #endif -->
</view>
</view>
</template>
<script>
export default {
name: 'diy-img-ads',
props: {
value: {
type: Object,
default: () => {
return {};
}
}
},
data() {
return {
isDots: true,
swiperHeight: 0,
imgAdsValue: null, //
swiperIndex: 0
};
},
created() {
this.calcSingleRow();
},
computed: {
imgAdsMarginWarp: function () {
var obj = '';
obj = 'background-color:' + this.value.componentBgColor + ';';
return obj;
},
imgAdsSwiper: function () {
var obj = '';
if (this.value.componentAngle == 'round') {
obj += 'border-top-left-radius:' + this.value.topAroundRadius * 2 + 'rpx;';
obj += 'border-top-right-radius:' + this.value.topAroundRadius * 2 + 'rpx;';
obj += 'border-bottom-left-radius:' + this.value.bottomAroundRadius * 2 + 'rpx;';
obj += 'border-bottom-right-radius:' + this.value.bottomAroundRadius * 2 + 'rpx;';
}
return obj;
},
singleGraphBg: function () {
var imgArr = [];
for (let i = 0; i < this.imgAdsValue.list.length; i++) {
let item = this.imgAdsValue.list[i];
imgArr[i] = parseFloat(item.imgHeight);
}
imgArr.sort(function (a, b) {
return b - a;
});
var obj = '';
obj += 'background-color:' + this.imgAdsValue.backgroundColor + ';';
obj += 'height:' + imgArr[0] * (this.imgAdsValue.backgroundHeight / 100) * 2 + 'rpx;';
return obj;
}
},
methods: {
swiperChange(e) {
this.swiperIndex = e.detail.current;
},
goAdsItem(item) {
console.log(item);
if (item.adv_id > 0) {
this.advpoint(item.adv_id)
}
this.$util.diyRedirectTo(item.link)
},
advpoint(adv_id) {
this.$api.sendRequest({
url: '/api/adv/advpoint',
data: {
adv_id,
},
success: res => {
}
})
},
calcSingleRow() {
let maxHeight = 0;
//
this.imgAdsValue = JSON.parse(JSON.stringify(this.value));
this.imgAdsValue.list.forEach((item, index) => {
uni.getSystemInfo({
success: res => {
// // #ifdef MP-ALIPAY
// let numH = item.imgHeight.slice(0, -3)
// var ratio = numH / item.imgWidth;
// item.imgWidth = res.windowWidth;
// item.imgWidth -= this.value.margin.both * 2;
// item.imgHeight = item.imgWidth * ratio + "rpx";
// // #endif
// // #ifndef MP-ALIPAY
// var ratio = item.imgHeight / item.imgWidth;
// item.imgWidth = res.windowWidth;
// item.imgWidth -= this.value.margin.both * 2;
// item.imgHeight = item.imgWidth * ratio;
// // #endif
// // 750 * 350
item.imgWidth = 750 - this.value.margin.both * 2
item.imgHeight = 350 * (item.imgWidth / 750)
this.swiperHeight = item.imgHeight + 'rpx';
}
});
//
if (maxHeight == 0 || maxHeight < item.imgHeight) {
maxHeight = item.imgHeight;
}
});
// this.imgAdsValue.list.forEach((item, index) => {
// item.imgHeight = maxHeight * 2 + 'rpx';
// this.swiperHeight = maxHeight * 2 + 'rpx';
// });
this.imgAdsValue.indicatorColor = this.imgAdsValue.indicatorColor || '#fff';
//
if (this.imgAdsValue.list.length <= 1) {
this.isDots = false;
}
// #ifdef MP-WEIXIN || MP-ALIPAY
this.isDots = false;
// #endif
}
}
};
</script>
<style lang="scss" scoped>
.single-graph {
width: 100%;
line-height: 0;
display: flex;
justify-content: center;
flex-direction: column;
align-items: center;
box-sizing: border-box;
}
.simple-graph-wrap {
line-height: 0;
overflow: hidden;
position: relative;
image {
width: 100%;
}
.heat-map {
position: absolute;
}
}
.item.active text {
background: rgba(0, 0, 0, 0.3);
position: absolute;
bottom: 0;
color: #ffffff;
font-size: $font-size-tag;
width: 100%;
left: 0;
line-height: 40rpx;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
padding: 0 10rpx;
text-align: center;
}
.swiper-box {
position: relative;
width: 100%;
overflow: hidden;
box-sizing: border-box;
}
.swiper {
margin: 0 auto;
overflow: hidden;
}
.swiper-item {
width: 100%;
height: auto !important;
display: flex;
justify-content: center;
flex-direction: column;
position: relative;
.item {
width: 100%;
height: auto;
text-align: center;
position: relative;
overflow: hidden;
image {
width: 100%;
max-width: 100%;
height: 100%;
}
.heat-map {
position: absolute;
}
}
}
.swiper-dot-box {
position: absolute;
bottom: 20rpx;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
padding: 0 40rpx 8rpx;
box-sizing: border-box;
&.swiper-left {
justify-content: flex-start;
}
&.swiper-right {
justify-content: flex-end;
}
.swiper-dot {
background-color: #b2b2b2;
width: 15rpx;
border-radius: 50%;
height: 15rpx;
margin: 8rpx;
&.active {
background-color: rgba(0, 0, 0, 1);
}
}
&.straightLine {
.swiper-dot {
width: 18rpx;
height: 6rpx;
border-radius: 4rpx;
&.active {
width: 36rpx;
background-color: rgba(0, 0, 0, 1);
}
}
}
}
/* 隐藏滚动条,但依旧具备可以滚动的功能 */
/deep/.uni-scroll-view::-webkit-scrollbar {
display: none;
}
.swiper /deep/ .uni-swiper-dots-horizontal {
bottom: 25rpx;
}
.swiper-left /deep/ .uni-swiper-dots-horizontal {
left: 40rpx;
transform: translate(0);
}
.swiper-right /deep/ .uni-swiper-dots-horizontal {
right: 40rpx;
display: flex;
justify-content: flex-end;
transform: translate(0);
}
.carousel-angle /deep/ .uni-swiper-dots-horizontal .uni-swiper-dot {
width: 24rpx;
border-radius: 0;
height: 8rpx;
}
.swiper /deep/ .swiper-item .item uni-image>div {
background-size: cover !important;
}
.swiper.ns-indicator-dots /deep/ .uni-swiper-dot {
width: 18rpx;
height: 6rpx;
border-radius: 4rpx;
}
.swiper.ns-indicator-dots /deep/ .uni-swiper-dot-active {
width: 36rpx;
}
</style>

692
components/diy-components/diy-index-page.vue

@ -0,0 +1,692 @@
<template>
<scroll-view scroll-y="true" :style="{ height: scrollHeight }" @scroll="scroll" :scroll-top="scrollTop" @scrolltolower="scrolltolower">
<view class="bg" :style="warpCss">
<view class="nav_top_category">
<scroll-view class="diyIndex widthAuto" @click="changePageIndex(0)">
<view
class="item text-fiexd"
:class="{ fill: value.styleType == 'fill' }"
:style="{ background: pageIndex == 0 && value.styleType == 'fill' ? value.selectColor : '' }"
>
<view
class="text-con"
:class="pageIndex == 0 ? 'active' : ''"
:style="{
color: index == pageIndex ? '' : value.noColor
}"
v-if="value.styleType == 'fill'"
>
{{ cateList[0].short_name ? cateList[0].short_name : cateList[0].category_name }}
</view>
<view
class="text-con"
:class="pageIndex == 0 ? 'active' : ''"
:style="{
color: pageIndex == 0 ? value.selectColor : value.noColor
}"
v-else
>
{{ cateList[0].short_name ? cateList[0].short_name : cateList[0].category_name }}
</view>
<view
class="color-base-bg line"
v-if="pageIndex == 0 && value.styleType != 'fill'"
:style="{ background: value.selectColor ? value.selectColor + '!important' : 'rgba(0,0,0,0)' + '!important' }"
></view>
</view>
</scroll-view>
<scroll-view
v-if="value"
scroll-with-animation
class="diyIndex"
scroll-x="true"
:scroll-into-view="'a' + pageIndex"
:style="{ background: value.backgroundColor ? value.backgroundColor : '', width: 'calc(100% - 102rpx)' }"
>
<view
class="item"
:id="'a' + index"
v-for="(item, index) in cateList"
:key="index"
@click="changePageIndex(index)"
:class="{ fill: value.styleType == 'fill' }"
:style="{ background: index == pageIndex && value.styleType == 'fill' ? value.selectColor : '' }"
v-if="index > 0"
>
<view
class="text-con"
:class="index == pageIndex ? 'active' : ''"
:style="{
color: index == pageIndex ? '' : value.noColor
}"
v-if="value.styleType == 'fill'"
>
{{ item.short_name ? item.short_name : item.category_name }}
</view>
<view
class="text-con"
:class="index == pageIndex ? 'active' : ''"
:style="{
color: index == pageIndex ? value.selectColor : value.noColor
}"
v-else
>
{{ item.short_name ? item.short_name : item.category_name }}
</view>
<view
class="color-base-bg line"
v-if="index == pageIndex && value.styleType != 'fill'"
:style="{ background: value.selectColor ? value.selectColor + '!important' : 'rgba(0,0,0,0)' + '!important' }"
></view>
</view>
</scroll-view>
</view>
<view class="index-page-content" :style="{ height: scrollTopHeight }">
<block v-if="pageIndex == 0"><slot></slot></block>
<block v-else>
<view class="index-category-box">
<!-- 二级分类 -->
<view class="twoCategorylist" v-if="twoCategorylist != 'undefined' && twoCategorylist && twoCategorylist.length > 0">
<view class="twoCategory min" v-if="twoCategorylist.length <= 5">
<view class="twoCategory-page">
<view class="swiper-item" v-for="(item, index) in twoCategorylist" :key="index" @click="toCateGoodsList(item.category_id_2, 2)">
<view class="item-box">
<image :src="$util.img(item.image)" v-if="item.image" mode="aspectFill"></image>
<image :src="$util.getDefaultImage().goods" v-else mode="aspectFill"></image>
<view>{{ item.category_name }}</view>
</view>
</view>
</view>
</view>
<view class="twoCategory base" v-if="twoCategorylist.length > 5 && twoCategorylist.length <= 10">
<view class="twoCategory-page">
<view class="swiper-item" v-for="(item, index) in twoCategorylist" :key="index" @click="toCateGoodsList(item.category_id_2, 2)">
<view class="item-box">
<image :src="$util.img(item.image)" v-if="item.image" mode="aspectFill"></image>
<image :src="$util.getDefaultImage().goods" v-else mode="aspectFill"></image>
<view>{{ item.category_name }}</view>
</view>
</view>
</view>
</view>
<swiper class="twoCategory big" :duration="500" v-if="twoCategorylist.length > 10" @change="swiperTocategoryChange">
<swiper-item class="twoCategory-page" v-for="page in maxPage" :key="page">
<view
class="swiper-item"
v-for="(item, index) in twoCategorylist"
:key="index"
v-if="index >= (page - 1) * 10 && index < page * 10"
@click="toCateGoodsList(item.category_id_2, 2)"
>
<view class="item-box">
<image :src="item.image" mode="aspectFill"></image>
<view>{{ item.category_name }}</view>
</view>
</view>
</swiper-item>
</swiper>
<view class="dot-box">
<view
class="dot-item"
v-for="page in maxPage"
v-if="maxPage > 1"
:key="page"
:class="twoCategorylistId == page - 1 ? 'active color-base-bg' : ''"
></view>
</view>
</view>
<!-- 分类广告 -->
<image class="category_adv ns-margin" v-if="cateList[pageIndex].image_adv" :src="$util.img(cateList[pageIndex].image_adv)" mode="widthFix"></image>
<view class="category-goods" v-show="!isloading">
<view class="goods-list double-column" v-if="goodsList[pageIndex].list.length">
<view class="goods-item" v-for="(item, index) in goodsList[pageIndex].list" :key="index" @click="toDetail(item)">
<view class="goods-img">
<image :src="goodsImg(item.goods_image)" mode="widthFix" @error="imgError(index)"></image>
<view class="color-base-bg goods-tag" v-if="value.goodsTag == 'default' && goodsTag(item) != ''">{{ goodsTag(item) }}</view>
<view class="goods-tag-img" v-if="value.goodsTag == 'diy'"><image :src="$util.img(value.tagImg.imageUrl)" mode=""></image></view>
</view>
<view class="info-wrap">
<view class="name-wrap">
<view class="goods-name">{{ item.goods_name }}</view>
</view>
<view class="pro-info">
<view class="delete-price font-size-activity-tag color-tip">
<text class="unit">{{ $lang('common.currencySymbol') }}</text>
{{ item.market_price > 0 ? item.market_price : item.price }}
</view>
<view class="sale font-size-activity-tag color-tip">已售{{ item.sale_num }}{{ item.unit ? item.unit : '件' }}</view>
</view>
<view class="lineheight-clear">
<view class="discount-price">
<text class="unit color-base-text font-size-tag">{{ $lang('common.currencySymbol') }}</text>
<text class="price color-base-text font-size-toolbar">{{ showPrice(item) }}</text>
</view>
<view class="member-price-tag" v-if="item.member_price && item.member_price == showPrice(item)">
<image :src="$util.img('public/uniapp/index/VIP.png')" mode="widthFix"></image>
</view>
<view class="member-price-tag" v-else-if="item.promotion_type == 1">
<image :src="$util.img('public/uniapp/index/discount.png')" mode="widthFix"></image>
</view>
</view>
</view>
</view>
</view>
<ns-empty v-else-if="!isloading" :isIndex="false" text="该分类下暂无商品"></ns-empty>
</view>
<view class="loading" v-show="isloading"><ns-loading ref="loading"></ns-loading></view>
</view>
</block>
</view>
</view>
</scroll-view>
</template>
<script>
import nsLoading from '@/components/ns-loading/ns-loading.vue';
export default {
props: {
value: {
type: Object
},
scrollHeight: {
type: String
},
scrollTopHeight: {
type: String
},
bgUrl: {
type: String
}
},
components: {
nsLoading
},
data() {
return {
pageIndex: 0, //id
cateList: [
{
//header
category_name: '首页'
}
],
twoCategorylist: [], //
twoCategorylistId: 0, //swiper
goodsList: {},
scrollTop: 0,
scrollTopCopy: 0,
isloading: true
};
},
computed: {
warpCss() {
var obj = '';
obj += 'background-color:' + this.value.componentBgColor + ';';
obj += this.bgUrl ? 'background:' + 'url(' + this.$util.img(this.bgUrl) + ') no-repeat 0 0/100%' : '';
return obj;
},
maxPage() {
let num = 0;
if (this.twoCategorylist && this.twoCategorylist.length) {
num = Math.ceil(this.twoCategorylist.length / 10);
}
return num;
},
type() {
if (this.value) {
return true;
} else {
return false;
}
}
},
watch: {
type(newVal, oldVal) {
if (newVal) {
this.getCategoryList();
}
}
},
mounted() {
this.getCategoryList();
},
methods: {
initPageIndex() {
this.pageIndex = 0;
},
//
getCategoryList() {
let url = '/api/goodscategory/tree';
let data = {
level: 3,
template: 2
};
this.$api.sendRequest({
url: url,
data: data,
success: res => {
if (res.code >= 0) {
let arr = [];
let obj = {
list: [],
isAll: false
};
obj.category_name = this.value.title ? this.value.title : '首页';
arr.push(obj);
this.cateList = arr.concat(res.data);
Object.keys(this.cateList).forEach((key, index) => {
this.goodsList[key] = {
page: 1,
list: [],
isAll: false
};
});
this.twoCategorylist = this.cateList[this.pageIndex].child_list;
}
}
});
},
//id
changePageIndex(e) {
this.isloading = true;
this.pageIndex = e;
if (e == 0) return;
this.twoCategorylist = this.cateList[this.pageIndex].child_list;
this.twoCategorylist = this.cateList[this.pageIndex].child_list;
if (this.cateList[this.pageIndex].child_list) {
this.twoCategorylist = this.cateList[this.pageIndex].child_list;
this.twoCategorylist.forEach(v => {
if (v.image) {
v.image = this.$util.img(v.image);
} else {
v.image = this.$util.getDefaultImage().goods;
}
});
} else {
this.twoCategorylist = false;
}
let id = e;
if (this.goodsList[id] && this.goodsList[id].length) return;
this.scrollTop = this.scrollTopCopy;
this.$nextTick(function() {
this.scrollTop = 0;
});
this.getGoodsList();
},
//swiper
swiperChange(e) {
this.changePageIndex(e.detail.current);
},
//
swiperTocategoryChange(e) {
this.twoCategorylistId = e.detail.current;
},
toDetail(item) {
this.$util.redirectTo('/page_goods/detail/detail', {
goods_id: item.goods_id
});
},
scroll(e) {
this.scrollTopCopy = e.detail.scrollTop;
},
getGoodsList() {
let id = this.pageIndex;
var data = {
page: this.goodsList[id].page,
page_size: 10
};
data.category_id = this.cateList[this.pageIndex].category_id_1;
data.category_level = 1;
this.$api.sendRequest({
url: '/api/goodssku/page',
data: data,
success: res => {
this.isloading = false;
if (res.code == 0 && res.data) {
this.goodsList[id].list = this.goodsList[id].list.concat(res.data.list);
if (this.goodsList[id].list.length == res.data.count) {
this.goodsList[id].isAll = true;
}
this.goodsList[id].page += 1;
}
this.$forceUpdate();
}
});
},
//
scrolltolower() {
let id = this.pageIndex;
if (this.goodsList[id].isAll) return;
this.isloading = true;
this.getGoodsList();
},
toCateGoodsList(e, f) {
this.$util.redirectTo('/page_goods/goodsList/goodsList', { category_id: e, category_level: f });
},
goodsImg(imgStr) {
let imgs = imgStr.split(',');
return imgs[0] ? this.$util.img(imgs[0], { size: 'mid' }) : this.$util.getDefaultImage().goods;
},
imgError(index) {
this.goodsList[index].goods_image = this.$util.getDefaultImage().goods;
},
showPrice(data) {
let price = data.discount_price;
if (data.member_price && parseFloat(data.member_price) < parseFloat(price)) price = data.member_price;
return price;
},
goodsTag(data) {
return data.label_name || '';
}
}
};
</script>
<style lang="scss">
.bg {
width: 100%;
height: 100%;
padding: 0 30rpx;
box-sizing: border-box;
}
.nav_top_category {
display: flex;
.text-fiexd {
.text-con {
line-height: 60rpx;
// &.active{
// line-height: 1.8;
// }
}
}
}
.diyIndex {
width: 100%;
height: 100rpx;
white-space: nowrap;
padding: 20rpx 0 0;
box-sizing: border-box;
&.widthAuto {
width: auto;
}
.item {
padding: 0 20rpx;
display: inline-block;
line-height: 80rpx;
font-size: $font-size-base;
text-align: center;
.text-con {
height: 60rpx;
line-height: 60rpx;
}
.text-con.active {
font-size: $font-size-toolbar;
font-weight: 600;
}
.line {
width: 100%;
height: 5rpx;
border-radius: 5rpx;
}
&.fill {
border-radius: 50rpx;
.text-con.active {
font-size: $font-size-base;
font-weight: 600;
color: #fff;
}
}
}
}
.index-page-box {
width: 100%;
height: calc(100vh - 288rpx);
}
.index-page-content {
width: 100%;
// height: calc(100vh - 144px);
}
.index-category-box.active {
padding-bottom: 160rpx;
padding-bottom: calc(160rpx + constant(safe-area-inset-bottom));
padding-bottom: calc(160rpx + env(safe-area-inset-bottom));
}
.index-category-box {
width: 100%;
padding-bottom: 110rpx;
padding-bottom: calc(110rpx + constant(safe-area-inset-bottom));
padding-bottom: calc(110rpx + env(safe-area-inset-bottom));
.twoCategorylist {
position: relative;
}
.twoCategory.min {
height: 160rpx;
}
.twoCategory.big {
height: 340rpx;
}
.twoCategory {
width: 100%;
background: #ffffff;
border-radius: 15rpx;
overflow: hidden;
margin-top: 20rpx;
.twoCategory-page {
width: 100%;
height: 100%;
padding: 20rpx;
box-sizing: border-box;
}
.swiper-item {
width: 120rpx;
height: 120rpx;
display: inline-block;
margin-right: calc((100% - 120rpx * 5) / 4);
overflow: hidden;
.item-box {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
image {
width: 88rpx;
height: 88rpx;
}
view {
width: 100%;
font-size: 22rpx;
line-height: 1;
margin-top: 10rpx;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 1;
overflow: hidden;
text-align: center;
}
}
}
.swiper-item:nth-child(5n) {
margin-right: 0;
}
.swiper-item:nth-child(10n + 6) {
margin-top: 15rpx;
}
}
.dot-box {
width: calc(100% - 40rpx);
height: 50rpx;
position: absolute;
bottom: 0rpx;
left: 20rpx;
background: rgba($color: #000000, $alpha: 0);
display: flex;
justify-content: center;
align-items: center;
.dot-item {
width: 12rpx;
height: 12rpx;
background: #cccccc;
border-radius: 6rpx;
margin-right: 10rpx;
}
.dot-item.active {
width: 24rpx;
}
}
.category_adv {
width: calc(100%);
margin-bottom: 0;
border-radius: 15rpx;
}
.category-goods {
width: 100%;
}
}
.loading {
width: 100%;
height: 50rpx;
}
/deep/.uni-scroll-view::-webkit-scrollbar {
/* 隐藏滚动条,但依旧具备可以滚动的功能 */
display: none;
}
.goods-list.double-column {
display: flex;
flex-wrap: wrap;
margin-top: $margin-updown;
.goods-item {
flex: 1;
position: relative;
background-color: #fff;
flex-basis: 48%;
max-width: calc((100% - 30rpx) / 2);
margin-right: $margin-both;
margin-bottom: $margin-updown;
border-radius: $border-radius;
&:nth-child(2n) {
margin-right: 0;
}
.goods-img {
position: relative;
overflow: hidden;
padding-top: 100%;
border-top-left-radius: $border-radius;
border-top-right-radius: $border-radius;
image {
width: 100%;
position: absolute;
top: 50%;
left: 0;
transform: translateY(-50%);
}
}
.goods-tag {
color: #fff;
line-height: 1;
padding: 8rpx 16rpx;
position: absolute;
border-bottom-right-radius: $border-radius;
top: 0;
left: 0;
font-size: $font-size-goods-tag;
}
.goods-tag-img {
position: absolute;
border-top-left-radius: $border-radius;
width: 80rpx;
height: 80rpx;
top: 0;
left: 0;
z-index: 5;
overflow: hidden;
image {
width: 100%;
height: 100%;
}
}
.info-wrap {
padding: 0 26rpx 26rpx 26rpx;
}
.goods-name {
font-size: $font-size-base;
line-height: 1.3;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
margin-top: 20rpx;
height: 68rpx;
}
.discount-price {
display: inline-block;
font-weight: bold;
line-height: 1;
margin-top: 16rpx;
.unit {
margin-right: 6rpx;
}
}
.pro-info {
display: flex;
margin-top: 16rpx;
.delete-price {
text-decoration: line-through;
flex: 1;
.unit {
margin-right: 6rpx;
}
}
& > view {
line-height: 1;
&:nth-child(2) {
text-align: right;
}
}
}
.member-price-tag {
display: inline-block;
width: 60rpx;
line-height: 1;
margin-left: 6rpx;
image {
width: 100%;
}
}
}
}
</style>

249
components/diy-components/diy-many-goods-list.vue

@ -0,0 +1,249 @@
<template>
<view class="many-goods-list">
<u-tabs class="utabs" @change="tabsChange" keyName="title" :list="value.list" :current="cateIndex"
lineColor="var(--base-color)" :activeStyle="{
color: '#303133',
fontWeight: 'bold',
transform: 'scale(1.15)'
}" :inactiveStyle="{
color: '#999',
transform: 'scale(1)'
}"></u-tabs>
<!-- <div style="height: 24rpx;"></div> -->
<!-- <scroll-view scroll-x="true" :scroll-into-view="'a' + cateIndex">
<view
v-for="(item, index) in value.list"
class="scroll-item"
:class="{ active: index == cateIndex }"
:id="'a' + index"
:key="index"
@click="changeCateIndex(item, index)"
>
<view class="item-wrap">
<view class="split-line" v-if="index > 0"></view>
<view class="cate">
<view class="name">{{ item.title }}</view>
<view class="desc" :class="{ 'color-base-bg': index == cateIndex && item.desc }">{{ item.desc }}</view>
</view>
</view>
</view>
</scroll-view>
-->
<diy-goods-list v-show="cateIndex==0" :value.sync="goodsValue0" ref="diyGoodsList0">
</diy-goods-list>
<!-- <diy-goods-list v-if="cateIndex==0" :value.sync="goodsValue0" ref="diyGoodsList0">
</diy-goods-list> -->
<diy-goods-list v-show="cateIndex==1" :value.sync="goodsValue1" ref="diyGoodsList1">
</diy-goods-list>
<diy-goods-list v-show="cateIndex==2" :value.sync="goodsValue2" ref="diyGoodsList2">
</diy-goods-list>
<diy-goods-list v-show="cateIndex==3" :value.sync="goodsValue3" ref="diyGoodsList3">
</diy-goods-list>
<diy-goods-list v-show="cateIndex==4" :value.sync="goodsValue4" ref="diyGoodsList4">
</diy-goods-list>
<diy-goods-list v-show="cateIndex==5" :value.sync="goodsValue5" ref="diyGoodsList5">
</diy-goods-list>
</view>
</template>
<script>
export default {
name: 'diy-many-goods-list',
props: {
value: {
type: Object,
default: () => {
return {};
}
},
},
data() {
return {
cateIndex: 0, // id
goodsValue0: null, //
goodsValue1: null,
goodsValue2: null,
goodsValue3: null,
goodsValue4: null,
goodsValue5: null,
};
},
created() {
this.goodsValue0 = this.value.list[0]
this.goodsValue1 = this.value.list[1]
this.goodsValue2 = this.value.list[2]
this.goodsValue3 = this.value.list[3]
this.goodsValue4 = this.value.list[4]
this.goodsValue5 = this.value.list[5]
console.log(this.value, '组件的总数据');
this.changeCateIndex(this.value.list[0], 0, true);
// this.changeCateIndex(this.value.list[0], 0);
},
mounted() {
// this.$nextTick(_ => {
// this.changeCateIndex(this.value.list[0], 0, true);
// })
},
methods: {
tabsChange(e) {
this.changeCateIndex(e, e.index, true);
},
changeCateIndex(item, index, isFirst) {
console.log(this.cateIndex, '之前的tab');
this.cateIndex = Number(item.newCategoryId) - 1;
console.log(this.cateIndex, '之后的tab');
this.goodsValue = {}
this["goodsValue" + index] = {
sources: item.sources,
categoryId: item.categoryId,
categoryName: item.categoryName,
newCategoryId: item.newCategoryId,
newCategoryName: item.newCategoryName,
goodsId: item.goodsId,
componentBgColor: this.value.componentBgColor,
componentAngle: this.value.componentAngle,
topAroundRadius: this.value.topAroundRadius,
bottomAroundRadius: this.value.bottomAroundRadius,
elementBgColor: this.value.elementBgColor,
elementAngle: this.value.elementAngle,
topElementAroundRadius: this.value.topElementAroundRadius,
bottomElementAroundRadius: this.value.bottomElementAroundRadius,
count: this.value.count,
nameLineMode: this.value.nameLineMode,
template: this.value.template,
style: this.value.style,
ornament: this.value.ornament,
sortWay: this.value.sortWay,
saleStyle: this.value.saleStyle,
tag: this.value.tag,
btnStyle: this.value.btnStyle,
goodsNameStyle: this.value.goodsNameStyle,
theme: this.value.theme,
priceStyle: this.value.priceStyle,
slideMode: this.value.slideMode,
imgAroundRadius: this.value.imgAroundRadius,
cartEvent: this.value.cartEvent,
cateName: this.cateIndex + 1,
tabsTitle: item.title,
pageStyle: this.value.pageStyle
};
console.log("goodsValue" + index, '切换之后的数据');
console.log(this["goodsValue" + index], '切换之后的数据源头');
// this.goodsValue0 = {
// sources: item.sources,
// categoryId: item.categoryId,
// categoryName: item.categoryName,
// newCategoryId: item.newCategoryId,
// newCategoryName: item.newCategoryName,
// goodsId: item.goodsId,
// componentBgColor: this.value.componentBgColor,
// componentAngle: this.value.componentAngle,
// topAroundRadius: this.value.topAroundRadius,
// bottomAroundRadius: this.value.bottomAroundRadius,
// elementBgColor: this.value.elementBgColor,
// elementAngle: this.value.elementAngle,
// topElementAroundRadius: this.value.topElementAroundRadius,
// bottomElementAroundRadius: this.value.bottomElementAroundRadius,
// count: this.value.count,
// nameLineMode: this.value.nameLineMode,
// template: this.value.template,
// style: this.value.style,
// ornament: this.value.ornament,
// sortWay: this.value.sortWay,
// saleStyle: this.value.saleStyle,
// tag: this.value.tag,
// btnStyle: this.value.btnStyle,
// goodsNameStyle: this.value.goodsNameStyle,
// theme: this.value.theme,
// priceStyle: this.value.priceStyle,
// slideMode: this.value.slideMode,
// imgAroundRadius: this.value.imgAroundRadius,
// cartEvent: this.value.cartEvent,
// cateName: this.cateIndex + 1,
// tabsTitle: item.title,
// pageStyle: this.value.pageStyle
// };
//
// #ifdef APP
if (isFirst) return;
// #endif
// // #ifndef APP
// if (this["goodsValue" + index].goodsId > 20) {
// if (isFirst) return;
// }
// // #endif
this.$refs["diyGoodsList" + index].goodsValue = this["goodsValue" + index];
this.$refs["diyGoodsList" + index].list = [];
this.$refs["diyGoodsList" + index].getGoodsList();
this.$refs["diyGoodsList" + index].page = 1;
this.$refs["diyGoodsList" + index].nodata = false;
}
}
};
</script>
<style lang="scss" scoped>
scroll-view {
width: 100%;
white-space: nowrap;
box-sizing: border-box;
padding: 40rpx 20rpx;
.scroll-item {
display: inline-block;
text-align: center;
vertical-align: top;
.item-wrap {
display: flex;
align-items: center;
}
.split-line {
display: inline-block;
width: 1rpx;
height: 30rpx;
// background-color: #e5e5e5;
margin: 0 20rpx;
}
&.active {
.name {
font-weight: bold;
}
.desc {
color: #ffffff;
border-radius: 20rpx;
}
}
.name {
font-size: 32rpx;
color: $color-title;
line-height: 1;
}
.desc {
font-size: $font-size-tag;
color: $color-tip;
height: 36rpx;
line-height: 36rpx;
margin-top: 10rpx;
min-width: 120rpx;
}
}
}
</style>

1080
components/diy-components/diy-member-info.vue

File diff suppressed because it is too large

340
components/diy-components/diy-member-my-order.vue

@ -0,0 +1,340 @@
<template>
<view class="common-wrap" :style="warpCss">
<view class="order-wrap">
<view class="status-wrap">
<view class="item-wrap" @click="redirect('/pages/order/list?status=waitpay')">
<view class="icon-block">
<template v-if="value.style == 3">
<image
:src="$util.img('public/uniapp/member/order/wait_pay.png')"
mode="widthFix"
></image>
<view
class="icon-shade"
:style="
'-webkit-mask-image: url(' +
$util.img('public/uniapp/member/order/wait_pay_shade.png') +
')'
"
></view>
</template>
<template v-else>
<diy-icon
:icon="value.icon.waitPay.icon"
v-if="value.icon.waitPay"
:value="value.icon.waitPay.style ? value.icon.waitPay.style : null"
></diy-icon>
</template>
<text
v-if="orderNum.waitpay > 0"
class="order-num color-base-bg price-font"
>
{{ orderNum.waitpay > 99 ? '99+' : orderNum.waitpay }}
</text>
</view>
<view class="title">待付款</view>
</view>
<view class="item-wrap" @click="redirect('/pages/order/list?status=waitsend')">
<view class="icon-block">
<template v-if="value.style == 3">
<image
:src="$util.img('public/uniapp/member/order/wait_send.png')"
mode="widthFix"
></image>
<view
class="icon-shade"
:style="
'-webkit-mask-image: url(' +
$util.img(
'public/uniapp/member/order/wait_send_shade.png'
) +
')'
"
></view>
</template>
<template v-else>
<diy-icon
:icon="value.icon.waitSend.icon"
v-if="value.icon.waitSend"
:value="
value.icon.waitSend.style ? value.icon.waitSend.style : null
"
></diy-icon>
</template>
<text
v-if="orderNum.waitsend > 0"
class="order-num color-base-bg price-font"
>
{{ orderNum.waitsend > 99 ? '99+' : orderNum.waitsend }}
</text>
</view>
<view class="title">待发货</view>
</view>
<view class="item-wrap" @click="redirect('/pages/order/list?status=waitconfirm')">
<view class="icon-block">
<template v-if="value.style == 3">
<image
:src="$util.img('public/uniapp/member/order/wait_confirm.png')"
mode="widthFix"
></image>
<view
class="icon-shade"
:style="
'-webkit-mask-image: url(' +
$util.img(
'public/uniapp/member/order/wait_confirm_shade.png'
) +
')'
"
></view>
</template>
<template v-else>
<diy-icon
:icon="value.icon.waitConfirm.icon"
v-if="value.icon.waitConfirm"
:value="
value.icon.waitConfirm.style
? value.icon.waitConfirm.style
: null
"
></diy-icon>
</template>
<text
v-if="orderNum.waitconfirm > 0"
class="order-num color-base-bg price-font"
>
{{ orderNum.waitconfirm > 99 ? '99+' : orderNum.waitconfirm }}
</text>
</view>
<view class="title">待收货</view>
</view>
<view class="item-wrap" @click="redirect('/pages/order/list?status=waitrate')">
<view class="icon-block">
<template v-if="value.style == 3">
<image
:src="$util.img('public/uniapp/member/order/wait_rate.png')"
mode="widthFix"
></image>
<view
class="icon-shade"
:style="
'-webkit-mask-image: url(' +
$util.img(
'public/uniapp/member/order/wait_rate_shade.png'
) +
')'
"
></view>
</template>
<template v-else>
<diy-icon
:icon="value.icon.waitRate.icon"
v-if="value.icon.waitRate"
:value="
value.icon.waitRate.style ? value.icon.waitRate.style : null
"
></diy-icon>
</template>
<text
v-if="orderNum.waitrate > 0"
class="order-num color-base-bg price-font"
>
{{ orderNum.waitrate > 99 ? '99+' : orderNum.waitrate }}
</text>
</view>
<view class="title">待评价</view>
</view>
<view class="item-wrap" @click="redirect('/pages_tool/order/activist')">
<view class="icon-block">
<template v-if="value.style == 3">
<image
:src="$util.img('public/uniapp/member/order/refunding.png')"
mode="widthFix"
></image>
<view
class="icon-shade"
:style="
'-webkit-mask-image: url(' +
$util.img(
'public/uniapp/member/order/refunding_shade.png'
) +
')'
"
></view>
</template>
<template v-else>
<diy-icon
:icon="value.icon.refunding.icon"
v-if="value.icon.refunding"
:value="
value.icon.refunding.style ? value.icon.refunding.style : null
"
></diy-icon>
</template>
<text
v-if="orderNum.refunding > 0"
class="order-num color-base-bg price-font"
>
{{ orderNum.refunding > 99 ? '99+' : orderNum.refunding }}
</text>
</view>
<view class="title">售后/退款</view>
</view>
</view>
</view>
<ns-login ref="login"></ns-login>
</view>
</template>
<script>
//
export default {
name: 'diy-member-my-order',
props: {
value: {
type: Object
},
token: {
type: String
}
},
data() {
return {
orderNum: {
waitpay: 0,
waitsend: 0,
waitconfirm: 0,
waitrate: 0,
refunding: 0
}
};
},
created() {
this.getOrderNum();
},
mounted() {
uni.$on('changeStore', data => {
if (data) {
this.getOrderNum();
}
});
},
watch: {
token(nVal, oVal) {
this.getOrderNum();
}
},
computed: {
warpCss() {
var obj = '';
obj += 'background-color:' + this.value.componentBgColor + ';';
if (this.value.componentAngle == 'round') {
obj += 'border-top-left-radius:' + this.value.topAroundRadius * 2 + 'rpx;';
obj += 'border-top-right-radius:' + this.value.topAroundRadius * 2 + 'rpx;';
obj += 'border-bottom-left-radius:' + this.value.bottomAroundRadius * 2 + 'rpx;';
obj += 'border-bottom-right-radius:' + this.value.bottomAroundRadius * 2 + 'rpx;';
}
return obj;
}
},
methods: {
/**
* 获取订单数量
*/
getOrderNum() {
if (!uni.getStorageSync('token')) return;
this.$api.sendRequest({
url: '/api/order/num',
data: {
order_status: 'waitpay,waitsend,waitconfirm,waitrate,refunding'
},
success: res => {
if (res.code == 0) {
this.orderNum = res.data;
}
}
});
},
/**
* 跳转
* @param {Object} url
*/
redirect(url) {
if (!uni.getStorageSync('token')) {
this.$refs.login.open(url);
} else {
this.$util.redirectTo(url);
}
}
}
};
</script>
<style lang="scss">
.common-wrap {
width: 100%;
box-sizing: border-box;
}
.order-wrap {
.status-wrap {
display: flex;
padding: 30rpx 0;
align-items: center;
justify-content: center;
color: #333;
}
.item-wrap {
flex: 1;
text-align: center;
.icon-block {
width: 60rpx;
height: 60rpx;
font-size: 60rpx;
margin: 4rpx auto;
position: relative;
& > image {
position: absolute;
top: 5%;
right: 5%;
width: 90%;
height: 90%;
z-index: 5;
}
.icon-shade {
width: 90%;
height: 90%;
position: absolute;
z-index: 4;
top: 5%;
right: 5%;
background: $base-color;
-webkit-mask: no-repeat center / contain;
}
}
.order-num {
position: absolute;
top: 0;
right: 0;
transform: translate(50%, -50%);
display: inline-block;
box-sizing: border-box;
color: #ffffff;
line-height: 1.2;
text-align: center;
font-size: 24rpx;
padding: 0 6rpx;
min-width: 30rpx;
border-radius: 16rpx;
height: 30rpx;
text-align: center;
display: flex;
align-items: center;
justify-content: center;
}
.title {
font-size: 26rpx;
}
}
}
</style>

184
components/diy-components/diy-notice.vue

@ -0,0 +1,184 @@
<template>
<view class="diy-notice">
<view :class="['notice', value.contentStyle]" :style="noticeWrapCss">
<image v-if="value.iconType == 'img'" class="notice-img" :src="$util.img(value.imageUrl)" mode="aspectFit"></image>
<diy-icon
v-if="value.iconType == 'icon'"
:icon="value.icon"
:value="value.style ? value.style : 'null'"
:style="{ maxWidth: 30 * 2 + 'rpx', maxHeight: 30 * 2 + 'rpx', width: '100%', height: '100%' }"
></diy-icon>
<view class="notice-xian"></view>
<view class="main-wrap">
<text v-if="value.contentStyle == 'style-2'" class="iconfont icon-gonggao" :style="{ color: value.textColor }"></text>
<view class="uni-swiper-msg">
<!-- 横向滚动horizontal -->
<template v-if="value.scrollWay == 'horizontal'">
<swiper :vertical="false" :duration="0" autoplay="true" circular="true">
<swiper-item v-for="(item, index) in list" :key="index" @touchmove.stop>
<text @click="toLink(item)" class="beyond-hiding animate" :style="{ color: value.textColor }">{{ item.title }}</text>
</swiper-item>
</swiper>
</template>
<!-- 上下滚动upDown -->
<template v-if="value.scrollWay == 'upDown'">
<swiper :vertical="true" :duration="500" autoplay="true" circular="true">
<swiper-item v-for="(item, index) in list" :key="index">
<text @click="toLink(item)" class="beyond-hiding" :style="{ color: value.textColor }">{{ item.title }}</text>
</swiper-item>
</swiper>
</template>
</view>
<text v-if="value.contentStyle == 'style-2'" class="iconfont icon-right arrows" @click="toLink"></text>
</view>
</view>
</view>
</template>
<script>
//
export default {
name: 'diy-notice',
props: {
value: {
type: Object
}
},
data() {
return {
list: []
};
},
created() {
//
if (this.value.sources == 'default') this.getData();
else this.list = this.value.list;
},
computed: {
noticeWrapCss: function() {
var obj = '';
obj += 'background-color:' + this.value.componentBgColor + ';';
if (this.value.componentAngle == 'round') {
obj += 'border-top-left-radius:' + this.value.topAroundRadius * 2 + 'rpx;';
obj += 'border-top-right-radius:' + this.value.topAroundRadius * 2 + 'rpx;';
obj += 'border-bottom-left-radius:' + this.value.bottomAroundRadius * 2 + 'rpx;';
obj += 'border-bottom-right-radius:' + this.value.bottomAroundRadius * 2 + 'rpx;';
}
return obj;
}
},
methods: {
getData() {
var data = {};
data.id_arr = this.value.noticeIds.toString();
this.$api.sendRequest({
url: '/api/notice/lists',
data: data,
success: res => {
console.log(res.data,'data');
if (res.code == 0 && res.data) {
this.list = res.data;
}
}
});
},
toLink(item) {
if (this.value.sources == 'initial') this.$util.redirectTo('/pages_tool/notice/detail', { notice_id: item.id });
else if (!item) this.$util.redirectTo('/pages_tool/notice/list');
else this.$util.diyRedirectTo(item.link);
}
}
};
</script>
<style lang="scss">
.notice {
height: 80rpx;
position: relative;
display: flex;
align-items: center;
overflow: hidden;
padding: 20rpx;
font-size: 70rpx;
box-sizing: border-box;
.notice-img {
width: 212rpx;
height: 40rpx;
}
.notice-xian {
width: 1rpx;
height: 26rpx;
background-color: #e4e4e4;
margin: 0 22rpx;
}
&.style-2 {
.main-wrap {
display: flex;
align-items: center;
.uni-swiper-msg {
width: 400rpx;
margin: 0 10rpx;
}
.arrows {
color: #999;
font-size: $font-size-sub;
}
}
}
}
.main-wrap {
display: inline-block;
width: calc(100% - 115rpx);
position: relative;
}
swiper {
height: 50rpx;
}
.beyond-hiding {
display: inline-block;
width: 100%;
white-space: nowrap;
}
.animate {
width: auto;
overflow: hidden;
text-overflow: ellipsis;
padding-left: 40rpx;
font-size: $font-size-base;
color: #000;
display: inline-block;
white-space: nowrap;
animation: 5s wordsLoop linear infinite normal;
}
@keyframes wordsLoop {
0% {
transform: translateX(400rpx);
-webkit-transform: translateX(400rpx);
}
100% {
transform: translateX(-100%);
-webkit-transform: translateX(-100%);
}
}
@-webkit-keyframes wordsLoop {
0% {
transform: translateX(400rpx);
-webkit-transform: translateX(400rpx);
}
100% {
transform: translateX(-100%);
-webkit-transform: translateX(-100%);
}
}
</style>

536
components/diy-components/diy-rubik-cube.vue

@ -0,0 +1,536 @@
<template>
<view>
<!-- 自定义 -->
<view v-if="value.mode == 'custom-rubik-cube'">
<view style="position: relative;"><rich-text :nodes="customHtml"></rich-text></view>
</view>
<view v-else :class="['rubik-cube', value.mode]" :style="rubikCubeWrapCss">
<!-- 1左2右 -->
<template v-if="value.mode == 'row1-lt-of2-rt'">
<view class="template-left">
<view :class="['item', value.mode]" @click="$util.diyRedirectTo(value.list[0].link)"
:style="{ padding: value.imageGap + 'rpx', height: list[0].imgHeight * 2 + 'rpx' }">
<image :src="$util.img(value.list[0].imageUrl)" mode="aspectFill" :style="list[0].pageItemStyle"></image>
</view>
</view>
<view class="template-right">
<template v-for="(item, index) in list">
<template v-if="index > 0">
<view :key="index" :class="['item', value.mode]" @click="$util.diyRedirectTo(item.link)"
:style="{ padding: value.imageGap + 'rpx', height: item.imgHeight }">
<image :src="$util.img(item.imageUrl)" mode="aspectFill" :style="item.pageItemStyle"></image>
</view>
</template>
</template>
</view>
</template>
<!-- 1左3右 -->
<template v-else-if="value.mode == 'row1-lt-of1-tp-of2-bm'">
<view class="template-left" :style="{ paddingRight: value.imageGap + 'rpx' }">
<view :class="['item', value.mode]" :style="{ height: list[0].imgHeight + 'rpx' }"
@click="$util.diyRedirectTo(value.list[0].link)">
<image :src="$util.img(value.list[0].imageUrl)" mode="aspectFill" :style="list[0].pageItemStyle"></image>
</view>
</view>
<view class="template-right" :style="{ paddingLeft: value.imageGap + 'rpx' }">
<view :class="['item', value.mode]"
:style="{ height: list[1].imgHeight + 'rpx', paddingBottom: value.imageGap + 'rpx' }"
@click="$util.diyRedirectTo(value.list[1].link)">
<image :src="$util.img(value.list[1].imageUrl)" mode="aspectFill" :style="list[1].pageItemStyle"></image>
</view>
<view class="template-bottom" :style="{ paddingTop: value.imageGap + 'rpx' }">
<template v-for="(item, index) in list">
<template v-if="index > 1">
<view :key="index" :class="['item', value.mode]" @click="$util.diyRedirectTo(item.link)" :style="{
height: item.imgHeight + 'rpx',
paddingLeft: index == 3 ? value.imageGap * 2 + 'rpx' : 0
}">
<image :src="$util.img(item.imageUrl)" mode="aspectFill" :style="item.pageItemStyle"></image>
</view>
</template>
</template>
</view>
</view>
</template>
<template v-else>
<view :class="['item', value.mode]" v-for="(item, index) in list" :key="index"
@click="$util.diyRedirectTo(item.link)"
:style="{ padding: value.imageGap + 'rpx', height: item.imgHeight * 2 + 'rpx' }">
<image :src="$util.img(item.imageUrl)" mode="aspectFill" :style="item.pageItemStyle"></image>
</view>
</template>
</view>
</view>
</template>
<script>
//
// import htmlParser from '@/common/js/html-parser';
export default {
name: 'diy-rubik-cube',
props: {
value: {
type: Object,
default: () => {
return {};
}
}
},
data() {
return {
customHtml: ''
};
},
created() {
this.init()
},
computed: {
list() {
var arr = JSON.parse(JSON.stringify(this.value.list));
arr.forEach((item, index) => {
item.pageItemStyle = this.countBorderRadius(this.value.mode, index);
});
return arr;
},
rubikCubeWrapCss() {
var obj = '';
obj += 'background-color:' + this.value.componentBgColor + ';';
if (this.value.componentAngle == 'round') {
obj += 'border-top-left-radius:' + this.value.topAroundRadius * 2 + 'rpx;';
obj += 'border-top-right-radius:' + this.value.topAroundRadius * 2 + 'rpx;';
obj += 'border-bottom-left-radius:' + this.value.bottomAroundRadius * 2 + 'rpx;';
obj += 'border-bottom-right-radius:' + this.value.bottomAroundRadius * 2 + 'rpx;';
}
return obj;
}
},
watch: {
value() {
this.init();
}
},
methods: {
init() {
if (this.value.mode == 'custom-rubik-cube') {
this.value.diyHtml = this.value.diyHtml.replace(/&quot;/g, '"');
// this.customHtml = htmlParser(this.value.diyHtml);
} else {
var singleRow = {
'row1-of2': {
ratio: 2,
width: '50%'
},
'row1-of3': {
ratio: 3,
width: '33.33%'
},
'row1-of4': {
ratio: 4,
width: '25%'
}
};
if (singleRow[this.value.mode]) {
this.calcSingleRow(singleRow[this.value.mode]);
} else if (this.value.mode == 'row2-lt-of2-rt') {
this.calcFourSquare();
} else if (this.value.mode == 'row1-lt-of2-rt') {
this.calcRowOneLeftOfTwoRight();
} else if (this.value.mode == 'row1-tp-of2-bm') {
this.calcRowOneTopOfTwoBottom();
} else if (this.value.mode == 'row1-lt-of1-tp-of2-bm') {
this.calcRowOneLeftOfOneTopOfTwoBottom();
}
}
},
/**
* 魔方单行多个平分宽度
* 公式
* 宽度屏幕宽度/2示例375/2=187.5
* 比例原图高/原图宽示例322/690=0.46
* 高度宽度*比例示例187.5*0.46=86.25
*/
calcSingleRow(params) {
let maxHeight = 0;
this.list.forEach((item, index) => {
uni.getSystemInfo({
success: res => {
var ratio = item.imgHeight / item.imgWidth;
item.imgWidth = 375 / params.ratio;
item.imgWidth -= this.value.margin.both * 2;
item.imgHeight = item.imgWidth * ratio;
}
});
//
if (maxHeight == 0 || maxHeight < item.imgHeight) maxHeight = item.imgHeight;
});
this.list.forEach((item, index) => {
item.imgWidth = params.width;
item.imgHeight = maxHeight;
});
},
/**
* 魔方四方型各占50%
*/
calcFourSquare() {
let maxHeightFirst = 0;
let maxHeightTwo = 0;
this.list.forEach((item, index) => {
uni.getSystemInfo({
success: res => {
var ratio = item.imgHeight / item.imgWidth;
item.imgWidth = 375 / 2;
item.imgWidth -= this.value.margin.both * 2;
item.imgHeight = item.imgWidth * ratio;
}
});
//
if (index <= 1) {
if (maxHeightFirst == 0 || maxHeightFirst < item.imgHeight) {
maxHeightFirst = item.imgHeight;
}
} else if (index > 1) {
if (maxHeightTwo == 0 || maxHeightTwo < item.imgHeight) {
maxHeightTwo = item.imgHeight;
}
}
});
this.list.forEach((item, index) => {
item.imgWidth = '50%';
if (index <= 1) {
item.imgHeight = maxHeightFirst;
} else if (index > 1) {
item.imgHeight = maxHeightTwo;
}
});
},
/**
* 魔方1左2右
*/
calcRowOneLeftOfTwoRight() {
let rightHeight = 0; //
let divide = 'left'; // leftright
if (this.list[1].imgWidth === this.list[2].imgWidth) divide = 'right';
this.list.forEach((item, index) => {
uni.getSystemInfo({
success: res => {
if (index == 0) {
var ratio = item.imgHeight / item.imgWidth; //
item.imgWidth = 375 / 2;// 使pxrpx
item.imgWidth -= (this.value.margin.both * 2 + this.value.imageGap / 2);
item.imgHeight = item.imgWidth * ratio;
rightHeight = item.imgHeight / 2 - this.value.imageGap / 2;
} else {
item.imgWidth = this.list[0].imgWidth;
item.imgHeight = rightHeight * 2;
item.imgHeight += 'rpx';
// if (divide == 'left') {
// item.imgWidth = this.list[0].imgWidth;
// item.imgHeight = rightHeight / 100;
// } else {
// var ratio = item.imgHeight / item.imgWidth; //
// if (isNaN(ratio)) ratio = 0;
// item.imgWidth = res.windowWidth * ratio;
// item.imgHeight = item.imgHeight * ratio;
// if (this.list[1].imgHeight) this.list[0].imgHeight = this.list[1].imgHeight * 2;
// }
}
}
});
});
// this.list.forEach((item, index) => {
// if (index == 0) item.imgHeight += this.value.imageGap;
// item.imgHeight += 'px';
// });
},
/**
* 魔方1上2下
*/
calcRowOneTopOfTwoBottom() {
var maxHeight = 0;
this.list.forEach((item, index) => {
uni.getSystemInfo({
success: res => {
var ratio = item.imgHeight / item.imgWidth; //
if (index == 0) item.imgWidth = 375;
else if (index > 0) item.imgWidth = 375 / 2;
item.imgWidth -= this.value.margin.both * 2;
item.imgHeight = item.imgWidth * ratio;
//
if (index > 0 && (maxHeight == 0 || maxHeight < item.imgHeight)) maxHeight = item.imgHeight;
}
});
});
this.list.forEach((item, index) => {
if (index == 0) item.imgWidth -= this.value.margin.both * 2; //
if (index > 0) item.imgWidth -= this.value.margin.both * 2; //
item.imgWidth += item.imgWidth * 2 + 'rpx';
if (index > 0) item.imgHeight = maxHeight;
// else item.imgHeight += 'px';
});
},
/**
* 魔方1左3右
*/
calcRowOneLeftOfOneTopOfTwoBottom() {
this.list.forEach((item, index) => {
uni.getSystemInfo({
success: res => {
//
if (index == 0) {
var ratio = item.imgHeight / item.imgWidth;
item.imgWidth = 375 / 2;
item.imgWidth -= this.value.margin.both * 2;
item.imgHeight = item.imgWidth * ratio;
} else if (index == 1) {
item.imgWidth = 375 / 2;
item.imgWidth -= this.value.margin.both * 2;
item.imgHeight = this.list[0].imgHeight / 2;
} else if (index > 1) {
item.imgWidth = this.list[0].imgWidth / 2;
item.imgHeight = this.list[0].imgHeight / 2;
}
}
});
});
this.list.forEach((item, index) => {
if (index == 0) {
item.imgHeight += this.value.imageGap;
item.imgHeight *= 2;
} else {
item.imgHeight *= 2;
}
if (index > 1) {
item.imgWidth -= this.value.imageGap / 2;
item.imgWidth -= this.value.margin.both; //
item.imgWidth = item.imgWidth * 2 + 'rpx';
} else {
item.imgWidth -= this.value.margin.both * 2; //
item.imgWidth = item.imgWidth * 2 + 'rpx';
}
});
},
countBorderRadius(type, index) {
var obj = '';
if (this.value.elementAngle == 'right') {
return obj;
}
var defaultData = {
'row1-lt-of2-rt': [
['border-top-right-radius', 'border-bottom-right-radius'],
['border-top-left-radius', 'border-bottom-left-radius', 'border-bottom-right-radius'],
['border-top-left-radius', 'border-bottom-left-radius', 'border-top-right-radius']
],
'row1-lt-of1-tp-of2-bm': [
['border-top-right-radius', 'border-bottom-right-radius'],
['border-top-left-radius', 'border-bottom-left-radius', 'border-bottom-right-radius'],
['border-radius'],
['border-top-left-radius', 'border-bottom-left-radius', 'border-top-right-radius']
],
'row1-tp-of2-bm': [
['border-bottom-left-radius', 'border-bottom-right-radius'],
['border-top-left-radius', 'border-bottom-right-radius', 'border-top-right-radius'],
['border-top-left-radius', 'border-bottom-left-radius', 'border-top-right-radius']
],
'row2-lt-of2-rt': [
['border-top-right-radius', 'border-bottom-left-radius', 'border-bottom-right-radius'],
['border-top-left-radius', 'border-bottom-right-radius', 'border-bottom-left-radius'],
['border-top-left-radius', 'border-bottom-right-radius', 'border-top-right-radius'],
['border-top-left-radius', 'border-bottom-left-radius', 'border-top-right-radius']
],
'row1-of4': [
['border-top-right-radius', 'border-bottom-right-radius'],
['border-radius'],
['border-radius'],
['border-top-left-radius', 'border-bottom-left-radius']
],
'row1-of3': [['border-top-right-radius', 'border-bottom-right-radius'], ['border-radius'], ['border-top-left-radius', 'border-bottom-left-radius']],
'row1-of2': [['border-top-right-radius', 'border-bottom-right-radius'], ['border-top-left-radius', 'border-bottom-left-radius']]
};
defaultData[type][index].forEach((item, index) => {
// obj += item + ':' + this.value.aroundRadius * 2 + 'rpx;';
obj += 'border-top-left-radius:' + this.value.topElementAroundRadius * 2 + 'rpx;';
obj += 'border-top-right-radius:' + this.value.topElementAroundRadius * 2 + 'rpx;';
obj += 'border-bottom-left-radius:' + this.value.bottomElementAroundRadius * 2 + 'rpx;';
obj += 'border-bottom-right-radius:' + this.value.bottomElementAroundRadius * 2 + 'rpx;';
});
return obj;
}
}
};
</script>
<style lang="scss">
.rubik-cube {
overflow: hidden;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.rubik-cube .item {
text-align: center;
line-height: 0;
overflow: hidden;
}
.rubik-cube .item image {
width: 100%;
max-width: 100%;
height: 100%;
}
//
.rubik-cube .item.row1-of2 {
width: 50% !important;
box-sizing: border-box;
padding-top: 0 !important;
padding-bottom: 0 !important;
}
.rubik-cube .item.row1-of2:nth-child(1) {
padding-left: 0 !important;
}
.rubik-cube .item.row1-of2:nth-child(2) {
padding-right: 0 !important;
}
//
.rubik-cube .item.row1-of3 {
width: 33.33%;
box-sizing: border-box;
padding-top: 0 !important;
padding-bottom: 0 !important;
}
.rubik-cube .item.row1-of3:nth-child(1) {
padding-left: 0 !important;
}
.rubik-cube .item.row1-of3:nth-child(3) {
padding-right: 0 !important;
}
//
.rubik-cube .item.row1-of4 {
width: 25%;
box-sizing: border-box;
padding-top: 0 !important;
padding-bottom: 0 !important;
}
.rubik-cube .item.row1-of4:nth-child(1) {
padding-left: 0 !important;
}
.rubik-cube .item.row1-of4:nth-child(4) {
padding-right: 0 !important;
}
//
.rubik-cube .item.row2-lt-of2-rt {
width: 50%;
display: inline-block;
box-sizing: border-box;
}
.rubik-cube .item.row2-lt-of2-rt:nth-child(1) {
padding-left: 0 !important;
padding-top: 0 !important;
}
.rubik-cube .item.row2-lt-of2-rt:nth-child(2) {
padding-right: 0 !important;
padding-top: 0 !important;
}
.rubik-cube .item.row2-lt-of2-rt:nth-child(3) {
padding-left: 0 !important;
padding-bottom: 0 !important;
}
.rubik-cube .item.row2-lt-of2-rt:nth-child(4) {
padding-right: 0 !important;
padding-bottom: 0 !important;
}
//
.rubik-cube .template-left,
.rubik-cube .template-right {
width: 50%;
box-sizing: border-box;
}
.rubik-cube .template-left .item.row1-lt-of2-rt:nth-child(1) {
width: auto;
padding-top: 0 !important;
padding-left: 0 !important;
padding-bottom: 0 !important;
}
.rubik-cube .template-right .item.row1-lt-of2-rt:nth-child(1) {
padding-top: 0 !important;
padding-right: 0 !important;
}
.rubik-cube .template-right .item.row1-lt-of2-rt:nth-child(2) {
padding-right: 0 !important;
padding-bottom: 0 !important;
}
.rubik-cube.row1-lt-of2-rt .template-right {
display: flex;
flex-direction: column;
justify-content: space-between;
}
//
.rubik-cube .item.row1-tp-of2-bm:nth-child(1) {
width: 100%;
box-sizing: border-box;
padding-top: 0 !important;
padding-left: 0 !important;
padding-right: 0 !important;
}
.rubik-cube .item.row1-tp-of2-bm:nth-child(2) {
width: 50%;
box-sizing: border-box;
padding-left: 0 !important;
padding-bottom: 0 !important;
}
.rubik-cube .item.row1-tp-of2-bm:nth-child(3) {
width: 50%;
box-sizing: border-box;
padding-right: 0 !important;
padding-bottom: 0 !important;
}
//
.rubik-cube .template-left .item.row1-lt-of1-tp-of2-bm {
width: 100%;
box-sizing: border-box;
}
.rubik-cube .template-bottom {
display: flex;
align-items: center;
justify-content: space-between;
}
.rubik-cube .template-bottom .item.row1-lt-of1-tp-of2-bm {
width: 50%;
}
</style>

250
components/diy-components/diy-search.vue

@ -0,0 +1,250 @@
<template>
<div class="navbar" :style="{ backgroundColor: navbarBgColor }">
<!-- <u-navbar title=" " :autoBack="false" leftIconSize="0" :bgColor="navbarBgColor" > -->
<!-- <view class="search-box" :style="searchWrapCss" slot="left" style="width: calc(100% );">
<view class="img" v-if="value.searchStyle == 2 && value.iconType == 'img'">
<image :src="$util.img(value.imageUrl)" mode="aspectFill"></image>
</view>
<diy-icon class="icon" v-if="value.searchStyle == 2 && value.iconType == 'icon'" :icon="value.icon"
:value="value.style ? value.style : 'null'"
:style="{ maxWidth: 30 * 2 + 'rpx', maxHeight: 30 * 2 + 'rpx' }"></diy-icon>
<view class="search-content" :style="inputStyle" style="border: 1px var(--base-color) solid;"
@click="search()">
<input type="text" class="uni-input ns-font-size-base" maxlength="50" :placeholder="value.title"
v-model="searchText" @confirm="search()" :placeholderStyle="placeholderStyle" />
<text class="iconfont icon-sousuo3" @click="search()"
:style="{ color: value.textColor ? value.textColor : 'rgba(0,0,0,0)' }"></text>
<div class="text">
<div class="line"></div>
<div>搜索</div>
</div>
</view>
<image :src="$util.img('/upload/weapp/user/ld.png')" @click="toNews" class="news"></image>
</view> -->
<view class="search-box" :style="searchWrapCss" slot="center" style="width:calc(100%-56rpx);">
<view class="img" v-if="value.searchStyle == 2 && value.iconType == 'img'">
<image :src="$util.img(value.imageUrl)" mode="aspectFill"></image>
</view>
<diy-icon class="icon" v-if="value.searchStyle == 2 && value.iconType == 'icon'" :icon="value.icon"
:value="value.style ? value.style : 'null'"
:style="{ maxWidth: 30 * 2 + 'rpx', maxHeight: 30 * 2 + 'rpx' }"></diy-icon>
<view class="search-content" :style="inputStyle" style="border: 1px var(--base-color) solid;" @click="search()">
<input type="text" class="uni-input ns-font-size-base" maxlength="50" :placeholder="value.title"
v-model="searchText" @confirm="search()" :placeholderStyle="placeholderStyle" />
<text class="iconfont icon-sousuo3"
:style="{ color: value.textColor ? value.textColor : 'rgba(0,0,0,0)' }"></text>
<div class="text">
<div class="line"></div>
<div>搜索</div>
</div>
</view>
<view class="">
<image :src="$util.img('/upload/weapp/user/ld.png')" @click="toNews" class="news"></image>
<u-badge type="error" max="99" :value="read_no_num" :absolute="true" :offset="[0, 0]"> </u-badge>
</view>
</view>
</div>
<!-- #ifndef H5 -->
<!-- <div style="height: 80rpx;"></div> -->
<!-- #endif -->
<!-- #ifdef H5 -->
<!-- <div style="height: 60rpx;"></div> -->
<!-- #endif -->
</template>
<script>
//
export default {
name: 'diy-search',
props: {
value: {
type: Object,
default: () => {
return {};
}
}
},
watch: {
'$store.state.navbarBgColor': {
handler: function (newVal, oldVal) {
// this.navbarBgColor = newVal;
}
}
},
data() {
return {
searchText: '',
navbarBgColor: 'transparent',
read_no_num: "",
};
},
computed: {
searchWrapCss() {
var obj = '';
obj += 'background-color:' + this.value.componentBgColor + ';';
if (this.value.borderType == 2) {
obj += 'border-radius:' + '100rpx;';
}
obj += 'text-align:' + this.value.textAlign + ';';
return obj;
},
inputStyle() {
var obj = '';
obj += 'background-color:' + this.value.elementBgColor + ';';
if (this.value.borderType == 2) {
obj += 'border-radius:' + '40rpx;';
} else {
obj += 'border-radius:' + '16rpx;';
}
return obj;
},
placeholderStyle() {
var obj = '';
if (this.value.textColor) {
obj += 'color:' + this.value.textColor;
} else {
obj += 'color: rgba(0,0,0,0)';
}
return obj;
}
},
created() {
if (uni.getStorageSync('token')) {
this.getMessageNum()
}
},
methods: {
search() {
this.$util.redirectTo('/pages_tool/goods/search');
},
toNews() {
uni.navigateTo({
url: '/pages_tool/news/news'
});
},
getMessageNum() {
this.$api.sendRequest({
url: '/api/notice/messageNum',
success: res => {
this.read_no_num = res.data.read_no_num;
}
})
}
}
};
</script>
<style lang="scss">
.navbar {
// position: fixed;
// z-index: 9999;
width: 100%;
height: 90rpx;
// position: sticky;
// top: 0;
// padding: 32rpx 0rpx 0rpx 32rpx;
// padding-top: calc(var(--status-bar-height) + 40rpx);
// top:0;
// left: 0;
background: transparent;
// position: sticky;top: 0; background: #f7f7f7;
}
.news {
width: 48rpx;
height: 48rpx;
margin: 16rpx;
}
/deep/ .uni-input-placeholder {
overflow: initial;
}
.search-box {
position: relative;
display: flex;
align-items: center;
background: transparent;
/* #ifndef H5 */
// padding-top: 50rpx;
/* #endif */
.img {
width: 170rpx;
height: 60rpx;
margin-right: 20rpx;
image {
width: 100%;
height: 100%;
}
}
.icon {
width: 170rpx;
height: 60rpx;
margin-right: 20rpx;
}
}
.search-content {
flex: 1;
position: relative;
.text {
position: absolute;
top: 50%;
right: 30rpx;
display: flex;
align-items: center;
transform: translateY(-50%);
font-size: 28rpx;
z-index: 10;
color: $base-color;
.line {
width: 1px;
height: 36rpx;
background: linear-gradient(180deg,
rgba(33, 187, 243, 0) 0%,
$base-color 50%,
rgba(33, 187, 243, 0) 100%);
margin-right: 20rpx;
}
}
}
.search-content input {
box-sizing: border-box;
display: block;
height: 68rpx;
width: 100%;
padding: 0 20rpx 0 64rpx;
color: #333333;
}
.search-content .iconfont {
position: absolute;
top: 50%;
left: -5rpx;
transform: translateY(-50%);
font-size: 36rpx;
z-index: 10;
width: 80rpx;
font-weight: bold;
text-align: center;
}
</style>

24
components/diy-components/diy-text-extend.vue

@ -0,0 +1,24 @@
<template>
<view><text style="font-weight: bold;font-size: 20px;color: #0cc361;">我是扩展标题组件</text></view>
</template>
<script>
//
export default {
name: 'diy-text-extend',
props: {
value: {
type: Object
}
},
data() {
return {};
},
computed: {},
created() {
},
methods: {}
};
</script>
<style></style>

116
components/diy-components/diy-text-nav.vue

@ -0,0 +1,116 @@
<template>
<view :style="{ fontSize: value.fontSize * 2 + 'rpx' }">
<view
v-if="value.arrangement == 'vertical'"
class="diy-text-nav"
:style="{
fontSize: value.fontSize * 2 + 'rpx',
background: value.backgroundColor,
textAlign: value.textAlign
}"
@click="redirectTo(value.list[0].link)"
>
<view
class="single"
:style="{
fontSize: value.fontSize * 2 + 'rpx',
color: value.textColor ? value.textColor : 'rgba(0,0,0,0)'
}"
>
{{ value.list[0].text }}
<text class="subhead">{{ value.list[0].secondText }}</text>
<!-- <text :style="{ fontSize: value.fontSize * 2 + 'rpx'}" class="iconfont icon-right font-size-goods-tag"></text> -->
</view>
</view>
<view v-else class="diy-text-nav" :style="{ background: value.backgroundColor }">
<scroll-view scroll-x>
<view
v-for="(item, index) in value.list"
:key="index"
class="item"
@click="redirectTo(item.link)"
:style="{
textAlign: value.textAlign,
fontSize: value.fontSize * 2 + 'rpx',
color: value.textColor ? value.textColor : 'rgba(0,0,0,0)'
}"
>
{{ item.text }}
</view>
</scroll-view>
</view>
</view>
</template>
<script>
//
export default {
name: 'diy-text-nav',
props: {
value: {
type: Object
}
},
data() {
return {};
},
methods: {
redirectTo(link) {
this.$util.diyRedirectTo(link);
}
}
};
</script>
<style>
.control-text-navigation i {
float: right;
margin: 6rpx 20rpx 0 0;
}
.diy-text-nav {
padding: 20rpx;
}
.diy-text-nav scroll-view {
width: 100%;
flex-direction: row;
white-space: nowrap;
}
.diy-text-nav scroll-view .item {
display: inline-block;
margin-left: 16rpx;
position: relative;
min-width: 25%;
text-overflow: ellipsis;
text-align: center;
}
.diy-text-nav .single {
position: relative;
}
.diy-text-nav .single .subhead {
font-size: 24rpx;
color: #777;
margin-left: 20rpx;
}
.diy-text-nav .iconfont {
position: absolute;
top: 50%;
transform: translateY(-50%);
right: 0;
}
</style>
<style scoped lang="scss">
.uni-view {
font-size: 0;
}
.diy-text-nav {
/deep/.uni-scroll-view::-webkit-scrollbar {
display: none;
}
}
</style>

980
components/diy-components/diy-text.vue

@ -0,0 +1,980 @@
<template>
<view class="diy-text" @click="$util.diyRedirectTo(value.link)" :style="warpCss">
<view :class="value.style == 'style-8' ? 'title2' : 'title'" :style="{ fontSize: value.fontSize * 2 + 'rpx', color: value.textColor }">
<block v-if="value.style == 'style-1'" style="height: 40rpx; line-height: 40rpx;">
<view class="text-left" :style="{ color: value.textColor}"><text></text></view>
<text>{{ value.text }}</text>
<view class="text-right" :style="{ color: value.textColor}"><text></text></view>
</block>
<block v-else-if="value.style == 'style-2'">
<view class="style2">
<text :style="{ color: value.textColor, fontSize: value.fontSize * 2 + 'rpx' }">{{ value.text }}</text>
<view class="xian" :style="{ background: value.textColor }">
<view class="line-triangle" :style="{ borderColor: value.textColor }"></view>
</view>
</view>
</block>
<block v-else-if="value.style == 'style-3'">
<view class="style3">
<text :style="{ color: value.textColor, fontSize: value.fontSize * 2 + 'rpx' }">{{ value.text }}</text>
<view class="inner-line" :style="{ background: value.textColor }"><view class="line-short" :style="{ background: value.textColor }"></view></view>
</view>
</block>
<block v-else-if="value.style == 'style-4'">
<view class="style4">
<text :style="{ color: value.textColor, fontSize: value.fontSize * 2 + 'rpx' }">{{ value.text }}</text>
<view class="line-box">
<view class="line-left" :style="{ background: value.textColor }"></view>
<view class="line-center" :style="{ borderColor: value.textColor }"></view>
<view class="line-right" :style="{ background: value.textColor }"></view>
</view>
</view>
</block>
<block v-else-if="value.style == 'style-5'">
<view class="style5">
<view class="style5-box" :style="{ color: value.textColor }">
<text class="style5-title" :style="{ color: value.textColor, fontSize: value.fontSize * 2 + 'rpx' }">{{ value.text }}</text>
<view class="line-left" :style="{ background: value.textColor }"></view>
<view class="line-right" :style="{ background: value.textColor }"></view>
</view>
</view>
</block>
<block v-else-if="value.style == 'style-6'">
<view class="style6">
<view class="style6-box" :style="{ color: value.textColor }">
<text class="style6-title" :style="{ color: value.textColor, fontSize: value.fontSize * 2 + 'rpx' }">{{ value.text }}</text>
<view class="style6-wrap" :style="{ color: value.textColor }"></view>
</view>
</view>
</block>
<block v-else-if="value.style == 'style-7'">
<view class="style7">
<view class="style7-box" :style="{ color: value.textColor }">
<text class="style7-title" :style="{ background: value.textColor, fontSize: value.fontSize * 2 + 'rpx' }">{{ value.text }}</text>
<view class="style7-wrap" :style="{ color: value.textColor }"></view>
</view>
</view>
</block>
<block v-else-if="value.style == 'style-8'">
<view class="style8">
<view class="style8-box" :style="{ color: value.textColor }">
<text class="style8-title" :style="{ color: value.textColor, fontSize: value.fontSize * 2 + 'rpx' }">{{ value.text }}</text>
<view class="style8-wrap" :style="{ background: value.textColor, height: value.fontSize * 2 + 'rpx' }"></view>
</view>
</view>
</block>
<block v-else-if="value.style == 'style-9'">
<view class="style9">
<view class="style9-box">
<view class="style9-center">
<view class="left-img"><image :src="$util.img('public/uniapp/diy/style9-1.png')"></image></view>
<text
class="style9-title"
:style="{ fontSize: value.fontSize * 2 + 'rpx', color: value.textColor, fontWeight: value.fontWeight }"
>
{{ value.text }}
</text>
<view class="right-img"><image :src="$util.img('public/uniapp/diy/style9-2.png')"></image></view>
<view
class="style9-more"
v-if="value.more.isShow"
:style="{ color: value.more.color }"
@click.stop="$util.diyRedirectTo(value.more.link)"
>
{{ value.more.text }}
<view class="iconfont icon-right" :style="{ color: value.more.color }"></view>
</view>
</view>
<text class="sub-title" :style="{ color: value.subTitle.color }">{{ value.subTitle.text }}</text>
</view>
</view>
</block>
<block v-else-if="value.style == 'style-10'">
<view class="style10">
<view class="style10-box">
<view class="style10-center">
<view class="left-img"><image :src="$util.img('public/uniapp/diy/style10-1.png')"></image></view>
<text
class="style10-title"
v-if="$util.img('public/uniapp/diy/style10-3.png')"
:style="{
backgroundImage: 'url(' + $util.img('public/uniapp/diy/style10-3.png') + ')',
backgroundSize: 100 + '%',
backgroundPositionY: 93 + '%',
backgroundRepeat: 'no-repeat',
fontSize: value.fontSize * 2 + 'rpx',
color: value.textColor,
fontWeight: value.fontWeight
}"
>
{{ value.text }}
</text>
<view class="right-img"><image :src="$util.img('public/uniapp/diy/style10-2.png')"></image></view>
<view class="style10-more" v-if="value.more.isShow" :style="{ color: value.more.color }" @click.stop="$util.diyRedirectTo(value.more.link)">
{{ value.more.text }}
<view class="iconfont icon-right" :style="{ color: value.more.color }"></view>
</view>
</view>
<text class="sub-title" :style="{ color: value.subTitle.color }">{{ value.subTitle.text }}</text>
</view>
</view>
</block>
<block v-else-if="value.style == 'style-11'">
<view class="style11" :style="{ backgroundColor: value.backgroundColor }">
<view class="style11-box">
<view class="style11-conter">
<view class="style11-conter-box">
<view class="left">
<view
class="style11-title"
:style="{
fontSize: value.fontSize * 2 + 'rpx',
color: value.textColor,
fontWeight: value.fontWeight
}"
>
{{ value.text }}
</view>
<view class="style11-sub" :style="{ color: value.subTitle.color }">{{ value.subTitle.text }}</view>
</view>
<view class="style11-more" v-if="value.more.isShow" :style="{ color: value.more.color }" @click.stop="$util.diyRedirectTo(value.more.link)">
{{ value.more.text }}
<view class="iconfont icon-right" :style="{ color: value.more.color }"></view>
</view>
<image class="center-img" :src="$util.img('public/uniapp/diy/style11-1.png')" mode="widthFix"></image>
<image class="right-img" :src="$util.img('public/uniapp/diy/style11-2.png')" mode="widthFix"></image>
</view>
</view>
</view>
</view>
</block>
<view class="style12" v-if="value.style == 'style-12'">
<view
class="style12-title"
:style="{
fontSize: value.fontSize * 2 + 'rpx',
color: value.textColor,
fontWeight: value.fontWeight
}"
>
{{ value.text }}
</view>
<text class="style12-sub-title" :style="{ color: value.subTitle.color }">{{ value.subTitle.text }}</text>
<view class="style12-more" v-if="value.more.isShow" :style="{ color: value.more.color }" @click.stop="$util.diyRedirectTo(value.more.link)">
<text>{{ value.more.text }}</text>
<view class="iconfont icon-right" :style="{ color: value.more.color }"></view>
</view>
</view>
<view class="style13" v-else-if="value.style == 'style-13'">
<image class="left-img" :src="$util.img('public/uniapp/diy/style13-1.png')" mode="widthFix"></image>
<view
class="style13-title"
:style="{
fontSize: value.fontSize * 2 + 'rpx',
color: value.textColor,
fontWeight: value.fontWeight
}"
>
{{ value.text }}
</view>
<image class="right-img" :src="$util.img('public/uniapp/diy/style13-1.png')" mode="widthFix"></image>
</view>
<view class="style14" v-else-if="value.style == 'style-14'">
<view class="title-wrap">
<view class="text">
<text :style="{ fontSize: value.fontSize * 2 + 'rpx', color: value.textColor, fontWeight: value.fontWeight }">
{{ value.text }}
</text>
<text class="zone" :style="{ fontSize: value.fontSize * 2 + 'rpx', fontWeight: value.fontWeight }">专区</text>
</view>
<text class="iconfont icon-danxuan-xuanzhong" :style="{ color: value.textColor, fontWeight: value.fontWeight }"></text>
<text class="iconfont icon-danxuan-xuanzhong" :style="{ color: value.textColor, fontWeight: value.fontWeight }"></text>
<text class="iconfont icon-danxuan-xuanzhong" :style="{ color: value.textColor, fontWeight: value.fontWeight }"></text>
<view
class="sub-title"
v-show="value.subTitle.text"
:style="{ fontSize: value.subTitle.fontSize * 2 + 'rpx', color: value.subTitle.color }"
>
{{ value.subTitle.text }}
</view>
</view>
<view v-show="value.more.isShow == 1" class="more" :style="{ color: value.more.color }">
<text>{{ value.more.text }}</text>
<text class="iconfont icon-right"></text>
</view>
</view>
<!-- 图十五 -->
<view class="style15" v-else-if="value.style == 'style-15'">
<view class="title-wrap">
<view class="ornament" style="margin-right: 40rpx;">
<text class="line" :style="{ color: value.textColor, fontWeight: value.fontWeight }"></text>
<text class="line" :style="{ color: value.textColor, fontWeight: value.fontWeight }"></text>
<text class="my">
<text class="yuan" :style="{ backgroundColor: value.textColor, fontWeight: value.fontWeight }"></text>
<text class="vertical" :style="{ color: value.textColor, fontWeight: value.fontWeight }"></text>
</text>
</view>
<text :style="{ fontSize: value.fontSize * 2 + 'rpx', color: value.textColor, fontWeight: value.fontWeight }">
{{ value.text }}
</text>
<view class="ornament" style="margin-left: 40rpx;">
<text class="line" :style="{ color: value.textColor, fontWeight: value.fontWeight }"></text>
<text class="line" :style="{ color: value.textColor, fontWeight: value.fontWeight }"></text>
<text class="my">
<text class="yuan" :style="{ backgroundColor: value.textColor, fontWeight: value.fontWeight }"></text>
<text class="vertical" :style="{ color: value.textColor, fontWeight: value.fontWeight }"></text>
</text>
</view>
</view>
<view
class="sub-title"
v-show="value.subTitle.text"
:style="{ fontSize: value.subTitle.fontSize * 2 + 'rpx', color: value.subTitle.color }"
>
{{ value.subTitle.text }}
</view>
</view>
<!-- 图十六 -->
<view class="style16" v-if="value.style == 'style-16'">
<view
class="style16-title"
:style="{
fontSize: value.fontSize * 2 + 'rpx',
color: value.textColor,
fontWeight: value.fontWeight
}"
>
{{ value.text }}
</view>
<view class="style16-sub-title" v-show="value.subTitle.text" :style="{ color: value.subTitle.color, backgroundColor: value.subTitle.bgColor }">
<text :class="['js-icon', value.subTitle.icon]" :style="{ backgroundColor: value.subTitle.bgColor }"></text>
<text :style="{ fontWeight: value.subTitle.fontWeight }">{{ value.subTitle.text }}</text>
</view>
<view class="style16-more" v-if="value.more.isShow" :style="{ color: value.more.color }" @click.stop="$util.diyRedirectTo(value.more.link)">
<text>{{ value.more.text }}</text>
<view class="iconfont icon-right" :style="{ color: value.more.color }"></view>
</view>
</view>
</view>
</view>
</template>
<script>
//
export default {
name: 'diy-text',
props: {
value: {
type: Object
}
},
data() {
return {};
},
created() {},
computed: {
warpCss() {
var obj = '';
obj += 'background-color:' + this.value.componentBgColor + ';';
if (this.value.componentAngle == 'round') {
obj += 'border-top-left-radius:' + this.value.topAroundRadius * 2 + 'rpx;';
obj += 'border-top-right-radius:' + this.value.topAroundRadius * 2 + 'rpx;';
obj += 'border-bottom-left-radius:' + this.value.bottomAroundRadius * 2 + 'rpx;';
obj += 'border-bottom-right-radius:' + this.value.bottomAroundRadius * 2 + 'rpx;';
}
return obj;
}
},
methods: {}
};
</script>
<style lang="scss">
.diy-text {
padding: 0;
display: flex;
justify-content: center;
}
.diy-text .title {
margin: 0;
color: #333;
display: flex;
align-items: center;
width: 100%;
justify-content: center;
}
.diy-text .title2 {
margin: 0;
color: #333;
display: flex;
align-items: center;
width: 100%;
}
.diy-text .title > text {
padding: 0 15rpx;
}
.left {
transform: translateY(0%);
width: 30rpx;
height: 24rpx;
}
.right {
transform: translateY(0%);
width: 30rpx;
height: 24rpx;
}
.style2 {
width: 100%;
text-align: center;
.xian {
width: 100%;
height: 2rpx;
vertical-align: top;
position: relative;
}
.line-triangle {
background: transparent !important;
position: absolute;
border: 12rpx solid #000;
border-top-color: transparent !important;
border-left-color: transparent !important;
left: 50%;
bottom: -10rpx;
margin-left: -12rpx;
transform: rotate(45deg);
}
}
.style3 {
width: 100%;
text-align: center;
.inner-line {
width: 100%;
height: 2rpx;
vertical-align: top;
position: relative;
}
.line-short {
width: 324rpx;
height: 6rpx;
position: absolute;
bottom: 0;
left: 50%;
margin-left: -162rpx;
}
}
.style4 {
text-align: center;
width: 100%;
.line-box {
height: 5rpx;
position: relative;
text-align: center;
margin-top: 5rpx;
width: 100%;
.line-left {
display: inline-block;
position: absolute;
top: 8rpx;
left: 0;
bottom: 0;
width: calc((100% - 44rpx) / 2);
height: 2rpx;
}
.line-center {
width: 12rpx;
height: 12rpx;
border: 2rpx solid;
display: inline-block;
-webkit-transform: rotate(45deg);
transform: rotate(45deg);
position: absolute;
top: 0;
left: 50%;
bottom: 0;
margin-left: -6rpx;
}
.line-right {
display: inline-block;
position: absolute;
top: 8rpx;
bottom: 0;
right: 0;
width: calc((100% - 44rpx) / 2);
height: 2rpx;
}
}
}
.style5 {
text-align: center;
position: relative;
.style5-box {
display: inline-block;
padding: 10rpx !important;
border: 1rpx solid;
position: relative;
.style5-title {
display: inline-block;
padding: 10rpx 30rpx;
border: 1rpx solid;
line-height: 1;
}
.line-left {
height: 10rpx;
position: absolute;
width: 80rpx;
top: 50%;
margin-top: -4rpx;
left: 0;
margin-left: -60rpx;
}
.line-right {
height: 10rpx;
position: absolute;
width: 80rpx;
top: 50%;
margin-top: -4rpx;
right: 0;
margin-right: -60rpx;
}
}
}
.style6 {
text-align: center;
position: relative;
.style6-box {
display: inline-block;
position: relative;
.style6-title {
display: inline-block;
padding: 6rpx 50rpx;
border: 1rpx solid;
position: relative;
z-index: 2;
padding-bottom: 6rpx;
background: rgb(255, 255, 255);
line-height: 1.5;
}
.style6-wrap {
position: absolute;
display: inline-block;
width: 100%;
top: 10rpx;
right: 4rpx;
bottom: -10rpx;
left: 10rpx;
border: 1rpx solid;
z-index: 0;
box-sizing: border-box;
}
}
}
.style7 {
text-align: center;
position: relative;
.style7-box {
display: inline-block;
position: relative;
.style7-title {
display: inline-block;
padding: 0rpx 50rpx;
position: relative;
z-index: 2;
padding-bottom: 6rpx;
color: rgb(255, 255, 255);
line-height: 1.5;
}
.style7-wrap {
width: 100%;
box-sizing: border-box;
position: absolute;
top: 10rpx;
right: 4rpx;
bottom: -10rpx;
left: 10rpx;
border: 1rpx solid;
z-index: 0;
}
}
}
.style8 {
position: relative;
text-align: left;
.style8-box {
text-align: left !important;
.style8-title{
margin-left: 20rpx;
}
.style8-wrap {
height: 100%;
position: absolute;
top: 50%;
transform: translateY(-50%);
left: 0;
width: 4rpx;
}
}
}
.style9 {
width: 100%;
.style9-box {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 100%;
.style9-center {
display: flex;
justify-content: center;
align-items: center;
width: calc(100% - 264rpx);
position: relative;
text {
max-width: 100%;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.left-img {
width: 40rpx;
height: 40rpx;
text-align: center;
flex-shrink: 0;
image {
width: 100%;
height: 100%;
}
}
.right-img {
width: 40rpx;
height: 40rpx;
text-align: center;
flex-shrink: 0;
image {
width: 100%;
height: 100%;
}
}
.style9-more {
display: flex;
position: absolute;
right: -140rpx;
/* #ifdef MP-WEIXIN */
right: -120rpx;
/* #endif */
top: 14rpx;
line-height: 1;
align-items: center;
.iconfont {
line-height: 1;
}
}
.sub-title {
line-height: 1;
}
}
}
}
.style10 {
width: 100%;
.style10-box {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 100%;
.style10-center {
display: flex;
justify-content: center;
align-items: center;
width: calc(100% - 264rpx);
position: relative;
text {
max-width: 100%;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
padding-bottom: 8rpx;
z-index: 99;
}
.left-img {
padding-bottom: 13rpx;
width: 40rpx;
height: 40rpx;
text-align: center;
flex-shrink: 0;
image {
width: 100%;
height: 100%;
}
}
.center-img {
width: 198rpx;
height: 18rpx;
text-align: center;
flex-shrink: 0;
position: absolute;
bottom: 26rpx;
z-index: 5;
image {
width: 100%;
height: 100%;
}
}
.right-img {
padding-bottom: 13rpx;
width: 40rpx;
height: 40rpx;
text-align: center;
flex-shrink: 0;
image {
width: 100%;
height: 100%;
}
}
.style10-more {
display: flex;
position: absolute;
right: -140rpx;
/* #ifdef MP-WEIXIN */
right: -120rpx;
/* #endif */
top: 14rpx;
line-height: 1;
align-items: center;
.iconfont {
line-height: 1;
}
}
.sub-title {
line-height: 1;
}
}
}
}
.style11 {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
.style11-box {
width: 100%;
margin: 10rpx 0;
.style11-conter {
.style11-conter-box {
display: flex;
justify-content: space-between;
align-items: center;
position: relative;
.left {
display: flex;
width: 70%;
flex-direction: column;
justify-content: space-between;
height: 100%;
margin: 15rpx 0;
padding-left: 34rpx;
z-index: 9;
.style11-title {
width: 100%;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
.style11-sub {
letter-spacing: 14rpx;
width: 100%;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
}
}
.style11-more {
display: flex;
margin-right: 20rpx;
}
}
.center-img {
width: 61rpx;
position: absolute;
bottom: -26rpx;
left: 16rpx;
z-index: 0;
}
.right-img {
width: 35rpx;
position: absolute;
top: -14rpx;
left: 172rpx;
z-index: 0;
}
}
}
}
.style12 {
display: flex;
align-items: center;
width: 100%;
padding: 20rpx;
.style12-title {
text-align: left;
max-width: 200rpx;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
.style12-sub-title {
text-align: left;
max-width: 300rpx;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
.style12-more {
display: flex;
align-items: center;
margin-left: auto;
text {
padding: 0;
max-width: 160rpx;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
}
}
.style13 {
display: flex;
align-items: center;
justify-content: center;
.style13-title {
max-width: 420rpx;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
margin: 0 10rpx;
}
image {
height: 50rpx;
width: 76rpx;
}
.right-img {
transform: rotateY(180deg);
}
}
.style14 {
display: flex;
justify-content: space-between;
text-align: initial;
align-items: center;
flex: 1;
padding: 0 20rpx;
text {
padding: 0 !important;
}
.title-wrap {
.text {
display: inline-block;
}
.iconfont {
font-size: 24rpx;
&:nth-of-type(1) {
margin-left: 20rpx;
}
&:nth-of-type(2) {
opacity: 0.6;
}
&:nth-of-type(3) {
opacity: 0.4;
}
}
.sub-title {
opacity: 0.6;
}
.more {
text:first-child {
font-size: 28rpx;
}
}
}
}
.style15 {
flex: 1;
text {
padding: 0 !important;
line-height: 1;
}
.title-wrap {
display: flex;
justify-content: center;
align-items: center;
}
.ornament {
display: flex;
align-items: flex-end;
.line {
border-left: 8rpx solid;
transform: rotate(40deg);
border-radius: 40rpx;
height: 28rpx;
display: block;
margin-right: 12rpx;
&:nth-of-type(2) {
height: 40rpx;
margin-right: 10rpx;
position: relative;
top: 4rpx;
}
}
.my {
transform: rotate(40deg);
line-height: 0;
position: relative;
top: 4rpx;
.yuan {
font-size: 100rpx;
border-radius: 50%;
width: 8rpx;
height: 8rpx;
display: block;
}
.vertical {
border-left: 8rpx solid;
height: 20rpx;
margin-top: 4rpx;
display: inline-block;
border-radius: 40rpx;
}
}
}
.sub-title {
opacity: 0.6;
text-align: center;
}
}
.style16 {
display: flex;
align-items: center;
width: 100%;
padding: 20rpx;
.style16-more {
display: flex;
align-items: center;
margin-left: auto;
& > text {
max-width: 200rpx;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
}
.style16-title {
text-align: left;
max-width: 200rpx;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
.style16-sub-title {
margin-left: 20rpx;
text-align: left;
max-width: 300rpx;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
border-radius: 34rpx;
background-image: radial-gradient(transparent 60%, #fff);
height: 50rpx;
display: flex;
align-items: center;
padding: 0 20rpx;
position: relative;
&> .js-icon {
padding: 8rpx;
background-image: radial-gradient(transparent 30%, #fff);
border-radius: 50%;
margin-left: -20rpx;
margin-right: 6rpx;
font-size: 28rpx;
line-height: 1;
}
}
}
</style>

108
components/diy-components/diy-video.vue

@ -0,0 +1,108 @@
<template>
<view class="" :style="boxStyle">
<view class="goods-video" v-show="switchMedia == 'video'">
<video :id="videoId" :src="$util.img(value.videoUrl)" :poster="$util.img(value.imageUrl)"
:style="videoWarpCss + boxStyle" objectFit="contain" :controls="true" :show-fullscreen-btn="true"
:auto-pause-if-navigate="false" :auto-pause-if-open-native="false" :show-mute-btn="true" :autoplay="autoplay"
@pause="pauseVideo()"></video>
</view>
<view style="position: relative;" v-show="switchMedia == 'img'" @click="changeType()">
<img class="play_icon" :src="$util.img('upload/weapp/user/play_icon.png')" alt="">
<image class="goods-img" :style="videoWarpCss + boxStyle" :src="$util.img(value.imageUrl)" mode="scaleToFill"
style="width: 100%;">
</image>
</view>
</view>
</template>
<script>
//
export default {
name: 'diy-video',
props: {
value: {
type: Object
}
},
data() {
return {
videoId: 'video' + this._uid,
switchMedia: "img",
autoplay: false,
videoKey: 1,
boxStyle: {},
videoContext: null
};
},
created() {
uni.$on('videoStop', () => {
this.pauseVideo()
})
// uni.$on('videoStart', () => {
// this.changeType()
// })
this.videoContext = uni.createVideoContext(this.videoId)
},
computed: {
videoWarpCss: function () {
var obj = '';
if (this.value.componentAngle == 'round') {
obj += 'border-top-left-radius:' + this.value.topAroundRadius * 2 + 'rpx;';
obj += 'border-top-right-radius:' + this.value.topAroundRadius * 2 + 'rpx;';
obj += 'border-bottom-left-radius:' + this.value.bottomAroundRadius * 2 + 'rpx;';
obj += 'border-bottom-right-radius:' + this.value.bottomAroundRadius * 2 + 'rpx;';
}
this.calcStyle()
return obj;
}
},
methods: {
calcStyle() {
// uni.getSystemInfo({
// success: res => {
// const { screenWidth, screenHeight, ratio } = res
// }
// });
this.$nextTick(() => {
this.boxStyle = `width: 100%; height: ${this.value.imgHeight / (this.value.imgWidth / 690)}rpx;`
// this.boxStyle = {
// width: '100%',
// height: this.value.imgHeight / (this.value.imgWidth / 690) + 'rpx'
// }
})
},
changeType() {
this.switchMedia = "video";
this.autoplay = true;
this.videoContext.play();
},
pauseVideo() {
this.switchMedia = "img";
this.autoplay = false;
this.videoContext.pause();
}
}
};
</script>
<style scoped>
video {
width: 100%;
}
.play_icon {
width: 80rpx;
height: 80rpx;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
z-index: 10;
}
</style>

127
components/egg.vue

@ -0,0 +1,127 @@
<template>
<!-- IP选择器 -->
<view class="">
<picker mode='selector' @change="selectIP" @cancel="selectIPStatus = false; IPclickNum = 0" :value="selectIPindex"
:range="IPArray" range-key="title">
<view class="uni-input" style="text-align: center;color: #fff;background-color: #000;" v-if="selectIPStatus">
<text>当前服务器</text>
<text>{{ IPArray[selectIPindex].title }}</text>
</view>
</picker>
<!-- 自定义IP弹出框 -->
<uniPopup ref="changeIPRef">
<view class=""
style="width: 80vw;height: 30vh;background-color: #FFFFFF;border-radius: 20rpx;padding: 30rpx;text-align: center;">
<view style="width: 100%;font-size: 40rpx;border-bottom: 1rpx solid #e3e3e3;margin-bottom: 20rpx;">自定义服务器</view>
<view class="">
<textarea v-model="ipConfigChange" style="border: 1rpx solid #e3e3e3;padding: 20rpx;" :maxlength="80" focus
auto-height placeholder-style="color:#ffee89" placeholder="注意使用英文标点符号与大小写" />
<text style="color: #dadada;font-size: 20rpx;">参考案例<text
style="color: #ef6d53;">https://www.baidu.com/</text></text>
<button type="primary" style="position: absolute;bottom: 0;width: 90%;margin-bottom: 20rpx;"
@tap="comfirmSelectIP(selectIPindex, ipConfigChange)">确定</button>
</view>
</view>
</uniPopup>
</view>
</template>
<script>
import uniPopup from "./uni-popup/uni-popup"
export default {
name: "egg",
components: {
uniPopup
},
props: {
// (1s=1000ms)
IPArray: {
type: Array
},
defaultIP: {
type: String,
},
time: {
type: Number,
default: 1200
},
//
clickNum: {
type: Number,
default: 8
}
},
data() {
return {
ipConfigChange: "", // IP
selectIPStatus: false,
selectIPindex: 0,
IPclickNum: 0,
}
},
methods: {
// IP 使 this.$refs.switchIp.openSelectIP()
openSelectIP() {
this.IPclickNum++
let countNum = this.clickNum //
// if (this.IPclickNum > (countNum - countNum / 2) && this.IPclickNum < countNum) {
// uni.showToast({
// title: '' + (countNum - this.IPclickNum) + '',
// icon: "none",
// duration: 800
// });
// }
if (this.IPclickNum >= countNum) {
this.IPclickNum = 0
// IP
this.IPArray.find((item, index) => {
if (item.ipConfig == this.defaultIP) {
this.selectIPindex = index
}
})
uni.showToast({
title: '您当前正在使用IP:' + this.defaultIP,
icon: "none",
duration: 3000
});
this.selectIPStatus = true // IP
}
//
setTimeout(() => {
this.IPclickNum = 0
}, this.time)
},
// IP
selectIP(event) {
//
this.selectIPindex = event.detail.value
// IP
if (event.detail.value === 2) {
// IP便
this.ipConfigChange = this.IPArray[event.detail.value].ipConfig
// IP
this.$refs.changeIPRef.open()
}
this.comfirmSelectIP(event.detail.value)
},
// IP
comfirmSelectIP(index, value) {
// IP
if (value && index === 2) {
this.IPArray[index].ipConfig = value
this.$refs.changeIPRef.close()
}
//
this.selectIPStatus = false
// IP
this.$emit("change", this.IPArray[index])
uni.showToast({
title: '请注意!正在使用' + JSON.stringify(this.IPArray[index]),
icon: "none",
duration: 3000
});
},
}
}
</script>

1523
components/goods-item/index.vue

File diff suppressed because it is too large

39
components/goodsPrice.vue

@ -0,0 +1,39 @@
<template>
<text v-if="userInfo.show_price && token">
<text class="price-symbol price-font">¥</text>
<template v-if="goodsSkuDetail.discount_price > 0">
<text class="price price-font">{{ goodsSkuDetail.discount_price }}</text>
</template>
<template v-else>
<template v-if="goodsSkuDetail.member_price > 0">
<text class="price price-font">{{ goodsSkuDetail.member_price }}</text>
</template>
<template v-else>
<text class="price price-font">{{ goodsSkuDetail.price}}</text>
</template>
</template>
</text>
</template>
<script>
import { mapGetters } from 'vuex';
export default {
props: {
goodsSkuDetail: {
type: Object
}
},
data() {
return {
token: uni.getStorageSync('token')
};
},
computed: {
...mapGetters(['userInfo'])
},
// inject: ['showDiscount']
};
</script>
<style lang="scss" scoped></style>

992
components/horizontalGoodsItem.vue

@ -0,0 +1,992 @@
<template>
<!-- 一行一个 -->
<div class="seckill-item">
<div class="cover" @click="click">
<view class="cover1"><img :src="item[coverName]" /></view>
<!-- <view class="cover1">
<image :src="$util.img(item[coverName])" alt="" />
</view> -->
<!-- <image :src="$util.img(item.goods_image)" mode="aspectFill"></image> -->
<!-- <view class="time">销量{{ item.sale_num }}</view> -->
<!-- <div class="time">23:23:46</div> -->
</div>
<div class="right">
<div class="title" @click="click">{{ item.goods_name }}</div>
<div class="labels-1" @click="click">
<div class="label-item">产地{{ item.address }}</div>
<div class="label-item">规格{{ item.spec_name||'-' }}</div>
<div class="label-item" v-if=" item.execu_content">执行标准{{ item.execu_content.title ||'-'}}</div>
<div class="label-item">生产企业{{ item.business }}</div>
</div>
<div class="bottom" v-if="userInfo.show_price && token">
<div class="price" @click="click">
¥
<text class="price1">
{{
parseFloat(showPrice(item))
.toFixed(2)
.split('.')[0]
}}
</text>
.
<text>
{{
parseFloat(showPrice(item))
.toFixed(2)
.split('.')[1]
}}
</text>
/{{ item.unit ? item.unit : '' }}
</div>
<div style="display: flex;align-items: ceter;margin-top: 20rpx;" v-if="item.stock">
<view slot="minus" class="minus" @click.stop="numChange(item, 'minus')">
<u-icon name="minus-circle-fill" size="20" color="var(--base-color)"></u-icon>
</view>
<view class="df aic jcsa" style="margin:0 24rpx;" @click="focus(item)">
{{ item.cart_num || 0 }}
</view>
<view slot="plus" class="minus" @click.stop="numChange(item, 'add')">
<u-icon name="plus-circle-fill" size="20" color="var(--base-color)"></u-icon>
</view>
</div>
<div style="display: flex;align-items: ceter;margin-top: 20rpx;" v-else>库存不足</div>
</div>
</div>
<uni-popup ref="skuPopup" type="bottom" class="sku-layer" v-if="goods_Item_Detail">
<view class="sku-info">
<view class="header">
<view class="img-wrap" @click="previewMedia()">
<image :src="$util.img(goods_Item_Detail.sku_image, { size: 'mid' })" mode="aspectFit" />
</view>
<view class="main">
<view class="goods_name">{{ goods_Item_Detail.goods_name }}</view>
<view class="price-wrap">
<text class="unit price-style small"></text>
<block>
<text class="price price-style large">
{{
parseFloat(showPrice(goods_Item_Detail))
.toFixed(2)
.split('.')[0]
}}
</text>
<text class="unit price-style small">
.{{
parseFloat(showPrice(goods_Item_Detail))
.toFixed(2)
.split('.')[1]
}}
</text>
</block>
</view>
<view class="stock">
<block v-if="goods_Item_Detail.stock_show">
库存{{ goods_Item_Detail.stock }}
</block>
</view>
</view>
<view class="sku-close iconfont icon-close" @click="closeSkuPopup()"></view>
</view>
<view class="body-item">
<scroll-view scroll-y class="wrap">
<view class="number-wrap">
<view class="number-line">
<text class="title font-size-base">购买数量</text>
<text class="limit-txt color-base-text" v-if="limitNumber > 0">
(每人限购{{ limitNumber }})
</text>
<text v-if="
goods_Item_Detail.maxBuy > 0 && goods_Item_Detail.minBuy > 1
" class="limit-txt color-base-text">
({{ goods_Item_Detail.minBuy }}件起售限购{{
goods_Item_Detail.maxBuy
}})
</text>
<text v-else-if="goods_Item_Detail.maxBuy > 0" class="limit-txt color-base-text">
(限购{{ goods_Item_Detail.maxBuy }})
</text>
<text v-else-if="goods_Item_Detail.minBuy > 1" class="limit-txt color-base-text">
({{ goods_Item_Detail.minBuy }}件起售)
</text>
<view class="number">
<button type="default" class="decrease color-line-border"
:class="{ disabled: decreaseDisabled }" @click="changeNum('-')">
-
</button>
<input id="tet" type="number"
class="uni-input color-line-border font-size-goods-tag" disabled="true"
v-model="number" placeholder="0" />
<button type="default" class="increase color-line-border"
:class="{ disabled: increaseDisabled }" @click="changeNum('+')">
+
</button>
</view>
</view>
</view>
</scroll-view>
</view>
<u-number-keyboard mode="number" @change="change" :dotDisabled="true"
@backspace="backspace"></u-number-keyboard>
<view class="footer">
<button type="primary" v-if="goods_Item_Detail.stock" @click="confirm()">
加入购物车
</button>
<button type="primary" v-else disabled="true">库存不足</button>
</view>
</view>
</uni-popup>
</div>
</template>
<script>
import { mapGetters } from 'vuex';
export default {
name: 'horizontalGoodsItem',
props: {
item: {
default: () => {}
},
coverName: {
default: 'cover'
}
},
data() {
return {
token: uni.getStorageSync('token'),
goodsSkuDetail: {
goods_id: 0,
goods_service: []
},
goods_name: '',
discount_price: '',
sku_id: '',
unit: '',
stock: Number,
goods_image: '',
number: 1,
limitNumber: 0, //
minNumber: 0,
goods_Item_Detail: {},
loading: false,
keyboardShow: true
};
},
computed: {
...mapGetters(['userInfo']),
decreaseDisabled: function() {
let min = this.goods_Item_Detail.minBuy > 0 ? this.goods_Item_Detail.minBuy : 1;
return this.goods_Item_Detail.number <= min;
},
increaseDisabled: function() {
let max =
this.goods_Item_Detail.maxBuy > 0 &&
this.goods_Item_Detail.maxBuy < this.goods_Item_Detail.stock ?
this.goods_Item_Detail.maxBuy :
this.goods_Item_Detail.stock;
return this.goods_Item_Detail.number >= max;
},
},
methods: {
backspace() {
let str = String(this.number);
str = str.slice(0, -1);
this.number = str;
},
change(e) {
if (!this.number) {
this.number = e;
} else {
this.number = this.number + String(e);
}
},
click() {
this.$emit('click', this.item);
},
inputBlur(event, item) {
const v = event.detail.value;
item.cart_num = 1;
const zero = /^(0{2,})|[^0-9]/g;
let final = 0;
if (!v) {
final = 0;
} else {
final = v.toString().replace(zero, v => {
return 0;
});
if (final.split('')[0] * 1 === 0) {
final = final.slice(1) - 0 || 0;
}
}
this.$nextTick(() => {
item.cart_num = final.toString() || 0;
this.$api.sendRequest({
url: '/api/cart/add',
data: {
num: v,
sku_id: item.sku_id,
is_all: 1
},
success: () => {
this.$store.dispatch('getCartNumber');
}
});
});
},
goodsTag(data) {
return data.label_name || '';
},
showPrice(data) {
let price = data.discount_price;
if (data.member_price && parseFloat(data.member_price) < parseFloat(price))
price = data.member_price;
return price;
},
focus(item) {
this.number = item.cart_num;
uni.hideKeyboard();
this.getGoodsItem(item);
uni.removeStorageSync('buyer_message');
},
changeNum(tag) {
if (this.goods_Item_Detail.max_buy) {
// is_limit limit_type 1 2
if (this.goods_Item_Detail.is_limit && this.goods_Item_Detail.limit_type == 1) {
if (this.goods_Item_Detail.number >= this.goods_Item_Detail.max_buy && tag == "+") {
this.$util.showToast({
title: `每人限购${this.goods_Item_Detail.max_buy}`
});
return
}
} else if (this.goods_Item_Detail.is_limit && this.goods_Item_Detail.limit_type == 2) {
if (this.goods_Item_Detail.purchased_num >= this.goods_Item_Detail.max_buy) {
this.$util.showToast({
// title: `${this.goods_Item_Detail.max_buy}${this.goods_Item_Detail.purchased_num}`
title: `每人长期限购${this.goods_Item_Detail.max_buy}`
});
return
}
}
}
if (this.goods_Item_Detail.stock == 0) return;
var min = 1;
var stock = this.goods_Item_Detail.stock;
if (this.maxBuy == 1) {
stock = 1;
}
if (this.goods_Item_Detail.is_limit == 1 && this.maxBuy > 0 && this.maxBuy < stock)
stock = this.maxBuy;
if (
this.goods_Item_Detail.is_limit == 1 &&
this.goods_Item_Detail.limit_type == 2 &&
this.maxBuy > 0 &&
this.goods_Item_Detail.purchased_num > 0
) {
let maxBuy = this.maxBuy - this.goods_Item_Detail.purchased_num;
stock =
maxBuy < this.goods_Item_Detail.stock ? maxBuy : this.goods_Item_Detail.stock;
}
if (this.minBuy > 1) {
min = this.minBuy;
}
if (tag == '+') {
//
if (this.number < stock) {
this.number++;
} else {
if (this.number >= this.goods_Item_Detail.stock) {
this.$util.showToast({
title: '库存不足'
});
return;
}
if (this.goods_Item_Detail.is_limit == 1 && this.maxBuy > 0) {
if (this.goods_Item_Detail.limit_type == 1) {
this.$util.showToast({
title: '该商品每次最多购买' + this.maxBuy + this.goods_Item_Detail.unit
});
return;
}
if (this.goods_Item_Detail.limit_type == 2) {
let message =
'该商品每人限购' + this.maxBuy + this.goods_Item_Detail.unit;
message +=
this.goods_Item_Detail.purchased_num > 0 ?
',您已购买了' +
this.goods_Item_Detail.purchased_num +
this.goods_Item_Detail.unit :
'';
this.$util.showToast({
title: message
});
return;
}
}
if (
this.type == 'seckill' &&
this.goods_Item_Detail.seckill_id &&
this.goods_Item_Detail.num > 0
) {
this.$util.showToast({
title: '该商品每人限购' +
this.goods_Item_Detail.num +
this.goods_Item_Detail.unit
});
return;
}
if (
this.type == 'presale' &&
this.goods_Item_Detail.presale_id &&
this.goods_Item_Detail.presale_num > 0
) {
this.$util.showToast({
title: '该商品每人限购' +
this.goods_Item_Detail.presale_num +
this.goods_Item_Detail.unit
});
return;
}
}
} else if (tag == '-') {
//
if (this.number > min) {
this.number -= 1;
} else {
if (this.minBuy > 1) {
this.$util.showToast({
title: '该商品' + this.minBuy + '件起售'
});
}
return;
}
}
if (this.number > this.limitNumber && this.limitNumber) {
this.number = this.limitNumber;
}
},
//
keyInput(flag, callback) {
setTimeout(() => {
var stock = this.goods_Item_Detail.stock;
// 0
if (this.goods_Item_Detail.stock == 0) {
this.number = 0;
return;
}
//
if (flag && this.number.length == 0) this.number = 1;
// 0
if (flag && (this.number <= 0 || isNaN(this.number))) this.number = 1;
if (this.number > stock) {
this.number = stock;
}
//
if (this.minBuy > 1 && this.number < this.minBuy) {
this.number = this.minBuy;
}
if (flag) this.number = parseInt(this.number);
if (callback) callback();
}, 0);
},
//
confirm() {
//
uni.removeStorageSync('delivery');
if (this.preview) {
this.$util.showToast({
title: '预览商品无法购买'
});
return;
}
if (!uni.getStorageSync('token')) {
this.$refs.login.open();
return;
}
//
this.keyInput(true, () => {
if (this.goods_Item_Detail.stock == 0) {
this.$util.showToast({
title: '商品已售罄'
});
return;
}
if (this.number.length == 0 || this.number <= 0) {
this.$util.showToast({
title: '购买数量不能小于等于0'
});
return;
}
if (this.goods_Item_Detail.buy_num > this.goods_Item_Detail.stock) {
this.$util.showToast({
title: '库存小于最低购买数量'
});
return;
}
if (this.number > this.goods_Item_Detail.stock) {
this.$util.showToast({
title: '库存不足'
});
return;
}
if (
this.goods_Item_Detail.is_limit == 1 &&
this.goods_Item_Detail.limit_type == 1 &&
this.maxBuy > 0 &&
this.number > this.maxBuy
) {
this.$util.showToast({
title: '该商品每次最多购买' + this.maxBuy + this.goods_Item_Detail.unit
});
return;
}
if (
this.goods_Item_Detail.is_limit == 1 &&
this.goods_Item_Detail.limit_type == 2 &&
this.maxBuy > 0 &&
this.number + this.goods_Item_Detail.purchased_num > this.maxBuy
) {
let message = '该商品每人限购' + this.maxBuy + this.goods_Item_Detail.unit;
message +=
this.goods_Item_Detail.purchased_num > 0 ?
',您已购买了' +
this.goods_Item_Detail.purchased_num +
this.goods_Item_Detail.unit :
'';
this.$util.showToast({
title: message
});
return;
}
if (
this.type == 'join_cart' &&
this.goods_Item_Detail.is_limit == 1 &&
this.maxBuy > 0 &&
this.cartNumber + this.number > this.maxBuy
) {
this.$util.showToast({
title: '该商品每人限购' + this.maxBuy + this.goods_Item_Detail.unit
});
return;
}
if (this.goods_Item_Detail.max_buy) {
if (this.goods_Item_Detail.purchased_num >= this.goods_Item_Detail.max_buy) {
this.$util.showToast({
title: `每人限购${this.goods_Item_Detail.max_buy}件,您已购买${this.goods_Item_Detail.purchased_num}`
});
return
}
}
if (this.goods_Item_Detail.max_buy) {
// is_limit limit_type 1 2
if (this.goods_Item_Detail.is_limit && this.goods_Item_Detail.limit_type == 1) {
if (this.number > this.goods_Item_Detail.max_buy) {
this.$util.showToast({
title: `每人限购${this.goods_Item_Detail.max_buy}`
});
return
}
} else if (this.goods_Item_Detail.is_limit && this.goods_Item_Detail.limit_type == 2) {
if (this.goods_Item_Detail.purchased_num >= this.goods_Item_Detail.max_buy) {
this.$util.showToast({
// title: `${this.goods_Item_Detail.max_buy}${this.goods_Item_Detail.purchased_num}`
title: `每人长期限购${this.goods_Item_Detail.max_buy}`
});
return
}
}
}
if (this.btnSwitch) return;
this.btnSwitch = true;
this.$api.sendRequest({
url: '/api/cart/add',
data: {
sku_id: this.goods_Item_Detail.sku_id,
num: this.number,
is_all: 1
},
success: res => {
var data = res.data;
if (data > 0) {
this.$util.showToast({
title: '加入购物车成功'
});
this.cartNumber += this.number;
if (this.callback) this.callback();
this.$store.dispatch('getCartNumber');
}
// uni.$emit('refresh', true);
this.$refs.skuPopup.close();
this.btnSwitch = false;
},
fail: res => {
this.$refs.skuPopup.close();
this.btnSwitch = false;
}
});
});
},
getGoodsItem(item) {
this.loading = true;
this.$api.sendRequest({
url: '/api/goodssku/detail',
data: {
goods_id: item.goods_id
},
success: res => {
this.goods_Item_Detail = res.data.goods_sku_detail;
this.goods_Item_Detail.goods_spec_format = JSON.parse(
res.data.goods_sku_detail.goods_spec_format
);
this.goods_Item_Detail.number = item.cart_num;
this.$refs.skuPopup.open();
uni.$emit('cartBottomShow', false);
this.loading = false;
}
});
},
numChange(item, type) {
if (item.max_buy) {
// is_limit limit_type 1 2
if (item.is_limit && item.limit_type == 1) {
if (item.cart_num >= item.max_buy && type == "add") {
this.$util.showToast({
title: `每人限购${item.max_buy}`
});
return
}
} else if (item.is_limit && item.limit_type == 2) {
if (item.purchased_num >= item.max_buy) {
this.$util.showToast({
// title: `${item.max_buy}${item.purchased_num}`
title: `每人长期限购${item.max_buy}`
});
return
}
}
}
if (type == 'add') {
if (item.cart_num >= item.stock) {
this.$util.showToast({
title: '库存不足'
});
return;
}
}
item.cart_num = Number(item.cart_num);
let setp = 1;
item.cart_num ? item.cart_num : (item.cart_num = 0);
if (type == 'minus' && !item.cart_num) {
return;
}
if (!item.cart_num || item.is_multiple) {
setp = item.min_buy || 1;
} else {
if (type == 'add') {
setp = item.cart_num >= item.min_buy ? 1 : item.min_buy;
} else {
setp = item.cart_num == item.min_buy ? item.min_buy : 1;
}
}
type == 'add' ? (item.cart_num += setp) : (item.cart_num -= setp);
this.$forceUpdate();
this.$api.sendRequest({
url: '/api/cart/add',
data: {
num: item.cart_num,
sku_id: item.sku_id,
is_all: 1
},
success: ({ data }) => {
if (data > 0) {
this.$util.showToast({
title: '加入购物车成功'
});
this.$forceUpdate();
this.cartNumber += this.number;
if (this.callback) this.callback();
this.$store.dispatch('getCartNumber');
// uni.$emit('refresh', true);
}
}
});
}
}
};
</script>
<style lang="scss" scoped>
.seckill-item {
background-color: #fff;
margin-bottom: 30rpx;
padding: 24rpx;
display: flex;
line-height: 40rpx;
border-radius: 16rpx;
.labels-1 {
margin-top: 10rpx !important;
.label-item {
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
font-size: 28rpx !important;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #999999 !important;
line-height: 40rpx !important;
}
}
.right {
padding-left: 20rpx;
flex: 1;
font-size: 24rpx;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #999999;
.bottom {
display: flex;
align-items: center;
justify-content: space-between;
margin-top: 16rpx;
.price {
// height: 104rpx;
font-size: 28rpx;
font-family: DINAlternate-Bold, DINAlternate;
font-weight: bold;
color: #f33b50;
.price1 {
font-size: 40rpx;
}
}
}
.title {
font-size: 32rpx;
font-family: PingFangSC-Medium, PingFang SC;
font-weight: 500;
color: #333333;
margin-bottom: 16rpx;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
}
}
.cover1 {
width: 44vw;
height: 44vw;
border-radius: 16rpx;
display: flex;
justify-content: center;
img {
width: 100%;
height: 100%;
border-radius: 16rpx;
object-fit: cover;
}
.time {
width: 100%;
position: absolute;
text-align: center;
font-size: 30rpx;
font-family: PingFangSC-Regular, PingFang SC;
font-weight: 400;
color: #ffffff;
line-height: 44rpx;
background-color: rgba(0, 0, 0, 0.4);
bottom: 0;
border-radius: 0 0 8rpx 8rpx;
}
}
}
.sku-layer {
.sku-info {
max-height: 75vh;
height: 65vh;
position: relative;
.header {
padding: 30rpx 30rpx 20rpx 210rpx;
position: relative;
border-bottom: 2rpx solid $color-line;
min-height: 170rpx;
.img-wrap {
width: 160rpx;
height: 160rpx;
position: absolute;
left: 20rpx;
border-radius: $border-radius;
overflow: hidden;
padding: 2rpx;
background-color: #fff;
line-height: 208rpx;
image {
width: 100%;
height: 100%;
}
}
}
.main {
font-size: 24rpx;
line-height: 40rpx;
padding-right: 40rpx;
.price-wrap {
font-weight: bold;
.unit {
margin-right: 4rpx;
}
}
.stock {
font-size: $font-size-tag;
color: $color-tip;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
height: 70rpx;
overflow: hidden;
}
.price {
word-wrap: break-word;
}
.goods_name {
font-size: 30rpx;
font-weight: 600;
}
.sku-name {
display: -webkit-box;
-webkit-line-clamp: 1;
-webkit-box-orient: vertical;
overflow: hidden;
height: 42rpx;
.spec-value {
&::after {
content: '/';
}
&:last-child {
&::after {
content: '';
}
}
}
}
}
.sku-close {
position: absolute;
top: 20rpx;
right: 40rpx;
width: 40rpx;
height: 80rpx;
font-size: 40rpx;
}
}
.body-item {
padding: 0 30rpx;
height: 120rpx;
box-sizing: border-box;
overflow: scroll;
.wrap {
height: 120rpx;
}
.sku-list-wrap {
padding-bottom: 0rpx;
.title {
padding: 20rpx 0;
display: block;
}
}
.items {
position: relative;
display: inline-block;
border: 2rpx solid $color-line;
padding: 4rpx 30rpx;
border-radius: 8rpx;
margin: 0 20rpx 20rpx 0;
background-color: #fff;
font-size: $font-size-tag;
.disabled {
border: 2rpx dashed;
}
image {
height: 44rpx;
width: 44rpx;
border-radius: $border-radius;
margin-right: 10rpx;
display: inline-block;
vertical-align: middle;
}
}
.number-wrap {
.number-line {
padding: 20rpx 0;
line-height: 72rpx;
}
.title {
font-weight: 400;
}
.number {
display: flex;
height: 72rpx;
border-radius: 6rpx;
float: right;
button {
display: inline-block;
line-height: 64rpx;
height: 68rpx;
width: 60rpx;
font-size: 48rpx;
box-sizing: content-box;
border: 2rpx solid $color-line;
padding: 0;
margin: 0;
border-radius: 0;
background-color: #fff !important;
&.disabled {
background: #f7f7f7 !important;
}
}
input {
display: inline-block;
line-height: 64rpx;
height: 68rpx;
width: 72rpx;
text-align: center;
font-weight: 700;
border: 2rpx solid;
margin: 0;
padding: 0;
vertical-align: top;
background-color: $color-bg !important;
}
}
}
}
.keyBoard {
padding: 0 30rpx;
}
/deep/ .u-keyboard {
background-color: #fff;
.u-keyboard__button-wrapper {
.u-keyboard__button-wrapper__button {
background-color: #eee;
}
}
}
.footer {
height: 100rpx;
width: 100%;
margin-top: 40rpx;
color: #fff;
z-index: 1;
display: flex;
justify-content: center;
align-items: flex-start;
button {
width: 100%;
height: 80rpx;
background-color: var(--goods-btn-color);
font-weight: bold;
}
}
}
</style>

56
components/l-time/l-time.vue

@ -0,0 +1,56 @@
<template>
<text>{{ temp }}</text>
</template>
<script>
import _time_ from './time.js';
export default {
name: 'l-time',
props: {
//
text: {
type: [String, Number, Date],
default: ''
},
//false
maxDate: {
type: Boolean,
default: false
}
},
data() {
return {
textVal: this.text
};
},
watch: {
text() {
this.textVal = this.text;
}
},
computed: {
temp() {
return this.getText();
}
},
methods: {
getText() {
let self = this;
let timeVal = _time_.getFormatTime(self.textVal, self.maxDate);
if (timeVal && (timeVal.endsWith('刚刚') || timeVal.endsWith('分钟前'))) {
setTimeout(() => {
let temp = self.textVal;
self.textVal = '';
self.textVal = temp;
}, 60000);
}
return this.textVal ? timeVal : '';
},
onClick() {
this.$emit('on-tap', this.textVal);
}
}
};
</script>
<style></style>

161
components/l-time/time.js

@ -0,0 +1,161 @@
Function.prototype.asyAfter = function(afterfn) {
var _self = this;
return function() {
var ret = _self.apply(this, arguments);
if (ret === 'next') {
return afterfn.apply(this, arguments);
}
return ret;
}
}
Date.prototype.pattern = function(fmt) {
var o = {
"M+": this.getMonth() + 1, //月份
"d+": this.getDate(), //日
"h+": this.getHours() % 12 == 0 ? 12 : this.getHours() % 12, //小时
"H+": this.getHours(), //小时
"m+": this.getMinutes(), //分
"s+": this.getSeconds(), //秒
"q+": Math.floor((this.getMonth() + 3) / 3), //季度
"S": this.getMilliseconds() //毫秒
};
var week = {
"0": "\u65e5",
"1": "\u4e00",
"2": "\u4e8c",
"3": "\u4e09",
"4": "\u56db",
"5": "\u4e94",
"6": "\u516d"
};
if (/(y+)/.test(fmt)) {
fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
}
if (/(E+)/.test(fmt)) {
fmt = fmt.replace(RegExp.$1, ((RegExp.$1.length > 1) ? (RegExp.$1.length > 2 ? "\u661f\u671f" : "\u5468") :
"") +
week[this.getDay() + ""]);
}
for (var k in o) {
if (new RegExp("(" + k + ")").test(fmt)) {
fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k])
.length)));
}
}
return fmt;
}
const isType = type => (/^\[object\s(.*)\]$/.exec(Object.prototype.toString.call(type)))[1];
let Time = function() {};
let timeProto = Time.prototype;
//获取当前时间戳
timeProto.getUnix = function() {
return new Date().getTime();
}
//获取当天0点0分0秒时间戳
timeProto.getTodayUnix = function() {
let date = new Date();
let myDate = `${date.getFullYear()}/${(date.getMonth() + 1)}/${date.getDate()} 00:00:00`;
return new Date(myDate).getTime();
}
//获取今年1月1日0点0分0秒时间戳
timeProto.getYearUnix = function() {
let date = new Date();
date.setMonth(0);
date.setDate(1);
date.setHours(0);
date.setMinutes(0);
date.setSeconds(0);
date.setMilliseconds(0);
return date.getTime();
}
//获取当前时间标准年月日
timeProto.getLastDate = function(constTime) {
if (!constTime) {
return;
}
let date = new Date(constTime);
if (date.pattern) {
return date.pattern("yyyy-MM-dd");
}
let month = date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1;
let day = date.getDate() < 10 ? '0' + date.getDate() : date.getDate();
return date.getFullYear() + '-' + month + '-' + day;
}
const resDateStr = function(timer, constTime) {
let _just = function(timer) {
if (timer <= 0 || Math.floor(timer / 60) <= 0) {
return "刚刚"
} else return 'next';
}
let _mm = function(timer) {
if (timer < 3600) {
return Math.floor(timer / 60) + "分钟前"
} else return 'next';
}
let _hh = function(timer, constTime) {
let today = _time_.getTodayUnix();
if (timer >= 3600 && (constTime - today >= 0)) {
//可切换显示模式
// return "今天 " + new Date(constTime).pattern("HH:mm");
return Math.floor(timer / 60 / 60) + "小时前";
} else {
return 'next'
};
}
let _dd = function(timer, constTime) {
let today = _time_.getTodayUnix();
timer = (today - constTime) / 1000;
if (timer / 86400 <= 31) {
return Math.ceil(timer / 86400) + "天前"
} else return 'next';
}
let _dlast = function(timer, constTime) {
return _time_.getLastDate(constTime);
}
let dateFilter = _just.asyAfter(_mm).asyAfter(_hh).asyAfter(_dd).asyAfter(_dlast);
return dateFilter(timer, constTime);
}
//转换时间
const reg = new RegExp("-", "g");
timeProto.getFormatTime = function(constTime, max) {
if (!constTime) {
return "";
}
switch (isType(constTime)) {
case 'Date':
constTime = constTime.getTime();
break;
case 'String':
constTime = constTime.replace(reg, "/");
default:
constTime = new Date(constTime).getTime();
break;
}
let now = this.getUnix();
let year = this.getYearUnix();
let timer = (now - constTime) / 1000;
if (constTime > now && max) {
return this.getLastDate(constTime);
}
let _t = this;
return resDateStr(timer, constTime);
}
const _time_ = new Time();
export default _time_;

336
components/load-refresh/load-refresh.vue

@ -0,0 +1,336 @@
<template>
<view class="load-refresh">
<!-- 刷新动画可自定义占高100rpx -->
<view class="animation" :style="{'--color': color}">
<view v-if="!playState" class="remind">
{{moving ? '↑ 松开释放' : '↓ 下拉刷新'}}
</view>
<view v-if="playState && refreshType === 'hollowDots'" class="refresh hollow-dots-spinner">
<view class="dot"></view>
<view class="dot"></view>
<view class="dot"></view>
</view>
<view v-if="playState && refreshType === 'halfCircle'" class="refresh half-circle-spinner">
<view class="circle circle-1"></view>
<view class="circle circle-2"></view>
</view>
<view v-if="playState && refreshType === 'swappingSquares'" class="refresh swapping-squares-spinner">
<view class="square"></view>
<view class="square"></view>
<view class="square"></view>
<view class="square"></view>
</view>
</view>
<!-- 数据列表块 -->
<view
class="cover-container"
:style="[{
background: backgroundCover,
transform: coverTransform,
transition: coverTransition
}]"
@touchstart="coverTouchstart"
@touchmove="coverTouchmove"
@touchend="coverTouchend">
<scroll-view scroll-y class="list" :scroll-top="scrollTop" @scrolltolower="loadMore" :style="getHeight">
<!-- 数据集插槽 -->
<slot name="content-list"></slot>
<!-- 上拉加载 -->
<view class="load-more">{{loadText}}</view>
</scroll-view>
</view>
</view>
</template>
<script>
export default {
name: 'loadRefresh',
props: {
isRefresh: {
type: Boolean,
default: true
},
refreshType: {
type: String,
default: 'hollowDots'
},
fixedHeight: {
type: String,
default: '0'
},
heightReduce: {
type: String,
default: '0'
},
color: {
type: String,
default: '#04C4C4'
},
backgroundCover: {
type: String,
default: 'white'
},
currentPage: {
type: Number,
default: 0
},
totalPages: {
type: Number,
default: 0
}
},
data() {
return {
startY: 0,
moveY: 0,
updating: false, // true:
updateType: true, // true: : false:
moving: false,
scrollTop: -1,
coverTransform: 'translateY(0px)',
coverTransition: '0s',
playState: false // paused/ running
}
},
computed: {
//
getHeight() {
// rpx = px / uni.getSystemInfoSync().windowWidth * 750
if (Number(this.fixedHeight)) {
return `height: ${this.fixedHeight}rpx;`
} else {
let height = uni.getSystemInfoSync().windowHeight - uni.upx2px(0 + this.heightReduce)
return `height: ${height}px;`
}
},
// loadText
loadText() {
const { currentPage, totalPages, updating, updateType } = this
if (!updateType && updating) {
return '加载中...'
} else if (currentPage < totalPages) {
return '上拉加载更多'
} else {
return '已经到底啦~'
}
}
},
methods: {
// currentPagetotalPages @loadMore
loadMore() {
const { currentPage, totalPages } = this
if (!this.updating && currentPage < totalPages) {
this.updating = true
this.updateType = false
this.$emit('loadMore')
}
},
//
coverTouchstart(e) {
if (!this.isRefresh) {
return
}
this.coverTransition = 'transform .1s linear'
this.startY = e.touches[0].clientY
},
coverTouchmove(e) {
if (!this.isRefresh || this.updating) {
return
}
this.moveY = e.touches[0].clientY
let moveDistance = this.moveY - this.startY
if (moveDistance <= 50) {
this.coverTransform = `translateY(${moveDistance}px)`
}
this.moving = moveDistance >= 50
},
coverTouchend() {
if (!this.isRefresh || this.updating) {
return
}
if (this.moving) {
this.runRefresh()
} else {
this.coverTransition = 'transform 0.3s cubic-bezier(.21,1.93,.53,.64)'
this.coverTransform = 'translateY(0px)'
}
},
runRefresh() {
this.scrollTop = 0
this.coverTransition = 'transform .1s linear'
this.coverTransform = 'translateY(50px)'
this.playState = true
this.updating = true
this.updateType = true
this.$emit('refresh')
},
completed() {
if (this.updateType) {
//
this.moving = false
this.scrollTop = -1
this.coverTransition = 'transform 0.3s cubic-bezier(.21,1.93,.53,.64)'
this.coverTransform = 'translateY(0px)'
setTimeout(() => {
this.playState = false
}, 300)
}
this.updating = false
}
}
}
</script>
<style lang="scss" scoped>
$color: var(--color);
.load-refresh{
margin: 0;
padding: 0;
width: 100%;
.cover-container{
width: 100%;
margin-top: -100rpx;
.list{
width: 100%;
.load-more{
font-size: 20rpx;
text-align: center;
color: #AAAAAA;
padding: 16rpx;
}
}
}
}
/* 动画 */
.animation {
width: 100%;
height: 100rpx;
.remind {
width: 100%;
height: 100rpx;
text-align: center;
line-height: 100rpx;
}
.refresh {
width: 100%;
height: 100rpx;
display: flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
view {
// animation-play-state: $playState!important;
}
}
/* HollowDots */
.hollow-dots-spinner .dot {
width: 30rpx;
height: 30rpx;
margin: 0 calc(30rpx / 2);
border: calc(30rpx / 5) solid $color;
border-radius: 50%;
float: left;
transform: scale(0);
animation: hollowDots 1000ms ease infinite 0ms;
}
.hollow-dots-spinner .dot:nth-child(1) {
animation-delay: calc(300ms * 1);
}
.hollow-dots-spinner .dot:nth-child(2) {
animation-delay: calc(300ms * 2);
}
.hollow-dots-spinner .dot:nth-child(3) {
animation-delay: calc(300ms * 3);
}
@keyframes hollowDots {
50% {
transform: scale(1);
opacity: 1;
}
100% {
opacity: 0;
}
}
/* halfCircle */
.half-circle-spinner .circle {
content: "";
position: absolute;
width: 60rpx;
height: 60rpx;
border-radius: 100%;
border: calc(60rpx / 10) solid transparent;
}
.half-circle-spinner .circle.circle-1 {
border-top-color: $color;
animation: halfCircle 1s infinite;
}
.half-circle-spinner .circle.circle-2 {
border-bottom-color: $color;
animation: halfCircle 1s infinite alternate;
}
@keyframes halfCircle {
0% {
transform: rotate(0deg);
}
100%{
transform: rotate(360deg);
}
}
/* swappingSquares */
.swapping-squares-spinner {
position: relative;
}
.swapping-squares-spinner .square {
height: calc(65rpx * 0.25 / 1.3);
width: calc(65rpx * 0.25 / 1.3);
animation-duration: 1000ms;
border: calc(65rpx * 0.04 / 1.3) solid $color;
margin-right: auto;
margin-left: auto;
position: absolute;
animation-iteration-count: infinite;
}
.swapping-squares-spinner .square:nth-child(1) {
animation-name: swappingSquares-child-1;
animation-delay: 500ms;
}
.swapping-squares-spinner .square:nth-child(2) {
animation-name: swappingSquares-child-2;
animation-delay: 0ms;
}
.swapping-squares-spinner .square:nth-child(3) {
animation-name: swappingSquares-child-3;
animation-delay: 500ms;
}
.swapping-squares-spinner .square:nth-child(4) {
animation-name: swappingSquares-child-4;
animation-delay: 0ms;
}
@keyframes swappingSquares-child-1 {
50% {
transform: translate(150%,150%) scale(2,2);
}
}
@keyframes swappingSquares-child-2 {
50% {
transform: translate(-150%,150%) scale(2,2);
}
}
@keyframes swappingSquares-child-3 {
50% {
transform: translate(-150%,-150%) scale(2,2);
}
}
@keyframes swappingSquares-child-4 {
50% {
transform: translate(150%,-150%) scale(2,2);
}
}
}
</style>

113
components/loading-cover/loading-cover.vue

@ -0,0 +1,113 @@
<template>
<view class="loading-layer" v-if="isShow">
<view class="loading-anim" v-if="themeStyle">
<view class="box item"><view class="border out item" :style="{'border-left-color':themeStyle.main_color, 'border-top-color':themeStyle.main_color}"></view></view>
</view>
</view>
</template>
<script>
export default {
name: 'loading-cover',
props: {
initShow: {
type: Boolean,
default: true
}
},
data() {
return {
isShow: true
};
},
components: {},
created() {
this.isShow = this.initShow;
},
methods: {
show() {
this.isShow = true;
},
hide() {
this.isShow = false;
}
}
};
</script>
<style lang="scss">
@keyframes spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
.loading-layer {
width: 100%;
height: 100%;
position: fixed;
top: 0;
left: 0;
z-index: 997;
background: #f8f8f8;
}
.loading-anim {
position: absolute;
left: 50%;
top: 40%;
transform: translate(-50%, -50%);
}
.loading-anim > .item {
position: relative;
width: 70rpx;
height: 70rpx;
perspective: 1600rpx;
transform-style: preserve-3d;
transition: all 0.2s ease-out;
}
.loading-anim .border {
position: absolute;
border-radius: 50%;
border: 6rpx solid;
}
.loading-anim .out {
top: 15%;
left: 15%;
width: 70%;
height: 70%;
border-left-color: #FF4646;
border-right-color: #C5C5C5 !important;
// border-right-color: rgba($color: #000000, $alpha: 0) !important;
border-top-color: #FF4646 ;
border-bottom-color: #C5C5C5 !important;
// border-bottom-color: rgba($color: #000000, $alpha: 0) !important;
animation: spin 0.6s linear normal infinite;
}
.loading-anim .in {
top: 25%;
left: 25%;
width: 50%;
height: 50%;
border-top-color: transparent !important;
border-bottom-color: transparent !important;
animation: spin 0.8s linear infinite;
}
.loading-anim .mid {
top: 40%;
left: 40%;
width: 20%;
height: 20%;
border-left-color: transparent;
border-right-color: transparent;
animation: spin 0.6s linear infinite;
}
</style>

228
components/ls-dom-video/ls-dom-video.vue

@ -0,0 +1,228 @@
<template>
<view v-html="videoHtml" id="dom-video" class="dom-video" :eventDrive="eventDrive"
:change:eventDrive="domVideo.eventHandle" :videoSrc="videoSrc" :change:videoSrc="domVideo.srcChange"
:videoProps="videoProps" :change:videoProps="domVideo.propsChange" :randomNum="randomNum"
:change:randomNum="domVideo.randomNumChange" />
</template>
<script>
export default {
props: {
src: {
type: String,
default: ''
},
autoplay: {
type: Boolean,
default: false
},
loop: {
type: Boolean,
default: false
},
controls: {
type: Boolean,
default: false
},
objectFit: {
type: String,
default: 'contain'
},
muted: {
type: Boolean,
default: false
},
poster: {
type: String,
default: ''
},
},
//
data() {
return {
videoHtml: '',
videoSrc: '',
eventDrive: null,
videoProps: {},
randomNum: Math.floor(Math.random() * 100000000 + 1)
}
},
watch: {
//
src: {
handler(val) {
if (!val) return
this.initVideoHtml()
setTimeout(() => {
this.videoSrc = val
}, 0)
},
immediate: true
},
//
autoplay: {
handler(val) {
this.videoProps.autoplay = val
},
immediate: true
},
},
//
mounted() {
this.initVideoHtml()
},
beforeDestroy() {
this.videoHtml = ''
},
//
methods: {
// video
listener(data) {
console.log('向父组件传递事件 =>', data)
this.$emit('listener', data)
},
//
initVideoHtml() {
this.videoHtml = `<video
src="${this.src}"
id="dom-html-video_${this.randomNum}"
class="dom-html-video"
${this.autoplay ? 'autoplay' : ''}
${this.loop ? 'loop' : ''}
${this.controls ? 'controls' : ''}
${this.muted ? 'muted' : ''}
${this.poster ? 'poster="' + this.poster + '"' : ''}
preload="auto"
playsinline
webkit-playsinline
width="100%"
height="100%"
style="object-fit: ${this.objectFit};padding:0;"
>
<source src="${this.src}" type="video/mp4">
<source src="${this.src}" type="video/ogg">
<source src="${this.src}" type="video/webm">
</video>
`
// console.log('html =>', this.videoHtml)
},
resetEventDrive() {
this.eventDrive = null
},
// service/ => renderjs
play() {
this.eventDrive = 'play'
},
pause() {
this.eventDrive = 'pause'
},
stop() {
this.eventDrive = 'stop'
}
}
}
</script>
<script module="domVideo" lang="renderjs">
export default {
data() {
return {
video: null,
num: '',
options: {},
}
},
mounted() {
this.initVideoEvent()
},
methods: {
initVideoEvent() {
setTimeout(() => {
let video = document.getElementById(`dom-html-video_${this.num}`)
this.video = video
//
video.addEventListener('play', () => {
this.$ownerInstance.callMethod('listener', {
name: 'play',
currentTime: 0,
duration: this.video.duration
})
})
video.addEventListener('pause', () => {
this.$ownerInstance.callMethod('listener', {
name: 'pause',
currentTime: this.video.currentTime,
duration: this.video.duration
})
})
video.addEventListener('ended', () => {
this.$ownerInstance.callMethod('listener', {
name: 'ended',
currentTime: this.video.currentTime,
duration: this.video.duration
})
this.$ownerInstance.callMethod('resetEventDrive')
})
}, 100)
},
eventHandle(eventType) {
if (eventType) {
this.video = document.getElementById(`dom-html-video_${this.num}`)
if (!this.video) {
console.error(`Cannot find video element with id: dom-html-video_${this.num}`);
return;
}
if (eventType === 'play') {
this.video.play()
} else if (eventType === 'pause') {
this.video.pause()
} else if (eventType === 'stop') {
this.video.pause()
this.video.currentTime = 0;
}
}
},
srcChange(val) {
//
// this.initVideoEvent()
setTimeout(() => {
let video = document.getElementById(`dom-html-video_${this.num}`)
video.addEventListener('loadedmetadata', () => {
console.log('this.options', this.options)
let { autoplay } = this.options
if (!autoplay) {
video.pause()
} else {
video.play()
}
})
}, 100)
},
propsChange(obj) {
this.options = obj
},
randomNumChange(val) {
this.num = val
},
}
}
</script>
<style lang="scss" scoped>
.dom-video {
overflow: hidden;
height: 100%;
padding: 0;
&-height {
height: 100%;
}
}
</style>

326
components/mTikTok.vue

@ -0,0 +1,326 @@
<template>
<swiper class="m-tiktok-video-swiper" circular @change="swiperChange" :current="current" :vertical="true"
duration="300">
{{originList}}
<swiper-item v-for="(item, index) in displaySwiperList" :key="index">
<view class="swiper-item" @click="handleClick">
<ls-dom-video :ref="'DomVideo'+index" v-if="index === 0 || !isFirstLoad" :src="item.video"
:autoplay="true" :controls="false" @ended="endedVideo" @listener="listener"></ls-dom-video>
<!-- <video class="m-tiktok-video-player" :src="item.src" :id="`video__${index}`" :controls="controls"
:show-center-play-btn="controls" :object-fit="item.objectFit" :autoplay="false" :loop="loop"
:custom-cache="false" @ended="ended" @controlstoggle="controlstoggle" @play="onPlay"
@error="emits('error')" @loadedmetadata="loadVideoData($event, item)"
v-if="index === 0 || !isFirstLoad"></video> -->
<!-- <view class="m-tiktok-video-play-btn" v-if="!controls && displayIndex === index" @click="togglePlay">
<text class="m-tiktok-video-iconfont video-icon" :class="{ active: !isPlaying }">&#xe607;</text>
</view>
<image v-if="item.poster && displayIndex != index" :src="item.poster" class="m-tiktok-video-poster"
mode="aspectFit"></image>
<slot :item="item"></slot> -->
</view>
</swiper-item>
</swiper>
</template>
<script>
export default {
props: {
/**
* 视频列表
*/
videoList: {
type: Array,
default: () => [],
},
/**
* 是否循环播放一个视频
*/
loop: {
type: Boolean,
default: true,
},
/**
* 显示原生控制栏
*/
controls: {
type: Boolean,
default: false,
},
/**
* 是否自动播放
*/
autoplay: {
type: Boolean,
default: true,
},
/**
* 是否自动滚动播放
*/
autoChange: {
type: Boolean,
default: false,
},
/**
* 滚动加载阈值即播放到剩余多少个之后触发加载更多
*/
loadMoreOffsetCount: {
type: Number,
default: 2,
},
/**
* 视频自动自适应平铺模式
* 竖屏cover横屏自适应
*/
autoObjectFit: {
type: Boolean,
default: true,
},
},
data() {
return {
originList: [], //
displaySwiperList: [], // swiper
displayIndex: 0, // swiper012
originIndex: 0, //
current: 0,
oid: 0,
videoContexts: [],
isFirstLoad: true,
isPlaying: false,
loadTimer: null,
}
},
watch: {
videoList: {
handler(val) {
if (val.length) {
this.originList = val;
console.log(this.originList);
if (this.isFirstLoad || this.videoContexts.length) {
this.initSwiperData(this.originIndex)
this.initVideoContexts()
}
}
},
immediate: true,
deep: true
},
},
mounted() {
console.log(this.videoList);
},
methods: {
initVideoContexts() {
this.videoContexts = this.videoContexts.map((item, index) => {
return uni.createVideoContext(`video__${index}`, this);
})
},
onPlay(e) {
this.isPlaying = true;
this.initFirstLoad()
this.$emit('play', e)
},
handleClick(e) {
this.$emit("click", e);
},
ended() {
if (this.autoChange) {
if (this.displayIndex < 2) {
this.current = this.displayIndex + 1
} else {
this.current = 0
}
}
this.$emit('ended')
},
/**
* 初始一个显示的swiper数据
* @originIndex 从源数据的哪个开始显示默认0如从其他页面跳转进来要显示第n个这个参数就是他的下标
*/
initSwiperData(originIndex) {
const originListLength = this.originList.length; //
const displayList = []; // swiper
displayList[this.displayIndex] = this.originList[originIndex];
displayList[this.displayIndex - 1 == -1 ? 2 : this.displayIndex - 1] =
this.originList[
originIndex - 1 == -1 ? originListLength - 1 : originIndex - 1
];
displayList[this.displayIndex + 1 == 3 ? 0 : this.displayIndex + 1] =
this.originList[originIndex + 1 == originListLength ? 0 : originIndex + 1];
this.displaySwiperList = displayList;
console.log('displaySwiperList', this.displaySwiperList);
if (this.oid >= this.originList.length) {
this.oid = 0;
}
if (this.oid < 0) {
this.oid = this.originList.length - 1;
}
//
this.videoContexts.map((item) => item?.stop());
setTimeout(() => {
if (this.autoplay) {
uni.createVideoContext(`video__${this.displayIndex}`, this).play();
}
}, 500)
this.$emit('change', {
index: originIndex,
detail: this.originList[originIndex],
})
//
this.originIndex = originIndex;
//
var pCount = this.originList.length - this.loadMoreOffsetCount;
if (originIndex == pCount) {
this.$emit('loadMore')
}
},
/**
* swiper滑动时候
*/
swiperChange(event) {
const { current } = event.detail;
this.isFirstLoad = false
const originListLength = this.originList.length
//
if (this.displayIndex - current == 2 || this.displayIndex - current == -1) {
this.originIndex =
this.originIndex + 1 == originListLength ? 0 : this.originIndex + 1;
this.displayIndex =
this.displayIndex + 1 == 3 ? 0 : this.displayIndex + 1;
this.oid = this.originIndex - 1;
this.initSwiperData(this.originIndex);
}
// -21
else if (
this.displayIndex - current == -2 ||
this.displayIndex - current == 1
) {
this.originIndex =
this.originIndex - 1 == -1 ?
originListLength - 1 :
this.originIndex - 1;
this.displayIndex =
this.displayIndex - 1 == -1 ? 2 : this.displayIndex - 1;
this.oid = this.originIndex + 1;
this.initSwiperData(this.originIndex);
}
},
controlstoggle(e) {
this.$emit('controlstoggle', e)
},
togglePlay() {
const video = uni.createVideoContext(`video__${this.displayIndex}`, this)
if (this.isPlay) {
video.pause()
this.isPlay = false
} else {
video.play()
this.isPlay = true
}
},
playSeeked(value) {
const video = uni.createVideoContext(`video__${this.displayIndex}`, this)
video.seek(value)
},
initFirstLoad() {
if (this.isFirstLoad) {
this.loadTimer = setTimeout(() => {
this.isFirstLoad = false
clearTimeout(this.loadTimer)
}, 5000)
}
},
/**
* 视频源数据加载时触发
* @param $event
* @param item
*/
loadVideoData($event, item) {
if (item.objectFit) {
return
}
if (!this.autoObjectFit) {
return
}
//
if ($event.detail.width < $event.detail.height) {
item.objectFit = 'cover'
} else {
item.objectFit = 'contain'
}
}
},
onUnload() {
clearTimeout(this.loadTimer)
},
}
</script>
<style lang="scss">
// @font-face {
// font-family: "m-tiktok-play-icon";
// src: url(data:font/woff2;charset=utf-8;base64,d09GMgABAAAAAAJ0AA0AAAAABlgAAAIiAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP0ZGVE0cGh4GYACCQhEICkhaCwoAATYCJAMQBCAFhQIHLxt4BcieBXbLR4jiyygbC491Mg0vz9JsPPz/ft/2ufeMmCQP9fXfRhxvMKHjkcSsTkqWplJJqpFFfn79mr4NG5fvwujI+EPeZCbudGJcy6oVklRVp8IAdgMJUqD853ceuhm3iSafWxNoC0bbskAmUGABTlrDAgwsC+xJ3/SJf3DecLgpCpyFgDcXlRJ8uiufSVcHBjENilBVIVGQKS50UZ6U1+ApeD7+6kcvRVcl2fZub1Q8/BfJG9VHbUp9J0UAYBWhomIRgUZWYFHOKkgp+FFsyVvmRkB0E4AooAg/DwF/49FSQIJeBMbBDIAEQIzfDW+OPVHX48vXUy26fUwfJnN0+tW5bLx3+dz5fHT61rQEIBDc77r579ZI8793IDWgftfb8/q83gC9Cggqvex6gvqcDoBMGojkOvpX4wgU9OtHC2DcOwgwoYpA6LWDQNHjDgJVr8cCpF7PBOgy4JUA3Xq9BYF+29EgMGAiLlSRfVgDlgyjlmQx7JSsRgVQYkeyy7RLstuoF7Lfid+qAWtxbiWmkbDEVgmyA2hRBHx6jOEomxtSuCEvAg5k/U4c0Bh2XJIYfiwLaz88BE9oYgkrKPS0dWGtk7/X7rqFOsU+TZzFM4k9Qx9jOkEXC3iErR+f0LhcASEUC9g0CtaGY3Jrsjf6zPrqiLsTyi1RpN9z3wPOMRaa6+jQAzbblCgVWLpySeZmOVzvLw8uOfSjoLSEEiV7Yg==) format("woff2");
// font-weight: normal;
// font-style: normal;
// font-display: swap;
// }
.m-tiktok-video-iconfont {
// font-family: m-tiktok-play-icon;
}
.m-tiktok-video-swiper,
.m-tiktok-video-player {
width: 100%;
height: 100vh;
background-color: #000;
}
.m-tiktok-video-swiper {
.swiper-item {
position: relative;
}
.m-tiktok-video-poster {
background-color: #000;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
.m-tiktok-video-play-btn {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 1;
display: flex;
align-items: center;
justify-content: center;
.video-icon {
font-size: 50px;
display: block;
color: rgba(255, 255, 255, 0.8);
opacity: 0;
&.active {
opacity: 1;
}
}
}
}
</style>

55
components/mescroll/components/mescroll-down.css

@ -0,0 +1,55 @@
/* 下拉刷新区域 */
.mescroll-downwarp {
position: absolute;
top: -100%;
left: 0;
width: 100%;
height: 100%;
text-align: center;
}
/* 下拉刷新--内容区,定位于区域底部 */
.mescroll-downwarp .downwarp-content {
position: absolute;
left: 0;
bottom: 0;
width: 100%;
min-height: 60rpx;
padding: 20rpx 0;
text-align: center;
}
/* 下拉刷新--提示文本 */
.mescroll-downwarp .downwarp-tip {
display: inline-block;
font-size: 28rpx;
color: gray;
vertical-align: middle;
margin-left: 16rpx;
}
/* 下拉刷新--旋转进度条 */
.mescroll-downwarp .downwarp-progress {
display: inline-block;
width: 32rpx;
height: 32rpx;
border-radius: 50%;
border: 2rpx solid gray;
border-bottom-color: transparent;
vertical-align: middle;
}
/* 旋转动画 */
.mescroll-downwarp .mescroll-rotate {
animation: mescrollDownRotate 0.6s linear infinite;
}
@keyframes mescrollDownRotate {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}

52
components/mescroll/components/mescroll-down.vue

@ -0,0 +1,52 @@
<!-- 下拉刷新区域 -->
<template>
<view v-if="mOption.use" class="mescroll-downwarp">
<view class="downwarp-content">
<view class="downwarp-progress" :class="{ 'mescroll-rotate': isDownLoading }" :style="{ transform: downRotate }"></view>
<view class="downwarp-tip">{{ downText }}</view>
</view>
</view>
</template>
<script>
export default {
props: {
option: Object, // down
type: Number, // inOffset1 outOffset2 showLoading3 endDownScroll4
rate: Number // (inOffset: rate<1; outOffset: rate>=1)
},
computed: {
// ,propdefault
mOption() {
return this.option || {};
},
//
isDownLoading() {
return this.type === 3;
},
//
downRotate() {
return 'rotate(' + 360 * this.rate + 'deg)';
},
//
downText() {
switch (this.type) {
case 1:
return this.mOption.textInOffset;
case 2:
return this.mOption.textOutOffset;
case 3:
return this.mOption.textLoading;
case 4:
return this.mOption.textLoading;
default:
return this.mOption.textInOffset;
}
}
}
};
</script>
<style>
@import './mescroll-down.css';
</style>

90
components/mescroll/components/mescroll-empty.vue

@ -0,0 +1,90 @@
<!--空布局
可作为独立的组件, 不使用mescroll的页面也能单独引入, 以便APP全局统一管理:
import MescrollEmpty from '@/components/mescroll-uni/components/mescroll-empty.vue';
<mescroll-empty v-if="isShowEmpty" :option="optEmpty" @emptyclick="emptyClick"></mescroll-empty>
-->
<template>
<view class="mescroll-empty" :class="{ 'empty-fixed': option.fixed }" :style="{ 'z-index': option.zIndex, top: option.top }">
<image v-if="icon" class="empty-icon" :src="icon" mode="widthFix" />
<view v-if="tip" class="empty-tip">{{ tip }}</view>
<view v-if="option.btnText" class="empty-btn" @click="emptyClick">{{ option.btnText }}</view>
</view>
</template>
<script>
//
import GlobalOption from './../mescroll-uni-option.js';
export default {
props: {
// empty: GlobalOption.up.empty
option: {
type: Object,
default() {
return {};
}
}
},
// 使computed,option
computed: {
//
icon() {
return this.option.icon == null ? GlobalOption.up.empty.icon : this.option.icon; // 使,
},
//
tip() {
return this.option.tip == null ? GlobalOption.up.empty.tip : this.option.tip; // 使,
}
},
methods: {
//
emptyClick() {
this.$emit('emptyclick');
}
}
};
</script>
<style>
/* 无任何数据的空布局 */
.mescroll-empty {
box-sizing: border-box;
width: 100%;
padding: 100rpx 50rpx;
text-align: center;
}
.mescroll-empty.empty-fixed {
z-index: 99;
position: absolute; /*transform会使fixed失效,最终会降级为absolute */
top: 100rpx;
left: 0;
}
.mescroll-empty .empty-icon {
width: 280rpx;
height: 280rpx;
}
.mescroll-empty .empty-tip {
margin-top: 20rpx;
font-size: $font-size-tag;
color: gray;
}
.mescroll-empty .empty-btn {
display: inline-block;
margin-top: 40rpx;
min-width: 200rpx;
padding: 18rpx;
font-size: $font-size-base;
border: 1rpx solid #e04b28;
border-radius: 60rpx;
color: #e04b28;
}
.mescroll-empty .empty-btn:active {
opacity: 0.75;
}
</style>

81
components/mescroll/components/mescroll-top.vue

@ -0,0 +1,81 @@
<!-- 回到顶部的按钮 -->
<template>
<image
v-if="mOption.src"
class="mescroll-totop"
:class="[value ? 'mescroll-totop-in' : 'mescroll-totop-out', { 'mescroll-safe-bottom': mOption.safearea }]"
:style="{ 'z-index': mOption.zIndex, left: left, right: right, bottom: addUnit(mOption.bottom), width: addUnit(mOption.width), 'border-radius': addUnit(mOption.radius) }"
:src="mOption.src"
mode="widthFix"
@click="toTopClick"
/>
</template>
<script>
export default {
props: {
// up.toTop
option: Object,
//
value: false
},
computed: {
// ,propdefault
mOption() {
return this.option || {};
},
//
left() {
return this.mOption.left ? this.addUnit(this.mOption.left) : 'auto';
},
// ()
right() {
return this.mOption.left ? 'auto' : this.addUnit(this.mOption.right);
}
},
methods: {
addUnit(num) {
if (!num) return 0;
if (typeof num === 'number') return num + 'rpx';
return num;
},
toTopClick() {
this.$emit('input', false); // 使v-model
this.$emit('click'); //
}
}
};
</script>
<style>
/* 回到顶部的按钮 */
.mescroll-totop {
z-index: 99;
position: fixed !important; /* 加上important避免编译到H5,在多mescroll中定位失效 */
right: 46rpx !important;
bottom: 272rpx !important;
width: 72rpx;
height: auto;
border-radius: 50%;
opacity: 0;
transition: opacity 0.5s; /* 过渡 */
margin-bottom: var(--window-bottom); /* css变量 */
}
/* 适配 iPhoneX */
.mescroll-safe-bottom {
margin-bottom: calc(var(--window-bottom) + constant(safe-area-inset-bottom)); /* window-bottom + 适配 iPhoneX */
margin-bottom: calc(var(--window-bottom) + env(safe-area-inset-bottom));
}
/* 显示 -- 淡入 */
.mescroll-totop-in {
opacity: 1;
}
/* 隐藏 -- 淡出且不接收事件*/
.mescroll-totop-out {
opacity: 0;
pointer-events: none;
}
</style>

47
components/mescroll/components/mescroll-up.css

@ -0,0 +1,47 @@
/* 上拉加载区域 */
.mescroll-upwarp {
min-height: 60rpx;
padding: 30rpx 0;
text-align: center;
clear: both;
margin-bottom: 20rpx;
}
/*提示文本 */
.mescroll-upwarp .upwarp-tip,
.mescroll-upwarp .upwarp-nodata {
display: inline-block;
font-size: 28rpx;
color: #b1b1b1;
vertical-align: middle;
}
.mescroll-upwarp .upwarp-tip {
margin-left: 16rpx;
}
/*旋转进度条 */
.mescroll-upwarp .upwarp-progress {
display: inline-block;
width: 32rpx;
height: 32rpx;
border-radius: 50%;
border: 2rpx solid #b1b1b1;
border-bottom-color: transparent;
vertical-align: middle;
}
/* 旋转动画 */
.mescroll-upwarp .mescroll-rotate {
animation: mescrollUpRotate 0.6s linear infinite;
}
@keyframes mescrollUpRotate {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}

39
components/mescroll/components/mescroll-up.vue

@ -0,0 +1,39 @@
<!-- 上拉加载区域 -->
<template>
<view class="mescroll-upwarp">
<!-- 加载中 (此处不能用v-if,否则android小程序快速上拉可能会不断触发上拉回调) -->
<view v-show="isUpLoading">
<view class="upwarp-progress mescroll-rotate"></view>
<view class="upwarp-tip">{{ mOption.textLoading }}</view>
</view>
<!-- 无数据 -->
<view v-if="isUpNoMore" class="upwarp-nodata">{{ mOption.textNoMore }}</view>
</view>
</template>
<script>
export default {
props: {
option: Object, // up
type: Number // 0loading1loading2
},
computed: {
// ,propdefault
mOption() {
return this.option || {};
},
//
isUpLoading() {
return this.type === 1;
},
//
isUpNoMore() {
return this.type === 2;
}
}
};
</script>
<style>
@import './mescroll-up.css';
</style>

15
components/mescroll/mescroll-body.css

@ -0,0 +1,15 @@
page {
-webkit-overflow-scrolling: touch;
/* 使iOS滚动流畅 */
}
.mescroll-body {
position: relative;
/* 下拉刷新区域相对自身定位 */
height: auto;
/* 不可固定高度,否则overflow: hidden, 可通过设置最小高度使列表不满屏仍可下拉*/
overflow: hidden;
/* 遮住顶部下拉刷新区域 */
box-sizing: border-box;
/* 避免设置padding出现双滚动条的问题 */
}

298
components/mescroll/mescroll-body.vue

@ -0,0 +1,298 @@
<template>
<view
class="mescroll-body"
:style="{ minHeight: minHeight, 'padding-top': padTop, 'padding-bottom': padBottom, 'padding-bottom': padBottomConstant, 'padding-bottom': padBottomEnv }"
@touchstart="touchstartEvent"
@touchmove="touchmoveEvent"
@touchend="touchendEvent"
@touchcancel="touchendEvent"
>
<view class="mescroll-body-content mescroll-touch" :style="{ transform: translateY, transition: transition }">
<!-- 下拉加载区域 (支付宝小程序子组件传参给子子组件仍报单项数据流的异常,暂时不通过mescroll-down组件实现)-->
<!-- <mescroll-down :option="mescroll.optDown" :type="downLoadType" :rate="downRate"></mescroll-down> -->
<view v-if="mescroll.optDown.use" class="mescroll-downwarp">
<view class="downwarp-content">
<view class="downwarp-progress" :class="{ 'mescroll-rotate': isDownLoading }" :style="{ transform: downRotate }"></view>
<view class="downwarp-tip">{{ downText }}</view>
</view>
</view>
<!-- 列表内容 -->
<slot></slot>
<!-- 空布局 -->
<!-- <mescroll-empty v-if="isShowEmpty" :option="mescroll.optUp.empty" @emptyclick="emptyClick"></mescroll-empty> -->
<!-- 上拉加载区域 (下拉刷新时不显示, 支付宝小程序子组件传参给子子组件仍报单项数据流的异常,暂时不通过mescroll-up组件实现)-->
<!-- <mescroll-up v-if="mescroll.optUp.use && !isDownLoading" :option="mescroll.optUp" :type="upLoadType"></mescroll-up> -->
<view v-if="mescroll.optUp.use && !isDownLoading" class="mescroll-upwarp">
<!-- 加载中 (此处不能用v-if,否则android小程序快速上拉可能会不断触发上拉回调) -->
<view v-show="upLoadType === 1">
<view class="upwarp-progress mescroll-rotate"></view>
<view class="upwarp-tip">{{ mescroll.optUp.textLoading }}</view>
</view>
<!-- 无数据 -->
<view v-if="upLoadType === 2" class="upwarp-nodata">{{ mescroll.optUp.textNoMore }}</view>
</view>
</view>
<!-- 回到顶部按钮 (fixed元素需写在transform外面,防止降级为absolute)-->
<mescroll-top v-model="isShowToTop" :option="mescroll.optUp.toTop" @click="toTopClick" v-if="showTop"></mescroll-top>
</view>
</template>
<script>
// mescroll-uni.js,
import MeScroll from './mescroll-uni.js';
//
import GlobalOption from './mescroll-uni-option.js';
//
// import MescrollEmpty from './components/mescroll-empty.vue';
//
import MescrollTop from './components/mescroll-top.vue';
export default {
components: {
// MescrollEmpty,
MescrollTop
},
data() {
return {
mescroll: { optDown: {}, optUp: {} }, // mescroll
downHight: 0, //:
downRate: 0, // (inOffset: rate<1; outOffset: rate>=1)
downLoadType: 4, // inOffset1 outOffset2 showLoading3 endDownScroll4
upLoadType: 0, // 0loading1loading2
isShowEmpty: false, //
isShowToTop: false, //
windowHeight: 0, // 使
statusBarHeight: 0 //
};
},
props: {
down: Object, //
up: Object, //
top: [String, Number], // (20, "20rpx", "20px", "20%", rpx, windowHeight)
topbar: Boolean, // top, false (使:,)
bottom: [String, Number], // (20, "20rpx", "20px", "20%", rpx, windowHeight)
safearea: Boolean, // bottom, false (iPhoneX使)
height: [String, Number], // mescroll,windowHeight,使
showTop: {
type: Boolean,
default: true
}
},
computed: {
// mescroll,windowHeight,使
minHeight() {
return this.toPx(this.height || '100%') + 'px';
},
// (px)
numTop() {
return this.toPx(this.top) + (this.topbar ? this.statusBarHeight : 0);
},
padTop() {
return this.numTop + 'px';
},
// (px)
numBottom() {
return this.toPx(this.bottom);
},
padBottom() {
return this.numBottom + 'px';
},
padBottomConstant() {
return this.safearea ? 'calc(' + this.padBottom + ' + constant(safe-area-inset-bottom))' : this.padBottom;
},
padBottomEnv() {
return this.safearea ? 'calc(' + this.padBottom + ' + env(safe-area-inset-bottom))' : this.padBottom;
},
//
isDownReset() {
return this.downLoadType === 3 || this.downLoadType === 4;
},
//
transition() {
return this.isDownReset ? 'transform 300ms' : '';
},
translateY() {
return this.downHight > 0 ? 'translateY(' + this.downHight + 'px)' : ''; // transform使fixed,fixedmescroll
},
//
isDownLoading() {
return this.downLoadType === 3;
},
//
downRotate() {
return 'rotate(' + 360 * this.downRate + 'deg)';
},
//
downText() {
switch (this.downLoadType) {
case 1:
return this.mescroll.optDown.textInOffset;
case 2:
return this.mescroll.optDown.textOutOffset;
case 3:
return this.mescroll.optDown.textLoading;
case 4:
return this.mescroll.optDown.textLoading;
default:
return this.mescroll.optDown.textInOffset;
}
}
},
methods: {
//number,rpx,upx,px,% --> px
toPx(num) {
if (typeof num === 'string') {
if (num.indexOf('px') !== -1) {
if (num.indexOf('rpx') !== -1) {
// "10rpx"
num = num.replace('rpx', '');
} else if (num.indexOf('upx') !== -1) {
// "10upx"
num = num.replace('upx', '');
} else {
// "10px"
return Number(num.replace('px', ''));
}
} else if (num.indexOf('%') !== -1) {
// ,windowHeight,"10%"windowHeight10%
let rate = Number(num.replace('%', '')) / 100;
return this.windowHeight * rate;
}
}
return num ? uni.upx2px(Number(num)) : 0;
},
//touchstart,
touchstartEvent(e) {
this.mescroll.touchstartEvent(e);
},
//touchmove,
touchmoveEvent(e) {
this.mescroll.touchmoveEvent(e);
},
//touchend,
touchendEvent(e) {
this.mescroll.touchendEvent(e);
},
//
emptyClick() {
this.$emit('emptyclick', this.mescroll);
},
//
toTopClick() {
this.mescroll.scrollTo(0, this.mescroll.optUp.toTop.duration); //
this.$emit('topclick', this.mescroll); //
}
},
// 使createdmescroll; mountedcssH5
created() {
let vm = this;
let diyOption = {
//
down: {
inOffset(mescroll) {
vm.downLoadType = 1; // offset (mescroll,)
},
outOffset(mescroll) {
vm.downLoadType = 2; // offset (mescroll,)
},
onMoving(mescroll, rate, downHight) {
// ,;
vm.downHight = downHight; // (mescroll,)
vm.downRate = rate; // (inOffset: rate<1; outOffset: rate>=1)
},
showLoading(mescroll, downHight) {
vm.downLoadType = 3; // (mescroll,)
vm.downHight = downHight; // (mescroll,)
},
endDownScroll(mescroll) {
vm.downLoadType = 4; // (mescroll,)
vm.downHight = 0; // (mescroll,)
},
//
callback: function(mescroll) {
vm.$emit('down', mescroll);
}
},
//
up: {
//
showLoading() {
vm.upLoadType = 1;
},
//
showNoMore() {
vm.upLoadType = 2;
},
//
hideUpScroll() {
vm.upLoadType = 0;
},
//
empty: {
onShow(isShow) {
//
vm.isShowEmpty = isShow;
}
},
//
toTop: {
onShow(isShow) {
//
vm.isShowToTop = isShow;
}
},
//
callback: function(mescroll) {
vm.$emit('up', mescroll);
}
}
};
MeScroll.extend(diyOption, GlobalOption); //
let myOption = JSON.parse(
JSON.stringify({
down: vm.down,
up: vm.up
})
); // ,props
MeScroll.extend(myOption, diyOption); //
// MeScroll
vm.mescroll = new MeScroll(myOption, true); // true,body
// initmescroll
vm.$emit('init', vm.mescroll);
//
const sys = uni.getSystemInfoSync();
if (sys.windowHeight) vm.windowHeight = sys.windowHeight;
if (sys.statusBarHeight) vm.statusBarHeight = sys.statusBarHeight;
// 使downbottomOffset
vm.mescroll.setBodyHeight(sys.windowHeight);
// 使pagescroll,scrollTo
vm.mescroll.resetScrollTo((y, t) => {
uni.pageScrollTo({
scrollTop: y,
duration: t
});
});
// up.toTop.safearea,vuesafearea
if (vm.up && vm.up.toTop && vm.up.toTop.safearea != null) {
} else {
vm.mescroll.optUp.toTop.safearea = vm.safearea;
}
}
};
</script>
<style>
@import './mescroll-body.css';
@import './components/mescroll-down.css';
@import './components/mescroll-up.css';
</style>

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

Loading…
Cancel
Save