init
This commit is contained in:
commit
3e9a18639c
|
|
@ -0,0 +1,3 @@
|
|||
/unpackage
|
||||
/.hbuilderx
|
||||
/.idea
|
||||
|
|
@ -0,0 +1,221 @@
|
|||
<script>
|
||||
import auth from 'common/js/auth.js';
|
||||
import { Weixin } from 'common/js/wx-jssdk.js';
|
||||
|
||||
export default {
|
||||
mixins: [auth],
|
||||
onLaunch: function() {
|
||||
uni.hideTabBar();
|
||||
|
||||
// #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 H5
|
||||
// 自动授权登录
|
||||
if (!uni.getStorageSync('token')) {
|
||||
this.getAuthInfo();
|
||||
} else {
|
||||
this.$api.sendRequest({
|
||||
url: '/api/member/info',
|
||||
complete: () => {
|
||||
if (!uni.getStorageSync('token')) this.getAuthInfo();
|
||||
}
|
||||
});
|
||||
}
|
||||
// #endif
|
||||
},
|
||||
onShow: function() {
|
||||
// #ifdef MP-WEIXIN
|
||||
// 自动授权登录
|
||||
if (!uni.getStorageSync('token')) {
|
||||
this.getAuthInfo();
|
||||
} else {
|
||||
this.$api.sendRequest({
|
||||
url: '/api/member/info',
|
||||
complete: () => {
|
||||
if (!uni.getStorageSync('token')) this.getAuthInfo();
|
||||
}
|
||||
});
|
||||
}
|
||||
// #endif
|
||||
},
|
||||
onHide: function() {},
|
||||
methods: {
|
||||
/**
|
||||
* 获取授权信息
|
||||
*/
|
||||
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();
|
||||
}
|
||||
},
|
||||
// 代表在wacth里声明了firstName这个方法之后立即先去执行handler方法
|
||||
immediate: true
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss">
|
||||
@import './common/css/main.scss';
|
||||
@import './common/css/iconfont.css';
|
||||
@import './common/css/icondiy.css'; // 自定义图标库
|
||||
@import './common/css/icon/extend.css'; // 扩展图标库
|
||||
</style>
|
||||
Binary file not shown.
|
|
@ -0,0 +1,123 @@
|
|||
.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 */
|
||||
height: 100vh;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.page-img {
|
||||
background-size: contain !important;
|
||||
background-repeat: no-repeat !important;
|
||||
}
|
||||
|
||||
.page-header {
|
||||
background-size: 100% !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: 100% !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;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,64 @@
|
|||
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: res.message ? res.message : '小程序配置错误'
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
fail: () => {
|
||||
this.$util.showToast({
|
||||
title: '请求失败'
|
||||
});
|
||||
}
|
||||
})
|
||||
// #endif
|
||||
|
||||
// #ifdef H5
|
||||
if (this.$util.isWeiXin()){
|
||||
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;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
// #endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
var config = {
|
||||
// api请求地址
|
||||
baseUrl: '',
|
||||
// 图片域名
|
||||
imgDomain: '',
|
||||
// H5端域名
|
||||
h5Domain: '',
|
||||
// 腾讯地图key
|
||||
mpKey: '',
|
||||
//客服地址
|
||||
webSocket : '',
|
||||
//本地端主动给服务器ping的时间, 0 则不开启 , 单位秒
|
||||
pingInterval: 1500
|
||||
};
|
||||
|
||||
export default config;
|
||||
|
|
@ -0,0 +1,368 @@
|
|||
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',
|
||||
pullDownRefresh: true, //下拉刷新
|
||||
followOfficialAccount: null, // 关注公众号组件
|
||||
isLoad: false // 检测是否刷新
|
||||
};
|
||||
},
|
||||
onLoad(data) {
|
||||
uni.hideTabBar();
|
||||
this.name = data.name || '';
|
||||
this.isDefault = data.is_default || '';
|
||||
|
||||
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]);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
onShow() {
|
||||
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 (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
|
||||
|
||||
},
|
||||
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: {
|
||||
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.isLoad = false;
|
||||
this.$api.sendRequest({
|
||||
url: '/api/diyview/info',
|
||||
data: {
|
||||
name: this.name,
|
||||
is_default: this.isDefault
|
||||
},
|
||||
success: res => {
|
||||
if (res.code != 0 || !res.data) {
|
||||
if (this.$refs.loadingCover) this.$refs.loadingCover.hide();
|
||||
this.$util.showToast({
|
||||
title: '未配置自定义页面数据'
|
||||
});
|
||||
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);
|
||||
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;
|
||||
}
|
||||
// 关注公众号组件
|
||||
if (this.diyData.value[i].componentName == 'FollowOfficialAccount') {
|
||||
this.followOfficialAccount = 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.pullDownRefresh) {
|
||||
setTimeout(() => {
|
||||
this.$refs.diyGroup.refresh(this.diyData);
|
||||
});
|
||||
this.pullDownRefresh = true;
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
uni.stopPullDownRefresh();
|
||||
if (this.$refs.loadingCover) this.$refs.loadingCover.hide();
|
||||
this.isLoad = true;
|
||||
}, 150);
|
||||
}
|
||||
});
|
||||
},
|
||||
closePopupWindow() {
|
||||
this.$refs.uniPopupWindow.close();
|
||||
uni.setStorageSync(this.name + '_popwindow_count', -1);
|
||||
},
|
||||
closeCollectPopupWindow() {
|
||||
this.$refs.collectPopupWindow.close();
|
||||
uni.setStorageSync('isCollect', true);
|
||||
},
|
||||
uniPopupWindowFn() {
|
||||
this.$util.diyRedirectTo(this.diyData.global.popWindow.link);
|
||||
this.closePopupWindow();
|
||||
}
|
||||
},
|
||||
onPageScroll(e) {
|
||||
if (this.$refs.topNav) {
|
||||
if (e.scrollTop >= 20) {
|
||||
this.$refs.topNav.navTopBg();
|
||||
} else {
|
||||
this.$refs.topNav.unSetnavTopBg();
|
||||
}
|
||||
}
|
||||
},
|
||||
onPullDownRefresh() {
|
||||
this.pullDownRefresh = false;
|
||||
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 (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
|
||||
},
|
||||
//分享给好友
|
||||
onShareAppMessage() {
|
||||
return this.mpShareData.appMessage;
|
||||
},
|
||||
//分享到朋友圈
|
||||
onShareTimeline() {
|
||||
return this.mpShareData.timeLine;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
export default {
|
||||
emjoyList: {
|
||||
"[emjoy_01]": 'public/static/img/emjoy/emjoy_01.gif',
|
||||
"[emjoy_02]": 'public/static/img/emjoy/emjoy_02.gif',
|
||||
"[emjoy_03]": 'public/static/img/emjoy/emjoy_03.gif',
|
||||
"[emjoy_04]": 'public/static/img/emjoy/emjoy_04.gif',
|
||||
"[emjoy_05]": 'public/static/img/emjoy/emjoy_05.gif',
|
||||
"[emjoy_06]": 'public/static/img/emjoy/emjoy_06.gif',
|
||||
"[emjoy_07]": 'public/static/img/emjoy/emjoy_07.gif',
|
||||
"[emjoy_08]": 'public/static/img/emjoy/emjoy_08.gif',
|
||||
"[emjoy_09]": 'public/static/img/emjoy/emjoy_09.gif',
|
||||
|
||||
"[emjoy_10]": 'public/static/img/emjoy/emjoy_10.gif',
|
||||
"[emjoy_11]": 'public/static/img/emjoy/emjoy_11.gif',
|
||||
"[emjoy_12]": 'public/static/img/emjoy/emjoy_12.gif',
|
||||
"[emjoy_13]": 'public/static/img/emjoy/emjoy_13.gif',
|
||||
"[emjoy_14]": 'public/static/img/emjoy/emjoy_14.gif',
|
||||
"[emjoy_15]": 'public/static/img/emjoy/emjoy_15.gif',
|
||||
"[emjoy_16]": 'public/static/img/emjoy/emjoy_16.gif',
|
||||
"[emjoy_17]": 'public/static/img/emjoy/emjoy_17.gif',
|
||||
"[emjoy_18]": 'public/static/img/emjoy/emjoy_18.gif',
|
||||
"[emjoy_19]": 'public/static/img/emjoy/emjoy_19.gif',
|
||||
|
||||
"[emjoy_20]": 'public/static/img/emjoy/emjoy_20.gif',
|
||||
"[emjoy_21]": 'public/static/img/emjoy/emjoy_21.gif',
|
||||
"[emjoy_22]": 'public/static/img/emjoy/emjoy_22.gif',
|
||||
"[emjoy_23]": 'public/static/img/emjoy/emjoy_23.gif',
|
||||
"[emjoy_24]": 'public/static/img/emjoy/emjoy_24.gif',
|
||||
"[emjoy_25]": 'public/static/img/emjoy/emjoy_25.gif',
|
||||
"[emjoy_26]": 'public/static/img/emjoy/emjoy_26.gif',
|
||||
"[emjoy_27]": 'public/static/img/emjoy/emjoy_27.gif',
|
||||
"[emjoy_28]": 'public/static/img/emjoy/emjoy_28.gif',
|
||||
"[emjoy_29]": 'public/static/img/emjoy/emjoy_29.gif',
|
||||
|
||||
"[emjoy_30]": 'public/static/img/emjoy/emjoy_30.gif',
|
||||
"[emjoy_31]": 'public/static/img/emjoy/emjoy_31.gif',
|
||||
"[emjoy_32]": 'public/static/img/emjoy/emjoy_32.gif',
|
||||
"[emjoy_33]": 'public/static/img/emjoy/emjoy_33.gif',
|
||||
"[emjoy_34]": 'public/static/img/emjoy/emjoy_34.gif',
|
||||
"[emjoy_35]": 'public/static/img/emjoy/emjoy_35.gif',
|
||||
"[emjoy_36]": 'public/static/img/emjoy/emjoy_36.gif',
|
||||
"[emjoy_37]": 'public/static/img/emjoy/emjoy_37.gif',
|
||||
"[emjoy_38]": 'public/static/img/emjoy/emjoy_38.gif',
|
||||
"[emjoy_39]": 'public/static/img/emjoy/emjoy_39.gif',
|
||||
|
||||
"[emjoy_40]": 'public/static/img/emjoy/emjoy_40.gif',
|
||||
"[emjoy_41]": 'public/static/img/emjoy/emjoy_41.gif',
|
||||
"[emjoy_42]": 'public/static/img/emjoy/emjoy_42.gif',
|
||||
"[emjoy_43]": 'public/static/img/emjoy/emjoy_43.gif',
|
||||
"[emjoy_44]": 'public/static/img/emjoy/emjoy_44.gif',
|
||||
"[emjoy_45]": 'public/static/img/emjoy/emjoy_45.gif',
|
||||
"[emjoy_46]": 'public/static/img/emjoy/emjoy_46.gif',
|
||||
"[emjoy_47]": 'public/static/img/emjoy/emjoy_47.gif',
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
export default {
|
||||
data() {
|
||||
return {
|
||||
fenxiaoWords: {}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getFenxiaoWrods() {
|
||||
this.$api.sendRequest({
|
||||
url: '/fenxiao/api/config/words',
|
||||
success: res => {
|
||||
if (res.code >= 0 && res.data) {
|
||||
this.fenxiaoWords = res.data;
|
||||
uni.setStorageSync('fenxiaoWords', res.data);
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
onShow() {
|
||||
if (uni.getStorageSync('fenxiaoWords')) this.fenxiaoWords = uni.getStorageSync('fenxiaoWords');
|
||||
this.getFenxiaoWrods();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,129 @@
|
|||
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();
|
||||
},
|
||||
computed: {
|
||||
themeStyle() {
|
||||
return uni.getStorageSync('theme_style');
|
||||
},
|
||||
//插件是否存在
|
||||
addonIsExist() {
|
||||
return uni.getStorageSync('addon_is_exist');
|
||||
},
|
||||
tabBarList() {
|
||||
// return uni.getStorageSync('bottomNav');
|
||||
return this.$store.state.tabBarList;
|
||||
},
|
||||
siteInfo() {
|
||||
return uni.getStorageSync('siteInfo');
|
||||
// return this.$store.state.siteInfo;
|
||||
},
|
||||
storeToken() {
|
||||
return this.$store.state.token;
|
||||
},
|
||||
bottomNavHidden() {
|
||||
return this.$store.state.bottomNavHidden;
|
||||
// return uni.getStorageSync('bottomNavHidden');
|
||||
}
|
||||
},
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,408 @@
|
|||
// 商品详情业务
|
||||
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: '',
|
||||
globalS: {
|
||||
title: '',
|
||||
topNavColor: "#ffffff",
|
||||
topNavBg: false,
|
||||
navBarSwitch: true, // 导航栏是否显示
|
||||
textNavColor: "#333333",
|
||||
moreLink: {
|
||||
name: ""
|
||||
},
|
||||
navStyle: 1,
|
||||
bgUrl: '',
|
||||
},
|
||||
}
|
||||
},
|
||||
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);
|
||||
this.globalS.title = this.goodsSkuDetail.goods_name;
|
||||
if (this.goodsSkuDetail.config) {
|
||||
this.globalS.navBarSwitch = this.goodsSkuDetail.config.nav_bar_switch;
|
||||
}
|
||||
|
||||
this.modifyGoodsInfo();
|
||||
this.getWhetherCollection();
|
||||
|
||||
// 初始化商品详情视图数据
|
||||
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,
|
||||
isVirtual:this.goodsSkuDetail.is_virtual
|
||||
});
|
||||
|
||||
//媒体
|
||||
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);
|
||||
}
|
||||
|
||||
let maxHeight = '';
|
||||
this.goodsSkuDetail.goods_image_list.forEach((item, index) => {
|
||||
if (typeof item.pic_spec == "string")
|
||||
item.pic_spec = item.pic_spec.split('*');
|
||||
|
||||
uni.getSystemInfo({
|
||||
success: (res) => {
|
||||
let ratio = item.pic_spec[0] / res.windowWidth;
|
||||
item.pic_spec[0] = item.pic_spec[0] / ratio;
|
||||
item.pic_spec[1] = item.pic_spec[1] / ratio;
|
||||
}
|
||||
});
|
||||
|
||||
if (!maxHeight || maxHeight < item.pic_spec[1]) {
|
||||
maxHeight = item.pic_spec[1];
|
||||
}
|
||||
})
|
||||
this.goodsSkuDetail.swiperHeight = maxHeight + 'px';
|
||||
|
||||
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 != '/pages/goods/detail') this.setPublicShare();
|
||||
|
||||
this.getBarrageData();
|
||||
this.getGoodsForm();
|
||||
},
|
||||
/**
|
||||
* 刷新商品详情数据
|
||||
* @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);
|
||||
|
||||
if (typeof this.getMemberCardInfo == 'function') this.getMemberCardInfo();
|
||||
},
|
||||
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');
|
||||
},
|
||||
//获取购物车数量
|
||||
getCartCount() {
|
||||
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]
|
||||
})
|
||||
},
|
||||
/**
|
||||
* 获取商品表单
|
||||
*/
|
||||
getGoodsForm() {
|
||||
this.$api.sendRequest({
|
||||
url: "/form/api/form/goodsform",
|
||||
data: {
|
||||
goods_id: this.goodsSkuDetail.goods_id
|
||||
},
|
||||
success: res => {
|
||||
if (res.code == 0 && res.data) this.$set(this.goodsSkuDetail, 'goods_form', 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
|
||||
}
|
||||
|
|
@ -0,0 +1,411 @@
|
|||
import util from './util.js'
|
||||
/*
|
||||
* HTML5 Parser By Sam Blowes
|
||||
*
|
||||
* Designed for HTML5 documents
|
||||
*
|
||||
* Original code by John Resig (ejohn.org)
|
||||
* http://ejohn.org/blog/pure-javascript-html-parser/
|
||||
* Original code by Erik Arvidsson, Mozilla Public License
|
||||
* http://erik.eae.net/simplehtmlparser/simplehtmlparser.js
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
* License
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* This code is triple licensed using Apache Software License 2.0,
|
||||
* Mozilla Public License or GNU Public License
|
||||
*
|
||||
* ////////////////////////////////////////////////////////////////////////////
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy
|
||||
* of the License at http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* ////////////////////////////////////////////////////////////////////////////
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License
|
||||
* Version 1.1 (the "License"); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS"
|
||||
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing rights and limitations
|
||||
* under the License.
|
||||
*
|
||||
* The Original Code is Simple HTML Parser.
|
||||
*
|
||||
* The Initial Developer of the Original Code is Erik Arvidsson.
|
||||
* Portions created by Erik Arvidssson are Copyright (C) 2004. All Rights
|
||||
* Reserved.
|
||||
*
|
||||
* ////////////////////////////////////////////////////////////////////////////
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
* Usage
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* // Use like so:
|
||||
* HTMLParser(htmlString, {
|
||||
* start: function(tag, attrs, unary) {},
|
||||
* end: function(tag) {},
|
||||
* chars: function(text) {},
|
||||
* comment: function(text) {}
|
||||
* });
|
||||
*
|
||||
* // or to get an XML string:
|
||||
* HTMLtoXML(htmlString);
|
||||
*
|
||||
* // or to get an XML DOM Document
|
||||
* HTMLtoDOM(htmlString);
|
||||
*
|
||||
* // or to inject into an existing document/DOM node
|
||||
* HTMLtoDOM(htmlString, document);
|
||||
* HTMLtoDOM(htmlString, document.body);
|
||||
*
|
||||
*/
|
||||
// Regular Expressions for parsing tags and attributes
|
||||
var startTag =
|
||||
/^<([-A-Za-z0-9_]+)((?:\s+[a-zA-Z_:][-a-zA-Z0-9_:.]*(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)>/;
|
||||
var endTag = /^<\/([-A-Za-z0-9_]+)[^>]*>/;
|
||||
var attr = /([a-zA-Z_:][-a-zA-Z0-9_:.]*)(?:\s*=\s*(?:(?:"((?:\\.|[^"])*)")|(?:'((?:\\.|[^'])*)')|([^>\s]+)))?/g; // Empty Elements - HTML 5
|
||||
|
||||
var empty = makeMap(
|
||||
'area,base,basefont,br,col,frame,hr,img,input,link,meta,param,embed,command,keygen,source,track,wbr'); // Block Elements - HTML 5
|
||||
// fixed by xxx 将 ins 标签从块级名单中移除
|
||||
|
||||
var block = makeMap(
|
||||
'a,address,article,applet,aside,audio,blockquote,button,canvas,center,dd,del,dir,div,dl,dt,fieldset,figcaption,figure,footer,form,frameset,h1,h2,h3,h4,h5,h6,header,hgroup,hr,iframe,isindex,li,map,menu,noframes,noscript,object,ol,output,p,pre,section,script,table,tbody,td,tfoot,th,thead,tr,ul,video'
|
||||
); // Inline Elements - HTML 5
|
||||
|
||||
var inline = makeMap(
|
||||
'abbr,acronym,applet,b,basefont,bdo,big,br,button,cite,code,del,dfn,em,font,i,iframe,img,input,ins,kbd,label,map,object,q,s,samp,script,select,small,span,strike,strong,sub,sup,textarea,tt,u,var'
|
||||
); // Elements that you can, intentionally, leave open
|
||||
// (and which close themselves)
|
||||
|
||||
var closeSelf = makeMap('colgroup,dd,dt,li,options,p,td,tfoot,th,thead,tr'); // Attributes that have their values filled in disabled="disabled"
|
||||
|
||||
var fillAttrs = makeMap(
|
||||
'checked,compact,declare,defer,disabled,ismap,multiple,nohref,noresize,noshade,nowrap,readonly,selected'); // Special Elements (can contain anything)
|
||||
|
||||
var special = makeMap('script,style');
|
||||
|
||||
function HTMLParser(html, handler) {
|
||||
var index;
|
||||
var chars;
|
||||
var match;
|
||||
var stack = [];
|
||||
var last = html;
|
||||
|
||||
stack.last = function() {
|
||||
return this[this.length - 1];
|
||||
};
|
||||
|
||||
while (html) {
|
||||
chars = true; // Make sure we're not in a script or style element
|
||||
if (!stack.last() || !special[stack.last()]) {
|
||||
// Comment
|
||||
if (html.indexOf('<!--') == 0) {
|
||||
index = html.indexOf('-->');
|
||||
|
||||
if (index >= 0) {
|
||||
if (handler.comment) {
|
||||
handler.comment(html.substring(4, index));
|
||||
}
|
||||
|
||||
html = html.substring(index + 3);
|
||||
chars = false;
|
||||
} // end tag
|
||||
|
||||
} else if (html.indexOf('</') == 0) {
|
||||
match = html.match(endTag);
|
||||
|
||||
if (match) {
|
||||
html = html.substring(match[0].length);
|
||||
match[0].replace(endTag, parseEndTag);
|
||||
chars = false;
|
||||
} // start tag
|
||||
|
||||
} else if (html.indexOf('<') == 0) {
|
||||
match = html.match(startTag);
|
||||
|
||||
if (match) {
|
||||
html = html.substring(match[0].length);
|
||||
match[0].replace(startTag, parseStartTag);
|
||||
chars = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (chars) {
|
||||
index = html.indexOf('<');
|
||||
var text = index < 0 ? html : html.substring(0, index);
|
||||
html = index < 0 ? '' : html.substring(index);
|
||||
|
||||
if (handler.chars) {
|
||||
handler.chars(text);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
html = html.replace(new RegExp('([\\s\\S]*?)<\/' + stack.last() + '[^>]*>'), function(all, text) {
|
||||
text = text.replace(/<!--([\s\S]*?)-->|<!\[CDATA\[([\s\S]*?)]]>/g, '$1$2');
|
||||
|
||||
if (handler.chars) {
|
||||
handler.chars(text);
|
||||
}
|
||||
|
||||
return '';
|
||||
});
|
||||
parseEndTag('', stack.last());
|
||||
}
|
||||
|
||||
|
||||
if (html == last) {
|
||||
throw 'Parse Error: ' + html;
|
||||
}
|
||||
|
||||
last = html;
|
||||
} // Clean up any remaining tags
|
||||
|
||||
|
||||
parseEndTag();
|
||||
|
||||
function parseStartTag(tag, tagName, rest, unary) {
|
||||
tagName = tagName.toLowerCase();
|
||||
|
||||
if (block[tagName]) {
|
||||
while (stack.last() && inline[stack.last()]) {
|
||||
parseEndTag('', stack.last());
|
||||
}
|
||||
}
|
||||
|
||||
if (closeSelf[tagName] && stack.last() == tagName) {
|
||||
parseEndTag('', tagName);
|
||||
}
|
||||
|
||||
unary = empty[tagName] || !!unary;
|
||||
|
||||
if (!unary) {
|
||||
stack.push(tagName);
|
||||
}
|
||||
|
||||
if (handler.start) {
|
||||
var attrs = [];
|
||||
rest.replace(attr, function(match, name) {
|
||||
var value = arguments[2] ? arguments[2] : arguments[3] ? arguments[3] : arguments[4] ? arguments[4] : fillAttrs[
|
||||
name] ? name : '';
|
||||
attrs.push({
|
||||
name: name,
|
||||
value: value,
|
||||
escaped: value.replace(/(^|[^\\])"/g, '$1\\\"') // "
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
if (handler.start) {
|
||||
handler.start(tagName, attrs, unary);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function parseEndTag(tag, tagName) {
|
||||
// If no tag name is provided, clean shop
|
||||
if (!tagName) {
|
||||
var pos = 0;
|
||||
} // Find the closest opened tag of the same type
|
||||
else {
|
||||
for (var pos = stack.length - 1; pos >= 0; pos--) {
|
||||
if (stack[pos] == tagName) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pos >= 0) {
|
||||
// Close all the open elements, up the stack
|
||||
for (var i = stack.length - 1; i >= pos; i--) {
|
||||
if (handler.end) {
|
||||
handler.end(stack[i]);
|
||||
}
|
||||
} // Remove the open elements from the stack
|
||||
|
||||
|
||||
stack.length = pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function makeMap(str) {
|
||||
var obj = {};
|
||||
var items = str.split(',');
|
||||
|
||||
for (var i = 0; i < items.length; i++) {
|
||||
obj[items[i]] = true;
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
function removeDOCTYPE(html) {
|
||||
return html.replace(/<\?xml.*\?>\n/, '').replace(/<!doctype.*>\n/, '').replace(/<!DOCTYPE.*>\n/, '');
|
||||
}
|
||||
|
||||
/**
|
||||
* 忽略注释
|
||||
* @param {Object} html
|
||||
*/
|
||||
function replaceAnnotation(html) {
|
||||
var html = html.replace(/<!--[\s\S]*-->/gi, '');
|
||||
return html;
|
||||
}
|
||||
|
||||
/**
|
||||
* 替换图片
|
||||
* @param {Object} html
|
||||
*/
|
||||
function replaceImage(html) {
|
||||
// #ifdef MP
|
||||
let info = uni.getSystemInfoSync();
|
||||
var screenWidth = info.safeArea.width || info.screenWidth;
|
||||
screenWidth -= 20;
|
||||
screenWidth += 'px';
|
||||
// #endif
|
||||
|
||||
// #ifdef H5
|
||||
var screenWidth = '100%';
|
||||
// #endif
|
||||
|
||||
let rep = `<img style="width:100% !important;display:block;max-width: ${screenWidth} !important;"`;
|
||||
var html = html.replace(/\\/g, '').replace(/<img/g, rep);
|
||||
html = html.replace(/<img [^>]*src=['"]([^'"]+)[^>]*>/gi, (match, capture) => {
|
||||
return rep + ' src="' + util.img(capture) + '"/>';
|
||||
});
|
||||
return html;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将style属性中的双引号改为单引号
|
||||
* @param {Object} html
|
||||
*/
|
||||
function replaceStyleQuotes(html) {
|
||||
var html = html.replace(/style\s*=\s*["][^>]*;[^"]?/gi, (match, capture) => {
|
||||
match = match.replace(/[:](\s?)[\s\S]*/gi, (a, b) => {
|
||||
return a.replace(/"/g, "'");
|
||||
});
|
||||
return match;
|
||||
});
|
||||
return html;
|
||||
}
|
||||
|
||||
function parseAttrs(attrs) {
|
||||
return attrs.reduce(function(pre, attr) {
|
||||
var value = attr.value;
|
||||
var name = attr.name;
|
||||
|
||||
if (pre[name]) {
|
||||
pre[name] = pre[name] + " " + value;
|
||||
} else {
|
||||
pre[name] = value;
|
||||
}
|
||||
|
||||
return pre;
|
||||
}, {});
|
||||
}
|
||||
|
||||
function parseHtml(html) {
|
||||
html = removeDOCTYPE(html);
|
||||
html = replaceAnnotation(html); //忽略注释
|
||||
html = replaceImage(html); //替换图片
|
||||
html = replaceStyleQuotes(html); //将style属性中的双引号改为单引号
|
||||
var stacks = [];
|
||||
var results = {
|
||||
node: 'root',
|
||||
children: []
|
||||
};
|
||||
HTMLParser(html, {
|
||||
start: function start(tag, attrs, unary) {
|
||||
var node = {
|
||||
name: tag
|
||||
};
|
||||
|
||||
if (attrs.length !== 0) {
|
||||
node.attrs = parseAttrs(attrs);
|
||||
}
|
||||
|
||||
if (unary) {
|
||||
var parent = stacks[0] || results;
|
||||
|
||||
if (!parent.children) {
|
||||
parent.children = [];
|
||||
}
|
||||
|
||||
parent.children.push(node);
|
||||
} else {
|
||||
stacks.unshift(node);
|
||||
}
|
||||
},
|
||||
end: function end(tag) {
|
||||
var node = stacks.shift();
|
||||
if (node.name !== tag) console.error('invalid state: mismatch end tag');
|
||||
if (stacks.length === 0) {
|
||||
results.children.push(node);
|
||||
} else {
|
||||
var parent = stacks[0];
|
||||
|
||||
if (!parent.children) {
|
||||
parent.children = [];
|
||||
}
|
||||
|
||||
parent.children.push(node);
|
||||
}
|
||||
},
|
||||
chars: function chars(text) {
|
||||
var node = {
|
||||
type: 'text',
|
||||
text: text
|
||||
};
|
||||
|
||||
if (stacks.length === 0) {
|
||||
results.children.push(node);
|
||||
} else {
|
||||
var parent = stacks[0];
|
||||
|
||||
if (!parent.children) {
|
||||
parent.children = [];
|
||||
}
|
||||
|
||||
parent.children.push(node);
|
||||
}
|
||||
},
|
||||
comment: function comment(text) {
|
||||
var node = {
|
||||
node: 'comment',
|
||||
text: text
|
||||
};
|
||||
var parent = stacks[0];
|
||||
|
||||
if (!parent.children) {
|
||||
parent.children = [];
|
||||
}
|
||||
|
||||
parent.children.push(node);
|
||||
}
|
||||
});
|
||||
return results.children;
|
||||
}
|
||||
|
||||
export default parseHtml;
|
||||
|
|
@ -0,0 +1,171 @@
|
|||
import Config from './config.js'
|
||||
import Util from './util.js'
|
||||
import store from '@/store/index.js'
|
||||
|
||||
// #ifdef H5
|
||||
const app_type = Util.isWeiXin() ? 'wechat' : 'h5';
|
||||
const app_type_name = Util.isWeiXin() ? '微信公众号' : 'H5';
|
||||
// #endif
|
||||
|
||||
// #ifdef MP-WEIXIN
|
||||
const app_type = 'weapp';
|
||||
const app_type_name = '微信小程序';
|
||||
// #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 = 'app';
|
||||
const app_type_name = 'APP';
|
||||
// #endif
|
||||
|
||||
export default {
|
||||
sendRequest(params) {
|
||||
if (!Config.baseUrl) {
|
||||
uni.showToast({ title: '未配置请求域名', 'icon': 'none', duration: 10000});
|
||||
return;
|
||||
}
|
||||
|
||||
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('store')) data.store_id = uni.getStorageSync('store').store_id;
|
||||
|
||||
// 参数
|
||||
if (params.data != undefined) Object.assign(data, params.data);
|
||||
|
||||
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);
|
||||
// } catch (e) {
|
||||
// //TODO handle the exception
|
||||
// console.log('api error:', 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) => {
|
||||
if (res.errMsg && res.errMsg == 'request:fail url not in domain list') {
|
||||
uni.showToast({ title: Config.baseUrl + '不在request 合法域名列表中', 'icon': 'none', duration: 10000});
|
||||
return;
|
||||
}
|
||||
reject(res);
|
||||
},
|
||||
complete: (res) => {
|
||||
if ((res.errMsg && res.errMsg != "request:ok") || (res.statusCode && [200, 500].indexOf(res.statusCode) == -1)) {
|
||||
uni.showToast({ title: Config.baseUrl + '请求失败', 'icon': 'none', duration: 10000})
|
||||
return;
|
||||
}
|
||||
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);
|
||||
// } catch (e) {
|
||||
// //TODO handle the exception
|
||||
// console.log('api error:', 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'
|
||||
})
|
||||
}
|
||||
typeof params.success == 'function' && params.success(res.data);
|
||||
},
|
||||
fail: (res) => {
|
||||
if (res.errMsg && res.errMsg == 'request:fail url not in domain list') {
|
||||
uni.showToast({ title: Config.baseUrl + '不在request 合法域名列表中', 'icon': 'none', duration: 10000});
|
||||
return;
|
||||
}
|
||||
typeof params.fail == 'function' && params.fail(res);
|
||||
},
|
||||
complete: (res) => {
|
||||
if ((res.errMsg && res.errMsg != "request:ok") || (res.statusCode && [200, 500].indexOf(res.statusCode) == -1)) {
|
||||
uni.showToast({ title: Config.baseUrl + '请求失败', 'icon': 'none', duration: 10000})
|
||||
return;
|
||||
}
|
||||
typeof params.complete == 'function' && params.complete(res);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,127 @@
|
|||
const langList = ['zh-cn', 'en-us'];
|
||||
|
||||
var locale = uni.getStorageSync('lang') || "zh-cn"; //设置语言
|
||||
|
||||
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 = uni.getStorageSync('lang') || "zh-cn"; //设置语言
|
||||
|
||||
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: this.lang("tabBar.home")
|
||||
});
|
||||
uni.setTabBarItem({
|
||||
index: 1,
|
||||
text: this.lang("tabBar.category")
|
||||
});
|
||||
uni.setTabBarItem({
|
||||
index: 2,
|
||||
text: this.lang("tabBar.cart")
|
||||
});
|
||||
uni.setTabBarItem({
|
||||
index: 3,
|
||||
text: this.lang("tabBar.member")
|
||||
});
|
||||
},
|
||||
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;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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,
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
(function() {
|
||||
var u = navigator.userAgent,
|
||||
w = window.innerWidth;
|
||||
if (w >= 960) {
|
||||
window.innerWidth = 960;
|
||||
window.onload = function() {
|
||||
window.innerWidth = 960;
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,419 @@
|
|||
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',//活动辅色
|
||||
},
|
||||
groupby:{
|
||||
groupby_promotion_color: '#E64136',//活动背景
|
||||
groupby_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',//活动辅色
|
||||
},
|
||||
groupby:{
|
||||
groupby_promotion_color: '#E64136',//活动背景
|
||||
groupby_promotion_aux_color: '#F7B500',//活动辅色
|
||||
},
|
||||
},
|
||||
'blue':{
|
||||
name:'blue',
|
||||
main_color : '#36ABFF',
|
||||
aux_color : '#FA6400',
|
||||
bg_color: '#36ABFF',
|
||||
bg_color_shallow: '#36ABFF',
|
||||
promotion_color: '#36ABFF ',
|
||||
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:'#36ABFF',
|
||||
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',//活动辅色
|
||||
},
|
||||
groupby:{
|
||||
groupby_promotion_color: '#E64136',//活动背景
|
||||
groupby_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',//活动辅色
|
||||
},
|
||||
groupby:{
|
||||
groupby_promotion_color: '#E64136',//活动背景
|
||||
groupby_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',//活动辅色
|
||||
},
|
||||
groupby:{
|
||||
groupby_promotion_color: '#E64136',//活动背景
|
||||
groupby_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',//活动辅色
|
||||
},
|
||||
groupby:{
|
||||
groupby_promotion_color: '#E64136',//活动背景
|
||||
groupby_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',//活动辅色
|
||||
},
|
||||
groupby:{
|
||||
groupby_promotion_color: '#E64136',//活动背景
|
||||
groupby_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',//活动辅色
|
||||
},
|
||||
groupby:{
|
||||
groupby_promotion_color: '#E64136',//活动背景
|
||||
groupby_promotion_aux_color: '#F7B500',//活动辅色
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,900 @@
|
|||
import Config from './config.js'
|
||||
import store from '@/store/index.js'
|
||||
import Http from './http.js'
|
||||
import {
|
||||
Weixin
|
||||
} from 'common/js/wx-jssdk.js';
|
||||
|
||||
export default {
|
||||
/**
|
||||
* 页面跳转
|
||||
* @param {string} to 跳转链接 /pages/idnex/index
|
||||
* @param {Object} param 参数 {key : value, ...}
|
||||
* @param {string} mode 模式
|
||||
*/
|
||||
redirectTo(to, param, mode) {
|
||||
let url = to;
|
||||
let tabbarList = ['/pages/index/index', '/pages/goods/category', '/pages/goods/cart',
|
||||
'/pages/member/index'
|
||||
]
|
||||
if (param != undefined) {
|
||||
Object.keys(param).forEach(function(key) {
|
||||
if (url.indexOf('?') != -1) {
|
||||
url += "&" + key + "=" + param[key];
|
||||
} else {
|
||||
url += "?" + key + "=" + param[key];
|
||||
}
|
||||
});
|
||||
}
|
||||
for (let i = 0; i < tabbarList.length; i++) {
|
||||
if (url.indexOf(tabbarList[i]) == 0) {
|
||||
uni.switchTab({
|
||||
url
|
||||
})
|
||||
return;
|
||||
}
|
||||
}
|
||||
switch (mode) {
|
||||
case 'tabbar':
|
||||
// 跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面。
|
||||
uni.switchTab({
|
||||
url
|
||||
})
|
||||
break;
|
||||
case 'redirectTo':
|
||||
// 关闭当前页面,跳转到应用内的某个页面。
|
||||
uni.redirectTo({
|
||||
url
|
||||
});
|
||||
break;
|
||||
case 'reLaunch':
|
||||
// 关闭所有页面,打开到应用内的某个页面。
|
||||
uni.reLaunch({
|
||||
url
|
||||
});
|
||||
break;
|
||||
default:
|
||||
// 保留当前页面,跳转到应用内的某个页面
|
||||
uni.navigateTo({
|
||||
url
|
||||
});
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 图片路径转换
|
||||
* @param {String} img_path 图片地址
|
||||
* @param {Object} params 参数,针对商品、相册里面的图片区分大中小,size: big、mid、small
|
||||
*/
|
||||
img(img_path, params) {
|
||||
var path = "";
|
||||
if (img_path != undefined && img_path != "") {
|
||||
if (img_path.split(',').length > 1) {
|
||||
img_path = img_path.split(',')[0];
|
||||
}
|
||||
if (params && img_path != this.getDefaultImage().goods) {
|
||||
// 过滤默认图
|
||||
let arr = img_path.split(".");
|
||||
let suffix = arr[arr.length - 1];
|
||||
arr.pop();
|
||||
arr[arr.length - 1] = arr[arr.length - 1] + "_" + params.size.toUpperCase();
|
||||
arr.push(suffix);
|
||||
img_path = arr.join(".");
|
||||
}
|
||||
if (img_path.indexOf("http://") == -1 && img_path.indexOf("https://") == -1) {
|
||||
path = Config.imgDomain + "/" + img_path;
|
||||
} else {
|
||||
path = img_path;
|
||||
}
|
||||
// 处理商品助手的图片路径
|
||||
path = path.replace("addons/NsGoodsAssist/", "").replace("shop/goods/", "");
|
||||
}
|
||||
// path += '?t=' + parseInt(new Date().getTime() / 1000);
|
||||
return path;
|
||||
},
|
||||
/**
|
||||
* 时间戳转日期格式
|
||||
* @param {Object} timeStamp
|
||||
*/
|
||||
timeStampTurnTime(timeStamp, type = "") {
|
||||
if (timeStamp != undefined && timeStamp != "" && timeStamp > 0) {
|
||||
var date = new Date();
|
||||
date.setTime(timeStamp * 1000);
|
||||
var y = date.getFullYear();
|
||||
var m = date.getMonth() + 1;
|
||||
m = m < 10 ? ('0' + m) : m;
|
||||
var d = date.getDate();
|
||||
d = d < 10 ? ('0' + d) : d;
|
||||
var h = date.getHours();
|
||||
h = h < 10 ? ('0' + h) : h;
|
||||
var minute = date.getMinutes();
|
||||
var second = date.getSeconds();
|
||||
minute = minute < 10 ? ('0' + minute) : minute;
|
||||
second = second < 10 ? ('0' + second) : second;
|
||||
if (type) {
|
||||
if (type == 'yearMonthDay') {
|
||||
return y + '年' + m + '月' + d + '日';
|
||||
}
|
||||
return y + '-' + m + '-' + d;
|
||||
} else {
|
||||
return y + '-' + m + '-' + d + ' ' + h + ':' + minute + ':' + second;
|
||||
}
|
||||
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 日期格式转时间戳
|
||||
* @param {Object} timeStamp
|
||||
*/
|
||||
timeTurnTimeStamp(string) {
|
||||
var f = string.split(' ', 2);
|
||||
var d = (f[0] ? f[0] : '').split('-', 3);
|
||||
var t = (f[1] ? f[1] : '').split(':', 3);
|
||||
return (new Date(
|
||||
parseInt(d[0], 10) || null,
|
||||
(parseInt(d[1], 10) || 1) - 1,
|
||||
parseInt(d[2], 10) || null,
|
||||
parseInt(t[0], 10) || null,
|
||||
parseInt(t[1], 10) || null,
|
||||
parseInt(t[2], 10) || null
|
||||
)).getTime() / 1000;
|
||||
},
|
||||
/**
|
||||
* 倒计时
|
||||
* @param {Object} seconds 秒
|
||||
*/
|
||||
countDown(seconds) {
|
||||
let [day, hour, minute, second] = [0, 0, 0, 0]
|
||||
if (seconds > 0) {
|
||||
day = Math.floor(seconds / (60 * 60 * 24))
|
||||
hour = Math.floor(seconds / (60 * 60)) - (day * 24)
|
||||
minute = Math.floor(seconds / 60) - (day * 24 * 60) - (hour * 60)
|
||||
second = Math.floor(seconds) - (day * 24 * 60 * 60) - (hour * 60 * 60) - (minute * 60)
|
||||
}
|
||||
if (day < 10) {
|
||||
day = '0' + day
|
||||
}
|
||||
if (hour < 10) {
|
||||
hour = '0' + hour
|
||||
}
|
||||
if (minute < 10) {
|
||||
minute = '0' + minute
|
||||
}
|
||||
if (second < 10) {
|
||||
second = '0' + second
|
||||
}
|
||||
return {
|
||||
d: day,
|
||||
h: hour,
|
||||
i: minute,
|
||||
s: second
|
||||
};
|
||||
},
|
||||
/**
|
||||
* 数值去重
|
||||
* @param {Array} arr 数组
|
||||
* @param {string} field 字段
|
||||
*/
|
||||
unique(arr, field) {
|
||||
const res = new Map();
|
||||
return arr.filter((a) => !res.has(a[field]) && res.set(a[field], 1));
|
||||
},
|
||||
/**
|
||||
* 判断值是否在数组中
|
||||
* @param {Object} elem
|
||||
* @param {Object} arr
|
||||
* @param {Object} i
|
||||
*/
|
||||
inArray: function(elem, arr) {
|
||||
return arr == null ? -1 : arr.indexOf(elem);
|
||||
},
|
||||
/**
|
||||
* 获取某天日期
|
||||
* @param {Object} day
|
||||
*/
|
||||
getDay: function(day) {
|
||||
var today = new Date();
|
||||
var targetday_milliseconds = today.getTime() + 1000 * 60 * 60 * 24 * day;
|
||||
today.setTime(targetday_milliseconds);
|
||||
|
||||
const doHandleMonth = function(month) {
|
||||
var m = month;
|
||||
if (month.toString().length == 1) {
|
||||
m = "0" + month;
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
var tYear = today.getFullYear();
|
||||
var tMonth = today.getMonth();
|
||||
var tDate = today.getDate();
|
||||
var tWeek = today.getDay();
|
||||
var time = parseInt(today.getTime() / 1000);
|
||||
tMonth = doHandleMonth(tMonth + 1);
|
||||
tDate = doHandleMonth(tDate);
|
||||
|
||||
const week = ['周日', '周一', '周二', '周三', '周四', '周五', '周六']
|
||||
return {
|
||||
't': time,
|
||||
'y': tYear,
|
||||
'm': tMonth,
|
||||
'd': tDate,
|
||||
'w': week[tWeek]
|
||||
};
|
||||
},
|
||||
/**
|
||||
* 图片选择加上传
|
||||
* @param number num
|
||||
* @param {Object} params
|
||||
* @param {Object} callback
|
||||
* @param string url
|
||||
* return array
|
||||
*/
|
||||
upload: function(num, params, callback, url) {
|
||||
// #ifdef H5
|
||||
var app_type = this.isWeiXin() ? 'wechat' : 'h5';
|
||||
var app_type_name = this.isWeiXin() ? '微信公众号' : 'H5';
|
||||
// #endif
|
||||
|
||||
// #ifdef MP-WEIXIN
|
||||
var app_type = 'weapp';
|
||||
var app_type_name = '微信小程序';
|
||||
// #endif
|
||||
|
||||
// #ifdef MP-ALIPAY
|
||||
var app_type = 'aliapp';
|
||||
var app_type_name = '支付宝小程序';
|
||||
// #endif
|
||||
|
||||
// #ifdef MP-BAIDU
|
||||
var app_type = 'baiduapp';
|
||||
var app_type_name = '百度小程序';
|
||||
// #endif
|
||||
|
||||
// #ifdef MP-TOUTIAO
|
||||
var app_type = 'MP-TOUTIAO';
|
||||
var app_type_name = '头条小程序';
|
||||
// #endif
|
||||
|
||||
// #ifdef MP-QQ
|
||||
var app_type = 'MP-QQ';
|
||||
var app_type_name = 'QQ小程序';
|
||||
// #endif
|
||||
var data = {
|
||||
token: uni.getStorageSync('token'),
|
||||
app_type: app_type,
|
||||
app_type_name: app_type_name
|
||||
}
|
||||
data = Object.assign(data, params);
|
||||
|
||||
var imgs_num = num;
|
||||
var _self = this;
|
||||
|
||||
uni.chooseImage({
|
||||
count: imgs_num,
|
||||
sizeType: ['compressed'], //可以指定是原图还是压缩图,默认二者都有
|
||||
sourceType: ['album', 'camera'], //从相册或者拍照
|
||||
success: async function(res) {
|
||||
const tempFilePaths = res.tempFilePaths;
|
||||
var _data = data;
|
||||
var imgs = [];
|
||||
uni.showLoading({
|
||||
title: '图片上传中'
|
||||
})
|
||||
for (var i = 0; i < tempFilePaths.length; i++) {
|
||||
var path = await _self.upload_file_server(tempFilePaths[i], _data, params.path,
|
||||
url);
|
||||
imgs.push(path);
|
||||
if (imgs.length == tempFilePaths.length) {
|
||||
uni.hideLoading()
|
||||
uni.showToast({
|
||||
title: '上传成功',
|
||||
icon: 'none'
|
||||
})
|
||||
typeof callback == 'function' && callback(imgs);
|
||||
}
|
||||
}
|
||||
},
|
||||
fail: err => {
|
||||
uni.hideLoading()
|
||||
uni.showToast({
|
||||
title: '上传失败',
|
||||
icon: 'none'
|
||||
})
|
||||
}
|
||||
});
|
||||
},
|
||||
//上传
|
||||
upload_file_server(tempFilePath, data, path, url = "", callback) {
|
||||
if (url) {
|
||||
var uploadUrl = Config.baseUrl + url
|
||||
} else {
|
||||
var uploadUrl = Config.baseUrl + '/api/upload/' + path
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.uploadFile({
|
||||
url: uploadUrl,
|
||||
filePath: tempFilePath,
|
||||
name: 'file',
|
||||
formData: data,
|
||||
success: function(res) {
|
||||
var path_str = JSON.parse(res.data);
|
||||
if (path_str.code >= 0) {
|
||||
resolve(path_str.data.pic_path);
|
||||
typeof callback == 'function' && callback(path_str.data.pic_path);
|
||||
} else {
|
||||
reject("error");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
},
|
||||
/**
|
||||
* 复制
|
||||
* @param {Object} message
|
||||
* @param {Object} callback
|
||||
*/
|
||||
copy(value, callback) {
|
||||
// #ifdef H5
|
||||
var oInput = document.createElement('input'); //创建一个隐藏input(重要!)
|
||||
oInput.value = value; //赋值
|
||||
oInput.setAttribute("readonly", "readonly");
|
||||
document.body.appendChild(oInput);
|
||||
oInput.select(); // 选择对象
|
||||
document.execCommand("Copy"); // 执行浏览器复制命令
|
||||
oInput.className = 'oInput';
|
||||
oInput.style.display = 'none';
|
||||
uni.hideKeyboard();
|
||||
this.showToast({
|
||||
title: '复制成功'
|
||||
});
|
||||
|
||||
typeof callback == 'function' && callback();
|
||||
// #endif
|
||||
|
||||
// #ifdef MP || APP-PLUS
|
||||
uni.setClipboardData({
|
||||
data: value,
|
||||
success: () => {
|
||||
typeof callback == 'function' && callback();
|
||||
}
|
||||
});
|
||||
// #endif
|
||||
},
|
||||
/**
|
||||
* 是否是微信浏览器
|
||||
*/
|
||||
isWeiXin() {
|
||||
// #ifndef H5
|
||||
return false;
|
||||
// #endif
|
||||
var ua = navigator.userAgent.toLowerCase();
|
||||
if (ua.match(/MicroMessenger/i) == "micromessenger") {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 显示消息提示框
|
||||
* @param {Object} params 参数
|
||||
*/
|
||||
showToast(params = {}) {
|
||||
params.title = params.title || "";
|
||||
params.icon = params.icon || "none";
|
||||
// params.position = params.position || 'bottom';
|
||||
params.duration = params.duration || 1500;
|
||||
uni.showToast(params);
|
||||
if (params.success) params.success();
|
||||
},
|
||||
/**
|
||||
* 检测苹果X以上的手机
|
||||
*/
|
||||
isIPhoneX() {
|
||||
let res = uni.getSystemInfoSync();
|
||||
if (res.model.search('iPhone X') != -1) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
//判断安卓还是iOS
|
||||
isAndroid() {
|
||||
let platform = uni.getSystemInfoSync().platform
|
||||
if (platform == 'ios') {
|
||||
return false;
|
||||
} else if (platform == 'android') {
|
||||
return true;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 深度拷贝对象
|
||||
* @param {Object} obj
|
||||
*/
|
||||
deepClone(obj) {
|
||||
const isObject = function(obj) {
|
||||
return typeof obj == 'object';
|
||||
}
|
||||
|
||||
if (!isObject(obj)) {
|
||||
throw new Error('obj 不是一个对象!')
|
||||
}
|
||||
//判断传进来的是对象还是数组
|
||||
let isArray = Array.isArray(obj)
|
||||
let cloneObj = isArray ? [] : {}
|
||||
//通过for...in来拷贝
|
||||
for (let key in obj) {
|
||||
cloneObj[key] = isObject(obj[key]) ? this.deepClone(obj[key]) : obj[key]
|
||||
}
|
||||
return cloneObj
|
||||
},
|
||||
/**
|
||||
* 自定义模板的跳转链接
|
||||
* @param {Object} link
|
||||
*/
|
||||
diyRedirectTo(link) {
|
||||
if (link == null || Object.keys(link).length == 1) return;
|
||||
|
||||
if (link.wap_url && link.wap_url.indexOf('http') != -1 || link.wap_url && link.wap_url.indexOf('http') != -1) {
|
||||
// #ifdef H5
|
||||
window.location.href = link.wap_url;
|
||||
// #endif
|
||||
// #ifdef MP
|
||||
this.redirectTo('/pages_tool/webview/webview', {
|
||||
src: encodeURIComponent(link.wap_url)
|
||||
});
|
||||
// #endif
|
||||
} else if (link.appid) {
|
||||
uni.navigateToMiniProgram({
|
||||
appId: link.appid,
|
||||
path: link.page
|
||||
})
|
||||
} else if (link.name == 'MOBILE' && !link.wap_url) {
|
||||
uni.makePhoneCall({
|
||||
phoneNumber: link.mobile,
|
||||
success: (res) => {},
|
||||
fail: (res) => {}
|
||||
});
|
||||
} else if (link.wap_url) {
|
||||
this.redirectTo(link.wap_url);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 获取默认图
|
||||
* @param {Object} link
|
||||
*/
|
||||
getDefaultImage() {
|
||||
let defaultImg = uni.getStorageSync('default_img');
|
||||
if (defaultImg) {
|
||||
defaultImg.goods = this.img(defaultImg.goods);
|
||||
defaultImg.head = this.img(defaultImg.head);
|
||||
defaultImg.store = this.img(defaultImg.store);
|
||||
defaultImg.article = this.img(defaultImg.article);
|
||||
return defaultImg;
|
||||
} else {
|
||||
return {
|
||||
goods: '',
|
||||
head: '',
|
||||
store: '',
|
||||
article: ''
|
||||
};
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 判断手机是否为iphoneX系列
|
||||
*/
|
||||
uniappIsIPhoneX() {
|
||||
let isIphoneX = false;
|
||||
let systemInfo = uni.getSystemInfoSync();
|
||||
// #ifdef MP
|
||||
if (systemInfo.model.search('iPhone X') != -1 || systemInfo.model.search('iPhone 11') != -1 || systemInfo.model
|
||||
.search('iPhone 12') != -1 || systemInfo.model.search('iPhone 13') != -1) {
|
||||
isIphoneX = true;
|
||||
}
|
||||
// #endif
|
||||
|
||||
// #ifdef H5
|
||||
var u = navigator.userAgent;
|
||||
var isIOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios终端
|
||||
if (isIOS) {
|
||||
if (systemInfo.screenWidth == 375 && systemInfo.screenHeight == 812 && systemInfo.pixelRatio == 3) {
|
||||
isIphoneX = true;
|
||||
} else if (systemInfo.screenWidth == 414 && systemInfo.screenHeight == 896 && systemInfo.pixelRatio == 3) {
|
||||
isIphoneX = true;
|
||||
} else if (systemInfo.screenWidth == 414 && systemInfo.screenHeight == 896 && systemInfo.pixelRatio == 2) {
|
||||
isIphoneX = true;
|
||||
}
|
||||
}
|
||||
// #endif
|
||||
return isIphoneX;
|
||||
},
|
||||
/**
|
||||
* 判断手机是否为iphone11系列
|
||||
*/
|
||||
uniappIsIPhone11() {
|
||||
let isIphone11 = false;
|
||||
let systemInfo = uni.getSystemInfoSync();
|
||||
// #ifdef MP
|
||||
if (systemInfo.model.search('iPhone 11') != -1) {
|
||||
isIphone11 = true;
|
||||
}
|
||||
// #endif
|
||||
return isIphone11;
|
||||
},
|
||||
// #ifdef H5
|
||||
//判断该浏览器是否为safaria浏览器
|
||||
isSafari() {
|
||||
let res = uni.getSystemInfoSync();
|
||||
var ua = navigator.userAgent.toLowerCase();
|
||||
if (ua.indexOf('applewebkit') > -1 && ua.indexOf('mobile') > -1 && ua.indexOf('safari') > -1 &&
|
||||
ua.indexOf('linux') === -1 && ua.indexOf('android') === -1 && ua.indexOf('chrome') === -1 &&
|
||||
ua.indexOf('ios') === -1 && ua.indexOf('browser') === -1) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
// #endif
|
||||
numberFixed(e, f) {
|
||||
if (!f) {
|
||||
f = 0;
|
||||
}
|
||||
return Number(e).toFixed(f);
|
||||
},
|
||||
/**
|
||||
* 获取url参数
|
||||
*/
|
||||
getUrlCode(callback) {
|
||||
var url = location.search;
|
||||
var theRequest = new Object();
|
||||
if (url.indexOf('?') != -1) {
|
||||
var str = url.substr(1);
|
||||
var strs = str.split('&');
|
||||
for (var i = 0; i < strs.length; i++) {
|
||||
theRequest[strs[i].split('=')[0]] = strs[i].split('=')[1];
|
||||
}
|
||||
}
|
||||
typeof callback == 'function' && callback(theRequest);
|
||||
},
|
||||
/**
|
||||
* 获取当前页面路由
|
||||
*/
|
||||
getCurrRoute() {
|
||||
let routes = getCurrentPages(); // 获取当前打开过的页面路由数组
|
||||
return routes.length ? routes[routes.length - 1].route : '';
|
||||
},
|
||||
goBack(backUrl = '/pages/index/index') {
|
||||
if (getCurrentPages().length == 1) {
|
||||
this.redirectTo(backUrl);
|
||||
} else {
|
||||
uni.navigateBack();
|
||||
}
|
||||
},
|
||||
/**
|
||||
* @param {Object} 转化时间字符串 (转化时分秒)
|
||||
*/
|
||||
getTimeStr(val) {
|
||||
var h = parseInt(val / 3600).toString();
|
||||
var m = parseInt((val % 3600) / 60).toString();
|
||||
if (m.length == 1) {
|
||||
m = '0' + m;
|
||||
}
|
||||
if (h.length == 1) {
|
||||
h = '0' + h;
|
||||
}
|
||||
return h + ':' + m;
|
||||
},
|
||||
/**
|
||||
* 获取定位信息
|
||||
*/
|
||||
getLocation(param = {}) {
|
||||
uni.getLocation({
|
||||
type: param.type ?? 'gcj02',
|
||||
success: res => {
|
||||
store.commit('setLocation', res);
|
||||
typeof param.success == 'function' && param.success(res);
|
||||
},
|
||||
fail: res => {
|
||||
typeof param.fail == 'function' && param.fail(res);
|
||||
},
|
||||
complete: res => {
|
||||
typeof param.complete == 'function' && param.complete(res);
|
||||
}
|
||||
});
|
||||
},
|
||||
// 计算两个经纬度之间的距离
|
||||
getDistance(lat1, lng1, lat2, lng2) {
|
||||
var radLat1 = lat1 * Math.PI / 180.0;
|
||||
var radLat2 = lat2 * Math.PI / 180.0;
|
||||
var a = radLat1 - radLat2;
|
||||
var b = lng1 * Math.PI / 180.0 - lng2 * Math.PI / 180.0;
|
||||
var s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) +
|
||||
Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2)));
|
||||
s = s * 6378.137; // EARTH_RADIUS;
|
||||
s = Math.round(s * 10000) / 10000;
|
||||
return s;
|
||||
},
|
||||
//记录分享人
|
||||
onSourceMember(source_member) {
|
||||
Http.sendRequest({
|
||||
url: '/api/Member/alterShareRelation',
|
||||
data: {
|
||||
share_member: source_member,
|
||||
},
|
||||
success: res => {
|
||||
if (res.code >= 0) {
|
||||
uni.removeStorage({
|
||||
key: 'source_member',
|
||||
success: res => {
|
||||
console.log('删除成功', res)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
/**
|
||||
* 微信订阅消息
|
||||
*/
|
||||
subscribeMessage(string) {
|
||||
let keywords = string;
|
||||
Http.sendRequest({
|
||||
url: '/weapp/api/weapp/messagetmplids',
|
||||
data: {
|
||||
keywords: keywords
|
||||
},
|
||||
success: res => {
|
||||
if (res.data.length) {
|
||||
uni.requestSubscribeMessage({
|
||||
tmplIds: res.data,
|
||||
success: (res) => {
|
||||
console.log("res", res)
|
||||
},
|
||||
fail: (res) => {
|
||||
console.log('fail', res)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
/**
|
||||
* 分享获取memberId,进行上下级绑定
|
||||
*/
|
||||
getMemberId() {
|
||||
return new Promise((resolve, reject) => {
|
||||
Http.sendRequest({
|
||||
url: "/api/member/id",
|
||||
success: res => {
|
||||
if (res.code >= 0) {
|
||||
resolve(res.data)
|
||||
} else {
|
||||
reject(res)
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
},
|
||||
/**
|
||||
* 获取小程序分享内容数据
|
||||
*/
|
||||
getMpShare(path) {
|
||||
//如果没有特别指定 则获取当前页面的路由
|
||||
if (!path) {
|
||||
let route = this.getCurrentRoute();
|
||||
path = route.path;
|
||||
if(path == '/pages/member/index'){
|
||||
return new Promise((resolve, reject) => { resolve({}) });
|
||||
};
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
Http.sendRequest({
|
||||
url: "/weapp/api/weapp/share",
|
||||
data: {
|
||||
path: path
|
||||
},
|
||||
success: res => {
|
||||
if (res.code >= 0) {
|
||||
let shareConfig = res.data.data;
|
||||
if (shareConfig) {
|
||||
//分享给好友
|
||||
let appMessageData = {
|
||||
title: shareConfig.title,
|
||||
path: shareConfig.path,
|
||||
imageUrl: shareConfig.imageUrl,
|
||||
success: res => {},
|
||||
fail: res => {}
|
||||
}
|
||||
//分享到朋友圈
|
||||
let query = '';
|
||||
if (shareConfig.path.indexOf('?') > 0) {
|
||||
query = shareConfig.path.split('?')[1];
|
||||
}
|
||||
let timeLineData = {
|
||||
title: shareConfig.title,
|
||||
query: shareConfig.path,
|
||||
imageUrl: shareConfig.imageUrl,
|
||||
}
|
||||
resolve({
|
||||
appMessage: appMessageData,
|
||||
timeLine: timeLineData,
|
||||
})
|
||||
} else {
|
||||
reject(res.data);
|
||||
}
|
||||
} else {
|
||||
reject(res.data)
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
},
|
||||
/**
|
||||
* 设置公众号分享
|
||||
* @param {Object} shareData
|
||||
*/
|
||||
setPublicShare(shareData, callback) {
|
||||
if (!this.isWeiXin()) return;
|
||||
Http.sendRequest({
|
||||
url: '/wechat/api/wechat/jssdkconfig',
|
||||
data: {
|
||||
url: uni.getSystemInfoSync().platform == 'ios' ? uni.getStorageSync('initUrl') : window.location
|
||||
.href
|
||||
},
|
||||
success: res => {
|
||||
if (res.code == 0) {
|
||||
var wxJS = new Weixin();
|
||||
wxJS.init(res.data);
|
||||
wxJS.weixin.showOptionMenu();
|
||||
|
||||
wxJS.setShareData({
|
||||
title: shareData.title ?? '',
|
||||
desc: shareData.desc ?? '',
|
||||
link: shareData.link ?? location.href,
|
||||
imgUrl: shareData.imgUrl ? this.img(shareData.imgUrl) : ''
|
||||
}, (res) => {
|
||||
typeof callback == 'function' && callback(res);
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
//获取当前路由
|
||||
getCurrentRoute() {
|
||||
let currentRoutes = getCurrentPages(); // 获取当前打开过的页面路由数组
|
||||
let currentRoute = currentRoutes[currentRoutes.length - 1].route //获取当前页面路由
|
||||
let currentParam = currentRoutes[currentRoutes.length - 1].options; //获取路由参数
|
||||
// 拼接参数
|
||||
let param = [];
|
||||
for (let key in currentParam) {
|
||||
param.push(key + '=' + currentParam[key])
|
||||
}
|
||||
let currentPath = '/' + currentRoute;
|
||||
let currentQuery = param.join('&');
|
||||
if (currentQuery) currentPath += '?' + currentQuery;
|
||||
|
||||
return {
|
||||
path: currentPath,
|
||||
query: currentQuery,
|
||||
}
|
||||
},
|
||||
//获取分享路由
|
||||
getCurrentShareRoute(member_id) {
|
||||
let route = this.getCurrentRoute();
|
||||
//去掉原来的分享人数据
|
||||
route.path = route.path.replace(/[?|&]source_member=\d+/, '');
|
||||
if (member_id) {
|
||||
//路径的处理
|
||||
if (route.path.indexOf('?') > 0) {
|
||||
route.path += '&';
|
||||
} else {
|
||||
route.path += '?';
|
||||
}
|
||||
route.path += 'source_member=' + member_id;
|
||||
//参数的处理
|
||||
if (route.query) {
|
||||
route.query += '&';
|
||||
}
|
||||
route.query += 'source_member=' + member_id;
|
||||
}
|
||||
return route;
|
||||
},
|
||||
/**
|
||||
* 对象转style字符串
|
||||
* @param {Object} obj
|
||||
*/
|
||||
objToStyle(obj) {
|
||||
let s = [];
|
||||
for (let i in obj) {
|
||||
s.push(i + ':' + obj[i]);
|
||||
}
|
||||
return s.join(';')
|
||||
},
|
||||
/**
|
||||
* 颜色减值
|
||||
* @param {Object} c1
|
||||
* @param {Object} c2
|
||||
* @param {Object} ratio
|
||||
*/
|
||||
colourBlend(c1, c2, ratio) {
|
||||
ratio = Math.max(Math.min(Number(ratio), 1), 0)
|
||||
let r1 = parseInt(c1.substring(1, 3), 16)
|
||||
let g1 = parseInt(c1.substring(3, 5), 16)
|
||||
let b1 = parseInt(c1.substring(5, 7), 16)
|
||||
let r2 = parseInt(c2.substring(1, 3), 16)
|
||||
let g2 = parseInt(c2.substring(3, 5), 16)
|
||||
let b2 = parseInt(c2.substring(5, 7), 16)
|
||||
let r = Math.round(r1 * (1 - ratio) + r2 * ratio)
|
||||
let g = Math.round(g1 * (1 - ratio) + g2 * ratio)
|
||||
let b = Math.round(b1 * (1 - ratio) + b2 * ratio)
|
||||
r = ('0' + (r || 0).toString(16)).slice(-2)
|
||||
g = ('0' + (g || 0).toString(16)).slice(-2)
|
||||
b = ('0' + (b || 0).toString(16)).slice(-2)
|
||||
return '#' + r + g + b
|
||||
},
|
||||
/**
|
||||
* 生成贝塞尔曲线轨迹
|
||||
* @param {Object} points
|
||||
* @param {Object} times
|
||||
*/
|
||||
bezier(points, times) {
|
||||
var bezier_points = [];
|
||||
var points_D = [];
|
||||
var points_E = [];
|
||||
const DIST_AB = Math.sqrt(Math.pow(points[1]['x'] - points[0]['x'], 2) + Math.pow(points[1]['y'] - points[0][
|
||||
'y'
|
||||
], 2));
|
||||
// 邻控制BC点间距
|
||||
const DIST_BC = Math.sqrt(Math.pow(points[2]['x'] - points[1]['x'], 2) + Math.pow(points[2]['y'] - points[1][
|
||||
'y'
|
||||
], 2));
|
||||
// D每次在AB方向上移动的距离
|
||||
const EACH_MOVE_AD = -(DIST_AB / times);
|
||||
// E每次在BC方向上移动的距离
|
||||
const EACH_MOVE_BE = -(DIST_BC / times);
|
||||
// 点AB的正切
|
||||
const TAN_AB = (points[1]['y'] - points[0]['y']) / (points[1]['x'] - points[0]['x']);
|
||||
// 点BC的正切
|
||||
const TAN_BC = (points[2]['y'] - points[1]['y']) / (points[2]['x'] - points[1]['x']);
|
||||
// 点AB的弧度值
|
||||
const RADIUS_AB = Math.atan(TAN_AB);
|
||||
// 点BC的弧度值
|
||||
const RADIUS_BC = Math.atan(TAN_BC);
|
||||
// 每次执行
|
||||
for (var i = 1; i <= times; i++) {
|
||||
// AD的距离
|
||||
var dist_AD = EACH_MOVE_AD * i;
|
||||
// BE的距离
|
||||
var dist_BE = EACH_MOVE_BE * i;
|
||||
// D点的坐标
|
||||
var point_D = {};
|
||||
point_D['x'] = dist_AD * Math.cos(RADIUS_AB) + points[0]['x'];
|
||||
point_D['y'] = dist_AD * Math.sin(RADIUS_AB) + points[0]['y'];
|
||||
points_D.push(point_D);
|
||||
// E点的坐标
|
||||
var point_E = {};
|
||||
point_E['x'] = dist_BE * Math.cos(RADIUS_BC) + points[1]['x'];
|
||||
point_E['y'] = dist_BE * Math.sin(RADIUS_BC) + points[1]['y'];
|
||||
points_E.push(point_E);
|
||||
// 此时线段DE的正切值
|
||||
var tan_DE = (point_E['y'] - point_D['y']) / (point_E['x'] - point_D['x']);
|
||||
// tan_DE的弧度值
|
||||
var radius_DE = Math.atan(tan_DE);
|
||||
// 地市DE的间距
|
||||
var dist_DE = Math.sqrt(Math.pow((point_E['x'] - point_D['x']), 2) + Math.pow((point_E['y'] - point_D['y']),
|
||||
2));
|
||||
// 此时DF的距离
|
||||
var dist_DF = (dist_AD / DIST_AB) * dist_DE;
|
||||
// 此时DF点的坐标
|
||||
var point_F = {};
|
||||
point_F['x'] = dist_DF * Math.cos(radius_DE) + point_D['x'];
|
||||
point_F['y'] = dist_DF * Math.sin(radius_DE) + point_D['y'];
|
||||
bezier_points.push(point_F);
|
||||
}
|
||||
return {
|
||||
'bezier_points': bezier_points
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -0,0 +1,338 @@
|
|||
<template>
|
||||
<view class="chat-message" >
|
||||
<block v-if="message.contentType == 'sendGood'"><ns-chat-goods :skuId="message.sku_id" :goodsDetail="message.goodsDetail" @sendMsg="sendGood"></ns-chat-goods></block>
|
||||
<block v-if="message.contentType == 'sendOrder'">
|
||||
<ns-chat-order :orderId="message.order_id" :orderdetails="message.orderDetail" @sendMsg="sendOrder"></ns-chat-order>
|
||||
</block>
|
||||
<block v-if="message.contentType == 'goodssku'"><ns-chat-receiveGoods :skuId="message.sku_id"></ns-chat-receiveGoods></block>
|
||||
<view class="message" v-if="message.contentType == 'string'">
|
||||
<view class="message-item " :class="message.isItMe ? 'right' : 'left'">
|
||||
<block v-if="message.isItMe">
|
||||
<view class="head_img">
|
||||
<image class="img" :src="myHeadImg" v-if="myHeadImg" @error="myHeadImgError" mode="aspectFit"></image>
|
||||
<image class="img" :src="defaultHead" mode="aspectFit" v-else></image>
|
||||
</view>
|
||||
</block>
|
||||
<block v-else>
|
||||
<view class="head_img">
|
||||
<image class="img" :src="avatar" mode="aspectFit" v-if="avatar"></image>
|
||||
<image class="img" :src="defaultHead" mode="aspectFit" v-else></image>
|
||||
</view>
|
||||
</block>
|
||||
<view class="chat_text">
|
||||
<text class="iconfont icon-warn margin-right color-base-text" v-if="message.isItMe && !message.sendStatus"></text>
|
||||
<view class="content"><rich-text :nodes="stringToEmjoy(message.content)"></rich-text></view>
|
||||
<!-- <text class="iconfont icon-warn margin-left" v-if="!message.isItMe && !message.sendStatus"></text> -->
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="message" v-if="message.contentType == 'image'">
|
||||
<view class="message-item " :class="message.isItMe ? 'right' : 'left'">
|
||||
<block v-if="message.isItMe">
|
||||
<view class="head_img">
|
||||
<image class="img" :src="myHeadImg" v-if="myHeadImg" mode="aspectFit"></image>
|
||||
<image class="img" :src="defaultHead" mode="aspectFit" v-else></image>
|
||||
</view>
|
||||
</block>
|
||||
<block v-else>
|
||||
<view class="head_img">
|
||||
<image class="img" :src="avatar" mode="aspectFit" v-if="avatar"></image>
|
||||
<image class="img" :src="defaultHead" mode="aspectFit" v-else></image>
|
||||
</view>
|
||||
</block>
|
||||
<view class="chat_img">
|
||||
<text class="iconfont icon-warn margin-right color-base-text" v-if="message.isItMe && !message.sendStatus"></text>
|
||||
<view class="content_img" @click="previewMedia($util.img(message.image))" :style="{ backgroundImage: 'url(' + $util.img(message.image) + ')' }">
|
||||
<!-- <image class="img_img" :src="$util.img(message.image)" mode="aspectFit"></image> -->
|
||||
</view>
|
||||
<!-- <text class="iconfont icon-warn margin-left" v-if="!message.isItMe && !message.sendStatus"></text> -->
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-else-if="message.contentType == 'goods'"><ns-chat-goods :isCanSend="false" :skuId="message.sku_id"></ns-chat-goods></view>
|
||||
<view v-else-if="message.contentType == 'order'"><ns-chat-order :isCanSend="false" :orderId="message.order_id"></ns-chat-order></view>
|
||||
|
||||
<view class="no-connect-box" v-if="message.contentType == 'noline'"><view class="no-connect">客服不在线</view></view>
|
||||
<view class="no-connect-box" v-if="message.contentType == 'online'"><view class="no-connect">客服在线</view></view>
|
||||
<uni-popup ref="imgPopup" type="center">
|
||||
<view class="imagePop"><image :src="$util.img(currImg)" mode="aspectFit"></image></view>
|
||||
</uni-popup>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import nsChatGoods from '@/components/ns-chat/ns-chat-goods.vue';
|
||||
import nsChatOrder from '@/components/ns-chat/ns-chat-order.vue';
|
||||
import nsChatReceiveGoods from '@/components/ns-chat/ns-chat-receiveGoods.vue';
|
||||
import htmlParser from '@/common/js/html-parser';
|
||||
import uniPopup from '@/components/uni-popup/uni-popup.vue';
|
||||
import emjoy from '@/common/js/emjoy.js';
|
||||
|
||||
export default {
|
||||
name: 'chat-message',
|
||||
props: {
|
||||
message: {
|
||||
type: Object
|
||||
},
|
||||
shopInfo: {
|
||||
type: Object
|
||||
},
|
||||
userInfo: {
|
||||
type: Object
|
||||
},
|
||||
send: {
|
||||
type: Boolean
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
avatar: '', //店铺头像
|
||||
defaultAvatar: this.$util.getDefaultImage().store,
|
||||
myHeadImg: '', //我的头像
|
||||
defaultHead: this.$util.getDefaultImage().head,
|
||||
emjoyList: emjoy.emjoyList,
|
||||
currImg: ''
|
||||
};
|
||||
},
|
||||
components: {
|
||||
nsChatGoods,
|
||||
nsChatOrder,
|
||||
uniPopup,
|
||||
nsChatReceiveGoods
|
||||
},
|
||||
mounted() {
|
||||
this.avatar = this.$util.img(this.shopInfo.logo_square);
|
||||
this.myHeadImg = this.$util.img(this.userInfo.headimg);
|
||||
},
|
||||
methods: {
|
||||
// 预览图片
|
||||
previewMedia(img_url) {
|
||||
var paths = [img_url];
|
||||
uni.previewImage({
|
||||
current: 0,
|
||||
urls: paths
|
||||
});
|
||||
},
|
||||
sendGood() {
|
||||
this.$emit('sendGood', 'goods');
|
||||
},
|
||||
sendOrder() {
|
||||
this.$emit('sendOrder', 'order');
|
||||
},
|
||||
// 处理图片错误
|
||||
myHeadImgError() {
|
||||
this.myHeadImg = this.defaultHead;
|
||||
},
|
||||
stringToEmjoy(value) {
|
||||
if (!value) return;
|
||||
// 兼容旧版本图片
|
||||
var reg = RegExp(/\[/);
|
||||
if (reg.test(value)) {
|
||||
let string = value; // 需要把和匹配出来
|
||||
let reg = new RegExp('\\[emjoy_(.+?)\\]', 'g');
|
||||
let emjoyString = string.replace(reg, v => {
|
||||
let emjoy = '';
|
||||
for (let index in this.emjoyList) {
|
||||
if (v == index) {
|
||||
let _url = this.$util.img(this.emjoyList[index]);
|
||||
emjoy = "<img class='message-img' src='" + _url + "'/>";
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (emjoy) {
|
||||
return emjoy;
|
||||
} else {
|
||||
return v;
|
||||
}
|
||||
});
|
||||
let content = htmlParser(emjoyString);
|
||||
content.forEach(v => {
|
||||
if (v.name == 'img') {
|
||||
v.attrs.style = 'display: inline-block;width: 32rpx !important;height: 32rpx !important;padding:0 2rpx;';
|
||||
}
|
||||
});
|
||||
return content;
|
||||
} else {
|
||||
let content = value;
|
||||
return content;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
/deep/.uni-popup__wrapper.uni-custom .uni-popup__wrapper-box {
|
||||
background-color: #000;
|
||||
}
|
||||
|
||||
/deep/.uni-popup__wrapper.uni-custom.center .uni-popup__wrapper-box {
|
||||
max-width: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.imagePop {
|
||||
height: 50vh;
|
||||
width: 100vw;
|
||||
text-align: center;
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.chat-message {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
.message {
|
||||
padding: 13rpx 20rpx;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.left .content {
|
||||
padding: 20rpx;
|
||||
max-width: 450rpx;
|
||||
border-radius: 10rpx;
|
||||
font-size: 30rpx;
|
||||
}
|
||||
|
||||
.right .content {
|
||||
padding: 20rpx;
|
||||
max-width: 450rpx;
|
||||
border-radius: 10rpx;
|
||||
font-size: 30rpx;
|
||||
}
|
||||
|
||||
.content_img {
|
||||
height: 200rpx;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
text-align: right;
|
||||
margin-left: 28rpx;
|
||||
background-position: center right;
|
||||
background-repeat: no-repeat;
|
||||
background-size: contain;
|
||||
|
||||
image {
|
||||
min-height: 80rpx;
|
||||
min-width: 80rpx;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.right .content_img {
|
||||
margin-right: 28rpx;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.message-item {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: flex-start;
|
||||
align-content: flex-start;
|
||||
flex-wrap: nowrap;
|
||||
flex-direction: row;
|
||||
|
||||
.head_img {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
|
||||
.img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
//图片
|
||||
.contentType3 {
|
||||
padding: 0;
|
||||
border-radius: 2rpx;
|
||||
background-color: transparent !important;
|
||||
|
||||
.img {
|
||||
width: 200rpx;
|
||||
height: auto;
|
||||
max-width: 300rpx;
|
||||
max-height: 400rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.contentType3::after {
|
||||
border: none !important;
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.content-type-right {
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
|
||||
&.right {
|
||||
flex-direction: row-reverse;
|
||||
|
||||
.content {
|
||||
background-color: #4cd964;
|
||||
margin-right: 28rpx;
|
||||
word-break: break-all;
|
||||
line-height: 36rpx;
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
|
||||
&.left {
|
||||
.content {
|
||||
background-color: #ffffff;
|
||||
margin-left: 28rpx;
|
||||
word-break: break-all;
|
||||
line-height: 36rpx;
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.next {
|
||||
width: 100%;
|
||||
height: 20rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.no-connect-box {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
margin: 20rpx 0 50rpx;
|
||||
|
||||
.no-connect {
|
||||
display: inline-block;
|
||||
padding: 0 20rpx;
|
||||
height: 40rpx;
|
||||
background: red;
|
||||
margin: 0 auto;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
border-radius: 9rpx;
|
||||
text-align: center;
|
||||
line-height: 40rpx;
|
||||
font-size: 22rpx;
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
|
||||
.chat_text,
|
||||
.chat_img {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.iconfont {
|
||||
font-size: 36rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.chat_img {
|
||||
width: 30%;
|
||||
height: 200rpx;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,742 @@
|
|||
<template>
|
||||
<view class="order-container" :class="{ 'safe-area': isIphoneX }">
|
||||
<!-- #ifdef MP -->
|
||||
<view
|
||||
class="payment-navbar"
|
||||
:style="{
|
||||
'padding-top': menuButtonBounding.top + 'px',
|
||||
height: menuButtonBounding.height + 'px'
|
||||
}"
|
||||
>
|
||||
<view class="navbar-title">确认订单</view>
|
||||
</view>
|
||||
<view class="payment-navbar-block" :style="{ height: menuButtonBounding.bottom + 'px' }"></view>
|
||||
<!-- #endif -->
|
||||
|
||||
<scroll-view scroll-y="true" class="order-scroll-container">
|
||||
<view class="payment-navbar-block"></view>
|
||||
<template v-if="paymentData">
|
||||
<template v-if="paymentData.is_virtual == 0">
|
||||
<!-- 配送方式 -->
|
||||
<view class="delivery-mode" v-if="goodsData.express_type.length > 1">
|
||||
<view class="action">
|
||||
<view
|
||||
:class="{ active: item.name == orderCreateData.delivery.delivery_type }"
|
||||
v-for="(item, index) in goodsData.express_type"
|
||||
:key="index"
|
||||
@click="selectDeliveryType(item)"
|
||||
>
|
||||
{{ item.title }}
|
||||
<!-- 外圆角 -->
|
||||
<view class="out-radio"></view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="address-box" :class="{ 'not-delivery-type': goodsData.express_type.length <= 1 }" v-if="orderCreateData.delivery.delivery_type == 'express'">
|
||||
<view class="info-wrap" v-if="memberAddress" @click="selectAddress">
|
||||
<view class="content">
|
||||
<text class="name">{{ memberAddress.name ? memberAddress.name : '' }}</text>
|
||||
<text class="mobile">{{ memberAddress.mobile ? memberAddress.mobile : '' }}</text>
|
||||
<view class="desc-wrap">
|
||||
{{ memberAddress.full_address ? memberAddress.full_address : '' }} {{ memberAddress.address ? memberAddress.address : '' }}
|
||||
</view>
|
||||
</view>
|
||||
<text class="cell-more iconfont icon-right"></text>
|
||||
</view>
|
||||
<view class="empty-wrap" v-else @click="selectAddress">
|
||||
<view class="info">请设置收货地址</view>
|
||||
<view class="cell-more"><view class="iconfont icon-right"></view></view>
|
||||
</view>
|
||||
<image class="address-line" :src="$util.img('public/uniapp/order/address-line.png')"></image>
|
||||
</view>
|
||||
|
||||
<view class="address-box" :class="{ 'not-delivery-type': goodsData.express_type.length <= 1 }" v-if="orderCreateData.delivery.delivery_type == 'local'">
|
||||
<view v-if="localMemberAddress">
|
||||
<block v-if="storeList && Object.keys(storeList).length > 1">
|
||||
<view class="local-delivery-store" v-if="storeInfo" @click="openPopup('deliveryPopup')">
|
||||
<view class="info">
|
||||
由
|
||||
<text class="store-name">{{ storeInfo.store_name }}</text>
|
||||
提供配送
|
||||
</view>
|
||||
<view class="cell-more">
|
||||
<text>点击切换</text>
|
||||
<text class="iconfont icon-right"></text>
|
||||
</view>
|
||||
</view>
|
||||
<view v-else class="local-delivery-store">
|
||||
<view class="info"><text class="store-name">您的附近没有可配送的门店,请选择其他配送方式</text></view>
|
||||
</view>
|
||||
</block>
|
||||
<view class="info-wrap local" @click="selectAddress">
|
||||
<view class="content">
|
||||
<text class="name">{{ localMemberAddress.name ? localMemberAddress.name : '' }}</text>
|
||||
<text class="mobile">{{ localMemberAddress.mobile ? localMemberAddress.mobile : '' }}</text>
|
||||
<view class="desc-wrap">
|
||||
{{ localMemberAddress.full_address ? localMemberAddress.full_address : '' }}
|
||||
{{ localMemberAddress.address ? localMemberAddress.address : '' }}
|
||||
</view>
|
||||
</view>
|
||||
<text class="cell-more iconfont icon-right"></text>
|
||||
</view>
|
||||
<view class="local-box" v-if="calculateGoodsData.local_config && calculateGoodsData.local_config.info.time_is_open == 1">
|
||||
<view class="pick-block" @click="localtime('')">
|
||||
<view class="title font-size-base">送达时间</view>
|
||||
<view class="time-picker">
|
||||
<text :class="{ 'color-tip': !deliveryTime }">{{ deliveryTime ? deliveryTime : '请选择送达时间' }}</text>
|
||||
<text class="iconfont icon-right cell-more"></text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="empty-wrap" v-else @click="selectAddress">
|
||||
<view class="info">请设置收货地址</view>
|
||||
<view class="cell-more"><view class="iconfont icon-right"></view></view>
|
||||
</view>
|
||||
|
||||
<image class="address-line" :src="$util.img('public/uniapp/order/address-line.png')"></image>
|
||||
</view>
|
||||
|
||||
<!-- 门店信息 -->
|
||||
<view class="store-box" :class="{ 'not-delivery-type': goodsData.express_type.length <= 1 }" v-if="orderCreateData.delivery.delivery_type == 'store'">
|
||||
<block v-if="storeInfo">
|
||||
<view @click="openPopup('deliveryPopup')" class="store-info">
|
||||
<view class="store-address-info">
|
||||
<view class="info-wrap">
|
||||
<view class="title">
|
||||
<text>{{ storeInfo.store_name }}</text>
|
||||
</view>
|
||||
<view class="store-detail">
|
||||
<view v-if="storeInfo.open_date">营业时间:{{ storeInfo.open_date }}</view>
|
||||
<view class="address">{{ storeInfo.full_address }} {{ storeInfo.address }}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="cell-more iconfont icon-right"></view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="mobile-wrap store-mobile">
|
||||
<view class="form-group">
|
||||
<text class="text">预留手机</text>
|
||||
<input
|
||||
type="number"
|
||||
maxlength="11"
|
||||
placeholder="请输入您的手机号码"
|
||||
placeholder-class="color-tip placeholder"
|
||||
class="input"
|
||||
v-model="orderCreateData.member_address.mobile"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
<view class="store-time" @click="storetime('')">
|
||||
<view class="left">提货时间</view>
|
||||
<view class="right">
|
||||
{{ deliveryTime }}
|
||||
<text class="iconfont icon-right"></text>
|
||||
</view>
|
||||
</view>
|
||||
</block>
|
||||
<view v-else class="empty">当前无自提门店,请选择其它配送方式</view>
|
||||
<image class="address-line" :src="$util.img('public/uniapp/order/address-line.png')"></image>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<!-- 店铺 -->
|
||||
<view class="site-wrap order-goods">
|
||||
<view class="site-body">
|
||||
<!-- 商品 -->
|
||||
<view class="goods-item" v-for="(goodsItem, goodsIndex) in goodsData.goods_list" :key="goodsIndex">
|
||||
<view class="goods-wrap">
|
||||
<view class="goods-img" @click="$util.redirectTo('/pages/goods/detail', { goods_id: goodsItem.goods_id })">
|
||||
<image :src="$util.img(goodsItem.sku_image, { size: 'mid' })" @error="imageError(goodsIndex)" mode="aspectFill"></image>
|
||||
</view>
|
||||
<view class="goods-info">
|
||||
<view class="top-wrap">
|
||||
<view @click="$util.redirectTo('/pages/goods/detail', { goods_id: goodsItem.goods_id })" class="goods-name">{{ goodsItem.sku_name }}</view>
|
||||
<view class="sku" v-if="goodsItem.sku_spec_format">
|
||||
<view class="goods-spec">
|
||||
<block v-for="(x, i) in goodsItem.sku_spec_format" :key="i">
|
||||
<view>{{ x.spec_value_name }}</view>
|
||||
</block>
|
||||
</view>
|
||||
</view>
|
||||
<block v-if="goodsItem.is_virtual == 0">
|
||||
<view
|
||||
class="error-tips"
|
||||
v-if="
|
||||
orderCreateData.delivery &&
|
||||
goodsItem.support_trade_type &&
|
||||
goodsItem.support_trade_type.indexOf(orderCreateData.delivery.delivery_type) == -1
|
||||
"
|
||||
>
|
||||
<text class="iconfont icon-gantanhao"></text>
|
||||
<text>该商品不支持{{ orderCreateData.delivery.delivery_type_name }}</text>
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
<view class="goods-sub-section">
|
||||
<view class="color-base-text">
|
||||
<text class="unit price-style small">{{ $lang('common.currencySymbol') }}</text>
|
||||
|
||||
<text class="goods-price price-style large">
|
||||
{{
|
||||
parseFloat(goodsItem.price)
|
||||
.toFixed(2)
|
||||
.split('.')[0]
|
||||
}}
|
||||
</text>
|
||||
<text class="unit price-style small">
|
||||
.{{
|
||||
parseFloat(goodsItem.price)
|
||||
.toFixed(2)
|
||||
.split('.')[1]
|
||||
}}
|
||||
</text>
|
||||
</view>
|
||||
<view>
|
||||
<text class="font-size-tag">x</text>
|
||||
<text class="font-size-base">{{ goodsItem.num }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view
|
||||
class="member-goods-card order-cell"
|
||||
v-if="calculateGoodsData && calculateGoodsData.goods_list[goodsIndex].member_card_list"
|
||||
@click="selectMemberGoodsCard(goodsIndex)"
|
||||
>
|
||||
<text class="tit">次卡抵扣</text>
|
||||
<view class="box text-overflow">
|
||||
<block v-if="calculateGoodsData.goods_list[goodsIndex].card_promotion_money">
|
||||
<text class="text">
|
||||
次卡抵扣{{ calculateGoodsData.goods_list[goodsIndex].card_use_num }}张/{{ calculateGoodsData.goods_list[goodsIndex].card_use_num }}次
|
||||
</text>
|
||||
<text class="price-font">-¥{{ calculateGoodsData.goods_list[goodsIndex].card_promotion_money | moneyFormat }}</text>
|
||||
</block>
|
||||
<text class="color-tip" v-else>请选择次卡</text>
|
||||
</view>
|
||||
<text class="iconfont icon-right"></text>
|
||||
</view>
|
||||
<view class="goods-form" v-if="goodsItem.goods_form" @click="editForm(goodsIndex)">
|
||||
<ns-form
|
||||
:data="goodsItem.goods_form.json_data"
|
||||
ref="goodsForm"
|
||||
:custom-attr="{ sku_id: goodsItem.sku_id, form_id: goodsItem.goods_form.id }"
|
||||
></ns-form>
|
||||
<text class="cell-more iconfont icon-right"></text>
|
||||
<view class="shade"></view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="site-wrap buyer-message">
|
||||
<view class="order-cell">
|
||||
<text class="tit">买家留言</text>
|
||||
<view class="box text-overflow " @click="openPopup('buyerMessagePopup')">
|
||||
<text v-if="orderCreateData.buyer_message">{{ orderCreateData.buyer_message }}</text>
|
||||
<text class="color-sub" v-else>无留言</text>
|
||||
</view>
|
||||
<text class="iconfont icon-right"></text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-if="paymentData.system_form" class="system-form-wrap">
|
||||
<view class="order-cell">
|
||||
<text class="tit">{{ paymentData.system_form.form_name }}</text>
|
||||
</view>
|
||||
<ns-form :data="paymentData.system_form.json_data" ref="form"></ns-form>
|
||||
</view>
|
||||
|
||||
<view
|
||||
class="site-wrap"
|
||||
v-if="
|
||||
(calculateGoodsData && calculateGoodsData.coupon_list && calculateGoodsData.coupon_list.length) ||
|
||||
promotionInfo ||
|
||||
(calculateGoodsData && calculateGoodsData.max_usable_point > 0) ||
|
||||
goodsData.invoice
|
||||
"
|
||||
>
|
||||
<view class="site-footer">
|
||||
<view class="order-cell coupon" v-if="calculateGoodsData && calculateGoodsData.coupon_list && calculateGoodsData.coupon_list.length">
|
||||
<text class="tit">优惠券</text>
|
||||
<view class="box text-overflow" @click="openPopup('couponPopup')">
|
||||
<template v-if="orderCreateData.coupon && orderCreateData.coupon.coupon_id">
|
||||
<text>已使用优惠券,优惠</text>
|
||||
<text class="unit price-font">{{ $lang('common.currencySymbol') }}</text>
|
||||
<text class="money price-font">{{ (calculateData && calculateData.coupon_money ? calculateData.coupon_money : 0) | moneyFormat }}</text>
|
||||
</template>
|
||||
<text v-else>不使用优惠券</text>
|
||||
</view>
|
||||
<text class="iconfont icon-right"></text>
|
||||
</view>
|
||||
<view class="order-cell" v-if="promotionInfo">
|
||||
<text class="tit">活动优惠</text>
|
||||
<view class="box text-overflow" @click="openPopup('promotionPopup')">
|
||||
<text>{{ promotionInfo.title }}</text>
|
||||
</view>
|
||||
<text class="iconfont icon-right"></text>
|
||||
</view>
|
||||
<view class="order-cell point" v-if="calculateGoodsData && calculateGoodsData.max_usable_point > 0">
|
||||
<text class="tit">
|
||||
<text>使用{{ parseInt(calculateGoodsData.max_usable_point) }}积分可抵扣</text>
|
||||
<text class="unit price-font">{{ $lang('common.currencySymbol') }}</text>
|
||||
<text class="money price-font">{{ calculateData.point_money | moneyFormat }}</text>
|
||||
</text>
|
||||
<view class="box"></view>
|
||||
<ns-switch class="balance-switch" @change="usePoint" :checked="orderCreateData.is_point == 1"></ns-switch>
|
||||
</view>
|
||||
<view class="order-cell order-invoice-cell" v-if="goodsData.invoice">
|
||||
<text class="tit">发票</text>
|
||||
<view class="box text-overflow" @click="openPopup('invoicePopup')">
|
||||
<text v-if="orderCreateData.is_invoice == 1">
|
||||
{{ orderCreateData.invoice_type == 1 ? '纸质' : '电子' }}发票({{ orderCreateData.invoice_content }})
|
||||
</text>
|
||||
<text v-else>无需发票</text>
|
||||
</view>
|
||||
<text class="iconfont icon-right"></text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="site-wrap box member-card-wrap" v-if="paymentData.recommend_member_card">
|
||||
<view class="head" @click="selectMemberCard">
|
||||
<text class="iconfont icon-huiyuan"></text>
|
||||
<view class="info">
|
||||
开通{{ paymentData.recommend_member_card.level_name }}
|
||||
<text>本单预计可省</text>
|
||||
<text class="price-color">{{ paymentData.recommend_member_card.discount_money | moneyFormat }}</text>
|
||||
<text>元</text>
|
||||
</view>
|
||||
<text class="iconfont" :class="orderCreateData.is_open_card == 1 ? 'icon-yuan_checked color-base-text' : 'icon-yuan_checkbox'"></text>
|
||||
</view>
|
||||
<view class="body" v-if="orderCreateData.is_open_card">
|
||||
<view
|
||||
class="item"
|
||||
:class="{ 'active color-base-border': item.key == orderCreateData.member_card_unit }"
|
||||
v-for="(item, index) in cardChargeType"
|
||||
:key="index"
|
||||
@click="selectMembercardUnit(item.key)"
|
||||
>
|
||||
<view class="title">{{ item.title }}</view>
|
||||
<view class="price price-font">{{ $lang('common.currencySymbol') }}{{ parseFloat(item.value) }}/{{ item.unit }}</view>
|
||||
<text class="iconfont icon-icon color-base-text price-font identify" v-if="item.key == orderCreateData.member_card_unit"></text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 订单金额 -->
|
||||
<template v-if="calculateData">
|
||||
<view class="order-money">
|
||||
<view class="order-cell">
|
||||
<text class="tit">商品金额</text>
|
||||
<view class="box">
|
||||
<text class="unit color-title price-font">{{ $lang('common.currencySymbol') }}</text>
|
||||
<text class="money color-title price-font">{{ calculateData.goods_money | moneyFormat }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="order-cell" v-if="calculateData.is_virtual == 0 && calculateData.delivery_money > 0">
|
||||
<text class="tit">运费</text>
|
||||
<view class="box color-base-text">
|
||||
<text class="operator">+</text>
|
||||
<text class="unit price-font">{{ $lang('common.currencySymbol') }}</text>
|
||||
<text class="money price-font">{{ calculateData.delivery_money | moneyFormat }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="order-cell" v-if="orderCreateData.is_invoice && calculateData.invoice_money > 0">
|
||||
<text class="tit">
|
||||
<text>税费</text>
|
||||
<text class="color-base-text font-bold price-font">({{ goodsData.invoice.invoice_rate }}%)</text>
|
||||
</text>
|
||||
<view class="box color-base-text">
|
||||
<text class="operator">+</text>
|
||||
<text class="unit price-font">{{ $lang('common.currencySymbol') }}</text>
|
||||
<text class="money price-font">{{ calculateData.invoice_money | moneyFormat }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="order-cell" v-if="orderCreateData.is_invoice && calculateData.invoice_delivery_money > 0">
|
||||
<text class="tit">发票邮寄费</text>
|
||||
<view class="box color-base-text">
|
||||
<text class="operator">+</text>
|
||||
<text class="unit price-font">{{ $lang('common.currencySymbol') }}</text>
|
||||
<text class="money price-font">{{ calculateData.invoice_delivery_money | moneyFormat }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="order-cell" v-if="calculateData.promotion_money > 0">
|
||||
<text class="tit">优惠</text>
|
||||
<view class="box color-base-text">
|
||||
<text class="operator">-</text>
|
||||
<text class="unit price-font">{{ $lang('common.currencySymbol') }}</text>
|
||||
<text class="money price-font">{{ calculateData.promotion_money | moneyFormat }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="order-cell" v-if="calculateData.coupon_money">
|
||||
<text class="tit">优惠券</text>
|
||||
<view class="box color-base-text">
|
||||
<text class="operator">-</text>
|
||||
<text class="unit price-font">{{ $lang('common.currencySymbol') }}</text>
|
||||
<text class="money price-font">{{ calculateData.coupon_money | moneyFormat }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="order-cell" v-if="calculateData.point_money > 0">
|
||||
<text class="tit">积分抵扣</text>
|
||||
<view class="box color-base-text">
|
||||
<text class="operator">-</text>
|
||||
<text class="unit price-font">{{ $lang('common.currencySymbol') }}</text>
|
||||
<text class="money price-font">{{ calculateData.point_money | moneyFormat }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="order-cell" v-if="calculateData.member_card_money > 0">
|
||||
<text class="tit">会员卡</text>
|
||||
<view class="box color-base-text">
|
||||
<text class="operator">+</text>
|
||||
<text class="unit price-font">{{ $lang('common.currencySymbol') }}</text>
|
||||
<text class="money price-font">{{ calculateData.member_card_money | moneyFormat }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-if="transactionAgreement.title && transactionAgreement.content" class="agreement">
|
||||
购买前请先阅读
|
||||
<text @click="$refs.agreementPopup.open()">《{{ transactionAgreement.title }}》</text>
|
||||
,下单即代表同意该协议
|
||||
</view>
|
||||
|
||||
<view class="order-submit bottom-safe-area">
|
||||
<view class="order-settlement-info">
|
||||
<text class="font-size-base color-tip margin-right">共{{ calculateData.goods_num }}件</text>
|
||||
<text class="font-size-base">合计:</text>
|
||||
<text class=" unit price-font">{{ $lang('common.currencySymbol') }}</text>
|
||||
<text class=" money price-font">
|
||||
{{
|
||||
parseFloat(calculateData.pay_money)
|
||||
.toFixed(2)
|
||||
.split('.')[0]
|
||||
}}
|
||||
</text>
|
||||
<text class=" unit price-font">
|
||||
.{{
|
||||
parseFloat(calculateData.pay_money)
|
||||
.toFixed(2)
|
||||
.split('.')[1]
|
||||
}}
|
||||
</text>
|
||||
</view>
|
||||
<view class="submit-btn">
|
||||
<button type="primary" size="mini" @click="create()" v-if="!surplusStartMoney()">提交订单</button>
|
||||
<button v-else class="no-submit" size="mini">差{{ surplusStartMoney() | moneyFormat }}起送</button>
|
||||
</view>
|
||||
</view>
|
||||
<view class="order-submit-block"></view>
|
||||
|
||||
<payment ref="choosePaymentPopup" @close="payClose" v-if="calculateData"></payment>
|
||||
</template>
|
||||
|
||||
<!-- 发票弹窗 -->
|
||||
<uni-popup ref="invoicePopup" type="bottom" :mask-click="false">
|
||||
<view :style="orderCreateData.is_invoice == 1 ? 'height: 83vh;' : 'height: 48vh;'" class="invoice-popup popup" @touchmove.prevent.stop>
|
||||
<view class="popup-header">
|
||||
<text class="tit">发票</text>
|
||||
<text class="iconfont icon-close" @click="closePopup('invoicePopup')"></text>
|
||||
</view>
|
||||
<scroll-view scroll-y="true" class="popup-body" :class="{ 'safe-area': isIphoneX }">
|
||||
<view>
|
||||
<view class="invoice-cell" v-if="goodsData.invoice">
|
||||
<text class="tit">需要发票</text>
|
||||
<view class="option-grpup">
|
||||
<view class="option-item" :class="{ 'color-base-bg active': orderCreateData.is_invoice == 0 }" @click="changeIsInvoice">不需要</view>
|
||||
<view class="option-item" :class="{ 'color-base-bg active': orderCreateData.is_invoice == 1 }" @click="changeIsInvoice">需要</view>
|
||||
</view>
|
||||
</view>
|
||||
<block v-if="orderCreateData.is_invoice == 1">
|
||||
<view class="invoice-cell">
|
||||
<text class="tit">发票类型</text>
|
||||
<view class="option-grpup">
|
||||
<view
|
||||
class="option-item"
|
||||
:class="{ 'color-base-bg active': orderCreateData.invoice_type == item }"
|
||||
@click="changeInvoiceType(item)"
|
||||
v-for="(item, index) in goodsData.invoice.invoice_type.split(',')"
|
||||
:key="index"
|
||||
>
|
||||
{{ item == 1 ? '纸质' : '电子' }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="invoice-cell">
|
||||
<text class="tit">抬头类型</text>
|
||||
<view class="option-grpup">
|
||||
<view
|
||||
class="option-item"
|
||||
:class="{ 'color-base-bg active': orderCreateData.invoice_title_type == 1 }"
|
||||
@click="changeInvoiceTitleType(1)"
|
||||
>
|
||||
个人
|
||||
</view>
|
||||
<view
|
||||
class="option-item"
|
||||
:class="{ 'color-base-bg active': orderCreateData.invoice_title_type == 2 }"
|
||||
@click="changeInvoiceTitleType(2)"
|
||||
>
|
||||
企业
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="invoice-cell">
|
||||
<text class="tit">发票信息</text>
|
||||
<view class="invoice-form-group">
|
||||
<input type="text" placeholder="请填写抬头名称" v-model.trim="orderCreateData.invoice_title" />
|
||||
<input
|
||||
v-if="orderCreateData.invoice_title_type == 2"
|
||||
type="text"
|
||||
placeholder="请填写纳税人识别号"
|
||||
v-model.trim="orderCreateData.taxpayer_number"
|
||||
/>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="请填写邮寄地址"
|
||||
v-model.trim="orderCreateData.invoice_full_address"
|
||||
v-if="orderCreateData.invoice_type == 1"
|
||||
/>
|
||||
<input type="text" placeholder="请填写邮箱" v-model.trim="orderCreateData.invoice_email" v-if="orderCreateData.invoice_type == 2" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="invoice-cell">
|
||||
<text class="tit">发票内容</text>
|
||||
<view class="option-grpup">
|
||||
<view
|
||||
:key="index"
|
||||
v-for="(item, index) in goodsData.invoice.invoice_content_array"
|
||||
:class="{ 'color-base-bg active': item == orderCreateData.invoice_content }"
|
||||
@click="changeInvoiceContent(item)"
|
||||
class="option-item content"
|
||||
>
|
||||
{{ item }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</block>
|
||||
<view class="invoice-tops">发票内容将以根据税法调整,具体请以展示为准,发票内容显示详细商品名 称及价格信息</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="popup-footer" @click="saveInvoice" :class="{ 'bottom-safe-area': isIphoneX }"><view class="confirm-btn color-base-bg">确定</view></view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
|
||||
<!-- 活动优惠弹窗 -->
|
||||
<uni-popup ref="promotionPopup" type="bottom" v-if="promotionInfo">
|
||||
<view class="promotion-popup popup">
|
||||
<view class="popup-header">
|
||||
<text class="tit">活动优惠</text>
|
||||
<text class="iconfont icon-close" @click="closePopup('promotionPopup')"></text>
|
||||
</view>
|
||||
<scroll-view scroll-y="true" class="popup-body" :class="{ 'safe-area': isIphoneX }">
|
||||
<view class="order-cell" style="align-items: baseline;">
|
||||
<view class="tit">
|
||||
<text class="promotion-mark ns-gradient-promotionpages-payment">{{ promotionInfo.title }}</text>
|
||||
</view>
|
||||
<view class="promotion-content"><view class="tit tit-content" style="white-space: pre-line;" v-html="promotionInfo.content"></view></view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="popup-footer" :class="{ 'bottom-safe-area': isIphoneX }">
|
||||
<view class="confirm-btn color-base-bg" @click="closePopup('promotionPopup')">确定</view>
|
||||
</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
|
||||
<!-- 门店列表弹窗 -->
|
||||
<uni-popup ref="deliveryPopup" type="bottom">
|
||||
<view class="delivery-popup popup">
|
||||
<view class="popup-header">
|
||||
<text class="tit">已为您甄选出附近所有相关门店</text>
|
||||
<text class="iconfont icon-close" @click="closePopup('deliveryPopup')"></text>
|
||||
</view>
|
||||
<view class="popup-body store-popup" :class="{ 'safe-area': isIphoneX }">
|
||||
<view class="delivery-content">
|
||||
<block v-if="storeList">
|
||||
<view class="item-wrap" v-for="(item, index) in storeList" :key="index" @click="selectPickupPoint(item)">
|
||||
<view class="detail">
|
||||
<view class="name" :class="item.store_id == orderCreateData.delivery.store_id ? 'color-base-text' : ''">
|
||||
<text>{{ item.store_name }}</text>
|
||||
<text v-if="item.distance">({{ item.distance }}km)</text>
|
||||
</view>
|
||||
<view class="info">
|
||||
<view :class="item.store_id == orderCreateData.delivery.store_id ? 'color-base-text' : ''" class="font-size-goods-tag">
|
||||
营业时间:{{ item.open_date }}
|
||||
</view>
|
||||
<view :class="item.store_id == orderCreateData.delivery.store_id ? 'color-base-text' : ''" class="font-size-goods-tag">
|
||||
地址:{{ item.full_address }}{{ item.address }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="icon" v-if="item.store_id == orderCreateData.delivery.store_id">
|
||||
<text class="iconfont icon-yuan_checked color-base-text"></text>
|
||||
</view>
|
||||
</view>
|
||||
</block>
|
||||
<view v-if="!storeList" class="empty">所选择收货地址附近没有可以自提的门店</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
|
||||
<!-- 留言弹窗 -->
|
||||
<uni-popup ref="buyerMessagePopup" type="bottom">
|
||||
<view style="height: auto;" class="buyermessag-popup popup" @touchmove.prevent.stop>
|
||||
<view class="popup-header">
|
||||
<text class="tit">买家留言</text>
|
||||
<text class="iconfont icon-close" @click="closePopup('buyerMessagePopup')"></text>
|
||||
</view>
|
||||
<scroll-view scroll-y="true" class="popup-body" :class="{ 'safe-area': isIphoneX }">
|
||||
<view>
|
||||
<view class="buyermessag-cell">
|
||||
<view class="buyermessag-form-group">
|
||||
<textarea
|
||||
type="text"
|
||||
maxlength="100"
|
||||
placeholder="留言前建议先与商家协调一致"
|
||||
placeholder-class="color-tip"
|
||||
v-model="orderCreateData.buyer_message"
|
||||
></textarea>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="popup-footer" @click="saveBuyerMessage" :class="{ 'bottom-safe-area': isIphoneX }"><view class="confirm-btn color-base-bg">确定</view></view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
|
||||
<!-- 优惠券弹窗 -->
|
||||
<uni-popup ref="couponPopup" type="bottom" v-if="calculateGoodsData && calculateGoodsData.coupon_list && calculateGoodsData.coupon_list.length" :mask-click="false">
|
||||
<view class="coupon-popup popup" @touchmove.prevent.stop>
|
||||
<view class="popup-header">
|
||||
<text class="tit">优惠券</text>
|
||||
<text class="iconfont icon-close" @click="closePopup('couponPopup')"></text>
|
||||
</view>
|
||||
<scroll-view scroll-y="true" class="popup-body" :class="{ 'safe-area': isIphoneX }">
|
||||
<view class="coupon-item" v-for="(couponItem, couponIndex) in calculateGoodsData.coupon_list" :key="couponIndex" @click="selectCoupon(couponItem)">
|
||||
<view class="coupon-info" :style="{ backgroundColor: 'var(--main-color-shallow)' }">
|
||||
<view class="info-wrap">
|
||||
<image class="coupon-line" mode="heightFix" :src="$util.img('public/uniapp/coupon/coupon_line.png')"></image>
|
||||
<view class="coupon-money">
|
||||
<template v-if="couponItem.type == 'divideticket'">
|
||||
<text class="unit">{{ $lang('common.currencySymbol') }}</text>
|
||||
<text class="money">{{ parseFloat(couponItem.money) }}</text>
|
||||
</template>
|
||||
<template v-else-if="couponItem.type == 'reward'">
|
||||
<text class="unit">{{ $lang('common.currencySymbol') }}</text>
|
||||
<text class="money">{{ parseFloat(couponItem.money) }}</text>
|
||||
</template>
|
||||
<template v-else-if="couponItem.type == 'discount'">
|
||||
<text class="money">{{ parseFloat(couponItem.discount) }}</text>
|
||||
<text class="unit">折</text>
|
||||
</template>
|
||||
<view class="at-least">
|
||||
<template v-if="couponItem.at_least > 0">
|
||||
满{{ couponItem.at_least }}可用
|
||||
</template>
|
||||
<template v-else>
|
||||
无门槛
|
||||
</template>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="desc-wrap">
|
||||
<view class="coupon-name">{{ couponItem.coupon_name }}</view>
|
||||
<view v-if="couponItem.type == 'discount' && couponItem.discount_limit > 0" class="limit">最多可抵¥{{ couponItem.discount_limit }}</view>
|
||||
<view class="time font-size-goods-tag">有效期:{{ couponItem.end_time ? $util.timeStampTurnTime(couponItem.end_time) : '长期有效' }}</view>
|
||||
</view>
|
||||
<view
|
||||
class="iconfont"
|
||||
:class="orderCreateData.coupon.coupon_id == couponItem.coupon_id ? 'icon-yuan_checked color-base-text' : 'icon-yuan_checkbox'"
|
||||
></view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="popup-footer" :class="{ 'bottom-safe-area': isIphoneX }"><view class="confirm-btn color-base-bg" @click="useCpopon">确定</view></view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
|
||||
<!-- 交易协议 -->
|
||||
<view @touchmove.prevent>
|
||||
<uni-popup ref="agreementPopup" type="center" :maskClick="false">
|
||||
<view class="agreement-conten-box">
|
||||
<view class="close"><text class="iconfont icon-close" @click="$refs.agreementPopup.close()"></text></view>
|
||||
<view class="title">{{ transactionAgreement.title }}</view>
|
||||
<view class="con">
|
||||
<scroll-view scroll-y="true" class="con"><rich-text :nodes="transactionAgreement.content"></rich-text></scroll-view>
|
||||
</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
</view>
|
||||
|
||||
<!-- 表单修改弹窗 -->
|
||||
<uni-popup ref="editFormPopup" type="bottom">
|
||||
<view style="height: auto;" class="form-popup popup" @touchmove.prevent.stop>
|
||||
<view class="popup-header">
|
||||
<text class="tit">买家信息</text>
|
||||
<text class="iconfont icon-close" @click="$refs.editFormPopup.close()"></text>
|
||||
</view>
|
||||
<scroll-view scroll-y="true" class="popup-body" :class="{ 'safe-area': isIphoneX }">
|
||||
<ns-form v-if="tempFormData" :data="tempFormData.json_data" ref="tempForm"></ns-form>
|
||||
</scroll-view>
|
||||
<view class="popup-footer" @click="saveForm" :class="{ 'bottom-safe-area': isIphoneX }"><view class="confirm-btn color-base-bg">确定</view></view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
|
||||
<uni-popup ref="memberGoodsCardPopup" type="bottom">
|
||||
<view class="popup" @touchmove.prevent.stop>
|
||||
<view class="popup-header">
|
||||
<text class="tit">选择次卡</text>
|
||||
<text class="iconfont icon-close" @click="$refs.memberGoodsCardPopup.close()"></text>
|
||||
</view>
|
||||
<scroll-view scroll-y="true" class="goods-card-popup popup-body" :class="{ 'safe-area': isIphoneX }">
|
||||
<view v-for="(item, index) in selectGoodsCard.cardList" class="card-item" @click="selectGoodsCard.click(item.item_id)">
|
||||
<view class="content">
|
||||
<view class="title">{{ item.goods_name }}</view>
|
||||
<view class="info">
|
||||
<text v-if="item.card_type == 'timecard'">不限次数</text>
|
||||
<text v-if="item.card_type == 'oncecard'">剩余{{ item.num - item.use_num }}次</text>
|
||||
<text v-if="item.card_type == 'commoncard'">剩余{{ item.total_num - item.total_use_num }}次</text>
|
||||
<text>|</text>
|
||||
<text>{{ item.end_time ? $util.timeStampTurnTime(item.end_time) : '长期有效' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="iconfont" :class="selectGoodsCard.itemId == item.item_id ? 'icon-yuan_checked color-base-text' : 'icon-yuan_checkbox'"></view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="popup-footer" @click="saveMemberGoodsCard" :class="{ 'bottom-safe-area': isIphoneX }">
|
||||
<view class="confirm-btn color-base-bg">确定</view>
|
||||
</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
|
||||
<!-- 门店自提时间 -->
|
||||
<ns-select-time @selectTime="selectPickupTime" ref="timePopup"></ns-select-time>
|
||||
</template>
|
||||
</scroll-view>
|
||||
|
||||
<ns-login ref="login"></ns-login>
|
||||
<loading-cover ref="loadingCover"></loading-cover>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import payment from './payment.js';
|
||||
|
||||
export default {
|
||||
name: 'common-payment',
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
props: {
|
||||
api: Object,
|
||||
createDataKey: String
|
||||
},
|
||||
mixins: [payment]
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import '@/common/css/order_parment.scss';
|
||||
</style>
|
||||
|
|
@ -0,0 +1,836 @@
|
|||
export default {
|
||||
options: { styleIsolation: 'shared' },
|
||||
data() {
|
||||
return {
|
||||
outTradeNo: '',
|
||||
isIphoneX: false,
|
||||
orderCreateData: {
|
||||
is_balance: 0,
|
||||
is_point: 1,
|
||||
is_invoice: 0, // 是否需要发票 0 无发票 1 有发票
|
||||
invoice_type: 0, // 发票类型 1 纸质 2 电子
|
||||
invoice_title_type: 1, // 抬头类型 1 个人 2 企业
|
||||
is_tax_invoice: 0, // 是否需要增值税专用发票 0 不需要 1 需要
|
||||
coupon: {
|
||||
coupon_id: 0
|
||||
},
|
||||
delivery: {},
|
||||
member_goods_card: {} // 会员次卡
|
||||
},
|
||||
paymentData: null,
|
||||
calculateData: null,
|
||||
tempData: null,
|
||||
storeId: 0,
|
||||
deliveryTime: '', // 提货时间
|
||||
memberAddress: null, // 会员收货地址
|
||||
localMemberAddress: null, // 会员本地配送收货地址
|
||||
isRepeat: false,
|
||||
promotionInfo: null,
|
||||
transactionAgreement: {}, // 购买须知
|
||||
tempFormData: null,
|
||||
menuButtonBounding: {} ,// 小程序胶囊属性
|
||||
storeConfig: null,
|
||||
localConfig: null,
|
||||
selectGoodsCard: {
|
||||
skuId: 0,
|
||||
itemId: 0,
|
||||
cardList: {}
|
||||
} // 当前选择的次卡
|
||||
}
|
||||
},
|
||||
inject: ['promotion'],
|
||||
created(){
|
||||
// #ifdef MP
|
||||
this.menuButtonBounding = uni.getMenuButtonBoundingClientRect();
|
||||
// #endif
|
||||
this.isIphoneX = this.$util.uniappIsIPhoneX()
|
||||
if (uni.getStorageSync('token')) {
|
||||
Object.assign(this.orderCreateData, uni.getStorageSync(this.createDataKey))
|
||||
if (this.location) {
|
||||
this.orderCreateData.latitude = this.location.latitude;
|
||||
this.orderCreateData.longitude = this.location.longitude;
|
||||
}
|
||||
this.payment();
|
||||
} else {
|
||||
setTimeout(() => {
|
||||
this.$refs.loadingCover.hide();
|
||||
this.$refs.login.open(this.$util.getCurrentRoute().path)
|
||||
})
|
||||
}
|
||||
this.getTransactionAgreement();
|
||||
},
|
||||
computed: {
|
||||
storeToken() {
|
||||
return this.$store.state.token;
|
||||
},
|
||||
goodsData(){
|
||||
if (this.paymentData) {
|
||||
this.paymentData.shop_goods_list.goods_list.forEach(item => {
|
||||
if (item.sku_spec_format) item.sku_spec_format = JSON.parse(item.sku_spec_format);
|
||||
})
|
||||
return this.paymentData.shop_goods_list;
|
||||
}
|
||||
},
|
||||
calculateGoodsData(){
|
||||
if (this.calculateData) return this.calculateData.shop_goods_list;
|
||||
},
|
||||
// 余额可抵扣金额
|
||||
balanceDeduct() {
|
||||
if (this.calculateData) {
|
||||
if (this.calculateData.member_account.balance_total <= parseFloat(this.calculateData.order_money).toFixed(2)) {
|
||||
return parseFloat(this.calculateData.member_account.balance_total).toFixed(2);
|
||||
} else {
|
||||
return parseFloat(this.calculateData.order_money).toFixed(2);
|
||||
}
|
||||
}
|
||||
},
|
||||
// 门店列表
|
||||
storeList(){
|
||||
let storeList = null;
|
||||
if (this.orderCreateData.delivery) {
|
||||
if (this.orderCreateData.delivery.delivery_type == 'local' && this.localConfig) {
|
||||
storeList = this.localConfig.store_list;
|
||||
storeList = storeList.reduce((res, item) => {
|
||||
return {...res, [item.store_id]: item}
|
||||
}, {})
|
||||
}
|
||||
if (this.orderCreateData.delivery.delivery_type == 'store' && this.storeConfig) {
|
||||
storeList = this.storeConfig.store_list;
|
||||
storeList = storeList.reduce((res, item) => {
|
||||
return {...res, [item.store_id]: item}
|
||||
}, {})
|
||||
}
|
||||
}
|
||||
return storeList;
|
||||
},
|
||||
// 门店信息
|
||||
storeInfo: {
|
||||
get(){
|
||||
if (this.storeList && this.orderCreateData.delivery && this.orderCreateData.delivery.delivery_type != 'express' && this.storeId) {
|
||||
return this.storeList[ this.orderCreateData.delivery.store_id ];
|
||||
}
|
||||
},
|
||||
set(value){
|
||||
this.storeList[ this.orderCreateData.delivery.store_id ].store_image = value;
|
||||
}
|
||||
},
|
||||
// 会员卡购买周期
|
||||
cardChargeType(){
|
||||
if (this.paymentData.recommend_member_card) {
|
||||
let charge_rule_arr = [];
|
||||
let charge_rule = this.paymentData.recommend_member_card.charge_rule;
|
||||
Object.keys(charge_rule).forEach((key, index)=>{
|
||||
switch (key) {
|
||||
case 'week':
|
||||
charge_rule_arr.push({'key': key, 'value': charge_rule[key], 'title' : '周卡', unit: '周'});
|
||||
break;
|
||||
case 'month':
|
||||
charge_rule_arr.push({'key': key, 'value': charge_rule[key], 'title' : '月卡', unit: '月'});
|
||||
break;
|
||||
case 'quarter':
|
||||
charge_rule_arr.push({'key': key, 'value': charge_rule[key], 'title' : '季卡', unit: '季'});
|
||||
break;
|
||||
case 'year':
|
||||
charge_rule_arr.push({'key': key, 'value': charge_rule[key], 'title' : '年卡', unit: '年'});
|
||||
break;
|
||||
}
|
||||
})
|
||||
return charge_rule_arr;
|
||||
}
|
||||
},
|
||||
// 定位信息
|
||||
location(){
|
||||
return this.$store.state.location;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
storeToken: function(nVal, oVal) {
|
||||
this.payment();
|
||||
},
|
||||
deliveryTime: function(nVal){
|
||||
if (!nVal) this.$refs.timePopup.refresh();
|
||||
},
|
||||
location: function(nVal){
|
||||
if (nVal) {
|
||||
this.orderCreateData.latitude = nVal.latitude;
|
||||
this.orderCreateData.longitude = nVal.longitude;
|
||||
this.payment();
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* 父级页面onShow调用
|
||||
*/
|
||||
pageShow(){
|
||||
if (uni.getStorageSync('addressBack') ) {
|
||||
uni.removeStorageSync('addressBack');
|
||||
this.payment();
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 获取订单结算数据
|
||||
*/
|
||||
payment(){
|
||||
this.$api.sendRequest({
|
||||
url: this.api.payment,
|
||||
data: this.orderCreateData,
|
||||
success: res => {
|
||||
if (res.code == 0 && res.data) {
|
||||
let data = res.data;
|
||||
|
||||
// #ifdef MP-WEIXIN
|
||||
var scene = uni.getStorageSync('is_test') ? 1175 : wx.getLaunchOptionsSync().scene;
|
||||
if([1175, 1176, 1177, 1191, 1195].indexOf(scene) != -1 && data.shop_goods_list.express_type){
|
||||
data.shop_goods_list.express_type = data.shop_goods_list.express_type.filter(item => item.name == 'express' );
|
||||
}
|
||||
// #endif
|
||||
|
||||
if (data.shop_goods_list) {
|
||||
// 配送方式
|
||||
if (data.shop_goods_list.express_type && data.shop_goods_list.express_type.length) {
|
||||
let deliveryStorage = uni.getStorageSync('delivery');
|
||||
data.shop_goods_list.express_type.forEach(item => {
|
||||
if (deliveryStorage) {
|
||||
if (item.name == deliveryStorage.delivery_type) {
|
||||
this.orderCreateData.delivery = deliveryStorage;
|
||||
this.storeId = deliveryStorage.store_id ?? 0;
|
||||
if (deliveryStorage.delivery_type == 'store') {
|
||||
this.orderCreateData.member_address = {mobile: data.member_account.mobile ?? '' }
|
||||
if (!this.location) this.$util.getLocation();
|
||||
}
|
||||
if (deliveryStorage.delivery_type == 'local' && !this.location) this.$util.getLocation();
|
||||
}
|
||||
}
|
||||
if (item.name == 'local') this.localConfig = item;
|
||||
if (item.name == 'store') this.storeConfig = item;
|
||||
})
|
||||
|
||||
if (!this.orderCreateData.delivery.delivery_type) {
|
||||
this.selectDeliveryType(data.shop_goods_list.express_type[0], false);
|
||||
}
|
||||
|
||||
if(uni.getStorageSync('deliveryTime') && uni.getStorageSync('deliveryTime')['delivery_type'] && uni.getStorageSync('deliveryTime')['delivery_type'] == this.orderCreateData.delivery.delivery_type){
|
||||
this.deliveryTime = uni.getStorageSync('deliveryTime')['deliveryTime'];
|
||||
this.orderCreateData.buyer_ask_delivery_time = uni.getStorageSync('deliveryTime')['buyer_ask_delivery_time'];
|
||||
}
|
||||
}
|
||||
|
||||
// 优惠券
|
||||
if (data.shop_goods_list.coupon_list && data.shop_goods_list.coupon_list[0])
|
||||
this.orderCreateData.coupon = {coupon_id: data.shop_goods_list.coupon_list[0].coupon_id };
|
||||
}
|
||||
// 地址、手机号
|
||||
if (data.is_virtual) {
|
||||
this.orderCreateData.member_address = '';
|
||||
}
|
||||
|
||||
// 处理表单数据
|
||||
data = this.handleGoodsFormData(data);
|
||||
|
||||
// 该方法在父级组件中
|
||||
this.promotionInfo = this.promotion(data);
|
||||
|
||||
this.paymentData = data;
|
||||
this.calculate();
|
||||
}else{
|
||||
this.$util.showToast({
|
||||
title: res.message
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
this.$util.redirectTo('/pages/index/index');
|
||||
}, 1000)
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
/**
|
||||
* 处理商品表单数据
|
||||
* @param {Object} data
|
||||
*/
|
||||
handleGoodsFormData(data){
|
||||
let goodsFormData = uni.getStorageSync('goodFormData');
|
||||
data.shop_goods_list.goods_list.forEach(item => {
|
||||
if (item.goods_form) {
|
||||
let formData = {};
|
||||
if (item.form_data) {
|
||||
item.form_data.map(formIem => {
|
||||
formData[formIem.id] = formIem;
|
||||
})
|
||||
} else if (goodsFormData && goodsFormData.goods_id == item.goods_id) {
|
||||
goodsFormData.form_data.map(formIem => {
|
||||
formData[formIem.id] = formIem;
|
||||
})
|
||||
}
|
||||
if (Object.keys(formData).length) {
|
||||
item.goods_form.json_data.forEach(formIem => {
|
||||
if (formData[formIem.id]) {
|
||||
formIem.val = formData[formIem.id].val;
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
return data;
|
||||
},
|
||||
/**
|
||||
* 订单创建
|
||||
*/
|
||||
calculate(){
|
||||
this.$api.sendRequest({
|
||||
url: this.api.calculate,
|
||||
data: this.handleCreateData(),
|
||||
success: res => {
|
||||
if (this.$refs.loadingCover && this.$refs.loadingCover.isShow) this.$refs.loadingCover.hide();
|
||||
if (res.code == 0 && res.data) {
|
||||
this.calculateData = res.data;
|
||||
if (res.data.delivery) {
|
||||
if (res.data.delivery.delivery_type == 'express') this.memberAddress = res.data.member_address;
|
||||
if (res.data.delivery.delivery_type == 'local') this.localMemberAddress = res.data.member_address;
|
||||
}
|
||||
// 次卡
|
||||
res.data.shop_goods_list.goods_list.forEach(item => {
|
||||
if (item.member_card_list) {
|
||||
if (this.orderCreateData.member_goods_card[ item.sku_id ]) {
|
||||
let itemId = this.orderCreateData.member_goods_card[ item.sku_id ];
|
||||
if (!item.member_card_list[itemId]) delete this.orderCreateData.member_goods_card[ item.sku_id ];
|
||||
}
|
||||
} else if (this.orderCreateData.member_goods_card[ item.sku_id ]) {
|
||||
delete this.orderCreateData.member_goods_card[ item.sku_id ];
|
||||
}
|
||||
})
|
||||
if (!res.data.shop_goods_list.coupon_id) this.orderCreateData.coupon.coupon_id = 0;
|
||||
else this.orderCreateData.coupon.coupon_id = res.data.shop_goods_list.coupon_id;
|
||||
|
||||
this.$forceUpdate();
|
||||
} else {
|
||||
this.$util.showToast({
|
||||
title: res.message
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
/**
|
||||
* 订单创建
|
||||
*/
|
||||
create(){
|
||||
if (!this.verify() || this.isRepeat) return;
|
||||
this.isRepeat = true;
|
||||
uni.showLoading({title: ''})
|
||||
this.$api.sendRequest({
|
||||
url: this.api.create,
|
||||
data: this.handleCreateData(),
|
||||
success: res => {
|
||||
uni.hideLoading();
|
||||
if (res.code == 0) {
|
||||
this.outTradeNo = res.data;
|
||||
uni.removeStorageSync('deliveryTime');
|
||||
uni.removeStorageSync('goodFormData');
|
||||
uni.setStorageSync('paySource', '');
|
||||
if (this.calculateData.pay_money == 0) {
|
||||
// #ifdef MP-WEIXIN
|
||||
if (this.paymentData.is_virtual || this.orderCreateData.delivery.delivery_type == 'store') {
|
||||
this.$util.subscribeMessage('ORDER_VERIFY_OUT_TIME,VERIFY_CODE_EXPIRE,VERIFY');
|
||||
}
|
||||
// #endif
|
||||
this.$util.redirectTo('/pages_tool/pay/result', {
|
||||
code: res.data
|
||||
}, 'redirectTo');
|
||||
} else {
|
||||
this.openChoosePayment();
|
||||
}
|
||||
} else {
|
||||
this.$util.showToast({ title: res.message });
|
||||
this.isRepeat = false;
|
||||
}
|
||||
// 更新购物车数量
|
||||
this.$store.dispatch('getCartNumber');
|
||||
}
|
||||
})
|
||||
},
|
||||
/**
|
||||
* 处理订单计算、创建传参
|
||||
*/
|
||||
handleCreateData(){
|
||||
let data = this.$util.deepClone(this.orderCreateData);
|
||||
// 订单表单
|
||||
if (this.$refs.form) {
|
||||
data.form_data = { form_id: this.paymentData.system_form.id, form_data: this.$util.deepClone(this.$refs.form.formData) };
|
||||
}
|
||||
// 商品表单
|
||||
if (this.$refs.goodsForm) {
|
||||
if (!data.form_data) data.form_data = {};
|
||||
data.form_data.goods_form = {};
|
||||
this.$refs.goodsForm.forEach(item => {
|
||||
data.form_data.goods_form[item._props.customAttr.sku_id] = {
|
||||
form_id: item._props.customAttr.form_id,
|
||||
form_data: this.$util.deepClone(item.formData)
|
||||
}
|
||||
})
|
||||
}
|
||||
Object.keys(data).forEach((key) => {
|
||||
let item = data[key];
|
||||
if (typeof item == 'object') data[key] = JSON.stringify(item);
|
||||
})
|
||||
if (data.member_address && this.orderCreateData.delivery && this.orderCreateData.delivery.delivery_type != 'store' ) delete data.member_address;
|
||||
return data;
|
||||
},
|
||||
/**
|
||||
* 打开支付弹窗
|
||||
*/
|
||||
openChoosePayment(){
|
||||
// #ifdef MP-WEIXIN
|
||||
if (this.paymentData.is_virtual) {
|
||||
this.$util.subscribeMessage('ORDER_URGE_PAYMENT,ORDER_PAY');
|
||||
} else {
|
||||
switch(this.orderCreateData.delivery.delivery_type){
|
||||
case 'express'://物流配送
|
||||
this.$util.subscribeMessage('ORDER_URGE_PAYMENT,ORDER_PAY,ORDER_DELIVERY');
|
||||
break;
|
||||
case 'store'://门店自提
|
||||
this.$util.subscribeMessage('ORDER_URGE_PAYMENT,ORDER_PAY');
|
||||
break;
|
||||
case 'local'://同城配送
|
||||
this.$util.subscribeMessage('ORDER_URGE_PAYMENT,ORDER_PAY,ORDER_DELIVERY');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// #endif
|
||||
this.$refs.choosePaymentPopup.getPayInfo(this.outTradeNo);
|
||||
},
|
||||
verify(){
|
||||
if (this.paymentData.is_virtual == 0) {
|
||||
if (!this.orderCreateData.delivery || !this.orderCreateData.delivery.delivery_type) {
|
||||
this.$util.showToast({ title: '商家未设置配送方式' });
|
||||
return false;
|
||||
}
|
||||
if (
|
||||
(this.orderCreateData.delivery.delivery_type == 'express' && !this.memberAddress) ||
|
||||
(this.orderCreateData.delivery.delivery_type == 'local' && !this.localMemberAddress)
|
||||
) {
|
||||
this.$util.showToast({ title: '请先选择您的收货地址' });
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.orderCreateData.delivery.delivery_type == 'store') {
|
||||
if (!this.orderCreateData.delivery.store_id) {
|
||||
this.$util.showToast({
|
||||
title: '没有可提货的门店,请选择其他配送方式'
|
||||
});
|
||||
return false;
|
||||
}
|
||||
if (!this.orderCreateData.member_address.mobile) {
|
||||
this.$util.showToast({
|
||||
title: '请输入预留手机'
|
||||
});
|
||||
return false;
|
||||
}
|
||||
var reg = /^[1](([3][0-9])|([4][5-9])|([5][0-3,5-9])|([6][5,6])|([7][0-8])|([8][0-9])|([9][1,8,9]))[0-9]{8}$/;
|
||||
if (!reg.test(this.orderCreateData.member_address.mobile)) {
|
||||
this.$util.showToast({
|
||||
title: '请输入正确的手机号'
|
||||
});
|
||||
return false;
|
||||
}
|
||||
if (!this.deliveryTime) {
|
||||
this.$util.showToast({
|
||||
title: '请选择提货时间'
|
||||
});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.orderCreateData.delivery.delivery_type == 'local') {
|
||||
if (!this.orderCreateData.delivery.store_id) {
|
||||
this.$util.showToast({
|
||||
title: '没有可配送的门店,请选择其他配送方式'
|
||||
});
|
||||
return false;
|
||||
}
|
||||
if (this.calculateGoodsData.local_config && this.calculateGoodsData.local_config.info.time_is_open == 1 && !this.deliveryTime) {
|
||||
this.$util.showToast({
|
||||
title: '请选择送达时间'
|
||||
});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.$refs.goodsForm) {
|
||||
let formVerify = true;
|
||||
for (let i = 0; i < this.$refs.goodsForm.length; i++) {
|
||||
let item = this.$refs.goodsForm[i];
|
||||
formVerify = item.verify();
|
||||
if (!formVerify) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!formVerify) return false;
|
||||
}
|
||||
if (this.paymentData.system_form) {
|
||||
let formVerify = this.$refs.form.verify();
|
||||
if (!formVerify) return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
/**
|
||||
* 选择收货地址
|
||||
*/
|
||||
selectAddress() {
|
||||
var params = {
|
||||
back: this.$util.getCurrentRoute().path,
|
||||
local: 0,
|
||||
type: 1
|
||||
}
|
||||
// 外卖配送需要定位地址
|
||||
if (this.orderCreateData.delivery.delivery_type == 'local') {
|
||||
params.local = 1;
|
||||
params.type = 2;
|
||||
}
|
||||
this.$util.redirectTo('/pages_tool/member/address', params);
|
||||
},
|
||||
/**
|
||||
* 选择配送方式
|
||||
* @param {Object} data
|
||||
*/
|
||||
selectDeliveryType(data, calculate = true){
|
||||
if (this.orderCreateData.delivery && this.orderCreateData.delivery.delivery_type == data.name) return;
|
||||
|
||||
let delivery = {
|
||||
delivery_type: data.name,
|
||||
delivery_type_name: data.title
|
||||
}
|
||||
// 如果是门店配送
|
||||
if (data.name == 'store' || data.name == 'local') {
|
||||
if(data.store_list[0]) {
|
||||
delivery.store_id = data.store_list[0].store_id;
|
||||
}
|
||||
this.storeId = delivery.store_id ? delivery.store_id : 0;
|
||||
if (!this.orderCreateData.member_address) this.orderCreateData.member_address = {mobile: this.paymentData && this.paymentData.member_account.mobile ? this.paymentData.member_account.mobile : '' }
|
||||
}
|
||||
this.$set(this.orderCreateData, 'delivery', delivery);
|
||||
this.orderCreateData.buyer_ask_delivery_time = '';
|
||||
this.deliveryTime = '';
|
||||
uni.removeStorageSync('deliveryTime');
|
||||
uni.setStorageSync('delivery', delivery);
|
||||
|
||||
// 配送方式不为门店配送时
|
||||
if (this.orderCreateData.delivery.delivery_type != 'express' && !this.location) this.$util.getLocation();
|
||||
if (calculate) this.calculate();
|
||||
},
|
||||
/**
|
||||
* 图片错误
|
||||
* @param {Object} index
|
||||
*/
|
||||
imageError(index){
|
||||
this.paymentData.shop_goods_list.goods_list[index].sku_image = this.$util.getDefaultImage().goods;
|
||||
this.$forceUpdate();
|
||||
},
|
||||
/**
|
||||
* 选择门店
|
||||
* @param {Object} data
|
||||
*/
|
||||
selectPickupPoint(data) {
|
||||
if (data.store_id != this.storeId) {
|
||||
this.storeId = data.store_id;
|
||||
this.orderCreateData.delivery.store_id = data.store_id;
|
||||
this.calculate();
|
||||
this.resetDeliveryTime();
|
||||
// 存储所选门店
|
||||
let delivery = uni.getStorageSync('delivery');
|
||||
delivery.store_id = data.store_id;
|
||||
uni.setStorageSync('delivery', delivery)
|
||||
}
|
||||
this.$refs.deliveryPopup.close();
|
||||
},
|
||||
/**
|
||||
* 重置提货时间
|
||||
*/
|
||||
resetDeliveryTime(){
|
||||
this.orderCreateData.buyer_ask_delivery_time = '';
|
||||
this.deliveryTime = '';
|
||||
uni.removeStorageSync('deliveryTime');
|
||||
},
|
||||
/**
|
||||
* 门店
|
||||
*/
|
||||
storetime(type = ''){
|
||||
if(this.storeInfo){
|
||||
let data = this.$util.deepClone(this.storeInfo);
|
||||
if (data.delivery_time) {
|
||||
data.delivery_time = JSON.parse(data.delivery_time);
|
||||
data.end_time = data.delivery_time[ (data.delivery_time.length - 1) ].end_time;
|
||||
} else {
|
||||
data.delivery_time = [ {start_time: data.start_time, end_time: data.end_time} ]
|
||||
}
|
||||
let obj = {
|
||||
delivery:this.orderCreateData.delivery,
|
||||
dataTime:data
|
||||
}
|
||||
this.$refs.timePopup.open(obj,type);
|
||||
this.$forceUpdate();
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 选择自提时间
|
||||
* @param {Object} data
|
||||
*/
|
||||
selectPickupTime(data){
|
||||
this.deliveryTime = data.data.month + '('+ data.data.time +')';
|
||||
|
||||
let nowDate = new Date();
|
||||
let Year = nowDate.getFullYear();
|
||||
let timeData = data.data.month.split('月');
|
||||
let month = timeData[0];
|
||||
let date = timeData[1].split('日')[0];
|
||||
this.orderCreateData.buyer_ask_delivery_time = Year + '-' + month + '-' + date + ' ' + data.data.time
|
||||
|
||||
//将时间缓存,避免切换地址时重置
|
||||
uni.setStorageSync('deliveryTime',{
|
||||
'deliveryTime' : this.deliveryTime,
|
||||
'buyer_ask_delivery_time' : this.orderCreateData.buyer_ask_delivery_time,
|
||||
'delivery_type' : this.orderCreateData.delivery.delivery_type
|
||||
});
|
||||
|
||||
},
|
||||
storeImgError(){
|
||||
this.storeInfo.store_image = this.$util.getDefaultImage().store;
|
||||
},
|
||||
openPopup(ref) {
|
||||
this.tempData = this.$util.deepClone(this.orderCreateData);
|
||||
this.$refs[ref].open();
|
||||
},
|
||||
closePopup(ref) {
|
||||
this.orderCreateData = this.$util.deepClone(this.tempData);
|
||||
this.$refs[ref].close();
|
||||
this.tempData = null;
|
||||
},
|
||||
/**
|
||||
* 切换发票开关
|
||||
*/
|
||||
changeIsInvoice() {
|
||||
if (this.orderCreateData.is_invoice == 0) {
|
||||
this.orderCreateData.is_invoice = 1;
|
||||
if (!this.orderCreateData.invoice_type) this.orderCreateData.invoice_type = this.goodsData.invoice.invoice_type.split(',')[0];
|
||||
} else {
|
||||
this.orderCreateData.is_invoice = 0;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 切换发票类型
|
||||
* @param {Object} invoice_type
|
||||
*/
|
||||
changeInvoiceType(invoice_type) {
|
||||
this.orderCreateData.invoice_type = invoice_type;
|
||||
},
|
||||
/**
|
||||
* 切换发票个人还是企业
|
||||
* @param {Object} invoice_title_type
|
||||
*/
|
||||
changeInvoiceTitleType(invoice_title_type) {
|
||||
this.orderCreateData.invoice_title_type = invoice_title_type;
|
||||
},
|
||||
/**
|
||||
* 切换增值税专用发票开关
|
||||
*/
|
||||
changeIsTaxInvoice() {
|
||||
if (this.orderCreateData.is_tax_invoice == 0) this.orderCreateData.is_tax_invoice = 1;
|
||||
else this.orderCreateData.is_tax_invoice = 0;
|
||||
this.$forceUpdate();
|
||||
},
|
||||
/**
|
||||
* 选择发票内容
|
||||
* @param {Object} invoice_content
|
||||
*/
|
||||
changeInvoiceContent(invoice_content) {
|
||||
this.orderCreateData.invoice_content = invoice_content;
|
||||
this.$forceUpdate();
|
||||
},
|
||||
/**
|
||||
* 验证发票内容
|
||||
*/
|
||||
invoiceVerify() {
|
||||
if (!this.orderCreateData.invoice_title) {
|
||||
this.$util.showToast({
|
||||
title: '请填写发票抬头'
|
||||
});
|
||||
return false;
|
||||
}
|
||||
if (!this.orderCreateData.taxpayer_number && this.orderCreateData.invoice_title_type == 2) {
|
||||
this.$util.showToast({
|
||||
title: '请填写纳税人识别号'
|
||||
});
|
||||
return false;
|
||||
}
|
||||
if (this.orderCreateData.invoice_type == 1 && !this.orderCreateData.invoice_full_address && this.orderPaymentData.is_virtual ==1) {
|
||||
this.$util.showToast({
|
||||
title: '请填写发票邮寄地址'
|
||||
});
|
||||
return false;
|
||||
}
|
||||
if (this.orderCreateData.invoice_type == 2 && !this.orderCreateData.invoice_email) {
|
||||
this.$util.showToast({
|
||||
title: '请填写邮箱'
|
||||
});
|
||||
return false;
|
||||
}
|
||||
if (this.orderCreateData.invoice_type == 2) {
|
||||
var reg = /^([a-zA-Z]|[0-9])(\w|\-)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/;
|
||||
if (!reg.test(this.orderCreateData.invoice_email)) {
|
||||
this.$util.showToast({
|
||||
title: '请填写正确的邮箱'
|
||||
});
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!this.orderCreateData.invoice_content) {
|
||||
this.$util.showToast({
|
||||
title: '请选择发票内容'
|
||||
});
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
/**
|
||||
* 保存发票设置
|
||||
*/
|
||||
saveInvoice(){
|
||||
if (this.orderCreateData.is_invoice == 1 && !this.invoiceVerify()) return;
|
||||
this.calculate();
|
||||
this.$refs.invoicePopup.close();
|
||||
},
|
||||
/**
|
||||
* 保存留言
|
||||
*/
|
||||
saveBuyerMessage(){
|
||||
this.$refs.buyerMessagePopup.close();
|
||||
},
|
||||
/**
|
||||
* 选择会员卡
|
||||
*/
|
||||
selectMemberCard() {
|
||||
this.orderCreateData.is_open_card = this.orderCreateData.is_open_card ? 0 : 1;
|
||||
if (!this.orderCreateData.member_card_unit) this.orderCreateData.member_card_unit = this.cardChargeType[0].key;
|
||||
this.calculate();
|
||||
},
|
||||
/**
|
||||
* 选择会员卡充值类型
|
||||
* @param {Object} key
|
||||
*/
|
||||
selectMembercardUnit(key){
|
||||
this.orderCreateData.member_card_unit = key;
|
||||
this.calculate();
|
||||
},
|
||||
/**
|
||||
* 使用积分抵扣
|
||||
*/
|
||||
usePoint() {
|
||||
this.orderCreateData.is_point = this.orderCreateData.is_point ? 0 : 1;
|
||||
this.calculate();
|
||||
},
|
||||
/**
|
||||
* 支付弹窗关闭
|
||||
*/
|
||||
payClose(){
|
||||
this.$util.redirectTo('/pages/order/detail', {order_id: this.$refs.choosePaymentPopup.payInfo.order_id}, 'redirectTo');
|
||||
},
|
||||
/**
|
||||
* 选择优惠券
|
||||
* @param {Object} data
|
||||
*/
|
||||
selectCoupon(data){
|
||||
if (this.orderCreateData.coupon.coupon_id == data.coupon_id) this.orderCreateData.coupon = {coupon_id: 0};
|
||||
else this.orderCreateData.coupon = {coupon_id: data.coupon_id};
|
||||
},
|
||||
/**
|
||||
* 使用优惠券
|
||||
*/
|
||||
useCpopon(){
|
||||
this.$refs.couponPopup.close();
|
||||
this.calculate();
|
||||
},
|
||||
/**
|
||||
* 同城配送送达时间
|
||||
*/
|
||||
localtime(type = ''){
|
||||
let data = this.$util.deepClone(this.calculateGoodsData.local_config.info);
|
||||
if (data.delivery_time) {
|
||||
data.end_time = data.delivery_time[ (data.delivery_time.length - 1) ].end_time;
|
||||
}
|
||||
let obj = {
|
||||
delivery: this.orderCreateData.delivery,
|
||||
dataTime: data
|
||||
}
|
||||
this.$refs.timePopup.open(obj,type);
|
||||
},
|
||||
/**
|
||||
* 剩余起送价
|
||||
*/
|
||||
surplusStartMoney(){
|
||||
let money = 0;
|
||||
if (this.calculateData && this.calculateData.delivery && this.calculateData.delivery.delivery_type == 'local') {
|
||||
let startDeliveryMoney = this.calculateGoodsData.delivery.start_money ?? 0;
|
||||
money = parseFloat(startDeliveryMoney) - parseFloat(this.calculateData.goods_money);
|
||||
money = money < 0 ? 0 : money;
|
||||
}
|
||||
return money;
|
||||
},
|
||||
/**
|
||||
* 交易协议
|
||||
*/
|
||||
getTransactionAgreement(){
|
||||
this.$api.sendRequest({
|
||||
url: '/api/order/transactionagreement',
|
||||
success: res => {
|
||||
if (res.data) this.transactionAgreement = res.data;
|
||||
}
|
||||
})
|
||||
},
|
||||
editForm(index){
|
||||
this.tempFormData = {
|
||||
index: index,
|
||||
json_data: this.$util.deepClone(this.goodsData.goods_list[index].goods_form.json_data)
|
||||
}
|
||||
this.$refs.editFormPopup.open();
|
||||
},
|
||||
saveForm(){
|
||||
if (this.$refs.tempForm.verify()) {
|
||||
this.$set(this.paymentData.shop_goods_list.goods_list[ this.tempFormData.index ].goods_form, 'json_data', this.$refs.tempForm.formData);
|
||||
this.$refs.editFormPopup.close();
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 切换次卡
|
||||
* @param {Object} index
|
||||
*/
|
||||
selectMemberGoodsCard(index){
|
||||
let sku_id = this.goodsData.goods_list[index].sku_id;
|
||||
this.selectGoodsCard = {
|
||||
skuId: sku_id,
|
||||
itemId: this.orderCreateData.member_goods_card[sku_id] ? this.orderCreateData.member_goods_card[sku_id] : 0,
|
||||
cardList: this.$util.deepClone(this.calculateGoodsData.goods_list[index].member_card_list),
|
||||
click: (item_id) => {
|
||||
this.selectGoodsCard.itemId = this.selectGoodsCard.itemId == item_id ? 0 : item_id;
|
||||
}
|
||||
}
|
||||
this.$refs.memberGoodsCardPopup.open();
|
||||
},
|
||||
/**
|
||||
* 选择次卡
|
||||
*/
|
||||
saveMemberGoodsCard(){
|
||||
this.orderCreateData.member_goods_card[ this.selectGoodsCard.skuId ] = this.selectGoodsCard.itemId || 0;
|
||||
this.$refs.memberGoodsCardPopup.close();
|
||||
this.calculate();
|
||||
}
|
||||
},
|
||||
filters: {
|
||||
// 金额格式化输出
|
||||
moneyFormat(money) {
|
||||
return parseFloat(money).toFixed(2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,185 @@
|
|||
<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 = {
|
||||
num: this.value.count
|
||||
};
|
||||
if (this.value.sources == 'diy') {
|
||||
data.num = 0;
|
||||
data.article_id_arr = this.value.articleIds.toString();
|
||||
}
|
||||
|
||||
this.$api.sendRequest({
|
||||
url: '/api/article/lists',
|
||||
data: data,
|
||||
success: res => {
|
||||
if (res.code == 0 && res.data) {
|
||||
let data = res.data;
|
||||
this.list = data;
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
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-top: 24rpx;
|
||||
&:first-of-type{
|
||||
margin-top: 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>
|
||||
|
|
@ -0,0 +1,660 @@
|
|||
<template>
|
||||
<view class="diy-bargain" v-if="list.length" :class="[value.template, value.style]" :style="warpCss">
|
||||
<!-- 商品头部 -->
|
||||
<view v-if="value.titleStyle.isShow" :class="[value.titleStyle.style,'bargain-head']"
|
||||
:style="{'backgroundImage': 'url(' + $util.img(value.titleStyle.backgroundImage) + '), linear-gradient(to right,'+value.titleStyle.bgColorStart+','+ value.titleStyle.bgColorEnd+')' }">
|
||||
<view v-if="value.titleStyle.leftStyle == 'text'" class="left-text"
|
||||
:style="{fontSize: value.titleStyle.fontSize*2 + 'rpx',color: value.titleStyle.textColor,fontWeight: value.titleStyle.fontWeight ? 'bold' : ''}">
|
||||
{{value.titleStyle.leftText}}</view>
|
||||
<image v-else class="left-img" :src="$util.img(value.titleStyle.leftImg)" mode="heightFix"></image>
|
||||
<view class="head-content" :style="{color: value.titleStyle.textColor}">低至0元免费拿</view>
|
||||
<view class="head-right"
|
||||
:style="{fontSize: value.titleStyle.moreFontSize*2 + 'rpx',color: value.titleStyle.moreColor}"
|
||||
@click="$util.redirectTo('/pages_promotion/bargain/list')">
|
||||
<text>{{value.titleStyle.more}}</text>
|
||||
<text class="iconfont icon-right"></text>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 商品列表 -->
|
||||
<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.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="progress" v-if="value.style=='style-2'">
|
||||
<view class="bg">
|
||||
<view class="curr" :style="{width: progress(item)*2+'rpx'}">
|
||||
<image class="progress-bar" mode="widthFix"
|
||||
:src="$util.img('public/uniapp/bargain/progress_bar_01.png')">
|
||||
</image>
|
||||
</view>
|
||||
</view>
|
||||
<view class="num" v-if="item.is_bargaining">
|
||||
已砍 <text>¥{{(item.price - item.curr_price).toFixed(2)}}</text>,仅差
|
||||
<text>¥{{item.curr_price}}</text>
|
||||
</view>
|
||||
<view class="num" v-else>
|
||||
最低可砍至 <text>¥{{item.floor_price}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="price-wrap">
|
||||
<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' : '' }">{{ value.style=='style-2' ? item.price.split(".")[0] : item.floor_price.split(".")[0] }}</text>
|
||||
<text class="unit price-style small"
|
||||
:style="{ color: value.theme == 'diy' ? value.priceStyle.mainColor +'!important' : '' }">{{ value.style=='style-2' ? "."+item.price.split(".")[1] : "."+item.floor_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'
|
||||
}">
|
||||
{{ item.is_bargaining ? '继续砍价' : value.btnStyle.text }}
|
||||
</button>
|
||||
</view>
|
||||
</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)"
|
||||
:lazy-load="true"></image>
|
||||
<image class="bg"
|
||||
v-if="value.saleStyle.control&&value.template == 'horizontal-slide'&&value.style!='style-2'"
|
||||
:src="$util.img('public/uniapp/bargain/bg.png')" mode="widthFix"></image>
|
||||
<view class="num"
|
||||
v-if="value.saleStyle.control&&value.template == 'horizontal-slide'&&value.style!='style-2'"
|
||||
:style="{ color: value.theme == 'diy' ? value.saleStyle.color : '' }">已砍{{ item.sale_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&&value.template == 'horizontal-slide'&&value.style!='style-2'">
|
||||
<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.floor_price.split(".")[0] }}</text>
|
||||
<text class="unit price-style small"
|
||||
:style="{ color: value.theme == 'diy' ? value.priceStyle.mainColor +'!important' : '' }">{{ "."+item.floor_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)" :lazy-load="true"></image>
|
||||
<image class="bg"
|
||||
v-if="value.saleStyle.control&&value.template == 'horizontal-slide'&&value.style!='style-2'"
|
||||
:src="$util.img('public/uniapp/bargain/bg.png')" mode="widthFix"></image>
|
||||
<view class="num"
|
||||
v-if="value.saleStyle.control&&value.template == 'horizontal-slide'&&value.style!='style-2'"
|
||||
:style="{ color: value.theme == 'diy' ? value.saleStyle.color : '' }">
|
||||
已砍{{ item.sale_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&&value.template == 'horizontal-slide'&&value.style!='style-2'">
|
||||
<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.floor_price.split(".")[0] }}</text>
|
||||
<text class="unit price-style small"
|
||||
:style="{ color: value.theme == 'diy' ? value.priceStyle.mainColor +'!important' : '' }">{{ "."+item.floor_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-bargain',
|
||||
props: {
|
||||
value: {
|
||||
type: Object
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
list: [],
|
||||
page: 1
|
||||
};
|
||||
},
|
||||
components: {},
|
||||
async created() {
|
||||
if (this.value.template == 'row1-of1' && this.value.style == 'style-2')
|
||||
await this.getDataing();
|
||||
this.getData();
|
||||
},
|
||||
computed: {
|
||||
warpCss() {
|
||||
var obj = '';
|
||||
if (this.value.componentBgColor) obj += 'background:' + 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') {
|
||||
if (this.value.ornament.type == 'shadow')
|
||||
return '420rpx';
|
||||
else
|
||||
return '400rpx';
|
||||
}
|
||||
if (this.value.ornament.type == 'shadow')
|
||||
return '386rpx';
|
||||
else
|
||||
return '378rpx';
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
rpxUpPx(res) {
|
||||
const screenWidth = uni.getSystemInfoSync().safeArea.width || uni.getSystemInfoSync().screenWidth;
|
||||
var data = screenWidth * parseInt(res) / 750;
|
||||
return Math.floor(data);
|
||||
},
|
||||
// 查找自己参与的砍价
|
||||
async getDataing() {
|
||||
var res = await this.$api.sendRequest({
|
||||
url: '/bargain/api/goods/bargainingList',
|
||||
data: {},
|
||||
async: false
|
||||
});
|
||||
|
||||
res.data && res.data.forEach((item, index) => {
|
||||
item.is_bargaining = 1;
|
||||
});
|
||||
this.list = res.data || [];
|
||||
},
|
||||
// 查找可砍价的商品
|
||||
getData() {
|
||||
var data = {
|
||||
num: this.value.count,
|
||||
is_exclude_bargaining: 1
|
||||
};
|
||||
if (this.value.sources == 'diy') {
|
||||
data.num = 0;
|
||||
data.id_arr = this.value.goodsId.toString();
|
||||
}
|
||||
|
||||
this.$api.sendRequest({
|
||||
url: '/bargain/api/goods/lists',
|
||||
data: data,
|
||||
success: res => {
|
||||
if (res.code == 0) {
|
||||
if (this.value.template == 'row1-of1' && this.value.style == 'style-2')
|
||||
this.list = this.list.concat(res.data).splice(0, this.value.count);
|
||||
else
|
||||
this.list = res.data;
|
||||
|
||||
// 切屏滚动,每页显示固定数量
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
progress(data) {
|
||||
// 214 表示当前进度条的宽度
|
||||
let progress = (((parseFloat(data.price) - parseFloat(data.curr_price)) / parseFloat(data.price)) * 214)
|
||||
.toFixed();
|
||||
if (progress == 'NaN') {
|
||||
progress = 0;
|
||||
}
|
||||
return progress;
|
||||
},
|
||||
toDetail(e) {
|
||||
this.$util.redirectTo('/pages_promotion/bargain/detail', {
|
||||
b_id: e.bargain_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-bargain {
|
||||
overflow: hidden;
|
||||
|
||||
// 头部
|
||||
.bargain-head {
|
||||
&.style-1 {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
height: 88rpx;
|
||||
box-sizing: border-box;
|
||||
padding: 0 20rpx;
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
margin-bottom: 20rpx;
|
||||
border-radius: 18rpx 18rpx 0 0;
|
||||
|
||||
.left-img {
|
||||
height: 40rpx;
|
||||
width: 156rpx;
|
||||
}
|
||||
|
||||
.head-content {
|
||||
position: relative;
|
||||
color: #fff;
|
||||
font-size: $font-size-tag;
|
||||
margin-right: auto;
|
||||
margin-left: 20rpx;
|
||||
line-height: 1;
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 2rpx;
|
||||
height: 24rpx;
|
||||
background-color: #fff;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
left: -12rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.head-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: $font-size-sub;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 商品列表
|
||||
&.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;
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
padding: 6rpx 0 6rpx 20rpx;
|
||||
|
||||
.goods-name {
|
||||
&.multi-hidden {
|
||||
line-height: 1.3;
|
||||
}
|
||||
}
|
||||
|
||||
.price-wrap {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.discount-price {
|
||||
white-space: nowrap;
|
||||
font-weight: bold;
|
||||
line-height: 1;
|
||||
|
||||
.unit {
|
||||
font-size: $font-size-tag;
|
||||
margin-right: 4rpx;
|
||||
color: var(--price-color);
|
||||
}
|
||||
|
||||
.price {
|
||||
font-size: $font-size-toolbar;
|
||||
color: var(--price-color);
|
||||
}
|
||||
}
|
||||
|
||||
button {
|
||||
margin: 0;
|
||||
padding: 0 20rpx;
|
||||
color: var(--btn-text-color);
|
||||
background-color: $base-color;
|
||||
color: #fff;
|
||||
min-width: 112rpx;
|
||||
height: 52rpx;
|
||||
line-height: 52rpx;
|
||||
font-size: $font-size-tag;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.style-2 {
|
||||
.discount-price {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.progress {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-top: 10rpx;
|
||||
margin-right: 16rpx;
|
||||
|
||||
.bg {
|
||||
margin-left: 6rpx;
|
||||
width: auto;
|
||||
height: 20rpx;
|
||||
border-radius: 20rpx;
|
||||
background-color: #FFEADB;
|
||||
position: relative;
|
||||
|
||||
&::after {
|
||||
content: "";
|
||||
width: 26rpx;
|
||||
height: 26rpx;
|
||||
border-radius: 50%;
|
||||
background-color: #FA1A1A;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
right: -18rpx;
|
||||
}
|
||||
|
||||
.curr {
|
||||
width: 0;
|
||||
height: 20rpx;
|
||||
border-radius: 20rpx;
|
||||
background-color: #FA1A1A;
|
||||
position: relative;
|
||||
.progress-bar {
|
||||
position: absolute;
|
||||
right: -20rpx;
|
||||
width: 30rpx;
|
||||
height: 30rpx;
|
||||
max-width: inherit !important;
|
||||
max-height: inherit !important;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.num {
|
||||
font-size: $font-size-tag;
|
||||
margin-top: 12rpx;
|
||||
line-height: 1;
|
||||
|
||||
text {
|
||||
color: #FA1A1A;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.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: 100%;
|
||||
}
|
||||
|
||||
.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: 160rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.goods-name {
|
||||
line-height: 1.3;
|
||||
|
||||
&.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: var(--price-color);
|
||||
}
|
||||
|
||||
.price {
|
||||
font-size: $font-size-toolbar;
|
||||
color: var(--price-color);
|
||||
}
|
||||
}
|
||||
|
||||
.original-price {
|
||||
margin-top: 4rpx;
|
||||
font-size: $font-size-tag;
|
||||
color: $color-tip;
|
||||
line-height: 1;
|
||||
text-decoration: line-through;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.swiper {
|
||||
padding: 20rpx;
|
||||
width: 100%;
|
||||
white-space: nowrap;
|
||||
box-sizing: border-box;
|
||||
|
||||
.swiper-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.item {
|
||||
width: 200rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,292 @@
|
|||
<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)' : '#333333' }"
|
||||
>
|
||||
{{ 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) {
|
||||
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: 998;
|
||||
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>
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,976 @@
|
|||
<template>
|
||||
<view class="" :class="['category-page-wrap', 'category-template-' + value.template]">
|
||||
<!-- #ifndef H5 -->
|
||||
<block v-if="value.template == 4">
|
||||
<view class="search-box u-navbar-content-title" v-if="value.search" @click="$util.redirectTo('/pages_tool/goods/search')" :style="navbarInnerStyle">
|
||||
<view class="search-content">
|
||||
<input type="text" class="uni-input font-size-tag" maxlength="50" placeholder="商品搜索" confirm-type="search" disabled="true" />
|
||||
<text class="iconfont icon-sousuo3"></text>
|
||||
</view>
|
||||
</view>
|
||||
<view :style="navbarInnerStyle" v-if="!value.search">商品分类</view>
|
||||
</block>
|
||||
<block v-if="value.template != 4">
|
||||
<view :style="navbarInnerStyle">商品分类</view>
|
||||
<view class="search-box" v-if="value.search" @click="$util.redirectTo('/pages_tool/goods/search')">
|
||||
<view class="search-content">
|
||||
<input type="text" class="uni-input font-size-tag" maxlength="50" placeholder="商品搜索" confirm-type="search" disabled="true" />
|
||||
<text class="iconfont icon-sousuo3"></text>
|
||||
</view>
|
||||
</view>
|
||||
</block>
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef H5 -->
|
||||
<view class="search-box" v-if="value.search" @click="$util.redirectTo('/pages_tool/goods/search')">
|
||||
<view class="search-content">
|
||||
<input type="text" class="uni-input font-size-tag" maxlength="50" placeholder="商品搜索" confirm-type="search" disabled="true" />
|
||||
<text class="iconfont icon-sousuo3"></text>
|
||||
</view>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
<view class="template-four wx" v-if="value.template == 4">
|
||||
<scroll-view scroll-x="true" class="template-four-wrap" :scroll-with-animation="true" :scroll-into-view="'category-one-' + oneCategorySelect" enable-flex="true">
|
||||
<view
|
||||
class="category-item"
|
||||
:id="'category-one-' + index"
|
||||
v-for="(item, index) in templateFourData"
|
||||
:key="index"
|
||||
:class="{ select: oneCategorySelect == index }"
|
||||
@click="templateFourOneFn(index)"
|
||||
>
|
||||
<view class="image-warp" :class="[{ 'color-base-border': oneCategorySelect == index }]"><image :src="$util.img(item.image)" mode="aspectFill"></image></view>
|
||||
<view :class="['text', { 'color-base-bg': oneCategorySelect == index }]">{{ item.category_name }}</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="category-item-all" @click="$refs.templateFourPopup.open()">
|
||||
<view class="category-item-all-wrap">
|
||||
<text class="text">展开</text>
|
||||
<image class="img" :src="$util.img('/public/uniapp/category/unfold.png')" mode="aspectFill"></image>
|
||||
</view>
|
||||
</view>
|
||||
<uni-popup type="top" ref="templateFourPopup" class="aaa">
|
||||
<view class="template-four-popup">
|
||||
<scroll-view scroll-y="true" class="template-four-scroll" enable-flex="true">
|
||||
<view
|
||||
class="item"
|
||||
:class="{ selected: oneCategorySelect == index }"
|
||||
@click="templateFourOneFn(index)"
|
||||
v-for="(item, index) in templateFourData"
|
||||
:key="index"
|
||||
>
|
||||
<view class="image-warp" :class="[{ 'color-base-border': oneCategorySelect == index }]">
|
||||
<image :src="$util.img(item.image)" mode="aspectFill"></image>
|
||||
</view>
|
||||
<view :class="['text', { 'color-base-bg': oneCategorySelect == index }]">{{ item.category_name }}</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="pack-up" @click="$refs.templateFourPopup.close()">
|
||||
<text>点击收起</text>
|
||||
<text class="iconfont icon-iconangledown-copy"></text>
|
||||
</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
</view>
|
||||
|
||||
<view class="content-box" v-if="categoryTree">
|
||||
<block v-if="categoryTree.length">
|
||||
<scroll-view scroll-y="true" class="tree-wrap">
|
||||
<view class="category-item-wrap">
|
||||
<view
|
||||
class="category-item"
|
||||
v-for="(item, index) in categoryTree"
|
||||
:key="index"
|
||||
:class="[
|
||||
{ select: select == index },
|
||||
{ 'border-bottom': value.template == 4 && select + 1 === index },
|
||||
{ 'border-top': value.template == 4 && select - 1 === index }
|
||||
]"
|
||||
@click="switchOneCategory(index)"
|
||||
>
|
||||
<view class="">{{ item.category_name }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<view class="right-flex-wrap">
|
||||
<scroll-view
|
||||
scroll-y="true"
|
||||
class="content-wrap"
|
||||
v-if="value.template == 1 || loadType == 'all'"
|
||||
ref="contentWrap"
|
||||
:scroll-into-view="categoryId"
|
||||
:scroll-with-animation="true"
|
||||
@scroll="listenScroll"
|
||||
@touchstart="touchStart"
|
||||
:refresher-enabled="true"
|
||||
refresher-default-style="none"
|
||||
:refresher-triggered="triggered"
|
||||
@refresherrefresh="onRefresh"
|
||||
@refresherrestore="onRestore"
|
||||
>
|
||||
<view class="child-category" v-for="(item, index) in categoryTree" :key="index" :id="'category-' + index">
|
||||
<diy-category-item
|
||||
:category="item"
|
||||
:value="value"
|
||||
ref="categoryItem"
|
||||
:index="index"
|
||||
:select="select"
|
||||
:oneCategorySelect="oneCategorySelect"
|
||||
@tologin="toLogin"
|
||||
@selectsku="selectSku($event, index)"
|
||||
@addCart="addCartPoint"
|
||||
@loadfinish="getHeightArea"
|
||||
></diy-category-item>
|
||||
</view>
|
||||
<view class="end-tips" ref="endTips" :style="{ opacity: endTips }">已经到底了~</view>
|
||||
</scroll-view>
|
||||
|
||||
<view class="content-wrap" v-if="(value.template == 2 || value.template == 3 || value.template == 4) && loadType == 'part'">
|
||||
<view
|
||||
class="child-category-wrap"
|
||||
v-for="(item, index) in categoryTree"
|
||||
:key="index"
|
||||
:id="'category-' + index"
|
||||
:style="{ display: select == index ? 'block' : 'none' }"
|
||||
>
|
||||
<diy-category-item
|
||||
:category="item"
|
||||
:value="value"
|
||||
ref="categoryItem"
|
||||
:index="index"
|
||||
:last="index == categoryTree.length - 1 ? true : false"
|
||||
:select="select"
|
||||
:oneCategorySelect="oneCategorySelect"
|
||||
@tologin="toLogin"
|
||||
@selectsku="selectSku($event, index)"
|
||||
@addCart="addCartPoint"
|
||||
@switch="switchOneCategory"
|
||||
></diy-category-item>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</block>
|
||||
<view class="category-empty" v-else>
|
||||
<image :src="$util.img('public/uniapp/category/empty.png')" mode="widthFix"></image>
|
||||
<view class="tips">暂时没有分类哦!</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="cart-box" v-if="(value.template == 2 || value.template == 4) && value.quickBuy && token && categoryTree && categoryTree.length">
|
||||
<view class="left-wrap">
|
||||
<view class="cart-icon" ref="cartIcon" :animation="cartAnimation" @click="$util.redirectTo('/pages/goods/cart')">
|
||||
<text class="iconfont icon-ziyuan1"></text>
|
||||
<view class="num" v-if="cartNumber">{{ cartNumber < 99 ? cartNumber : '99+' }}</view>
|
||||
</view>
|
||||
<view class="price">
|
||||
<text class="title">总计:</text>
|
||||
<text class="unit font-size-tag price-font">¥</text>
|
||||
<text class="money font-size-toolbar price-font">{{ cartMoney[0] }}</text>
|
||||
<text class="unit font-size-tag price-font">.{{ cartMoney[1] ? cartMoney[1] : '00' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="right-wrap"><button type="primary" class="settlement-btn" @click="settlement">去结算</button></view>
|
||||
</view>
|
||||
|
||||
<view class="cart-point" :style="{ left: item.left + 'px', top: item.top + 'px' }" :key="index" v-for="(item, index) in carIconList"></view>
|
||||
|
||||
<ns-goods-sku-category ref="skuSelect" @addCart="addCartPoint"></ns-goods-sku-category>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// 获取系统状态栏的高度
|
||||
let systemInfo = uni.getSystemInfoSync();
|
||||
let menuButtonInfo = {};
|
||||
// 如果是小程序,获取右上角胶囊的尺寸信息,避免导航栏右侧内容与胶囊重叠(支付宝小程序非本API,尚未兼容)
|
||||
// #ifdef MP-WEIXIN || MP-BAIDU || MP-TOUTIAO || MP-QQ
|
||||
menuButtonInfo = uni.getMenuButtonBoundingClientRect();
|
||||
// #endif
|
||||
|
||||
import nsGoodsSkuCategory from '@/components/ns-goods-sku/ns-goods-sku-category.vue';
|
||||
var contentWrapHeight, query, cartPosition;
|
||||
export default {
|
||||
components: { nsGoodsSkuCategory },
|
||||
name: 'diy-category',
|
||||
props: {
|
||||
value: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
oneCategorySelect: 0,
|
||||
select: 0,
|
||||
categoryId: 'category-0',
|
||||
categoryTree: null,
|
||||
scrollLock: false,
|
||||
triggered: true,
|
||||
heightArea: [],
|
||||
isSub: false,
|
||||
token: null,
|
||||
carIconList: {},
|
||||
endTips: 0,
|
||||
cartAnimation: {},
|
||||
loadType: '',
|
||||
templateFourData: []
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getCategoryTree();
|
||||
this.$store.dispatch('getCartNumber');
|
||||
this.token = uni.getStorageSync('token');
|
||||
this.loadType = this.value.goodsLevel == 1 && this.value.loadType == 'all' ? 'all' : 'part';
|
||||
},
|
||||
mounted() {
|
||||
query = uni.createSelectorQuery().in(this);
|
||||
query
|
||||
.select('.content-wrap')
|
||||
.boundingClientRect(data => {
|
||||
if (data) contentWrapHeight = data.height;
|
||||
})
|
||||
.exec();
|
||||
setTimeout(() => {
|
||||
query
|
||||
.select('.end-tips')
|
||||
.boundingClientRect(data => {
|
||||
if (data && data.top > contentWrapHeight) this.endTips = 1;
|
||||
})
|
||||
.exec();
|
||||
query
|
||||
.select('.cart-icon')
|
||||
.boundingClientRect(data => {
|
||||
if (data) cartPosition = data;
|
||||
})
|
||||
.exec();
|
||||
if (this.value.template == 1) this.getHeightArea(-1);
|
||||
}, 500);
|
||||
},
|
||||
computed: {
|
||||
cartMoney() {
|
||||
let cartMoney = parseFloat(this.$store.state.cartMoney).toFixed(2);
|
||||
return cartMoney.split('.');
|
||||
},
|
||||
cartNumber() {
|
||||
return this.$store.state.cartNumber;
|
||||
},
|
||||
// 转换字符数值为真正的数值
|
||||
navbarHeight() {
|
||||
// #ifdef APP-PLUS || H5
|
||||
return 44;
|
||||
// #endif
|
||||
// #ifdef MP
|
||||
// 小程序特别处理,让导航栏高度 = 胶囊高度 + 两倍胶囊顶部与状态栏底部的距离之差(相当于同时获得了导航栏底部与胶囊底部的距离)
|
||||
// 此方法有缺陷,暂不用(会导致少了几个px),采用直接固定值的方式
|
||||
// return menuButtonInfo.height + (menuButtonInfo.top - this.navbarHeight) * 2;//导航高度
|
||||
// let height = systemInfo.platform == 'ios' ? 44 : 48;
|
||||
let height = menuButtonInfo.top;
|
||||
// height += systemInfo.navbarHeight;
|
||||
return height;
|
||||
// #endif
|
||||
},
|
||||
// 导航栏内部盒子的样式
|
||||
navbarInnerStyle() {
|
||||
let style = '';
|
||||
// 导航栏宽度,如果在小程序下,导航栏宽度为胶囊的左边到屏幕左边的距离
|
||||
// style += 'height:' + this.navbarHeight + 'px;';
|
||||
style += 'height:' + menuButtonInfo.height * 2 + 'rpx;';
|
||||
// // 如果是各家小程序,导航栏内部的宽度需要减少右边胶囊的宽度
|
||||
style += 'padding-top:' + this.navbarHeight + 'px;';
|
||||
// #ifdef MP
|
||||
if (this.value.template == 4 && this.value.search) {
|
||||
let rightButtonWidth = menuButtonInfo.width ? menuButtonInfo.width * 2 + 'rpx' : '70rpx';
|
||||
style += 'padding-right:calc(' + rightButtonWidth + ' + 30rpx);';
|
||||
}
|
||||
// #endif
|
||||
if (this.value.template != 4 || (this.value.template == 4 && !this.value.search)) {
|
||||
style += 'text-align: center;';
|
||||
style += 'line-height:' + menuButtonInfo.height * 2 + 'rpx;';
|
||||
style += 'font-size: 24rpx;';
|
||||
style += 'padding-bottom: 10rpx;';
|
||||
}
|
||||
return style;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* 页面显示
|
||||
*/
|
||||
pageShow() {
|
||||
this.$store.dispatch('getCartNumber');
|
||||
this.token = uni.getStorageSync('token');
|
||||
if (!this.heightArea.length) this.getHeightArea(-1);
|
||||
},
|
||||
/**
|
||||
* 获取高度区间
|
||||
*/
|
||||
getHeightArea(index) {
|
||||
let heightArea = [];
|
||||
query
|
||||
.selectAll('.content-wrap .child-category')
|
||||
.boundingClientRect(data => {
|
||||
if (data && data.length) {
|
||||
data.forEach((item, index) => {
|
||||
if (index == 0) heightArea.push([0, item.height]);
|
||||
else heightArea.push([heightArea[index - 1][1], heightArea[index - 1][1] + item.height]);
|
||||
});
|
||||
}
|
||||
})
|
||||
.exec();
|
||||
this.heightArea = heightArea;
|
||||
if (index != -1 && index < this.categoryTree.length - 1) this.$refs.categoryItem[index + 1].getGoodsList();
|
||||
},
|
||||
/**
|
||||
* 获取全部分类
|
||||
*/
|
||||
getCategoryTree() {
|
||||
this.$api.sendRequest({
|
||||
url: '/api/goodscategory/tree',
|
||||
data: {
|
||||
level: 3
|
||||
},
|
||||
success: res => {
|
||||
if (res.code == 0) {
|
||||
this.categoryTree = res.data;
|
||||
if (this.value.template == 4) {
|
||||
this.templateFourData = JSON.parse(JSON.stringify(this.categoryTree));
|
||||
this.categoryTree = this.templateFourData[0].child_list;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
/**
|
||||
* 切换一级分类
|
||||
* @param {Object} index
|
||||
*/
|
||||
switchOneCategory(index) {
|
||||
if (index >= this.categoryTree.length) return;
|
||||
this.select = index;
|
||||
this.categoryId = 'category-' + index;
|
||||
// 阻止切换分类之后滚动事件也立即执行
|
||||
this.scrollLock = true;
|
||||
},
|
||||
touchStart() {
|
||||
this.scrollLock = false;
|
||||
},
|
||||
/**
|
||||
* 监听滚动
|
||||
* @param {Object} event
|
||||
*/
|
||||
listenScroll(event) {
|
||||
if (this.scrollLock) return;
|
||||
let scrollTop = event.detail.scrollTop;
|
||||
if (this.heightArea.length) {
|
||||
for (let i = 0; i < this.heightArea.length; i++) {
|
||||
if (scrollTop >= this.heightArea[i][0] && scrollTop <= this.heightArea[i][1]) {
|
||||
this.select = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (this.value.template != 1 && this.value.loadType == 'all' && this.heightArea[this.select][1] - scrollTop - contentWrapHeight < 300) {
|
||||
this.$refs.categoryItem[this.select].getGoodsList();
|
||||
}
|
||||
}
|
||||
},
|
||||
onRefresh() {
|
||||
this.triggered = false;
|
||||
},
|
||||
onRestore() {
|
||||
this.triggered = 'restore'; // 需要重置
|
||||
},
|
||||
toLogin() {
|
||||
this.$emit('tologin');
|
||||
},
|
||||
/**
|
||||
* sku选择
|
||||
* @param {Object} data
|
||||
* @param {Object} index
|
||||
*/
|
||||
selectSku(data, index) {
|
||||
this.$api.sendRequest({
|
||||
url: '/api/goodssku/getInfoForCategory',
|
||||
data: {
|
||||
sku_id: data.sku_id
|
||||
},
|
||||
success: res => {
|
||||
if (res.code >= 0) {
|
||||
let data = res.data,
|
||||
obj = {};
|
||||
|
||||
let item = res.data;
|
||||
item.unit = item.unit || '件';
|
||||
|
||||
if (item.sku_images) item.sku_images = item.sku_images.split(',');
|
||||
else item.sku_images = [];
|
||||
|
||||
// 多规格时合并主图
|
||||
if (item.goods_spec_format && item.goods_image) {
|
||||
item.goods_image = item.goods_image.split(',');
|
||||
item.sku_images = item.goods_image.concat(item.sku_images);
|
||||
}
|
||||
|
||||
// 当前商品SKU规格
|
||||
if (item.sku_spec_format) item.sku_spec_format = JSON.parse(item.sku_spec_format);
|
||||
|
||||
// 商品SKU格式
|
||||
if (item.goods_spec_format) item.goods_spec_format = JSON.parse(item.goods_spec_format);
|
||||
|
||||
// 限时折扣
|
||||
if (item.promotion_type == 1) {
|
||||
item.discountTimeMachine = this.$util.countDown(item.end_time - res.timestamp);
|
||||
}
|
||||
|
||||
if (item.promotion_type == 1 && item.discountTimeMachine) {
|
||||
if (item.member_price > 0 && Number(item.member_price) <= Number(item.discount_price)) {
|
||||
item.show_price = item.member_price;
|
||||
} else {
|
||||
item.show_price = item.discount_price;
|
||||
}
|
||||
} else if (item.member_price > 0) {
|
||||
item.show_price = item.member_price;
|
||||
} else {
|
||||
item.show_price = item.price;
|
||||
}
|
||||
|
||||
this.$refs.skuSelect.show('join_cart', item, () => {});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
settlement() {
|
||||
let cartList = Object.keys(this.$store.state.cartList),
|
||||
cartIds = [];
|
||||
if (!cartList.length || this.isSub) return;
|
||||
this.isSub = true;
|
||||
|
||||
cartList.forEach(key => {
|
||||
cartIds.push(this.$store.state.cartList[key].cart_id);
|
||||
});
|
||||
|
||||
uni.removeStorageSync('delivery');
|
||||
uni.setStorage({
|
||||
key: 'orderCreateData',
|
||||
data: {
|
||||
cart_ids: cartIds.toString()
|
||||
},
|
||||
success: () => {
|
||||
this.$util.redirectTo('/pages/order/payment');
|
||||
this.isSub = false;
|
||||
}
|
||||
});
|
||||
},
|
||||
/**
|
||||
* 添加点
|
||||
* @param {Object} left
|
||||
* @param {Object} top
|
||||
*/
|
||||
addCartPoint(left, top) {
|
||||
if (this.value.template != 2 && !this.value.quickBuy) return;
|
||||
|
||||
let key = new Date().getTime();
|
||||
this.$set(this.carIconList, key, {
|
||||
left: left,
|
||||
top: top,
|
||||
index: 0,
|
||||
bezierPos: this.$util.bezier([{ x: left, y: top }, { x: left - 200, y: left - 120 }, { x: cartPosition.left + 10, y: cartPosition.top }], 6).bezier_points,
|
||||
timer: null
|
||||
});
|
||||
this.startAnimation(key);
|
||||
},
|
||||
/**
|
||||
* 执行动画
|
||||
* @param {Object} key
|
||||
*/
|
||||
startAnimation(key) {
|
||||
let bezierPos = this.carIconList[key].bezierPos,
|
||||
index = this.carIconList[key].index;
|
||||
|
||||
this.carIconList[key].timer = setInterval(() => {
|
||||
if (index < 6) {
|
||||
this.carIconList[key].left = bezierPos[index].x;
|
||||
this.carIconList[key].top = bezierPos[index].y;
|
||||
index++;
|
||||
} else {
|
||||
clearInterval(this.carIconList[key].timer);
|
||||
delete this.carIconList[key];
|
||||
this.$forceUpdate();
|
||||
|
||||
// 购物车图标
|
||||
setTimeout(() => {
|
||||
this.$store.commit('setCartChange');
|
||||
}, 100);
|
||||
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);
|
||||
}
|
||||
}, 50);
|
||||
},
|
||||
// 风格四头部切换
|
||||
templateFourOneFn(index) {
|
||||
this.categoryTree = this.templateFourData[index].child_list || [];
|
||||
this.oneCategorySelect = index;
|
||||
this.select = 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.category-page-wrap {
|
||||
width: 100vw;
|
||||
height: calc(100vh - var(--tab-bar-height, 0));
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.content-box {
|
||||
flex: 1;
|
||||
height: 0;
|
||||
display: flex;
|
||||
|
||||
.tree-wrap {
|
||||
width: 170rpx;
|
||||
height: 100%;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.right-flex-wrap {
|
||||
flex: 1;
|
||||
width: 0;
|
||||
height: 100%;
|
||||
background: #fff;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
transform: translateX(0px);
|
||||
|
||||
.content-wrap {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
height: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.child-category-wrap {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
.tree-wrap .category-item-wrap {
|
||||
height: auto;
|
||||
background-color: #fff;
|
||||
}
|
||||
.tree-wrap .category-item {
|
||||
line-height: 1.5;
|
||||
padding: 26rpx 28rpx;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
background-color: #f5f5f5;
|
||||
|
||||
view {
|
||||
color: #222222;
|
||||
width: 100%;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
}
|
||||
&.border-top {
|
||||
border-bottom-right-radius: 12rpx;
|
||||
}
|
||||
&.border-bottom {
|
||||
border-top-right-radius: 12rpx;
|
||||
}
|
||||
&.select {
|
||||
background: #fff;
|
||||
view {
|
||||
color: #333;
|
||||
font-weight: bold;
|
||||
}
|
||||
&::before {
|
||||
content: ' ';
|
||||
width: 8rpx;
|
||||
height: 34rpx;
|
||||
background: var(--base-color);
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.search-box {
|
||||
position: relative;
|
||||
padding: 20rpx 30rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: #fff;
|
||||
|
||||
.search-content {
|
||||
position: relative;
|
||||
height: 70rpx;
|
||||
border-radius: 40rpx;
|
||||
flex: 1;
|
||||
background-color: #f5f5f5;
|
||||
|
||||
input {
|
||||
box-sizing: border-box;
|
||||
display: block;
|
||||
height: 70rpx;
|
||||
width: 100%;
|
||||
padding: 0 20rpx 0 40rpx;
|
||||
background: #f5f5f5;
|
||||
color: #333;
|
||||
border-radius: 40rpx;
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: 10rpx;
|
||||
transform: translateY(-50%);
|
||||
font-size: $font-size-toolbar;
|
||||
z-index: 10;
|
||||
color: #89899a;
|
||||
width: 80rpx;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.cart-box {
|
||||
height: 100rpx;
|
||||
width: 100%;
|
||||
background: #fff;
|
||||
border-top: 1px solid #f5f5f5;
|
||||
box-sizing: border-box;
|
||||
padding: 0 30rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
.left-wrap {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.cart-icon {
|
||||
width: 70rpx;
|
||||
height: 70rpx;
|
||||
position: relative;
|
||||
|
||||
.iconfont {
|
||||
color: var(--btn-text-color);
|
||||
width: inherit;
|
||||
height: inherit;
|
||||
background-color: $base-color;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.num {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
transform: translate(60%, 0);
|
||||
display: inline-block;
|
||||
box-sizing: border-box;
|
||||
color: #fff;
|
||||
line-height: 1.2;
|
||||
text-align: center;
|
||||
font-size: 24rpx;
|
||||
padding: 0 6rpx;
|
||||
min-width: 30rpx;
|
||||
border-radius: 16rpx;
|
||||
background-color: var(--price-color);
|
||||
border: 2rpx solid #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.price {
|
||||
margin-left: 30rpx;
|
||||
|
||||
.title {
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.money,
|
||||
.unit {
|
||||
font-weight: bold;
|
||||
color: var(--price-color);
|
||||
}
|
||||
}
|
||||
|
||||
.settlement-btn {
|
||||
margin: 0 0 0 20rpx;
|
||||
width: 200rpx;
|
||||
font-weight: bold;
|
||||
border-radius: 50rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.cart-point {
|
||||
width: 26rpx;
|
||||
height: 26rpx;
|
||||
position: fixed;
|
||||
z-index: 1000;
|
||||
background: #f00;
|
||||
border-radius: 50%;
|
||||
transition: all 0.05s;
|
||||
}
|
||||
|
||||
.category-empty {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
|
||||
image {
|
||||
width: 380rpx;
|
||||
}
|
||||
|
||||
.tips {
|
||||
font-size: 26rpx;
|
||||
font-weight: 500;
|
||||
color: #999;
|
||||
margin-top: 50rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.end-tips {
|
||||
text-align: center;
|
||||
color: #999;
|
||||
font-size: 24rpx;
|
||||
padding: 20rpx 0;
|
||||
opacity: 0;
|
||||
}
|
||||
// 风格四
|
||||
.category-template-4 {
|
||||
.search-box {
|
||||
background-color: #f0f5ff;
|
||||
.search-content input {
|
||||
background-color: #fff;
|
||||
}
|
||||
}
|
||||
.cart-box {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
/deep/ .template-four {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
&:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: 20rpx;
|
||||
height: 4rpx;
|
||||
left: 0;
|
||||
right: 0;
|
||||
box-shadow: 0 20rpx 14rpx rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
.template-four-wrap {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
padding-left: 20rpx;
|
||||
padding-right: 80rpx;
|
||||
padding-bottom: 10rpx;
|
||||
display: flex;
|
||||
height: 180rpx;
|
||||
align-items: baseline;
|
||||
box-sizing: border-box;
|
||||
background-image: linear-gradient(#f0f5ff 45%, #fff);
|
||||
}
|
||||
|
||||
.template-four-popup {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
.title {
|
||||
line-height: 1;
|
||||
margin-bottom: 20rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
.template-four-scroll {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: baseline;
|
||||
align-content: baseline;
|
||||
white-space: break-spaces;
|
||||
padding: 20rpx;
|
||||
white-space: nowrap;
|
||||
height: 380rpx;
|
||||
box-sizing: border-box;
|
||||
.uni-scroll-view-content {
|
||||
flex-wrap: wrap;
|
||||
align-items: baseline;
|
||||
align-content: baseline;
|
||||
}
|
||||
.item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 4rpx 0;
|
||||
color: #666;
|
||||
margin-right: 16rpx;
|
||||
border-radius: 40rpx;
|
||||
margin-bottom: 10rpx;
|
||||
width: calc((100% - 64rpx) / 5);
|
||||
&:nth-child(5n + 5) {
|
||||
margin-right: 0;
|
||||
}
|
||||
.image-warp {
|
||||
margin-bottom: 6rpx;
|
||||
padding: 4rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 42rpx;
|
||||
border: 4rpx solid transparent;
|
||||
}
|
||||
image {
|
||||
width: 84rpx;
|
||||
height: 84rpx;
|
||||
border-radius: 32rpx;
|
||||
}
|
||||
.text {
|
||||
padding: 2rpx 16rpx;
|
||||
border-radius: 40rpx;
|
||||
font-size: $font-size-tag;
|
||||
}
|
||||
&.selected {
|
||||
.text {
|
||||
background-color: $base-color;
|
||||
color: var(--btn-text-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.pack-up {
|
||||
font-size: $font-size-tag;
|
||||
color: #888888;
|
||||
height: 74rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-top: 2rpx solid #f2f2f2;
|
||||
.iconfont {
|
||||
font-size: 40rpx;
|
||||
margin-left: -4rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
.category-item-all {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
z-index: 1;
|
||||
right: 0;
|
||||
top: 0;
|
||||
width: 72rpx;
|
||||
line-height: 1;
|
||||
.category-item-all-wrap {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 2;
|
||||
background-image: linear-gradient(#f0f5ff 45%, #fff);
|
||||
}
|
||||
|
||||
.text {
|
||||
writing-mode: tb-rl;
|
||||
margin-bottom: 6rpx;
|
||||
letter-spacing: 4rpx;
|
||||
font-size: $font-size-tag;
|
||||
font-weight: bold;
|
||||
}
|
||||
.img {
|
||||
width: 20rpx;
|
||||
height: 20rpx;
|
||||
}
|
||||
&::after {
|
||||
content: '';
|
||||
box-shadow: -4rpx 10rpx 20rpx rgba(0, 0, 0, 0.1);
|
||||
position: absolute;
|
||||
left: 0;
|
||||
width: 10rpx;
|
||||
// height: 100rpx;
|
||||
top: 20%;
|
||||
bottom: 20%;
|
||||
background-image: linear-gradient(#f0f5ff 45%, #fff);
|
||||
// transform: translateY(-50%);
|
||||
// background-color: #F0F5FF;
|
||||
}
|
||||
}
|
||||
.uni-scroll-view-content {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.category-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-width: 130rpx;
|
||||
flex-shrink: 0;
|
||||
margin-right: 20rpx;
|
||||
padding: 4rpx 0;
|
||||
&:last-of-type {
|
||||
margin-right: 0;
|
||||
}
|
||||
.image-warp {
|
||||
margin-bottom: 6rpx;
|
||||
padding: 4rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 42rpx;
|
||||
border: 4rpx solid transparent;
|
||||
}
|
||||
image {
|
||||
width: 84rpx;
|
||||
height: 84rpx;
|
||||
border-radius: 32rpx;
|
||||
}
|
||||
}
|
||||
.select {
|
||||
.text {
|
||||
padding: 8rpx 16rpx;
|
||||
border-radius: 40rpx;
|
||||
color: #fff;
|
||||
font-size: $font-size-tag;
|
||||
line-height: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
.content-wrap .categoty-goods-wrap .goods-list {
|
||||
margin-top: 30rpx;
|
||||
}
|
||||
|
||||
.tree-wrap .category-item.select::before {
|
||||
border-top-right-radius: 8rpx;
|
||||
border-bottom-right-radius: 8rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
<template>
|
||||
<view></view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// 自定义扩展组件
|
||||
export default {
|
||||
name: 'diy-comp-extend',
|
||||
props: {
|
||||
value: {
|
||||
type: Object
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
computed: {},
|
||||
created() {},
|
||||
methods: {}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style></style>
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,419 @@
|
|||
<template>
|
||||
<view class="diy-fenxiao" v-if="list.length" :class="['goods-list', value.template, value.style]" :style="goodsListWarpCss">
|
||||
<view class="goods-item" v-for="(item, index) in list" :key="index" @click="toDetail(item)" :class="[value.ornament.type]" :style="goodsItemCss">
|
||||
<view class="goods-img" :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }">
|
||||
<image :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }" :src="$util.img(item.goods_image,{size: 'mid'})" mode="widthFix" @error="imgError(index)"></image>
|
||||
</view>
|
||||
<view class="info-wrap" v-if="value.goodsNameStyle.control || value.priceStyle.mainControl || value.priceStyle.lineControl || value.btnStyle.control">
|
||||
<view class="name-wrap">
|
||||
<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>
|
||||
<view class="pro-info">
|
||||
<view class="discount-price">
|
||||
<view class="price-wrap" v-if="value.priceStyle.mainControl">
|
||||
<text class="unit price-style small" :style="{ color: value.theme == 'diy' ? value.priceStyle.mainColor : '' }">赚 ¥</text>
|
||||
<text class="price price-style large" :style="{ color: value.theme == 'diy' ? value.priceStyle.mainColor : '' }">{{ item.commission_money.split(".")[0] }}</text>
|
||||
<text class="unit price-style small" :style="{ color: value.theme == 'diy' ? value.priceStyle.mainColor : '' }">{{ "."+item.commission_money.split(".")[1] }}</text>
|
||||
</view>
|
||||
<view
|
||||
class="sale-btn"
|
||||
v-if="value.btnStyle.control && item.is_collect == 0"
|
||||
: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'
|
||||
}"
|
||||
@click.stop="followGoods(item, index)"
|
||||
>
|
||||
关注
|
||||
</view>
|
||||
<view
|
||||
class="sale-btn"
|
||||
v-if="value.btnStyle.control && item.is_collect == 1"
|
||||
: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'
|
||||
}"
|
||||
@click.stop="delFollowTip(item, index)"
|
||||
>
|
||||
取消关注
|
||||
</view>
|
||||
</view>
|
||||
<view class="delete-price" v-if="value.priceStyle.lineControl" :style="{ color: value.theme == 'diy' ? value.priceStyle.lineColor : '' }">
|
||||
¥{{ item.discount_price }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'diy-fenxiao-goods-list',
|
||||
props: {
|
||||
value: {
|
||||
type: Object
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
list: [],
|
||||
currentRoute: ''
|
||||
};
|
||||
},
|
||||
created() {
|
||||
let currentPage = getCurrentPages()[getCurrentPages().length - 1];
|
||||
this.currentRoute = '/' + currentPage.route;
|
||||
if (!uni.getStorageSync('token')) {
|
||||
this.$util.redirectTo(
|
||||
'/pages_tool/login/login',
|
||||
{
|
||||
back: this.currentRoute
|
||||
},
|
||||
'redirectTo'
|
||||
);
|
||||
}
|
||||
this.getData();
|
||||
},
|
||||
computed: {
|
||||
goodsListWarpCss() {
|
||||
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;
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
//页面跳转
|
||||
toDetail(e) {
|
||||
this.$util.redirectTo('/pages/goods/detail', { goods_id: e.goods_id });
|
||||
},
|
||||
//关注
|
||||
followGoods(e, index) {
|
||||
let goods_id = e.goods_id;
|
||||
let sku_id = e.sku_id;
|
||||
this.$api.sendRequest({
|
||||
url: '/fenxiao/api/goodscollect/add',
|
||||
data: {
|
||||
goods_id: goods_id,
|
||||
sku_id: sku_id
|
||||
},
|
||||
success: res => {
|
||||
if (res.code >= 0) {
|
||||
this.$util.showToast({ title: '关注成功' });
|
||||
this.list[index].is_collect = 1;
|
||||
this.list[index].collect_id = res.data;
|
||||
}
|
||||
this.$forceUpdate();
|
||||
}
|
||||
});
|
||||
},
|
||||
//取消关注
|
||||
delFollowTip(e, index) {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '确认取消关注该商品吗',
|
||||
success: res => {
|
||||
if (res.confirm) {
|
||||
this.delFollow(e.collect_id, index);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
delFollow(e, f) {
|
||||
this.$api.sendRequest({
|
||||
url: '/fenxiao/api/goodscollect/delete',
|
||||
data: {
|
||||
collect_id: e
|
||||
},
|
||||
success: res => {
|
||||
let msg = '';
|
||||
if (res.code == 0) {
|
||||
msg = '取消成功';
|
||||
} else {
|
||||
msg = res.message;
|
||||
}
|
||||
this.$util.showToast({
|
||||
title: msg
|
||||
});
|
||||
|
||||
let arr = this.list;
|
||||
arr[f].is_collect = 0;
|
||||
this.list = arr;
|
||||
this.$forceUpdate();
|
||||
}
|
||||
});
|
||||
},
|
||||
toMore() {
|
||||
this.$util.redirectTo('/pages_promotion/fenxiao/goods_list');
|
||||
},
|
||||
getData() {
|
||||
var data = {
|
||||
page: 1,
|
||||
page_size: this.value.count
|
||||
};
|
||||
if (this.value.sources == 'category') {
|
||||
data.category_id = this.value.categoryId;
|
||||
data.category_level = 1;
|
||||
} else if (this.value.sources == 'diy') {
|
||||
data.page_size = 0;
|
||||
data.goods_id_arr = this.value.goodsId.toString();
|
||||
}
|
||||
this.$api.sendRequest({
|
||||
url: '/fenxiao/api/goods/page',
|
||||
data: data,
|
||||
success: res => {
|
||||
if (res.code == 0) {
|
||||
this.list = res.data.list;
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
imgError(index) {
|
||||
if (this.list[index]) this.list[index].goods_image = this.$util.getDefaultImage().goods;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.diy-fenxiao {
|
||||
}
|
||||
|
||||
// 商品列表单列样式
|
||||
.goods-list.row1-of1 {
|
||||
.goods-item {
|
||||
background-color: #fff;
|
||||
display: flex;
|
||||
margin-bottom: 20rpx;
|
||||
&:last-of-type {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
&.shadow {
|
||||
margin: 8rpx 8rpx 20rpx 8rpx;
|
||||
}
|
||||
|
||||
.goods-img {
|
||||
width: 180rpx;
|
||||
overflow: hidden;
|
||||
margin-right: 20rpx;
|
||||
image {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.info-wrap {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
position: relative;
|
||||
|
||||
.name-wrap {
|
||||
flex: 1;
|
||||
margin-bottom: 10rpx;
|
||||
.goods-name {
|
||||
font-size: $font-size-base;
|
||||
line-height: 1.3;
|
||||
&.multi-hidden {
|
||||
height: 72rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.pro-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
.sale {
|
||||
font-size: 20rpx;
|
||||
line-height: 1;
|
||||
color: #999;
|
||||
}
|
||||
.discount-price {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 10rpx;
|
||||
.price-wrap {
|
||||
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 {
|
||||
text-decoration: line-through;
|
||||
flex: 1;
|
||||
line-height: 28rpx;
|
||||
color: $color-tip;
|
||||
font-size: $font-size-activity-tag;
|
||||
}
|
||||
}
|
||||
.sale-btn {
|
||||
position: absolute;
|
||||
right: 20rpx;
|
||||
bottom: 26rpx;
|
||||
height: 50rpx;
|
||||
line-height: 52rpx;
|
||||
color: #fff;
|
||||
width: 120rpx;
|
||||
text-align: center;
|
||||
background-color: $base-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 商品列表两列样式
|
||||
.goods-list.row1-of2 {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
.goods-item {
|
||||
position: relative;
|
||||
background: #fff;
|
||||
overflow: hidden;
|
||||
margin-right: 20rpx;
|
||||
margin-top: 20rpx;
|
||||
width: calc(50% - 10rpx);
|
||||
&:nth-child(2n+2) {
|
||||
width: calc(50% - 11rpx);
|
||||
margin-right: 0;
|
||||
}
|
||||
&:nth-of-type(1),
|
||||
&:nth-of-type(2) {
|
||||
margin-top: 0;
|
||||
}
|
||||
&.shadow {
|
||||
width: calc(50% - 18rpx);
|
||||
&:nth-child(2n-1) {
|
||||
margin-left: 8rpx;
|
||||
}
|
||||
&:nth-of-type(1),
|
||||
&:nth-of-type(2) {
|
||||
margin-top: 8rpx;
|
||||
}
|
||||
}
|
||||
.goods-img {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
height: 350rpx;
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
top: 49%;
|
||||
left: 0;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
}
|
||||
|
||||
.info-wrap {
|
||||
padding: 10rpx 20rpx;
|
||||
|
||||
.name-wrap {
|
||||
margin-bottom: 10rpx;
|
||||
.goods-name {
|
||||
font-size: $font-size-base;
|
||||
line-height: 1.3;
|
||||
&.multi-hidden {
|
||||
height: 72rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.pro-info {
|
||||
margin-top: 10rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
.sale {
|
||||
font-size: 20rpx;
|
||||
line-height: 1;
|
||||
color: #999;
|
||||
}
|
||||
.discount-price {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
.price-wrap {
|
||||
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 {
|
||||
text-decoration: line-through;
|
||||
flex: 1;
|
||||
line-height: 28rpx;
|
||||
color: $color-tip;
|
||||
font-size: $font-size-activity-tag;
|
||||
}
|
||||
}
|
||||
.sale-btn {
|
||||
position: absolute;
|
||||
right: 20rpx;
|
||||
bottom: 26rpx;
|
||||
height: 50rpx;
|
||||
line-height: 52rpx;
|
||||
color: #fff;
|
||||
width: 120rpx;
|
||||
text-align: center;
|
||||
background-color: $base-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -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>
|
||||
|
|
@ -0,0 +1,135 @@
|
|||
<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">
|
||||
<view class="li-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>
|
||||
</view>
|
||||
</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('/pages/goods/list', {
|
||||
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 {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
padding: 20rpx;
|
||||
|
||||
.li-item{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: calc(100% / 4 - 20rpx) !important;
|
||||
height: 124rpx;
|
||||
margin: 10rpx;
|
||||
background-color: #fff;
|
||||
.brand-pic {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,438 @@
|
|||
<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.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 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>
|
||||
export default {
|
||||
name: 'diy-goods-recommend',
|
||||
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 = {
|
||||
num: this.goodsValue.count
|
||||
};
|
||||
if (this.goodsValue.sources == 'category') {
|
||||
data.category_id = this.goodsValue.categoryId;
|
||||
data.category_level = 1;
|
||||
} else if (this.goodsValue.sources == 'diy') {
|
||||
data.num = 0;
|
||||
data.goods_id_arr = this.goodsValue.goodsId.toString();
|
||||
}
|
||||
data.order = this.goodsValue.sortWay;
|
||||
|
||||
this.$api.sendRequest({
|
||||
url: '/api/goodssku/components',
|
||||
data: data,
|
||||
success: res => {
|
||||
if (res.code == 0 && res.data) {
|
||||
let data = res.data;
|
||||
this.list = data;
|
||||
|
||||
// 切屏滚动,每页显示固定数量
|
||||
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('/pages/goods/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;
|
||||
&.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>
|
||||
|
|
@ -0,0 +1,317 @@
|
|||
<template>
|
||||
<view :style="componentStyle">
|
||||
<block v-if="value.showStyle == 'pageSlide'">
|
||||
<swiper :class="['graphic-nav', 'pageSlide', value.carousel.type]" circular :indicator-dots="false" :style="swiperHeight" @change="swiperChange">
|
||||
<swiper-item class="graphic-nav-wrap" v-for="(numItem, numIndex) in Math.ceil(value.list.length / (value.pageCount * value.rowCount))">
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<view
|
||||
class="graphic-nav-item"
|
||||
v-for="(item, index) in value.list"
|
||||
:key="index"
|
||||
v-if="index >= [(numItem) * (value.pageCount * value.rowCount)] && index < [(numItem+1) * (value.pageCount * value.rowCount)]"
|
||||
:style="{ width: 100 / value.rowCount + '%' }"
|
||||
@click="redirectTo(item.link)"
|
||||
>
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef H5 -->
|
||||
<view
|
||||
class="graphic-nav-item"
|
||||
v-for="(item, index) in value.list"
|
||||
:key="index"
|
||||
v-if="index >= [(numItem - 1) * (value.pageCount * value.rowCount)] && index < [numItem * (value.pageCount * value.rowCount)]"
|
||||
:style="{ width: 100 / value.rowCount + '%' }"
|
||||
@click="redirectTo(item.link)"
|
||||
>
|
||||
<!-- #endif -->
|
||||
<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"
|
||||
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>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
|
||||
<view class="swiper-dot-box" v-if="isIndicatorDots" :class="value.carousel.type">
|
||||
<view v-for="(numItem, numIndex) in Math.ceil(value.list.length / (value.pageCount * value.rowCount))" :key="numIndex">
|
||||
<view class="swiper-dot" :class="{'active':numIndex==swiperCurrent}" ></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</block>
|
||||
<scroll-view v-else :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>
|
||||
<ns-login ref="login"></ns-login>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'diy-graphic-nav',
|
||||
props: {
|
||||
value: {
|
||||
type: Object
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
pageWidth: '',
|
||||
indicatorDots: false,
|
||||
swiperCurrent:0
|
||||
};
|
||||
},
|
||||
created() {
|
||||
},
|
||||
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) {
|
||||
if (link.wap_url) {
|
||||
if (this.$util.getCurrRoute() == 'pages/member/index' && !uni.getStorageSync('token')) {
|
||||
this.$refs.login.open(link.wap_url);
|
||||
return;
|
||||
}
|
||||
}
|
||||
this.$util.diyRedirectTo(link);
|
||||
},
|
||||
swiperChange(e){
|
||||
this.swiperCurrent = e.detail.current
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style>
|
||||
|
||||
/* 固定显示 */
|
||||
.graphic-nav.fixed >>> .uni-scroll-view-content {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
/* 单行滑动 */
|
||||
.graphic-nav.singleSlide >>> .uni-scroll-view-content {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.graphic-nav.pageSlide >>> .uni-swiper-dots-horizontal {
|
||||
bottom: 0rpx;
|
||||
}
|
||||
|
||||
.graphic-nav.pageSlide.straightLine >>> .uni-swiper-dot {
|
||||
width: 30rpx;
|
||||
border-radius: 0;
|
||||
height: 8rpx;
|
||||
}
|
||||
|
||||
.graphic-nav.pageSlide.circle >>> .uni-swiper-dot {
|
||||
width: 14rpx;
|
||||
height: 14rpx;
|
||||
}
|
||||
|
||||
</style>
|
||||
<style lang="scss">
|
||||
|
||||
|
||||
.graphic-nav {
|
||||
padding: 16rpx;
|
||||
box-sizing: border-box;
|
||||
&.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,.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>
|
||||
|
|
@ -0,0 +1,268 @@
|
|||
<template>
|
||||
<view class="diy-group">
|
||||
<view v-for="(item, index) in diyGlobalData.value" :key="index" :style="item.pageStyle">
|
||||
<view v-if="addonIsExist.store && showStore && item.componentName == 'StoreShow'">
|
||||
<!-- 门店展示 -->
|
||||
<diy-store :storeId="storeId" :value="item"></diy-store>
|
||||
</view>
|
||||
|
||||
<template v-if="addonIsExist.store && item.componentName == 'StoreInfo'">
|
||||
<!-- 门店详情 -->
|
||||
<diy-store-info :value="item" :storeId="storeId"></diy-store-info>
|
||||
</template>
|
||||
|
||||
<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="!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'">
|
||||
<!-- 富文本 -->
|
||||
<diy-rich-text :value="item"></diy-rich-text>
|
||||
</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 :value="item"></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"></diy-video>
|
||||
</template>
|
||||
|
||||
<template v-if="item.componentName == 'Seckill' && addonIsExist.seckill">
|
||||
<!-- 秒杀 -->
|
||||
<diy-seckill :value="item"></diy-seckill>
|
||||
</template>
|
||||
|
||||
<template v-if="item.componentName == 'Pintuan' && addonIsExist.pintuan">
|
||||
<!-- 拼团 -->
|
||||
<diy-pintuan :value="item"></diy-pintuan>
|
||||
</template>
|
||||
|
||||
<template v-if="item.componentName == 'Groupbuy' && addonIsExist.groupbuy">
|
||||
<!-- 团购 -->
|
||||
<diy-groupbuy :value="item"></diy-groupbuy>
|
||||
</template>
|
||||
|
||||
<!-- 拼团返利 -->
|
||||
<template v-if="item.componentName == 'Pinfan' && addonIsExist.pinfan">
|
||||
<diy-pinfan :value="item"></diy-pinfan>
|
||||
</template>
|
||||
|
||||
<template v-if="item.componentName == 'Bargain' && addonIsExist.bargain">
|
||||
<!-- 砍价 -->
|
||||
<diy-bargain :value="item"></diy-bargain>
|
||||
</template>
|
||||
|
||||
<template v-if="item.componentName == 'Presale' && addonIsExist.bargain">
|
||||
<!-- 预售 -->
|
||||
<diy-presale :value="item"></diy-presale>
|
||||
</template>
|
||||
|
||||
<template v-if="item.componentName == 'Notes' && addonIsExist.notes">
|
||||
<!-- 店铺笔记 -->
|
||||
<diy-notes :value="item"></diy-notes>
|
||||
</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 == 'LiveInfo'">
|
||||
<!-- 小程序直播 -->
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<diy-live :value="item"></diy-live>
|
||||
<!-- #endif -->
|
||||
</template>
|
||||
|
||||
<template v-if="item.componentName == 'FenxiaoGoodsList'">
|
||||
<!-- 分销商品 -->
|
||||
<diy-fenxiao-goods-list :value="item"></diy-fenxiao-goods-list>
|
||||
</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>
|
||||
|
||||
<!-- 自定义扩展组件 -->
|
||||
<diy-comp-extend :value="item"></diy-comp-extend>
|
||||
</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
|
||||
};
|
||||
},
|
||||
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();
|
||||
}
|
||||
},
|
||||
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' + ';';
|
||||
}
|
||||
});
|
||||
},
|
||||
// 刷新数据
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.diy-group {
|
||||
width: 100%;
|
||||
}
|
||||
// .diy-goods-level-wrap {
|
||||
// position: relative;
|
||||
// height: 60vh;
|
||||
// }
|
||||
</style>
|
||||
|
|
@ -0,0 +1,412 @@
|
|||
<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 = {
|
||||
num: this.value.count
|
||||
};
|
||||
if (this.value.sources == 'diy') {
|
||||
data.num = 0;
|
||||
data.goods_id_arr = this.value.goodsId.toString();
|
||||
}
|
||||
this.$api.sendRequest({
|
||||
url: '/groupbuy/api/goods/lists',
|
||||
data: data,
|
||||
success: res => {
|
||||
if (res.code == 0) {
|
||||
this.list = res.data;
|
||||
|
||||
// 切屏滚动,每页显示固定数量
|
||||
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;
|
||||
&.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>
|
||||
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
@ -0,0 +1,329 @@
|
|||
<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="$util.diyRedirectTo(imgAdsValue.list[0].link)">
|
||||
<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>
|
||||
<swiper
|
||||
v-else
|
||||
class="swiper"
|
||||
:style="{ height: swiperHeight }"
|
||||
:class="{
|
||||
'swiper-left': imgAdsValue.indicatorLocation == 'left',
|
||||
'swiper-right': imgAdsValue.indicatorLocation == 'right',
|
||||
'ns-indicator-dots': imgAdsValue.carouselStyle == 'line'
|
||||
}"
|
||||
autoplay="true"
|
||||
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="$util.diyRedirectTo(item.link)"
|
||||
>
|
||||
<view class="item" :style="{ height: item.imgHeight }">
|
||||
<image :src="$util.img(item.imageUrl)" mode="aspectFill"></image>
|
||||
<!-- 热区功能 -->
|
||||
<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 -->
|
||||
<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;
|
||||
},
|
||||
calcSingleRow() {
|
||||
let maxHeight = 0;
|
||||
|
||||
// 深拷贝一层数据,防止数据更改越权
|
||||
this.imgAdsValue = JSON.parse(JSON.stringify(this.value));
|
||||
this.imgAdsValue.list.forEach((item, index) => {
|
||||
uni.getSystemInfo({
|
||||
success: res => {
|
||||
var ratio = item.imgHeight / item.imgWidth;
|
||||
item.imgWidth = res.windowWidth;
|
||||
item.imgWidth -= this.value.margin.both * 2;
|
||||
item.imgHeight = item.imgWidth * ratio;
|
||||
}
|
||||
});
|
||||
|
||||
// 获取最大高度
|
||||
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
|
||||
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>
|
||||
|
|
@ -0,0 +1,693 @@
|
|||
<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('/pages/goods/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('/pages/goods/list', { 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>
|
||||
|
|
@ -0,0 +1,235 @@
|
|||
<template>
|
||||
<view v-if="liveInfo && liveInfo.roomid != undefined">
|
||||
<view class="live-wrap" @click="entryRoom(liveInfo.roomid)">
|
||||
<view class="banner-wrap">
|
||||
<image
|
||||
:src="liveInfo.banner != '' ? $util.img(liveInfo.banner) : $util.img('public/uniapp/live/live_default_banner.png')"
|
||||
mode="widthFix"
|
||||
@error="liveInfo.banner = $util.img('public/uniapp/live/live_default_banner.png')"
|
||||
></image>
|
||||
<view class="shade"></view>
|
||||
<view class="wrap">
|
||||
<view class="room-name">
|
||||
<text class="status-name font-size-base" :class="{ 'color-base-bg': liveInfo.live_status == '101' }">
|
||||
<text class="iconfont icon-zhibozhong font-size-sub" v-if="liveInfo.live_status == '101'"></text>
|
||||
<text class="iconfont icon-zhibojieshu font-size-sub" v-else></text>
|
||||
{{ liveInfo.status_name }}
|
||||
</text>
|
||||
{{ liveInfo.name }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="room-info" v-if="value.isShowAnchorInfo || value.isShowLiveGood">
|
||||
<block v-if="value.isShowAnchorInfo">
|
||||
<image
|
||||
:src="liveInfo.anchor_img != '' ? $util.img(liveInfo.anchor_img) : $util.getDefaultImage().head"
|
||||
class="anchor-img"
|
||||
@error="liveInfo.anchor_img = $util.getDefaultImage().head"
|
||||
></image>
|
||||
<text class="anchor-name">主播:{{ liveInfo.anchor_name }}</text>
|
||||
</block>
|
||||
<text class="separate" v-if="value.isShowAnchorInfo && value.isShowLiveGood">|</text>
|
||||
<block v-if="value.isShowLiveGood">
|
||||
<text class="goods-text">直播商品:{{ liveInfo.goods.length }}</text>
|
||||
</block>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// 直播
|
||||
export default {
|
||||
components: {},
|
||||
name: 'diy-live',
|
||||
props: {
|
||||
value: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
liveInfo: {
|
||||
banner: '',
|
||||
anchor_img: ''
|
||||
}
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getLiveInfo();
|
||||
},
|
||||
methods: {
|
||||
getLiveInfo() {
|
||||
this.$api.sendRequest({
|
||||
url: '/live/api/live/info',
|
||||
success: res => {
|
||||
if (res.code == 0 && res.data) {
|
||||
this.liveInfo = res.data;
|
||||
this.getLiveStatus();
|
||||
} else {
|
||||
this.liveInfo = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
entryRoom(roomId) {
|
||||
// #ifdef MP-WEIXIN
|
||||
wx.navigateTo({
|
||||
url: `plugin-private://wx2b03c6e691cd7370/pages/live-player-plugin?room_id=${roomId}`
|
||||
});
|
||||
// #endif
|
||||
},
|
||||
getLiveStatus() {
|
||||
// #ifdef MP-WEIXIN
|
||||
let livePlayer = requirePlugin('live-player-plugin');
|
||||
|
||||
livePlayer
|
||||
.getLiveStatus({ room_id: this.liveInfo.roomid })
|
||||
.then(res => {
|
||||
const liveStatus = res.liveStatus;
|
||||
if (liveStatus && liveStatus != this.liveInfo.live_status) {
|
||||
this.changeLiveStatus(liveStatus);
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
console.log('get live status', err);
|
||||
});
|
||||
|
||||
// 往后间隔1分钟或更慢的频率去轮询获取直播状态
|
||||
var timer = setInterval(() => {
|
||||
livePlayer
|
||||
.getLiveStatus({ room_id: this.liveInfo.roomid })
|
||||
.then(res => {
|
||||
const liveStatus = res.liveStatus;
|
||||
if (liveStatus && liveStatus != this.liveInfo.live_status) {
|
||||
this.changeLiveStatus(liveStatus);
|
||||
}
|
||||
if (this.$util.inArray(liveStatus, [103, 104, 106, 107])) {
|
||||
clearInterval(timer);
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
console.log('get live status', err);
|
||||
});
|
||||
}, 60000);
|
||||
// #endif
|
||||
},
|
||||
changeLiveStatus(status) {
|
||||
this.$api.sendRequest({
|
||||
url: '/live/api/live/modifyLiveStatus',
|
||||
data: {
|
||||
room_id: this.liveInfo.roomid,
|
||||
status: status
|
||||
},
|
||||
success: res => {
|
||||
if (res.code == 0) {
|
||||
this.getLiveInfo();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.live-wrap {
|
||||
background: #fff;
|
||||
border-radius: 16rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.banner-wrap {
|
||||
width: 100%;
|
||||
position: relative;
|
||||
line-height: 1;
|
||||
display: flex;
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.shade {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
background: rgba($color: #888, $alpha: 0.3);
|
||||
left: 0;
|
||||
top: 0;
|
||||
z-index: 5;
|
||||
}
|
||||
|
||||
.wrap {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
z-index: 10;
|
||||
padding: 26rpx 20rpx;
|
||||
box-sizing: border-box;
|
||||
|
||||
.room-name {
|
||||
font-size: $font-size-toolbar;
|
||||
color: #fff;
|
||||
line-height: 1;
|
||||
width: 100%;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.status-name {
|
||||
display: inline-block;
|
||||
font-size: $font-size-activity-tag;
|
||||
color: #fff;
|
||||
padding: 8rpx 12rpx;
|
||||
background-color: rgba(0, 0, 0, 0.6);
|
||||
border-radius: 36rpx;
|
||||
margin-right: 20rpx;
|
||||
|
||||
.icon-zhibozhong {
|
||||
font-size: $font-size-activity-tag;
|
||||
color: #fff;
|
||||
margin-right: 9rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.room-info {
|
||||
padding: 20rpx 30rpx;
|
||||
background: #fff;
|
||||
display: flex;
|
||||
|
||||
.anchor-img {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
|
||||
.anchor-name,
|
||||
.goods-text {
|
||||
font-size: $font-size-base;
|
||||
line-height: 60rpx;
|
||||
}
|
||||
|
||||
.separate {
|
||||
color: #808080;
|
||||
margin: 0 10rpx;
|
||||
line-height: 56rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style scoped>
|
||||
.coupon-all >>> .uni-scroll-view::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,143 @@
|
|||
<template>
|
||||
<view class="many-goods-list">
|
||||
<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-if="goodsValue" :value="goodsValue" ref="diyGoodsList"></diy-goods-list>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'diy-many-goods-list',
|
||||
props: {
|
||||
value: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
cateIndex: 0, // 当前选中的分类id
|
||||
goodsValue: null // 商品列表数据
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.changeCateIndex(this.value.list[0], 0, true);
|
||||
},
|
||||
methods: {
|
||||
changeCateIndex(item, index, isFirst) {
|
||||
this.cateIndex = index;
|
||||
this.goodsValue = {
|
||||
sources: item.sources,
|
||||
categoryId: item.categoryId,
|
||||
categoryName: item.categoryName,
|
||||
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
|
||||
};
|
||||
|
||||
// 如果是第一次加载,不需要执行下面代码
|
||||
if (isFirst) return;
|
||||
this.$refs.diyGoodsList.goodsValue = this.goodsValue;
|
||||
this.$refs.diyGoodsList.getGoodsList();
|
||||
}
|
||||
}
|
||||
};
|
||||
</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 35rpx;
|
||||
}
|
||||
|
||||
&.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;
|
||||
max-width: 220rpx;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
padding: 0 10rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,248 @@
|
|||
<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=wait_use')">
|
||||
<view class="icon-block">
|
||||
<template v-if="value.style == 3">
|
||||
<image :src="$util.img('public/uniapp/member/order/wait_use.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.waitUse.icon" v-if="value.icon.waitUse" :value="value.icon.waitUse.style ? value.icon.waitUse.style : null"></diy-icon>
|
||||
</template>
|
||||
<text v-if="orderNum.wait_use > 0" class="order-num color-base-bg price-font">{{ orderNum.wait_use > 99 ? '99+' : orderNum.wait_use }}</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,
|
||||
refunding: 0,
|
||||
wait_use: 0
|
||||
}
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.init();
|
||||
},
|
||||
watch: {
|
||||
token(nVal, oVal) {
|
||||
this.init();
|
||||
}
|
||||
},
|
||||
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: {
|
||||
init() {
|
||||
if (uni.getStorageSync('token')) {
|
||||
this.getOrderNum();
|
||||
} else {
|
||||
this.orderNum = {
|
||||
waitpay: 0,
|
||||
waitsend: 0,
|
||||
waitconfirm: 0,
|
||||
refunding: 0,
|
||||
wait_use: 0
|
||||
};
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 获取订单数量
|
||||
*/
|
||||
getOrderNum() {
|
||||
this.$api.sendRequest({
|
||||
url: '/api/order/num',
|
||||
data: {
|
||||
order_status: 'waitpay,waitsend,waitconfirm,refunding,wait_use'
|
||||
},
|
||||
success: res => {
|
||||
if (res.code == 0) {
|
||||
this.orderNum = res.data;
|
||||
}else{
|
||||
this.orderNum = {
|
||||
waitpay: 0,
|
||||
waitsend: 0,
|
||||
waitconfirm: 0,
|
||||
refunding: 0,
|
||||
wait_use: 0
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
/**
|
||||
* 跳转
|
||||
* @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>
|
||||
|
|
@ -0,0 +1,338 @@
|
|||
<template>
|
||||
<view class="diy-notes" v-if="dataList.length" :style="{ backgroundColor: value.componentBgColor }">
|
||||
<view class="diy-notes-top">
|
||||
<view class="notes-title" :style="{ color: value.titleTextColor}">
|
||||
{{ value.title }}
|
||||
</view>
|
||||
<view class="notes-more" @click="toMore()" :style="{ color: value.moreTextColor}">{{ value.more }}</view>
|
||||
</view>
|
||||
|
||||
<scroll-view class="diy-notes-box" scroll-x="true" show-scrollbar="true">
|
||||
<view class="notes-box-item" v-for="(item, i) in dataList" :key="i" @click="toDetail(item.note_id)" :style="notesItemStyle">
|
||||
<view class="notes-item" v-if="item.status == 1">
|
||||
<view class="notes-item-con">
|
||||
<view class="notes-title">{{ item.note_title }}</view>
|
||||
<view class="notes-highlights-list" v-if="value.notesLabel == 1 && item.goods_highlights">
|
||||
<text class="color-base-bg" v-for="(labelItem, labelIndex) in item.label" :key="labelIndex">{{ labelItem }}</text>
|
||||
</view>
|
||||
<view class="notes-intro">
|
||||
<text class="notes-label color-base-text">#{{ item.note_type == 'goods_item' ? '单品介绍' : '掌柜说' }}#</text>
|
||||
{{ item.note_abstract }}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="notes-img-wrap" :class="{ 'notes-img-wrap-list': item.cover_type == 1 }">
|
||||
<image v-if="item.cover_type == 0" :src="$util.img(item.img)" @error="imageError(i)" mode="aspectFill" class="notes-item-image"></image>
|
||||
<image
|
||||
v-else
|
||||
v-for="(imgItem, imgIndex) in item.img"
|
||||
:key="imgIndex"
|
||||
:src="$util.img(imgItem)"
|
||||
@error="imageError(i)"
|
||||
mode="aspectFit"
|
||||
class="notes-item-image-li"
|
||||
></image>
|
||||
</view>
|
||||
|
||||
<view class="notes-item-con">
|
||||
<view class="notes-info" v-if="(value.readNum == 1 && item.is_show_read_num == 1) || (value.uploadTime == 1 && item.is_show_release_time == 1)">
|
||||
<view class="notes-num">
|
||||
<text v-show="value.uploadTime == 1 && item.is_show_release_time == 1">{{ item.update_time_day }}</text>
|
||||
</view>
|
||||
<view class="notes-num">
|
||||
<text v-show="value.readNum == 1 && item.is_show_read_num == 1">阅读 {{ item.initial_read_num + item.read_num }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<ns-login ref="login"></ns-login>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'diy-notes',
|
||||
props: {
|
||||
value: {
|
||||
type: Object
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
dataList: [],
|
||||
giveLikeFlag: false
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getDataList();
|
||||
},
|
||||
computed:{
|
||||
notesItemStyle(){
|
||||
var css = "";
|
||||
css += 'background-color:' + this.value.contentBgColor + ';'
|
||||
if(this.value.elementAngle == "round"){
|
||||
css += 'border-top-left-radius:' + this.value.topElementAroundRadius * 2 + 'rpx;';
|
||||
css += 'border-top-right-radius:' + this.value.topElementAroundRadius * 2 + 'rpx;';
|
||||
css += 'border-bottom-left-radius:' + this.value.bottomElementAroundRadius * 2 + 'rpx;';
|
||||
css += 'border-bottom-right-radius:' + this.value.bottomElementAroundRadius * 2 + 'rpx;';
|
||||
}
|
||||
return css;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
refresh() {
|
||||
this.getDataList();
|
||||
},
|
||||
getDataList() {
|
||||
var data = { num: this.value.count };
|
||||
|
||||
if (this.value.sources == 'diy') {
|
||||
data.num = 0;
|
||||
data.note_id_arr = this.value.noteId.toString();
|
||||
}
|
||||
|
||||
this.$api.sendRequest({
|
||||
url: '/notes/api/notes/lists',
|
||||
data: data,
|
||||
success: res => {
|
||||
var data = res.data;
|
||||
this.dataList = [];
|
||||
if (data) {
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
var item = {};
|
||||
item = data[i];
|
||||
if (data[i].cover_type == 1) {
|
||||
item.img = data[i].cover_img.split(',');
|
||||
} else {
|
||||
item.img = data[i].cover_img;
|
||||
}
|
||||
|
||||
if (data[i].upload_time) {
|
||||
item.update_time_day = this.$util.timeStampTurnTime(data[i].upload_time).split(' ')[0];
|
||||
} else {
|
||||
item.update_time_day = this.$util.timeStampTurnTime(data[i].create_time).split(' ')[0];
|
||||
}
|
||||
|
||||
item.label = data[i].goods_highlights.split(',');
|
||||
this.dataList.push(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
toMore() {
|
||||
this.$util.redirectTo('/pages_tool/store_notes/note_list');
|
||||
},
|
||||
toDetail(id) {
|
||||
this.$util.redirectTo('/pages_tool/store_notes/note_detail', {
|
||||
note_id: id
|
||||
});
|
||||
},
|
||||
/* 点赞 */
|
||||
giveLike(noteId, index) {
|
||||
if (!uni.getStorageSync('token')) {
|
||||
this.$refs.login.open('/pages/index/index');
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.giveLikeFlag) return false;
|
||||
this.giveLikeFlag = true;
|
||||
|
||||
var url = this.dataList[index].is_dianzan == 1 ? '/notes/api/record/delete' : '/notes/api/record/add';
|
||||
this.$api.sendRequest({
|
||||
url: url,
|
||||
data: {
|
||||
note_id: noteId
|
||||
},
|
||||
success: res => {
|
||||
this.giveLikeFlag = false;
|
||||
if (res.code == 0 && res.data > 0) {
|
||||
if (this.noteType != 'goods_item')
|
||||
this.dataList[index].dianzan_num = this.dataList[index].is_dianzan == 1 ? this.dataList[index].dianzan_num - 1 : this.dataList[index].dianzan_num + 1;
|
||||
else {
|
||||
this.dataList[index].dianzan_num = this.dataList[index].is_dianzan == 1 ? this.dataList[index].dianzan_num - 1 : this.dataList[index].dianzan_num + 1;
|
||||
}
|
||||
this.dataList[index].is_dianzan = this.dataList[index].is_dianzan == 1 ? 0 : 1;
|
||||
} else {
|
||||
this.$util.showToast({
|
||||
title: res.message
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
imageError(index) {
|
||||
this.dataList[index].img = this.$util.getDefaultImage().goods;
|
||||
this.$forceUpdate();
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
scroll-view ::-webkit-scrollbar {
|
||||
width: 0;
|
||||
height: 0;
|
||||
background-color: transparent;
|
||||
touch-action: none;
|
||||
}
|
||||
.diy-notes {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.diy-notes-top {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
|
||||
.notes-title {
|
||||
width: 70%;
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.notes-more {
|
||||
font-size: $font-size-tag;
|
||||
color: #858585;
|
||||
}
|
||||
|
||||
.notes-more::after {
|
||||
font-family: 'iconfont';
|
||||
content: '\e6a3';
|
||||
font-size: $font-size-tag;
|
||||
line-height: 1;
|
||||
position: relative;
|
||||
margin-left: 4rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.diy-notes-box {
|
||||
width: 100%;
|
||||
padding: 30rpx 0 20rpx;
|
||||
}
|
||||
|
||||
.notes-box-item {
|
||||
width: calc(100% - 8rpx);
|
||||
margin: 0 auto;
|
||||
height: 100%;
|
||||
margin-bottom: 30rpx;
|
||||
border-radius: 10rpx;
|
||||
overflow: hidden;
|
||||
-moz-box-shadow: 0 0 20rpx rgba(0, 0, 0, 0.02);
|
||||
-webkit-box-shadow: 0 0 20rpx rgba(0, 0, 0, 0.02);
|
||||
box-shadow: 0 0 20rpx rgba(0, 0, 0, 0.02);
|
||||
|
||||
.notes-item {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 20rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.notes-img-wrap {
|
||||
position: relative;
|
||||
height: 300rpx;
|
||||
|
||||
.notes-item-image {
|
||||
width: 100%;
|
||||
height: 300rpx;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.notes-label {
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
left: 20rpx;
|
||||
bottom: 20rpx;
|
||||
max-width: calc(100vh - 40rpx);
|
||||
background-color: #ffffff;
|
||||
line-height: 36rpx;
|
||||
padding: 0 10rpx 0 4rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.notes-img-wrap-list {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
height: auto;
|
||||
|
||||
image {
|
||||
width: calc((100% - 40rpx) / 3);
|
||||
height: 210rpx;
|
||||
margin-top: 20rpx;
|
||||
|
||||
&:nth-child(-n + 3) {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&:after {
|
||||
content: '';
|
||||
width: calc((100% - 40rpx) / 3);
|
||||
}
|
||||
}
|
||||
|
||||
.notes-item-con {
|
||||
.notes-title {
|
||||
font-size: 30rpx;
|
||||
font-weight: 600;
|
||||
line-height: 44rpx;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.notes-highlights-list {
|
||||
text {
|
||||
display: inline-block;
|
||||
color: #ffffff;
|
||||
font-size: 24rpx;
|
||||
line-height: 36rpx;
|
||||
padding: 0 10rpx;
|
||||
border-radius: 4rpx;
|
||||
margin: 0 5rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.notes-intro {
|
||||
margin: 4rpx 0 8rpx;
|
||||
line-height: 40rpx;
|
||||
overflow: hidden;
|
||||
|
||||
text {
|
||||
float: left;
|
||||
margin-right: 16rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.notes-info {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-top: 20rpx;
|
||||
|
||||
.notes-num {
|
||||
> text {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: $font-size-tag;
|
||||
color: #969799;
|
||||
|
||||
text.iconfont {
|
||||
font-size: 26rpx;
|
||||
margin-right: 6rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,182 @@
|
|||
<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 using-hidden" :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 => {
|
||||
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>
|
||||
|
|
@ -0,0 +1,501 @@
|
|||
<template>
|
||||
<view class="diy-pinfan" 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="tag-wrap" v-if="value.groupStyle.control || value.saleStyle.control">
|
||||
<view
|
||||
v-if="value.groupStyle.control"
|
||||
:style="{ color: value.theme == 'diy' ? value.groupStyle.bgColor : '', borderColor: value.theme == 'diy' ? value.groupStyle.bgColor : '' }"
|
||||
>
|
||||
<text class="iconfont icon-yonghu3" :style="{ backgroundColor: value.theme == 'diy' ? value.groupStyle.bgColor : '' }"></text>
|
||||
<text>{{ item.pintuan_num }}人团</text>
|
||||
</view>
|
||||
<view
|
||||
v-if="value.saleStyle.control"
|
||||
:style="{ color: value.theme == 'diy' ? value.saleStyle.color : '', borderColor: value.theme == 'diy' ? value.saleStyle.color : '' }"
|
||||
>
|
||||
<text>已拼{{ item.order_num }}件</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="price-wrap">
|
||||
<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.pintuan_price.split(".")[0] }}</text>
|
||||
<text class="unit price-style small" :style="{ color: value.theme == 'diy' ? value.priceStyle.mainColor +'!important' : '' }">{{ "."+item.pintuan_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>
|
||||
<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'
|
||||
}"
|
||||
>
|
||||
<text class="text">{{ value.btnStyle.text }}</text>
|
||||
<text class="fan" v-if="item.reward_type == 4">返{{ item.reward_type_num }}积分</text>
|
||||
<text class="fan" v-if="item.reward_type == 1 || item.reward_type == 2">返¥{{ item.reward_type_num }}</text>
|
||||
<text class="fan" v-if="item.reward_type == 3">返优惠券</text>
|
||||
</button>
|
||||
</view>
|
||||
</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>
|
||||
</view>
|
||||
<view :class="['content', { 'multi-content': value.nameLineMode == 'multiple' }]" v-if="value.goodsNameStyle.control || value.priceStyle.mainControl">
|
||||
<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 v-if="value.groupStyle.control" class="num">
|
||||
<text
|
||||
class="content-tuan-box"
|
||||
:style="{ color: value.theme == 'diy' ? value.groupStyle.color : '', backgroundColor: value.theme == 'diy' ? value.groupStyle.bgColor : '' }"
|
||||
>
|
||||
{{ item.pintuan_num }}人团
|
||||
</text>
|
||||
<text class="content-tuan-price" :style="{ color: value.theme == 'diy' ? value.groupStyle.bgColor : '' }" v-if="item.reward_type == 4">
|
||||
返{{ item.reward_type_num }}积分
|
||||
</text>
|
||||
<text
|
||||
class="content-tuan-price"
|
||||
:style="{ color: value.theme == 'diy' ? value.groupStyle.bgColor : '' }"
|
||||
v-if="item.reward_type == 1 || item.reward_type == 2"
|
||||
>
|
||||
返¥{{ item.reward_type_num }}
|
||||
</text>
|
||||
<text class="content-tuan-price" :style="{ color: value.theme == 'diy' ? value.groupStyle.bgColor : '' }" v-if="item.reward_type == 3">返优惠券</text>
|
||||
</view>
|
||||
<view class="price-wrap" 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.pintuan_price.split('.')[0] }}</text>
|
||||
<text class="unit price-style small" :style="{ color: value.theme == 'diy' ? value.priceStyle.mainColor +'!important' : '' }">{{ "."+item.pintuan_price.split('.')[1] }}</text>
|
||||
</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>
|
||||
</view>
|
||||
<view :class="['content', { 'multi-content': value.nameLineMode == 'multiple' }]" v-if="value.goodsNameStyle.control || value.priceStyle.mainControl">
|
||||
<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 v-if="value.groupStyle.control" class="num">
|
||||
<text
|
||||
class="content-tuan-box"
|
||||
:style="{ color: value.theme == 'diy' ? value.groupStyle.color : '', backgroundColor: value.theme == 'diy' ? value.groupStyle.bgColor : '' }"
|
||||
>
|
||||
{{ item.pintuan_num }}人团
|
||||
</text>
|
||||
<text class="content-tuan-price" :style="{ color: value.theme == 'diy' ? value.groupStyle.bgColor : '' }" v-if="item.reward_type == 4">
|
||||
返{{ item.reward_type_num }}积分
|
||||
</text>
|
||||
<text
|
||||
class="content-tuan-price"
|
||||
:style="{ color: value.theme == 'diy' ? value.groupStyle.bgColor : '' }"
|
||||
v-if="item.reward_type == 1 || item.reward_type == 2"
|
||||
>
|
||||
返¥{{ item.reward_type_num }}
|
||||
</text>
|
||||
<text class="content-tuan-price" :style="{ color: value.theme == 'diy' ? value.groupStyle.bgColor : '' }" v-if="item.reward_type == 3">
|
||||
返优惠券
|
||||
</text>
|
||||
</view>
|
||||
<view class="price-wrap" 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.pintuan_price.split('.')[1] }}</text>
|
||||
<text class="unit price-style small" :style="{ color: value.theme == 'diy' ? value.priceStyle.mainColor +'!important' : '' }">{{ "."+item.pintuan_price.split('.')[1] }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
</template>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'diy-pinfan',
|
||||
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' ? '444rpx' : '432rpx';
|
||||
return this.value.ornament.type == 'shadow' ? '404rpx' : '396rpx';
|
||||
}
|
||||
},
|
||||
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 = {
|
||||
num: this.value.count
|
||||
};
|
||||
if (this.value.sources == 'diy') {
|
||||
data.num = 0;
|
||||
data.goods_id_arr = this.value.goodsId.toString();
|
||||
}
|
||||
this.$api.sendRequest({
|
||||
url: '/pinfan/api/goods/lists',
|
||||
data: data,
|
||||
success: res => {
|
||||
if (res.code == 0 && res.data) {
|
||||
this.list = res.data;
|
||||
|
||||
// 切屏滚动,每页显示固定数量
|
||||
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/pinfan/detail', {
|
||||
pinfan_id: e.pintuan_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-pinfan {
|
||||
&.row1-of1 {
|
||||
.item {
|
||||
display: flex;
|
||||
margin-bottom: 20rpx;
|
||||
padding: 16rpx;
|
||||
&.shadow {
|
||||
margin: 8rpx 8rpx 20rpx 8rpx;
|
||||
}
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.img-wrap {
|
||||
width: 200rpx;
|
||||
height: 200rpx;
|
||||
image {
|
||||
width: 200rpx;
|
||||
}
|
||||
}
|
||||
.content {
|
||||
flex: 1;
|
||||
margin-left: 20rpx;
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-direction: column;
|
||||
padding: 6rpx 0;
|
||||
.goods-name {
|
||||
line-height: 1.3;
|
||||
}
|
||||
.tag-wrap {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: 4rpx;
|
||||
> view {
|
||||
height: 30rpx;
|
||||
line-height: 30rpx;
|
||||
border: 2rpx solid $base-color;
|
||||
border-radius: 6rpx;
|
||||
margin-right: 10rpx;
|
||||
font-size: $font-size-activity-tag;
|
||||
color: $base-color;
|
||||
.iconfont {
|
||||
display: inline-block;
|
||||
width: 30rpx;
|
||||
height: 30rpx;
|
||||
font-size: $font-size-activity-tag;
|
||||
color: #ffffff;
|
||||
text-align: center;
|
||||
margin-right: -6rpx;
|
||||
background: $base-color;
|
||||
}
|
||||
text:last-child {
|
||||
padding: 0 10rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
.price-wrap {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
> view:last-of-type {
|
||||
flex: 1;
|
||||
}
|
||||
.discount-price {
|
||||
white-space: nowrap;
|
||||
font-weight: bold;
|
||||
.unit {
|
||||
font-size: $font-size-tag;
|
||||
color: $base-color;
|
||||
}
|
||||
.price {
|
||||
font-size: $font-size-toolbar;
|
||||
color: $base-color;
|
||||
}
|
||||
}
|
||||
.original-price {
|
||||
font-size: $font-size-tag;
|
||||
color: $color-tip;
|
||||
text-decoration: line-through;
|
||||
margin: 0 10rpx 4rpx 10rpx;
|
||||
}
|
||||
}
|
||||
button {
|
||||
bottom: 10rpx;
|
||||
height: 90rpx;
|
||||
line-height: 40rpx;
|
||||
padding: 0 16rpx;
|
||||
margin: 0;
|
||||
text-align: center;
|
||||
background-color: $base-color;
|
||||
color: #ffffff;
|
||||
.text {
|
||||
display: block;
|
||||
margin-top: 6rpx;
|
||||
font-size: $font-size-tag;
|
||||
}
|
||||
.fan {
|
||||
font-size: $font-size-activity-tag;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
&.horizontal-slide {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
.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;
|
||||
}
|
||||
}
|
||||
.content {
|
||||
padding: 10rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
&.multi-content{
|
||||
height: 188rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.goods-name {
|
||||
line-height: 1.3;
|
||||
&.multi-hidden {
|
||||
white-space: break-spaces;
|
||||
}
|
||||
}
|
||||
.num {
|
||||
margin-top: auto;
|
||||
font-size: $font-size-activity-tag;
|
||||
.content-tuan-box {
|
||||
border-radius: 4rpx;
|
||||
color: #ffffff;
|
||||
background-color: $base-color;
|
||||
padding: 6rpx;
|
||||
}
|
||||
.content-tuan-price {
|
||||
border-radius: 4rpx;
|
||||
padding: 4rpx 6rpx;
|
||||
border: 2rpx solid $base-color;
|
||||
color: $base-color;
|
||||
margin-left: -2rpx;
|
||||
}
|
||||
}
|
||||
.price-wrap {
|
||||
white-space: nowrap;
|
||||
margin-top: 10rpx;
|
||||
font-weight: bold;
|
||||
line-height: 1;
|
||||
.unit {
|
||||
font-size: $font-size-tag;
|
||||
height: 32rpx;
|
||||
color: $base-color;
|
||||
}
|
||||
.price {
|
||||
font-size: $font-size-toolbar;
|
||||
color: $base-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.swiper {
|
||||
width: 100%;
|
||||
white-space: nowrap;
|
||||
padding: 20rpx;
|
||||
box-sizing: border-box;
|
||||
.swiper-item{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.item {
|
||||
width: 200rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,696 @@
|
|||
<template>
|
||||
<view class="diy-pintuan" v-if="list.length" :class="[value.template, value.style]" :style="warpCss">
|
||||
<view v-if="value.titleStyle.isShow" :class="[value.titleStyle.style,'pintuan-head']"
|
||||
:style="{'backgroundImage': 'url(' + $util.img(value.titleStyle.backgroundImage) + '), linear-gradient(to right,'+value.titleStyle.bgColorStart+','+ value.titleStyle.bgColorEnd+')' }">
|
||||
<view v-if="value.titleStyle.leftStyle == 'text'" class="left-text"
|
||||
:style="{fontSize: value.titleStyle.fontSize*2 + 'rpx',color: value.titleStyle.textColor,fontWeight: value.titleStyle.fontWeight ? 'bold' : ''}">
|
||||
{{value.titleStyle.leftText}}</view>
|
||||
<image v-else class="left-img" :src="$util.img(value.titleStyle.leftImg)" mode="heightFix"></image>
|
||||
<view class="head-content">
|
||||
<view class="img-warp">
|
||||
<block v-if="headData && headData.member_list && headData.member_list.length">
|
||||
<image v-for="(item,index) in headData.member_list" :key="index"
|
||||
:src="$util.img(item.member_img || 'public/static/img/default_img/square.png')"
|
||||
mode="aspectFill" @error="headImageError(index)"></image>
|
||||
</block>
|
||||
<block v-else>
|
||||
<image :src="$util.img('public/static/img/default_img/square.png')" mode="aspectFill">
|
||||
</image>
|
||||
<image :src="$util.img('public/static/img/default_img/square.png')" mode="aspectFill">
|
||||
</image>
|
||||
<image :src="$util.img('public/static/img/default_img/square.png')" mode="aspectFill">
|
||||
</image>
|
||||
</block>
|
||||
</view>
|
||||
<text :style="{color: value.titleStyle.textColor}">{{value.titleStyle.virtualNum || headData.pintuan_count}}人拼团成功</text>
|
||||
</view>
|
||||
<view class="head-right" :style="{fontSize: value.titleStyle.moreFontSize*2 + 'rpx',color: value.titleStyle.moreColor}" @click="$util.redirectTo('/pages_promotion/pintuan/list')">
|
||||
<text>{{value.titleStyle.more}}</text>
|
||||
<text class="iconfont icon-right"></text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<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="tag-wrap" v-if="value.groupStyle.control || value.saleStyle.control">
|
||||
<view v-if="value.groupStyle.control" :style="{
|
||||
color: value.theme == 'diy' ? value.groupStyle.bgColorStart : '',
|
||||
borderColor: value.theme == 'diy' ? value.groupStyle.bgColorStart : ''
|
||||
}">
|
||||
<text class="iconfont icon-yonghu3"
|
||||
:style="{ backgroundColor: value.theme == 'diy' ? value.groupStyle.bgColorStart : '' }"></text>
|
||||
<text>{{ item.pintuan_num }}人团</text>
|
||||
</view>
|
||||
<view v-if="value.saleStyle.control"
|
||||
:style="{ color: value.theme == 'diy' ? value.saleStyle.color : '', borderColor: value.theme == 'diy' ? value.saleStyle.color : '' }">
|
||||
<text>已拼{{ item.order_num }}件</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="bottom-wrap">
|
||||
<view class="price-wrap">
|
||||
<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.pintuan_price.split(".")[0] }}</text>
|
||||
<text class="unit price-style small"
|
||||
:style="{ color: value.theme == 'diy' ? value.priceStyle.mainColor +'!important' : '' }">{{ "."+item.pintuan_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>
|
||||
<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>
|
||||
</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>
|
||||
<view v-if="value.groupStyle.control && value.style!='style-2'" class="num" :style="{
|
||||
color: value.theme == 'diy' ? value.groupStyle.color : '',
|
||||
background: value.theme == 'diy' ? 'linear-gradient(to right,' + value.groupStyle.bgColorStart + ',' + value.groupStyle.bgColorEnd + ')' : ''
|
||||
}">
|
||||
{{ item.pintuan_num }}人团
|
||||
</view>
|
||||
</view>
|
||||
<view :class="['content', { 'multi-content': value.nameLineMode == 'multiple' }]"
|
||||
v-if="value.goodsNameStyle.control || value.priceStyle.mainControl">
|
||||
<view v-if="value.goodsNameStyle.control && value.style!='style-2'" 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="price-wrap" 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.pintuan_price.split(".")[0] }}</text>
|
||||
<text class="unit price-style small"
|
||||
:style="{ color: value.theme == 'diy' ? value.priceStyle.mainColor +'!important' : '' }">{{ "."+item.pintuan_price.split(".")[1] }}</text>
|
||||
</view>
|
||||
<view class="sale-num" v-if="value.style=='style-2'">已拼{{item.sale_num}}件</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>
|
||||
<view v-if="value.groupStyle.control && value.style!='style-2'" class="num" :style="{
|
||||
color: value.theme == 'diy' ? value.groupStyle.color : '',
|
||||
background: value.theme == 'diy' ? 'linear-gradient(to right,' + value.groupStyle.bgColorStart + ',' + value.groupStyle.bgColorEnd + ')' : ''
|
||||
}">
|
||||
{{ item.pintuan_num }}人团
|
||||
</view>
|
||||
</view>
|
||||
<view :class="['content', { 'multi-content': value.nameLineMode == 'multiple' }]"
|
||||
v-if="value.goodsNameStyle.control || value.priceStyle.mainControl">
|
||||
<view v-if="value.goodsNameStyle.control && value.style!='style-2'" 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="price-wrap" 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.pintuan_price.split(".")[0] }}</text>
|
||||
<text class="unit price-style small"
|
||||
:style="{ color: value.theme == 'diy' ? value.priceStyle.mainColor +'!important' : '' }">{{ "."+item.pintuan_price.split(".")[1] }}</text>
|
||||
</view>
|
||||
<view class="sale-num" v-if="value.style=='style-2'">已拼{{item.sale_num}}件</view>
|
||||
</view>
|
||||
</view>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
</template>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'diy-pintuan',
|
||||
props: {
|
||||
value: {
|
||||
type: Object
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
list: [],
|
||||
page: 1,
|
||||
scrollWidth: 0,
|
||||
headData: []
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getData();
|
||||
this.getHeadData();
|
||||
},
|
||||
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 if (this.value.template == 'horizontal-slide' && this.value.style == 'style-2')
|
||||
width = [screenWidth - (this.rpxUpPx(212) * 3) - (this.rpxUpPx(this.value
|
||||
.margin.both * 2) * 2)] / 6;
|
||||
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.template == 'horizontal-slide' && this.value.style == 'style-2'){
|
||||
if (this.value.nameLineMode == 'multiple') {
|
||||
if (this.value.ornament.type == 'shadow')
|
||||
return '360rpx';
|
||||
else
|
||||
return '342rpx';
|
||||
}
|
||||
if (this.value.ornament.type == 'shadow')
|
||||
return '324rpx';
|
||||
else
|
||||
return '308rpx';
|
||||
}else{
|
||||
if (this.value.nameLineMode == 'multiple') {
|
||||
if (this.value.ornament.type == 'shadow')
|
||||
return '400rpx';
|
||||
else
|
||||
return '382rpx';
|
||||
}
|
||||
if (this.value.ornament.type == 'shadow')
|
||||
return '364rpx';
|
||||
else
|
||||
return '348rpx';
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
rpxUpPx(res) {
|
||||
const screenWidth = uni.getSystemInfoSync().safeArea.width || uni.getSystemInfoSync().screenWidth;
|
||||
var data = screenWidth * parseInt(res) / 750;
|
||||
return Math.floor(data);
|
||||
},
|
||||
getHeadData() {
|
||||
var data = {
|
||||
num: 3
|
||||
};
|
||||
this.$api.sendRequest({
|
||||
url: '/pintuan/api/order/pintuanmember',
|
||||
data: data,
|
||||
success: res => {
|
||||
if (res.code == 0 && res.data) {
|
||||
this.headData = res.data;
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
getData() {
|
||||
var data = {
|
||||
num: this.value.count
|
||||
};
|
||||
if (this.value.sources == 'diy') {
|
||||
data.num = 6;
|
||||
data.goods_id_arr = this.value.goodsId.toString();
|
||||
}
|
||||
this.$api.sendRequest({
|
||||
url: '/pintuan/api/goods/lists',
|
||||
data: data,
|
||||
success: res => {
|
||||
if (res.code == 0 && res.data) {
|
||||
this.list = res.data;
|
||||
|
||||
// 切屏滚动,每页显示固定数量
|
||||
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/pintuan/detail', {
|
||||
pintuan_id: e.pintuan_id
|
||||
});
|
||||
},
|
||||
imageError(index) {
|
||||
if(this.list[index]) this.list[index].goods_image = this.$util.getDefaultImage().goods;
|
||||
this.$forceUpdate();
|
||||
},
|
||||
headImageError(index) {
|
||||
this.headData.member_list[index].member_img = this.$util.img('public/static/img/default_img/square.png');
|
||||
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-pintuan {
|
||||
overflow: hidden;
|
||||
.pintuan-head {
|
||||
padding: 0 24rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
height: 88rpx;
|
||||
box-sizing: border-box;
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
margin-bottom: 20rpx;
|
||||
border-radius: 18rpx 18rpx 0 0;
|
||||
|
||||
.left-img {
|
||||
width: 174rpx;
|
||||
height: 40rpx;
|
||||
}
|
||||
|
||||
.head-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-left: 50rpx;
|
||||
margin-right: auto;
|
||||
color: #fff;
|
||||
|
||||
.img-warp {
|
||||
position: relative;
|
||||
margin-right: 8rpx;
|
||||
line-height: 1;
|
||||
|
||||
image {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
border-radius: 50%;
|
||||
border: 2rpx solid #FF3D3D;
|
||||
margin-left: -14rpx;
|
||||
}
|
||||
|
||||
&:after {
|
||||
content: "";
|
||||
width: 2rpx;
|
||||
height: 28rpx;
|
||||
background-color: #fff;
|
||||
position: absolute;
|
||||
left: -32rpx;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.head-right {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: $font-size-sub;
|
||||
color: #fff;
|
||||
line-height: 1;
|
||||
}
|
||||
}
|
||||
|
||||
&.row1-of1 {
|
||||
.item {
|
||||
display: flex;
|
||||
margin-bottom: 20rpx;
|
||||
padding: 16rpx;
|
||||
|
||||
&.shadow {
|
||||
margin: 8rpx 8rpx 20rpx 8rpx;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.img-wrap {
|
||||
width: 200rpx;
|
||||
height: 200rpx;
|
||||
|
||||
image {
|
||||
width: 200rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
flex: 1;
|
||||
margin-left: 20rpx;
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-direction: column;
|
||||
padding: 6rpx 0;
|
||||
|
||||
.tag-wrap {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
>view {
|
||||
height: 30rpx;
|
||||
line-height: 30rpx;
|
||||
border: 2rpx solid $base-color;
|
||||
border-radius: 6rpx;
|
||||
margin-right: 10rpx;
|
||||
font-size: $font-size-activity-tag;
|
||||
color: $base-color;
|
||||
|
||||
.iconfont {
|
||||
display: inline-block;
|
||||
width: 30rpx;
|
||||
height: 30rpx;
|
||||
font-size: $font-size-activity-tag;
|
||||
color: #ffffff;
|
||||
text-align: center;
|
||||
margin-right: -6rpx;
|
||||
background: $base-color;
|
||||
}
|
||||
|
||||
text:last-child {
|
||||
padding: 0 10rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.goods-name {
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.bottom-wrap {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.price-wrap {
|
||||
overflow: hidden;
|
||||
width: 260rpx;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
flex-wrap: wrap;
|
||||
|
||||
>view:last-of-type {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.discount-price {
|
||||
white-space: nowrap;
|
||||
font-weight: bold;
|
||||
line-height: 1;
|
||||
|
||||
.unit {
|
||||
font-size: $font-size-tag;
|
||||
color: var(--price-color);
|
||||
}
|
||||
|
||||
.price {
|
||||
font-size: $font-size-toolbar;
|
||||
color: var(--price-color);
|
||||
}
|
||||
}
|
||||
|
||||
.original-price {
|
||||
font-size: $font-size-tag;
|
||||
color: $color-tip;
|
||||
line-height: 1;
|
||||
text-decoration: line-through;
|
||||
margin: 0 10rpx;
|
||||
}
|
||||
}
|
||||
|
||||
button {
|
||||
margin-right: 20rpx;
|
||||
min-width: 112rpx;
|
||||
height: 52rpx;
|
||||
line-height: 52rpx;
|
||||
padding: 0 20rpx;
|
||||
margin: 0;
|
||||
color: var(--btn-text-color);
|
||||
background-color: $base-color;
|
||||
color: #fff;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.horizontal-slide {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.flex-between {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.scroll {
|
||||
width: calc(100% - 40rpx);
|
||||
padding: 20rpx;
|
||||
line-height: 1;
|
||||
white-space: nowrap;
|
||||
|
||||
.item.shadow {
|
||||
margin-bottom: 4rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.item {
|
||||
display: inline-block;
|
||||
width: 200rpx;
|
||||
overflow: hidden;
|
||||
box-sizing: border-box;
|
||||
flex-shrink: 0;
|
||||
|
||||
&: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;
|
||||
}
|
||||
|
||||
.num {
|
||||
width: 80rpx;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
font-size: $font-size-tag;
|
||||
line-height: 1;
|
||||
color: #ffffff;
|
||||
text-align: center;
|
||||
border-top-left-radius: 20rpx;
|
||||
border-top-right-radius: 20rpx;
|
||||
padding: 10rpx;
|
||||
transform: translate(50%);
|
||||
background: $base-color;
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 10rpx 10rpx 16rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
|
||||
&.multi-content {
|
||||
height: 142rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.goods-name {
|
||||
line-height: 1.3;
|
||||
font-size: $font-size-base;
|
||||
|
||||
&.multi-hidden {
|
||||
white-space: break-spaces;
|
||||
}
|
||||
}
|
||||
|
||||
.price-wrap {
|
||||
line-height: 1;
|
||||
white-space: nowrap;
|
||||
margin-top: 10rpx;
|
||||
font-weight: bold;
|
||||
|
||||
.unit {
|
||||
font-size: $font-size-tag;
|
||||
height: 32rpx;
|
||||
color: var(--price-color);
|
||||
}
|
||||
|
||||
.price {
|
||||
font-size: $font-size-toolbar;
|
||||
color: var(--price-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.swiper {
|
||||
padding: 20rpx;
|
||||
width: 100%;
|
||||
white-space: nowrap;
|
||||
box-sizing: border-box;
|
||||
|
||||
.swiper-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.item {
|
||||
width: 200rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
|
||||
&.style-2 {
|
||||
.item {
|
||||
width: 212rpx;
|
||||
&:nth-child(3n+3){
|
||||
width: 210rpx;
|
||||
}
|
||||
|
||||
.img-wrap {
|
||||
|
||||
width: 212rpx;
|
||||
height: 212rpx;
|
||||
|
||||
>image {
|
||||
width: 212rpx !important;
|
||||
}
|
||||
}
|
||||
|
||||
.price-wrap {
|
||||
text-align: center;
|
||||
margin-top: 0 !important;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
|
||||
.sale-num {
|
||||
text-align: center;
|
||||
color: #666666;
|
||||
line-height: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.scroll {
|
||||
padding: 0;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.swiper {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,377 @@
|
|||
<template>
|
||||
<view class="diy-presale" 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.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' : '' }">{{ showPrice(item).split(".")[0] }}</text>
|
||||
<text class="unit price-style small" :style="{ color: value.theme == 'diy' ? value.priceStyle.mainColor +'!important' : '' }">{{ "."+showPrice(item).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>
|
||||
</view>
|
||||
<view :class="['content', { 'multi-content': value.nameLineMode == 'multiple' }]" v-if="value.goodsNameStyle.control || value.priceStyle.mainControl">
|
||||
<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' : '' }">{{ showPrice(item).split(".")[0] }}</text>
|
||||
<text class="unit price-style small" :style="{ color: value.theme == 'diy' ? value.priceStyle.mainColor +'!important' : '' }">{{ "."+showPrice(item).split(".")[1] }}</text>
|
||||
</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>
|
||||
</view>
|
||||
<view :class="['content', { 'multi-content': value.nameLineMode == 'multiple' }]" v-if="value.goodsNameStyle.control || value.priceStyle.mainControl">
|
||||
<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' : '' }">{{ showPrice(item).split(".")[0] }}</text>
|
||||
<text class="unit price-style small" :style="{ color: value.theme == 'diy' ? value.priceStyle.mainColor +'!important' : '' }">{{ "."+showPrice(item).split(".")[1] }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
</template>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'diy-presale',
|
||||
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-right:' + width + "px;";
|
||||
obj += 'margin-left:' + width + "px;";
|
||||
}
|
||||
return obj;
|
||||
},
|
||||
swiperHeight() {
|
||||
if (this.value.nameLineMode == 'multiple') {
|
||||
return this.value.ornament.type == 'shadow' ? '390rpx' : '382rpx';
|
||||
}
|
||||
return this.value.ornament.type == 'shadow' ? '364rpx' : '348rpx';
|
||||
}
|
||||
},
|
||||
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 = {
|
||||
num: this.value.count
|
||||
};
|
||||
if (this.value.sources == 'diy') {
|
||||
data.num = 0;
|
||||
data.goods_id_arr = this.value.goodsId.toString();
|
||||
}
|
||||
this.$api.sendRequest({
|
||||
url: '/presale/api/goods/lists',
|
||||
data: data,
|
||||
success: res => {
|
||||
if (res.code == 0 && res.data) {
|
||||
this.list = res.data;
|
||||
|
||||
// 切屏滚动,每页显示固定数量
|
||||
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/presale/detail', {
|
||||
id: e.presale_id
|
||||
});
|
||||
},
|
||||
imageError(index) {
|
||||
this.list[index].goods_image = this.$util.getDefaultImage().goods;
|
||||
this.$forceUpdate();
|
||||
},
|
||||
showPrice(data) {
|
||||
let price = data.price;
|
||||
if (data.member_price && parseFloat(data.member_price) < parseFloat(price)) price = data.member_price;
|
||||
return price;
|
||||
}
|
||||
}
|
||||
};
|
||||
</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-presale {
|
||||
&.row1-of1 {
|
||||
.item {
|
||||
display: flex;
|
||||
margin-bottom: 20rpx;
|
||||
padding: 16rpx;
|
||||
&.shadow {
|
||||
margin: 8rpx 8rpx 20rpx 8rpx;
|
||||
}
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.img-wrap {
|
||||
width: 200rpx;
|
||||
height: 200rpx;
|
||||
> image {
|
||||
width: 200rpx;
|
||||
}
|
||||
}
|
||||
.content {
|
||||
flex: 1;
|
||||
margin-left: 20rpx;
|
||||
position: relative;
|
||||
padding: 6rpx 0;
|
||||
.goods-name{
|
||||
line-height: 1.5;
|
||||
}
|
||||
.discount-price {
|
||||
white-space: nowrap;
|
||||
font-weight: bold;
|
||||
position: absolute;
|
||||
bottom: 10rpx;
|
||||
left: 0;
|
||||
.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;
|
||||
margin: 0 auto;
|
||||
> image {
|
||||
width: 200rpx;
|
||||
}
|
||||
}
|
||||
.content {
|
||||
padding: 10rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
&.multi-content{
|
||||
height: 134rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.goods-name {
|
||||
line-height: 1.3;
|
||||
&.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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.swiper {
|
||||
padding: 20rpx;
|
||||
width: 100%;
|
||||
white-space: nowrap;
|
||||
box-sizing: border-box;
|
||||
.swiper-item{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.item {
|
||||
width: 200rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
<template>
|
||||
<view class="rich-text-box" :style="richTextWarpCss"><rich-text :nodes="html"></rich-text></view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// 富文本
|
||||
import htmlParser from '@/common/js/html-parser';
|
||||
export default {
|
||||
name: 'diy-rich-text',
|
||||
props: {
|
||||
value: {
|
||||
type: Object
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
html: ''
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
richTextWarpCss: 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;
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.html = htmlParser(this.value.html);
|
||||
},
|
||||
mounted() {},
|
||||
methods: {}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.rich-text-box {
|
||||
padding: $padding;
|
||||
box-sizing: border-box;
|
||||
height: auto;
|
||||
line-height: 1.5;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-all;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,542 @@
|
|||
<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() {
|
||||
if (this.value.mode == 'custom-rubik-cube') {
|
||||
this.value.diyHtml = this.value.diyHtml.replace(/"/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();
|
||||
}
|
||||
}
|
||||
},
|
||||
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;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* 魔方:单行多个,平分宽度
|
||||
* 公式:
|
||||
* 宽度:屏幕宽度/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'; // 划分规则,left:左,right:右
|
||||
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;// 因为这里使用px进行计算;最后结果会转换为rpx来适应屏幕的变化
|
||||
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>
|
||||
|
|
@ -0,0 +1,130 @@
|
|||
<template>
|
||||
<view class="search-box" :style="searchWrapCss">
|
||||
<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">
|
||||
<input
|
||||
type="text"
|
||||
class="uni-input ns-font-size-base"
|
||||
maxlength="50"
|
||||
:placeholder="value.title"
|
||||
v-model="searchText"
|
||||
@confirm="search()"
|
||||
disabled="true"
|
||||
@click="search()"
|
||||
:placeholderStyle="placeholderStyle"
|
||||
/>
|
||||
<text class="iconfont icon-sousuo3" @click="search()" :style="{ color: value.textColor ? value.textColor : 'rgba(0,0,0,0)' }"></text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// 搜索
|
||||
export default {
|
||||
name: 'diy-search',
|
||||
props: {
|
||||
value: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
searchText: ''
|
||||
};
|
||||
},
|
||||
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;';
|
||||
}
|
||||
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() {},
|
||||
methods: {
|
||||
search() {
|
||||
this.$util.redirectTo('/pages_tool/goods/search');
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
/deep/ .uni-input-placeholder {
|
||||
overflow: initial;
|
||||
}
|
||||
.search-box {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.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;
|
||||
}
|
||||
|
||||
.search-content input {
|
||||
box-sizing: border-box;
|
||||
display: block;
|
||||
height: 77rpx;
|
||||
width: 100%;
|
||||
padding: 0 20rpx 0 40rpx;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.search-content .iconfont {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: 4rpx;
|
||||
transform: translateY(-50%);
|
||||
font-size: 36rpx;
|
||||
z-index: 10;
|
||||
width: 80rpx;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,223 @@
|
|||
<template>
|
||||
<view class="store-info" v-if="store">
|
||||
<view class="store-info-top">
|
||||
<view class="info-image">
|
||||
<image :src="$util.img(store.store_image)" v-if="store.store_image" mode="aspectFit"></image>
|
||||
<image :src="$util.getDefaultImage().store" v-else></image>
|
||||
</view>
|
||||
<view class="info-desc">
|
||||
<view class="store-name">{{ store.store_name }}</view>
|
||||
<view class="item" v-if="store.open_date">
|
||||
<text>营业时间:</text>
|
||||
<text>{{ store.open_date }}</text>
|
||||
</view>
|
||||
<view class="item" v-if="store.telphone">
|
||||
<text>联系电话:</text>
|
||||
<text @click="phoneCall">{{ store.telphone }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- <text class="store-whole-country" @click="clearStore">
|
||||
全国
|
||||
<text class="iconfont icon-right"></text>
|
||||
</text> -->
|
||||
</view>
|
||||
<view class="store-map">
|
||||
<text>门店地图</text>
|
||||
<map class="map" :latitude="store.latitude" :longitude="store.longitude" :markers="covers"></map>
|
||||
</view>
|
||||
<view class="store-info-bottom" @click="mapRoute()" v-if="store.full_address || store.address">
|
||||
<view class="address-wrap">
|
||||
<view>{{ store.full_address + store.address }}</view>
|
||||
<text>距您当前位置{{ store.distance }}km</text>
|
||||
</view>
|
||||
<image :src="$util.img('addon/store/component/view/store_info/img/position.png')" />
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Map from '@/common/js/map/openMap.js';
|
||||
export default {
|
||||
props: {
|
||||
value: {
|
||||
type: Object
|
||||
},
|
||||
storeId: {
|
||||
type: [String, Number],
|
||||
default: 0
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
store: null,
|
||||
covers: []
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
// 定位信息
|
||||
location() {
|
||||
return this.$store.state.location;
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
if (this.location) {
|
||||
this.latitude = this.location.latitude;
|
||||
this.longitude = this.location.longitude;
|
||||
} else {
|
||||
this.$util.getLocation();
|
||||
}
|
||||
this.getInfo();
|
||||
},
|
||||
watch: {
|
||||
location: function(nVal) {
|
||||
if (nVal) {
|
||||
this.latitude = nVal.latitude;
|
||||
this.longitude = nVal.longitude;
|
||||
this.getInfo();
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
//打电话
|
||||
phoneCall() {
|
||||
uni.makePhoneCall({
|
||||
phoneNumber: this.store.telphone //仅为示例
|
||||
});
|
||||
},
|
||||
//获取门店详情
|
||||
getInfo() {
|
||||
let data = {
|
||||
store_id: this.storeId
|
||||
};
|
||||
if (this.latitude && this.longitude) {
|
||||
data.latitude = this.latitude;
|
||||
data.longitude = this.longitude;
|
||||
}
|
||||
this.$api.sendRequest({
|
||||
url: '/api/store/info',
|
||||
data: data,
|
||||
success: res => {
|
||||
if (res.data) {
|
||||
this.store = res.data;
|
||||
this.latitude = res.data.latitude;
|
||||
this.longitude = res.data.longitude;
|
||||
uni.setStorageSync('store', this.store);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
mapRoute() {
|
||||
Map.openMap(Number(this.latitude), Number(this.longitude), this.store_name, 'gcj02');
|
||||
},
|
||||
clearStore() {
|
||||
let _this = getCurrentPages()[getCurrentPages().length - 1];
|
||||
uni.setStorageSync('store', '');
|
||||
_this.refresh();
|
||||
this.$util.redirectTo('/pages/index/index');
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.store-info {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
.store-info-top {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
border-radius: 18rpx;
|
||||
background: #ffffff;
|
||||
padding: 20rpx 28rpx;
|
||||
margin-bottom: 32rpx;
|
||||
|
||||
.info-image {
|
||||
width: 128rpx;
|
||||
height: 128rpx;
|
||||
float: left;
|
||||
margin-right: 20rpx;
|
||||
image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 5px;
|
||||
}
|
||||
}
|
||||
.info-desc {
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding-left: 20rpx;
|
||||
box-sizing: border-box;
|
||||
width: 70%;
|
||||
.store-name {
|
||||
align-items: center;
|
||||
font-size: $font-size-toolbar;
|
||||
color: #2b2b2e;
|
||||
margin-bottom: 20rpx;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 1;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
.item {
|
||||
font-size: $font-size-tag;
|
||||
margin-bottom: 20rpx;
|
||||
text:first-child {
|
||||
color: #333333;
|
||||
}
|
||||
text:last-child {
|
||||
color: #666666;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.store-whole-country {
|
||||
text {
|
||||
font-size: 26rpx;
|
||||
color: #666666;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.store-map {
|
||||
margin: 16px 0;
|
||||
text {
|
||||
color: #2b2b2e;
|
||||
margin-bottom: 10px;
|
||||
font-weight: bold;
|
||||
display: block;
|
||||
font-size: $font-size-toolbar;
|
||||
}
|
||||
.map {
|
||||
width: 100%;
|
||||
height: 450rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.store-info-bottom {
|
||||
background: #ffffff;
|
||||
padding: 20rpx 28rpx;
|
||||
border-radius: 18rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.address-wrap {
|
||||
flex: 1;
|
||||
view {
|
||||
margin-bottom: 8rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
text {
|
||||
color: #666666;
|
||||
font-size: $font-size-tag;
|
||||
}
|
||||
}
|
||||
image {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,381 @@
|
|||
<template>
|
||||
<view class="store-wrap">
|
||||
<block v-if="value.style == 1">
|
||||
<view class="store-box store-one">
|
||||
<view class="store-info">
|
||||
<view class="info-box" :style="{ color: value.textColor }" @click="toStoreList()">
|
||||
<block v-if="store.store_id">
|
||||
<text class="title">{{ store.store_name }}</text>
|
||||
<text>
|
||||
<text class="change margin-left">切换</text>
|
||||
<text class="iconfont icon-right"></text>
|
||||
</text>
|
||||
</block>
|
||||
<text class="title" v-else>{{load && !storeList.length ? '没有附近门店' : '定位中...'}}</text>
|
||||
</view>
|
||||
<view class="address-box" :style="{ color: value.textColor }">
|
||||
<view class="address" :style="{ color: value.textColor }">
|
||||
<text class="iconfont icon-dizhi"></text>
|
||||
<text v-if="store.store_id" @click="mapRoute">{{ store.full_address }}{{ store.address }}</text>
|
||||
<text v-else>获取当前位置...</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="store-image" @click="selectStore()">
|
||||
<image :src="$util.img(store.store_image)" v-if="store.store_image && store.store_id" mode="aspectFill"></image>
|
||||
<image :src="$util.getDefaultImage().store" v-else mode="aspectFill"></image>
|
||||
</view>
|
||||
</view>
|
||||
</block>
|
||||
|
||||
<block v-if="value.style == 2">
|
||||
<view class="store-box store-three" @click="toStoreList()">
|
||||
<view class="store-info">
|
||||
<view class="store-image" @click="selectStore()">
|
||||
<image :src="$util.img(store.store_image)" v-if="store.store_image && store.store_id" mode="aspectFill"></image>
|
||||
<image :src="$util.getDefaultImage().store" v-else mode="aspectFill"></image>
|
||||
</view>
|
||||
<view class="info-box" :style="{ color: value.textColor }">
|
||||
<block v-if="store.store_id">
|
||||
<text class="title">{{ store.store_name }}</text>
|
||||
<text>
|
||||
<text class="change margin-left">切换</text>
|
||||
<text class="iconfont icon-right"></text>
|
||||
</text>
|
||||
</block>
|
||||
<text class="title" v-else>{{load && !storeList.length ? '没有附近门店' : '定位中...'}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="store-icon" @click.stop="search()"><text class="iconfont icon-sousuo3" :style="{ color: value.textColor }"></text></view>
|
||||
</view>
|
||||
</block>
|
||||
|
||||
<block v-if="value.style == 3">
|
||||
<view class="store-box store-four" @click="toStoreList()">
|
||||
<view class="store-left-wrap">
|
||||
<block v-if="store.store_id">
|
||||
<text class="iconfont icon-weizhi" :style="{ color: value.textColor }"></text>
|
||||
<text class="title" :style="{ color: value.textColor }">{{ store.store_name }}</text>
|
||||
<text class="iconfont icon-unfold" :style="{ color: value.textColor }"></text>
|
||||
</block>
|
||||
<text class="title" v-else :style="{ color: value.textColor }">{{load && !storeList.length ? '没有附近门店' : '定位中...'}}</text>
|
||||
</view>
|
||||
<view class="store-right-search">
|
||||
<input type="text" class="uni-input font-size-tag" disabled placeholder="商品搜索" @click.stop="search()" />
|
||||
<text class="iconfont icon-sousuo3" @click.stop="search()"></text>
|
||||
</view>
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// 门店列表
|
||||
import Map from '@/common/js/map/openMap.js';
|
||||
export default {
|
||||
name: 'ns-store',
|
||||
props: {
|
||||
storeId: {
|
||||
type: [String, Number],
|
||||
default() {
|
||||
return 0;
|
||||
}
|
||||
},
|
||||
value: {
|
||||
type: Object
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
type: 'country',
|
||||
store: {
|
||||
store_name: ''
|
||||
},
|
||||
showStore: 1,
|
||||
size: 2,
|
||||
num: 1,
|
||||
storeList: [],
|
||||
latitude: null, // 纬度
|
||||
longitude: null ,// 经度
|
||||
load: false
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
// 定位信息
|
||||
location() {
|
||||
return this.$store.state.location;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
storeId() {
|
||||
if (uni.getStorageSync('store')) {
|
||||
this.store = uni.getStorageSync('store');
|
||||
} else {
|
||||
this.getStoreList();
|
||||
}
|
||||
},
|
||||
location: function(nVal) {
|
||||
if (nVal) {
|
||||
this.latitude = nVal.latitude;
|
||||
this.longitude = nVal.longitude;
|
||||
this.getStoreList();
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
if (this.location && this.store.store_id) {
|
||||
this.latitude = this.location.latitude;
|
||||
this.longitude = this.location.longitude;
|
||||
} else {
|
||||
this.$util.getLocation({
|
||||
fail:()=>{
|
||||
this.getStoreList();
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
//跳转至门店列表
|
||||
toStoreList() {
|
||||
this.$util.redirectTo('/pages_tool/index/storelist', {});
|
||||
},
|
||||
selectStore() {
|
||||
if (this.store.store_id) {
|
||||
this.$util.diyRedirectTo({
|
||||
store_id: this.store.store_id,
|
||||
wap_url: '/pages_tool/index/diy?name=' + 'DIY_STORE'
|
||||
});
|
||||
}
|
||||
},
|
||||
search() {
|
||||
this.$util.redirectTo('/pages_tool/goods/search');
|
||||
},
|
||||
//获取门店列表
|
||||
getStoreList() {
|
||||
this.load = false;
|
||||
let data = {};
|
||||
if (this.latitude && this.longitude) {
|
||||
data.latitude = this.latitude;
|
||||
data.longitude = this.longitude;
|
||||
}
|
||||
this.$api.sendRequest({
|
||||
url: '/api/store/page',
|
||||
data: data,
|
||||
success: res => {
|
||||
let newArr = [];
|
||||
let msg = res.message;
|
||||
if (res.code == 0 && res.data) {
|
||||
newArr = res.data.list;
|
||||
} else {
|
||||
this.$util.showToast({
|
||||
title: msg
|
||||
});
|
||||
}
|
||||
this.storeList = newArr;
|
||||
for (let i = 0; i < this.storeList.length; i++) {
|
||||
if (this.storeList[i].store_id == res.data.store_id) {
|
||||
this.store = this.storeList[i];
|
||||
uni.setStorageSync('store', this.storeList[i]);
|
||||
this.$forceUpdate();
|
||||
}
|
||||
}
|
||||
this.load = true;
|
||||
}
|
||||
});
|
||||
},
|
||||
mapRoute() {
|
||||
if (!isNaN(Number(this.store.latitude)) && !isNaN(Number(this.store.longitude))) {
|
||||
Map.openMap(Number(this.store.latitude), Number(this.store.longitude), this.store.store_name, 'gcj02');
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.store-wrap {
|
||||
padding: 20rpx 0;
|
||||
box-sizing: border-box;
|
||||
|
||||
.store-box {
|
||||
// padding: 20rpx 24rpx;
|
||||
box-sizing: border-box;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
.noStoreBox {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
line-height: 120rpx;
|
||||
color: #ffffff;
|
||||
}
|
||||
.store-info {
|
||||
height: 100rpx;
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
justify-content: space-around;
|
||||
margin-right: 20rpx;
|
||||
|
||||
.info-box {
|
||||
// color: #ffffff;
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
margin-bottom: 6rpx;
|
||||
|
||||
text {
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.title {
|
||||
max-width: 60%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
font-size: $font-size-toolbar;
|
||||
margin-right: 40rpx;
|
||||
}
|
||||
|
||||
.change {
|
||||
font-size: $font-size-goods-tag;
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
font-size: $font-size-goods-tag;
|
||||
}
|
||||
}
|
||||
.address-box {
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
color: #ffffff;
|
||||
}
|
||||
.address {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
// display: flex;
|
||||
width: 100%;
|
||||
// align-items: center;
|
||||
// color: #ffffff;
|
||||
line-height: 1.2;
|
||||
font-size: $font-size-goods-tag;
|
||||
|
||||
.iconfont {
|
||||
font-size: $font-size-goods-tag;
|
||||
margin-right: 6rpx;
|
||||
}
|
||||
|
||||
.store-address-info {
|
||||
width: calc(100% - 30rpx);
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.store-image {
|
||||
width: 72rpx;
|
||||
height: 72rpx;
|
||||
border-radius: 50%;
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.store-one,
|
||||
.store-three {
|
||||
padding: 0 20rpx;
|
||||
}
|
||||
|
||||
.store-two {
|
||||
.store-image {
|
||||
align-self: flex-start;
|
||||
margin-right: 14rpx;
|
||||
}
|
||||
.info-box {
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
.store-info {
|
||||
height: 106rpx;
|
||||
}
|
||||
.switchover {
|
||||
display: flex;
|
||||
width: 120rpx;
|
||||
}
|
||||
}
|
||||
.store-three {
|
||||
.store-info {
|
||||
height: auto;
|
||||
justify-content: flex-start;
|
||||
flex-direction: inherit;
|
||||
align-items: center;
|
||||
}
|
||||
.info-box {
|
||||
margin-left: 18rpx;
|
||||
margin-bottom: 0 !important;
|
||||
}
|
||||
.store-icon text {
|
||||
font-size: 36rpx;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.store-four {
|
||||
padding: 0 !important;
|
||||
|
||||
.store-left-wrap {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
line-height: 1;
|
||||
.icon-weizhi {
|
||||
margin-right: 6rpx;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.icon-unfold {
|
||||
margin-left: 6rpx;
|
||||
}
|
||||
|
||||
.title {
|
||||
display: inline-block;
|
||||
max-width: 160rpx;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
.store-right-search {
|
||||
width: calc(100% - 260rpx);
|
||||
position: relative;
|
||||
|
||||
input {
|
||||
width: 100%;
|
||||
height: 72rpx;
|
||||
line-height: 72rpx;
|
||||
background-color: #ffffff;
|
||||
border: none;
|
||||
border-radius: 72rpx;
|
||||
padding-left: 30rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.icon-sousuo3 {
|
||||
position: absolute;
|
||||
right: 30rpx;
|
||||
top: 10rpx;
|
||||
font-size: 28rpx;
|
||||
color: #909399;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
<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>
|
||||
.uni-view {
|
||||
font-size: 0;
|
||||
}
|
||||
.diy-text-nav >>> .uni-scroll-view::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -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>
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
<template>
|
||||
<video :src="$util.img(value.videoUrl)" :poster="$util.img(value.imageUrl)" :style="videoWarpCss"></video>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// 视频
|
||||
export default {
|
||||
name: 'diy-video',
|
||||
props: {
|
||||
value: {
|
||||
type: Object
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
created() {},
|
||||
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;';
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
},
|
||||
methods: {}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
video {
|
||||
width: 100%;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,545 @@
|
|||
// 商品详情业务
|
||||
import {
|
||||
Weixin
|
||||
} from '@/common/js/wx-jssdk.js';
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
skuId: 0,
|
||||
goodsId: 0,
|
||||
isIphoneX: false, //判断手机是否是iphoneX以上
|
||||
whetherCollection: 0,
|
||||
|
||||
//是否开启预览,0:不开启,1:开启
|
||||
preview: 0,
|
||||
token: "",
|
||||
videoContext: '',
|
||||
|
||||
// 媒体,图片,视频
|
||||
|
||||
// 解决每个商品SKU图片数量不同时,无法切换到第一个,导致轮播图显示不出来
|
||||
swiperInterval: 1,
|
||||
swiperAutoplay: false,
|
||||
swiperCurrent: 1,
|
||||
switchMedia: 'img',
|
||||
|
||||
//评价
|
||||
goodsEvaluate: [{
|
||||
member_headimg: '',
|
||||
member_name: '',
|
||||
content: '',
|
||||
images: [],
|
||||
create_time: 0,
|
||||
sku_name: ''
|
||||
}],
|
||||
evaluateConfig: {
|
||||
evaluate_audit: 1,
|
||||
evaluate_show: 0,
|
||||
evaluate_status: 1
|
||||
},
|
||||
|
||||
// 是否可分享到好物圈
|
||||
goodsCircle: false,
|
||||
memberId: 0,
|
||||
service: null,
|
||||
shareUrl: '', // 分享链接
|
||||
source_member: 0, //分享人的id
|
||||
isCommunity: false, //社群弹窗
|
||||
|
||||
poster: "-1", //海报
|
||||
posterMsg: "", //海报错误信息
|
||||
posterHeight: 0,
|
||||
posterParams: {}, //海报所需参数
|
||||
detailTab: 0,
|
||||
goodsRoute: '',
|
||||
posterApi: '',
|
||||
goodsAttrShow: false, // 商品属性是否展开
|
||||
|
||||
storeList: {
|
||||
data: [],
|
||||
page: 1,
|
||||
page_size: 10
|
||||
}, //门店列表
|
||||
latitude: null, // 纬度
|
||||
longitude: null, // 经度
|
||||
store: {},
|
||||
storeId: 0,
|
||||
evaluateCount: 0, // 商品评论数量
|
||||
deliveryType: null, // 配送方式
|
||||
isVirtual: 0 //是否为虚拟商品
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.isIphoneX = this.$util.uniappIsIPhoneX();
|
||||
this.token = uni.getStorageSync('token');
|
||||
|
||||
// 门店信息
|
||||
this.store = uni.getStorageSync('store') ? uni.getStorageSync('store') : {};
|
||||
if (this.store) this.storeId = this.store.store_id;
|
||||
|
||||
if (this.location) {
|
||||
this.latitude = this.location.latitude;
|
||||
this.longitude = this.location.longitude;
|
||||
} else {
|
||||
this.$util.getLocation();
|
||||
}
|
||||
this.getStoreData();
|
||||
},
|
||||
computed: {
|
||||
location() {
|
||||
return this.$store.state.location;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
init(params) {
|
||||
this.skuId = params.sku_id;
|
||||
this.goodsId = params.goods_id;
|
||||
this.preview = params.preview;
|
||||
this.source_member = params.source_member;
|
||||
this.whetherCollection = params.whetherCollection;
|
||||
this.posterParams = params.posterParams;
|
||||
|
||||
this.shareUrl = params.shareUrl;
|
||||
this.memberId = params.memberId;
|
||||
this.goodsRoute = params.goodsRoute;
|
||||
this.posterApi = params.posterApi;
|
||||
this.isVirtual = params.isVirtual;
|
||||
this.getService();
|
||||
|
||||
// 评价设置
|
||||
this.getEvaluateConfig();
|
||||
this.videoContext = uni.createVideoContext('goodsVideo');
|
||||
|
||||
// #ifdef MP-WEIXIN
|
||||
this.goodsSyncToGoodsCircle();
|
||||
// #endif
|
||||
|
||||
this.getWhetherCollection();
|
||||
|
||||
if (this.isVirtual == 0) this.getEnabledExpressType();
|
||||
},
|
||||
swiperChange(e) {
|
||||
this.swiperCurrent = e.detail.current + 1;
|
||||
},
|
||||
|
||||
//-------------------------------------服务-------------------------------------
|
||||
|
||||
openMerchantsServicePopup() {
|
||||
this.$refs.merchantsServicePopup.open();
|
||||
},
|
||||
closeMerchantsServicePopup() {
|
||||
this.$refs.merchantsServicePopup.close();
|
||||
},
|
||||
|
||||
//-------------------------------------门店列表-------------------------------------
|
||||
openStoreListPopup() {
|
||||
this.$refs.storeListPopup.open();
|
||||
},
|
||||
closeStoreListPopup() {
|
||||
this.$refs.storeListPopup.close();
|
||||
},
|
||||
getStoreData() {
|
||||
//门店列表
|
||||
let data = {
|
||||
page: this.storeList.page,
|
||||
page_size: this.storeList.page_size
|
||||
};
|
||||
if (this.latitude && this.longitude) {
|
||||
data.latitude = this.latitude;
|
||||
data.longitude = this.longitude;
|
||||
}
|
||||
this.$api.sendRequest({
|
||||
url: '/api/store/page',
|
||||
data: data,
|
||||
success: res => {
|
||||
if (this.storeList.page == 1) this.storeList.data == [];
|
||||
if (res.code >= 0 && res.data) {
|
||||
this.storeList.data = this.storeList.data.concat(res.data.list);
|
||||
} else {
|
||||
this.$util.showToast({
|
||||
title: res.message
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
selectStore(item) {
|
||||
this.$util.diyRedirectTo({
|
||||
store_id: item.store_id,
|
||||
wap_url: '/pages_tool/index/diy?name=' + 'DIY_STORE'
|
||||
});
|
||||
this.closeStoreListPopup();
|
||||
},
|
||||
//-------------------------------------属性-------------------------------------
|
||||
|
||||
switchGoodsAttr() {
|
||||
this.goodsAttrShow = !this.goodsAttrShow;
|
||||
},
|
||||
//获取用户是否关注
|
||||
async getWhetherCollection() {
|
||||
this.$api.sendRequest({
|
||||
url: "/api/goodscollect/iscollect",
|
||||
data: {
|
||||
goods_id: this.goodsId
|
||||
},
|
||||
success: res => {
|
||||
this.whetherCollection = res.data;
|
||||
}
|
||||
});
|
||||
},
|
||||
//-------------------------------------评价-------------------------------------
|
||||
//商品评论列表
|
||||
getGoodsEvaluate() {
|
||||
|
||||
this.$api.sendRequest({
|
||||
url: "/api/goodsevaluate/firstinfo",
|
||||
data: {
|
||||
goods_id: this.goodsSkuDetail.goods_id
|
||||
},
|
||||
success: res => {
|
||||
let data = res.data;
|
||||
if (data) {
|
||||
this.goodsEvaluate = data;
|
||||
this.goodsEvaluate.forEach((item, index) => {
|
||||
if (this.goodsEvaluate[index].images) this.goodsEvaluate[index].images =
|
||||
this.goodsEvaluate[index].images.split(",");
|
||||
if (this.goodsEvaluate[index].is_anonymous == 1) this.goodsEvaluate[
|
||||
index].member_name = this.goodsEvaluate[index].member_name
|
||||
.replace(
|
||||
this.goodsEvaluate[index].member_name.substring(1, this
|
||||
.goodsEvaluate[index].member_name.length - 1), '***')
|
||||
})
|
||||
// if (this.goodsEvaluate.images) this.goodsEvaluate.images = this.goodsEvaluate.images.split(",");
|
||||
// if (this.goodsEvaluate.is_anonymous == 1) this.goodsEvaluate.member_name = this.goodsEvaluate.member_name.replace(
|
||||
// this.goodsEvaluate.member_name.substring(1, this.goodsEvaluate.member_name.length - 1), '***')
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
//商品评论列表
|
||||
getGoodsEvaluateCount() {
|
||||
|
||||
this.$api.sendRequest({
|
||||
url: "/api/goodsevaluate/count",
|
||||
data: {
|
||||
goods_id: this.goodsSkuDetail.goods_id
|
||||
},
|
||||
success: res => {
|
||||
if (res.code >= 0) {
|
||||
this.evaluateCount = res.data;
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
// 预览评价图片
|
||||
previewEvaluate(index, img_index, field) {
|
||||
var paths = [];
|
||||
for (let i = 0; i < this.goodsEvaluate[index][field].length; i++) {
|
||||
paths.push(this.$util.img(this.goodsEvaluate[index][field][i]));
|
||||
}
|
||||
uni.previewImage({
|
||||
current: img_index,
|
||||
urls: paths
|
||||
});
|
||||
},
|
||||
//-------------------------------------关注-------------------------------------
|
||||
editCollection() {
|
||||
if (this.preview) return; // 开启预览,禁止任何操作和跳转
|
||||
|
||||
if (this.token) {
|
||||
|
||||
//未关注添加关注
|
||||
if (this.whetherCollection == 0) {
|
||||
this.$api.sendRequest({
|
||||
url: "/api/goodscollect/add",
|
||||
data: {
|
||||
sku_id: this.skuId,
|
||||
goods_id: this.goodsSkuDetail.goods_id,
|
||||
sku_name: this.goodsSkuDetail.sku_name,
|
||||
sku_price: this.goodsSkuDetail.show_price,
|
||||
sku_image: this.goodsSkuDetail.sku_image
|
||||
},
|
||||
success: res => {
|
||||
var data = res.data;
|
||||
if (data > 0) {
|
||||
this.whetherCollection = 1;
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
//已关注取消关注
|
||||
this.$api.sendRequest({
|
||||
url: "/api/goodscollect/delete",
|
||||
data: {
|
||||
goods_id: this.goodsSkuDetail.goods_id
|
||||
},
|
||||
success: res => {
|
||||
var data = res.data;
|
||||
if (data > 0) {
|
||||
this.whetherCollection = 0;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if (this.source_member) {
|
||||
this.$refs.login.open(this.shareUrl + '&source_member=' + this.source_member);
|
||||
} else {
|
||||
this.$refs.login.open(this.shareUrl);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
collection() {
|
||||
if (this.preview) return; // 开启预览,禁止任何操作和跳转
|
||||
this.editCollection();
|
||||
if (this.token) {
|
||||
return this.whetherCollection ? 0 : 1;
|
||||
}
|
||||
},
|
||||
//-------------------------------------分享-------------------------------------
|
||||
// 打开分享弹出层
|
||||
openSharePopup() {
|
||||
this.$refs.sharePopup.open();
|
||||
},
|
||||
// 关闭分享弹出层
|
||||
closeSharePopup() {
|
||||
this.$refs.sharePopup.close();
|
||||
},
|
||||
copyUrl() {
|
||||
let text = this.$config.h5Domain + this.shareUrl;
|
||||
if (this.memberId) text += '&source_member=' + this.memberId;
|
||||
this.$util.copy(text, () => {
|
||||
this.closeSharePopup();
|
||||
});
|
||||
},
|
||||
|
||||
//-------------------------------------海报-------------------------------------
|
||||
// 打开海报弹出层
|
||||
openPosterPopup() {
|
||||
this.getGoodsPoster();
|
||||
this.$refs.sharePopup.close();
|
||||
this.$refs.posterPopup.open();
|
||||
if (this.poster != '-1') {
|
||||
setTimeout(() => {
|
||||
let view = uni.createSelectorQuery().in(this).select(".poster-layer .image-wrap");
|
||||
view.fields({
|
||||
size: true,
|
||||
}, data => {
|
||||
let posterWhith = data.width;
|
||||
let ratio = parseFloat((740 / posterWhith).toFixed(2));
|
||||
if (this.token != '') {
|
||||
this.posterHeight = parseInt(1240 / ratio);
|
||||
} else {
|
||||
this.posterHeight = parseInt(1100 / ratio);
|
||||
}
|
||||
}).exec();
|
||||
}, 100);
|
||||
}
|
||||
},
|
||||
// 关闭海报弹出层
|
||||
closePosterPopup() {
|
||||
this.$refs.posterPopup.close();
|
||||
},
|
||||
//生成海报
|
||||
getGoodsPoster() {
|
||||
uni.showLoading({
|
||||
'title': '海报生成中...'
|
||||
})
|
||||
//活动海报信息
|
||||
if (this.memberId) this.posterParams.source_member = this.memberId;
|
||||
|
||||
this.$api.sendRequest({
|
||||
url: this.posterApi,
|
||||
data: {
|
||||
page: this.goodsRoute,
|
||||
qrcode_param: JSON.stringify(this.posterParams)
|
||||
},
|
||||
success: res => {
|
||||
if (res.code == 0) {
|
||||
this.poster = res.data.path + "?time=" + new Date().getTime();
|
||||
} else {
|
||||
this.posterMsg = res.message;
|
||||
}
|
||||
uni.hideLoading();
|
||||
},
|
||||
fail: err => {
|
||||
uni.hideLoading();
|
||||
}
|
||||
});
|
||||
},
|
||||
// 预览图片
|
||||
previewMedia(index) {
|
||||
var paths = [];
|
||||
for (let i = 0; i < this.goodsSkuDetail.sku_images.length; i++) {
|
||||
paths.push(this.$util.img(this.goodsSkuDetail.sku_images[i], {
|
||||
size: 'big'
|
||||
}));
|
||||
}
|
||||
uni.previewImage({
|
||||
current: index,
|
||||
urls: paths,
|
||||
// longPressActions: {
|
||||
// itemList: ['发送给朋友', '保存图片', '关注'],
|
||||
// success: function(data) {
|
||||
// console.log('选中了第' + (data.tapIndex + 1) + '个按钮,第' + (data.index + 1) + '张图片');
|
||||
// },
|
||||
// fail: function(err) {
|
||||
// console.log(err.errMsg);
|
||||
// }
|
||||
// }
|
||||
});
|
||||
},
|
||||
swiperImageError(index) {
|
||||
this.goodsSkuDetail.sku_images[index] = this.$util.getDefaultImage().goods;
|
||||
this.$forceUpdate();
|
||||
},
|
||||
// #ifdef MP || APP-PLUS
|
||||
//小程序中保存海报
|
||||
saveGoodsPoster() {
|
||||
let url = this.$util.img(this.poster);
|
||||
uni.downloadFile({
|
||||
url: url,
|
||||
success: (res) => {
|
||||
if (res.statusCode === 200) {
|
||||
uni.saveImageToPhotosAlbum({
|
||||
filePath: res.tempFilePath,
|
||||
success: () => {
|
||||
this.$util.showToast({
|
||||
title: "保存成功"
|
||||
});
|
||||
},
|
||||
fail: () => {
|
||||
this.$util.showToast({
|
||||
title: "保存失败,请稍后重试"
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
// #endif
|
||||
//售后保障查询
|
||||
getService() {
|
||||
this.$api.sendRequest({
|
||||
url: '/api/goods/aftersale',
|
||||
success: res => {
|
||||
if (res.code == 0 && res.data) {
|
||||
this.service = res.data;
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// #ifdef MP-WEIXIN
|
||||
/**
|
||||
* 将商品同步到微信圈子
|
||||
*/
|
||||
goodsSyncToGoodsCircle() {
|
||||
this.$api.sendRequest({
|
||||
url: '/goodscircle/api/goods/sync',
|
||||
data: {
|
||||
goods_id: this.goodsSkuDetail.goods_id
|
||||
},
|
||||
success: res => {
|
||||
if (res.code == 0) {
|
||||
this.goodsCircle = true;
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
/**
|
||||
* 将商品推荐到微信圈子
|
||||
*/
|
||||
openBusinessView() {
|
||||
if (wx.openBusinessView) {
|
||||
wx.openBusinessView({
|
||||
businessType: 'friendGoodsRecommend',
|
||||
extraData: {
|
||||
product: {
|
||||
item_code: this.goodsSkuDetail.goods_id,
|
||||
title: this.goodsSkuDetail.sku_name,
|
||||
image_list: this.goodsSkuDetail.sku_images.map((ele) => {
|
||||
return this.$util.img(ele);
|
||||
})
|
||||
}
|
||||
},
|
||||
success: function(res) {
|
||||
console.log('success', res);
|
||||
},
|
||||
fail: function(res) {
|
||||
console.log('fail', res);
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
// #endif
|
||||
getEvaluateConfig() {
|
||||
this.$api.sendRequest({
|
||||
url: '/api/goodsevaluate/config',
|
||||
success: res => {
|
||||
if (res.code == 0) {
|
||||
var data = res.data;
|
||||
this.evaluateConfig = data;
|
||||
if (this.evaluateConfig.evaluate_show == 1) {
|
||||
//商品评论
|
||||
this.getGoodsEvaluate();
|
||||
this.getGoodsEvaluateCount();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
toEvaluateDetail(id) {
|
||||
this.$util.redirectTo('/pages_tool/goods/evaluate', {
|
||||
goods_id: id
|
||||
});
|
||||
},
|
||||
showImg(e) {
|
||||
//拿到图片的路径里面的内容放在我们数组中
|
||||
let contentimg = e.target.dataset.nodes;
|
||||
let arrImg = [];
|
||||
for (var i = 0; i < contentimg.length; i++) {
|
||||
var img = contentimg[i].children;
|
||||
if (Array.isArray(img)) {
|
||||
for (var j = 0; j < img.length; j++) {
|
||||
if (img[j].attrs && img[j].name == "img") {
|
||||
if (img[j].attrs.src) {
|
||||
arrImg.push(img[j].attrs.src)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//最后一步就是把我们的所有图片放在预览的api中就可以了
|
||||
uni.previewImage({
|
||||
current: arrImg,
|
||||
urls: arrImg,
|
||||
})
|
||||
},
|
||||
|
||||
//-------------------------------------社群-------------------------------------
|
||||
|
||||
//添加福利群
|
||||
onCommunity() {
|
||||
this.isCommunity = true
|
||||
},
|
||||
onCloseCommunity() {
|
||||
this.isCommunity = false
|
||||
},
|
||||
/**
|
||||
* 查询启用的配送方式
|
||||
*/
|
||||
getEnabledExpressType() {
|
||||
this.$api.sendRequest({
|
||||
url: "/api/config/enabledexpresstype",
|
||||
success: res => {
|
||||
if (res.code == 0 && res.data) this.deliveryType = res.data;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,436 @@
|
|||
<template>
|
||||
<view>
|
||||
<view scroll-y="true" class="goods-detail" :class="isIphoneX ? 'active' : ''">
|
||||
<view class="goods-container">
|
||||
<!-- 弹幕 -->
|
||||
<pengpai-fadein-out v-if="goodsSkuDetail.barrage_show && goodsSkuDetail.barrageData" ref="pengpai" :duration="1600" :wait="1900" :top="200" :left="0" :radius="60" :loop="true" :info="goodsSkuDetail.barrageData"></pengpai-fadein-out>
|
||||
|
||||
<!-- 商品媒体信息 -->
|
||||
<view class="goods-media" :style="{height: goodsSkuDetail.swiperHeight}">
|
||||
<!-- 商品图片 -->
|
||||
<view class="goods-img" :class="{ show: switchMedia == 'img' }">
|
||||
<swiper class="swiper" @change="swiperChange" :interval="swiperInterval" :autoplay="swiperAutoplay" autoplay="true" interval="4000" circular="true">
|
||||
<swiper-item v-for="(item, index) in goodsSkuDetail.sku_images" :key="index" :item-id="'goods_id_' + index">
|
||||
<view class="item" @click="previewMedia(index)">
|
||||
<image :src="$util.img(item, { size: 'big' })" @error="swiperImageError(index)" mode="aspectFit" />
|
||||
</view>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
<view class="img-indicator-dots">
|
||||
<text>{{ swiperCurrent }}</text>
|
||||
<text v-if="goodsSkuDetail.sku_images">/{{ goodsSkuDetail.sku_images.length }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 商品视频 -->
|
||||
<view class="goods-video" :class="{ show: switchMedia == 'video' }">
|
||||
<video id="goodsVideo" :src="$util.img(goodsSkuDetail.video_url)" :poster="$util.img(goodsSkuDetail.sku_image, { size: 'big' })" objectFit="cover"></video>
|
||||
</view>
|
||||
|
||||
<!-- 切换视频、图片 -->
|
||||
<view class="media-mode" v-if="goodsSkuDetail.video_url != ''">
|
||||
<text :class="{ 'color-base-bg': switchMedia == 'video' }" @click="switchMedia = 'video'">{{ $lang('video') }}</text>
|
||||
<text :class="{ 'color-base-bg': switchMedia == 'img' }" @click="(switchMedia = 'img'), videoContext.pause()">{{ $lang('image') }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 价格区域 -->
|
||||
<view class="goods-gression">
|
||||
<slot name="price"></slot>
|
||||
</view>
|
||||
|
||||
<view class="newdetail margin-bottom">
|
||||
<!-- 入口区域 -->
|
||||
<slot name="entrance"></slot>
|
||||
|
||||
<!-- 配送 -->
|
||||
<view class="item delivery-type" v-if="goodsSkuDetail.is_virtual == 0" @click="$refs.deliveryType.open()">
|
||||
<view class="label">配送</view>
|
||||
<block v-if="deliveryType">
|
||||
<view class="box">
|
||||
<block v-for="(item, index) in deliveryType" :key="index">
|
||||
<text v-if="goodsSkuDetail.support_trade_type.indexOf(index) != -1">{{ item.name }}</text>
|
||||
</block>
|
||||
</view>
|
||||
<text class="iconfont icon-right"></text>
|
||||
</block>
|
||||
<block v-else><view class="box">商家未配置配送方式</view></block>
|
||||
</view>
|
||||
|
||||
<!-- 门店 -->
|
||||
<view class="item store-wrap" @click="openStoreListPopup()" v-if="addonIsExist.store && Object.keys(store).length" >
|
||||
<view class="label">门店</view>
|
||||
<view class="list-wrap">
|
||||
<view class="name-wrap">
|
||||
<text class="icondiy icon-system-shop"></text>
|
||||
<text class="name">{{store.store_name}}</text>
|
||||
</view>
|
||||
<view class="other-wrap">
|
||||
<text class="distance" v-if="parseFloat(store.distance)">距离{{ store.distance > 1 ? store.distance + 'km' : store.distance * 1000 + 'm' }}</text>
|
||||
<text class="decorate" v-if="parseFloat(store.distance)">.</text>
|
||||
<view class="address">{{ store.full_address + store.address }}</view>
|
||||
</view>
|
||||
</view>
|
||||
<text class="iconfont icon-right"></text>
|
||||
<!-- <view class="img-wrap"><image :src="$util.img('public/uniapp/goods/detail_more.png')" mode="aspectFit" /></view> -->
|
||||
</view>
|
||||
|
||||
<view class="item service" @click="openMerchantsServicePopup()" v-if="goodsSkuDetail.goods_service.length">
|
||||
<view class="label">服务</view>
|
||||
<view class="list-wrap">
|
||||
<view class="item-wrap" v-for="(item, index) in goodsSkuDetail.goods_service" :key="index" v-if="index < 3">
|
||||
<view class="item-wrap-box">
|
||||
<view class="item-wrap-icon">
|
||||
<text class="iconfont icon-dui" v-if="!item.icon || (!item.icon.imageUrl && !item.icon.icon)"></text>
|
||||
<image class="icon-img" v-else-if="item.icon.iconType == 'img'" :src=" $util.img(item.icon.imageUrl)" />
|
||||
<diy-icon class="icon-box" v-else-if="item.icon.iconType == 'icon'" :icon="item.icon.icon" :value="item.icon.style ? item.icon.style : null"></diy-icon>
|
||||
</view>
|
||||
<text>{{ item.service_name }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<text class="iconfont icon-right"></text>
|
||||
<!-- <view class="img-wrap"><image :src="$util.img('public/uniapp/goods/detail_more.png')" mode="aspectFit" /></view> -->
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 配送方式 -->
|
||||
<view @touchmove.prevent.stop>
|
||||
<uni-popup ref="deliveryType" type="bottom">
|
||||
<view class="deliverytype-popup-layer popup-layer">
|
||||
<view class="head-wrap" @click="$refs.deliveryType.close()">
|
||||
<text>配送</text>
|
||||
<text class="iconfont icon-close"></text>
|
||||
</view>
|
||||
<scroll-view scroll-y class="type-body">
|
||||
<block v-for="(item, index) in deliveryType" :key="index">
|
||||
<view class="type-item" :class="{ 'not-support': goodsSkuDetail.support_trade_type.indexOf(index) == -1 }">
|
||||
<text class="iconfont" :class="item.icon"></text>
|
||||
<view class="content">
|
||||
<view class="title">{{ item.name }}</view>
|
||||
<view class="desc">{{ item.desc }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</block>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
</view>
|
||||
|
||||
<!-- 商品服务 -->
|
||||
<view @touchmove.prevent.stop>
|
||||
<uni-popup ref="merchantsServicePopup" type="bottom">
|
||||
<view class="goods-merchants-service-popup-layer popup-layer">
|
||||
<view class="head-wrap" @click="closeMerchantsServicePopup()">
|
||||
<text>商品服务</text>
|
||||
<text class="iconfont icon-close"></text>
|
||||
</view>
|
||||
<scroll-view scroll-y>
|
||||
<view class="item" :class="{ 'empty-desc': !item.desc }" v-for="(item, index) in goodsSkuDetail.goods_service" :key="index">
|
||||
<view class="item-icon" :class="{'empty-desc':!item.desc}">
|
||||
<text class="iconfont icon-dui color-base-text" v-if="!item.icon || (!item.icon.imageUrl && !item.icon.icon)"></text>
|
||||
<image class="icon-img" v-else-if="item.icon.iconType == 'img'" :src=" $util.img(item.icon.imageUrl)" />
|
||||
<diy-icon class="icon-box" v-else-if="item.icon.iconType == 'icon'" :icon="item.icon.icon" :value="item.icon.style ? item.icon.style : null"></diy-icon>
|
||||
</view>
|
||||
<view class="info-wrap">
|
||||
<text class="title">{{ item.service_name }}</text>
|
||||
<text class="describe" v-if="item.desc">{{ item.desc }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="button-box"><button type="primary" @click="closeMerchantsServicePopup()">确定</button></view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
</view>
|
||||
|
||||
<!-- 门店列表 -->
|
||||
<view @touchmove.prevent.stop>
|
||||
<uni-popup ref="storeListPopup" type="bottom">
|
||||
<view class="goods-merchants-service-popup-layer popup-layer store-list-wrap">
|
||||
<view class="head-wrap" @click="closeStoreListPopup()">
|
||||
<text>门店列表</text>
|
||||
<text class="iconfont icon-close"></text>
|
||||
</view>
|
||||
<scroll-view scroll-y>
|
||||
<view class="store-list-content">
|
||||
<view class="list-item" v-for="(item, index) in storeList.data" :key="index" @click="selectStore(item)">
|
||||
<view class="item-box">
|
||||
<view class="item-image">
|
||||
<image :src="$util.img(item.store_image)" v-if="item.store_image"></image>
|
||||
<image :src="$util.getDefaultImage().store" v-else></image>
|
||||
</view>
|
||||
<view class="item-info">
|
||||
<view class="item-title">
|
||||
<text class="title">{{ item.store_name }}</text>
|
||||
<text class="distance color-base-text" v-if="item.distance">
|
||||
距离{{ item.distance > 1 ? item.distance + 'km' : item.distance * 1000 + 'm' }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="item-time" v-if="item.open_date">营业时间:{{ item.open_date }}</view>
|
||||
<view class="item-address">{{ item.full_address + item.address }}</view>
|
||||
</view>
|
||||
<view class="item-right"><text class="iconfont icon-right"></text></view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
</view>
|
||||
|
||||
<!-- 业务区域 -->
|
||||
<slot name="business"></slot>
|
||||
|
||||
<view class="detail-community" v-if="goodsSkuDetail.qr_data && goodsSkuDetail.qr_data.qr_state == 1">
|
||||
<view class="community-box">
|
||||
<image :src="$util.img('public/uniapp/goods/detail_erweiImage.png')" mode="aspectFill"></image>
|
||||
<view class="community-content">
|
||||
<view class="community-title">{{ goodsSkuDetail.qr_data.qr_name }}</view>
|
||||
<view class="community-txt">{{ goodsSkuDetail.qr_data.community_describe }}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="community-btn" @click="onCommunity()">添加</view>
|
||||
</view>
|
||||
|
||||
<!-- 促销 -->
|
||||
<view class="community-model" @touchmove.prevent.stop @click.stop="onCloseCommunity()" v-show="isCommunity">
|
||||
<view class="community-model-content" @click.stop>
|
||||
<view class="community-model-content-radius"><view>添加社群</view></view>
|
||||
<view class="community-model-content-draw" v-if="goodsSkuDetail.qr_data && goodsSkuDetail.qr_data.qr_img">
|
||||
<image
|
||||
:src="
|
||||
goodsSkuDetail.qr_data.qr_img != '' && goodsSkuDetail.qr_data.qr_state == 1
|
||||
? $util.img(goodsSkuDetail.qr_data.qr_img)
|
||||
: $util.img('public/uniapp/goods/detail_erweiImage.png')
|
||||
"
|
||||
mode="aspectFill"
|
||||
show-menu-by-longpress="true"
|
||||
></image>
|
||||
</view>
|
||||
<view class="community-model-content-text">长按识别二维码,添加社群</view>
|
||||
</view>
|
||||
<view class="community-model-close" @click.stop="onCloseCommunity()"><text class="iconfont icon-close"></text></view>
|
||||
</view>
|
||||
|
||||
|
||||
<!-- 参与流程 -->
|
||||
<slot name="articipation"></slot>
|
||||
|
||||
<!-- 商品评价 -->
|
||||
<view class="group-wrap" v-if="evaluateConfig.evaluate_show == 1">
|
||||
<view class="goods-evaluate" @click="toEvaluateDetail(goodsSkuDetail.goods_id)">
|
||||
<view class="tit">
|
||||
<!-- <view class="tit" :class="{ active: goodsEvaluate.content }"> -->
|
||||
<view>
|
||||
<text class="color-title font-size-base">
|
||||
评价
|
||||
<text class="font-size-base">({{ evaluateCount }})</text>
|
||||
</text>
|
||||
<text class="evaluate-item-empty" v-if="!evaluateCount">暂无评价</text>
|
||||
<view class="evaluate-item-empty" v-else>
|
||||
<text class="font-size-tag">查看全部</text>
|
||||
<text class="iconfont icon-right font-size-tag"></text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="evaluate-item" v-for="(item, index) in goodsEvaluate" :key="index" v-if="item.content">
|
||||
<view class="evaluator">
|
||||
<view class="evaluator-info">
|
||||
<view class="evaluator-face">
|
||||
<image
|
||||
v-if="item.member_headimg"
|
||||
:src="$util.img(item.member_headimg)"
|
||||
@error="item.member_headimg = $util.getDefaultImage().head"
|
||||
mode="aspectFill"
|
||||
/>
|
||||
<image
|
||||
v-else
|
||||
:src="$util.getDefaultImage().head"
|
||||
@error="item.member_headimg = $util.getDefaultImage().head"
|
||||
mode="aspectFill"
|
||||
/>
|
||||
</view>
|
||||
<view class="evaluator-name-wrap">
|
||||
<text class="evaluator-name using-hidden" v-if="item.member_name.length > 2 && item.is_anonymous == 1">
|
||||
{{ item.member_name[0] }}***{{ item.member_name[item.member_name.length - 1] }}
|
||||
</text>
|
||||
<text class="evaluator-name using-hidden" v-else>{{ item.member_name }}</text>
|
||||
<view v-if="item.scores" class="evaluator-xing"><xiaoStarComponent :starCount="item.scores * 2"></xiaoStarComponent></view>
|
||||
</view>
|
||||
</view>
|
||||
<text class="time color-tip">{{ $util.timeStampTurnTime(item.create_time) }}</text>
|
||||
</view>
|
||||
<view class="cont margin-top">{{ item.content }}</view>
|
||||
<scroll-view scroll-x="true">
|
||||
<view class="evaluate-img" v-if="item.images">
|
||||
<view class="img-box" v-for="(img, img_index) in item.images" :key="img_index" @click="previewEvaluate(index, img_index, 'images')">
|
||||
<image :src="$util.img(img)" mode="aspectFill" />
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="goods-attr" v-if="goodsSkuDetail.goods_attr_format && goodsSkuDetail.goods_attr_format.length > 0">
|
||||
<view class="title">规格属性</view>
|
||||
<view class="attr-wrap">
|
||||
<block v-for="(item, index) in goodsSkuDetail.goods_attr_format" :key="index">
|
||||
<view class="item" v-if="goodsAttrShow || (!goodsAttrShow && index < 4)">
|
||||
<text class="attr-name">{{ item.attr_name }}</text>
|
||||
<text class="value-name">{{ item.attr_value_name }}</text>
|
||||
</view>
|
||||
</block>
|
||||
<view class="attr-action" v-if="goodsSkuDetail.goods_attr_format.length > 4" @click="switchGoodsAttr">
|
||||
<block v-if="!goodsAttrShow">
|
||||
展开<text class="iconfont icon-iconangledown"></text>
|
||||
</block>
|
||||
<block v-else>
|
||||
收起<text class="iconfont icon-iconangledown-copy"></text>
|
||||
</block>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 详情 -->
|
||||
<view class="goods-detail-tab">
|
||||
<view class="detail-tab">
|
||||
<!-- <view class="tab-line"></view> -->
|
||||
<view class="tab-item">商品详情</view>
|
||||
<!-- <view class="tab-line"></view> -->
|
||||
<!-- <view v-if="service.is_display == 1" class="tab-item" :class="detailTab == 1 ? 'active color-base-text' : ''" @click="detailTab = 1">售后保障</view> -->
|
||||
</view>
|
||||
|
||||
<view class="detail-content active" >
|
||||
<view class="detail-content-item">
|
||||
<view class="goods-details" v-if="goodsSkuDetail.goods_content">
|
||||
<rich-text :nodes="goodsSkuDetail.goods_content" @click="showImg($event)" :data-nodes="goodsSkuDetail.goods_content"></rich-text>
|
||||
</view>
|
||||
<view class="goods-details active" v-else>该商家暂无上传相关详情哦!</view>
|
||||
</view>
|
||||
<!-- <block v-if="service">
|
||||
<view class="detail-content-item" v-show="detailTab == 1 && service.is_display == 1">
|
||||
<view class="goods-details" v-if="service.content">
|
||||
<rich-text :nodes="service.content" @click="showImg($event)" :data-nodes="service.content"></rich-text>
|
||||
</view>
|
||||
<view class="goods-details active" v-else>该商品暂无相关售后哦!</view>
|
||||
</view>
|
||||
</block> -->
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 商品推荐 -->
|
||||
<ns-goods-recommend ref="goodrecommend" route="goods_detail"></ns-goods-recommend>
|
||||
|
||||
<ns-copyright></ns-copyright>
|
||||
|
||||
<!-- 海报 -->
|
||||
<view @touchmove.prevent.stop>
|
||||
<uni-popup ref="posterPopup" type="bottom" class="poster-layer">
|
||||
<template v-if="poster != '-1'">
|
||||
<view>
|
||||
<view class="image-wrap"><image :src="$util.img(poster)" :show-menu-by-longpress="true" /></view>
|
||||
<!-- #ifdef MP || APP-PLUS -->
|
||||
<view class="save" @click="saveGoodsPoster()">保存图片</view>
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef H5 -->
|
||||
<view class="save">长按保存图片</view>
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
<view class="close iconfont icon-close" @click="closePosterPopup()"></view>
|
||||
</template>
|
||||
<view v-else class="msg">{{ posterMsg }}</view>
|
||||
</uni-popup>
|
||||
</view>
|
||||
|
||||
<!-- 分享弹窗 -->
|
||||
<view @touchmove.prevent.stop>
|
||||
<uni-popup ref="sharePopup" type="bottom" class="share-popup">
|
||||
<view>
|
||||
<view class="share-title">分享</view>
|
||||
<view class="share-content">
|
||||
<!-- #ifdef MP -->
|
||||
<view class="share-box">
|
||||
<button class="share-btn" :plain="true" open-type="share">
|
||||
<view class="iconfont icon-share-friend"></view>
|
||||
<text>分享给好友</text>
|
||||
</button>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<view class="share-box" v-if="goodsCircle">
|
||||
<button class="share-btn" :plain="true" @click="openBusinessView">
|
||||
<view class="iconfont icon-haowuquan"></view>
|
||||
<text>分享到好物圈</text>
|
||||
</button>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
|
||||
<view class="share-box" @click="openPosterPopup">
|
||||
<button class="share-btn" :plain="true">
|
||||
<view class="iconfont icon-pengyouquan"></view>
|
||||
<text>生成分享海报</text>
|
||||
</button>
|
||||
</view>
|
||||
<!-- #ifdef H5 -->
|
||||
<view class="share-box" @click="copyUrl">
|
||||
<button class="share-btn" :plain="true">
|
||||
<view class="iconfont icon-fuzhilianjie"></view>
|
||||
<text>复制链接</text>
|
||||
</button>
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
<view class="share-footer" @click="closeSharePopup"><text>取消分享</text></view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
</view>
|
||||
|
||||
<slot name="fixedbtn"></slot>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 操作区域 -->
|
||||
<slot name="action"></slot>
|
||||
<to-top v-if="showTop" @toTop="scrollToTopNative()"></to-top>
|
||||
<ns-login ref="login"></ns-login>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import xiaoStarComponent from '@/components/xiao-star-component/xiao-star-component.vue';
|
||||
// 商品详情视图
|
||||
import uniPopup from '@/components/uni-popup/uni-popup.vue';
|
||||
import nsGoodsRecommend from '@/components/ns-goods-recommend/ns-goods-recommend.vue';
|
||||
import scroll from '@/common/js/scroll-view.js';
|
||||
import toTop from '@/components/toTop/toTop.vue';
|
||||
import goodsDetailBase from '@/common/js/goods_detail_base.js';
|
||||
import pengpaiFadeinOut from '@/components/pengpai-fadein-out/pengpai-fadein-out.vue';
|
||||
import detail from './detail.js';
|
||||
|
||||
export default {
|
||||
name: 'goods-detail-view',
|
||||
props: {
|
||||
goodsSkuDetail: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
},
|
||||
components: {
|
||||
uniPopup,
|
||||
nsGoodsRecommend,
|
||||
pengpaiFadeinOut,
|
||||
xiaoStarComponent,
|
||||
toTop
|
||||
},
|
||||
mixins: [scroll, detail]
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import '@/common/css/goods_detail.scss';
|
||||
</style>
|
||||
<style scoped></style>
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -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>
|
||||
|
|
@ -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_;
|
||||
|
|
@ -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>
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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, // 下拉状态(inOffset:1, outOffset:2, showLoading:3, endDownScroll:4)
|
||||
rate: Number // 下拉比率 (inOffset: rate<1; outOffset: rate>=1)
|
||||
},
|
||||
computed: {
|
||||
// 支付宝小程序需写成计算属性,prop定义default仍报错
|
||||
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>
|
||||
|
|
@ -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>
|
||||
|
|
@ -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: {
|
||||
// 支付宝小程序需写成计算属性,prop定义default仍报错
|
||||
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>
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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 // 上拉加载的状态:0(loading前),1(loading中),2(没有更多了)
|
||||
},
|
||||
computed: {
|
||||
// 支付宝小程序需写成计算属性,prop定义default仍报错
|
||||
mOption() {
|
||||
return this.option || {};
|
||||
},
|
||||
// 加载中
|
||||
isUpLoading() {
|
||||
return this.type === 1;
|
||||
},
|
||||
// 没有更多了
|
||||
isUpNoMore() {
|
||||
return this.type === 2;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@import './mescroll-up.css';
|
||||
</style>
|
||||
|
|
@ -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出现双滚动条的问题 */
|
||||
}
|
||||
|
|
@ -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, // 下拉刷新状态 (inOffset:1, outOffset:2, showLoading:3, endDownScroll:4)
|
||||
upLoadType: 0, // 上拉加载状态:0(loading前),1(loading中),2(没有更多了)
|
||||
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失效,需注意把fixed元素写在mescroll之外
|
||||
},
|
||||
// 是否在加载中
|
||||
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%"则等于windowHeight的10%
|
||||
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); // 派发点击回到顶部按钮的回调
|
||||
}
|
||||
},
|
||||
// 使用created初始化mescroll对象; 如果用mounted部分css样式编译到H5会失效
|
||||
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为滚动区域
|
||||
// init回调mescroll对象
|
||||
vm.$emit('init', vm.mescroll);
|
||||
|
||||
// 设置高度
|
||||
const sys = uni.getSystemInfoSync();
|
||||
if (sys.windowHeight) vm.windowHeight = sys.windowHeight;
|
||||
if (sys.statusBarHeight) vm.statusBarHeight = sys.statusBarHeight;
|
||||
// 使down的bottomOffset生效
|
||||
vm.mescroll.setBodyHeight(sys.windowHeight);
|
||||
|
||||
// 因为使用的是page的scroll,这里需自定义scrollTo
|
||||
vm.mescroll.resetScrollTo((y, t) => {
|
||||
uni.pageScrollTo({
|
||||
scrollTop: y,
|
||||
duration: t
|
||||
});
|
||||
});
|
||||
|
||||
// 具体的界面如果不配置up.toTop.safearea,则取本vue的safearea值
|
||||
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>
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
// mescroll-body 和 mescroll-uni 通用
|
||||
|
||||
// import MescrollUni from "./mescroll-uni.vue";
|
||||
// import MescrollBody from "./mescroll-body.vue";
|
||||
|
||||
const MescrollMixin = {
|
||||
// components: { // 非H5端无法通过mixin注册组件, 只能在main.js中注册全局组件或具体界面中注册
|
||||
// MescrollUni,
|
||||
// MescrollBody
|
||||
// },
|
||||
data() {
|
||||
return {
|
||||
mescroll: null //mescroll实例对象
|
||||
}
|
||||
},
|
||||
// 注册系统自带的下拉刷新 (配置down.native为true时生效, 还需在pages配置enablePullDownRefresh:true;详请参考mescroll-native的案例)
|
||||
onPullDownRefresh() {
|
||||
this.mescroll && this.mescroll.onPullDownRefresh();
|
||||
},
|
||||
// 注册列表滚动事件,用于判定在顶部可下拉刷新,在指定位置可显示隐藏回到顶部按钮 (此方法为页面生命周期,无法在子组件中触发, 仅在mescroll-body生效)
|
||||
onPageScroll(e) {
|
||||
this.mescroll && this.mescroll.onPageScroll(e);
|
||||
},
|
||||
// 注册滚动到底部的事件,用于上拉加载 (此方法为页面生命周期,无法在子组件中触发, 仅在mescroll-body生效)
|
||||
onReachBottom() {
|
||||
this.mescroll && this.mescroll.onReachBottom();
|
||||
},
|
||||
methods: {
|
||||
// mescroll组件初始化的回调,可获取到mescroll对象
|
||||
mescrollInit(mescroll) {
|
||||
this.mescroll = mescroll;
|
||||
this.mescrollInitByRef(); // 兼容字节跳动小程序
|
||||
},
|
||||
// 以ref的方式初始化mescroll对象 (兼容字节跳动小程序: http://www.mescroll.com/qa.html?v=20200107#q26)
|
||||
mescrollInitByRef() {
|
||||
if (!this.mescroll || !this.mescroll.resetUpScroll) {
|
||||
let mescrollRef = this.$refs.mescrollRef;
|
||||
if (mescrollRef) this.mescroll = mescrollRef.mescroll
|
||||
}
|
||||
},
|
||||
// 下拉刷新的回调
|
||||
downCallback() {
|
||||
// mixin默认resetUpScroll
|
||||
this.mescroll.resetUpScroll()
|
||||
},
|
||||
// 上拉加载的回调
|
||||
upCallback() {
|
||||
// mixin默认延时500自动结束加载
|
||||
setTimeout(() => {
|
||||
this.mescroll.endErr();
|
||||
}, 500)
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.mescrollInitByRef(); // 兼容字节跳动小程序, 避免未设置@init或@init此时未能取到ref的情况
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export default MescrollMixin;
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
// 全局配置
|
||||
// mescroll-body 和 mescroll-uni 通用
|
||||
const GlobalOption = {
|
||||
down: {
|
||||
// 其他down的配置参数也可以写,这里只展示了常用的配置:
|
||||
textInOffset: '下拉刷新', // 下拉的距离在offset范围内的提示文本
|
||||
textOutOffset: '释放更新', // 下拉的距离大于offset范围的提示文本
|
||||
textLoading: '加载中 ...', // 加载中的提示文本
|
||||
offset: 80, // 在列表顶部,下拉大于80px,松手即可触发下拉刷新的回调
|
||||
native: false // 是否使用系统自带的下拉刷新; 默认false; 仅在mescroll-body生效 (值为true时,还需在pages配置enablePullDownRefresh:true;详请参考mescroll-native的案例)
|
||||
},
|
||||
up: {
|
||||
// 其他up的配置参数也可以写,这里只展示了常用的配置:
|
||||
textLoading: '加载中 ...', // 加载中的提示文本
|
||||
textNoMore: '', // 没有更多数据的提示文本
|
||||
// textNoMore: '— 我是有底线的 —', // 没有更多数据的提示文本
|
||||
offset: 80, // 距底部多远时,触发upCallback
|
||||
isBounce: false, // 默认禁止橡皮筋的回弹效果, 必读事项: http://www.mescroll.com/qa.html?v=190725#q25
|
||||
toTop: {
|
||||
// 回到顶部按钮,需配置src才显示
|
||||
src: "http://www.mescroll.com/img/mescroll-totop.png?v=1", // 图片路径 (建议放入static目录, 如 /static/img/mescroll-totop.png )
|
||||
offset: 1000, // 列表滚动多少距离才显示回到顶部按钮,默认1000px
|
||||
right: 20, // 到右边的距离, 默认20 (支持"20rpx", "20px", "20%"格式的值, 纯数字则默认单位rpx)
|
||||
bottom: 120, // 到底部的距离, 默认120 (支持"20rpx", "20px", "20%"格式的值, 纯数字则默认单位rpx)
|
||||
width: 72 // 回到顶部图标的宽度, 默认72 (支持"20rpx", "20px", "20%"格式的值, 纯数字则默认单位rpx)
|
||||
},
|
||||
empty: {
|
||||
use: true, // 是否显示空布局
|
||||
icon: "http://www.mescroll.com/img/mescroll-empty.png?v=1", // 图标路径 (建议放入static目录, 如 /static/img/mescroll-empty.png )
|
||||
tip: '~ 暂无相关数据 ~' // 提示
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default GlobalOption
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
page {
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
/* 避免设置padding出现双滚动条的问题 */
|
||||
}
|
||||
|
||||
.mescroll-uni-warp {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.mescroll-uni {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
min-height: 200rpx;
|
||||
overflow-y: auto;
|
||||
box-sizing: border-box;
|
||||
/* 避免设置padding出现双滚动条的问题 */
|
||||
}
|
||||
|
||||
/* 定位的方式固定高度 */
|
||||
.mescroll-uni-fixed {
|
||||
z-index: 1;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
width: auto;
|
||||
/* 使right生效 */
|
||||
height: auto;
|
||||
/* 使bottom生效 */
|
||||
}
|
||||
|
|
@ -0,0 +1,841 @@
|
|||
/* mescroll
|
||||
* version 1.2.3
|
||||
* 2020-02-18 wenju
|
||||
* http://www.mescroll.com
|
||||
*/
|
||||
|
||||
export default function MeScroll(options, isScrollBody) {
|
||||
let me = this;
|
||||
me.version = '1.2.3'; // mescroll版本号
|
||||
me.options = options || {}; // 配置
|
||||
me.isScrollBody = isScrollBody || false; // 滚动区域是否为原生页面滚动; 默认为scroll-view
|
||||
|
||||
me.isDownScrolling = false; // 是否在执行下拉刷新的回调
|
||||
me.isUpScrolling = false; // 是否在执行上拉加载的回调
|
||||
let hasDownCallback = me.options.down && me.options.down.callback; // 是否配置了down的callback
|
||||
|
||||
// 初始化下拉刷新
|
||||
me.initDownScroll();
|
||||
// 初始化上拉加载,则初始化
|
||||
me.initUpScroll();
|
||||
|
||||
// 自动加载
|
||||
setTimeout(function() { // 待主线程执行完毕再执行,避免new MeScroll未初始化,在回调获取不到mescroll的实例
|
||||
// 自动触发下拉刷新 (只有配置了down的callback才自动触发下拉刷新)
|
||||
if (me.optDown.use && me.optDown.auto && hasDownCallback) {
|
||||
if (me.optDown.autoShowLoading) {
|
||||
me.triggerDownScroll(); // 显示下拉进度,执行下拉回调
|
||||
} else {
|
||||
me.optDown.callback && me.optDown.callback(me); // 不显示下拉进度,直接执行下拉回调
|
||||
}
|
||||
}
|
||||
// 自动触发上拉加载
|
||||
setTimeout(function() { // 延时确保先执行down的callback,再执行up的callback,因为部分小程序emit是异步,会导致isUpAutoLoad判断有误
|
||||
me.optUp.use && me.optUp.auto && !me.isUpAutoLoad && me.triggerUpScroll();
|
||||
}, 100)
|
||||
}, 30); // 需让me.optDown.inited和me.optUp.inited先执行
|
||||
}
|
||||
|
||||
/* 配置参数:下拉刷新 */
|
||||
MeScroll.prototype.extendDownScroll = function(optDown) {
|
||||
// 下拉刷新的配置
|
||||
MeScroll.extend(optDown, {
|
||||
use: true, // 是否启用下拉刷新; 默认true
|
||||
auto: true, // 是否在初始化完毕之后自动执行下拉刷新的回调; 默认true
|
||||
native: false, // 是否使用系统自带的下拉刷新; 默认false; 仅mescroll-body生效 (值为true时,还需在pages配置enablePullDownRefresh:true;详请参考mescroll-native的案例)
|
||||
autoShowLoading: false, // 如果设置auto=true(在初始化完毕之后自动执行下拉刷新的回调),那么是否显示下拉刷新的进度; 默认false
|
||||
isLock: false, // 是否锁定下拉刷新,默认false;
|
||||
offset: 80, // 在列表顶部,下拉大于80px,松手即可触发下拉刷新的回调
|
||||
startTop: 100, // scroll-view滚动到顶部时,此时的scroll-top不一定为0, 此值用于控制最大的误差
|
||||
fps: 80, // 下拉节流 (值越大每秒刷新频率越高)
|
||||
inOffsetRate: 1, // 在列表顶部,下拉的距离小于offset时,改变下拉区域高度比例;值小于1且越接近0,高度变化越小,表现为越往下越难拉
|
||||
outOffsetRate: 0.2, // 在列表顶部,下拉的距离大于offset时,改变下拉区域高度比例;值小于1且越接近0,高度变化越小,表现为越往下越难拉
|
||||
bottomOffset: 20, // 当手指touchmove位置在距离body底部20px范围内的时候结束上拉刷新,避免Webview嵌套导致touchend事件不执行
|
||||
minAngle: 45, // 向下滑动最少偏移的角度,取值区间 [0,90];默认45度,即向下滑动的角度大于45度则触发下拉;而小于45度,将不触发下拉,避免与左右滑动的轮播等组件冲突;
|
||||
textInOffset: '下拉刷新', // 下拉的距离在offset范围内的提示文本
|
||||
textOutOffset: '释放更新', // 下拉的距离大于offset范围的提示文本
|
||||
textLoading: '加载中 ...', // 加载中的提示文本
|
||||
inited: null, // 下拉刷新初始化完毕的回调
|
||||
inOffset: null, // 下拉的距离进入offset范围内那一刻的回调
|
||||
outOffset: null, // 下拉的距离大于offset那一刻的回调
|
||||
onMoving: null, // 下拉过程中的回调,滑动过程一直在执行; rate下拉区域当前高度与指定距离的比值(inOffset: rate<1; outOffset: rate>=1); downHight当前下拉区域的高度
|
||||
beforeLoading: null, // 准备触发下拉刷新的回调: 如果return true,将不触发showLoading和callback回调; 常用来完全自定义下拉刷新, 参考案例【淘宝 v6.8.0】
|
||||
showLoading: null, // 显示下拉刷新进度的回调
|
||||
afterLoading: null, // 准备结束下拉的回调. 返回结束下拉的延时执行时间,默认0ms; 常用于结束下拉之前再显示另外一小段动画,才去隐藏下拉刷新的场景, 参考案例【dotJump】
|
||||
endDownScroll: null, // 结束下拉刷新的回调
|
||||
callback: function(mescroll) {
|
||||
// 下拉刷新的回调;默认重置上拉加载列表为第一页
|
||||
mescroll.resetUpScroll();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/* 配置参数:上拉加载 */
|
||||
MeScroll.prototype.extendUpScroll = function(optUp) {
|
||||
// 上拉加载的配置
|
||||
MeScroll.extend(optUp, {
|
||||
use: true, // 是否启用上拉加载; 默认true
|
||||
auto: true, // 是否在初始化完毕之后自动执行上拉加载的回调; 默认true
|
||||
isLock: false, // 是否锁定上拉加载,默认false;
|
||||
isBoth: true, // 上拉加载时,如果滑动到列表顶部是否可以同时触发下拉刷新;默认true,两者可同时触发;
|
||||
isBounce: false, // 默认禁止橡皮筋的回弹效果, 必读事项: http://www.mescroll.com/qa.html?v=190725#q25
|
||||
callback: null, // 上拉加载的回调;function(page,mescroll){ }
|
||||
page: {
|
||||
num: 0, // 当前页码,默认0,回调之前会加1,即callback(page)会从1开始
|
||||
size: 10, // 每页数据的数量
|
||||
time: null // 加载第一页数据服务器返回的时间; 防止用户翻页时,后台新增了数据从而导致下一页数据重复;
|
||||
},
|
||||
noMoreSize: 5, // 如果列表已无数据,可设置列表的总数量要大于等于5条才显示无更多数据;避免列表数据过少(比如只有一条数据),显示无更多数据会不好看
|
||||
offset: 80, // 距底部多远时,触发upCallback
|
||||
textLoading: '加载中 ...', // 加载中的提示文本
|
||||
textNoMore: '-- END --', // 没有更多数据的提示文本
|
||||
inited: null, // 初始化完毕的回调
|
||||
showLoading: null, // 显示加载中的回调
|
||||
showNoMore: null, // 显示无更多数据的回调
|
||||
hideUpScroll: null, // 隐藏上拉加载的回调
|
||||
errDistance: 60, // endErr的时候需往上滑动一段距离,使其往下滑动时再次触发onReachBottom,仅mescroll-body生效
|
||||
toTop: {
|
||||
// 回到顶部按钮,需配置src才显示
|
||||
src: null, // 图片路径,默认null (绝对路径或网络图)
|
||||
offset: 1000, // 列表滚动多少距离才显示回到顶部按钮,默认1000
|
||||
duration: 300, // 回到顶部的动画时长,默认300ms (当值为0或300则使用系统自带回到顶部,更流畅; 其他值则通过step模拟,部分机型可能不够流畅,所以非特殊情况不建议修改此项)
|
||||
btnClick: null, // 点击按钮的回调
|
||||
onShow: null, // 是否显示的回调
|
||||
zIndex: 9990, // fixed定位z-index值
|
||||
left: null, // 到左边的距离, 默认null. 此项有值时,right不生效. (支持20, "20rpx", "20px", "20%"格式的值, 其中纯数字则默认单位rpx)
|
||||
right: 20, // 到右边的距离, 默认20 (支持20, "20rpx", "20px", "20%"格式的值, 其中纯数字则默认单位rpx)
|
||||
bottom: 120, // 到底部的距离, 默认120 (支持20, "20rpx", "20px", "20%"格式的值, 其中纯数字则默认单位rpx)
|
||||
safearea: false, // bottom的偏移量是否加上底部安全区的距离, 默认false, 需要适配iPhoneX时使用 (具体的界面如果不配置此项,则取本vue的safearea值)
|
||||
width: 72, // 回到顶部图标的宽度, 默认72 (支持20, "20rpx", "20px", "20%"格式的值, 其中纯数字则默认单位rpx)
|
||||
radius: "50%" // 圆角, 默认"50%" (支持20, "20rpx", "20px", "20%"格式的值, 其中纯数字则默认单位rpx)
|
||||
},
|
||||
empty: {
|
||||
use: true, // 是否显示空布局
|
||||
icon: null, // 图标路径
|
||||
tip: '~ 暂无相关数据 ~', // 提示
|
||||
btnText: '', // 按钮
|
||||
btnClick: null, // 点击按钮的回调
|
||||
onShow: null, // 是否显示的回调
|
||||
fixed: false, // 是否使用fixed定位,默认false; 配置fixed为true,以下的top和zIndex才生效 (transform会使fixed失效,最终会降级为absolute)
|
||||
top: "100rpx", // fixed定位的top值 (完整的单位值,如 "10%"; "100rpx")
|
||||
zIndex: 99 // fixed定位z-index值
|
||||
},
|
||||
onScroll: false // 是否监听滚动事件
|
||||
})
|
||||
}
|
||||
|
||||
/* 配置参数 */
|
||||
MeScroll.extend = function(userOption, defaultOption) {
|
||||
if (!userOption) return defaultOption;
|
||||
for (let key in defaultOption) {
|
||||
if (userOption[key] == null) {
|
||||
let def = defaultOption[key];
|
||||
if (def != null && typeof def === 'object') {
|
||||
userOption[key] = MeScroll.extend({}, def); // 深度匹配
|
||||
} else {
|
||||
userOption[key] = def;
|
||||
}
|
||||
} else if (typeof userOption[key] === 'object') {
|
||||
MeScroll.extend(userOption[key], defaultOption[key]); // 深度匹配
|
||||
}
|
||||
}
|
||||
return userOption;
|
||||
}
|
||||
|
||||
/* -------初始化下拉刷新------- */
|
||||
MeScroll.prototype.initDownScroll = function() {
|
||||
let me = this;
|
||||
// 配置参数
|
||||
me.optDown = me.options.down || {};
|
||||
me.extendDownScroll(me.optDown);
|
||||
|
||||
// 如果是mescroll-body且配置了native,则禁止自定义的下拉刷新
|
||||
if (me.isScrollBody && me.optDown.native) {
|
||||
me.optDown.use = false
|
||||
} else {
|
||||
me.optDown.native = false // 仅mescroll-body支持,mescroll-uni不支持
|
||||
}
|
||||
|
||||
me.downHight = 0; // 下拉区域的高度
|
||||
|
||||
// 在页面中加入下拉布局
|
||||
if (me.optDown.use && me.optDown.inited) {
|
||||
// 初始化完毕的回调
|
||||
setTimeout(function() { // 待主线程执行完毕再执行,避免new MeScroll未初始化,在回调获取不到mescroll的实例
|
||||
me.optDown.inited(me);
|
||||
}, 0)
|
||||
}
|
||||
}
|
||||
|
||||
/* 列表touchstart事件 */
|
||||
MeScroll.prototype.touchstartEvent = function(e) {
|
||||
if (!this.optDown.use) return;
|
||||
|
||||
this.startPoint = this.getPoint(e); // 记录起点
|
||||
this.startTop = this.getScrollTop(); // 记录此时的滚动条位置
|
||||
this.lastPoint = this.startPoint; // 重置上次move的点
|
||||
this.maxTouchmoveY = this.getBodyHeight() - this.optDown.bottomOffset; // 手指触摸的最大范围(写在touchstart避免body获取高度为0的情况)
|
||||
this.inTouchend = false; // 标记不是touchend
|
||||
}
|
||||
|
||||
/* 列表touchmove事件 */
|
||||
MeScroll.prototype.touchmoveEvent = function(e) {
|
||||
if (!this.optDown.use) return;
|
||||
if (!this.startPoint) return;
|
||||
let me = this;
|
||||
|
||||
// 节流
|
||||
let t = new Date().getTime();
|
||||
if (me.moveTime && t - me.moveTime < me.moveTimeDiff) { // 小于节流时间,则不处理
|
||||
return;
|
||||
} else {
|
||||
me.moveTime = t
|
||||
if (!me.moveTimeDiff) me.moveTimeDiff = 1000 / me.optDown.fps
|
||||
}
|
||||
|
||||
let scrollTop = me.getScrollTop(); // 当前滚动条的距离
|
||||
let curPoint = me.getPoint(e); // 当前点
|
||||
|
||||
let moveY = curPoint.y - me.startPoint.y; // 和起点比,移动的距离,大于0向下拉,小于0向上拉
|
||||
|
||||
// 向下拉 && 在顶部
|
||||
// mescroll-body,直接判定在顶部即可
|
||||
// scroll-view在滚动时不会触发touchmove,当触顶/底/左/右时,才会触发touchmove
|
||||
// scroll-view滚动到顶部时,scrollTop不一定为0; 在iOS的APP中scrollTop可能为负数,不一定和startTop相等
|
||||
if (moveY > 0 && (
|
||||
(me.isScrollBody && scrollTop <= 0) ||
|
||||
(!me.isScrollBody && (scrollTop <= 0 || (scrollTop <= me.optDown.startTop && scrollTop === me.startTop)))
|
||||
)) {
|
||||
// 可下拉的条件
|
||||
if (!me.inTouchend && !me.isDownScrolling && !me.optDown.isLock && (!me.isUpScrolling || (me.isUpScrolling &&
|
||||
me.optUp.isBoth))) {
|
||||
|
||||
// 下拉的角度是否在配置的范围内
|
||||
let angle = me.getAngle(me.lastPoint, curPoint); // 两点之间的角度,区间 [0,90]
|
||||
if (angle < me.optDown.minAngle) return; // 如果小于配置的角度,则不往下执行下拉刷新
|
||||
|
||||
// 如果手指的位置超过配置的距离,则提前结束下拉,避免Webview嵌套导致touchend无法触发
|
||||
if (me.maxTouchmoveY > 0 && curPoint.y >= me.maxTouchmoveY) {
|
||||
me.inTouchend = true; // 标记执行touchend
|
||||
me.touchendEvent(); // 提前触发touchend
|
||||
return;
|
||||
}
|
||||
|
||||
me.preventDefault(e); // 阻止默认事件
|
||||
|
||||
let diff = curPoint.y - me.lastPoint.y; // 和上次比,移动的距离 (大于0向下,小于0向上)
|
||||
|
||||
// 下拉距离 < 指定距离
|
||||
if (me.downHight < me.optDown.offset) {
|
||||
if (me.movetype !== 1) {
|
||||
me.movetype = 1; // 加入标记,保证只执行一次
|
||||
me.optDown.inOffset && me.optDown.inOffset(me); // 进入指定距离范围内那一刻的回调,只执行一次
|
||||
me.isMoveDown = true; // 标记下拉区域高度改变,在touchend重置回来
|
||||
}
|
||||
me.downHight += diff * me.optDown.inOffsetRate; // 越往下,高度变化越小
|
||||
|
||||
// 指定距离 <= 下拉距离
|
||||
} else {
|
||||
if (me.movetype !== 2) {
|
||||
me.movetype = 2; // 加入标记,保证只执行一次
|
||||
me.optDown.outOffset && me.optDown.outOffset(me); // 下拉超过指定距离那一刻的回调,只执行一次
|
||||
me.isMoveDown = true; // 标记下拉区域高度改变,在touchend重置回来
|
||||
}
|
||||
if (diff > 0) { // 向下拉
|
||||
me.downHight += Math.round(diff * me.optDown.outOffsetRate); // 越往下,高度变化越小
|
||||
} else { // 向上收
|
||||
me.downHight += diff; // 向上收回高度,则向上滑多少收多少高度
|
||||
}
|
||||
}
|
||||
|
||||
let rate = me.downHight / me.optDown.offset; // 下拉区域当前高度与指定距离的比值
|
||||
me.optDown.onMoving && me.optDown.onMoving(me, rate, me.downHight); // 下拉过程中的回调,一直在执行
|
||||
}
|
||||
}
|
||||
|
||||
me.lastPoint = curPoint; // 记录本次移动的点
|
||||
}
|
||||
|
||||
/* 列表touchend事件 */
|
||||
MeScroll.prototype.touchendEvent = function(e) {
|
||||
if (!this.optDown.use) return;
|
||||
// 如果下拉区域高度已改变,则需重置回来
|
||||
if (this.isMoveDown) {
|
||||
if (this.downHight >= this.optDown.offset) {
|
||||
// 符合触发刷新的条件
|
||||
this.triggerDownScroll();
|
||||
} else {
|
||||
// 不符合的话 则重置
|
||||
this.downHight = 0;
|
||||
this.optDown.endDownScroll && this.optDown.endDownScroll(this);
|
||||
}
|
||||
this.movetype = 0;
|
||||
this.isMoveDown = false;
|
||||
} else if (!this.isScrollBody && this.getScrollTop() === this.startTop) { // scroll-view到顶/左/右/底的滑动事件
|
||||
let isScrollUp = this.getPoint(e).y - this.startPoint.y < 0; // 和起点比,移动的距离,大于0向下拉,小于0向上拉
|
||||
// 上滑
|
||||
if (isScrollUp) {
|
||||
// 需检查滑动的角度
|
||||
let angle = this.getAngle(this.getPoint(e), this.startPoint); // 两点之间的角度,区间 [0,90]
|
||||
if (angle > 80) {
|
||||
// 检查并触发上拉
|
||||
this.triggerUpScroll(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 根据点击滑动事件获取第一个手指的坐标 */
|
||||
MeScroll.prototype.getPoint = function(e) {
|
||||
if (!e) {
|
||||
return {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
}
|
||||
if (e.touches && e.touches[0]) {
|
||||
return {
|
||||
x: e.touches[0].pageX,
|
||||
y: e.touches[0].pageY
|
||||
}
|
||||
} else if (e.changedTouches && e.changedTouches[0]) {
|
||||
return {
|
||||
x: e.changedTouches[0].pageX,
|
||||
y: e.changedTouches[0].pageY
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
x: e.clientX,
|
||||
y: e.clientY
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 计算两点之间的角度: 区间 [0,90]*/
|
||||
MeScroll.prototype.getAngle = function(p1, p2) {
|
||||
let x = Math.abs(p1.x - p2.x);
|
||||
let y = Math.abs(p1.y - p2.y);
|
||||
let z = Math.sqrt(x * x + y * y);
|
||||
let angle = 0;
|
||||
if (z !== 0) {
|
||||
angle = Math.asin(y / z) / Math.PI * 180;
|
||||
}
|
||||
return angle
|
||||
}
|
||||
|
||||
/* 触发下拉刷新 */
|
||||
MeScroll.prototype.triggerDownScroll = function() {
|
||||
if (this.optDown.beforeLoading && this.optDown.beforeLoading(this)) {
|
||||
//return true则处于完全自定义状态
|
||||
} else {
|
||||
this.showDownScroll(); // 下拉刷新中...
|
||||
this.optDown.callback && this.optDown.callback(this); // 执行回调,联网加载数据
|
||||
}
|
||||
}
|
||||
|
||||
/* 显示下拉进度布局 */
|
||||
MeScroll.prototype.showDownScroll = function() {
|
||||
this.isDownScrolling = true; // 标记下拉中
|
||||
if (this.optDown.native) {
|
||||
uni.startPullDownRefresh(); // 系统自带的下拉刷新
|
||||
this.optDown.showLoading && this.optDown.showLoading(this, 0); // 仍触发showLoading,因为上拉加载用到
|
||||
} else {
|
||||
this.downHight = this.optDown.offset; // 更新下拉区域高度
|
||||
this.optDown.showLoading && this.optDown.showLoading(this, this.downHight); // 下拉刷新中...
|
||||
}
|
||||
}
|
||||
|
||||
/* 显示系统自带的下拉刷新时需要处理的业务 */
|
||||
MeScroll.prototype.onPullDownRefresh = function() {
|
||||
this.isDownScrolling = true; // 标记下拉中
|
||||
this.optDown.showLoading && this.optDown.showLoading(this, 0); // 仍触发showLoading,因为上拉加载用到
|
||||
this.optDown.callback && this.optDown.callback(this); // 执行回调,联网加载数据
|
||||
}
|
||||
|
||||
/* 结束下拉刷新 */
|
||||
MeScroll.prototype.endDownScroll = function() {
|
||||
if (this.optDown.native) { // 结束原生下拉刷新
|
||||
this.isDownScrolling = false;
|
||||
this.optDown.endDownScroll && this.optDown.endDownScroll(this);
|
||||
uni.stopPullDownRefresh();
|
||||
return
|
||||
}
|
||||
let me = this;
|
||||
// 结束下拉刷新的方法
|
||||
let endScroll = function() {
|
||||
me.downHight = 0;
|
||||
me.isDownScrolling = false;
|
||||
me.optDown.endDownScroll && me.optDown.endDownScroll(me);
|
||||
!me.isScrollBody && me.setScrollHeight(0) // scroll-view重置滚动区域,使数据不满屏时仍可检查触发翻页
|
||||
}
|
||||
// 结束下拉刷新时的回调
|
||||
let delay = 0;
|
||||
if (me.optDown.afterLoading) delay = me.optDown.afterLoading(me); // 结束下拉刷新的延时,单位ms
|
||||
if (typeof delay === 'number' && delay > 0) {
|
||||
setTimeout(endScroll, delay);
|
||||
} else {
|
||||
endScroll();
|
||||
}
|
||||
}
|
||||
|
||||
/* 锁定下拉刷新:isLock=ture,null锁定;isLock=false解锁 */
|
||||
MeScroll.prototype.lockDownScroll = function(isLock) {
|
||||
if (isLock == null) isLock = true;
|
||||
this.optDown.isLock = isLock;
|
||||
}
|
||||
|
||||
/* 锁定上拉加载:isLock=ture,null锁定;isLock=false解锁 */
|
||||
MeScroll.prototype.lockUpScroll = function(isLock) {
|
||||
if (isLock == null) isLock = true;
|
||||
this.optUp.isLock = isLock;
|
||||
}
|
||||
|
||||
/* -------初始化上拉加载------- */
|
||||
MeScroll.prototype.initUpScroll = function() {
|
||||
let me = this;
|
||||
// 配置参数
|
||||
me.optUp = me.options.up || {
|
||||
use: false
|
||||
};
|
||||
me.extendUpScroll(me.optUp);
|
||||
|
||||
if (!me.optUp.isBounce) me.setBounce(false); // 不允许bounce时,需禁止window的touchmove事件
|
||||
|
||||
if (me.optUp.use === false) return; // 配置不使用上拉加载时,则不初始化上拉布局
|
||||
me.optUp.hasNext = true; // 如果使用上拉,则默认有下一页
|
||||
me.startNum = me.optUp.page.num + 1; // 记录page开始的页码
|
||||
|
||||
// 初始化完毕的回调
|
||||
if (me.optUp.inited) {
|
||||
setTimeout(function() { // 待主线程执行完毕再执行,避免new MeScroll未初始化,在回调获取不到mescroll的实例
|
||||
me.optUp.inited(me);
|
||||
}, 0)
|
||||
}
|
||||
}
|
||||
|
||||
/*滚动到底部的事件 (仅mescroll-body生效)*/
|
||||
MeScroll.prototype.onReachBottom = function() {
|
||||
if (this.isScrollBody && !this.isUpScrolling) { // 只能支持下拉刷新的时候同时可以触发上拉加载,否则滚动到底部就需要上滑一点才能触发onReachBottom
|
||||
if (!this.optUp.isLock && this.optUp.hasNext) {
|
||||
this.triggerUpScroll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*列表滚动事件 (仅mescroll-body生效)*/
|
||||
MeScroll.prototype.onPageScroll = function(e) {
|
||||
if (!this.isScrollBody) return;
|
||||
|
||||
// 更新滚动条的位置 (主要用于判断下拉刷新时,滚动条是否在顶部)
|
||||
this.setScrollTop(e.scrollTop);
|
||||
|
||||
// 顶部按钮的显示隐藏
|
||||
if (e.scrollTop >= this.optUp.toTop.offset) {
|
||||
this.showTopBtn();
|
||||
} else {
|
||||
this.hideTopBtn();
|
||||
}
|
||||
}
|
||||
|
||||
/*列表滚动事件*/
|
||||
MeScroll.prototype.scroll = function(e, onScroll) {
|
||||
// 更新滚动条的位置
|
||||
this.setScrollTop(e.scrollTop);
|
||||
// 更新滚动内容高度
|
||||
this.setScrollHeight(e.scrollHeight);
|
||||
|
||||
// 向上滑还是向下滑动
|
||||
if (this.preScrollY == null) this.preScrollY = 0;
|
||||
this.isScrollUp = e.scrollTop - this.preScrollY > 0;
|
||||
this.preScrollY = e.scrollTop;
|
||||
|
||||
// 上滑 && 检查并触发上拉
|
||||
this.isScrollUp && this.triggerUpScroll(true);
|
||||
|
||||
// 顶部按钮的显示隐藏
|
||||
if (e.scrollTop >= this.optUp.toTop.offset) {
|
||||
this.showTopBtn();
|
||||
} else {
|
||||
this.hideTopBtn();
|
||||
}
|
||||
|
||||
// 滑动监听
|
||||
this.optUp.onScroll && onScroll && onScroll()
|
||||
}
|
||||
|
||||
/* 触发上拉加载 */
|
||||
MeScroll.prototype.triggerUpScroll = function(isCheck) {
|
||||
if (!this.isUpScrolling && this.optUp.use && this.optUp.callback) {
|
||||
// 是否校验在底部; 默认不校验
|
||||
if (isCheck === true) {
|
||||
let canUp = false;
|
||||
// 还有下一页 && 没有锁定 && 不在下拉中
|
||||
if (this.optUp.hasNext && !this.optUp.isLock && !this.isDownScrolling) {
|
||||
if (this.getScrollBottom() <= this.optUp.offset) { // 到底部
|
||||
canUp = true; // 标记可上拉
|
||||
}
|
||||
}
|
||||
if (canUp === false) return;
|
||||
}
|
||||
this.showUpScroll(); // 上拉加载中...
|
||||
this.optUp.page.num++; // 预先加一页,如果失败则减回
|
||||
this.isUpAutoLoad = true; // 标记上拉已经自动执行过,避免初始化时多次触发上拉回调
|
||||
this.num = this.optUp.page.num; // 把最新的页数赋值在mescroll上,避免对page的影响
|
||||
this.size = this.optUp.page.size; // 把最新的页码赋值在mescroll上,避免对page的影响
|
||||
this.time = this.optUp.page.time; // 把最新的页码赋值在mescroll上,避免对page的影响
|
||||
this.optUp.callback(this); // 执行回调,联网加载数据
|
||||
}
|
||||
}
|
||||
|
||||
/* 显示上拉加载中 */
|
||||
MeScroll.prototype.showUpScroll = function() {
|
||||
this.isUpScrolling = true; // 标记上拉加载中
|
||||
this.optUp.showLoading && this.optUp.showLoading(this); // 回调
|
||||
}
|
||||
|
||||
/* 显示上拉无更多数据 */
|
||||
MeScroll.prototype.showNoMore = function() {
|
||||
this.optUp.hasNext = false; // 标记无更多数据
|
||||
this.optUp.showNoMore && this.optUp.showNoMore(this); // 回调
|
||||
}
|
||||
|
||||
/* 隐藏上拉区域**/
|
||||
MeScroll.prototype.hideUpScroll = function() {
|
||||
this.optUp.hideUpScroll && this.optUp.hideUpScroll(this); // 回调
|
||||
}
|
||||
|
||||
/* 结束上拉加载 */
|
||||
MeScroll.prototype.endUpScroll = function(isShowNoMore) {
|
||||
if (isShowNoMore != null) { // isShowNoMore=null,不处理下拉状态,下拉刷新的时候调用
|
||||
if (isShowNoMore) {
|
||||
this.showNoMore(); // isShowNoMore=true,显示无更多数据
|
||||
} else {
|
||||
this.hideUpScroll(); // isShowNoMore=false,隐藏上拉加载
|
||||
}
|
||||
}
|
||||
this.isUpScrolling = false; // 标记结束上拉加载
|
||||
}
|
||||
|
||||
/* 重置上拉加载列表为第一页
|
||||
*isShowLoading 是否显示进度布局;
|
||||
* 1.默认null,不传参,则显示上拉加载的进度布局
|
||||
* 2.传参true, 则显示下拉刷新的进度布局
|
||||
* 3.传参false,则不显示上拉和下拉的进度 (常用于静默更新列表数据)
|
||||
*/
|
||||
MeScroll.prototype.resetUpScroll = function(isShowLoading) {
|
||||
if (this.optUp && this.optUp.use) {
|
||||
let page = this.optUp.page;
|
||||
this.prePageNum = page.num; // 缓存重置前的页码,加载失败可退回
|
||||
this.prePageTime = page.time; // 缓存重置前的时间,加载失败可退回
|
||||
page.num = this.startNum; // 重置为第一页
|
||||
page.time = null; // 重置时间为空
|
||||
if (!this.isDownScrolling && isShowLoading !== false) { // 如果不是下拉刷新触发的resetUpScroll并且不配置列表静默更新,则显示进度;
|
||||
if (isShowLoading == null) {
|
||||
this.removeEmpty(); // 移除空布局
|
||||
this.showUpScroll(); // 不传参,默认显示上拉加载的进度布局
|
||||
} else {
|
||||
this.showDownScroll(); // 传true,显示下拉刷新的进度布局,不清空列表
|
||||
}
|
||||
}
|
||||
this.isUpAutoLoad = true; // 标记上拉已经自动执行过,避免初始化时多次触发上拉回调
|
||||
this.num = page.num; // 把最新的页数赋值在mescroll上,避免对page的影响
|
||||
this.size = page.size; // 把最新的页码赋值在mescroll上,避免对page的影响
|
||||
this.time = page.time; // 把最新的页码赋值在mescroll上,避免对page的影响
|
||||
this.optUp.callback && this.optUp.callback(this); // 执行上拉回调
|
||||
}
|
||||
}
|
||||
|
||||
/* 设置page.num的值 */
|
||||
MeScroll.prototype.setPageNum = function(num) {
|
||||
this.optUp.page.num = num - 1;
|
||||
}
|
||||
|
||||
/* 设置page.size的值 */
|
||||
MeScroll.prototype.setPageSize = function(size) {
|
||||
this.optUp.page.size = size;
|
||||
}
|
||||
|
||||
/* 联网回调成功,结束下拉刷新和上拉加载
|
||||
* dataSize: 当前页的数据量(必传)
|
||||
* totalPage: 总页数(必传)
|
||||
* systime: 服务器时间 (可空)
|
||||
*/
|
||||
MeScroll.prototype.endByPage = function(dataSize, totalPage, systime) {
|
||||
let hasNext;
|
||||
if (this.optUp.use && totalPage != null) hasNext = this.optUp.page.num < totalPage; // 是否还有下一页
|
||||
this.endSuccess(dataSize, hasNext, systime);
|
||||
}
|
||||
|
||||
/* 联网回调成功,结束下拉刷新和上拉加载
|
||||
* dataSize: 当前页的数据量(必传)
|
||||
* totalSize: 列表所有数据总数量(必传)
|
||||
* systime: 服务器时间 (可空)
|
||||
*/
|
||||
MeScroll.prototype.endBySize = function(dataSize, totalSize, systime) {
|
||||
let hasNext;
|
||||
if (this.optUp.use && totalSize != null) {
|
||||
let loadSize = (this.optUp.page.num - 1) * this.optUp.page.size + dataSize; // 已加载的数据总数
|
||||
hasNext = loadSize < totalSize; // 是否还有下一页
|
||||
}
|
||||
this.endSuccess(dataSize, hasNext, systime);
|
||||
}
|
||||
|
||||
/* 联网回调成功,结束下拉刷新和上拉加载
|
||||
* dataSize: 当前页的数据个数(不是所有页的数据总和),用于上拉加载判断是否还有下一页.如果不传,则会判断还有下一页
|
||||
* hasNext: 是否还有下一页,布尔类型;用来解决这个小问题:比如列表共有20条数据,每页加载10条,共2页.如果只根据dataSize判断,则需翻到第三页才会知道无更多数据,如果传了hasNext,则翻到第二页即可显示无更多数据.
|
||||
* systime: 服务器时间(可空);用来解决这个小问题:当准备翻下一页时,数据库新增了几条记录,此时翻下一页,前面的几条数据会和上一页的重复;这里传入了systime,那么upCallback的page.time就会有值,把page.time传给服务器,让后台过滤新加入的那几条记录
|
||||
*/
|
||||
MeScroll.prototype.endSuccess = function(dataSize, hasNext, systime) {
|
||||
let me = this;
|
||||
// 结束下拉刷新
|
||||
if (me.isDownScrolling) me.endDownScroll();
|
||||
|
||||
// 结束上拉加载
|
||||
if (me.optUp.use) {
|
||||
let isShowNoMore; // 是否已无更多数据
|
||||
if (dataSize != null) {
|
||||
let pageNum = me.optUp.page.num; // 当前页码
|
||||
let pageSize = me.optUp.page.size; // 每页长度
|
||||
// 如果是第一页
|
||||
if (pageNum === 1) {
|
||||
if (systime) me.optUp.page.time = systime; // 设置加载列表数据第一页的时间
|
||||
}
|
||||
if (dataSize < pageSize || hasNext === false) {
|
||||
// 返回的数据不满一页时,则说明已无更多数据
|
||||
me.optUp.hasNext = false;
|
||||
if (dataSize === 0 && pageNum === 1) {
|
||||
// 如果第一页无任何数据且配置了空布局
|
||||
isShowNoMore = false;
|
||||
me.showEmpty();
|
||||
} else {
|
||||
// 总列表数少于配置的数量,则不显示无更多数据
|
||||
let allDataSize = (pageNum - 1) * pageSize + dataSize;
|
||||
if (allDataSize < me.optUp.noMoreSize) {
|
||||
isShowNoMore = false;
|
||||
} else {
|
||||
isShowNoMore = true;
|
||||
}
|
||||
me.removeEmpty(); // 移除空布局
|
||||
}
|
||||
} else {
|
||||
// 还有下一页
|
||||
isShowNoMore = false;
|
||||
me.optUp.hasNext = true;
|
||||
me.removeEmpty(); // 移除空布局
|
||||
}
|
||||
}
|
||||
|
||||
// 隐藏上拉
|
||||
me.endUpScroll(isShowNoMore);
|
||||
}
|
||||
}
|
||||
|
||||
/* 回调失败,结束下拉刷新和上拉加载 */
|
||||
MeScroll.prototype.endErr = function(errDistance) {
|
||||
// 结束下拉,回调失败重置回原来的页码和时间
|
||||
if (this.isDownScrolling) {
|
||||
let page = this.optUp.page;
|
||||
if (page && this.prePageNum) {
|
||||
page.num = this.prePageNum;
|
||||
page.time = this.prePageTime;
|
||||
}
|
||||
this.endDownScroll();
|
||||
}
|
||||
// 结束上拉,回调失败重置回原来的页码
|
||||
if (this.isUpScrolling) {
|
||||
this.optUp.page.num--;
|
||||
this.endUpScroll(false);
|
||||
// 如果是mescroll-body,则需往回滚一定距离
|
||||
if (this.isScrollBody && errDistance !== 0) { // 不处理0
|
||||
if (!errDistance) errDistance = this.optUp.errDistance; // 不传,则取默认
|
||||
this.scrollTo(this.getScrollTop() - errDistance, 0) // 往上回滚的距离
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 显示空布局 */
|
||||
MeScroll.prototype.showEmpty = function() {
|
||||
this.optUp.empty.use && this.optUp.empty.onShow && this.optUp.empty.onShow(true)
|
||||
}
|
||||
|
||||
/* 移除空布局 */
|
||||
MeScroll.prototype.removeEmpty = function() {
|
||||
this.optUp.empty.use && this.optUp.empty.onShow && this.optUp.empty.onShow(false)
|
||||
}
|
||||
|
||||
/* 显示回到顶部的按钮 */
|
||||
MeScroll.prototype.showTopBtn = function() {
|
||||
if (!this.topBtnShow) {
|
||||
this.topBtnShow = true;
|
||||
this.optUp.toTop.onShow && this.optUp.toTop.onShow(true);
|
||||
}
|
||||
}
|
||||
|
||||
/* 隐藏回到顶部的按钮 */
|
||||
MeScroll.prototype.hideTopBtn = function() {
|
||||
if (this.topBtnShow) {
|
||||
this.topBtnShow = false;
|
||||
this.optUp.toTop.onShow && this.optUp.toTop.onShow(false);
|
||||
}
|
||||
}
|
||||
|
||||
/* 获取滚动条的位置 */
|
||||
MeScroll.prototype.getScrollTop = function() {
|
||||
return this.scrollTop || 0
|
||||
}
|
||||
|
||||
/* 记录滚动条的位置 */
|
||||
MeScroll.prototype.setScrollTop = function(y) {
|
||||
this.scrollTop = y;
|
||||
}
|
||||
|
||||
/* 滚动到指定位置 */
|
||||
MeScroll.prototype.scrollTo = function(y, t) {
|
||||
this.myScrollTo && this.myScrollTo(y, t) // scrollview需自定义回到顶部方法
|
||||
}
|
||||
|
||||
/* 自定义scrollTo */
|
||||
MeScroll.prototype.resetScrollTo = function(myScrollTo) {
|
||||
this.myScrollTo = myScrollTo
|
||||
}
|
||||
|
||||
/* 滚动条到底部的距离 */
|
||||
MeScroll.prototype.getScrollBottom = function() {
|
||||
return this.getScrollHeight() - this.getClientHeight() - this.getScrollTop()
|
||||
}
|
||||
|
||||
/* 计步器
|
||||
star: 开始值
|
||||
end: 结束值
|
||||
callback(step,timer): 回调step值,计步器timer,可自行通过window.clearInterval(timer)结束计步器;
|
||||
t: 计步时长,传0则直接回调end值;不传则默认300ms
|
||||
rate: 周期;不传则默认30ms计步一次
|
||||
* */
|
||||
MeScroll.prototype.getStep = function(star, end, callback, t, rate) {
|
||||
let diff = end - star; // 差值
|
||||
if (t === 0 || diff === 0) {
|
||||
callback && callback(end);
|
||||
return;
|
||||
}
|
||||
t = t || 300; // 时长 300ms
|
||||
rate = rate || 30; // 周期 30ms
|
||||
let count = t / rate; // 次数
|
||||
let step = diff / count; // 步长
|
||||
let i = 0; // 计数
|
||||
let timer = setInterval(function() {
|
||||
if (i < count - 1) {
|
||||
star += step;
|
||||
callback && callback(star, timer);
|
||||
i++;
|
||||
} else {
|
||||
callback && callback(end, timer); // 最后一次直接设置end,避免计算误差
|
||||
clearInterval(timer);
|
||||
}
|
||||
}, rate);
|
||||
}
|
||||
|
||||
/* 滚动容器的高度 */
|
||||
MeScroll.prototype.getClientHeight = function(isReal) {
|
||||
let h = this.clientHeight || 0
|
||||
if (h === 0 && isReal !== true) { // 未获取到容器的高度,可临时取body的高度 (可能会有误差)
|
||||
h = this.getBodyHeight()
|
||||
}
|
||||
return h
|
||||
}
|
||||
MeScroll.prototype.setClientHeight = function(h) {
|
||||
this.clientHeight = h;
|
||||
}
|
||||
|
||||
/* 滚动内容的高度 */
|
||||
MeScroll.prototype.getScrollHeight = function() {
|
||||
return this.scrollHeight || 0;
|
||||
}
|
||||
MeScroll.prototype.setScrollHeight = function(h) {
|
||||
this.scrollHeight = h;
|
||||
}
|
||||
|
||||
/* body的高度 */
|
||||
MeScroll.prototype.getBodyHeight = function() {
|
||||
return this.bodyHeight || 0;
|
||||
}
|
||||
MeScroll.prototype.setBodyHeight = function(h) {
|
||||
this.bodyHeight = h;
|
||||
}
|
||||
|
||||
/* 阻止浏览器默认滚动事件 */
|
||||
MeScroll.prototype.preventDefault = function(e) {
|
||||
// 小程序不支持e.preventDefault
|
||||
// app的bounce只能通过配置pages.json的style.app-plus.bounce为"none"来禁止
|
||||
// cancelable:是否可以被禁用; defaultPrevented:是否已经被禁用
|
||||
if (e && e.cancelable && !e.defaultPrevented) e.preventDefault()
|
||||
}
|
||||
|
||||
/* 是否允许下拉回弹(橡皮筋效果); true或null为允许; false禁止bounce */
|
||||
MeScroll.prototype.setBounce = function(isBounce) {
|
||||
// #ifdef H5
|
||||
if (isBounce === false) {
|
||||
this.optUp.isBounce = false; // 禁止
|
||||
// 标记当前页使用了mescroll (需延时,确保page已切换)
|
||||
setTimeout(function() {
|
||||
let uniPageDom = document.getElementsByTagName('uni-page')[0];
|
||||
uniPageDom && uniPageDom.setAttribute('use_mescroll', true)
|
||||
}, 30);
|
||||
// 避免重复添加事件
|
||||
if (window.isSetBounce) return;
|
||||
window.isSetBounce = true;
|
||||
// 需禁止window的touchmove事件才能有效的阻止bounce
|
||||
window.bounceTouchmove = function(e) {
|
||||
let el = e.target;
|
||||
// 当前touch的元素及父元素是否要拦截touchmove事件
|
||||
let isPrevent = true;
|
||||
while (el !== document.body && el !== document) {
|
||||
if (el.tagName === 'UNI-PAGE') { // 只扫描当前页
|
||||
if (!el.getAttribute('use_mescroll')) {
|
||||
isPrevent = false; // 如果当前页没有使用mescroll,则不阻止
|
||||
}
|
||||
break;
|
||||
}
|
||||
let cls = el.classList;
|
||||
if (cls) {
|
||||
if (cls.contains('mescroll-touch')) { // 采用scroll-view 此处不能过滤mescroll-uni,否则下拉仍然有回弹
|
||||
isPrevent = false; // mescroll-touch无需拦截touchmove事件
|
||||
break;
|
||||
} else if (cls.contains('mescroll-touch-x') || cls.contains('mescroll-touch-y')) {
|
||||
// 如果配置了水平或者垂直滑动
|
||||
let curX = e.touches ? e.touches[0].pageX : e.clientX; // 当前第一个手指距离列表顶部的距离x
|
||||
let curY = e.touches ? e.touches[0].pageY : e.clientY; // 当前第一个手指距离列表顶部的距离y
|
||||
if (!this.preWinX) this.preWinX = curX; // 设置上次移动的距离x
|
||||
if (!this.preWinY) this.preWinY = curY; // 设置上次移动的距离y
|
||||
// 计算两点之间的角度
|
||||
let x = Math.abs(this.preWinX - curX);
|
||||
let y = Math.abs(this.preWinY - curY);
|
||||
let z = Math.sqrt(x * x + y * y);
|
||||
this.preWinX = curX; // 记录本次curX的值
|
||||
this.preWinY = curY; // 记录本次curY的值
|
||||
if (z !== 0) {
|
||||
let angle = Math.asin(y / z) / Math.PI * 180; // 角度区间 [0,90]
|
||||
if ((angle <= 45 && cls.contains('mescroll-touch-x')) || (angle > 45 && cls.contains('mescroll-touch-y'))) {
|
||||
isPrevent = false; // 水平滑动或者垂直滑动,不拦截touchmove事件
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
el = el.parentNode; // 继续检查其父元素
|
||||
}
|
||||
// 拦截touchmove事件:是否可以被禁用&&是否已经被禁用 (这里不使用me.preventDefault(e)的方法,因为某些情况下会报找不到方法的异常)
|
||||
if (isPrevent && e.cancelable && !e.defaultPrevented && typeof e.preventDefault === "function") e.preventDefault();
|
||||
}
|
||||
window.addEventListener('touchmove', window.bounceTouchmove, {
|
||||
passive: false
|
||||
});
|
||||
} else {
|
||||
this.optUp.isBounce = true; // 允许
|
||||
if (window.bounceTouchmove) {
|
||||
window.removeEventListener('touchmove', window.bounceTouchmove);
|
||||
window.bounceTouchmove = null;
|
||||
window.isSetBounce = false;
|
||||
}
|
||||
}
|
||||
// #endif
|
||||
}
|
||||
|
|
@ -0,0 +1,416 @@
|
|||
<template>
|
||||
<view class="mescroll-uni-warp">
|
||||
<scroll-view
|
||||
:id="viewId"
|
||||
class="mescroll-uni"
|
||||
:class="{ 'mescroll-uni-fixed': isFixed }"
|
||||
:style="{
|
||||
height: scrollHeight,
|
||||
'padding-top': padTop,
|
||||
'padding-bottom': padBottom,
|
||||
'padding-bottom': padBottomConstant,
|
||||
'padding-bottom': padBottomEnv,
|
||||
top: fixedTop,
|
||||
bottom: fixedBottom,
|
||||
bottom: fixedBottomConstant,
|
||||
bottom: fixedBottomEnv
|
||||
}"
|
||||
:scroll-top="scrollTop"
|
||||
:scroll-with-animation="scrollAnim"
|
||||
@scroll="scroll"
|
||||
@touchstart="touchstartEvent"
|
||||
@touchmove="touchmoveEvent"
|
||||
@touchend="touchendEvent"
|
||||
@touchcancel="touchendEvent"
|
||||
:scroll-y="isDownReset"
|
||||
:enable-back-to-top="true"
|
||||
>
|
||||
<view class="mescroll-uni-content" :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> -->
|
||||
<ns-loading></ns-loading>
|
||||
</view>
|
||||
<!-- 无数据 -->
|
||||
<view v-if="upLoadType === 2" class="upwarp-nodata">{{ mescroll.optUp.textNoMore }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<!-- 回到顶部按钮 (fixed元素,需写在scroll-view外面,防止滚动的时候抖动)-->
|
||||
<mescroll-top v-if="showTop" v-model="isShowToTop" :option="mescroll.optUp.toTop" @click="toTopClick"></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';
|
||||
|
||||
import nsLoading from '@/components/ns-loading/ns-loading.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
MescrollEmpty,
|
||||
MescrollTop
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
mescroll: { optDown: {}, optUp: {} }, // mescroll实例
|
||||
viewId:
|
||||
'id_' +
|
||||
Math.random()
|
||||
.toString(36)
|
||||
.substr(2), // 随机生成mescroll的id(不能数字开头,否则找不到元素)
|
||||
downHight: 0, //下拉刷新: 容器高度
|
||||
downRate: 0, // 下拉比率(inOffset: rate<1; outOffset: rate>=1)
|
||||
downLoadType: 4, // 下拉刷新状态 (inOffset:1, outOffset:2, showLoading:3, endDownScroll:4)
|
||||
upLoadType: 0, // 上拉加载状态:0(loading前),1(loading中),2(没有更多了)
|
||||
isShowEmpty: false, // 是否显示空布局
|
||||
isShowToTop: false, // 是否显示回到顶部按钮
|
||||
scrollTop: 0, // 滚动条的位置
|
||||
scrollAnim: false, // 是否开启滚动动画
|
||||
windowTop: 0, // 可使用窗口的顶部位置
|
||||
windowBottom: 0, // 可使用窗口的底部位置
|
||||
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时使用)
|
||||
fixed: {
|
||||
// 是否通过fixed固定mescroll的高度, 默认true
|
||||
type: Boolean,
|
||||
default() {
|
||||
return true;
|
||||
}
|
||||
},
|
||||
height: [String, Number], // 指定mescroll的高度, 此项有值,则不使用fixed. (支持20, "20rpx", "20px", "20%"格式的值, 其中纯数字则默认单位rpx, 百分比则相对于windowHeight)
|
||||
showTop: {
|
||||
//是否需要展示返回顶部按钮
|
||||
type: Boolean,
|
||||
default() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
// 是否使用fixed定位 (当height有值,则不使用)
|
||||
isFixed() {
|
||||
return !this.height && this.fixed;
|
||||
},
|
||||
// mescroll的高度
|
||||
scrollHeight() {
|
||||
if (this.isFixed) {
|
||||
return 'auto';
|
||||
} else if (this.height) {
|
||||
return this.toPx(this.height) + 'px';
|
||||
} else {
|
||||
return '100%';
|
||||
}
|
||||
},
|
||||
// 下拉布局往下偏移的距离 (px)
|
||||
numTop() {
|
||||
return this.toPx(this.top) + (this.topbar ? this.statusBarHeight : 0);
|
||||
},
|
||||
fixedTop() {
|
||||
return this.isFixed ? this.numTop + this.windowTop + 'px' : 0;
|
||||
},
|
||||
padTop() {
|
||||
return !this.isFixed ? this.numTop + 'px' : 0;
|
||||
},
|
||||
// 上拉布局往上偏移 (px)
|
||||
numBottom() {
|
||||
return this.toPx(this.bottom);
|
||||
},
|
||||
fixedBottom() {
|
||||
return this.isFixed ? this.numBottom + this.windowBottom + 'px' : 0;
|
||||
},
|
||||
fixedBottomConstant() {
|
||||
return this.safearea ? 'calc(' + this.fixedBottom + ' + constant(safe-area-inset-bottom))' : this.fixedBottom;
|
||||
},
|
||||
fixedBottomEnv() {
|
||||
return this.safearea ? 'calc(' + this.fixedBottom + ' + env(safe-area-inset-bottom))' : this.fixedBottom;
|
||||
},
|
||||
padBottom() {
|
||||
return !this.isFixed ? this.numBottom + 'px' : 0;
|
||||
},
|
||||
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失效,需注意把fixed元素写在mescroll之外
|
||||
},
|
||||
// 是否在加载中
|
||||
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%"则等于windowHeight的10%
|
||||
let rate = Number(num.replace('%', '')) / 100;
|
||||
return this.windowHeight * rate;
|
||||
}
|
||||
}
|
||||
return num ? uni.upx2px(Number(num)) : 0;
|
||||
},
|
||||
//注册列表滚动事件,用于下拉刷新和上拉加载
|
||||
scroll(e) {
|
||||
this.mescroll.scroll(e.detail, () => {
|
||||
this.$emit('scroll', this.mescroll); // 此时可直接通过 this.mescroll.scrollTop获取滚动条位置; this.mescroll.isScrollUp获取是否向上滑动
|
||||
});
|
||||
},
|
||||
//注册列表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); // 派发点击回到顶部按钮的回调
|
||||
},
|
||||
// 更新滚动区域的高度 (使内容不满屏和到底,都可继续翻页)
|
||||
setClientHeight() {
|
||||
if (this.mescroll.getClientHeight(true) === 0 && !this.isExec) {
|
||||
this.isExec = true; // 避免多次获取
|
||||
this.$nextTick(() => {
|
||||
// 确保dom已渲染
|
||||
let view = uni
|
||||
.createSelectorQuery()
|
||||
.in(this)
|
||||
.select('#' + this.viewId);
|
||||
view.boundingClientRect(data => {
|
||||
this.isExec = false;
|
||||
if (data) {
|
||||
this.mescroll.setClientHeight(data.height);
|
||||
} else if (this.clientNum != 3) {
|
||||
// 极少部分情况,可能dom还未渲染完毕,递归获取,最多重试3次
|
||||
this.clientNum = this.clientNum == null ? 1 : this.clientNum + 1;
|
||||
setTimeout(() => {
|
||||
this.setClientHeight();
|
||||
}, this.clientNum * 100);
|
||||
}
|
||||
}).exec();
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
// 使用created初始化mescroll对象; 如果用mounted部分css样式编译到H5会失效
|
||||
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的情况)
|
||||
vm.setClientHeight();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
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);
|
||||
vm.mescroll.viewId = vm.viewId; // 附带id
|
||||
// init回调mescroll对象
|
||||
vm.$emit('init', vm.mescroll);
|
||||
|
||||
// 设置高度
|
||||
const sys = uni.getSystemInfoSync();
|
||||
if (sys.windowTop) vm.windowTop = sys.windowTop;
|
||||
if (sys.windowBottom) vm.windowBottom = sys.windowBottom;
|
||||
if (sys.windowHeight) vm.windowHeight = sys.windowHeight;
|
||||
if (sys.statusBarHeight) vm.statusBarHeight = sys.statusBarHeight;
|
||||
// 使down的bottomOffset生效
|
||||
vm.mescroll.setBodyHeight(sys.windowHeight);
|
||||
|
||||
// 因为使用的是scrollview,这里需自定义scrollTo
|
||||
vm.mescroll.resetScrollTo((y, t) => {
|
||||
let curY = vm.mescroll.getScrollTop();
|
||||
vm.scrollAnim = t !== 0; // t为0,则不使用动画过渡
|
||||
if (t === 0 || t === 300) {
|
||||
// 当t使用默认配置的300时,则使用系统自带的动画过渡
|
||||
vm.scrollTop = curY;
|
||||
vm.$nextTick(function() {
|
||||
vm.scrollTop = y;
|
||||
});
|
||||
} else {
|
||||
vm.mescroll.getStep(
|
||||
curY,
|
||||
y,
|
||||
step => {
|
||||
// 此写法可支持配置t
|
||||
vm.scrollTop = step;
|
||||
},
|
||||
t
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// 具体的界面如果不配置up.toTop.safearea,则取本vue的safearea值
|
||||
if (vm.up && vm.up.toTop && vm.up.toTop.safearea != null) {
|
||||
} else {
|
||||
vm.mescroll.optUp.toTop.safearea = vm.safearea;
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// 设置容器的高度
|
||||
this.setClientHeight();
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@import './mescroll-uni.css';
|
||||
@import './components/mescroll-down.css';
|
||||
@import './components/mescroll-up.css';
|
||||
</style>
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
/**
|
||||
* mescroll-body写在子组件时,需通过mescroll的mixins补充子组件缺少的生命周期:
|
||||
* 当一个页面只有一个mescroll-body写在子组件时, 则使用mescroll-comp.js (参考 mescroll-comp 案例)
|
||||
* 当一个页面有多个mescroll-body写在子组件时, 则使用mescroll-more.js (参考 mescroll-more 案例)
|
||||
*/
|
||||
const MescrollCompMixin = {
|
||||
// 因为子组件无onPageScroll和onReachBottom的页面生命周期,需在页面传递进到子组件
|
||||
onPageScroll(e) {
|
||||
let item = this.$refs["mescrollItem"];
|
||||
if (item && item.mescroll) item.mescroll.onPageScroll(e);
|
||||
},
|
||||
onReachBottom() {
|
||||
let item = this.$refs["mescrollItem"];
|
||||
if (item && item.mescroll) item.mescroll.onReachBottom();
|
||||
},
|
||||
// 当down的native: true时, 还需传递此方法进到子组件
|
||||
onPullDownRefresh() {
|
||||
let item = this.$refs["mescrollItem"];
|
||||
if (item && item.mescroll) item.mescroll.onPullDownRefresh();
|
||||
}
|
||||
}
|
||||
|
||||
export default MescrollCompMixin;
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
/**
|
||||
* mescroll-more-item的mixins, 仅在多个 mescroll-body 写在子组件时使用 (参考 mescroll-more 案例)
|
||||
*/
|
||||
const MescrollMoreItemMixin = {
|
||||
props: {
|
||||
i: Number, // 每个tab页的专属下标
|
||||
index: { // 当前tab的下标
|
||||
type: Number,
|
||||
default () {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
downOption: {
|
||||
auto: false // 不自动加载
|
||||
},
|
||||
upOption: {
|
||||
auto: false // 不自动加载
|
||||
},
|
||||
isInit: false // 当前tab是否已初始化
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
// 监听下标的变化
|
||||
index(val) {
|
||||
if (this.i === val && !this.isInit) {
|
||||
this.isInit = true; // 标记为true
|
||||
this.mescroll && this.mescroll.triggerDownScroll();
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// mescroll组件初始化的回调,可获取到mescroll对象
|
||||
mescrollInit(mescroll) {
|
||||
this.mescroll = mescroll;
|
||||
this.mescrollInitByRef && this.mescrollInitByRef(); // 兼容字节跳动小程序 (mescroll-mixins.js)
|
||||
// 自动加载当前tab的数据
|
||||
if (this.i === this.index) {
|
||||
this.isInit = true; // 标记为true
|
||||
this.mescroll.triggerDownScroll();
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
export default MescrollMoreItemMixin;
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
/**
|
||||
* mescroll-body写在子组件时,需通过mescroll的mixins补充子组件缺少的生命周期:
|
||||
* 当一个页面只有一个mescroll-body写在子组件时, 则使用mescroll-comp.js (参考 mescroll-comp 案例)
|
||||
* 当一个页面有多个mescroll-body写在子组件时, 则使用mescroll-more.js (参考 mescroll-more 案例)
|
||||
*/
|
||||
const MescrollMoreMixin = {
|
||||
data() {
|
||||
return {
|
||||
tabIndex: 0 // 当前tab下标
|
||||
}
|
||||
},
|
||||
// 因为子组件无onPageScroll和onReachBottom的页面生命周期,需在页面传递进到子组件
|
||||
onPageScroll(e) {
|
||||
let mescroll = this.getMescroll(this.tabIndex);
|
||||
mescroll && mescroll.onPageScroll(e);
|
||||
},
|
||||
onReachBottom() {
|
||||
let mescroll = this.getMescroll(this.tabIndex);
|
||||
mescroll && mescroll.onReachBottom();
|
||||
},
|
||||
// 当down的native: true时, 还需传递此方法进到子组件
|
||||
onPullDownRefresh() {
|
||||
let mescroll = this.getMescroll(this.tabIndex);
|
||||
mescroll && mescroll.onPullDownRefresh();
|
||||
},
|
||||
methods: {
|
||||
// 根据下标获取对应子组件的mescroll
|
||||
getMescroll(i) {
|
||||
if (!this.mescrollItems) this.mescrollItems = [];
|
||||
if (!this.mescrollItems[i]) {
|
||||
// v-for中的refs
|
||||
let vForItem = this.$refs["mescrollItem"];
|
||||
if (vForItem) {
|
||||
this.mescrollItems[i] = vForItem[i]
|
||||
} else {
|
||||
// 普通的refs,不可重复
|
||||
this.mescrollItems[i] = this.$refs["mescrollItem" + i];
|
||||
}
|
||||
}
|
||||
let item = this.mescrollItems[i]
|
||||
return item ? item.mescroll : null
|
||||
},
|
||||
// 切换tab,恢复滚动条位置
|
||||
tabChange(i) {
|
||||
let mescroll = this.getMescroll(i);
|
||||
if (mescroll) {
|
||||
// 延时(比$nextTick靠谱一些),确保元素已渲染
|
||||
setTimeout(() => {
|
||||
mescroll.scrollTo(mescroll.getScrollTop(), 0)
|
||||
}, 30)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default MescrollMoreMixin;
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
<template>
|
||||
<!-- top="xxx"下拉布局往下偏移,防止被悬浮菜单遮住 -->
|
||||
<mescroll v-if="isInit" :top="top" :down="downOption" @down="downCallback" :up="upOption" @up="upCallback" @emptyclick="emptyClick" @init="mescrollInit">
|
||||
<!-- 数据列表 -->
|
||||
<slot name="list"></slot>
|
||||
</mescroll>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Mescroll from './mescroll-uni.vue';
|
||||
export default {
|
||||
components: {
|
||||
Mescroll
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
mescroll: null, //mescroll实例对象
|
||||
downOption: {
|
||||
auto: false // 不自动加载
|
||||
},
|
||||
upOption: {
|
||||
auto: false, // 不自动加载
|
||||
page: {
|
||||
num: 0, // 当前页码,默认0,回调之前会加1,即callback(page)会从1开始
|
||||
size: 10 // 每页数据的数量
|
||||
},
|
||||
noMoreSize: 2, //如果列表已无数据,可设置列表的总数量要大于半页才显示无更多数据;避免列表数据过少(比如只有一条数据),显示无更多数据会不好看; 默认5
|
||||
empty: {
|
||||
tip: '~ 空空如也 ~', // 提示
|
||||
btnText: '去看看'
|
||||
},
|
||||
onScroll: true
|
||||
},
|
||||
scrollY: 0,
|
||||
isInit: false
|
||||
};
|
||||
},
|
||||
props: {
|
||||
top: [String, Number],
|
||||
size: [String, Number]
|
||||
},
|
||||
created() {
|
||||
if (this.size) this.upOption.page.size = this.size;
|
||||
this.isInit = true;
|
||||
},
|
||||
mounted() {
|
||||
this.mescroll.resetUpScroll();
|
||||
this.listenRefresh();
|
||||
},
|
||||
methods: {
|
||||
// mescroll组件初始化的回调,可获取到mescroll对象
|
||||
mescrollInit(mescroll) {
|
||||
this.mescroll = mescroll;
|
||||
},
|
||||
/*下拉刷新的回调 */
|
||||
downCallback() {
|
||||
// 这里加载你想下拉刷新的数据, 比如刷新轮播数据
|
||||
// loadSwiper();
|
||||
// 下拉刷新的回调,默认重置上拉加载列表为第一页 (自动执行 mescroll.num=1, 再触发upCallback方法 )
|
||||
this.mescroll.resetUpScroll();
|
||||
this.listenRefresh();
|
||||
},
|
||||
/*上拉加载的回调: mescroll携带page的参数, 其中num:当前页 从1开始, size:每页数据条数,默认10 */
|
||||
upCallback() {
|
||||
//联网加载数据
|
||||
this.$emit('getData', this.mescroll);
|
||||
},
|
||||
//点击空布局按钮的回调
|
||||
emptyClick() {
|
||||
this.$emit('emptytap', this.mescroll);
|
||||
},
|
||||
//刷新
|
||||
refresh() {
|
||||
this.mescroll.resetUpScroll();
|
||||
this.listenRefresh();
|
||||
},
|
||||
listenRefresh() {
|
||||
this.$emit('listenRefresh', true);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
@ -0,0 +1,234 @@
|
|||
<template>
|
||||
<view class="code-box">
|
||||
<view class="flex-box">
|
||||
<input :value="inputValue" type="number" :focus="autoFocus" :maxlength="maxlength" class="hide-input" @input="getVal" />
|
||||
<block v-for="(item, index) in ranges" :key="index">
|
||||
<view :class="['item', { active: codeIndex === item, middle: type === 'middle', bottom: type === 'bottom', box: type === 'box' }]">
|
||||
<view class="line" v-if="type !== 'middle'"></view>
|
||||
<view v-if="type === 'middle' && codeIndex <= item" class="bottom-line"></view>
|
||||
<block v-if="isPwd && codeArr.length >= item"><text class="dot">●</text></block>
|
||||
<block v-else>
|
||||
<text class="number">{{ codeArr[index] ? codeArr[index] : '' }}</text>
|
||||
</block>
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// 支持使用 v-model
|
||||
// 支持使用refs
|
||||
export default {
|
||||
name: 'mypOneInput',
|
||||
props: {
|
||||
// 支持外部提供,支持使用v-model
|
||||
// 支持通过value来做清空
|
||||
value: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 4/6
|
||||
maxlength: {
|
||||
type: Number,
|
||||
default: 4
|
||||
},
|
||||
autoFocus: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
isPwd: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
// middle-middle line, bottom-bottom line, box-square box
|
||||
type: {
|
||||
type: String,
|
||||
default: 'bottom'
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
maxlength: {
|
||||
immediate: true,
|
||||
handler: function(newV) {
|
||||
if (newV === 6) {
|
||||
this.ranges = [1, 2, 3, 4, 5, 6];
|
||||
} else {
|
||||
this.ranges = [1, 2, 3, 4];
|
||||
}
|
||||
}
|
||||
},
|
||||
value: {
|
||||
immediate: true,
|
||||
handler: function(newV) {
|
||||
if (newV !== this.inputValue) {
|
||||
this.inputValue = newV;
|
||||
this.toMakeAndCheck(newV);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
inputValue: '',
|
||||
codeIndex: 1,
|
||||
codeArr: [],
|
||||
ranges: [1, 2, 3, 4]
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
getVal(e) {
|
||||
const val = e.detail.value;
|
||||
this.inputValue = val;
|
||||
this.$emit('input', val);
|
||||
this.toMakeAndCheck(val);
|
||||
},
|
||||
toMakeAndCheck(val) {
|
||||
const arr = val.split('');
|
||||
this.codeIndex = arr.length + 1;
|
||||
this.codeArr = arr;
|
||||
if (this.codeIndex > Number(this.maxlength)) {
|
||||
this.$emit('finish', this.codeArr.join(''));
|
||||
}
|
||||
},
|
||||
// refs 时不再提供 v-model 支持
|
||||
// 支持使用refs来设置value
|
||||
// 没有提供数据保护与检测,自己在外面对数据进行检测保护
|
||||
set(val) {
|
||||
this.inputValue = val;
|
||||
this.toMakeAndCheck(val);
|
||||
},
|
||||
// 支持使用refs来清空
|
||||
clear() {
|
||||
this.inputValue = '';
|
||||
this.codeArr = [];
|
||||
this.codeIndex = 1;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@keyframes twinkling {
|
||||
0% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
|
||||
50% {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
100% {
|
||||
opacity: 0.2;
|
||||
}
|
||||
}
|
||||
|
||||
.code-box {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.flex-box {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.flex-box .hide-input {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: -100%;
|
||||
width: 200%;
|
||||
height: 100%;
|
||||
text-align: left;
|
||||
z-index: 9;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.flex-box .item {
|
||||
position: relative;
|
||||
flex: 1;
|
||||
margin-right: 18rpx;
|
||||
font-size: 70rpx;
|
||||
font-weight: bold;
|
||||
color: #333333;
|
||||
line-height: 100rpx;
|
||||
}
|
||||
|
||||
.flex-box .item::before {
|
||||
content: '';
|
||||
padding-top: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.flex-box .item:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.flex-box .middle {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.flex-box .box {
|
||||
box-sizing: border-box;
|
||||
border: 2rpx solid #cccccc;
|
||||
border-width: 2rpx 0 2rpx 2rpx;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.flex-box .box:first-of-type {
|
||||
border-top-left-radius: 8rpx;
|
||||
border-bottom-left-radius: 8rpx;
|
||||
}
|
||||
|
||||
.flex-box .box:last-child {
|
||||
border-right: 2rpx solid #cccccc;
|
||||
border-top-right-radius: 8rpx;
|
||||
border-bottom-right-radius: 8rpx;
|
||||
}
|
||||
|
||||
.flex-box .bottom {
|
||||
box-sizing: border-box;
|
||||
border-bottom: 2rpx solid #ddd;
|
||||
}
|
||||
|
||||
.flex-box .active {
|
||||
border-color: #ddd;
|
||||
}
|
||||
|
||||
.flex-box .active .line {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.flex-box .line {
|
||||
display: none;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: 2rpx;
|
||||
height: 40rpx;
|
||||
background: #333333;
|
||||
animation: twinkling 1s infinite ease;
|
||||
}
|
||||
|
||||
.flex-box .dot,
|
||||
.flex-box .number {
|
||||
line-height: 40rpx;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
.flex-box .bottom-line {
|
||||
height: 8rpx;
|
||||
background: #000000;
|
||||
width: 80%;
|
||||
position: absolute;
|
||||
border-radius: 4rpx;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
<template>
|
||||
<view v-if="advList.length" class="adv-wrap">
|
||||
<swiper :indicator-dots="advList.length > 1" indicator-active-color="#ffffff" :autoplay="true" :interval="3000" :duration="1000" v-if="advList.length > 1" class="ns-adv">
|
||||
<swiper-item v-for="(item, index) in advList" :key="index" @click="jumppage(item.adv_url)">
|
||||
<view class="image-box" :style="{ 'background-color': item.background }"><image :src="$util.img(item.adv_image)"></image></view>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
<view v-else class="adv-wrap ns-adv">
|
||||
<image :src="$util.img(advList[0]['adv_image'])" mode="widthFix"></image>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'ns-advert',
|
||||
props: {
|
||||
keyword: {
|
||||
type: String
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
advList: []
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.getAdvList();
|
||||
},
|
||||
methods: {
|
||||
//获取广告位
|
||||
getAdvList() {
|
||||
var item = {
|
||||
adv_image: '',
|
||||
adv_url: ''
|
||||
};
|
||||
this.$api.sendRequest({
|
||||
url: '/api/adv/detail',
|
||||
data: {
|
||||
keyword: this.keyword
|
||||
},
|
||||
success: res => {
|
||||
if (res.code == 0) {
|
||||
var data = res.data.adv_list;
|
||||
for (var index in data) {
|
||||
if (data[index].adv_url) data[index].adv_url = JSON.parse(data[index].adv_url);
|
||||
}
|
||||
this.advList = res.data.adv_list;
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
jumppage(e) {
|
||||
this.$util.diyRedirectTo(e);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.adv-wrap {
|
||||
width: 100%;
|
||||
}
|
||||
.bg {
|
||||
width: 100%;
|
||||
height: 158rpx;
|
||||
background-color: #fff;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
/* #ifdef H5 */
|
||||
top: 88rpx;
|
||||
/* #endif */
|
||||
/* #ifdef MP-WEIXIN */
|
||||
top: 0;
|
||||
/* #endif */
|
||||
}
|
||||
.ns-adv {
|
||||
background: #fff;
|
||||
height: 300rpx;
|
||||
border-radius: 10rpx;
|
||||
/* padding: 8rpx 24rpx 24rpx; */
|
||||
}
|
||||
|
||||
.ns-adv .image-box {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 10rpx;
|
||||
}
|
||||
|
||||
.ns-adv image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border-radius: 10rpx;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,363 @@
|
|||
<template>
|
||||
<view>
|
||||
<view @touchmove.prevent.stop v-if="birthday" class="reward-popup">
|
||||
<uni-popup ref="birthdayGift" type="center" :maskClick="false">
|
||||
<view class="reward-wrap">
|
||||
<view class="wrap" :style="{ backgroundImage: 'url(' + $util.img('public/uniapp/birthday_gift/birthday_gift_bg.png') + ')' }">
|
||||
<view class="birthday-title-name">Dear {{ birthday.nickname }}</view>
|
||||
<view class="birthday-title-desc" v-if="birthday.blessing_content">{{ birthday.blessing_content }}</view>
|
||||
<view class="birthday-title-desc" v-else>感谢您一直以来的支持,在您生日到来之际,特为您送上最真诚的祝福!</view>
|
||||
<view class="birthday-title-hint">
|
||||
<image :src="$util.img('public/uniapp/birthday_gift/birthday_gift_left.png')" mode="" class="birthday-img-all"></image>
|
||||
<view class="font-size-toolbar">生日贺礼</view>
|
||||
<image :src="$util.img('public/uniapp/birthday_gift/birthday_gift_right.png')" mode="" class="birthday-img-all"></image>
|
||||
</view>
|
||||
<scroll-view scroll-y="true" class="register-box">
|
||||
<view class="reward-content">
|
||||
<view class="content" v-if="birthday.point > 0">
|
||||
<view class="info">
|
||||
<text class="num">
|
||||
{{ parseFloat(birthday.point) }}
|
||||
<text class="type">积分</text>
|
||||
</text>
|
||||
<view class="desc">用于下单时抵现或兑换商品等</view>
|
||||
</view>
|
||||
<view class="tip" @click="closeRewardPopup('1')">立即查看</view>
|
||||
</view>
|
||||
<view class="content" v-if="birthday.balance_type == 0 && birthday.balance > 0">
|
||||
<view class="info">
|
||||
<text class="num">
|
||||
{{ parseFloat(birthday.balance) }}
|
||||
<text class="type">元红包</text>
|
||||
</text>
|
||||
<view class="desc">不可提现红包</view>
|
||||
</view>
|
||||
<view class="tip" @click="closeRewardPopup('2')">立即查看</view>
|
||||
</view>
|
||||
<view class="content" v-if="birthday.balance_type == 1 && birthday.balance_money > 0">
|
||||
<view class="info">
|
||||
<text class="num">
|
||||
{{ parseFloat(birthday.balance_money) }}
|
||||
<text class="type">元红包</text>
|
||||
</text>
|
||||
<view class="desc">可提现红包</view>
|
||||
</view>
|
||||
<view class="tip" @click="closeRewardPopup('2')">立即查看</view>
|
||||
</view>
|
||||
|
||||
<block v-if="birthday.coupon_list.length > 0">
|
||||
<block v-for="(item, index) in birthday.coupon_list" :key="index">
|
||||
<view class="content">
|
||||
<view class="info">
|
||||
<block v-if="item.type == 'reward'">
|
||||
<text class="num">
|
||||
{{ parseFloat(item.money) }}
|
||||
<text class="type">元优惠劵</text>
|
||||
</text>
|
||||
</block>
|
||||
<block v-else-if="item.type == 'discount'">
|
||||
<text class="num">
|
||||
{{ item.discount }}
|
||||
<text class="type">折</text>
|
||||
</text>
|
||||
</block>
|
||||
<view class="desc">用于下单时抵现或兑换商品等</view>
|
||||
</view>
|
||||
<view class="tip" @click="closeRewardPopup('3')">立即查看</view>
|
||||
</view>
|
||||
</block>
|
||||
</block>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
<view class="close-btn" @click="cancel()"><text class="iconfont icon-close btn"></text></view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import uniPopup from '../uni-popup/uni-popup.vue';
|
||||
|
||||
// 注册奖励弹出层
|
||||
export default {
|
||||
name: 'ns-birthday-gift',
|
||||
components: {
|
||||
uniPopup
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
birthday: {
|
||||
flag: false,
|
||||
coupon_list: {}
|
||||
},
|
||||
record: false,
|
||||
leatBirthday: false
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
introduction() {
|
||||
let bytesCount = 0;
|
||||
if (this.birthday.blessing_content) {
|
||||
for (let i = 0, n = this.birthday.blessing_content.length; i < n; i++) {
|
||||
let c = this.birthday.blessing_content.charCodeAt(i);
|
||||
if ((c >= 0x0001 && c <= 0x007e) || (0xff60 <= c && c <= 0xff9f)) {
|
||||
bytesCount += 1;
|
||||
} else {
|
||||
bytesCount += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
return bytesCount;
|
||||
}
|
||||
},
|
||||
async created() {
|
||||
await this.getBirthdayGift();
|
||||
//this.getReceiveGift();
|
||||
this.getBirthdaygiftRecord();
|
||||
},
|
||||
|
||||
methods: {
|
||||
getReward() {
|
||||
return this.birthday;
|
||||
},
|
||||
async open() {
|
||||
if (this.leatBirthday) {
|
||||
this.$refs.birthdayGift.open();
|
||||
await this.getReceiveGift();
|
||||
} else {
|
||||
await this.getBirthdayGift();
|
||||
await this.getReceiveGift();
|
||||
this.$refs.birthdayGift.open();
|
||||
}
|
||||
},
|
||||
cancel() {
|
||||
this.$refs.birthdayGift.close();
|
||||
},
|
||||
getRecord() {
|
||||
return this.record;
|
||||
},
|
||||
getBirthday() {
|
||||
return this.birthday;
|
||||
},
|
||||
/**
|
||||
* 获取生日礼配置
|
||||
*/
|
||||
async getBirthdayGift() {
|
||||
var res = await this.$api.sendRequest({
|
||||
url: '/birthdaygift/api/Config/config',
|
||||
async: false
|
||||
});
|
||||
if (res.code >= 0) {
|
||||
if (res.data) {
|
||||
this.birthday = res.data;
|
||||
this.leatBirthday = true;
|
||||
}
|
||||
}
|
||||
/* await this.$api.sendRequest({
|
||||
url: '/birthdaygift/api/Config/Config',
|
||||
success: res => {
|
||||
if (res.code >= 0) {
|
||||
if(res.data){
|
||||
this.birthday = res.data;
|
||||
uni.setStorageSync('birthdayFlag',res.data.flag);
|
||||
}
|
||||
}
|
||||
}
|
||||
}); */
|
||||
},
|
||||
// 领取
|
||||
async getReceiveGift() {
|
||||
if (this.birthday.flag == true) {
|
||||
await this.$api.sendRequest({
|
||||
url: '/birthdaygift/api/Config/receive',
|
||||
data: {
|
||||
id: this.birthday.id
|
||||
},
|
||||
success: res => {
|
||||
if (res.code >= 0) {
|
||||
this.$emit('getBirthday');
|
||||
uni.removeStorageSync('birthdayFlag');
|
||||
this.$util.redirectTo('/pages/member/index');
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
closeRewardPopup(type) {
|
||||
if (type == 1) {
|
||||
this.$util.redirectTo('/pages_tool/member/point_detail', {});
|
||||
return;
|
||||
} else if (type == 2) {
|
||||
this.$util.redirectTo('/pages_tool/member/balance_detail', {});
|
||||
return;
|
||||
} else {
|
||||
this.$util.redirectTo('/pages_tool/member/coupon', {});
|
||||
return;
|
||||
}
|
||||
},
|
||||
getBirthdaygiftRecord() {
|
||||
this.$api.sendRequest({
|
||||
url: '/birthdaygift/api/Config/getRecord',
|
||||
data: {},
|
||||
success: res => {
|
||||
if (res.code >= 0) {
|
||||
this.record = res.data;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style scoped>
|
||||
.register-box /deep/ .uni-scroll-view {
|
||||
background: unset !important;
|
||||
}
|
||||
.register-box {
|
||||
max-height: 300rpx;
|
||||
overflow-y: scroll;
|
||||
/* margin-top:350rpx; */
|
||||
}
|
||||
/deep/ .uni-popup__wrapper-box {
|
||||
background-color: transparent !important;
|
||||
}
|
||||
/deep/ .birthday-title-hint uni-image {
|
||||
width: 113rpx !important;
|
||||
height: 24rpx !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss">
|
||||
.reward-wrap {
|
||||
width: 85vw;
|
||||
height: auto;
|
||||
.wrap {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
background-size: 100%;
|
||||
background-repeat: no-repeat;
|
||||
padding-bottom: 40rpx;
|
||||
.birthday-title-name {
|
||||
font-size: $font-size-toolbar;
|
||||
font-weight: bold;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 1;
|
||||
overflow: hidden;
|
||||
padding-top: 350rpx;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
line-height: 1;
|
||||
}
|
||||
.birthday-title-desc {
|
||||
font-weight: 500;
|
||||
margin: 30rpx 70rpx 20rpx;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
}
|
||||
.birthday-title-hint {
|
||||
font-size: $font-size-toolbar;
|
||||
font-weight: bold;
|
||||
font-family: BDZongYi-A001;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin: 0 0 40rpx;
|
||||
line-height: 1;
|
||||
.birthday-img-all {
|
||||
width: 100rpx;
|
||||
height: 20rpx;
|
||||
}
|
||||
& > view {
|
||||
margin: 0 20rpx;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
.reward-content {
|
||||
margin: 0 40rpx;
|
||||
}
|
||||
.head {
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
line-height: 1;
|
||||
margin: 20rpx 0;
|
||||
}
|
||||
& .content:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 16rpx 26rpx;
|
||||
background: #fff;
|
||||
border-radius: 10rpx;
|
||||
margin-bottom: 20rpx;
|
||||
.info {
|
||||
flex: 1;
|
||||
}
|
||||
.tip {
|
||||
color: #fa5b14;
|
||||
padding: 10rpx 0 10rpx 20rpx;
|
||||
width: 60rpx;
|
||||
line-height: 1.5;
|
||||
letter-spacing: 2rpx;
|
||||
border-left: 2rpx dashed #e5e5e5;
|
||||
}
|
||||
.num {
|
||||
font-size: 48rpx;
|
||||
color: #fa5b14;
|
||||
font-weight: bolder;
|
||||
line-height: 1;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
display: inline-block;
|
||||
max-width: 300rpx;
|
||||
}
|
||||
.type {
|
||||
font-size: $font-size-base;
|
||||
margin-left: 10rpx;
|
||||
line-height: 1;
|
||||
font-weight: normal;
|
||||
color: #606266;
|
||||
}
|
||||
.desc {
|
||||
margin-top: 8rpx;
|
||||
color: $color-tip;
|
||||
font-size: $font-size-tag;
|
||||
line-height: 1;
|
||||
}
|
||||
}
|
||||
.close-btn {
|
||||
text-align: center;
|
||||
margin-top: 40rpx;
|
||||
.btn {
|
||||
font-size: 40rpx;
|
||||
color: #fff;
|
||||
border: 4rpx solid #fff;
|
||||
border-radius: 50%;
|
||||
padding: 10rpx;
|
||||
font-weight: bold;
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
margin: 0 auto;
|
||||
line-height: 40rpx;
|
||||
/* margin: 20rpx 140rpx;
|
||||
border: none;
|
||||
background: linear-gradient(90deg, #FF6A00, #FF3C00);
|
||||
border-radius: 40rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center; */
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,142 @@
|
|||
<template>
|
||||
<view class="message">
|
||||
<view class="goods-item" v-if="goodsInfo.goods_name">
|
||||
<image :src="$util.img(goodsInfo.sku_image)" mode="aspectFill"></image>
|
||||
<view class="goods-info">
|
||||
<view class="goods-name">{{ goodsInfo.sku_name ? goodsInfo.sku_name : goodsInfo.goods_name }}</view>
|
||||
<view class="goods-bottom">
|
||||
<view class="goods-price">
|
||||
<text class="goods-price-sign color-base-text">¥</text>
|
||||
<text class="color-base-text">{{ goodsInfo.price }}</text>
|
||||
</view>
|
||||
<view class="goods-option font-size-goods-tag disabled">已发送</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="goods-item" v-else-if="goodsDetail">
|
||||
<image :src="$util.img(goodsDetail.sku_image)" mode="aspectFill"></image>
|
||||
<view class="goods-info">
|
||||
<view class="goods-name">{{ goodsDetail.sku_name ? goodsDetail.sku_name : goodsDetail.goods_name }}</view>
|
||||
<view class="goods-bottom">
|
||||
<view class="goods-price">
|
||||
<text class="goods-price-sign color-base-text">¥</text>
|
||||
<text class="color-base-text">{{ goodsDetail.price }}</text>
|
||||
</view>
|
||||
<view class="goods-option font-size-goods-tag color-base-bg" @click="sendMsg('goods')">发送</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'ns-chat-goods',
|
||||
props: {
|
||||
skuId: {
|
||||
type: [Number, String]
|
||||
},
|
||||
goodsDetail: {
|
||||
type: [Object]
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
goodsInfo: {}
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.getGoodsInfo();
|
||||
},
|
||||
methods: {
|
||||
getGoodsInfo() {
|
||||
this.$api.sendRequest({
|
||||
url: '/api/goodssku/detail',
|
||||
data: {
|
||||
sku_id: this.skuId
|
||||
},
|
||||
success: res => {
|
||||
if (res.code >= 0) {
|
||||
this.goodsInfo = res.data.goods_sku_detail;
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
sendMsg() {
|
||||
this.$emit('sendMsg', 'goods');
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.message {
|
||||
padding: 13rpx 20rpx;
|
||||
box-sizing: border-box;
|
||||
width: 100vw;
|
||||
position: relative;
|
||||
.goods-item {
|
||||
width: 100%;
|
||||
height: 220rpx;
|
||||
|
||||
background: #ffffff;
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-radius: 20rpx;
|
||||
margin: 0 auto;
|
||||
padding: $padding;
|
||||
box-sizing: border-box;
|
||||
image {
|
||||
width: 180rpx;
|
||||
height: 180rpx;
|
||||
min-width: 180rpx;
|
||||
}
|
||||
.goods-info {
|
||||
width: 100%;
|
||||
height: 180rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
padding-left: 20rpx;
|
||||
box-sizing: border-box;
|
||||
.goods-name {
|
||||
width: 100%;
|
||||
line-height: 1.4;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
overflow: hidden;
|
||||
}
|
||||
.goods-bottom {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-end;
|
||||
text {
|
||||
line-height: 1;
|
||||
}
|
||||
.goods-price {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
padding-bottom: 10rpx;
|
||||
font-weight: 500;
|
||||
.goods-price-sign {
|
||||
font-size: $font-size-activity-tag;
|
||||
}
|
||||
}
|
||||
.goods-option {
|
||||
width: 150rpx;
|
||||
height: 50rpx;
|
||||
line-height: 50rpx;
|
||||
text-align: center;
|
||||
border-radius: $border-radius;
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
}
|
||||
.disabled {
|
||||
background: #e5e5e5;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,149 @@
|
|||
<template>
|
||||
<view class="message">
|
||||
<view class="goods-item" v-if="orderdetails">
|
||||
<image :src="$util.img(orderdetails.order_goods ? orderdetails.order_goods[0].sku_image : '')" mode="aspectFill"></image>
|
||||
<view class="goods-info">
|
||||
<view class="goods-name">{{ orderdetails.order_goods ? orderdetails.order_goods[0].sku_name : '' }}</view>
|
||||
<view class="font-size-goods-tag">订单状态:{{ orderdetails.order_status_name }}</view>
|
||||
<view class="font-size-goods-tag">配送方式:{{ orderdetails.delivery_type_name }}</view>
|
||||
<view class="goods-bottom">
|
||||
<view class="goods-price color-base-text">
|
||||
<text class="goods-price-sign">¥</text>
|
||||
<text>{{ orderdetails.order_goods ? orderdetails.order_goods[0].price : '' }}</text>
|
||||
</view>
|
||||
<view class="goods-option font-size-goods-tag color-base-bg" @click="sendMsg('order')">发送</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="goods-item" v-else-if="orderInfo">
|
||||
<image :src="$util.img(orderInfo.order_goods ? orderInfo.order_goods[0].sku_image : '')" mode="aspectFill"></image>
|
||||
<view class="goods-info">
|
||||
<view class="goods-name">{{ orderInfo.order_goods ? orderInfo.order_goods[0].sku_name : '' }}</view>
|
||||
<view class="font-size-goods-tag">订单状态:{{ orderInfo.order_status_name }}</view>
|
||||
<view class="font-size-goods-tag">配送方式:{{ orderInfo.delivery_type_name }}</view>
|
||||
<view class="goods-bottom">
|
||||
<view class="goods-price color-base-text">
|
||||
<text class="goods-price-sign">¥</text>
|
||||
<text>{{ orderInfo.order_goods ? orderInfo.order_goods[0].price : '' }}</text>
|
||||
</view>
|
||||
<view class="goods-option font-size-goods-tag disabled">已发送</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'ns-chat-order',
|
||||
props: {
|
||||
orderId: {
|
||||
type: [Number, String]
|
||||
},
|
||||
isCanSend: Boolean,
|
||||
orderdetails: {
|
||||
type: [Object]
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
orderInfo: {}
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.getGoodsInfo();
|
||||
},
|
||||
methods: {
|
||||
getGoodsInfo() {
|
||||
if (this.orderId) {
|
||||
this.$api.sendRequest({
|
||||
url: '/api/order/detail',
|
||||
data: {
|
||||
order_id: this.orderId
|
||||
},
|
||||
success: res => {
|
||||
if (res.code >= 0) {
|
||||
this.orderInfo = res.data;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
sendMsg() {
|
||||
this.$emit('sendMsg', 'order');
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.message {
|
||||
padding: 13rpx 20rpx;
|
||||
box-sizing: border-box;
|
||||
width: 100vw;
|
||||
position: relative;
|
||||
.goods-item {
|
||||
width: 100%;
|
||||
height: 220rpx;
|
||||
background: #ffffff;
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-radius: 20rpx;
|
||||
margin: 0 auto;
|
||||
padding: $padding;
|
||||
box-sizing: border-box;
|
||||
image {
|
||||
width: 180rpx;
|
||||
height: 180rpx;
|
||||
}
|
||||
.goods-info {
|
||||
width: 100%;
|
||||
height: 180rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
padding-left: 20rpx;
|
||||
box-sizing: border-box;
|
||||
.goods-name {
|
||||
width: 100%;
|
||||
line-height: 1.4;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 1;
|
||||
overflow: hidden;
|
||||
// font-size: $font-size-tag;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
.goods-bottom {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-end;
|
||||
text {
|
||||
line-height: 1;
|
||||
}
|
||||
.goods-price {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
padding-bottom: 10rpx;
|
||||
font-weight: 500;
|
||||
.goods-price-sign {
|
||||
font-size: 20rpx;
|
||||
}
|
||||
}
|
||||
.goods-option {
|
||||
width: 150rpx;
|
||||
height: 50rpx;
|
||||
line-height: 50rpx;
|
||||
text-align: center;
|
||||
border-radius: $border-radius;
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
}
|
||||
.disabled {
|
||||
background: #e5e5e5;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,142 @@
|
|||
<template>
|
||||
<view class="goods">
|
||||
<view class="goods-msg">
|
||||
<image :src="$util.img(goodsINfo.sku_image)" mode="aspectFill"></image>
|
||||
<view class="goods-item">
|
||||
<view class="title">{{ goodsINfo.goods_name }}</view>
|
||||
<view class="goods-sku">
|
||||
库存:{{ goodsINfo.stock }}
|
||||
<text>销量:{{ goodsINfo.sale_num }}</text>
|
||||
</view>
|
||||
<view class="goods-price">
|
||||
<view class="price color-base-text">
|
||||
<text class="price-util">¥</text>
|
||||
<text class="price-num">{{ goodsINfo.price }}</text>
|
||||
</view>
|
||||
<view class="see-shop color-base-text" @click="go_shop()">
|
||||
查看商品
|
||||
<text class="iconfont icon-right"></text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'ns-chat-receiveGoods',
|
||||
props: {
|
||||
skuId: {
|
||||
type: [Number, String]
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
goodsINfo: {}
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.getInfo();
|
||||
},
|
||||
methods: {
|
||||
getInfo() {
|
||||
this.$api.sendRequest({
|
||||
url: '/api/goodssku/detail',
|
||||
data: {
|
||||
sku_id: this.skuId
|
||||
},
|
||||
success: res => {
|
||||
if (res.code >= 0) {
|
||||
this.goodsINfo = res.data.goods_sku_detail;
|
||||
this.$emit('upDOM');
|
||||
// that.setPageScrollTo();
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
go_shop() {
|
||||
this.$util.redirectTo('/pages/goods/detail?goods_id=' + this.goodsINfo.goods_id);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.goods {
|
||||
padding: 13rpx 20rpx;
|
||||
box-sizing: border-box;
|
||||
width: 100vw;
|
||||
position: relative;
|
||||
|
||||
.goods-msg {
|
||||
width: 100%;
|
||||
height: 220rpx;
|
||||
background: #ffffff;
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-radius: 20rpx;
|
||||
margin: 0 auto;
|
||||
padding: $padding;
|
||||
box-sizing: border-box;
|
||||
|
||||
image {
|
||||
width: 180rpx;
|
||||
height: 180rpx;
|
||||
min-width: 180rpx;
|
||||
border-radius: $border-radius;
|
||||
}
|
||||
|
||||
.goods-item {
|
||||
width: 100%;
|
||||
height: 180rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
padding-left: 20rpx;
|
||||
box-sizing: border-box;
|
||||
|
||||
.title {
|
||||
width: 100%;
|
||||
line-height: 1.4;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.goods-sku {
|
||||
color: $color-sub;
|
||||
|
||||
text {
|
||||
padding-left: $padding;
|
||||
}
|
||||
}
|
||||
|
||||
.goods-price {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
.price {
|
||||
.price-util {
|
||||
font-size: $font-size-activity-tag;
|
||||
}
|
||||
}
|
||||
|
||||
.see-shop {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
text {
|
||||
padding-top: 4rpx;
|
||||
padding-left: 4rpx;
|
||||
font-size: $font-size-sub;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue