Compare commits
14 Commits
dev/1.0
...
custom/272
| Author | SHA1 | Date | |
|---|---|---|---|
| 40d411c57a | |||
| b079487c9a | |||
| ef7b609efb | |||
| 7a28bb7f7a | |||
| 921e8b79b1 | |||
| 0101c36012 | |||
| 469bc4da81 | |||
| 50072c45ab | |||
| c790d63005 | |||
| 71c866c0f8 | |||
| a5740f53af | |||
| 8f0a13c473 | |||
| 6d0c914e79 | |||
| 3fec0470cf |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -2,4 +2,3 @@
|
|||||||
/.hbuilderx
|
/.hbuilderx
|
||||||
/.idea
|
/.idea
|
||||||
/node_modules
|
/node_modules
|
||||||
/iconfont-preview.html
|
|
||||||
|
|||||||
@@ -1,47 +0,0 @@
|
|||||||
// 本地调试配置示例文件
|
|
||||||
// 复制此文件并重命名为 local.config.js 以使用自定义本地配置
|
|
||||||
|
|
||||||
const localDevConfig = ({
|
|
||||||
'460': { // 制氧设备平台
|
|
||||||
uniacid: 460,
|
|
||||||
domain: 'https://xcx30.5g-quickapp.com/',
|
|
||||||
},
|
|
||||||
'576-xcx30.5g': { // 活性石灰装备
|
|
||||||
uniacid: 576,
|
|
||||||
domain: 'https://xcx30.5g-quickapp.com/',
|
|
||||||
},
|
|
||||||
'2285': { // 数码喷墨墨水
|
|
||||||
uniacid: 2285,
|
|
||||||
domain: 'https://xcx.aigc-quickapp.com/',
|
|
||||||
},
|
|
||||||
'2811': { // POCT检测分析平台
|
|
||||||
uniacid: 2811,
|
|
||||||
domain: 'https://xcx6.aigc-quickapp.com/',
|
|
||||||
},
|
|
||||||
'2724': { // 生物菌肥
|
|
||||||
uniacid: 2724,
|
|
||||||
domain: 'https://xcx.aigc-quickapp.com/',
|
|
||||||
},
|
|
||||||
'2505': { // 煤矿钻机
|
|
||||||
uniacid: 2505,
|
|
||||||
domain: 'https://xcx.aigc-quickapp.com/',
|
|
||||||
},
|
|
||||||
'2777': { // 养老服务
|
|
||||||
uniacid: 2777,
|
|
||||||
domain: 'https://xcx.aigc-quickapp.com/',
|
|
||||||
},
|
|
||||||
'1': { // 开发平台
|
|
||||||
uniacid: 1,
|
|
||||||
domain: 'https://dev.aigc-quickapp.com',
|
|
||||||
},
|
|
||||||
'1-test': { // 测试平台
|
|
||||||
uniacid: 1,
|
|
||||||
domain: 'https://test.aigc-quickapp.com',
|
|
||||||
},
|
|
||||||
'local-2': { // 测试平台
|
|
||||||
uniacid: 2,
|
|
||||||
domain: 'http://localhost:8050/',
|
|
||||||
},
|
|
||||||
})['1']; // 选择要使用的环境配置
|
|
||||||
|
|
||||||
export default localDevConfig;
|
|
||||||
@@ -6,34 +6,10 @@ const localDevConfig = ({
|
|||||||
uniacid: 460,
|
uniacid: 460,
|
||||||
domain: 'https://xcx30.5g-quickapp.com/',
|
domain: 'https://xcx30.5g-quickapp.com/',
|
||||||
},
|
},
|
||||||
'576-xcx30.5g': { // 活性石灰装备
|
|
||||||
uniacid: 576,
|
|
||||||
domain: 'https://xcx30.5g-quickapp.com/',
|
|
||||||
},
|
|
||||||
'2285': { // 数码喷墨墨水
|
'2285': { // 数码喷墨墨水
|
||||||
uniacid: 2285,
|
uniacid: 2285,
|
||||||
domain: 'https://xcx.aigc-quickapp.com/',
|
domain: 'https://xcx.aigc-quickapp.com/',
|
||||||
},
|
},
|
||||||
'2811': { // POCT检测分析平台
|
|
||||||
uniacid: 2811,
|
|
||||||
domain: 'https://xcx6.aigc-quickapp.com/',
|
|
||||||
},
|
|
||||||
'2812': { // IVD数商模式
|
|
||||||
uniacid: 2812,
|
|
||||||
domain: 'https://xcx6.aigc-quickapp.com/',
|
|
||||||
},
|
|
||||||
'2724': { // 生物菌肥
|
|
||||||
uniacid: 2724,
|
|
||||||
domain: 'https://xcx.aigc-quickapp.com/',
|
|
||||||
},
|
|
||||||
'2505': { // 煤矿钻机
|
|
||||||
uniacid: 2505,
|
|
||||||
domain: 'https://xcx.aigc-quickapp.com/',
|
|
||||||
},
|
|
||||||
'2777': { // 养老服务
|
|
||||||
uniacid: 2777,
|
|
||||||
domain: 'https://xcx.aigc-quickapp.com/',
|
|
||||||
},
|
|
||||||
'1': { // 开发平台
|
'1': { // 开发平台
|
||||||
uniacid: 1,
|
uniacid: 1,
|
||||||
domain: 'https://dev.aigc-quickapp.com',
|
domain: 'https://dev.aigc-quickapp.com',
|
||||||
@@ -42,14 +18,6 @@ const localDevConfig = ({
|
|||||||
uniacid: 1,
|
uniacid: 1,
|
||||||
domain: 'https://test.aigc-quickapp.com',
|
domain: 'https://test.aigc-quickapp.com',
|
||||||
},
|
},
|
||||||
'local-2': { // 测试平台
|
})['2285']; // 选择要使用的环境配置
|
||||||
uniacid: 2,
|
|
||||||
domain: 'http://localhost:8050/',
|
|
||||||
},
|
|
||||||
'local-2-dev': { // 本地开发测试平台
|
|
||||||
uniacid: 2,
|
|
||||||
domain: 'http://localhost:8050/',
|
|
||||||
},
|
|
||||||
})['2812']; // 选择要使用的环境配置
|
|
||||||
|
|
||||||
export default localDevConfig;
|
export default localDevConfig;
|
||||||
9
App.vue
9
App.vue
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
mixins: [auth],
|
mixins: [auth],
|
||||||
onLaunch: async function(options) {
|
onLaunch: function(options) {
|
||||||
// 方式:支持快应用,从url中query部分获取uniacid,或useragent中获取uniacid
|
// 方式:支持快应用,从url中query部分获取uniacid,或useragent中获取uniacid
|
||||||
if(options.query.uniacid){
|
if(options.query.uniacid){
|
||||||
uni.setStorageSync('uniacid', options.query.uniacid);
|
uni.setStorageSync('uniacid', options.query.uniacid);
|
||||||
@@ -40,7 +40,7 @@
|
|||||||
// #endif
|
// #endif
|
||||||
|
|
||||||
// #ifdef H5
|
// #ifdef H5
|
||||||
if (this.$util.getDeviceInfo().platform == 'ios') {
|
if (uni.getSystemInfoSync().platform == 'ios') {
|
||||||
uni.setStorageSync('initUrl', location.href);
|
uni.setStorageSync('initUrl', location.href);
|
||||||
}
|
}
|
||||||
// #endif
|
// #endif
|
||||||
@@ -61,8 +61,7 @@
|
|||||||
|
|
||||||
// 主题风格
|
// 主题风格
|
||||||
if (uni.getStorageSync('themeStyle')) {
|
if (uni.getStorageSync('themeStyle')) {
|
||||||
const themeData = await configExternal.loadTheme(uni.getStorageSync('themeStyle'));
|
this.$store.commit('setThemeStyle', configExternal.loadThemeSync(uni.getStorageSync('themeStyle')));
|
||||||
this.$store.commit('setThemeStyle', themeData);
|
|
||||||
this.$store.dispatch('themeColorSet');
|
this.$store.dispatch('themeColorSet');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -314,7 +313,7 @@
|
|||||||
@import './common/css/iconfont.css';
|
@import './common/css/iconfont.css';
|
||||||
@import './common/css/icondiy.css'; // 自定义图标库
|
@import './common/css/icondiy.css'; // 自定义图标库
|
||||||
@import './common/css/icon/extend.css'; // 扩展图标库
|
@import './common/css/icon/extend.css'; // 扩展图标库
|
||||||
page {
|
page{
|
||||||
background: #f4f6fa;
|
background: #f4f6fa;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -123,7 +123,7 @@ image {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.choose-store {
|
.choose-store {
|
||||||
::v-deep .uni-popup__wrapper{
|
/deep/ .uni-popup__wrapper{
|
||||||
background: none!important;
|
background: none!important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -870,13 +870,13 @@
|
|||||||
// 海报
|
// 海报
|
||||||
// .uni-popup__wrapper-box
|
// .uni-popup__wrapper-box
|
||||||
.poster-layer {
|
.poster-layer {
|
||||||
::v-deep .uni-popup__wrapper.center {
|
/deep/ .uni-popup__wrapper.center {
|
||||||
width: 100vw!important;
|
width: 100vw!important;
|
||||||
height: 100vh!important;
|
height: 100vh!important;
|
||||||
background: none!important;
|
background: none!important;
|
||||||
}
|
}
|
||||||
|
|
||||||
::v-deep .uni-popup__wrapper.uni-custom.center .uni-popup__wrapper-box {
|
/deep/ .uni-popup__wrapper.uni-custom.center .uni-popup__wrapper-box {
|
||||||
max-width: 100vw!important;
|
max-width: 100vw!important;
|
||||||
max-height: 100vh!important;
|
max-height: 100vh!important;
|
||||||
background: none!important;
|
background: none!important;
|
||||||
|
|||||||
@@ -559,7 +559,7 @@ scroll-view ::-webkit-scrollbar {
|
|||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
::v-deep ::-webkit-scrollbar {
|
/deep/::-webkit-scrollbar {
|
||||||
width: 0;
|
width: 0;
|
||||||
height: 0;
|
height: 0;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
@@ -609,7 +609,7 @@ scroll-view ::-webkit-scrollbar {
|
|||||||
font-weight: 500!important;
|
font-weight: 500!important;
|
||||||
}
|
}
|
||||||
|
|
||||||
::v-deep .reward-popup .uni-popup__wrapper-box {
|
/deep/ .reward-popup .uni-popup__wrapper-box {
|
||||||
background: none !important;
|
background: none !important;
|
||||||
max-width: unset !important;
|
max-width: unset !important;
|
||||||
max-height: unset !important;
|
max-height: unset !important;
|
||||||
@@ -618,7 +618,7 @@ scroll-view ::-webkit-scrollbar {
|
|||||||
|
|
||||||
// #ifdef H5
|
// #ifdef H5
|
||||||
// 下拉加载动画【页面】
|
// 下拉加载动画【页面】
|
||||||
::v-deep body uni-page-refresh div{
|
/deep/ body uni-page-refresh div{
|
||||||
width: 14rpx !important;
|
width: 14rpx !important;
|
||||||
height: 14rpx !important;
|
height: 14rpx !important;
|
||||||
background-color: #ccc;
|
background-color: #ccc;
|
||||||
@@ -626,7 +626,7 @@ scroll-view ::-webkit-scrollbar {
|
|||||||
clip: rect(-152rpx, 90rpx, 90rpx, -30rpx) !important;
|
clip: rect(-152rpx, 90rpx, 90rpx, -30rpx) !important;
|
||||||
animation:.6s backgroundChange linear infinite;
|
animation:.6s backgroundChange linear infinite;
|
||||||
}
|
}
|
||||||
::v-deep body uni-page-refresh div::after{
|
/deep/ body uni-page-refresh div::after{
|
||||||
content: "";
|
content: "";
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: -22rpx;
|
left: -22rpx;
|
||||||
@@ -636,7 +636,7 @@ scroll-view ::-webkit-scrollbar {
|
|||||||
background-color: #ccc;
|
background-color: #ccc;
|
||||||
animation:.5s backgroundChange linear infinite;
|
animation:.5s backgroundChange linear infinite;
|
||||||
}
|
}
|
||||||
::v-deep body uni-page-refresh div::before{
|
/deep/ body uni-page-refresh div::before{
|
||||||
content: "";
|
content: "";
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: -22rpx;
|
right: -22rpx;
|
||||||
@@ -646,15 +646,15 @@ scroll-view ::-webkit-scrollbar {
|
|||||||
background-color: #ccc;
|
background-color: #ccc;
|
||||||
animation:.7s backgroundChange linear infinite;
|
animation:.7s backgroundChange linear infinite;
|
||||||
}
|
}
|
||||||
::v-deep body uni-page-refresh > div > div{
|
/deep/ body uni-page-refresh > div > div{
|
||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 下拉加载动画【scroll-view】
|
// 下拉加载动画【scroll-view】
|
||||||
::v-deep body .uni-scroll-view-refresher{
|
/deep/ body .uni-scroll-view-refresher{
|
||||||
background-color: transparent !important;
|
background-color: transparent !important;
|
||||||
}
|
}
|
||||||
::v-deep body .uni-scroll-view-refresher div{
|
/deep/ body .uni-scroll-view-refresher div{
|
||||||
left: 50%;
|
left: 50%;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
transform: translate(-50%, -50%);
|
transform: translate(-50%, -50%);
|
||||||
@@ -666,7 +666,7 @@ scroll-view ::-webkit-scrollbar {
|
|||||||
clip: rect(-152rpx, 90rpx, 90rpx, -30rpx) !important;
|
clip: rect(-152rpx, 90rpx, 90rpx, -30rpx) !important;
|
||||||
animation:.6s backgroundChange linear infinite;
|
animation:.6s backgroundChange linear infinite;
|
||||||
}
|
}
|
||||||
::v-deep body .uni-scroll-view-refresher div::after{
|
/deep/ body .uni-scroll-view-refresher div::after{
|
||||||
content: "";
|
content: "";
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: -22rpx;
|
left: -22rpx;
|
||||||
@@ -676,7 +676,7 @@ scroll-view ::-webkit-scrollbar {
|
|||||||
background-color: #ccc;
|
background-color: #ccc;
|
||||||
animation:.5s backgroundChange linear infinite;
|
animation:.5s backgroundChange linear infinite;
|
||||||
}
|
}
|
||||||
::v-deep body .uni-scroll-view-refresher div::before{
|
/deep/ body .uni-scroll-view-refresher div::before{
|
||||||
content: "";
|
content: "";
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: -22rpx;
|
right: -22rpx;
|
||||||
@@ -686,7 +686,7 @@ scroll-view ::-webkit-scrollbar {
|
|||||||
background-color: #ccc;
|
background-color: #ccc;
|
||||||
animation:.7s backgroundChange linear infinite;
|
animation:.7s backgroundChange linear infinite;
|
||||||
}
|
}
|
||||||
::v-deep body .uni-scroll-view-refresher > div > div{
|
/deep/ body .uni-scroll-view-refresher > div > div{
|
||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
@keyframes backgroundChange {
|
@keyframes backgroundChange {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// 修复图片垂直对齐问题,解决两张图片上下有空白缝隙问题
|
// 修复图片垂直对齐问题,解决两张图片上下有空白缝隙问题
|
||||||
::v-deep ._img {
|
/deep/ ._img {
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
}
|
}
|
||||||
@@ -377,7 +377,7 @@ view {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
::v-deep .goods-form {
|
/deep/ .goods-form {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
position: relative;
|
position: relative;
|
||||||
@@ -1354,7 +1354,7 @@ view {
|
|||||||
border-bottom: 2rpx solid #F4F4F6;
|
border-bottom: 2rpx solid #F4F4F6;
|
||||||
}
|
}
|
||||||
|
|
||||||
::v-deep .form-wrap {
|
/deep/ .form-wrap {
|
||||||
margin: 0 24rpx;
|
margin: 0 24rpx;
|
||||||
|
|
||||||
.icon-right {
|
.icon-right {
|
||||||
|
|||||||
@@ -60,107 +60,55 @@ export default {
|
|||||||
/**
|
/**
|
||||||
* 流式消息入口(自动适配平台)
|
* 流式消息入口(自动适配平台)
|
||||||
*/
|
*/
|
||||||
async sendStreamMessage(message, onChunk, onComplete) {
|
async sendStreamMessage(message, onChunk, onComplete) {
|
||||||
// #ifdef MP-WEIXIN
|
// #ifdef MP-WEIXIN
|
||||||
return new Promise((resolve, reject) => {
|
// 微信小程序:降级为普通请求 + 前端打字模拟
|
||||||
const socketTask = wx.connectSocket({
|
try {
|
||||||
url: 'wss://dev.aigc-quickapp.com/ws/aikefu',
|
const result = await this.sendMessage(message);
|
||||||
header: {}
|
const content = result.content || '';
|
||||||
});
|
const conversationId = result.conversationId || '';
|
||||||
|
|
||||||
let content = '';
|
// 保存会话ID(确保连续对话)
|
||||||
let conversationId = '';
|
if (conversationId) {
|
||||||
let isAuthenticated = false;
|
this.setConversationId(conversationId);
|
||||||
|
}
|
||||||
socketTask.onOpen(() => {
|
|
||||||
console.log('WebSocket 连接成功,开始认证...');
|
// 模拟打字效果
|
||||||
socketTask.send({
|
let index = 0;
|
||||||
data: JSON.stringify({
|
const chunkSize = 2; // 每次显示2个字符
|
||||||
action: 'auth',
|
return new Promise((resolve) => {
|
||||||
uniacid: store.state.uniacid || '1',
|
const timer = setInterval(() => {
|
||||||
token: store.state.token || 'test_token',
|
if (index < content.length) {
|
||||||
user_id: store.state.memberInfo?.id || 'anonymous'
|
const chunk = content.substring(index, index + chunkSize);
|
||||||
})
|
index += chunkSize;
|
||||||
});
|
if (onChunk) onChunk(chunk);
|
||||||
});
|
} else {
|
||||||
|
clearInterval(timer);
|
||||||
socketTask.onMessage((res) => {
|
if (onComplete) {
|
||||||
try {
|
onComplete({
|
||||||
const data = JSON.parse(res.data);
|
content: content,
|
||||||
console.log('收到 WebSocket 消息:', data);
|
conversation_id: conversationId
|
||||||
|
});
|
||||||
if (data.type === 'auth_success') {
|
}
|
||||||
console.log('认证成功,发送聊天消息...');
|
resolve({ content, conversation_id: conversationId });
|
||||||
isAuthenticated = true;
|
}
|
||||||
socketTask.send({
|
}, 80); // 打字速度:80ms/次
|
||||||
data: JSON.stringify({
|
});
|
||||||
action: 'chat',
|
} catch (error) {
|
||||||
uniacid: store.state.uniacid || '1',
|
console.error('小程序流式消息降级失败:', error);
|
||||||
query: message,
|
if (onComplete) {
|
||||||
user_id: store.state.memberInfo?.id || 'anonymous',
|
onComplete({ error: error.message || '发送失败' });
|
||||||
conversation_id: this.getConversationId() || ''
|
}
|
||||||
})
|
throw error;
|
||||||
});
|
}
|
||||||
} else if (data.type === 'auth_failed') {
|
|
||||||
const errorMsg = '认证失败,请重新登录';
|
|
||||||
console.error(errorMsg, data);
|
|
||||||
reject(new Error(errorMsg));
|
|
||||||
if (onComplete) onComplete({ error: errorMsg });
|
|
||||||
socketTask.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理流式消息块
|
|
||||||
else if (data.type === 'message' || data.event === 'message') {
|
|
||||||
const text = data.answer || data.content || data.text || '';
|
|
||||||
content += text;
|
|
||||||
if (onChunk) onChunk(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理流结束
|
|
||||||
else if (data.event === 'message_end' || data.type === 'message_end') {
|
|
||||||
conversationId = data.conversation_id || '';
|
|
||||||
if (conversationId) {
|
|
||||||
this.setConversationId(conversationId);
|
|
||||||
}
|
|
||||||
if (onComplete) {
|
|
||||||
onComplete({ content, conversation_id: conversationId });
|
|
||||||
}
|
|
||||||
resolve({ content, conversation_id: conversationId });
|
|
||||||
socketTask.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 可选:处理 done
|
|
||||||
else if (data.type === 'done') {
|
|
||||||
console.log('对话完成:', data);
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (e) {
|
|
||||||
console.error('WebSocket 消息解析失败:', e, '原始数据:', res.data);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
socketTask.onError((err) => {
|
|
||||||
const errorMsg = 'WebSocket 连接失败';
|
|
||||||
console.error(errorMsg, err);
|
|
||||||
reject(new Error(errorMsg));
|
|
||||||
if (onComplete) onComplete({ error: errorMsg });
|
|
||||||
});
|
|
||||||
|
|
||||||
socketTask.onClose(() => {
|
|
||||||
console.log('WebSocket 连接已关闭');
|
|
||||||
});
|
|
||||||
|
|
||||||
const timeout = setTimeout(() => {
|
|
||||||
if (!isAuthenticated || content === '') {
|
|
||||||
console.warn('WebSocket 超时,强制关闭');
|
|
||||||
socketTask.close();
|
|
||||||
reject(new Error('AI服务响应超时'));
|
|
||||||
if (onComplete) onComplete({ error: 'AI服务响应超时' });
|
|
||||||
}
|
|
||||||
}, 10000);
|
|
||||||
});
|
|
||||||
// #endif
|
// #endif
|
||||||
},
|
|
||||||
|
// #ifdef H5
|
||||||
|
// H5:使用真实流式(EventSource / Fetch)
|
||||||
|
return this.sendHttpStream(message, onChunk, onComplete);
|
||||||
|
// #endif
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* HTTP 流式请求(仅 H5 使用)
|
* HTTP 流式请求(仅 H5 使用)
|
||||||
*/
|
*/
|
||||||
@@ -183,75 +131,64 @@ export default {
|
|||||||
conversation_id: this.getConversationId() || ''
|
conversation_id: this.getConversationId() || ''
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!response.ok || !response.body) {
|
if (!response.ok) {
|
||||||
throw new Error('无效响应');
|
throw new Error(`HTTP ${response.status}`);
|
||||||
}
|
}
|
||||||
|
if (!response.body) {
|
||||||
|
throw new Error('响应体不可用');
|
||||||
|
}
|
||||||
|
|
||||||
const reader = response.body.getReader();
|
const reader = response.body.getReader();
|
||||||
const decoder = new TextDecoder('utf-8');
|
const decoder = new TextDecoder('utf-8');
|
||||||
let buffer = '';
|
let buffer = '';
|
||||||
let content = '';
|
let content = '';
|
||||||
let conversationId = '';
|
let conversationId = '';
|
||||||
|
|
||||||
while (true) {
|
function processBuffer(buf, callback) {
|
||||||
const { done, value } = await reader.read();
|
const lines = buf.split('\n');
|
||||||
if (done) break;
|
buf = lines.pop() || '';
|
||||||
|
|
||||||
buffer += decoder.decode(value, { stream: true });
|
|
||||||
|
|
||||||
// 按行分割,保留不完整的最后一行
|
|
||||||
const lines = buffer.split('\n');
|
|
||||||
buffer = lines.pop() || ''; // 未完成的行留到下次
|
|
||||||
|
|
||||||
for (const line of lines) {
|
for (const line of lines) {
|
||||||
const trimmed = line.trim();
|
const trimmed = line.trim();
|
||||||
if (trimmed.startsWith('data:')) {
|
if (trimmed.startsWith('data:')) {
|
||||||
try {
|
const jsonStr = trimmed.slice(5).trim();
|
||||||
const jsonStr = trimmed.slice(5).trim();
|
if (jsonStr) {
|
||||||
if (jsonStr && jsonStr !== '[DONE]') {
|
try {
|
||||||
const data = JSON.parse(jsonStr);
|
const data = JSON.parse(jsonStr);
|
||||||
if (data.event === 'message') {
|
if (data.event === 'message') {
|
||||||
const text = data.answer || data.text || '';
|
const text = data.answer || data.text || '';
|
||||||
content += text;
|
content += text;
|
||||||
if (onChunk) onChunk(text);
|
callback(text);
|
||||||
}
|
}
|
||||||
if (data.conversation_id) {
|
if (data.conversation_id) {
|
||||||
conversationId = data.conversation_id;
|
conversationId = data.conversation_id;
|
||||||
}
|
}
|
||||||
if (data.event === 'message_end') {
|
if (data.event === 'message_end') {
|
||||||
// 可提前结束
|
// 可选:提前完成
|
||||||
}
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.warn('解析流数据失败:', e);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
|
||||||
console.warn('解析失败:', e, line);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理最后残留的 buffer(如果有)
|
while (true) {
|
||||||
if (buffer.trim().startsWith('data:')) {
|
const { done, value } = await reader.read();
|
||||||
try {
|
if (done) break;
|
||||||
const jsonStr = buffer.trim().slice(5);
|
buffer += decoder.decode(value, { stream: true });
|
||||||
if (jsonStr) {
|
buffer = processBuffer(buffer, (chunk) => {
|
||||||
const data = JSON.parse(jsonStr);
|
if (onChunk) onChunk(chunk);
|
||||||
if (data.event === 'message') {
|
});
|
||||||
const text = data.answer || '';
|
|
||||||
content += text;
|
|
||||||
if (onChunk) onChunk(text);
|
|
||||||
}
|
|
||||||
if (data.conversation_id) {
|
|
||||||
conversationId = data.conversation_id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.warn('最后 buffer 解析失败:', e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (onComplete) {
|
if (onComplete) {
|
||||||
onComplete({ content, conversation_id: conversationId });
|
onComplete({
|
||||||
|
content,
|
||||||
|
conversation_id: conversationId
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return { content, conversation_id: conversationId };
|
return { content, conversation_id: conversationId };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -259,6 +196,11 @@ export default {
|
|||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
// #endif
|
// #endif
|
||||||
|
|
||||||
|
// #ifdef MP-WEIXIN
|
||||||
|
// 理论上不会执行到这里,但防止 fallback
|
||||||
|
return this.sendStreamMessage(message, onChunk, onComplete);
|
||||||
|
// #endif
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -489,4 +431,4 @@ export default {
|
|||||||
return null;
|
return null;
|
||||||
// #endif
|
// #endif
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -14,7 +14,7 @@ export const langConfig = {
|
|||||||
// 主题配置
|
// 主题配置
|
||||||
export const themeConfig = {
|
export const themeConfig = {
|
||||||
// 主题列表
|
// 主题列表
|
||||||
themeList: ['default', 'red', 'green', 'blue', 'pink', 'gold', 'purple', 'yellow', 'black'],
|
themeList: ['default', 'red', 'green', 'blue'],
|
||||||
// 默认主题
|
// 默认主题
|
||||||
defaultTheme: 'default'
|
defaultTheme: 'default'
|
||||||
};
|
};
|
||||||
@@ -98,6 +98,28 @@ class ConfigExternal {
|
|||||||
return this.loadPromises[key];
|
return this.loadPromises[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加载主题配置(同步方式)
|
||||||
|
* @param {string} theme - 主题名称
|
||||||
|
* @returns {object} - 主题配置
|
||||||
|
*/
|
||||||
|
loadThemeSync(theme = themeConfig.defaultTheme) {
|
||||||
|
if (this.loadedConfigs[`theme_${theme}`]) {
|
||||||
|
return this.loadedConfigs[`theme_${theme}`];
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 动态加载主题配置
|
||||||
|
const themeData = require(`@/common/js/style_color.js`)['default'][theme];
|
||||||
|
console.log('sync themeData => ', themeData);
|
||||||
|
this.loadedConfigs[`theme_${theme}`] = themeData;
|
||||||
|
return themeData;
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`加载主题 ${theme} 失败:`, error);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 加载主题配置(异步方式)
|
* 加载主题配置(异步方式)
|
||||||
* @param {string} theme - 主题名称
|
* @param {string} theme - 主题名称
|
||||||
@@ -116,7 +138,7 @@ class ConfigExternal {
|
|||||||
try {
|
try {
|
||||||
// 动态加载主题配置
|
// 动态加载主题配置
|
||||||
const themeData = require(`@/common/js/style_color.js`)['default'][theme];
|
const themeData = require(`@/common/js/style_color.js`)['default'][theme];
|
||||||
// console.log('async themeData => ', themeData);
|
console.log('async themeData => ', themeData);
|
||||||
this.loadedConfigs[`theme_${theme}`] = themeData;
|
this.loadedConfigs[`theme_${theme}`] = themeData;
|
||||||
resolve(themeData);
|
resolve(themeData);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -20,10 +20,6 @@ try {
|
|||||||
// 默认域名, 自定义发行时可以修改
|
// 默认域名, 自定义发行时可以修改
|
||||||
let defaultDomain = '';
|
let defaultDomain = '';
|
||||||
|
|
||||||
// #ifdef H5_XCX_5G_QUICKAPP_COM
|
|
||||||
defaultDomain = 'https://xcx20.5g-quickapp.com';
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
// #ifdef H5_XCX_AIGC_QUICKAPP_COM
|
// #ifdef H5_XCX_AIGC_QUICKAPP_COM
|
||||||
defaultDomain = 'https://xcx.aigc-quickapp.com/';
|
defaultDomain = 'https://xcx.aigc-quickapp.com/';
|
||||||
// #endif
|
// #endif
|
||||||
@@ -47,21 +43,19 @@ let localDevConfig = { uniacid: 0, domain: defaultDomain };
|
|||||||
|
|
||||||
// #ifndef PRODUCTION
|
// #ifndef PRODUCTION
|
||||||
// 尝试动态加载本地配置文件
|
// 尝试动态加载本地配置文件
|
||||||
if (process?.env?.NODE_ENV === 'development') {
|
try {
|
||||||
try {
|
// 尝试从项目根目录加载本地配置文件
|
||||||
// 尝试从项目根目录加载本地配置文件
|
// 使用相对路径的方式,确保在不同平台下都能正确解析
|
||||||
// 使用相对路径的方式,确保在不同平台下都能正确解析
|
let customConfig = require('@/.local.config.js').default;
|
||||||
let customConfig = require('@/.local.config.js').default;
|
if (customConfig) {
|
||||||
if (customConfig) {
|
localDevConfig = customConfig;
|
||||||
localDevConfig = customConfig;
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
// 如果本地配置文件不存在或加载失败,保持使用默认配置
|
|
||||||
// 只在开发模式下输出提示信息
|
|
||||||
// #ifdef WEB
|
|
||||||
console.log('本地配置文件 .local.config.js 不存在,使用默认配置');
|
|
||||||
// #endif
|
|
||||||
}
|
}
|
||||||
|
} catch (e) {
|
||||||
|
// 如果本地配置文件不存在或加载失败,保持使用默认配置
|
||||||
|
// 只在开发模式下输出提示信息
|
||||||
|
// #ifdef WEB
|
||||||
|
console.log('本地配置文件 .local.config.js 不存在,使用默认配置');
|
||||||
|
// #endif
|
||||||
}
|
}
|
||||||
// #endif
|
// #endif
|
||||||
|
|
||||||
|
|||||||
@@ -28,29 +28,28 @@ export class CustomerService {
|
|||||||
return this.latestPlatformConfig;
|
return this.latestPlatformConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 优先级:外部传入 > vuex store > 空对象
|
// 优先级:外部传入的最新配置 > vuex配置 > 空对象
|
||||||
const servicerConfig = this.externalConfig || this.vm.$store.state.servicerConfig || {};
|
const servicerConfig = this.externalConfig || this.vm.$store.state.servicerConfig || {};
|
||||||
console.log(`【实时客服配置】`, servicerConfig);
|
console.log(`【实时客服配置】`, servicerConfig);
|
||||||
|
|
||||||
let platformConfig = null;
|
let platformConfig = null;
|
||||||
|
|
||||||
// #ifdef H5
|
// #ifdef H5
|
||||||
platformConfig = servicerConfig.h5 && typeof servicerConfig.h5 === 'object' ? servicerConfig.h5 : null;
|
platformConfig = servicerConfig.h5 ? (typeof servicerConfig.h5 === 'object' ? servicerConfig.h5 : null) : null;
|
||||||
// #endif
|
// #endif
|
||||||
|
|
||||||
// #ifdef MP-WEIXIN
|
// #ifdef MP-WEIXIN
|
||||||
platformConfig = servicerConfig.weapp && typeof servicerConfig.weapp === 'object' ? servicerConfig.weapp : null;
|
platformConfig = servicerConfig.weapp ? (typeof servicerConfig.weapp === 'object' ? servicerConfig.weapp : null) : null;
|
||||||
// #endif
|
// #endif
|
||||||
|
|
||||||
// #ifdef MP-ALIPAY
|
// #ifdef MP-ALIPAY
|
||||||
platformConfig = servicerConfig.aliapp && typeof servicerConfig.aliapp === 'object' ? servicerConfig.aliapp : null;
|
platformConfig = servicerConfig.aliapp ? (typeof servicerConfig.aliapp === 'object' ? servicerConfig.aliapp : null) : null;
|
||||||
// #endif
|
// #endif
|
||||||
|
|
||||||
// #ifdef PC
|
// #ifdef PC
|
||||||
platformConfig = servicerConfig.pc && typeof servicerConfig.pc === 'object' ? servicerConfig.pc : null;
|
platformConfig = servicerConfig.pc ? (typeof servicerConfig.pc === 'object' ? servicerConfig.pc : null) : null;
|
||||||
// #endif
|
// #endif
|
||||||
|
|
||||||
// 防止空数组被当作有效配置
|
// 处理空数组情况(你的配置中pc/aliapp是空数组,转为null)
|
||||||
if (Array.isArray(platformConfig)) {
|
if (Array.isArray(platformConfig)) {
|
||||||
platformConfig = null;
|
platformConfig = null;
|
||||||
}
|
}
|
||||||
@@ -83,25 +82,39 @@ export class CustomerService {
|
|||||||
validateConfig() {
|
validateConfig() {
|
||||||
const config = this.getPlatformConfig();
|
const config = this.getPlatformConfig();
|
||||||
const wxworkConfig = this.getWxworkConfig();
|
const wxworkConfig = this.getWxworkConfig();
|
||||||
|
|
||||||
const result = {
|
const result = {
|
||||||
isValid: true,
|
isValid: true,
|
||||||
errors: [],
|
errors: [],
|
||||||
warnings: []
|
warnings: []
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!config || !config.type) {
|
if (!config) {
|
||||||
result.isValid = false;
|
result.isValid = false;
|
||||||
result.errors.push('客服类型未配置');
|
result.errors.push('客服配置不存在');
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (config.type === 'aikefu') {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!config.type) {
|
||||||
|
result.isValid = false;
|
||||||
|
result.errors.push('客服类型未配置');
|
||||||
|
}
|
||||||
|
|
||||||
if (config.type === 'wxwork') {
|
if (config.type === 'wxwork') {
|
||||||
if (!wxworkConfig || !wxworkConfig.enable) {
|
if (!wxworkConfig) {
|
||||||
result.warnings.push('企业微信未启用');
|
result.isValid = false;
|
||||||
}
|
result.errors.push('企业微信配置不存在');
|
||||||
if (!wxworkConfig.contact_url) {
|
} else {
|
||||||
result.warnings.push('企业微信活码链接未配置');
|
if (!wxworkConfig.enable) {
|
||||||
|
result.warnings.push('企业微信功能未启用');
|
||||||
|
}
|
||||||
|
if (!wxworkConfig.contact_url) {
|
||||||
|
result.warnings.push('企业微信活码链接未配置,将使用原有客服方式');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,39 +122,40 @@ export class CustomerService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 跳转到 AI 客服页面(Dify)
|
* 跳转到Dify客服页面
|
||||||
*/
|
*/
|
||||||
openDifyService() {
|
openDifyService() {
|
||||||
try {
|
try {
|
||||||
// 清除未读数(如果存在)
|
if (this.vm.setAiUnreadCount) {
|
||||||
if (typeof this.vm.setAiUnreadCount === 'function') {
|
|
||||||
this.vm.setAiUnreadCount(0);
|
this.vm.setAiUnreadCount(0);
|
||||||
}
|
}
|
||||||
|
// 强制跳转,忽略框架层的封装
|
||||||
// ✅ 修正路径:必须与 pages.json 中注册的路径一致
|
uni.redirectTo({
|
||||||
const aiChatUrl = '/pages_tool/ai-chat/index';
|
url: '/pages_tool/ai-chat/index',
|
||||||
|
|
||||||
// ✅ 使用 navigateTo 保留返回栈(体验更好)
|
|
||||||
uni.navigateTo({
|
|
||||||
url: aiChatUrl,
|
|
||||||
fail: (err) => {
|
fail: (err) => {
|
||||||
console.error('跳转 AI 客服失败:', err);
|
// 兜底:使用window.location跳转(H5)
|
||||||
// H5 兜底
|
|
||||||
// #ifdef H5
|
// #ifdef H5
|
||||||
window.location.href = aiChatUrl;
|
window.location.href = '/pages_tool/ai-chat/index';
|
||||||
// #endif
|
// #endif
|
||||||
uni.showToast({ title: '打开客服失败', icon: 'none' });
|
console.error('跳转Dify客服失败:', err);
|
||||||
|
uni.showToast({
|
||||||
|
title: '跳转客服失败',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('跳转 AI 客服异常:', e);
|
console.error('跳转Dify客服异常:', e);
|
||||||
uni.showToast({ title: '打开客服失败', icon: 'none' });
|
uni.showToast({
|
||||||
|
title: '跳转客服失败',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 处理客服点击事件(统一入口)
|
* 处理客服点击事件
|
||||||
* @param {Object} options 选项参数(用于消息卡片等)
|
* @param {Object} options 选项参数
|
||||||
*/
|
*/
|
||||||
handleCustomerClick(options = {}) {
|
handleCustomerClick(options = {}) {
|
||||||
const validation = this.validateConfig();
|
const validation = this.validateConfig();
|
||||||
@@ -156,9 +170,6 @@ export class CustomerService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const config = this.getPlatformConfig();
|
const config = this.getPlatformConfig();
|
||||||
console.log('【当前客服配置】', config);
|
|
||||||
console.log('【客服类型】', config.type);
|
|
||||||
|
|
||||||
const { niushop = {}, sendMessageTitle = '', sendMessagePath = '', sendMessageImg = '' } = options;
|
const { niushop = {}, sendMessageTitle = '', sendMessagePath = '', sendMessageImg = '' } = options;
|
||||||
|
|
||||||
if (config.type === 'none') {
|
if (config.type === 'none') {
|
||||||
@@ -166,51 +177,44 @@ export class CustomerService {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 核心路由:根据 type 决定行为
|
// 核心分支:根据最新的type处理
|
||||||
switch (config.type) {
|
switch (config.type) {
|
||||||
case 'aikefu':
|
case 'aikefu':
|
||||||
console.log('【跳转 AI 客服】目标路径: /pages_tool/ai-chat/index');
|
|
||||||
this.openDifyService();
|
this.openDifyService();
|
||||||
break;
|
break;
|
||||||
case 'wxwork':
|
case 'wxwork':
|
||||||
console.log('【跳转企业微信客服】');
|
|
||||||
this.openWxworkService(false, config, options);
|
this.openWxworkService(false, config, options);
|
||||||
break;
|
break;
|
||||||
case 'third':
|
case 'third':
|
||||||
console.log('【跳转第三方客服】');
|
|
||||||
this.openThirdService(config);
|
|
||||||
break;
|
|
||||||
case 'miniprogram':
|
|
||||||
console.log('【跳转第三方小程序客服】');
|
|
||||||
this.openThirdService(config);
|
this.openThirdService(config);
|
||||||
break;
|
break;
|
||||||
case 'niushop':
|
case 'niushop':
|
||||||
console.log('【跳转牛商客服】');
|
|
||||||
this.openNiushopService(niushop);
|
this.openNiushopService(niushop);
|
||||||
break;
|
break;
|
||||||
case 'weapp':
|
case 'weapp':
|
||||||
console.log('【跳转微信官方客服】');
|
|
||||||
this.openWeappService(config, options);
|
this.openWeappService(config, options);
|
||||||
break;
|
break;
|
||||||
case 'aliapp':
|
case 'aliapp':
|
||||||
console.log('【跳转支付宝客服】');
|
|
||||||
this.openAliappService(config);
|
this.openAliappService(config);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
console.error('【未知客服类型】', config.type);
|
|
||||||
this.makePhoneCall();
|
this.makePhoneCall();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ================== 各类型客服实现 ==================
|
/**
|
||||||
|
* 打开企业微信客服
|
||||||
|
* @param {boolean} useOriginalService 是否使用原有客服方式
|
||||||
|
* @param {Object} servicerConfig 客服配置
|
||||||
|
* @param {Object} options 选项参数
|
||||||
|
*/
|
||||||
openWxworkService(useOriginalService = false, servicerConfig = null, options = {}) {
|
openWxworkService(useOriginalService = false, servicerConfig = null, options = {}) {
|
||||||
const config = servicerConfig || this.getPlatformConfig();
|
const config = servicerConfig || this.getPlatformConfig();
|
||||||
const wxworkConfig = this.getWxworkConfig();
|
const wxworkConfig = this.getWxworkConfig();
|
||||||
const { sendMessageTitle = '', sendMessagePath = '', sendMessageImg = '' } = options;
|
const { sendMessageTitle = '', sendMessagePath = '', sendMessageImg = '' } = options;
|
||||||
|
|
||||||
// #ifdef MP-WEIXIN
|
// #ifdef MP-WEIXIN
|
||||||
if (!useOriginalService && wxworkConfig?.enable && wxworkConfig?.contact_url) {
|
if (wxworkConfig?.enable && wxworkConfig?.contact_url && !useOriginalService) {
|
||||||
wx.navigateToMiniProgram({
|
wx.navigateToMiniProgram({
|
||||||
appId: 'wxeb490c6f9b154ef9',
|
appId: 'wxeb490c6f9b154ef9',
|
||||||
path: `pages/contacts/externalContactDetail?url=${encodeURIComponent(wxworkConfig.contact_url)}`,
|
path: `pages/contacts/externalContactDetail?url=${encodeURIComponent(wxworkConfig.contact_url)}`,
|
||||||
@@ -221,16 +225,9 @@ export class CustomerService {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// 检查是否有企业微信配置
|
|
||||||
if (!config.wxwork_url && !config.corpid) {
|
|
||||||
console.error('企业微信配置不完整,缺少 wxwork_url 或 corpid');
|
|
||||||
uni.showToast({ title: '企业微信配置不完整', icon: 'none' });
|
|
||||||
this.fallbackToPhoneCall();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
wx.openCustomerServiceChat({
|
wx.openCustomerServiceChat({
|
||||||
extInfo: { url: config.wxwork_url || '' },
|
extInfo: { url: config.wxwork_url },
|
||||||
corpId: config.corpid || '',
|
corpId: config.corpid,
|
||||||
showMessageCard: true,
|
showMessageCard: true,
|
||||||
sendMessageTitle,
|
sendMessageTitle,
|
||||||
sendMessagePath,
|
sendMessagePath,
|
||||||
@@ -240,181 +237,224 @@ export class CustomerService {
|
|||||||
// #endif
|
// #endif
|
||||||
|
|
||||||
// #ifdef H5
|
// #ifdef H5
|
||||||
if (!useOriginalService && wxworkConfig?.enable && wxworkConfig?.contact_url) {
|
if (wxworkConfig?.enable && wxworkConfig?.contact_url) {
|
||||||
window.location.href = wxworkConfig.contact_url;
|
window.location.href = wxworkConfig.contact_url;
|
||||||
} else if (config.wxwork_url) {
|
} else if (config.wxwork_url) {
|
||||||
window.location.href = config.wxwork_url;
|
location.href = config.wxwork_url;
|
||||||
} else {
|
} else {
|
||||||
this.fallbackToPhoneCall();
|
this.fallbackToPhoneCall();
|
||||||
}
|
}
|
||||||
// #endif
|
// #endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 打开第三方客服
|
||||||
|
* @param {Object} config 客服配置
|
||||||
|
*/
|
||||||
openThirdService(config) {
|
openThirdService(config) {
|
||||||
console.log('【第三方客服配置】', config);
|
|
||||||
console.log('【配置字段】', Object.keys(config));
|
|
||||||
|
|
||||||
// 支持多种可能的字段名
|
|
||||||
const miniAppId = config.mini_app_id || config.miniAppId || config.appid || config.appId || config.app_id;
|
|
||||||
const miniAppPath = config.mini_app_path || config.miniAppPath || config.path || config.page_path || '';
|
|
||||||
|
|
||||||
console.log('【解析后的小程序配置】AppID:', miniAppId, 'Path:', miniAppPath);
|
|
||||||
|
|
||||||
// 优先处理第三方微信小程序客服
|
|
||||||
if (miniAppId) {
|
|
||||||
console.log('【跳转第三方小程序】AppID:', miniAppId, 'Path:', miniAppPath);
|
|
||||||
// #ifdef MP-WEIXIN
|
|
||||||
wx.navigateToMiniProgram({
|
|
||||||
appId: miniAppId,
|
|
||||||
path: miniAppPath,
|
|
||||||
success: () => {
|
|
||||||
console.log('【跳转第三方小程序成功】');
|
|
||||||
},
|
|
||||||
fail: (err) => {
|
|
||||||
console.error('【跳转第三方小程序失败】', err);
|
|
||||||
uni.showToast({ title: '跳转失败,请稍后重试', icon: 'none' });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// #endif
|
|
||||||
// #ifdef H5
|
|
||||||
uni.showToast({ title: '第三方小程序客服仅在微信小程序中可用', icon: 'none' });
|
|
||||||
// #endif
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理第三方链接客服
|
|
||||||
if (config.third_url) {
|
if (config.third_url) {
|
||||||
console.log('【跳转第三方链接】', config.third_url);
|
|
||||||
// #ifdef H5
|
|
||||||
window.location.href = config.third_url;
|
window.location.href = config.third_url;
|
||||||
// #endif
|
|
||||||
// #ifdef MP-WEIXIN
|
|
||||||
uni.setClipboardData({
|
|
||||||
data: config.third_url,
|
|
||||||
success: () => {
|
|
||||||
uni.showToast({ title: '链接已复制,请在浏览器打开', icon: 'none' });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// #endif
|
|
||||||
} else {
|
} else {
|
||||||
console.error('【第三方客服配置不完整】缺少 mini_app_id 或 third_url');
|
|
||||||
this.fallbackToPhoneCall();
|
this.fallbackToPhoneCall();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 打开牛商客服
|
||||||
|
* @param {Object} niushop 牛商参数
|
||||||
|
*/
|
||||||
openNiushopService(niushop) {
|
openNiushopService(niushop) {
|
||||||
if (Object.keys(niushop).length > 0 && this.vm.$util?.redirectTo) {
|
if (Object.keys(niushop).length > 0) {
|
||||||
this.vm.$util.redirectTo('/pages_tool/chat/room', niushop);
|
this.vm.$util.redirectTo('/pages_tool/chat/room', niushop);
|
||||||
} else {
|
} else {
|
||||||
this.makePhoneCall();
|
this.makePhoneCall();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 打开微信小程序客服
|
||||||
|
* @param {Object} config 客服配置
|
||||||
|
* @param {Object} options 选项参数
|
||||||
|
*/
|
||||||
openWeappService(config, options = {}) {
|
openWeappService(config, options = {}) {
|
||||||
// 如果 useOfficial 为 true 或 undefined,则使用原生系统客服(由 button open-type="contact" 触发)
|
if (!this.shouldUseCustomService(config)) {
|
||||||
// 此方法仅用于自定义跳转(如 useOfficial: false)
|
console.log('使用官方微信小程序客服');
|
||||||
if (config.useOfficial !== false) {
|
|
||||||
// 不做任何事,应由 <button open-type="contact"> 触发
|
|
||||||
console.log('使用微信官方客服,请确保按钮为 <button open-type="contact">');
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log('使用自定义微信小程序客服');
|
||||||
this.handleCustomWeappService(config, options);
|
this.handleCustomWeappService(config, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 处理自定义微信小程序客服
|
||||||
|
* @param {Object} config 客服配置
|
||||||
|
* @param {Object} options 选项参数
|
||||||
|
*/
|
||||||
handleCustomWeappService(config, options = {}) {
|
handleCustomWeappService(config, options = {}) {
|
||||||
|
const { sendMessageTitle = '', sendMessagePath = '', sendMessageImg = '' } = options;
|
||||||
|
|
||||||
if (config.customServiceUrl) {
|
if (config.customServiceUrl) {
|
||||||
let url = config.customServiceUrl;
|
let url = config.customServiceUrl;
|
||||||
const params = [];
|
const params = [];
|
||||||
const { sendMessageTitle, sendMessagePath, sendMessageImg } = options;
|
|
||||||
if (sendMessageTitle) params.push(`title=${encodeURIComponent(sendMessageTitle)}`);
|
if (sendMessageTitle) params.push(`title=${encodeURIComponent(sendMessageTitle)}`);
|
||||||
if (sendMessagePath) params.push(`path=${encodeURIComponent(sendMessagePath)}`);
|
if (sendMessagePath) params.push(`path=${encodeURIComponent(sendMessagePath)}`);
|
||||||
if (sendMessageImg) params.push(`img=${encodeURIComponent(sendMessageImg)}`);
|
if (sendMessageImg) params.push(`img=${encodeURIComponent(sendMessageImg)}`);
|
||||||
|
|
||||||
if (params.length > 0) {
|
if (params.length > 0) {
|
||||||
url += (url.includes('?') ? '&' : '?') + params.join('&');
|
url += (url.includes('?') ? '&' : '?') + params.join('&');
|
||||||
}
|
}
|
||||||
uni.navigateTo({ url });
|
|
||||||
|
uni.navigateTo({
|
||||||
|
url: url,
|
||||||
|
fail: (err) => {
|
||||||
|
console.error('跳转自定义客服页面失败:', err);
|
||||||
|
this.tryThirdPartyService(config, options);
|
||||||
|
}
|
||||||
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.tryThirdPartyService(config, options);
|
this.tryThirdPartyService(config, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 尝试使用第三方客服
|
||||||
|
* @param {Object} config 客服配置
|
||||||
|
* @param {Object} options 选项参数
|
||||||
|
*/
|
||||||
tryThirdPartyService(config, options = {}) {
|
tryThirdPartyService(config, options = {}) {
|
||||||
// 支持第三方微信小程序客服
|
if (config.thirdPartyServiceUrl) {
|
||||||
if (config.thirdPartyMiniAppId || config.mini_app_id) {
|
|
||||||
// #ifdef MP-WEIXIN
|
|
||||||
wx.navigateToMiniProgram({
|
|
||||||
appId: config.thirdPartyMiniAppId || config.mini_app_id,
|
|
||||||
path: config.thirdPartyMiniAppPath || config.mini_app_path || ''
|
|
||||||
});
|
|
||||||
// #endif
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 支持第三方链接客服
|
|
||||||
if (config.thirdPartyServiceUrl || config.third_url) {
|
|
||||||
const serviceUrl = config.thirdPartyServiceUrl || config.third_url;
|
|
||||||
// #ifdef H5
|
// #ifdef H5
|
||||||
window.open(serviceUrl, '_blank');
|
window.open(config.thirdPartyServiceUrl, '_blank');
|
||||||
// #endif
|
// #endif
|
||||||
|
|
||||||
// #ifdef MP-WEIXIN
|
// #ifdef MP-WEIXIN
|
||||||
uni.setClipboardData({ data: serviceUrl });
|
if (config.thirdPartyMiniAppId) {
|
||||||
uni.showToast({ title: '客服链接已复制', icon: 'none' });
|
wx.navigateToMiniProgram({
|
||||||
|
appId: config.thirdPartyMiniAppId,
|
||||||
|
path: config.thirdPartyMiniAppPath || '',
|
||||||
|
fail: (err) => {
|
||||||
|
console.error('跳转第三方小程序失败:', err);
|
||||||
|
this.fallbackToPhoneCall();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
uni.setClipboardData({
|
||||||
|
data: config.thirdPartyServiceUrl,
|
||||||
|
success: () => {
|
||||||
|
uni.showModal({
|
||||||
|
title: '客服链接已复制',
|
||||||
|
content: '客服链接已复制到剪贴板,请在浏览器中粘贴访问',
|
||||||
|
showCancel: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
// #endif
|
// #endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.fallbackToPhoneCall();
|
this.fallbackToPhoneCall();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 降级到电话客服
|
||||||
|
*/
|
||||||
|
fallbackToPhoneCall() {
|
||||||
|
uni.showModal({
|
||||||
|
title: '联系客服',
|
||||||
|
content: '在线客服暂时不可用,是否拨打电话联系客服?',
|
||||||
|
success: (res) => {
|
||||||
|
if (res.confirm) {
|
||||||
|
this.makePhoneCall();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 打开支付宝小程序客服
|
||||||
|
* @param {Object} config 客服配置
|
||||||
|
*/
|
||||||
openAliappService(config) {
|
openAliappService(config) {
|
||||||
if (config.type === 'aikefu') {
|
console.log('支付宝小程序客服', config);
|
||||||
this.openDifyService();
|
switch (config.type) {
|
||||||
} else if (config.type === 'third') {
|
case 'aikefu':
|
||||||
this.openThirdService(config);
|
this.openDifyService();
|
||||||
} else {
|
break;
|
||||||
// 支付宝原生客服由 button open-type="contact" 触发,此处不处理
|
case 'third':
|
||||||
console.log('使用支付宝官方客服');
|
this.openThirdService(config);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
console.log('使用支付宝官方客服');
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ================== 辅助方法 ==================
|
/**
|
||||||
|
* 拨打电话
|
||||||
|
*/
|
||||||
makePhoneCall() {
|
makePhoneCall() {
|
||||||
this.vm.$api.sendRequest({
|
this.vm.$api.sendRequest({
|
||||||
url: '/api/site/shopcontact',
|
url: '/api/site/shopcontact',
|
||||||
success: res => {
|
success: res => {
|
||||||
if (res.code === 0 && res.data?.mobile) {
|
if (res.code === 0 && res.data?.mobile) {
|
||||||
uni.makePhoneCall({ phoneNumber: res.data.mobile });
|
uni.makePhoneCall({
|
||||||
|
phoneNumber: res.data.mobile
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
uni.showToast({ title: '暂无客服电话', icon: 'none' });
|
uni.showToast({
|
||||||
|
title: '暂无客服电话',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
fail: () => {
|
fail: () => {
|
||||||
uni.showToast({ title: '获取客服电话失败', icon: 'none' });
|
uni.showToast({
|
||||||
|
title: '获取客服电话失败',
|
||||||
|
icon: 'none'
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 显示无客服弹窗
|
||||||
|
*/
|
||||||
showNoServicePopup() {
|
showNoServicePopup() {
|
||||||
const siteInfo = this.vm.$store.state.siteInfo || {};
|
const siteInfo = this.vm.$store.state.siteInfo || {};
|
||||||
const message = siteInfo?.site_tel
|
const message = siteInfo?.site_tel
|
||||||
? `请联系客服,客服电话是 ${siteInfo.site_tel}`
|
? `请联系客服,客服电话是${siteInfo.site_tel}`
|
||||||
: '抱歉,商家暂无客服,请线下联系';
|
: '抱歉,商家暂无客服,请线下联系';
|
||||||
uni.showModal({ title: '联系客服', content: message, showCancel: false });
|
|
||||||
}
|
|
||||||
|
|
||||||
showConfigErrorPopup(errors) {
|
|
||||||
uni.showModal({
|
uni.showModal({
|
||||||
title: '客服配置错误',
|
title: '联系客服',
|
||||||
content: `配置有误:\n${errors.join('\n')}`,
|
content: message,
|
||||||
showCancel: false
|
showCancel: false
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 显示配置错误弹窗
|
||||||
|
* @param {Array} errors 错误列表
|
||||||
|
*/
|
||||||
|
showConfigErrorPopup(errors) {
|
||||||
|
const message = errors.join('\n');
|
||||||
|
uni.showModal({
|
||||||
|
title: '配置错误',
|
||||||
|
content: `客服配置有误:\n${message}`,
|
||||||
|
showCancel: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 降级处理:使用原有客服方式
|
||||||
|
*/
|
||||||
fallbackToOriginalService() {
|
fallbackToOriginalService() {
|
||||||
uni.showModal({
|
uni.showModal({
|
||||||
title: '提示',
|
title: '提示',
|
||||||
content: '无法直接添加企业微信,是否使用其他方式联系客服?',
|
content: '无法直接添加企业微信客服,是否使用其他方式联系客服?',
|
||||||
success: (res) => {
|
success: (res) => {
|
||||||
if (res.confirm) {
|
if (res.confirm) {
|
||||||
this.openWxworkService(true);
|
this.openWxworkService(true);
|
||||||
@@ -423,19 +463,9 @@ export class CustomerService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fallbackToPhoneCall() {
|
|
||||||
uni.showModal({
|
|
||||||
title: '提示',
|
|
||||||
content: '在线客服不可用,是否拨打电话联系客服?',
|
|
||||||
success: (res) => {
|
|
||||||
if (res.confirm) this.makePhoneCall();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取按钮配置(用于 template 中 v-if / open-type 判断)
|
* 获取客服按钮配置
|
||||||
* @returns {Object}
|
* @returns {Object} 按钮配置
|
||||||
*/
|
*/
|
||||||
getButtonConfig() {
|
getButtonConfig() {
|
||||||
const config = this.getPlatformConfig();
|
const config = this.getPlatformConfig();
|
||||||
@@ -443,23 +473,38 @@ export class CustomerService {
|
|||||||
|
|
||||||
let openType = '';
|
let openType = '';
|
||||||
// #ifdef MP-WEIXIN
|
// #ifdef MP-WEIXIN
|
||||||
if (config.type === 'weapp' && config.useOfficial !== false) {
|
if (config.type === 'weapp') {
|
||||||
openType = 'contact';
|
openType = config.useOfficial !== false ? 'contact' : '';
|
||||||
}
|
}
|
||||||
// #endif
|
// #endif
|
||||||
|
|
||||||
// #ifdef MP-ALIPAY
|
// #ifdef MP-ALIPAY
|
||||||
if (config.type === 'aliapp') openType = 'contact';
|
if (config.type === 'aliapp') openType = 'contact';
|
||||||
// #endif
|
// #endif
|
||||||
|
|
||||||
return { ...config, openType };
|
return { ...config, openType };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断是否应该使用自定义客服处理
|
||||||
|
* @param {Object} config 客服配置
|
||||||
|
* @returns {boolean} 是否使用自定义客服
|
||||||
|
*/
|
||||||
|
shouldUseCustomService(config) {
|
||||||
|
// #ifdef MP-WEIXIN
|
||||||
|
if (config?.type === 'weapp') {
|
||||||
|
return config.useOfficial === false;
|
||||||
|
}
|
||||||
|
// #endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建客服服务实例
|
* 创建客服服务实例
|
||||||
* @param {Object} vueInstance Vue 实例(通常是 this)
|
* @param {Object} vueInstance Vue实例
|
||||||
* @param {Object} externalConfig 可选:外部传入的最新配置(如从 DIY 数据中提取)
|
* @param {Object} externalConfig 外部最新配置
|
||||||
* @returns {CustomerService}
|
* @returns {CustomerService} 客服服务实例
|
||||||
*/
|
*/
|
||||||
export function createCustomerService(vueInstance, externalConfig = null) {
|
export function createCustomerService(vueInstance, externalConfig = null) {
|
||||||
return new CustomerService(vueInstance, externalConfig);
|
return new CustomerService(vueInstance, externalConfig);
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
import WxMap from 'common/js/map-wx-jssdk.js';
|
import WxMap from 'common/js/map-wx-jssdk.js';
|
||||||
import Config from '@/common/js/config.js';
|
import Config from '@/common/js/config.js';
|
||||||
import util from '@/common/js/util.js';
|
|
||||||
|
|
||||||
let systemInfo = util.getDeviceInfo();
|
|
||||||
|
|
||||||
|
let systemInfo = uni.getSystemInfoSync();
|
||||||
export default {
|
export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@@ -609,10 +607,10 @@ export default {
|
|||||||
},
|
},
|
||||||
// 分享给好友
|
// 分享给好友
|
||||||
onShareAppMessage() {
|
onShareAppMessage() {
|
||||||
return this.mpShareData?.appMessage;
|
return this.mpShareData.appMessage;
|
||||||
},
|
},
|
||||||
// 分享到朋友圈
|
// 分享到朋友圈
|
||||||
onShareTimeline() {
|
onShareTimeline() {
|
||||||
return this.mpShareData?.timeLine;
|
return this.mpShareData.timeLine;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7,7 +7,7 @@ export default {
|
|||||||
computed: {
|
computed: {
|
||||||
// 是否是英文环境
|
// 是否是英文环境
|
||||||
isEnEnv() {
|
isEnEnv() {
|
||||||
return this.$langConfig.getCurrentLocale() === 'en-us';
|
return uni.getStorageSync('lang') === 'en-us';
|
||||||
},
|
},
|
||||||
themeStyle() {
|
themeStyle() {
|
||||||
return this.$store.state.themeStyle;
|
return this.$store.state.themeStyle;
|
||||||
@@ -65,18 +65,10 @@ export default {
|
|||||||
componentRefresh() {
|
componentRefresh() {
|
||||||
return this.$store.state.componentRefresh;
|
return this.$store.state.componentRefresh;
|
||||||
},
|
},
|
||||||
// AI客服配置
|
|
||||||
globalAIKefuConfig() {
|
|
||||||
return this.$store.state.globalAIKefuConfig;
|
|
||||||
},
|
|
||||||
// 客服配置
|
// 客服配置
|
||||||
servicerConfig() {
|
servicerConfig() {
|
||||||
return this.$store.state.servicerConfig;
|
return this.$store.state.servicerConfig;
|
||||||
},
|
},
|
||||||
// 企业微信配置
|
|
||||||
wxworkConfig() {
|
|
||||||
return this.$store.state.wxworkConfig;
|
|
||||||
},
|
|
||||||
diySeckillInterval() {
|
diySeckillInterval() {
|
||||||
return this.$store.state.diySeckillInterval;
|
return this.$store.state.diySeckillInterval;
|
||||||
},
|
},
|
||||||
@@ -153,7 +145,7 @@ export default {
|
|||||||
if (isJump && route != 'pages/index/index') {
|
if (isJump && route != 'pages/index/index') {
|
||||||
uni.setStorageSync('manual_change_store', true); // 手动切换门店
|
uni.setStorageSync('manual_change_store', true); // 手动切换门店
|
||||||
this.$store.dispatch('getCartNumber'); //重新获取购物车数据
|
this.$store.dispatch('getCartNumber'); //重新获取购物车数据
|
||||||
this.$util.redirectTo(this.$util.INDEX_PAGE_URL);
|
this.$util.redirectTo('/pages/index/index');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -240,7 +240,7 @@ export default {
|
|||||||
},
|
},
|
||||||
goHome() {
|
goHome() {
|
||||||
if (this.preview) return; // 开启预览,禁止任何操作和跳转
|
if (this.preview) return; // 开启预览,禁止任何操作和跳转
|
||||||
this.$util.redirectTo(this.$util.INDEX_PAGE_URL);
|
this.$util.redirectTo('/pages/index/index');
|
||||||
},
|
},
|
||||||
goCart() {
|
goCart() {
|
||||||
if (this.preview) return; // 开启预览,禁止任何操作和跳转
|
if (this.preview) return; // 开启预览,禁止任何操作和跳转
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { langConfig } from './config-external.js';
|
import { langConfig } from './config-external.js';
|
||||||
|
|
||||||
|
var locale = uni.getStorageSync('lang') || "zh-cn"; //设置语言
|
||||||
// 缓存已加载的语言包
|
// 缓存已加载的语言包
|
||||||
const loadedLangPacks = {};
|
var loadedLangPacks = {};
|
||||||
|
|
||||||
// 处理页面目录映射
|
// 处理页面目录映射
|
||||||
function processRoutePath(route) {
|
function processRoutePath(route) {
|
||||||
@@ -56,35 +56,23 @@ function loadLangPackSync(lang, path) {
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
langList: langConfig.langList,
|
langList: langConfig.langList,
|
||||||
|
|
||||||
/**
|
|
||||||
* 获得当前本地语言
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
getCurrentLocale() {
|
|
||||||
return uni.getStorageSync('lang') || "zh-cn";
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* * 解析多语言
|
* * 解析多语言
|
||||||
* @param {Object} field
|
* @param {Object} field
|
||||||
*/
|
*/
|
||||||
lang(field) {
|
lang(field) {
|
||||||
let _page = getCurrentPages()[getCurrentPages().length - 1];
|
let _this = getCurrentPages()[getCurrentPages().length - 1];
|
||||||
if (!_page) return;
|
if (!_this) return;
|
||||||
|
|
||||||
const locale = this.getCurrentLocale(); // 获得当前本地语言
|
|
||||||
|
|
||||||
let value = ''; // 存放解析后的语言值
|
|
||||||
let langPath = ''; // 存放当前页面语言包路径
|
|
||||||
|
|
||||||
|
var value = '';
|
||||||
try {
|
try {
|
||||||
//公共语言包(同步加载)
|
//公共语言包(同步加载)
|
||||||
var lang = loadLangPackSync(locale, 'common');
|
var lang = loadLangPackSync(locale, 'common');
|
||||||
|
|
||||||
//当前页面语言包(同步加载)
|
//当前页面语言包(同步加载)
|
||||||
let route = _page.route;
|
let route = _this.route;
|
||||||
langPath = processRoutePath(route);
|
let langPath = processRoutePath(route);
|
||||||
|
// console.log(`当前页面语言包路径: ${langPath}`);
|
||||||
|
|
||||||
// 加载当前页面语言包
|
// 加载当前页面语言包
|
||||||
let currentPageLang = loadLangPackSync(locale, langPath);
|
let currentPageLang = loadLangPackSync(locale, langPath);
|
||||||
@@ -112,7 +100,7 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('解析语言包失败:', e, { langPath, field, locale });
|
console.error('解析语言包失败:', e);
|
||||||
value = field;
|
value = field;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,10 +113,7 @@ export default {
|
|||||||
if (value == undefined || (value == 'title' && field == 'title')) value = ''; // field
|
if (value == undefined || (value == 'title' && field == 'title')) value = ''; // field
|
||||||
|
|
||||||
// 多语言调试,注释后可以关闭控制台输出
|
// 多语言调试,注释后可以关闭控制台输出
|
||||||
if (field == value) {
|
// console.log(`字段: ${field}, 值: ${value}`)
|
||||||
console.warn(`警告: 字段 ${field} 在语言包 ${langPath} 中未找到对应值,使用默认值 ${field} 当前语言: ${locale}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
@@ -137,18 +122,14 @@ export default {
|
|||||||
* @param {String} url 切换后跳转的页面url
|
* @param {String} url 切换后跳转的页面url
|
||||||
*/
|
*/
|
||||||
change(value, url = '/pages_tool/member/index') {
|
change(value, url = '/pages_tool/member/index') {
|
||||||
let _page = getCurrentPages()[getCurrentPages().length - 1];
|
let _this = getCurrentPages()[getCurrentPages().length - 1];
|
||||||
if (!_page) return;
|
if (!_this) return;
|
||||||
|
|
||||||
uni.setStorageSync("lang", value);
|
uni.setStorageSync("lang", value);
|
||||||
const locale = this.getCurrentLocale();
|
locale = uni.getStorageSync('lang') || "zh-cn"; //设置语言
|
||||||
|
|
||||||
// 清空已加载的语言包缓存
|
// 清空已加载的语言包缓存
|
||||||
for (let key in loadedLangPacks) {
|
loadedLangPacks = {};
|
||||||
if (!key.startsWith(locale)) {
|
|
||||||
delete loadedLangPacks[key];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.refresh();
|
this.refresh();
|
||||||
|
|
||||||
@@ -158,10 +139,9 @@ export default {
|
|||||||
},
|
},
|
||||||
//刷新标题、tabbar
|
//刷新标题、tabbar
|
||||||
refresh() {
|
refresh() {
|
||||||
let _page = getCurrentPages()[getCurrentPages().length - 1];
|
let _this = getCurrentPages()[getCurrentPages().length - 1];
|
||||||
if (!_page) return;
|
if (!_this) return;
|
||||||
|
locale = uni.getStorageSync('lang') || "zh-cn"; //设置语言
|
||||||
const locale = this.getCurrentLocale();
|
|
||||||
|
|
||||||
this.title(this.lang("title"));
|
this.title(this.lang("title"));
|
||||||
|
|
||||||
@@ -212,4 +192,4 @@ export default {
|
|||||||
}
|
}
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import util from '@/common/js/util.js'
|
|
||||||
import TransformCoordinate from './transformCoordinate.js'
|
import TransformCoordinate from './transformCoordinate.js'
|
||||||
|
|
||||||
function openMapByDefault(latitude, longitude, name) {
|
function openMapByDefault(latitude, longitude, name) {
|
||||||
@@ -86,8 +85,7 @@ export default {
|
|||||||
openMap(latitude, longitude, name, coord_type = 'gcj02') {
|
openMap(latitude, longitude, name, coord_type = 'gcj02') {
|
||||||
let arr = getCoordByType(longitude, latitude, coord_type)
|
let arr = getCoordByType(longitude, latitude, coord_type)
|
||||||
// #ifdef APP-PLUS
|
// #ifdef APP-PLUS
|
||||||
let platform = util.getDeviceInfo().platform;
|
switch (uni.getSystemInfoSync().platform) {
|
||||||
switch (platform) {
|
|
||||||
case 'android':
|
case 'android':
|
||||||
console.log('运行Android上')
|
console.log('运行Android上')
|
||||||
openMapByAndroid(arr[1], arr[0], name)
|
openMapByAndroid(arr[1], arr[0], name)
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import { EventSafety } from '@/common/js/event-safety.js'
|
import { EventSafety } from './event-safety'
|
||||||
import util from '@/common/js/util.js'
|
|
||||||
|
|
||||||
export class NavigationHelper {
|
export class NavigationHelper {
|
||||||
constructor() {
|
constructor() {
|
||||||
@@ -60,7 +59,7 @@ export class NavigationHelper {
|
|||||||
// 微信小程序精确计算
|
// 微信小程序精确计算
|
||||||
try {
|
try {
|
||||||
const menuButtonInfo = wx.getMenuButtonBoundingClientRect()
|
const menuButtonInfo = wx.getMenuButtonBoundingClientRect()
|
||||||
let systemInfo = util.getDeviceInfo();
|
const systemInfo = uni.getSystemInfoSync()
|
||||||
|
|
||||||
const height = menuButtonInfo.bottom +
|
const height = menuButtonInfo.bottom +
|
||||||
(menuButtonInfo.top - systemInfo.statusBarHeight)
|
(menuButtonInfo.top - systemInfo.statusBarHeight)
|
||||||
@@ -120,7 +119,7 @@ export class NavigationHelper {
|
|||||||
// 获取状态栏高度
|
// 获取状态栏高度
|
||||||
getStatusBarHeight() {
|
getStatusBarHeight() {
|
||||||
// #ifdef MP-WEIXIN
|
// #ifdef MP-WEIXIN
|
||||||
let systemInfo = util.getDeviceInfo();
|
const systemInfo = uni.getSystemInfoSync()
|
||||||
return systemInfo.statusBarHeight || 20
|
return systemInfo.statusBarHeight || 20
|
||||||
// #endif
|
// #endif
|
||||||
// #ifdef H5
|
// #ifdef H5
|
||||||
@@ -139,7 +138,7 @@ export class NavigationHelper {
|
|||||||
// 获取安全区域
|
// 获取安全区域
|
||||||
getSafeAreaInsets() {
|
getSafeAreaInsets() {
|
||||||
try {
|
try {
|
||||||
let systemInfo = util.getDeviceInfo();
|
const systemInfo = uni.getSystemInfoSync()
|
||||||
return systemInfo.safeArea || {
|
return systemInfo.safeArea || {
|
||||||
top: 0,
|
top: 0,
|
||||||
bottom: 0,
|
bottom: 0,
|
||||||
|
|||||||
@@ -1,100 +0,0 @@
|
|||||||
// 文件分享工具函数
|
|
||||||
export default {
|
|
||||||
/**
|
|
||||||
* 生成文件预览链接
|
|
||||||
* @param {Object} file - 文件对象,包含 name 和 url 属性
|
|
||||||
* @returns {string} - 生成的文件预览链接
|
|
||||||
*/
|
|
||||||
generateFilePreviewUrl(file) {
|
|
||||||
// 推断文件类型
|
|
||||||
let fileType = '';
|
|
||||||
if (file.name) {
|
|
||||||
const ext = file.name.split('.').pop().toLowerCase();
|
|
||||||
if (['pdf'].includes(ext)) {
|
|
||||||
fileType = 'pdf';
|
|
||||||
} else if (['doc', 'docx'].includes(ext)) {
|
|
||||||
fileType = 'word';
|
|
||||||
} else if (['mp4', 'avi', 'mov', 'wmv', 'flv', 'mkv'].includes(ext)) {
|
|
||||||
fileType = 'video';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 构建文件预览链接
|
|
||||||
const previewUrl = `/pages_tool/file-preview/file-preview?fileName=${encodeURIComponent(file.name)}&fileUrl=${encodeURIComponent(file.url || '')}&fileType=${encodeURIComponent(fileType)}`;
|
|
||||||
return previewUrl;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 分享文件
|
|
||||||
* @param {Object} file - 文件对象,包含 name 和 url 属性
|
|
||||||
* @param {string} title - 分享标题,默认使用文件名
|
|
||||||
* @param {string} desc - 分享描述,默认使用固定文案
|
|
||||||
*/
|
|
||||||
shareFile(file, title = file.name, desc = '查看企业文件:' + file.name) {
|
|
||||||
// 生成文件预览链接
|
|
||||||
const filePreviewUrl = this.generateFilePreviewUrl(file);
|
|
||||||
|
|
||||||
// #ifdef H5
|
|
||||||
// H5 平台分享
|
|
||||||
if (navigator.share) {
|
|
||||||
// 使用 Web Share API
|
|
||||||
navigator.share({
|
|
||||||
title: title,
|
|
||||||
text: desc,
|
|
||||||
url: filePreviewUrl
|
|
||||||
}).catch(err => {
|
|
||||||
console.error('分享失败:', err);
|
|
||||||
uni.showToast({ title: '分享失败', icon: 'none' });
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// 不支持 Web Share API 的浏览器
|
|
||||||
uni.setClipboardData({
|
|
||||||
data: filePreviewUrl,
|
|
||||||
success: () => {
|
|
||||||
uni.showToast({ title: '链接已复制,请粘贴分享', icon: 'success' });
|
|
||||||
},
|
|
||||||
fail: () => {
|
|
||||||
uni.showToast({ title: '复制失败', icon: 'none' });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
// #ifdef MP-WEIXIN
|
|
||||||
// 微信小程序分享
|
|
||||||
uni.showActionSheet({
|
|
||||||
itemList: ['发送给朋友', '分享到朋友圈'],
|
|
||||||
success: (res) => {
|
|
||||||
if (res.tapIndex === 0) {
|
|
||||||
// 发送给朋友
|
|
||||||
uni.shareAppMessage({
|
|
||||||
title: title,
|
|
||||||
path: filePreviewUrl,
|
|
||||||
success: () => {
|
|
||||||
uni.showToast({ title: '分享成功', icon: 'success' });
|
|
||||||
},
|
|
||||||
fail: () => {
|
|
||||||
uni.showToast({ title: '分享失败', icon: 'none' });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else if (res.tapIndex === 1) {
|
|
||||||
// 分享到朋友圈
|
|
||||||
uni.shareTimeline({
|
|
||||||
title: desc,
|
|
||||||
path: filePreviewUrl,
|
|
||||||
success: () => {
|
|
||||||
uni.showToast({ title: '分享成功', icon: 'success' });
|
|
||||||
},
|
|
||||||
fail: () => {
|
|
||||||
uni.showToast({ title: '分享失败', icon: 'none' });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
fail: () => {
|
|
||||||
// 用户取消分享
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// #endif
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -1,460 +1,419 @@
|
|||||||
/**
|
export default {
|
||||||
* 颜色配置
|
'default': {
|
||||||
* 包含默认颜色和其他颜色
|
//红色
|
||||||
* 特别注意:
|
name: 'default',
|
||||||
* 1. 分组不会被计算成Key,分组下的属性会被计算成Key
|
main_color: '#F4391c',
|
||||||
* 2. 分组下的属性如果有相同的Key,会被覆盖
|
aux_color: '#F7B500',
|
||||||
* 3. 例如:hoverNav,hoverNav_bg_color和hoverNav_text_color, 不会生成hoverNav_hoverNav_bg_color和hoverNav_hoverNav_text_color
|
bg_color: '#FF4646',//主题背景
|
||||||
* 问题原因:历史遗留
|
bg_color_shallow: '#FF4646',//主题背景渐变浅色
|
||||||
*/
|
promotion_color: '#FF4646',//活动背景
|
||||||
export default {
|
promotion_aux_color: '#F7B500',//活动背景辅色
|
||||||
'default': {
|
main_color_shallow: '#FFF4F4',//淡背景
|
||||||
//红色
|
price_color: 'rgb(252,82,39)',//价格颜色
|
||||||
name: 'default',
|
btn_text_color: '#FFFFFF',//按钮文字颜色
|
||||||
main_color: '#F4391c',
|
goods_detail: {
|
||||||
aux_color: '#F7B500',
|
goods_price: 'rgb(252,82,39,1)',//价格
|
||||||
bg_color: '#FF4646',//主题背景
|
promotion_tag: '#FF4646',
|
||||||
bg_color_shallow: '#FF4646',//主题背景渐变浅色
|
goods_card_bg: '#201A18',//会员卡背景
|
||||||
promotion_color: '#FF4646',//活动背景
|
goods_card_bg_shallow: '#7C7878',//会员卡背景浅色
|
||||||
promotion_aux_color: '#F7B500',//活动背景辅色
|
goods_card_color: '#FFD792',
|
||||||
main_color_shallow: '#FFF4F4',//淡背景
|
goods_coupon: '#FC5227',
|
||||||
price_color: 'rgb(252,82,39)',//价格颜色
|
goods_cart_num_corner: '#FC5227',//购物车数量角标
|
||||||
btn_text_color: '#FFFFFF',//按钮文字颜色
|
goods_btn_color: '#FF4646',//按钮颜色
|
||||||
...{
|
goods_btn_color_shallow: '#F7B500',//副按钮颜色
|
||||||
goods_price: 'rgb(252,82,39,1)',//价格
|
},
|
||||||
promotion_tag: '#FF4646',
|
pintuan: {
|
||||||
goods_card_bg: '#201A18',//会员卡背景
|
pintuan_label_bg: '#F7B500',
|
||||||
goods_card_bg_shallow: '#7C7878',//会员卡背景浅色
|
pintuan_label_color: '#FFFFFF',
|
||||||
goods_card_color: '#FFD792',
|
pintuan_color: '#FA6400',
|
||||||
goods_coupon: '#FC5227',
|
pintuan_promotion_color: '#FA3A1D',//活动背景
|
||||||
goods_cart_num_corner: '#FC5227',//购物车数量角标
|
pintuan_promotion_aux_color: '#FD9A01',//活动背景辅色
|
||||||
goods_btn_color: '#FF4646',//按钮颜色
|
},
|
||||||
goods_btn_color_shallow: '#F7B500',//副按钮颜色
|
super_member: {
|
||||||
},
|
super_member_start_bg: '#7c7878',
|
||||||
...{
|
super_member_end_bg: '#201a18',
|
||||||
pintuan_label_bg: '#F7B500',
|
super_member_start_text_color: '#FFDBA6',
|
||||||
pintuan_label_color: '#FFFFFF',
|
super_member_end_text_color: '#FFEBCA',
|
||||||
pintuan_color: '#FA6400',
|
},
|
||||||
pintuan_promotion_color: '#FA3A1D',//活动背景
|
bargain: {
|
||||||
pintuan_promotion_aux_color: '#FD9A01',//活动背景辅色
|
bargain_promotion_color: '#F0353E',//活动背景
|
||||||
},
|
bargain_promotion_aux_color: '#FD9A01',//活动辅色
|
||||||
...{
|
},
|
||||||
super_member_start_bg: '#7c7878',
|
seckill: {
|
||||||
super_member_end_bg: '#201a18',
|
seckill_promotion_color: '#F83530',//活动背景
|
||||||
super_member_start_text_color: '#FFDBA6',
|
seckill_promotion_aux_color: '#FD9A01',//活动辅色
|
||||||
super_member_end_text_color: '#FFEBCA',
|
},
|
||||||
},
|
giftcard: {
|
||||||
...{
|
giftcard_promotion_color: '#FF3369',//活动背景
|
||||||
bargain_promotion_color: '#F0353E',//活动背景
|
giftcard_promotion_aux_color: '#F7B500',//活动辅色
|
||||||
bargain_promotion_aux_color: '#FD9A01',//活动辅色
|
},
|
||||||
},
|
groupby: {
|
||||||
...{
|
groupby_promotion_color: '#E64136',//活动背景
|
||||||
seckill_promotion_color: '#F83530',//活动背景
|
groupby_promotion_aux_color: '#F7B500',//活动辅色
|
||||||
seckill_promotion_aux_color: '#FD9A01',//活动辅色
|
},
|
||||||
},
|
},
|
||||||
...{
|
'green': {
|
||||||
giftcard_promotion_color: '#FF3369',//活动背景
|
name: 'green',
|
||||||
giftcard_promotion_aux_color: '#F7B500',//活动辅色
|
main_color: '#19C650',
|
||||||
},
|
aux_color: '#FA6400',
|
||||||
...{
|
bg_color: '#19C650',
|
||||||
groupby_promotion_color: '#E64136',//活动背景
|
bg_color_shallow: '#19C650',
|
||||||
groupby_promotion_aux_color: '#F7B500',//活动辅色
|
promotion_color: '#19C650',
|
||||||
},
|
promotion_aux_color: '#FA6400',
|
||||||
...{
|
main_color_shallow: '#F0FFF5',//淡背景
|
||||||
hover_nav_bg_color: '#FFFC', //背景色: 红色 '#c6251b', 白色: '#FFFC'
|
price_color: 'rgba(252,82,39,1)',//价格颜色
|
||||||
hover_nav_text_color: '#000' // 文字颜色: 白色 '#FFFFFF', 黑色: '#000'
|
btn_text_color: '#FFFFFF',//按钮文字颜色
|
||||||
},
|
goods_detail: {
|
||||||
},
|
goods_price: 'rgba(252,82,39,1)',//价格
|
||||||
'green': {
|
promotion_tag: '#19C650',
|
||||||
name: 'green',
|
goods_card_bg: '#201A18',//会员卡背景
|
||||||
main_color: '#19C650',
|
goods_card_bg_shallow: '#7C7878',//会员卡背景浅色
|
||||||
aux_color: '#FA6400',
|
goods_card_color: '#FFD792',
|
||||||
bg_color: '#19C650',
|
goods_coupon: '#FC5227',
|
||||||
bg_color_shallow: '#19C650',
|
goods_cart_num_corner: '#FC5227',//购物车数量角标
|
||||||
promotion_color: '#19C650',
|
goods_btn_color: '#19C650',//按钮颜色
|
||||||
promotion_aux_color: '#FA6400',
|
goods_btn_color_shallow: '#FA6400',//副按钮颜色
|
||||||
main_color_shallow: '#F0FFF5',//淡背景
|
},
|
||||||
price_color: 'rgba(252,82,39,1)',//价格颜色
|
pintuan: {
|
||||||
btn_text_color: '#FFFFFF',//按钮文字颜色
|
pintuan_label_bg: '#F7B500',
|
||||||
...{
|
pintuan_label_color: '#FFFFFF',
|
||||||
goods_price: 'rgba(252,82,39,1)',//价格
|
pintuan_color: '#FA6400',
|
||||||
promotion_tag: '#19C650',
|
pintuan_promotion_color: '#FA3A1D',//活动背景
|
||||||
goods_card_bg: '#201A18',//会员卡背景
|
pintuan_promotion_aux_color: '#FD9A01',//活动背景辅色
|
||||||
goods_card_bg_shallow: '#7C7878',//会员卡背景浅色
|
},
|
||||||
goods_card_color: '#FFD792',
|
super_member: {
|
||||||
goods_coupon: '#FC5227',
|
super_member_start_bg: '#7c7878',
|
||||||
goods_cart_num_corner: '#FC5227',//购物车数量角标
|
super_member_end_bg: '#201a18',
|
||||||
goods_btn_color: '#19C650',//按钮颜色
|
super_member_start_text_color: '#FFDBA6',
|
||||||
goods_btn_color_shallow: '#FA6400',//副按钮颜色
|
super_member_end_text_color: '#FFEBCA',
|
||||||
},
|
},
|
||||||
...{
|
bargain: {
|
||||||
pintuan_label_bg: '#F7B500',
|
bargain_promotion_color: '#F0353E',//活动背景
|
||||||
pintuan_label_color: '#FFFFFF',
|
bargain_promotion_aux_color: '#FD9A01',//活动辅色
|
||||||
pintuan_color: '#FA6400',
|
},
|
||||||
pintuan_promotion_color: '#FA3A1D',//活动背景
|
seckill: {
|
||||||
pintuan_promotion_aux_color: '#FD9A01',//活动背景辅色
|
seckill_promotion_color: '#F83530',//活动背景
|
||||||
},
|
seckill_promotion_aux_color: '#FD9A01',//活动辅色
|
||||||
...{
|
},
|
||||||
super_member_start_bg: '#7c7878',
|
giftcard: {
|
||||||
super_member_end_bg: '#201a18',
|
giftcard_promotion_color: '#FF3369',//活动背景
|
||||||
super_member_start_text_color: '#FFDBA6',
|
giftcard_promotion_aux_color: '#F7B500',//活动辅色
|
||||||
super_member_end_text_color: '#FFEBCA',
|
},
|
||||||
},
|
groupby: {
|
||||||
...{
|
groupby_promotion_color: '#E64136',//活动背景
|
||||||
bargain_promotion_color: '#F0353E',//活动背景
|
groupby_promotion_aux_color: '#F7B500',//活动辅色
|
||||||
bargain_promotion_aux_color: '#FD9A01',//活动辅色
|
},
|
||||||
},
|
},
|
||||||
...{
|
'blue': {
|
||||||
seckill_promotion_color: '#F83530',//活动背景
|
name: 'blue',
|
||||||
seckill_promotion_aux_color: '#FD9A01',//活动辅色
|
main_color: '#36ABFF',
|
||||||
},
|
aux_color: '#FA6400',
|
||||||
...{
|
bg_color: '#36ABFF',
|
||||||
giftcard_promotion_color: '#FF3369',//活动背景
|
bg_color_shallow: '#36ABFF',
|
||||||
giftcard_promotion_aux_color: '#F7B500',//活动辅色
|
promotion_color: '#36ABFF ',
|
||||||
},
|
promotion_aux_color: '#FA6400',
|
||||||
...{
|
main_color_shallow: '#E2F3FF',
|
||||||
groupby_promotion_color: '#E64136',//活动背景
|
price_color: 'rgba(252,82,39,1)',//价格颜色
|
||||||
groupby_promotion_aux_color: '#F7B500',//活动辅色
|
btn_text_color: '#FFFFFF',//按钮文字颜色
|
||||||
},
|
goods_detail: {
|
||||||
...{
|
goods_price: 'rgba(252,82,39,1)',//价格
|
||||||
hover_nav_bg_color: '#19C650',//背景色
|
promotion_tag: '#36ABFF',
|
||||||
hover_nav_text_color: '#FFFFFF'
|
goods_card_bg: '#201A18',//会员卡背景
|
||||||
},
|
goods_card_bg_shallow: '#7C7878',//会员卡背景浅色
|
||||||
},
|
goods_card_color: '#FFD792',
|
||||||
'blue': {
|
goods_coupon: '#FC5227',
|
||||||
name: 'blue',
|
goods_cart_num_corner: '#FC5227',//购物车数量角标
|
||||||
main_color: '#36ABFF',
|
goods_btn_color: '#36ABFF',//按钮颜色
|
||||||
aux_color: '#FA6400',
|
goods_btn_color_shallow: '#FA6400',//副按钮颜色
|
||||||
bg_color: '#36ABFF',
|
},
|
||||||
bg_color_shallow: '#36ABFF',
|
pintuan: {
|
||||||
promotion_color: '#36ABFF ',
|
pintuan_label_bg: '#F7B500',
|
||||||
promotion_aux_color: '#FA6400',
|
pintuan_label_color: '#FFFFFF',
|
||||||
main_color_shallow: '#E2F3FF',
|
pintuan_color: '#FA6400',
|
||||||
price_color: 'rgba(252,82,39,1)',//价格颜色
|
pintuan_promotion_color: '#FA3A1D',//活动背景
|
||||||
btn_text_color: '#FFFFFF',//按钮文字颜色
|
pintuan_promotion_aux_color: '#FD9A01',//活动背景辅色
|
||||||
...{
|
},
|
||||||
goods_price: 'rgba(252,82,39,1)',//价格
|
super_member: {
|
||||||
promotion_tag: '#36ABFF',
|
super_member_start_bg: '#7c7878',
|
||||||
goods_card_bg: '#201A18',//会员卡背景
|
super_member_end_bg: '#201a18',
|
||||||
goods_card_bg_shallow: '#7C7878',//会员卡背景浅色
|
super_member_start_text_color: '#FFDBA6',
|
||||||
goods_card_color: '#FFD792',
|
super_member_end_text_color: '#FFEBCA',
|
||||||
goods_coupon: '#FC5227',
|
},
|
||||||
goods_cart_num_corner: '#FC5227',//购物车数量角标
|
bargain: {
|
||||||
goods_btn_color: '#36ABFF',//按钮颜色
|
bargain_promotion_color: '#F0353E',//活动背景
|
||||||
goods_btn_color_shallow: '#FA6400',//副按钮颜色
|
bargain_promotion_aux_color: '#FD9A01',//活动辅色
|
||||||
},
|
},
|
||||||
...{
|
seckill: {
|
||||||
pintuan_label_bg: '#F7B500',
|
seckill_promotion_color: '#F83530',//活动背景
|
||||||
pintuan_label_color: '#FFFFFF',
|
seckill_promotion_aux_color: '#FD9A01',//活动辅色
|
||||||
pintuan_color: '#FA6400',
|
},
|
||||||
pintuan_promotion_color: '#FA3A1D',//活动背景
|
giftcard: {
|
||||||
pintuan_promotion_aux_color: '#FD9A01',//活动背景辅色
|
giftcard_promotion_color: '#FF3369',//活动背景
|
||||||
},
|
giftcard_promotion_aux_color: '#F7B500',//活动辅色
|
||||||
...{
|
},
|
||||||
super_member_start_bg: '#7c7878',
|
groupby: {
|
||||||
super_member_end_bg: '#201a18',
|
groupby_promotion_color: '#E64136',//活动背景
|
||||||
super_member_start_text_color: '#FFDBA6',
|
groupby_promotion_aux_color: '#F7B500',//活动辅色
|
||||||
super_member_end_text_color: '#FFEBCA',
|
},
|
||||||
},
|
},
|
||||||
...{
|
'pink': {
|
||||||
bargain_promotion_color: '#F0353E',//活动背景
|
name: 'pink',
|
||||||
bargain_promotion_aux_color: '#FD9A01',//活动辅色
|
main_color: '#FF407E',
|
||||||
},
|
aux_color: '#F7B500',
|
||||||
...{
|
bg_color: '#FF407E',//主题背景
|
||||||
seckill_promotion_color: '#F83530',//活动背景
|
bg_color_shallow: '#FF407E',//主题背景渐变浅色
|
||||||
seckill_promotion_aux_color: '#FD9A01',//活动辅色
|
promotion_color: '#FF407E',//活动背景
|
||||||
},
|
promotion_aux_color: '#F7B500',//活动背景辅色
|
||||||
...{
|
main_color_shallow: '#FFF5F8',//淡背景
|
||||||
giftcard_promotion_color: '#FF3369',//活动背景
|
price_color: 'rgba(252,82,39,1)',//价格颜色
|
||||||
giftcard_promotion_aux_color: '#F7B500',//活动辅色
|
btn_text_color: '#FFFFFF',//按钮文字颜色
|
||||||
},
|
goods_detail: {
|
||||||
...{
|
goods_price: 'rgba(252,82,39,1)',//价格
|
||||||
groupby_promotion_color: '#E64136',//活动背景
|
promotion_tag: '#FF407E',
|
||||||
groupby_promotion_aux_color: '#F7B500',//活动辅色
|
goods_card_bg: '#201A18',//会员卡背景
|
||||||
},
|
goods_card_bg_shallow: '#7C7878',//会员卡背景浅色
|
||||||
...{
|
goods_card_color: '#FFD792',
|
||||||
hover_nav_bg_color: '#36ABFF',//背景色
|
goods_coupon: '#FC5227',
|
||||||
hover_nav_text_color: '#FFFFFF'
|
goods_cart_num_corner: '#FC5227',//购物车数量角标
|
||||||
},
|
goods_btn_color: '#FF407E',//按钮颜色
|
||||||
},
|
goods_btn_color_shallow: '#F7B500',//副按钮颜色
|
||||||
'pink': {
|
},
|
||||||
name: 'pink',
|
pintuan: {
|
||||||
main_color: '#FF407E',
|
pintuan_label_bg: '#F7B500',
|
||||||
aux_color: '#F7B500',
|
pintuan_label_color: '#FFFFFF',
|
||||||
bg_color: '#FF407E',//主题背景
|
pintuan_color: '#FA6400',
|
||||||
bg_color_shallow: '#FF407E',//主题背景渐变浅色
|
pintuan_promotion_color: '#FA3A1D',//活动背景
|
||||||
promotion_color: '#FF407E',//活动背景
|
pintuan_promotion_aux_color: '#FD9A01',//活动背景辅色
|
||||||
promotion_aux_color: '#F7B500',//活动背景辅色
|
},
|
||||||
main_color_shallow: '#FFF5F8',//淡背景
|
super_member: {
|
||||||
price_color: 'rgba(252,82,39,1)',//价格颜色
|
super_member_start_bg: '#7c7878',
|
||||||
btn_text_color: '#FFFFFF',//按钮文字颜色
|
super_member_end_bg: '#201a18',
|
||||||
...{
|
super_member_start_text_color: '#FFDBA6',
|
||||||
goods_price: 'rgba(252,82,39,1)',//价格
|
super_member_end_text_color: '#FFEBCA',
|
||||||
promotion_tag: '#FF407E',
|
},
|
||||||
goods_card_bg: '#201A18',//会员卡背景
|
bargain: {
|
||||||
goods_card_bg_shallow: '#7C7878',//会员卡背景浅色
|
bargain_promotion_color: '#F0353E',//活动背景
|
||||||
goods_card_color: '#FFD792',
|
bargain_promotion_aux_color: '#FD9A01',//活动辅色
|
||||||
goods_coupon: '#FC5227',
|
},
|
||||||
goods_cart_num_corner: '#FC5227',//购物车数量角标
|
seckill: {
|
||||||
goods_btn_color: '#FF407E',//按钮颜色
|
seckill_promotion_color: '#F83530',//活动背景
|
||||||
goods_btn_color_shallow: '#F7B500',//副按钮颜色
|
seckill_promotion_aux_color: '#FD9A01',//活动辅色
|
||||||
},
|
},
|
||||||
...{
|
giftcard: {
|
||||||
pintuan_label_bg: '#F7B500',
|
giftcard_promotion_color: '#FF3369',//活动背景
|
||||||
pintuan_label_color: '#FFFFFF',
|
giftcard_promotion_aux_color: '#F7B500',//活动辅色
|
||||||
pintuan_color: '#FA6400',
|
},
|
||||||
pintuan_promotion_color: '#FA3A1D',//活动背景
|
groupby: {
|
||||||
pintuan_promotion_aux_color: '#FD9A01',//活动背景辅色
|
groupby_promotion_color: '#E64136',//活动背景
|
||||||
},
|
groupby_promotion_aux_color: '#F7B500',//活动辅色
|
||||||
...{
|
},
|
||||||
super_member_start_bg: '#7c7878',
|
},
|
||||||
super_member_end_bg: '#201a18',
|
'gold': {
|
||||||
super_member_start_text_color: '#FFDBA6',
|
name: 'gold',
|
||||||
super_member_end_text_color: '#FFEBCA',
|
main_color: '#CFAF70',
|
||||||
},
|
aux_color: '#444444',
|
||||||
...{
|
bg_color: '#CFAF70',//主题背景
|
||||||
bargain_promotion_color: '#F0353E',//活动背景
|
bg_color_shallow: '#CFAF70',//主题背景渐变浅色
|
||||||
bargain_promotion_aux_color: '#FD9A01',//活动辅色
|
promotion_color: '#CFAF70',//活动背景
|
||||||
},
|
promotion_aux_color: '#444444',//活动背景辅色
|
||||||
...{
|
main_color_shallow: '#FFFAF1',//淡背景
|
||||||
seckill_promotion_color: '#F83530',//活动背景
|
price_color: 'rgba(252,82,39,1)',//价格颜色
|
||||||
seckill_promotion_aux_color: '#FD9A01',//活动辅色
|
btn_text_color: '#FFFFFF',//按钮文字颜色
|
||||||
},
|
goods_detail: {
|
||||||
...{
|
goods_price: 'rgba(252,82,39,1)',//价格
|
||||||
giftcard_promotion_color: '#FF3369',//活动背景
|
promotion_tag: '#CFAF70',
|
||||||
giftcard_promotion_aux_color: '#F7B500',//活动辅色
|
goods_card_bg: '#201A18',//会员卡背景
|
||||||
},
|
goods_card_bg_shallow: '#7C7878',//会员卡背景浅色
|
||||||
...{
|
goods_card_color: '#FFD792',
|
||||||
groupby_promotion_color: '#E64136',//活动背景
|
goods_coupon: '#FC5227',
|
||||||
groupby_promotion_aux_color: '#F7B500',//活动辅色
|
goods_cart_num_corner: '#FC5227',//购物车数量角标
|
||||||
},
|
goods_btn_color: '#CFAF70',//按钮颜色
|
||||||
...{
|
goods_btn_color_shallow: '#444444',//副按钮颜色
|
||||||
hover_nav_bg_color: '#FF407E',//背景色
|
},
|
||||||
hover_nav_text_color: '#FFFFFF'
|
pintuan: {
|
||||||
},
|
pintuan_label_bg: '#F7B500',
|
||||||
},
|
pintuan_label_color: '#FFFFFF',
|
||||||
'gold': {
|
pintuan_color: '#FA6400',
|
||||||
name: 'gold',
|
pintuan_promotion_color: '#FA3A1D',//活动背景
|
||||||
main_color: '#CFAF70',
|
pintuan_promotion_aux_color: '#FD9A01',//活动背景辅色
|
||||||
aux_color: '#444444',
|
},
|
||||||
bg_color: '#CFAF70',//主题背景
|
super_member: {
|
||||||
bg_color_shallow: '#CFAF70',//主题背景渐变浅色
|
super_member_start_bg: '#7c7878',
|
||||||
promotion_color: '#CFAF70',//活动背景
|
super_member_end_bg: '#201a18',
|
||||||
promotion_aux_color: '#444444',//活动背景辅色
|
super_member_start_text_color: '#FFDBA6',
|
||||||
main_color_shallow: '#FFFAF1',//淡背景
|
super_member_end_text_color: '#FFEBCA',
|
||||||
price_color: 'rgba(252,82,39,1)',//价格颜色
|
},
|
||||||
btn_text_color: '#FFFFFF',//按钮文字颜色
|
bargain: {
|
||||||
...{
|
bargain_promotion_color: '#F0353E',//活动背景
|
||||||
goods_price: 'rgba(252,82,39,1)',//价格
|
bargain_promotion_aux_color: '#FD9A01',//活动辅色
|
||||||
promotion_tag: '#CFAF70',
|
},
|
||||||
goods_card_bg: '#201A18',//会员卡背景
|
seckill: {
|
||||||
goods_card_bg_shallow: '#7C7878',//会员卡背景浅色
|
seckill_promotion_color: '#F83530',//活动背景
|
||||||
goods_card_color: '#FFD792',
|
seckill_promotion_aux_color: '#FD9A01',//活动辅色
|
||||||
goods_coupon: '#FC5227',
|
},
|
||||||
goods_cart_num_corner: '#FC5227',//购物车数量角标
|
giftcard: {
|
||||||
goods_btn_color: '#CFAF70',//按钮颜色
|
giftcard_promotion_color: '#FF3369',//活动背景
|
||||||
goods_btn_color_shallow: '#444444',//副按钮颜色
|
giftcard_promotion_aux_color: '#F7B500',//活动辅色
|
||||||
},
|
},
|
||||||
...{
|
groupby: {
|
||||||
pintuan_label_bg: '#F7B500',
|
groupby_promotion_color: '#E64136',//活动背景
|
||||||
pintuan_label_color: '#FFFFFF',
|
groupby_promotion_aux_color: '#F7B500',//活动辅色
|
||||||
pintuan_color: '#FA6400',
|
},
|
||||||
pintuan_promotion_color: '#FA3A1D',//活动背景
|
},
|
||||||
pintuan_promotion_aux_color: '#FD9A01',//活动背景辅色
|
'purple': {
|
||||||
},
|
name: 'purple',
|
||||||
...{
|
main_color: '#A253FF',
|
||||||
super_member_start_bg: '#7c7878',
|
aux_color: '#222222',
|
||||||
super_member_end_bg: '#201a18',
|
bg_color: '#A253FF',//主题背景
|
||||||
super_member_start_text_color: '#FFDBA6',
|
bg_color_shallow: '#A253FF',//主题背景渐变浅色
|
||||||
super_member_end_text_color: '#FFEBCA',
|
promotion_color: '#A253FF',//活动背景
|
||||||
},
|
promotion_aux_color: '#222222',//活动背景辅色
|
||||||
...{
|
main_color_shallow: '#F8F3FF',//淡背景
|
||||||
bargain_promotion_color: '#F0353E',//活动背景
|
price_color: 'rgba(252,82,39,1)',//价格颜色
|
||||||
bargain_promotion_aux_color: '#FD9A01',//活动辅色
|
btn_text_color: '#FFFFFF',//按钮文字颜色
|
||||||
},
|
goods_detail: {
|
||||||
...{
|
goods_price: 'rgba(252,82,39,1)',//价格
|
||||||
seckill_promotion_color: '#F83530',//活动背景
|
promotion_tag: '#A253FF',
|
||||||
seckill_promotion_aux_color: '#FD9A01',//活动辅色
|
goods_card_bg: '#201A18',//会员卡背景
|
||||||
},
|
goods_card_bg_shallow: '#7C7878',//会员卡背景浅色
|
||||||
...{
|
goods_card_color: '#FFD792',
|
||||||
giftcard_promotion_color: '#FF3369',//活动背景
|
goods_coupon: '#FC5227',
|
||||||
giftcard_promotion_aux_color: '#F7B500',//活动辅色
|
goods_cart_num_corner: '#FC5227',//购物车数量角标
|
||||||
},
|
goods_btn_color: '#A253FF',//按钮颜色
|
||||||
...{
|
goods_btn_color_shallow: '#222222',//副按钮颜色
|
||||||
groupby_promotion_color: '#E64136',//活动背景
|
},
|
||||||
groupby_promotion_aux_color: '#F7B500',//活动辅色
|
pintuan: {
|
||||||
},
|
pintuan_label_bg: '#F7B500',
|
||||||
...{
|
pintuan_label_color: '#FFFFFF',
|
||||||
hover_nav_bg_color: '#CFAF70',//背景色
|
pintuan_color: '#FA6400',
|
||||||
hover_nav_text_color: '#FFFFFF'
|
pintuan_promotion_color: '#FA3A1D',//活动背景
|
||||||
},
|
pintuan_promotion_aux_color: '#FD9A01',//活动背景辅色
|
||||||
},
|
},
|
||||||
'purple': {
|
super_member: {
|
||||||
name: 'purple',
|
super_member_start_bg: '#7c7878',
|
||||||
main_color: '#A253FF',
|
super_member_end_bg: '#201a18',
|
||||||
aux_color: '#222222',
|
super_member_start_text_color: '#FFDBA6',
|
||||||
bg_color: '#A253FF',//主题背景
|
super_member_end_text_color: '#FFEBCA',
|
||||||
bg_color_shallow: '#A253FF',//主题背景渐变浅色
|
},
|
||||||
promotion_color: '#A253FF',//活动背景
|
bargain: {
|
||||||
promotion_aux_color: '#222222',//活动背景辅色
|
bargain_promotion_color: '#F0353E',//活动背景
|
||||||
main_color_shallow: '#F8F3FF',//淡背景
|
bargain_promotion_aux_color: '#FD9A01',//活动辅色
|
||||||
price_color: 'rgba(252,82,39,1)',//价格颜色
|
},
|
||||||
btn_text_color: '#FFFFFF',//按钮文字颜色
|
seckill: {
|
||||||
...{
|
seckill_promotion_color: '#F83530',//活动背景
|
||||||
goods_price: 'rgba(252,82,39,1)',//价格
|
seckill_promotion_aux_color: '#FD9A01',//活动辅色
|
||||||
promotion_tag: '#A253FF',
|
},
|
||||||
goods_card_bg: '#201A18',//会员卡背景
|
giftcard: {
|
||||||
goods_card_bg_shallow: '#7C7878',//会员卡背景浅色
|
giftcard_promotion_color: '#FF3369',//活动背景
|
||||||
goods_card_color: '#FFD792',
|
giftcard_promotion_aux_color: '#F7B500',//活动辅色
|
||||||
goods_coupon: '#FC5227',
|
},
|
||||||
goods_cart_num_corner: '#FC5227',//购物车数量角标
|
groupby: {
|
||||||
goods_btn_color: '#A253FF',//按钮颜色
|
groupby_promotion_color: '#E64136',//活动背景
|
||||||
goods_btn_color_shallow: '#222222',//副按钮颜色
|
groupby_promotion_aux_color: '#F7B500',//活动辅色
|
||||||
},
|
},
|
||||||
...{
|
},
|
||||||
pintuan_label_bg: '#F7B500',
|
'yellow': {
|
||||||
pintuan_label_color: '#FFFFFF',
|
name: 'yellow',
|
||||||
pintuan_color: '#FA6400',
|
main_color: '#FFD009',
|
||||||
pintuan_promotion_color: '#FA3A1D',//活动背景
|
aux_color: '#1D262E',
|
||||||
pintuan_promotion_aux_color: '#FD9A01',//活动背景辅色
|
bg_color: '#FFD009',//主题背景
|
||||||
},
|
bg_color_shallow: '#FFD009',//主题背景渐变浅色
|
||||||
...{
|
promotion_color: '#FFD009',//活动背景
|
||||||
super_member_start_bg: '#7c7878',
|
promotion_aux_color: '#1D262E',//活动背景辅色
|
||||||
super_member_end_bg: '#201a18',
|
main_color_shallow: '#FFFBEF',//淡背景
|
||||||
super_member_start_text_color: '#FFDBA6',
|
price_color: 'rgba(252,82,39,1)',//价格颜色
|
||||||
super_member_end_text_color: '#FFEBCA',
|
btn_text_color: '#303133',//按钮文字颜色
|
||||||
},
|
goods_detail: {
|
||||||
...{
|
goods_price: 'rgba(252,82,39,1)',//价格
|
||||||
bargain_promotion_color: '#F0353E',//活动背景
|
promotion_tag: '#FFD009',
|
||||||
bargain_promotion_aux_color: '#FD9A01',//活动辅色
|
goods_card_bg: '#201A18',//会员卡背景
|
||||||
},
|
goods_card_bg_shallow: '#7C7878',//会员卡背景浅色
|
||||||
...{
|
goods_card_color: '#FFD792',
|
||||||
seckill_promotion_color: '#F83530',//活动背景
|
goods_coupon: '#FC5227',
|
||||||
seckill_promotion_aux_color: '#FD9A01',//活动辅色
|
goods_cart_num_corner: '#FC5227',//购物车数量角标
|
||||||
},
|
goods_btn_color: '#FFD009',//按钮颜色
|
||||||
...{
|
goods_btn_color_shallow: '#1D262E',//副按钮颜色
|
||||||
giftcard_promotion_color: '#FF3369',//活动背景
|
},
|
||||||
giftcard_promotion_aux_color: '#F7B500',//活动辅色
|
pintuan: {
|
||||||
},
|
pintuan_label_bg: '#F7B500',
|
||||||
...{
|
pintuan_label_color: '#FFFFFF',
|
||||||
groupby_promotion_color: '#E64136',//活动背景
|
pintuan_color: '#FA6400',
|
||||||
groupby_promotion_aux_color: '#F7B500',//活动辅色
|
pintuan_promotion_color: '#FA3A1D',//活动背景
|
||||||
},
|
pintuan_promotion_aux_color: '#FD9A01',//活动背景辅色
|
||||||
...{
|
},
|
||||||
hover_nav_bg_color: '#A253FF',//背景色
|
super_member: {
|
||||||
hover_nav_text_color: '#FFFFFF'
|
super_member_start_bg: '#7c7878',
|
||||||
},
|
super_member_end_bg: '#201a18',
|
||||||
},
|
super_member_start_text_color: '#FFDBA6',
|
||||||
'yellow': {
|
super_member_end_text_color: '#FFEBCA',
|
||||||
name: 'yellow',
|
},
|
||||||
main_color: '#FFD009',
|
bargain: {
|
||||||
aux_color: '#1D262E',
|
bargain_promotion_color: '#F0353E',//活动背景
|
||||||
bg_color: '#FFD009',//主题背景
|
bargain_promotion_aux_color: '#FD9A01',//活动辅色
|
||||||
bg_color_shallow: '#FFD009',//主题背景渐变浅色
|
},
|
||||||
promotion_color: '#FFD009',//活动背景
|
seckill: {
|
||||||
promotion_aux_color: '#1D262E',//活动背景辅色
|
seckill_promotion_color: '#F83530',//活动背景
|
||||||
main_color_shallow: '#FFFBEF',//淡背景
|
seckill_promotion_aux_color: '#FD9A01',//活动辅色
|
||||||
price_color: 'rgba(252,82,39,1)',//价格颜色
|
},
|
||||||
btn_text_color: '#303133',//按钮文字颜色
|
giftcard: {
|
||||||
...{
|
giftcard_promotion_color: '#FF3369',//活动背景
|
||||||
goods_price: 'rgba(252,82,39,1)',//价格
|
giftcard_promotion_aux_color: '#F7B500',//活动辅色
|
||||||
promotion_tag: '#FFD009',
|
},
|
||||||
goods_card_bg: '#201A18',//会员卡背景
|
groupby: {
|
||||||
goods_card_bg_shallow: '#7C7878',//会员卡背景浅色
|
groupby_promotion_color: '#E64136',//活动背景
|
||||||
goods_card_color: '#FFD792',
|
groupby_promotion_aux_color: '#F7B500',//活动辅色
|
||||||
goods_coupon: '#FC5227',
|
},
|
||||||
goods_cart_num_corner: '#FC5227',//购物车数量角标
|
},
|
||||||
goods_btn_color: '#FFD009',//按钮颜色
|
'black': {
|
||||||
goods_btn_color_shallow: '#1D262E',//副按钮颜色
|
name: 'black',
|
||||||
},
|
main_color: '#222222',
|
||||||
...{
|
aux_color: '#FFFFFF',
|
||||||
pintuan_label_bg: '#F7B500',
|
bg_color: '#222222',//主题背景
|
||||||
pintuan_label_color: '#FFFFFF',
|
bg_color_shallow: '#333333',//主题背景渐变浅色
|
||||||
pintuan_color: '#FA6400',
|
promotion_color: '#222222',//活动背景
|
||||||
pintuan_promotion_color: '#FA3A1D',//活动背景
|
promotion_aux_color: '#FA8B00',//活动背景辅色
|
||||||
pintuan_promotion_aux_color: '#FD9A01',//活动背景辅色
|
main_color_shallow: '#efefef',//淡背景
|
||||||
},
|
price_color: 'rgba(255,0,0,1)',//价格颜色
|
||||||
...{
|
btn_text_color: '#FFFFFF',//按钮文字颜色
|
||||||
super_member_start_bg: '#7c7878',
|
goods_detail: {
|
||||||
super_member_end_bg: '#201a18',
|
goods_price: 'rgba(255,0,0,1)',//价格
|
||||||
super_member_start_text_color: '#FFDBA6',
|
promotion_tag: '#222222',
|
||||||
super_member_end_text_color: '#FFEBCA',
|
goods_card_bg: '#201A18',//会员卡背景
|
||||||
},
|
goods_card_bg_shallow: '#7C7878',//会员卡背景浅色
|
||||||
...{
|
goods_card_color: '#FFD792',
|
||||||
bargain_promotion_color: '#F0353E',//活动背景
|
goods_coupon: '#222222',
|
||||||
bargain_promotion_aux_color: '#FD9A01',//活动辅色
|
goods_cart_num_corner: '#FF0000',//购物车数量角标
|
||||||
},
|
goods_btn_color: '#222222',//按钮颜色
|
||||||
...{
|
goods_btn_color_shallow: '#FA8B00',//副按钮颜色
|
||||||
seckill_promotion_color: '#F83530',//活动背景
|
},
|
||||||
seckill_promotion_aux_color: '#FD9A01',//活动辅色
|
pintuan: {
|
||||||
},
|
pintuan_label_bg: '#F7B500',
|
||||||
...{
|
pintuan_label_color: '#FFFFFF',
|
||||||
giftcard_promotion_color: '#FF3369',//活动背景
|
pintuan_color: '#FA6400',
|
||||||
giftcard_promotion_aux_color: '#F7B500',//活动辅色
|
pintuan_promotion_color: '#FA3A1D',//活动背景
|
||||||
},
|
pintuan_promotion_aux_color: '#FD9A01',//活动背景辅色
|
||||||
...{
|
},
|
||||||
groupby_promotion_color: '#E64136',//活动背景
|
super_member: {
|
||||||
groupby_promotion_aux_color: '#F7B500',//活动辅色
|
super_member_start_bg: '#fadcb5',
|
||||||
},
|
super_member_end_bg: '#f6bd74',
|
||||||
...{
|
super_member_start_text_color: '#ab6126',
|
||||||
hover_nav_bg_color: '#FFD009',//背景色
|
super_member_end_text_color: '#d19336',
|
||||||
hover_nav_text_color: '#303133'
|
},
|
||||||
},
|
bargain: {
|
||||||
},
|
bargain_promotion_color: '#F0353E',//活动背景
|
||||||
'black': {
|
bargain_promotion_aux_color: '#FD9A01',//活动辅色
|
||||||
name: 'black',
|
},
|
||||||
main_color: '#222222',
|
seckill: {
|
||||||
aux_color: '#FFFFFF',
|
seckill_promotion_color: '#F83530',//活动背景
|
||||||
bg_color: '#222222',//主题背景
|
seckill_promotion_aux_color: '#FD9A01',//活动辅色
|
||||||
bg_color_shallow: '#333333',//主题背景渐变浅色
|
},
|
||||||
promotion_color: '#222222',//活动背景
|
giftcard: {
|
||||||
promotion_aux_color: '#FA8B00',//活动背景辅色
|
giftcard_promotion_color: '#FF3369',//活动背景
|
||||||
main_color_shallow: '#efefef',//淡背景
|
giftcard_promotion_aux_color: '#F7B500',//活动辅色
|
||||||
price_color: 'rgba(255,0,0,1)',//价格颜色
|
},
|
||||||
btn_text_color: '#FFFFFF',//按钮文字颜色
|
groupby: {
|
||||||
...{
|
groupby_promotion_color: '#E64136',//活动背景
|
||||||
goods_price: 'rgba(255,0,0,1)',//价格
|
groupby_promotion_aux_color: '#F7B500',//活动辅色
|
||||||
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_label_bg: '#F7B500',
|
|
||||||
pintuan_label_color: '#FFFFFF',
|
|
||||||
pintuan_color: '#FA6400',
|
|
||||||
pintuan_promotion_color: '#FA3A1D',//活动背景
|
|
||||||
pintuan_promotion_aux_color: '#FD9A01',//活动背景辅色
|
|
||||||
},
|
|
||||||
...{
|
|
||||||
super_member_start_bg: '#fadcb5',
|
|
||||||
super_member_end_bg: '#f6bd74',
|
|
||||||
super_member_start_text_color: '#ab6126',
|
|
||||||
super_member_end_text_color: '#d19336',
|
|
||||||
},
|
|
||||||
...{
|
|
||||||
bargain_promotion_color: '#F0353E',//活动背景
|
|
||||||
bargain_promotion_aux_color: '#FD9A01',//活动辅色
|
|
||||||
},
|
|
||||||
...{
|
|
||||||
seckill_promotion_color: '#F83530',//活动背景
|
|
||||||
seckill_promotion_aux_color: '#FD9A01',//活动辅色
|
|
||||||
},
|
|
||||||
...{
|
|
||||||
giftcard_promotion_color: '#FF3369',//活动背景
|
|
||||||
giftcard_promotion_aux_color: '#F7B500',//活动辅色
|
|
||||||
},
|
|
||||||
...{
|
|
||||||
groupby_promotion_color: '#E64136',//活动背景
|
|
||||||
groupby_promotion_aux_color: '#F7B500',//活动辅色
|
|
||||||
},
|
|
||||||
...{
|
|
||||||
hover_nav_bg_color: '#222222',//背景色
|
|
||||||
hover_nav_text_color: '#FFFFFF'
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,148 +0,0 @@
|
|||||||
/**
|
|
||||||
* 将常用的Uniapp提供的函数,存放到这里,按需引用
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 显示错误信息
|
|
||||||
* @param {Exception} err
|
|
||||||
* @param {Boolean} useModal
|
|
||||||
*/
|
|
||||||
const showError = (err, useModal = false) => {
|
|
||||||
const content = err?.message || err?.errMsg || err?.toString();
|
|
||||||
if (!useModal) {
|
|
||||||
uni.showToast({
|
|
||||||
title: content,
|
|
||||||
icon: 'none',
|
|
||||||
duration: 3000
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
uni.showModal({
|
|
||||||
title: '错误提示',
|
|
||||||
content,
|
|
||||||
showCancel: false,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 打电话
|
|
||||||
* @param {string} mobile 电话号码
|
|
||||||
*/
|
|
||||||
export const makePhoneCall = (mobile) => {
|
|
||||||
try {
|
|
||||||
uni.makePhoneCall({
|
|
||||||
phoneNumber: `${mobile}`,
|
|
||||||
success(e) {
|
|
||||||
console.log(e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (err) {
|
|
||||||
showError(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 拷贝文本(返回 Promise)
|
|
||||||
* @param {*} text
|
|
||||||
* @param {*} options
|
|
||||||
* @returns {Promise} 返回 Promise,成功时 resolve,失败时 reject
|
|
||||||
*/
|
|
||||||
export const copyTextAsync = (text, { copySuccess = '', copyFailed = '' } = {}) => {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
// 输入验证
|
|
||||||
if (!text && text !== '') {
|
|
||||||
const error = new Error('复制文本不能为空');
|
|
||||||
showError(error);
|
|
||||||
reject(error);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 超时监测
|
|
||||||
const timeoutId = setTimeout(() => {
|
|
||||||
let error = new Error('复制操作长时间无响应,请检查相关权限及配置是否正确');
|
|
||||||
// #ifdef MP-WEIXIN
|
|
||||||
error = new Error([
|
|
||||||
'复制操作长时间无响应!',
|
|
||||||
'原因:',
|
|
||||||
'1.微信平台->用户隐私保护指引->"剪贴板"功能未添加或审核未通过;',
|
|
||||||
'2.微信平台对剪贴板API调用频率有限制'
|
|
||||||
].join('\r\n'));
|
|
||||||
// #endif
|
|
||||||
showError(error, true);
|
|
||||||
reject(error);
|
|
||||||
}, 5000);
|
|
||||||
|
|
||||||
try {
|
|
||||||
uni.setClipboardData({
|
|
||||||
data: `${text}`,
|
|
||||||
success: (res) => {
|
|
||||||
clearTimeout(timeoutId);
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (copySuccess) {
|
|
||||||
uni.showToast({
|
|
||||||
title: copySuccess,
|
|
||||||
icon: 'success',
|
|
||||||
duration: 2000
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
showError(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
resolve(res);
|
|
||||||
},
|
|
||||||
fail: (err) => {
|
|
||||||
clearTimeout(timeoutId);
|
|
||||||
try {
|
|
||||||
uni.showToast({
|
|
||||||
title: err.message || err.errMsg || copyFailed || '复制失败',
|
|
||||||
icon: 'none',
|
|
||||||
duration: 2000
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
showError(e);
|
|
||||||
}
|
|
||||||
reject(err);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (err) {
|
|
||||||
clearTimeout(timeoutId);
|
|
||||||
showError(err);
|
|
||||||
reject(err);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 拷贝文本(回调形式,兼容旧代码)
|
|
||||||
* @param {*} text
|
|
||||||
* @param {*} options
|
|
||||||
* @param {Function} callback 回调函数,接收 (success, error) 参数
|
|
||||||
*/
|
|
||||||
export const copyText = (text, options = {}, callback) => {
|
|
||||||
copyTextAsync(text, options)
|
|
||||||
.then(res => {
|
|
||||||
if (callback) callback(true, null);
|
|
||||||
})
|
|
||||||
.catch(err => {
|
|
||||||
if (callback) callback(false, err);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 打开定位
|
|
||||||
* @param {Object} options
|
|
||||||
*/
|
|
||||||
export const openLocation = ({ latitude, longitude, name } = {}) => {
|
|
||||||
try {
|
|
||||||
uni.openLocation({
|
|
||||||
latitude,
|
|
||||||
longitude,
|
|
||||||
name,
|
|
||||||
});
|
|
||||||
} catch (err) {
|
|
||||||
showError(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -7,20 +7,15 @@ import {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 关于页面路径,使用常量导出
|
// 首页路径
|
||||||
export const INDEX_PAGE_URL = '/pages/index/index';
|
export const INDEX_PAGE_URL = '/pages/index/index';
|
||||||
export const CATEGORY_PAGE_URL = '/pages_goods/category';
|
|
||||||
export const CONTACT_PAGE_URL = '/pages_tool/contact/contact';
|
|
||||||
export const MEMBER_PAGE_URL = '/pages_tool/member/index';
|
|
||||||
export const LOGIN_PAGE_URL = '/pages_tool/login/login';
|
|
||||||
export const AI_CHAT_PAGE_URL = '/pages_tool/ai-chat/index';
|
|
||||||
|
|
||||||
// 当前最新的tabBar.list (参见pages.json 中的tabBar.list 配置)
|
// 当前最新的tabBar.list (参见pages.json 中的tabBar.list 配置)
|
||||||
export const systemTabBarList = [
|
export const systemTabBarList = [
|
||||||
INDEX_PAGE_URL,
|
INDEX_PAGE_URL,
|
||||||
CATEGORY_PAGE_URL,
|
'/pages_goods/category',
|
||||||
CONTACT_PAGE_URL,
|
'/pages_tool/contact/contact',
|
||||||
MEMBER_PAGE_URL
|
'/pages_tool/member/index'
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -37,28 +32,10 @@ export const adaptSubpackageUrl = (url) => {
|
|||||||
*/
|
*/
|
||||||
// 定义前缀映射表
|
// 定义前缀映射表
|
||||||
const urlPrefixMap = {
|
const urlPrefixMap = {
|
||||||
'/pages/promotion/': '/pages_promotion/',
|
|
||||||
'/pages/order/': '/pages_order/',
|
|
||||||
'/pages/goods/': '/pages_goods/',
|
'/pages/goods/': '/pages_goods/',
|
||||||
|
|
||||||
'/pages/contact/': '/pages_tool/contact/',
|
'/pages/contact/': '/pages_tool/contact/',
|
||||||
'/pages/member/': '/pages_tool/member/',
|
'/pages/member/': '/pages_tool/member/',
|
||||||
'/pages/login/': '/pages_tool/login/',
|
'/pages/vr': '/pages_tool/vr/'
|
||||||
'/pages/agreement/': '/pages_tool/agreement/',
|
|
||||||
'/pages/article/': '/pages_tool/article/',
|
|
||||||
'/pages/cases/': '/pages_tool/cases/',
|
|
||||||
'/pages/contact/': '/pages_tool/contact/',
|
|
||||||
'/pages/files/': '/pages_tool/files/',
|
|
||||||
'/pages/form/': '/pages_tool/form/',
|
|
||||||
'/pages/help/': '/pages_tool/help/',
|
|
||||||
'/pages/notice/': '/pages_tool/notice/',
|
|
||||||
'/pages/pay/': '/pages_tool/pay/',
|
|
||||||
'/pages/recharge/': '/pages_tool/recharge/',
|
|
||||||
'/pages/seal/': '/pages_tool/seal/',
|
|
||||||
'/pages/storeclose/': '/pages_tool/storeclose/',
|
|
||||||
'/pages/vr/': '/pages_tool/vr/',
|
|
||||||
'/pages/weapp/': '/pages_tool/weapp/',
|
|
||||||
'/pages/webview/': '/pages_tool/webview/',
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 构建正则表达式
|
// 构建正则表达式
|
||||||
@@ -84,55 +61,18 @@ export const adaptSubpackageUrl = (url) => {
|
|||||||
return replacePrefix(url);
|
return replacePrefix(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 检查tabBar是否激活
|
|
||||||
* @param {string} linkUrl 链接路径 /pages/goods/category
|
|
||||||
* @param {string} currentPageRoute 当前页面路径 /pages_goods/category
|
|
||||||
* @returns {boolean} 是否激活
|
|
||||||
*/
|
|
||||||
export const checkTabBarActive = (linkUrl, currentPageRoute) => {
|
|
||||||
const linkUrlParts = adaptSubpackageUrl(linkUrl).split('/');
|
|
||||||
const currentPageRouteParts = currentPageRoute.split('/');
|
|
||||||
|
|
||||||
// console.log('diy-bottom-nav verify:', { linkUrlParts, currentPageRouteParts});
|
|
||||||
|
|
||||||
try {
|
|
||||||
// 二级页面
|
|
||||||
if (linkUrlParts[2] === currentPageRouteParts[2]) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 一级页面,限定只能是goods相关
|
|
||||||
if (linkUrlParts[1] === currentPageRouteParts[1] && linkUrlParts[1] === 'pages_goods') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
console.error('diy-bottom-nav verify error:', error);
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
/** 导出页面URL常量 */
|
|
||||||
MEMBER_PAGE_URL,
|
|
||||||
CATEGORY_PAGE_URL,
|
|
||||||
CONTACT_PAGE_URL,
|
|
||||||
INDEX_PAGE_URL,
|
|
||||||
LOGIN_PAGE_URL,
|
|
||||||
AI_CHAT_PAGE_URL,
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 页面跳转
|
* 页面跳转
|
||||||
* @param {string} to 跳转链接 /pages/idnex/index
|
* @param {string} to 跳转链接 /pages/idnex/index
|
||||||
* @param {Object} param 参数 {key : value, ...}, 默认{}
|
* @param {Object} param 参数 {key : value, ...}
|
||||||
* @param {string} mode 模式 navigateTo、redirectTo、reLaunch、tabbar, 默认navigateTo
|
* @param {string} mode 模式
|
||||||
*/
|
*/
|
||||||
redirectTo(to, param = {}, mode = 'navigateTo') {
|
redirectTo(to, param, mode) {
|
||||||
let url = to;
|
let url = to;
|
||||||
|
|
||||||
// 替换url中的前缀
|
// 替换url中的前缀
|
||||||
console.log('页面跳转 redirectTo', to, param, mode);
|
console.log('redirectTo', to, param, mode);
|
||||||
url = adaptSubpackageUrl(url);
|
url = adaptSubpackageUrl(url);
|
||||||
console.log('adaptSubpackageUrl', url);
|
console.log('adaptSubpackageUrl', url);
|
||||||
|
|
||||||
@@ -151,7 +91,7 @@ export default {
|
|||||||
const tabBarUrl = systemTabBarList[i];
|
const tabBarUrl = systemTabBarList[i];
|
||||||
if (url.indexOf(tabBarUrl) == 0) {
|
if (url.indexOf(tabBarUrl) == 0) {
|
||||||
// 首页特殊处理,采用switchTab, 其他页面采用redirectTo, 不能返回,不能退回
|
// 首页特殊处理,采用switchTab, 其他页面采用redirectTo, 不能返回,不能退回
|
||||||
(tabBarUrl == INDEX_PAGE_URL ? uni.switchTab : uni.redirectTo)({ url });
|
(tabBarUrl == INDEX_PAGE_URL ? uni.switchTab : uni.redirectTo)({url});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -159,26 +99,26 @@ export default {
|
|||||||
// 如果url不包含tabBarList中的路径,根据mode判断跳转方式
|
// 如果url不包含tabBarList中的路径,根据mode判断跳转方式
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case 'tabbar':
|
case 'tabbar':
|
||||||
// 跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面。重置页面栈,仅保留 tabBar 页面
|
// 跳转到 tabBar 页面,并关闭其他所有非 tabBar 页面。
|
||||||
uni.switchTab({
|
uni.switchTab({
|
||||||
url
|
url
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case 'redirectTo':
|
case 'redirectTo':
|
||||||
// 关闭当前页面,跳转到应用内的某个页面。替换栈顶页面,长度不变(上限10层)
|
// 关闭当前页面,跳转到应用内的某个页面。
|
||||||
uni.redirectTo({
|
uni.redirectTo({
|
||||||
url
|
url
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case 'reLaunch':
|
case 'reLaunch':
|
||||||
// 关闭所有页面,打开到应用内的某个页面。清空栈后打开新页面,长度=1
|
// 关闭所有页面,打开到应用内的某个页面。
|
||||||
uni.reLaunch({
|
uni.reLaunch({
|
||||||
url
|
url
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
// 保留当前页面,跳转到应用内的某个页面,新增页面到栈顶,长度+1(上限10层)
|
// 保留当前页面,跳转到应用内的某个页面
|
||||||
console.log('保留当前页面,navigateTo跳转到应用内的某个页面', url);
|
console.log('保留当前页面,跳转到应用内的某个页面', url);
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
url
|
url
|
||||||
});
|
});
|
||||||
@@ -190,6 +130,8 @@ export default {
|
|||||||
* @param {Object} params 参数,针对商品、相册里面的图片区分大中小,size: big、mid、small
|
* @param {Object} params 参数,针对商品、相册里面的图片区分大中小,size: big、mid、small
|
||||||
*/
|
*/
|
||||||
img(img_path, params) {
|
img(img_path, params) {
|
||||||
|
|
||||||
|
|
||||||
var path = "";
|
var path = "";
|
||||||
if (img_path != undefined && img_path != "") {
|
if (img_path != undefined && img_path != "") {
|
||||||
if (img_path.split(',').length > 1) {
|
if (img_path.split(',').length > 1) {
|
||||||
@@ -549,7 +491,7 @@ export default {
|
|||||||
* 检测苹果X以上的手机
|
* 检测苹果X以上的手机
|
||||||
*/
|
*/
|
||||||
isIPhoneX() {
|
isIPhoneX() {
|
||||||
let res = this.getDeviceInfo();
|
let res = uni.getSystemInfoSync();
|
||||||
if (res.model.search('iPhone X') != -1) {
|
if (res.model.search('iPhone X') != -1) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -557,33 +499,13 @@ export default {
|
|||||||
},
|
},
|
||||||
//判断安卓还是iOS
|
//判断安卓还是iOS
|
||||||
isAndroid() {
|
isAndroid() {
|
||||||
let platform = this.getDeviceInfo().platform;
|
let platform = uni.getSystemInfoSync().platform
|
||||||
if (platform == 'ios') {
|
if (platform == 'ios') {
|
||||||
return false;
|
return false;
|
||||||
} else if (platform == 'android') {
|
} else if (platform == 'android') {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
/**
|
|
||||||
* 获取设备信息(包含降级处理)
|
|
||||||
*/
|
|
||||||
getDeviceInfo() {
|
|
||||||
try {
|
|
||||||
return uni.getDeviceInfo();
|
|
||||||
} catch (e) {
|
|
||||||
return uni.getSystemInfoSync();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* 获取窗口信息(包含降级处理)
|
|
||||||
*/
|
|
||||||
getWindowInfo() {
|
|
||||||
try {
|
|
||||||
return uni.getWindowInfo();
|
|
||||||
} catch (e) {
|
|
||||||
return uni.getSystemInfoSync();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
/**
|
/**
|
||||||
* 深度拷贝对象
|
* 深度拷贝对象
|
||||||
* @param {Object} obj
|
* @param {Object} obj
|
||||||
@@ -605,36 +527,6 @@ export default {
|
|||||||
}
|
}
|
||||||
return cloneObj
|
return cloneObj
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 打开微信企业客服
|
|
||||||
* @param {Function} fallbackFunc 降级处理函数
|
|
||||||
*/
|
|
||||||
openWxWorkServiceChat(fallbackFunc) {
|
|
||||||
// #ifdef MP-WEIXIN
|
|
||||||
let wxworkConfig = store.state?.wxworkConfig
|
|
||||||
if (wxworkConfig?.enable && wxworkConfig?.contact_url) {
|
|
||||||
// 直接使用活码链接跳转
|
|
||||||
wx.navigateToMiniProgram({
|
|
||||||
appId: 'wxeb490c6f9b154ef9', // 是企业微信官方小程序的AppID(固定值, 由腾讯企业微信团队维护, 不需要修改,用于展示"添加企业微信联系人"的官方页面)
|
|
||||||
path: `pages/contacts/externalContactDetail?url=${encodeURIComponent(wxworkConfig?.contact_url)}`,
|
|
||||||
success: () => {
|
|
||||||
console.log('跳转企业微信成功');
|
|
||||||
},
|
|
||||||
fail: (err) => {
|
|
||||||
console.error('跳转企业微信失败:', err);
|
|
||||||
// 降级处理:使用原有客服方式
|
|
||||||
fallbackFunc && fallbackFunc();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
fallbackFunc && fallbackFunc();
|
|
||||||
}
|
|
||||||
// #endif
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 自定义模板的跳转链接
|
* 自定义模板的跳转链接
|
||||||
* @param {Object} link
|
* @param {Object} link
|
||||||
@@ -657,6 +549,7 @@ export default {
|
|||||||
|
|
||||||
} else if (link.appid) {
|
} else if (link.appid) {
|
||||||
// 跳转其他小程序
|
// 跳转其他小程序
|
||||||
|
|
||||||
uni.navigateToMiniProgram({
|
uni.navigateToMiniProgram({
|
||||||
appId: link.appid,
|
appId: link.appid,
|
||||||
path: link.page
|
path: link.page
|
||||||
@@ -664,6 +557,7 @@ export default {
|
|||||||
|
|
||||||
} else if (link.name == 'MOBILE' && !link.wap_url) {
|
} else if (link.name == 'MOBILE' && !link.wap_url) {
|
||||||
// 拨打电话
|
// 拨打电话
|
||||||
|
|
||||||
uni.makePhoneCall({
|
uni.makePhoneCall({
|
||||||
phoneNumber: link.mobile,
|
phoneNumber: link.mobile,
|
||||||
success: (res) => {
|
success: (res) => {
|
||||||
@@ -696,19 +590,16 @@ export default {
|
|||||||
// #endif
|
// #endif
|
||||||
|
|
||||||
// #ifdef MP-WEIXIN
|
// #ifdef MP-WEIXIN
|
||||||
this.openWxWorkServiceChat(() => {
|
wx.openCustomerServiceChat({
|
||||||
wx.openCustomerServiceChat({
|
extInfo: {
|
||||||
extInfo: {
|
url: config.wxwork_url
|
||||||
url: config.wxwork_url
|
},
|
||||||
},
|
corpId: config.corpid,
|
||||||
corpId: config.corpid,
|
showMessageCard: true,
|
||||||
showMessageCard: true,
|
sendMessageTitle: 'this.sendMessageTitle',
|
||||||
sendMessageTitle: 'this.sendMessageTitle',
|
sendMessagePath: 'this.sendMessagePath',
|
||||||
sendMessagePath: 'this.sendMessagePath',
|
sendMessageImg: 'this.sendMessageImg'
|
||||||
sendMessageImg: 'this.sendMessageImg'
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// #endif
|
// #endif
|
||||||
break;
|
break;
|
||||||
case 'third':
|
case 'third':
|
||||||
@@ -759,7 +650,7 @@ export default {
|
|||||||
*/
|
*/
|
||||||
uniappIsIPhoneX() {
|
uniappIsIPhoneX() {
|
||||||
let isIphoneX = false;
|
let isIphoneX = false;
|
||||||
let systemInfo = this.getDeviceInfo();
|
let systemInfo = uni.getSystemInfoSync();
|
||||||
// #ifdef MP
|
// #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) {
|
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;
|
isIphoneX = true;
|
||||||
@@ -786,7 +677,7 @@ export default {
|
|||||||
*/
|
*/
|
||||||
uniappIsIPhone11() {
|
uniappIsIPhone11() {
|
||||||
let isIphone11 = false;
|
let isIphone11 = false;
|
||||||
let systemInfo = this.getDeviceInfo();
|
let systemInfo = uni.getSystemInfoSync();
|
||||||
// #ifdef MP
|
// #ifdef MP
|
||||||
if (systemInfo.model.search('iPhone 11') != -1) {
|
if (systemInfo.model.search('iPhone 11') != -1) {
|
||||||
isIphone11 = true;
|
isIphone11 = true;
|
||||||
@@ -797,7 +688,7 @@ export default {
|
|||||||
// #ifdef H5
|
// #ifdef H5
|
||||||
//判断该浏览器是否为safaria浏览器
|
//判断该浏览器是否为safaria浏览器
|
||||||
isSafari() {
|
isSafari() {
|
||||||
let res = this.getDeviceInfo();
|
let res = uni.getSystemInfoSync();
|
||||||
var ua = navigator.userAgent.toLowerCase();
|
var ua = navigator.userAgent.toLowerCase();
|
||||||
if (ua.indexOf('applewebkit') > -1 && ua.indexOf('mobile') > -1 && ua.indexOf('safari') > -1 &&
|
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('linux') === -1 && ua.indexOf('android') === -1 && ua.indexOf('chrome') === -1 &&
|
||||||
@@ -836,22 +727,13 @@ export default {
|
|||||||
let routes = getCurrentPages(); // 获取当前打开过的页面路由数组
|
let routes = getCurrentPages(); // 获取当前打开过的页面路由数组
|
||||||
return routes.length ? routes[routes.length - 1].route : '';
|
return routes.length ? routes[routes.length - 1].route : '';
|
||||||
},
|
},
|
||||||
goBack(backUrl = INDEX_PAGE_URL) {
|
goBack(backUrl = '/pages/index/index') {
|
||||||
if (getCurrentPages().length == 1) {
|
if (getCurrentPages().length == 1) {
|
||||||
this.redirectTo(backUrl);
|
this.redirectTo(backUrl);
|
||||||
} else {
|
} else {
|
||||||
uni.navigateBack();
|
uni.navigateBack();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
/**
|
|
||||||
* 隐藏“返回首页/小房子”按钮
|
|
||||||
* 这个函数,用到页面show, onshow 的生命周期时
|
|
||||||
*/
|
|
||||||
hideHomeButton() {
|
|
||||||
// #ifdef MP-WEIXIN
|
|
||||||
wx.hideHomeButton();
|
|
||||||
// #endif
|
|
||||||
},
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param val 转化时间字符串 (转化时分秒)
|
* @param val 转化时间字符串 (转化时分秒)
|
||||||
@@ -1201,74 +1083,5 @@ export default {
|
|||||||
verifyMobile(mobile) {
|
verifyMobile(mobile) {
|
||||||
var parse = /^\d{11}$/.test(mobile);
|
var parse = /^\d{11}$/.test(mobile);
|
||||||
return parse;
|
return parse;
|
||||||
},
|
|
||||||
/**
|
|
||||||
* 判断是否为快应用环境
|
|
||||||
* @returns {boolean} 是否为快应用
|
|
||||||
*/
|
|
||||||
isQuickApp() {
|
|
||||||
// #ifndef QUICKAPP-WEBVIEW
|
|
||||||
let _isQuickApp = false;
|
|
||||||
try {
|
|
||||||
const ua = navigator?.userAgent?.toLowerCase();
|
|
||||||
// console.log('ua = ', ua);
|
|
||||||
_isQuickApp = ua.indexOf('quickapp') !== -1;
|
|
||||||
|
|
||||||
if (!_isQuickApp) {
|
|
||||||
// 特殊说明由于网站是嵌入到快应用的Webview组件中<web>,UA中不会包含quickapp字符串,
|
|
||||||
// 但是会包含uniacid参数,所以这里通过uniacid参数来判断是否为快应用环境
|
|
||||||
_isQuickApp = ua.indexOf('uniacid=') !== -1;
|
|
||||||
}
|
|
||||||
} catch (e) { }
|
|
||||||
|
|
||||||
if (!_isQuickApp) {
|
|
||||||
const systemInfo = this.getDeviceInfo();
|
|
||||||
_isQuickApp = systemInfo?.platform === 'quickapp' || process?.env?.UNI_PLATFORM === 'quickapp';
|
|
||||||
}
|
|
||||||
return _isQuickApp;
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* 判断是否为华为快应用环境
|
|
||||||
* @returns {boolean} 是否为华为快应用
|
|
||||||
*/
|
|
||||||
isHuaweiQuickApp() {
|
|
||||||
if (!this.isQuickApp()) return false;
|
|
||||||
|
|
||||||
// #ifndef QUICKAPP-WEBVIEW-HUAWEI
|
|
||||||
const systemInfo = this.getDeviceInfo();
|
|
||||||
return systemInfo.brand === 'HUAWEI' || systemInfo.manufacturer === 'HUAWEI' ||
|
|
||||||
(typeof qh !== 'undefined' && qh.platform === 'huawei');
|
|
||||||
// #endif
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 蛇形命名转驼峰命名
|
|
||||||
* @param {string} str 蛇形命名字符串
|
|
||||||
* @returns {string} 驼峰命名字符串
|
|
||||||
*/
|
|
||||||
snakeToCamel(str) {
|
|
||||||
return str.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 蛇形命名转驼峰命名(递归处理对象中的所有属性名)
|
|
||||||
* @param {Object} obj 包含蛇形命名字符串属性的对象
|
|
||||||
* @returns {Object} 驼峰命名字符串属性的对象
|
|
||||||
*/
|
|
||||||
snakeToCamelForObj(obj) {
|
|
||||||
if (typeof obj !== 'object' || obj === null) return obj;
|
|
||||||
if (Array.isArray(obj)) return obj.map(this.snakeToCamelForObj.bind(this));
|
|
||||||
const newObj = {};
|
|
||||||
for (const key in obj) {
|
|
||||||
if (Object.hasOwnProperty.call(obj, key)) {
|
|
||||||
const newKey = this.snakeToCamel(key);
|
|
||||||
newObj[newKey] = this.snakeToCamelForObj(obj[key]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return newObj;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,143 +0,0 @@
|
|||||||
// 公共微信视频号样式
|
|
||||||
|
|
||||||
// CSS 变量
|
|
||||||
:root {
|
|
||||||
// 尺寸变量
|
|
||||||
--channel-play-btn-size: 80rpx;
|
|
||||||
--channel-play-btn-small-size: 60rpx;
|
|
||||||
--channel-play-btn-icon-size: 40rpx;
|
|
||||||
--channel-play-btn-icon-small-size: 30rpx;
|
|
||||||
--channel-border-radius: 12rpx;
|
|
||||||
--channel-stats-padding: 10rpx;
|
|
||||||
--channel-info-wrap-padding: 10rpx 0;
|
|
||||||
|
|
||||||
// 字体变量
|
|
||||||
--channel-name-font-size: 28rpx;
|
|
||||||
--video-title-font-size: 28rpx;
|
|
||||||
--video-title-small-font-size: 24rpx;
|
|
||||||
--video-stats-font-size: 24rpx;
|
|
||||||
--channel-stats-font-size: 20rpx;
|
|
||||||
|
|
||||||
// 颜色变量
|
|
||||||
--channel-name-color: #333;
|
|
||||||
--video-title-color: #333;
|
|
||||||
--video-title-small-color: #666;
|
|
||||||
--video-stats-color: #999;
|
|
||||||
--channel-stats-color: #fff;
|
|
||||||
--channel-border-color: #f0f0f0;
|
|
||||||
--channel-play-btn-bg: rgba(0, 0, 0, 0.4);
|
|
||||||
--channel-stats-bg: linear-gradient(transparent, rgba(0, 0, 0, 0.6));
|
|
||||||
|
|
||||||
// 间距变量
|
|
||||||
--channel-name-margin-bottom: 4rpx;
|
|
||||||
--video-title-margin-bottom: 8rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 响应式设计
|
|
||||||
@media (max-width: 375px) {
|
|
||||||
:root {
|
|
||||||
--channel-play-btn-size: 70rpx;
|
|
||||||
--channel-play-btn-small-size: 50rpx;
|
|
||||||
--channel-play-btn-icon-size: 35rpx;
|
|
||||||
--channel-play-btn-icon-small-size: 25rpx;
|
|
||||||
--channel-name-font-size: 24rpx;
|
|
||||||
--video-title-font-size: 24rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 750px) {
|
|
||||||
:root {
|
|
||||||
--channel-play-btn-size: 90rpx;
|
|
||||||
--channel-play-btn-small-size: 70rpx;
|
|
||||||
--channel-play-btn-icon-size: 45rpx;
|
|
||||||
--channel-play-btn-icon-small-size: 35rpx;
|
|
||||||
--channel-name-font-size: 32rpx;
|
|
||||||
--video-title-font-size: 32rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 播放按钮样式
|
|
||||||
.channel-play-btn {
|
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
left: 50%;
|
|
||||||
transform: translate(-50%, -50%);
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
width: var(--channel-play-btn-size);
|
|
||||||
height: var(--channel-play-btn-size);
|
|
||||||
background-color: var(--channel-play-btn-bg);
|
|
||||||
border-radius: 50%;
|
|
||||||
|
|
||||||
.play-icon {
|
|
||||||
width: var(--channel-play-btn-icon-size);
|
|
||||||
height: var(--channel-play-btn-icon-size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 小尺寸播放按钮(用于列表)
|
|
||||||
.channel-play-btn.small {
|
|
||||||
width: var(--channel-play-btn-small-size);
|
|
||||||
height: var(--channel-play-btn-small-size);
|
|
||||||
|
|
||||||
.play-icon {
|
|
||||||
width: var(--channel-play-btn-icon-small-size);
|
|
||||||
height: var(--channel-play-btn-icon-small-size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 视频统计信息
|
|
||||||
.channel-stats {
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
background: var(--channel-stats-bg);
|
|
||||||
padding: var(--channel-stats-padding);
|
|
||||||
color: var(--channel-stats-color);
|
|
||||||
font-size: var(--channel-stats-font-size);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 视频信息容器
|
|
||||||
.channel-info-wrap {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
flex: 1;
|
|
||||||
padding: var(--channel-info-wrap-padding);
|
|
||||||
|
|
||||||
.channel-name {
|
|
||||||
margin-bottom: var(--channel-name-margin-bottom);
|
|
||||||
white-space: nowrap;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
overflow: hidden;
|
|
||||||
font-size: var(--channel-name-font-size);
|
|
||||||
font-weight: 500;
|
|
||||||
color: var(--channel-name-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
.video-title {
|
|
||||||
white-space: nowrap;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
overflow: hidden;
|
|
||||||
font-size: var(--video-title-small-font-size);
|
|
||||||
color: var(--video-title-small-color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 视频标题
|
|
||||||
.video-title {
|
|
||||||
font-size: var(--video-title-font-size);
|
|
||||||
font-weight: 500;
|
|
||||||
color: var(--video-title-color);
|
|
||||||
margin-bottom: var(--video-title-margin-bottom);
|
|
||||||
line-height: 1.4;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 视频统计信息(非绝对定位版本)
|
|
||||||
.video-stats {
|
|
||||||
font-size: var(--video-stats-font-size);
|
|
||||||
color: var(--video-stats-color);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@@ -3,11 +3,11 @@
|
|||||||
<view class="article-wrap" :style="warpCss">
|
<view class="article-wrap" :style="warpCss">
|
||||||
<view :class="['list-wrap', value.style]" :style="warpCss">
|
<view :class="['list-wrap', value.style]" :style="warpCss">
|
||||||
<!-- 自动垂直滚动 -->
|
<!-- 自动垂直滚动 -->
|
||||||
<swiper class="auto-scroll-swiper" :style="[swiperStyle]" :vertical="swiperConfig.vertical !== false"
|
<swiper class="auto-scroll-swiper" :style="swiperStyle" :vertical="swiperConfig.vertical !== false"
|
||||||
:autoplay="swiperConfig.autoplay !== false" :circular="swiperConfig.circular !== false"
|
:autoplay="swiperConfig.autoplay !== false" :circular="swiperConfig.circular !== false"
|
||||||
:interval="swiperConfig.interval || 3000" :duration="swiperConfig.duration || 500"
|
:interval="swiperConfig.interval || 3000" :duration="swiperConfig.duration || 500"
|
||||||
:display-multiple-items="safeDisplayMultipleItems">
|
:display-multiple-items="safeDisplayMultipleItems">
|
||||||
<swiper-item v-for="(item, index) in list" :key="index" @tap.stop="toDetail(item)">
|
<swiper-item v-for="(item, index) in list" :key="index" @click="toDetail(item)">
|
||||||
<view class="swiper-item-content">
|
<view class="swiper-item-content">
|
||||||
<view :class="['item', value.ornament.type]" :style="itemCss">
|
<view :class="['item', value.ornament.type]" :style="itemCss">
|
||||||
<view class="article-img">
|
<view class="article-img">
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
<view class="time" :style="{ color: value.timecolor }">
|
<view class="time" :style="{ color: value.timecolor }">
|
||||||
{{ audiotime }}
|
{{ audiotime }}
|
||||||
</view>
|
</view>
|
||||||
<view @tap.stop="play()" class="start" :class="status ? 'iconj icon-07zanting' : 'iconj icon-bofang'"
|
<view @click="play()" class="start" :class="status ? 'iconj icon-07zanting' : 'iconj icon-bofang'"
|
||||||
style="padding-top: 18rpx"></view>
|
style="padding-top: 18rpx"></view>
|
||||||
</view>
|
</view>
|
||||||
<view class="fui-audio style3" :style="{ background: value.background }" v-else>
|
<view class="fui-audio style3" :style="{ background: value.background }" v-else>
|
||||||
@@ -30,7 +30,7 @@
|
|||||||
<!-- {{audios[value.id].audiotime}} -->
|
<!-- {{audios[value.id].audiotime}} -->
|
||||||
{{ audiotime }}
|
{{ audiotime }}
|
||||||
</view>
|
</view>
|
||||||
<view @tap.stop="play()" class="start" :class="status ? 'iconj icon-07zanting' : 'iconj icon-bofang'"></view>
|
<view @click="play()" class="start" :class="status ? 'iconj icon-07zanting' : 'iconj icon-bofang'"></view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
:style="{ color: value.titleStyle.textColor }">低至0元免费拿</view>
|
:style="{ color: value.titleStyle.textColor }">低至0元免费拿</view>
|
||||||
<view class="head-right"
|
<view class="head-right"
|
||||||
:style="{ fontSize: value.titleStyle.moreFontSize * 2 + 'rpx', color: value.titleStyle.moreColor }"
|
:style="{ fontSize: value.titleStyle.moreFontSize * 2 + 'rpx', color: value.titleStyle.moreColor }"
|
||||||
@tap.stop="$util.redirectTo('/pages_promotion/bargain/list')">
|
@click="$util.redirectTo('/pages_promotion/bargain/list')">
|
||||||
<text>{{ value.titleStyle.more }}</text>
|
<text>{{ value.titleStyle.more }}</text>
|
||||||
<text class="iconfont icon-right"></text>
|
<text class="iconfont icon-right"></text>
|
||||||
</view>
|
</view>
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
<!-- 商品列表 -->
|
<!-- 商品列表 -->
|
||||||
<template v-if="value.template == 'row1-of1'">
|
<template v-if="value.template == 'row1-of1'">
|
||||||
<view class="item" v-for="(item, index) in list" :key="index" @tap.stop="toDetail(item)"
|
<view class="item" v-for="(item, index) in list" :key="index" @click="toDetail(item)"
|
||||||
:class="[value.ornament.type]" :style="goodsItemCss">
|
:class="[value.ornament.type]" :style="goodsItemCss">
|
||||||
<view class="img-wrap" :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }">
|
<view class="img-wrap" :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }">
|
||||||
<image :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }"
|
<image :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }"
|
||||||
@@ -84,7 +84,7 @@
|
|||||||
|
|
||||||
<template v-if="value.template == 'horizontal-slide'">
|
<template v-if="value.template == 'horizontal-slide'">
|
||||||
<scroll-view v-if="value.slideMode == 'scroll'" class="scroll" :scroll-x="true" :show-scrollbar="false">
|
<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" @tap.stop="toDetail(item)"
|
<view class="item" v-for="(item, index) in list" :key="index" @click="toDetail(item)"
|
||||||
:class="[value.ornament.type]" :style="goodsItemCss">
|
:class="[value.ornament.type]" :style="goodsItemCss">
|
||||||
<view class="img-wrap" :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }">
|
<view class="img-wrap" :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }">
|
||||||
<image :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }"
|
<image :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }"
|
||||||
@@ -130,7 +130,7 @@
|
|||||||
<swiper-item v-for="(pageItem, pageIndex) in page" :key="pageIndex"
|
<swiper-item v-for="(pageItem, pageIndex) in page" :key="pageIndex"
|
||||||
:class="['swiper-item', (list.length && [list[pageIndex].length / 3] >= 1) && 'flex-between']">
|
:class="['swiper-item', (list.length && [list[pageIndex].length / 3] >= 1) && 'flex-between']">
|
||||||
<view class="item" v-for="(item, dataIndex) in list[pageIndex]" :key="dataIndex"
|
<view class="item" v-for="(item, dataIndex) in list[pageIndex]" :key="dataIndex"
|
||||||
@tap.stop="toDetail(item)" :class="[value.ornament.type]" :style="goodsItemCss">
|
@click="toDetail(item)" :class="[value.ornament.type]" :style="goodsItemCss">
|
||||||
<view class="img-wrap" :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }">
|
<view class="img-wrap" :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }">
|
||||||
<image :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }"
|
<image :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }"
|
||||||
:src="$util.img(item.goods_image, { size: 'mid' })" mode="widthFix"
|
:src="$util.img(item.goods_image, { size: 'mid' })" mode="widthFix"
|
||||||
@@ -365,7 +365,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
::v-deep .uni-scroll-view ::-webkit-scrollbar {
|
/deep/.uni-scroll-view ::-webkit-scrollbar {
|
||||||
/* 隐藏滚动条,但依旧具备可以滚动的功能 */
|
/* 隐藏滚动条,但依旧具备可以滚动的功能 */
|
||||||
display: none;
|
display: none;
|
||||||
width: 0;
|
width: 0;
|
||||||
@@ -374,7 +374,7 @@ export default {
|
|||||||
background: transparent;
|
background: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
::v-deep ::-webkit-scrollbar {
|
/deep/::-webkit-scrollbar {
|
||||||
display: none;
|
display: none;
|
||||||
width: 0;
|
width: 0;
|
||||||
height: 0;
|
height: 0;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<view data-component-name="diy-bottom-nav" v-if="tabBarList && tabBarList.list">
|
<view data-component-name="diy-bottom-nav" v-if="tabBarList && tabBarList.list">
|
||||||
<view class="tab-bar" :style="{ backgroundColor: tabBarList.backgroundColor }">
|
<view class="tab-bar" :style="{ backgroundColor: tabBarList.backgroundColor }">
|
||||||
<view class="tabbar-border"></view>
|
<view class="tabbar-border"></view>
|
||||||
<view class="item" v-for="(item, index) in tabBarList.list" :key="item.id" @tap.stop="redirectTo(item.link)">
|
<view class="item" v-for="(item, index) in tabBarList.list" :key="item.id" @click="redirectTo(item.link)">
|
||||||
<view class="bd">
|
<view class="bd">
|
||||||
<block v-if="item.link.wap_url == '/pages_goods/cart'">
|
<block v-if="item.link.wap_url == '/pages_goods/cart'">
|
||||||
<view class="icon" v-if="tabBarList.type == 1 || tabBarList.type == 2"
|
<view class="icon" v-if="tabBarList.type == 1 || tabBarList.type == 2"
|
||||||
@@ -59,7 +59,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { adaptSubpackageUrl, checkTabBarActive } from '@/common/js/util.js'
|
import { adaptSubpackageUrl } from '@/common/js/util.js'
|
||||||
import DiyMinx from './minx.js'
|
import DiyMinx from './minx.js'
|
||||||
// 底部导航栏
|
// 底部导航栏
|
||||||
export default {
|
export default {
|
||||||
@@ -145,16 +145,27 @@ export default {
|
|||||||
let linkUrl = link.wap_url;
|
let linkUrl = link.wap_url;
|
||||||
|
|
||||||
// 首页特殊处理
|
// 首页特殊处理
|
||||||
if (linkUrl === this.$util.INDEX_PAGE_URL && this.name === 'DIY_VIEW_INDEX') {
|
if (linkUrl === '/pages/index/index' && this.name === 'DIY_VIEW_INDEX') {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// console.log('diy-bottom-nav verify:', { likkUrl: adaptSubpackageUrl(linkUrl), currentPageRoute: currentPageRoute});
|
||||||
|
|
||||||
// 精确匹配当前路径
|
// 精确匹配当前路径
|
||||||
if (adaptSubpackageUrl(linkUrl) === currentPageRoute) {
|
if (adaptSubpackageUrl(linkUrl) === currentPageRoute) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return checkTabBarActive(linkUrl, currentPageRoute);
|
// 同属于一个子包的路径,也认为是匹配的
|
||||||
|
try {
|
||||||
|
if (adaptSubpackageUrl(linkUrl).split('/')[1] === currentPageRoute.split('/')[1]) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('diy-bottom-nav verify error:', error);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<view data-component-name="diy-category-item" class="item-wrap" :class="type">
|
<view data-component-name="diy-category-item" class="item-wrap" :class="type">
|
||||||
<block v-if="type == 'category' && category.child_list && category.child_list.length">
|
<block v-if="type == 'category' && category.child_list && category.child_list.length">
|
||||||
<view class="category-adv" v-if="category.image_adv" @tap.stop="diyRedirectTo(category.link_url)">
|
<view class="category-adv" v-if="category.image_adv" @click="diyRedirectTo(category.link_url)">
|
||||||
<image :src="$util.img(category.image_adv)" mode="widthFix" />
|
<image :src="$util.img(category.image_adv)" mode="widthFix" />
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
<view class="category-title">{{ category.category_name }}</view>
|
<view class="category-title">{{ category.category_name }}</view>
|
||||||
<view class="category-list">
|
<view class="category-list">
|
||||||
<view class="category-item" v-for="(one, oneIndex) in category.child_list" :key="oneIndex"
|
<view class="category-item" v-for="(one, oneIndex) in category.child_list" :key="oneIndex"
|
||||||
@tap.stop="$util.redirectTo('/pages_goods/list', { category_id: one.category_id })">
|
@click="$util.redirectTo('/pages_goods/list', { category_id: one.category_id })">
|
||||||
<view class="img-box">
|
<view class="img-box">
|
||||||
<image :src="$util.img(one.image)" mode="widthFix" />
|
<image :src="$util.img(one.image)" mode="widthFix" />
|
||||||
</view>
|
</view>
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
<view class="category-title">{{ one.category_name }}</view>
|
<view class="category-title">{{ one.category_name }}</view>
|
||||||
<view class="category-list">
|
<view class="category-list">
|
||||||
<view class="category-item" v-for="(two, twoIndex) in one.child_list" :key="twoIndex"
|
<view class="category-item" v-for="(two, twoIndex) in one.child_list" :key="twoIndex"
|
||||||
@tap.stop="$util.redirectTo('/pages_goods/list', { category_id: two.category_id })">
|
@click="$util.redirectTo('/pages_goods/list', { category_id: two.category_id })">
|
||||||
<view class="img-box">
|
<view class="img-box">
|
||||||
<image :src="$util.img(two.image)" mode="widthFix" :lazy-load="true" />
|
<image :src="$util.img(two.image)" mode="widthFix" :lazy-load="true" />
|
||||||
</view>
|
</view>
|
||||||
@@ -44,22 +44,22 @@
|
|||||||
:class="{ 'screen-category-4': value.template == 4 }" :scroll-with-animation="true"
|
:class="{ 'screen-category-4': value.template == 4 }" :scroll-with-animation="true"
|
||||||
:scroll-into-view="scrollIntoView">
|
:scroll-into-view="scrollIntoView">
|
||||||
<view class="item" id="category-2--1" :class="{ selected: categoryId == -1 }"
|
<view class="item" id="category-2--1" :class="{ selected: categoryId == -1 }"
|
||||||
@tap.stop="selectCategory(-1)">全部</view>
|
@click="selectCategory(-1)">全部</view>
|
||||||
<view class="item" :id="'category-2-' + oneIndex"
|
<view class="item" :id="'category-2-' + oneIndex"
|
||||||
:class="{ selected: categoryId == oneIndex }" @tap.stop="selectCategory(oneIndex)"
|
:class="{ selected: categoryId == oneIndex }" @click="selectCategory(oneIndex)"
|
||||||
v-for="(one, oneIndex) in category.child_list" :key="oneIndex">
|
v-for="(one, oneIndex) in category.child_list" :key="oneIndex">
|
||||||
{{ one.category_name }}
|
{{ one.category_name }}
|
||||||
</view>
|
</view>
|
||||||
</scroll-view>
|
</scroll-view>
|
||||||
<view class="iconfont icon-unfold" @tap.stop="$refs.screenCategoryPopup.open()"></view>
|
<view class="iconfont icon-unfold" @click="$refs.screenCategoryPopup.open()"></view>
|
||||||
</view>
|
</view>
|
||||||
<uni-popup type="top" ref="screenCategoryPopup">
|
<uni-popup type="top" ref="screenCategoryPopup">
|
||||||
<view class="screen-category-popup" @tap.stop="$refs.screenCategoryPopup.close()">
|
<view class="screen-category-popup" @click="$refs.screenCategoryPopup.close()">
|
||||||
<scroll-view scroll-y="true" class="screen-category"
|
<scroll-view scroll-y="true" class="screen-category"
|
||||||
:class="{ 'screen-category-4': value.template == 4 }">
|
:class="{ 'screen-category-4': value.template == 4 }">
|
||||||
<view class="title">全部</view>
|
<view class="title">全部</view>
|
||||||
<view class="item" :class="{ selected: categoryId == oneIndex }"
|
<view class="item" :class="{ selected: categoryId == oneIndex }"
|
||||||
@tap.stop="selectCategory(oneIndex)" v-for="(one, oneIndex) in category.child_list"
|
@click="selectCategory(oneIndex)" v-for="(one, oneIndex) in category.child_list"
|
||||||
:key="oneIndex">
|
:key="oneIndex">
|
||||||
{{ one.category_name }}
|
{{ one.category_name }}
|
||||||
</view>
|
</view>
|
||||||
@@ -81,13 +81,13 @@
|
|||||||
:data-template="value.template">
|
:data-template="value.template">
|
||||||
<block v-if="goodsList.length">
|
<block v-if="goodsList.length">
|
||||||
<view class="goods-item" v-for="(item, index) in goodsList" :key="index">
|
<view class="goods-item" v-for="(item, index) in goodsList" :key="index">
|
||||||
<view class="goods-img" @tap.stop="toDetail(item)">
|
<view class="goods-img" @click="toDetail(item)">
|
||||||
<image :src="goodsImg(item.goods_image)" mode="widthFix" @error="imgError(index)" />
|
<image :src="goodsImg(item.goods_image)" mode="widthFix" @error="imgError(index)" />
|
||||||
<view class="color-base-bg goods-tag" v-if="item.label_name">{{ item.label_name }}
|
<view class="color-base-bg goods-tag" v-if="item.label_name">{{ item.label_name }}
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="info-wrap">
|
<view class="info-wrap">
|
||||||
<view class="name-wrap" @tap.stop="toDetail(item)">
|
<view class="name-wrap" @click="toDetail(item)">
|
||||||
<view class="goods-name">{{ isEnEnv ? item.en_goods_name : item.goods_name }}</view>
|
<view class="goods-name">{{ isEnEnv ? item.en_goods_name : item.goods_name }}</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="price-wrap">
|
<view class="price-wrap">
|
||||||
@@ -100,7 +100,7 @@
|
|||||||
parseFloat(showPrice(item)).toFixed(2).split('.')[1] }}</text>
|
parseFloat(showPrice(item)).toFixed(2).split('.')[1] }}</text>
|
||||||
</block>
|
</block>
|
||||||
<block v-else>
|
<block v-else>
|
||||||
<text class="unit price-style small">{{ $lang('Make') ? $lang('Make') : '询底价' }}</text>
|
<text class="unit price-style small">{{ $lang('Make') ? $lang('Make') : '询价' }}</text>
|
||||||
</block>
|
</block>
|
||||||
</view>
|
</view>
|
||||||
<view class="member-price-tag"
|
<view class="member-price-tag"
|
||||||
@@ -122,25 +122,25 @@
|
|||||||
</view>
|
</view>
|
||||||
<!-- <view class="right-wrap" v-if="value.template == 2 || value.template == 4">
|
<!-- <view class="right-wrap" v-if="value.template == 2 || value.template == 4">
|
||||||
<block v-if="item.is_virtual">
|
<block v-if="item.is_virtual">
|
||||||
<view class="color-base-bg select-sku" @tap.stop="toDetail(item)">立即购买</view>
|
<view class="color-base-bg select-sku" @click="toDetail(item)">立即购买</view>
|
||||||
</block>
|
</block>
|
||||||
<block v-else>
|
<block v-else>
|
||||||
<view v-if="item.goods_spec_format" class="color-base-bg select-sku" @tap.stop="selectSku(item)">
|
<view v-if="item.goods_spec_format" class="color-base-bg select-sku" @click="selectSku(item)">
|
||||||
<text>选规格</text>
|
<text>选规格</text>
|
||||||
<text class="num-tag" v-if="item.num">{{ item.num }}</text>
|
<text class="num-tag" v-if="item.num">{{ item.num }}</text>
|
||||||
</view>
|
</view>
|
||||||
<block v-else>
|
<block v-else>
|
||||||
<block v-if="cartList['goods_' + item.goods_id]&&cartList['goods_' + item.goods_id]['sku_' + item.sku_id]">
|
<block v-if="cartList['goods_' + item.goods_id]&&cartList['goods_' + item.goods_id]['sku_' + item.sku_id]">
|
||||||
<view class="num-action reduce" @tap.stop="reduce(item)">
|
<view class="num-action reduce" @click="reduce(item)">
|
||||||
<text class="iconfont icon-jian"></text>
|
<text class="iconfont icon-jian"></text>
|
||||||
</view>
|
</view>
|
||||||
<view class="num">{{ cartList['goods_' + item.goods_id]['sku_' + item.sku_id].num }}</view>
|
<view class="num">{{ cartList['goods_' + item.goods_id]['sku_' + item.sku_id].num }}</view>
|
||||||
<view class="num-action" :id="'cart-num-' + index" @tap.stop="increase($event, item)">
|
<view class="num-action" :id="'cart-num-' + index" @click="increase($event, item)">
|
||||||
<text class="iconfont icon-jia"></text>
|
<text class="iconfont icon-jia"></text>
|
||||||
<view class="click-event"></view>
|
<view class="click-event"></view>
|
||||||
</view>
|
</view>
|
||||||
</block>
|
</block>
|
||||||
<view class="num-action" v-else :id="'cart-num-' + index" @tap.stop="increase($event, item, 0)">
|
<view class="num-action" v-else :id="'cart-num-' + index" @click="increase($event, item, 0)">
|
||||||
<text class="iconfont icon-jia"></text>
|
<text class="iconfont icon-jia"></text>
|
||||||
<view class="click-event"></view>
|
<view class="click-event"></view>
|
||||||
</view>
|
</view>
|
||||||
@@ -148,7 +148,7 @@
|
|||||||
</block>
|
</block>
|
||||||
</view> -->
|
</view> -->
|
||||||
<!-- <view class="right-wrap" v-if="value.template == 3">
|
<!-- <view class="right-wrap" v-if="value.template == 3">
|
||||||
<view class="color-base-bg select-sku" @tap.stop="toDetail(item)">立即购买</view>
|
<view class="color-base-bg select-sku" @click="toDetail(item)">立即购买</view>
|
||||||
</view> -->
|
</view> -->
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@@ -158,7 +158,7 @@
|
|||||||
<image :src="$util.img('public/uniapp/category/empty.png')" mode="widthFix" />
|
<image :src="$util.img('public/uniapp/category/empty.png')" mode="widthFix" />
|
||||||
</view>
|
</view>
|
||||||
<!-- <view class="end-tips" ref="endTips" v-if="last && (categoryId == -1 || !category.child_list || (category.child_list && categoryId == category.child_list.length - 1))">已经到底了~</view>
|
<!-- <view class="end-tips" ref="endTips" v-if="last && (categoryId == -1 || !category.child_list || (category.child_list && categoryId == category.child_list.length - 1))">已经到底了~</view>
|
||||||
<view class="end-tips" ref="endTips" v-else @tap.stop="switchCategory('next')">
|
<view class="end-tips" ref="endTips" v-else @click="switchCategory('next')">
|
||||||
<text class="iconfont icon-xiangshangzhanhang"></text>
|
<text class="iconfont icon-xiangshangzhanhang"></text>
|
||||||
上滑查看下一分类
|
上滑查看下一分类
|
||||||
</view> -->
|
</view> -->
|
||||||
@@ -173,13 +173,13 @@
|
|||||||
<view class="goods-list" :class="{ 'double-column': !isList, 'single-column': isList }"
|
<view class="goods-list" :class="{ 'double-column': !isList, 'single-column': isList }"
|
||||||
:data-template="value.template">
|
:data-template="value.template">
|
||||||
<view class="goods-item" v-for="(item, index) in goodsList" :key="index">
|
<view class="goods-item" v-for="(item, index) in goodsList" :key="index">
|
||||||
<view class="goods-img" @tap.stop="toDetail(item)">
|
<view class="goods-img" @click="toDetail(item)">
|
||||||
<image :src="goodsImg(item.goods_image)" mode="widthFix" @error="imgError(index)"
|
<image :src="goodsImg(item.goods_image)" mode="widthFix" @error="imgError(index)"
|
||||||
:lazy-load="true" />
|
:lazy-load="true" />
|
||||||
<view class="color-base-bg goods-tag" v-if="item.label_name">{{ item.label_name }}</view>
|
<view class="color-base-bg goods-tag" v-if="item.label_name">{{ item.label_name }}</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="info-wrap">
|
<view class="info-wrap">
|
||||||
<view class="name-wrap" @tap.stop="toDetail(item)">
|
<view class="name-wrap" @click="toDetail(item)">
|
||||||
<view class="goods-name">{{ isEnEnv ? item.en_goods_name : item.goods_name }}</view>
|
<view class="goods-name">{{ isEnEnv ? item.en_goods_name : item.goods_name }}</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="price-wrap">
|
<view class="price-wrap">
|
||||||
@@ -192,7 +192,7 @@
|
|||||||
parseFloat(showPrice(item)).toFixed(2).split('.')[1] }}</text>
|
parseFloat(showPrice(item)).toFixed(2).split('.')[1] }}</text>
|
||||||
</block>
|
</block>
|
||||||
<block v-else>
|
<block v-else>
|
||||||
<text class="unit price-style small">{{ $lang('Make') ? $lang('Make') : '询底价' }}</text>
|
<text class="unit price-style small">{{ $lang('Make') ? $lang('Make') : '询价' }}</text>
|
||||||
</block>
|
</block>
|
||||||
|
|
||||||
</view>
|
</view>
|
||||||
@@ -214,30 +214,30 @@
|
|||||||
</view>
|
</view>
|
||||||
<view class="right-wrap" v-if="value.template == 2">
|
<view class="right-wrap" v-if="value.template == 2">
|
||||||
<block v-if="item.is_virtual">
|
<block v-if="item.is_virtual">
|
||||||
<view class="color-base-bg select-sku" @tap.stop="toDetail(item)">立即购买</view>
|
<view class="color-base-bg select-sku" @click="toDetail(item)">立即购买</view>
|
||||||
</block>
|
</block>
|
||||||
<block v-else>
|
<block v-else>
|
||||||
<view v-if="item.goods_spec_format" class="color-base-bg select-sku"
|
<view v-if="item.goods_spec_format" class="color-base-bg select-sku"
|
||||||
@tap.stop="selectSku(item)">
|
@click="selectSku(item)">
|
||||||
<text>选规格</text>
|
<text>选规格</text>
|
||||||
<text class="num-tag" v-if="item.num">{{ item.num }}</text>
|
<text class="num-tag" v-if="item.num">{{ item.num }}</text>
|
||||||
</view>
|
</view>
|
||||||
<block v-else>
|
<block v-else>
|
||||||
<block
|
<block
|
||||||
v-if="cartList['goods_' + item.goods_id] && cartList['goods_' + item.goods_id]['sku_' + item.sku_id]">
|
v-if="cartList['goods_' + item.goods_id] && cartList['goods_' + item.goods_id]['sku_' + item.sku_id]">
|
||||||
<view class="num-action reduce" @tap.stop="reduce(item)">
|
<view class="num-action reduce" @click="reduce(item)">
|
||||||
<text class="iconfont icon-jian"></text>
|
<text class="iconfont icon-jian"></text>
|
||||||
</view>
|
</view>
|
||||||
<view class="num">{{ cartList['goods_' + item.goods_id]['sku_' +
|
<view class="num">{{ cartList['goods_' + item.goods_id]['sku_' +
|
||||||
item.sku_id].num }}</view>
|
item.sku_id].num }}</view>
|
||||||
<view class="num-action" :id="'cart-num-' + index"
|
<view class="num-action" :id="'cart-num-' + index"
|
||||||
@tap.stop="increase($event, item)">
|
@click="increase($event, item)">
|
||||||
<text class="iconfont icon-jia"></text>
|
<text class="iconfont icon-jia"></text>
|
||||||
<view class="click-event"></view>
|
<view class="click-event"></view>
|
||||||
</view>
|
</view>
|
||||||
</block>
|
</block>
|
||||||
<view class="num-action" v-else :id="'cart-num-' + index"
|
<view class="num-action" v-else :id="'cart-num-' + index"
|
||||||
@tap.stop="increase($event, item, 0)">
|
@click="increase($event, item, 0)">
|
||||||
<text class="iconfont icon-jia"></text>
|
<text class="iconfont icon-jia"></text>
|
||||||
<view class="click-event"></view>
|
<view class="click-event"></view>
|
||||||
</view>
|
</view>
|
||||||
@@ -245,7 +245,7 @@
|
|||||||
</block>
|
</block>
|
||||||
</view>
|
</view>
|
||||||
<view class="right-wrap" v-if="value.template == 3">
|
<view class="right-wrap" v-if="value.template == 3">
|
||||||
<view class="color-base-bg select-sku" @tap.stop="toDetail(item)">立即购买</view>
|
<view class="color-base-bg select-sku" @click="toDetail(item)">立即购买</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@@ -1160,7 +1160,7 @@ export default {
|
|||||||
.right-wrap {
|
.right-wrap {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: flex-end;
|
justify-content: end;
|
||||||
|
|
||||||
.num {
|
.num {
|
||||||
width: auto;
|
width: auto;
|
||||||
@@ -1314,7 +1314,7 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
::v-deep .uni-popup__wrapper-box {
|
/deep/ .uni-popup__wrapper-box {
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1348,7 +1348,7 @@ export default {
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
::v-deep .loading-layer {
|
/deep/ .loading-layer {
|
||||||
background: #fff !important;
|
background: #fff !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,9 +3,9 @@
|
|||||||
:style="{ height: 'calc(100vh - ' + tabBarHeight + ')' }">
|
:style="{ height: 'calc(100vh - ' + tabBarHeight + ')' }">
|
||||||
<!-- #ifdef MP-WEIXIN -->
|
<!-- #ifdef MP-WEIXIN -->
|
||||||
<!-- <block v-if="value.template == 4">
|
<!-- <block v-if="value.template == 4">
|
||||||
<view class="search-box" v-if="value.search" @tap.stop="$util.redirectTo('/pages_tool/goods/search')" :style="navbarInnerStyle">
|
<view class="search-box" v-if="value.search" @click="$util.redirectTo('/pages_tool/goods/search')" :style="navbarInnerStyle">
|
||||||
<view class="search-content">
|
<view class="search-content">
|
||||||
<input type="text" class="uni-input font-size-tag" maxlength="50" :placeholder="$lang('search')" confirm-type="search" @tap.stop="onClickSearch()" disabled="true" />
|
<input type="text" class="uni-input font-size-tag" maxlength="50" :placeholder="$lang('search')" confirm-type="search" @click.stop="onClickSearch()" @tap.stop="onClickSearch()" disabled="true" />
|
||||||
<text class="iconfont icon-sousuo3"></text>
|
<text class="iconfont icon-sousuo3"></text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@@ -13,35 +13,35 @@
|
|||||||
</block> -->
|
</block> -->
|
||||||
<block v-if="value.template != 4">
|
<block v-if="value.template != 4">
|
||||||
<!-- <view :style="navbarInnerStyle">商品分类</view> -->
|
<!-- <view :style="navbarInnerStyle">商品分类</view> -->
|
||||||
<view class="search-box" v-if="value.search" @tap.stop="onClickSearch()"
|
<view class="search-box" v-if="value.search" @click="onClickSearch()" @tap.stop="onClickSearch()"
|
||||||
:style="wxSearchHeight">
|
:style="wxSearchHeight">
|
||||||
<view class="search-content">
|
<view class="search-content">
|
||||||
<input type="text" class="uni-input" maxlength="50" :placeholder="$lang('search')"
|
<input type="text" class="uni-input" maxlength="50" :placeholder="$lang('search')"
|
||||||
confirm-type="search" @tap.stop="onClickSearch()"
|
confirm-type="search" @click.stop="onClickSearch()" @tap.stop="onClickSearch()"
|
||||||
disabled="true" />
|
disabled="true" />
|
||||||
<text class="iconfont icon-sousuo3"></text>
|
<text class="iconfont icon-sousuo3"></text>
|
||||||
</view>
|
</view>
|
||||||
<view class="iconfont" :class="{ 'icon-apps': !isList, 'icon-list': isList }"
|
<view class="iconfont" :class="{ 'icon-apps': !isList, 'icon-list': isList }"
|
||||||
@tap.stop.prevent="changeListStyle()"></view>
|
@click.stop.prevent="changeListStyle()"></view>
|
||||||
</view>
|
</view>
|
||||||
</block>
|
</block>
|
||||||
<!-- #endif -->
|
<!-- #endif -->
|
||||||
<!-- #ifdef H5 -->
|
<!-- #ifdef H5 -->
|
||||||
<view class="search-box" v-if="value.search" @tap.stop="onClickSearch()">
|
<view class="search-box" v-if="value.search" @click="onClickSearch()" @tap.stop="onClickSearch()">
|
||||||
<view class="search-content">
|
<view class="search-content">
|
||||||
<input type="text" class="uni-input" maxlength="50" :placeholder="$lang('search')" confirm-type="search"
|
<input type="text" class="uni-input" maxlength="50" :placeholder="$lang('search')" confirm-type="search"
|
||||||
@tap.stop="onClickSearch()" disabled="true" />
|
@click.stop="onClickSearch()" @tap.stop="onClickSearch()" disabled="true" />
|
||||||
<text class="iconfont icon-sousuo3"></text>
|
<text class="iconfont icon-sousuo3"></text>
|
||||||
</view>
|
</view>
|
||||||
<view class="iconfont" :class="{ 'icon-apps': !isList, 'icon-list': isList }"
|
<view class="iconfont" :class="{ 'icon-apps': !isList, 'icon-list': isList }"
|
||||||
@tap.stop.prevent="changeListStyle()"></view>
|
@click.stop.prevent="changeListStyle()"></view>
|
||||||
</view>
|
</view>
|
||||||
<!-- #endif -->
|
<!-- #endif -->
|
||||||
<view class="template-four wx" v-if="value.template == 4">
|
<view class="template-four wx" v-if="value.template == 4">
|
||||||
<scroll-view scroll-x="true" class="template-four-wrap" :scroll-with-animation="true"
|
<scroll-view scroll-x="true" class="template-four-wrap" :scroll-with-animation="true"
|
||||||
:scroll-into-view="'category-one-' + oneCategorySelect" enable-flex="true">
|
:scroll-into-view="'category-one-' + oneCategorySelect" enable-flex="true">
|
||||||
<view class="category-item" :id="'category-one-' + index" v-for="(item, index) in templateFourData"
|
<view class="category-item" :id="'category-one-' + index" v-for="(item, index) in templateFourData"
|
||||||
:key="index" :class="{ select: oneCategorySelect == index }" @tap.stop="templateFourOneFn(index)">
|
:key="index" :class="{ select: oneCategorySelect == index }" @click="templateFourOneFn(index)">
|
||||||
<view class="image-warp" :class="[{ 'color-base-border': oneCategorySelect == index }]">
|
<view class="image-warp" :class="[{ 'color-base-border': oneCategorySelect == index }]">
|
||||||
<image :src="$util.img(item.image)" mode="aspectFill" />
|
<image :src="$util.img(item.image)" mode="aspectFill" />
|
||||||
</view>
|
</view>
|
||||||
@@ -49,7 +49,7 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</scroll-view>
|
</scroll-view>
|
||||||
<view class="category-item-all" @tap.stop="$refs.templateFourPopup.open()">
|
<view class="category-item-all" @click="$refs.templateFourPopup.open()">
|
||||||
<view class="category-item-all-wrap">
|
<view class="category-item-all-wrap">
|
||||||
<text class="text">展开</text>
|
<text class="text">展开</text>
|
||||||
<image class="img" :src="$util.img('/public/uniapp/category/unfold.png')" mode="aspectFill"></image>
|
<image class="img" :src="$util.img('/public/uniapp/category/unfold.png')" mode="aspectFill"></image>
|
||||||
@@ -59,7 +59,7 @@
|
|||||||
<view class="template-four-popup">
|
<view class="template-four-popup">
|
||||||
<scroll-view scroll-y="true" class="template-four-scroll" enable-flex="true">
|
<scroll-view scroll-y="true" class="template-four-scroll" enable-flex="true">
|
||||||
<view class="item" :class="{ selected: oneCategorySelect == index }"
|
<view class="item" :class="{ selected: oneCategorySelect == index }"
|
||||||
@tap.stop="templateFourOneFn(index)" v-for="(item, index) in templateFourData" :key="index">
|
@click="templateFourOneFn(index)" v-for="(item, index) in templateFourData" :key="index">
|
||||||
<view class="image-warp" :class="[{ 'color-base-border': oneCategorySelect == index }]">
|
<view class="image-warp" :class="[{ 'color-base-border': oneCategorySelect == index }]">
|
||||||
<image :src="$util.img(item.image)" mode="aspectFill"></image>
|
<image :src="$util.img(item.image)" mode="aspectFill"></image>
|
||||||
</view>
|
</view>
|
||||||
@@ -67,7 +67,7 @@
|
|||||||
item.category_name }}</view>
|
item.category_name }}</view>
|
||||||
</view>
|
</view>
|
||||||
</scroll-view>
|
</scroll-view>
|
||||||
<view class="pack-up" @tap.stop="$refs.templateFourPopup.close()">
|
<view class="pack-up" @click="$refs.templateFourPopup.close()">
|
||||||
<text>点击收起</text>
|
<text>点击收起</text>
|
||||||
<text class="iconfont icon-iconangledown-copy"></text>
|
<text class="iconfont icon-iconangledown-copy"></text>
|
||||||
</view>
|
</view>
|
||||||
@@ -83,7 +83,7 @@
|
|||||||
{ select: select == index },
|
{ select: select == index },
|
||||||
{ 'border-bottom': value.template == 4 && select + 1 === index },
|
{ 'border-bottom': value.template == 4 && select + 1 === index },
|
||||||
{ 'border-top': value.template == 4 && select - 1 === index }
|
{ 'border-top': value.template == 4 && select - 1 === index }
|
||||||
]" @tap.stop="switchOneCategory(index)">
|
]" @click="switchOneCategory(index)">
|
||||||
<view class="">{{ item.category_name }}</view>
|
<view class="">{{ item.category_name }}</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@@ -130,7 +130,7 @@
|
|||||||
|
|
||||||
<!-- <view class="cart-box" v-if="(value.template == 2 || value.template == 4) && value.quickBuy && storeToken && categoryTree && categoryTree.length">
|
<!-- <view class="cart-box" v-if="(value.template == 2 || value.template == 4) && value.quickBuy && storeToken && categoryTree && categoryTree.length">
|
||||||
<view class="left-wrap">
|
<view class="left-wrap">
|
||||||
<view class="cart-icon" ref="cartIcon" :animation="cartAnimation" @tap.stop="$util.redirectTo('/pages_goods/cart')">
|
<view class="cart-icon" ref="cartIcon" :animation="cartAnimation" @click="$util.redirectTo('/pages_goods/cart')">
|
||||||
<text class="iconfont icon-ziyuan1"></text>
|
<text class="iconfont icon-ziyuan1"></text>
|
||||||
<view class="num" v-if="cartNumber">{{ cartNumber < 99 ? cartNumber : '99+' }}</view>
|
<view class="num" v-if="cartNumber">{{ cartNumber < 99 ? cartNumber : '99+' }}</view>
|
||||||
</view>
|
</view>
|
||||||
@@ -141,7 +141,7 @@
|
|||||||
<text class="unit font-size-tag price-font">.{{ cartTotalMoney[1] ? cartTotalMoney[1] : '00' }}</text>
|
<text class="unit font-size-tag price-font">.{{ cartTotalMoney[1] ? cartTotalMoney[1] : '00' }}</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="right-wrap"><button type="primary" class="settlement-btn" @tap.stop="settlement">去结算</button>
|
<view class="right-wrap"><button type="primary" class="settlement-btn" @click="settlement">去结算</button>
|
||||||
</view>
|
</view>
|
||||||
</view> -->
|
</view> -->
|
||||||
|
|
||||||
@@ -161,11 +161,15 @@ let menuButtonInfo = {};
|
|||||||
menuButtonInfo = uni.getMenuButtonBoundingClientRect();
|
menuButtonInfo = uni.getMenuButtonBoundingClientRect();
|
||||||
// #endif
|
// #endif
|
||||||
|
|
||||||
|
import nsGoodsSkuCategory from '@/components/ns-goods-sku/ns-goods-sku-category.vue';
|
||||||
import DiyMinx from './minx.js'
|
import DiyMinx from './minx.js'
|
||||||
var contentWrapHeight, query, cartPosition;
|
var contentWrapHeight, query, cartPosition;
|
||||||
|
|
||||||
// 商品分类
|
// 商品分类
|
||||||
export default {
|
export default {
|
||||||
|
components: {
|
||||||
|
nsGoodsSkuCategory
|
||||||
|
},
|
||||||
name: 'diy-category',
|
name: 'diy-category',
|
||||||
props: {
|
props: {
|
||||||
value: {
|
value: {
|
||||||
@@ -548,7 +552,7 @@ export default {
|
|||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss">
|
||||||
.category-page-wrap {
|
.category-page-wrap {
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
// height: calc(100vh - var(--tab-bar-height, 0));
|
// height: calc(100vh - var(--tab-bar-height, 0));
|
||||||
@@ -818,7 +822,7 @@ export default {
|
|||||||
z-index: 2;
|
z-index: 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
::v-deep .template-four {
|
/deep/ .template-four {
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
|
|
||||||
|
|||||||
@@ -1,645 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view class="channel-list-container" :style="[componentStyle, { '--row-count': value.rowCount }]">
|
|
||||||
<!-- 轮播模式 -->
|
|
||||||
<swiper v-if="value.showStyle == 'carousel' && carouselConfig.type != 'hide'" :indicator-dots="isIndicatorDots"
|
|
||||||
:autoplay="carouselConfig.autoplay || false" :interval="carouselConfig.interval || 3000"
|
|
||||||
:duration="carouselConfig.duration || 500" :circular="carouselConfig.circular || false"
|
|
||||||
:style="swiperHeight" class="channel-swiper">
|
|
||||||
<swiper-item v-for="(slide, slideIndex) in swiperSlides" :key="slideIndex">
|
|
||||||
<view :class="['swiper-slide-content', 'row1-of' + value.rowCount]">
|
|
||||||
<view v-for="(item, index) in slide" :key="index" :class="['channel-item', value.mode]">
|
|
||||||
<!-- 视频号视频卡片,轮播模式 -->
|
|
||||||
<diy-channel-video :value="item" @video-play="playVideo" :list-mode="true"
|
|
||||||
:title-line-clamp="value.titleLineClamp" :show-play-btn="value.showPlayBtn"
|
|
||||||
:show-view-count="value.showViewCount" :cover-style="computedCoverStyle"
|
|
||||||
:play-btn-style="value.playBtnStyle" :aspect-ratio="value.aspectRatio" />
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</swiper-item>
|
|
||||||
</swiper>
|
|
||||||
|
|
||||||
<!-- 固定布局模式 -->
|
|
||||||
<view v-else-if="value.showStyle == 'fixed'" :class="['channel-list', 'row1-of' + value.rowCount]">
|
|
||||||
<view v-for="(item, index) in value.list" :key="index" class="channel-item">
|
|
||||||
<!-- 视频号视频卡片,列表模式 -->
|
|
||||||
<diy-channel-video :value="item" @video-play="playVideo" :list-mode="true"
|
|
||||||
:title-line-clamp="value.titleLineClamp" :show-play-btn="value.showPlayBtn"
|
|
||||||
:show-view-count="value.showViewCount" :cover-style="computedCoverStyle"
|
|
||||||
:play-btn-style="value.playBtnStyle" :aspect-ratio="value.aspectRatio" />
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- 其他布局模式(如滚动布局) -->
|
|
||||||
<scroll-view v-else
|
|
||||||
:class="['channel-nav', value.showStyle == 'fixed' ? 'fixed-layout' : 'singleSlide', 'row1-of' + value.rowCount]"
|
|
||||||
:scroll-x="true"
|
|
||||||
:scroll-y="false"
|
|
||||||
:enhanced="true"
|
|
||||||
:bounces="false">
|
|
||||||
<view class="uni-scroll-view-content">
|
|
||||||
<view v-for="(item, index) in value.list" :key="index"
|
|
||||||
:class="['channel-nav-item', value.mode, 'row1-of' + value.rowCount]">
|
|
||||||
<!-- 视频号视频卡片,滚动模式 -->
|
|
||||||
<diy-channel-video :value="item" @video-play="playVideo" :list-mode="true"
|
|
||||||
:title-line-clamp="value.titleLineClamp" :show-play-btn="value.showPlayBtn"
|
|
||||||
:show-view-count="value.showViewCount" :cover-style="computedCoverStyle"
|
|
||||||
:play-btn-style="value.playBtnStyle" :aspect-ratio="value.aspectRatio" />
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</scroll-view>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
/**
|
|
||||||
* 微信视频号列表组件
|
|
||||||
* 支持多种布局模式,包括固定布局和滚动布局
|
|
||||||
* 可配置列数、视频高度、标题行数等属性
|
|
||||||
* 用于在页面中展示多个微信视频号视频
|
|
||||||
*/
|
|
||||||
import DiyMinx from './minx.js'
|
|
||||||
import { wechatChannelUtil, wechatChannelConfig } from './js/wechat-channel.js'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'diy-channel-list',
|
|
||||||
props: {
|
|
||||||
/**
|
|
||||||
* 组件配置数据
|
|
||||||
* @type {Object}
|
|
||||||
* @default () => ({})
|
|
||||||
* @property {string} showStyle - 显示样式,可选值:carousel, fixed, singleSlide
|
|
||||||
* @property {number} rowCount - 每行显示的视频数量
|
|
||||||
* @property {Array} list - 视频列表数据
|
|
||||||
* @property {string} componentBgColor - 组件背景色
|
|
||||||
* @property {string} componentAngle - 组件圆角类型,可选值:round
|
|
||||||
* @property {number} topAroundRadius - 顶部圆角半径
|
|
||||||
* @property {number} bottomAroundRadius - 底部圆角半径
|
|
||||||
* @property {Object} ornament - 装饰效果配置
|
|
||||||
* @property {boolean} showViewCount - 是否显示播放量,可选值:true, false
|
|
||||||
* @property {number} titleLineClamp - 标题显示行数
|
|
||||||
* @property {string} aspectRatio - 视频比例,可选值:16:9, 3:4
|
|
||||||
* @property {boolean} showPlayBtn - 是否显示播放按钮
|
|
||||||
* @property {Object} coverStyle - 视频封面图样式
|
|
||||||
* @property {Object} playBtnStyle - 播放按钮样式
|
|
||||||
* @property {string} mode - 显示模式, 可选值:video, text, image, graphic
|
|
||||||
* @property {number} imageSize - 图片尺寸(仅在特定模式下使用)
|
|
||||||
* @property {number} pageCount - 每页显示的视频数量
|
|
||||||
* @property {Object} carousel - 轮播配置
|
|
||||||
* @property {string} carousel.type - 轮播类型,可选值:default, hide
|
|
||||||
* @property {boolean} carousel.autoplay - 是否自动播放,默认false
|
|
||||||
* @property {number} carousel.interval - 自动播放间隔,默认3000ms
|
|
||||||
* @property {number} carousel.duration - 切换动画时长,默认500ms
|
|
||||||
* @property {boolean} carousel.circular - 是否循环播放,默认false
|
|
||||||
*/
|
|
||||||
value: {
|
|
||||||
type: Object,
|
|
||||||
default: () => ({})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mixins: [DiyMinx],
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
pageWidth: '', // 页面宽度
|
|
||||||
indicatorDots: false, // 是否显示轮播指示器
|
|
||||||
swiperCurrent: 0 // 当前轮播索引
|
|
||||||
}
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
// 组件创建时的逻辑
|
|
||||||
// 可以在这里进行初始化操作,如获取页面宽度等
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
// 组件挂载后添加鼠标拖拽滚动功能
|
|
||||||
if (!['fixed', 'carousel'].includes(this.value?.showStyle)) {
|
|
||||||
this.$nextTick(() => {
|
|
||||||
this.addMouseDragScroll();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
/**
|
|
||||||
* 组件刷新监听
|
|
||||||
* 当组件需要刷新时触发
|
|
||||||
* @param {*} newValue - 新值
|
|
||||||
*/
|
|
||||||
componentRefresh(newValue) {
|
|
||||||
// 监听组件刷新
|
|
||||||
// 可以在这里处理组件刷新时的逻辑
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
carouselConfig() {
|
|
||||||
return this.value?.carousel || {
|
|
||||||
type: 'default',
|
|
||||||
autoplay: false,
|
|
||||||
interval: 3000,
|
|
||||||
duration: 500,
|
|
||||||
circular: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* 组件样式
|
|
||||||
* 根据配置动态生成样式字符串,包括背景色、圆角、阴影和边框
|
|
||||||
* @returns {string} 样式字符串
|
|
||||||
*/
|
|
||||||
componentStyle() {
|
|
||||||
const style = {};
|
|
||||||
// 背景色
|
|
||||||
if (this.value?.componentBgColor) {
|
|
||||||
style.backgroundColor = this.value?.componentBgColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 圆角样式
|
|
||||||
if (this.value?.componentAngle == 'round') {
|
|
||||||
style.borderTopLeftRadius = (2 * this.value?.topAroundRadius) + 'rpx';
|
|
||||||
style.borderTopRightRadius = (2 * this.value?.topAroundRadius) + 'rpx';
|
|
||||||
style.borderBottomLeftRadius = (2 * this.value?.bottomAroundRadius) + 'rpx';
|
|
||||||
style.borderBottomRightRadius = (2 * this.value?.bottomAroundRadius) + 'rpx';
|
|
||||||
}
|
|
||||||
|
|
||||||
// 装饰效果:阴影
|
|
||||||
style.boxShadow = this.value?.ornament?.type == 'shadow' ? '0 0 10rpx ' + this.value?.ornament?.color : '';
|
|
||||||
// 装饰效果:边框
|
|
||||||
style.border = this.value?.ornament?.type == 'stroke' ? '2rpx solid ' + this.value?.ornament?.color : '';
|
|
||||||
|
|
||||||
return style;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 轮播高度
|
|
||||||
* 根据模式和配置计算轮播高度
|
|
||||||
* @returns {string} 轮播高度样式
|
|
||||||
*/
|
|
||||||
swiperHeight() {
|
|
||||||
let height = 0;
|
|
||||||
|
|
||||||
const pageCount = this.value?.pageCount || 1;
|
|
||||||
|
|
||||||
// 根据不同模式计算高度
|
|
||||||
if (this.value?.mode == 'graphic') {
|
|
||||||
height = (49 + this.value?.imageSize) * pageCount;
|
|
||||||
} else if (this.value?.mode == 'img') {
|
|
||||||
height = (22 + this.value?.imageSize) * pageCount;
|
|
||||||
} else if (this.value?.mode == 'text') {
|
|
||||||
height = 43 * pageCount;
|
|
||||||
} else { // 默认视频模式
|
|
||||||
if (this.value?.aspectRatio == '16:9') {
|
|
||||||
height = [250, 160, 140, 120][this.value.rowCount - 1];
|
|
||||||
} else {
|
|
||||||
height = [510, 280, 220, 180][this.value.rowCount - 1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 'height:' + (2 * height) + 'rpx';
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否显示指示器
|
|
||||||
* 根据轮播配置和列表长度判断是否显示指示器
|
|
||||||
* @returns {boolean} 是否显示指示器
|
|
||||||
*/
|
|
||||||
isIndicatorDots() {
|
|
||||||
// 当轮播类型不是隐藏,且视频数量超过一页时显示指示器
|
|
||||||
const pageCount = this.value?.pageCount || 1;
|
|
||||||
return this.value?.carousel?.type != 'hide' && Math.ceil(this.value?.list?.length / (pageCount * this.value?.rowCount)) > 1
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 轮播幻灯片数据
|
|
||||||
* 将视频列表分割成轮播所需的幻灯片数据
|
|
||||||
* @returns {Array} 轮播幻灯片数据
|
|
||||||
*/
|
|
||||||
swiperSlides() {
|
|
||||||
const slides = [];
|
|
||||||
const list = this.value?.list || [];
|
|
||||||
const pageSize = (this.value?.pageCount || 1) * (this.value?.rowCount || 1);
|
|
||||||
|
|
||||||
// 将列表数据分割成每页显示的数量
|
|
||||||
for (let i = 0; i < list.length; i += pageSize) {
|
|
||||||
slides.push(list.slice(i, i + pageSize));
|
|
||||||
}
|
|
||||||
|
|
||||||
return slides;
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* 视频封面样式
|
|
||||||
* 根据aspectRatio属性动态计算封面样式
|
|
||||||
* @returns {Object} 封面样式对象
|
|
||||||
*/
|
|
||||||
computedCoverStyle() {
|
|
||||||
const aspectRatio = this.value?.aspectRatio || '16:9';
|
|
||||||
let paddingTop = '56.25%'; // 默认 16:9 比例
|
|
||||||
|
|
||||||
if (aspectRatio === '3:4') {
|
|
||||||
paddingTop = '133.33%'; // 3:4 比例
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
width: '100%',
|
|
||||||
height: '0',
|
|
||||||
paddingTop: paddingTop
|
|
||||||
};
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
/**
|
|
||||||
* 播放视频
|
|
||||||
* 触发 video-play 事件,并在微信小程序中调用视频播放接口
|
|
||||||
* @param {Object} item - 视频数据对象
|
|
||||||
*/
|
|
||||||
async playVideo(item) {
|
|
||||||
await this.__$emitEvent({
|
|
||||||
eventName: 'video-play',
|
|
||||||
data: item,
|
|
||||||
promiseCallback: async (event, handler, awaitedResult) => {
|
|
||||||
if (!awaitedResult) return;
|
|
||||||
try {
|
|
||||||
// 发送视频被点击播放事件
|
|
||||||
this.$emit('channel-video-click-play', item);
|
|
||||||
console.log('播放视频:', item);
|
|
||||||
|
|
||||||
// #ifdef MP-WEIXIN
|
|
||||||
// 在微信小程序环境中调用视频播放接口
|
|
||||||
await wechatChannelUtil.playVideo(item);
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
// #ifndef MP-WEIXIN
|
|
||||||
if (item?.channelType === 'wechat') {
|
|
||||||
uni.showToast({
|
|
||||||
title: '视频号仅支持在微信小程序环境中播放',
|
|
||||||
icon: 'none',
|
|
||||||
duration: 2000
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// 在非微信小程序环境中,直接触发事件
|
|
||||||
this.$emit('video-play', item);
|
|
||||||
}
|
|
||||||
// #endif
|
|
||||||
} catch (err) {
|
|
||||||
console.error('打开视频号失败', err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 图片加载错误处理
|
|
||||||
* 当图片加载失败时,设置默认图片
|
|
||||||
* @param {number} index - 图片索引
|
|
||||||
*/
|
|
||||||
imgError(index) {
|
|
||||||
// 图片加载失败的处理逻辑
|
|
||||||
console.log('图片加载失败:', index);
|
|
||||||
// 为失败的图片设置默认图片
|
|
||||||
const item = this.value.list[index];
|
|
||||||
if (item) {
|
|
||||||
// 使用默认图片替代加载失败的图片
|
|
||||||
// #ifdef MP-WEIXIN
|
|
||||||
item.coverUrl = wechatChannelConfig.video.defaultCoverUrl;
|
|
||||||
// #endif
|
|
||||||
}
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* 添加鼠标拖拽滚动功能
|
|
||||||
* 在Web环境中实现与微信小程序相同的拖拽滚动效果
|
|
||||||
*/
|
|
||||||
addMouseDragScroll() {
|
|
||||||
// 只在Web环境中添加
|
|
||||||
// #ifndef MP
|
|
||||||
console.log('addMouseDragScroll called');
|
|
||||||
|
|
||||||
let isDragging = false;
|
|
||||||
let startX = 0;
|
|
||||||
let startScrollLeft = 0;
|
|
||||||
let currentScrollElement = null;
|
|
||||||
|
|
||||||
// 查找最近的可滚动祖先元素
|
|
||||||
const findScrollableParent = (element) => {
|
|
||||||
while (element && element !== document) {
|
|
||||||
const style = window.getComputedStyle(element);
|
|
||||||
if (style.overflowX === 'auto' || style.overflowX === 'scroll') {
|
|
||||||
return element;
|
|
||||||
}
|
|
||||||
element = element.parentElement;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
};
|
|
||||||
|
|
||||||
// 鼠标按下事件
|
|
||||||
const handleMouseDown = (e) => {
|
|
||||||
// 检查是否点击在组件内
|
|
||||||
if (this.$el.contains(e.target)) {
|
|
||||||
console.log('mousedown event in component:', e);
|
|
||||||
// 查找可滚动元素
|
|
||||||
currentScrollElement = findScrollableParent(e.target);
|
|
||||||
if (currentScrollElement) {
|
|
||||||
console.log('Found scrollable element:', currentScrollElement);
|
|
||||||
isDragging = true;
|
|
||||||
startX = e.pageX;
|
|
||||||
startScrollLeft = currentScrollElement.scrollLeft;
|
|
||||||
currentScrollElement.style.cursor = 'grabbing';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 鼠标移动事件
|
|
||||||
const handleMouseMove = (e) => {
|
|
||||||
if (!isDragging || !currentScrollElement) return;
|
|
||||||
console.log('mousemove event:', e);
|
|
||||||
e.preventDefault();
|
|
||||||
const dx = e.pageX - startX;
|
|
||||||
currentScrollElement.scrollLeft = startScrollLeft - dx;
|
|
||||||
console.log('scrollLeft:', currentScrollElement.scrollLeft);
|
|
||||||
};
|
|
||||||
|
|
||||||
// 鼠标释放事件
|
|
||||||
const handleMouseUp = () => {
|
|
||||||
if (isDragging && currentScrollElement) {
|
|
||||||
console.log('mouseup event');
|
|
||||||
currentScrollElement.style.cursor = 'grab';
|
|
||||||
}
|
|
||||||
isDragging = false;
|
|
||||||
currentScrollElement = null;
|
|
||||||
};
|
|
||||||
|
|
||||||
// 添加全局事件监听器
|
|
||||||
document.addEventListener('mousedown', handleMouseDown);
|
|
||||||
document.addEventListener('mousemove', handleMouseMove);
|
|
||||||
document.addEventListener('mouseup', handleMouseUp);
|
|
||||||
document.addEventListener('mouseleave', handleMouseUp);
|
|
||||||
|
|
||||||
console.log('Global mouse event listeners added');
|
|
||||||
|
|
||||||
// 组件销毁时移除事件监听器
|
|
||||||
this.$once('hook:beforeDestroy', () => {
|
|
||||||
document.removeEventListener('mousedown', handleMouseDown);
|
|
||||||
document.removeEventListener('mousemove', handleMouseMove);
|
|
||||||
document.removeEventListener('mouseup', handleMouseUp);
|
|
||||||
document.removeEventListener('mouseleave', handleMouseUp);
|
|
||||||
console.log('Global mouse event listeners removed');
|
|
||||||
});
|
|
||||||
|
|
||||||
// 为所有.channel-nav元素添加必要的样式
|
|
||||||
setTimeout(() => {
|
|
||||||
const channelNavs = document.querySelectorAll('.channel-nav');
|
|
||||||
console.log('Found channel-nav elements:', channelNavs.length);
|
|
||||||
channelNavs.forEach(element => {
|
|
||||||
element.style.overflowX = 'auto';
|
|
||||||
element.style.overflowY = 'hidden';
|
|
||||||
element.style.whiteSpace = 'nowrap';
|
|
||||||
element.style.width = '100%';
|
|
||||||
element.style.maxWidth = '100%';
|
|
||||||
element.style.cursor = 'grab';
|
|
||||||
element.style.userSelect = 'none'; // 防止文本选择
|
|
||||||
console.log('Added styles to channel-nav:', element);
|
|
||||||
});
|
|
||||||
}, 100); // 延迟执行,确保DOM已完全渲染
|
|
||||||
|
|
||||||
console.log('Mouse drag scroll setup completed');
|
|
||||||
// #endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
@import './css/common-channel.scss';
|
|
||||||
|
|
||||||
.channel-list-container {
|
|
||||||
padding: 16px 16px 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 列表布局样式
|
|
||||||
*/
|
|
||||||
.channel-list {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(var(--row-count, 2), 1fr);
|
|
||||||
gap: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 导航布局样式
|
|
||||||
* 支持固定布局和滚动布局
|
|
||||||
*/
|
|
||||||
.channel-nav {
|
|
||||||
box-sizing: border-box;
|
|
||||||
padding: 16rpx;
|
|
||||||
|
|
||||||
// 确保在H5环境中可以水平滚动
|
|
||||||
overflow-x: auto;
|
|
||||||
white-space: nowrap;
|
|
||||||
|
|
||||||
// 隐藏滚动条但保留滚动功能
|
|
||||||
::-webkit-scrollbar {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
scrollbar-width: none;
|
|
||||||
-ms-overflow-style: none;
|
|
||||||
|
|
||||||
// 启用触摸滚动和鼠标拖拽滚动
|
|
||||||
-webkit-overflow-scrolling: touch;
|
|
||||||
scroll-behavior: smooth;
|
|
||||||
|
|
||||||
.uni-scroll-view-content {
|
|
||||||
/* #ifdef MP-WEIXIN */
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: nowrap;
|
|
||||||
gap: 16rpx;
|
|
||||||
/* #endif */
|
|
||||||
/* #ifndef MP-WEIXIN */
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(var(--row-count, 2), 1fr);
|
|
||||||
gap: 16rpx;
|
|
||||||
/* #endif */
|
|
||||||
}
|
|
||||||
|
|
||||||
// 单滑动模式
|
|
||||||
&.singleSlide {
|
|
||||||
.uni-scroll-view-content {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: nowrap;
|
|
||||||
gap: 16rpx;
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.channel-nav-item {
|
|
||||||
flex-shrink: 0;
|
|
||||||
width: 280rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.channel-nav-item {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
box-sizing: border-box;
|
|
||||||
|
|
||||||
/* #ifdef MP-WEIXIN */
|
|
||||||
&.row1-of1 {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
&.row1-of2 {
|
|
||||||
width: calc(50% - 8rpx);
|
|
||||||
}
|
|
||||||
&.row1-of3 {
|
|
||||||
width: calc(33.333% - 10.67rpx);
|
|
||||||
}
|
|
||||||
&.row1-of4 {
|
|
||||||
width: calc(25% - 12rpx);
|
|
||||||
}
|
|
||||||
/* #endif */
|
|
||||||
}
|
|
||||||
|
|
||||||
// 1 列布局
|
|
||||||
&.row1-of1 {
|
|
||||||
.uni-scroll-view-content {
|
|
||||||
// #ifndef MP-WEIXIN
|
|
||||||
grid-template-columns: 1fr;
|
|
||||||
// #endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2 列布局
|
|
||||||
&.row1-of2 {
|
|
||||||
.uni-scroll-view-content {
|
|
||||||
// #ifndef MP-WEIXIN
|
|
||||||
grid-template-columns: repeat(2, 1fr);
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3 列布局
|
|
||||||
&.row1-of3 {
|
|
||||||
.uni-scroll-view-content {
|
|
||||||
// #ifndef MP-WEIXIN
|
|
||||||
grid-template-columns: repeat(3, 1fr);
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4 列布局
|
|
||||||
&.row1-of4 {
|
|
||||||
.uni-scroll-view-content {
|
|
||||||
// #ifndef MP-WEIXIN
|
|
||||||
grid-template-columns: repeat(4, 1fr);
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 确保所有视频卡片高度一致
|
|
||||||
*/
|
|
||||||
.channel-item,
|
|
||||||
.channel-nav-item {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 轮播样式
|
|
||||||
* 支持轮播模式的布局和样式
|
|
||||||
*/
|
|
||||||
.channel-swiper {
|
|
||||||
width: 100%;
|
|
||||||
box-sizing: border-box;
|
|
||||||
|
|
||||||
.swiper-slide-content {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(var(--row-count, 2), 1fr);
|
|
||||||
gap: 16rpx;
|
|
||||||
box-sizing: border-box;
|
|
||||||
|
|
||||||
.channel-item {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 轮播模式下的 1 列布局
|
|
||||||
&.row1-of1 {
|
|
||||||
grid-template-columns: 1fr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 轮播模式下的 2 列布局
|
|
||||||
&.row1-of2 {
|
|
||||||
grid-template-columns: repeat(2, 1fr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 轮播模式下的 3 列布局
|
|
||||||
&.row1-of3 {
|
|
||||||
grid-template-columns: repeat(3, 1fr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 轮播模式下的 4 列布局
|
|
||||||
&.row1-of4 {
|
|
||||||
grid-template-columns: repeat(4, 1fr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 响应式调整
|
|
||||||
* 在小屏幕设备上调整布局和间距
|
|
||||||
*/
|
|
||||||
@media (max-width: 375px) {
|
|
||||||
|
|
||||||
.channel-list,
|
|
||||||
.channel-nav,
|
|
||||||
.channel-swiper .swiper-slide-content {
|
|
||||||
gap: 12rpx;
|
|
||||||
padding: 12rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 小屏幕上的单滑动模式
|
|
||||||
.channel-nav {
|
|
||||||
&.singleSlide {
|
|
||||||
.uni-scroll-view-content {
|
|
||||||
gap: 12rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.channel-nav-item {
|
|
||||||
width: 240rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 视频比例样式调整
|
|
||||||
* 根据不同的视频比例调整布局
|
|
||||||
*/
|
|
||||||
|
|
||||||
// // 3:4 比例的视频卡片样式
|
|
||||||
// .channel-video.ratio-3-4 {
|
|
||||||
// // 调整视频卡片的整体高度
|
|
||||||
// ::v-deep .video-cover-wrap {
|
|
||||||
// padding-top: 133.33%; // 3:4 比例
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // 列表模式下的3:4比例调整
|
|
||||||
// &.list-mode {
|
|
||||||
// ::v-deep .video-cover-wrap {
|
|
||||||
// padding-top: 133.33%; // 3:4 比例
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // 16:9 比例的视频卡片样式(默认)
|
|
||||||
// .channel-video.ratio-16-9 {
|
|
||||||
// // 保持默认的16:9比例
|
|
||||||
// ::v-deep .video-cover-wrap {
|
|
||||||
// padding-top: 56.25%; // 16:9 比例
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // 列表模式下的16:9比例保持默认
|
|
||||||
// &.list-mode {
|
|
||||||
// ::v-deep .video-cover-wrap {
|
|
||||||
// padding-top: 56.25%; // 16:9 比例
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }</style>
|
|
||||||
@@ -1,489 +0,0 @@
|
|||||||
<template>
|
|
||||||
<view class="channel-video" :class="{ 'list-mode': listMode }">
|
|
||||||
<!-- 嵌入式视频播放 -->
|
|
||||||
<view v-if="canUseEmbedMode" class="embed-video-container">
|
|
||||||
<view class="video-cover-wrap" :style="[coverStyle]">
|
|
||||||
<!-- #ifdef MP-WEIXIN -->
|
|
||||||
<native-component>
|
|
||||||
<!-- 嵌入式视频播放组件 -->
|
|
||||||
<channel-video :feed-id="value.feedId" :finder-user-name="value.finderUserName"
|
|
||||||
:feed-token="value.feedToken" :auto-play="autoPlay">
|
|
||||||
</channel-video>
|
|
||||||
</native-component>
|
|
||||||
<!-- #endif -->
|
|
||||||
</view>
|
|
||||||
<view class="video-info">
|
|
||||||
<!-- 视频标题,支持多行显示控制 -->
|
|
||||||
<view class="video-title" :style="{ '--title-line-clamp': titleLineClamp }">{{ value.videoTitle }}
|
|
||||||
</view>
|
|
||||||
<!-- 视频统计信息 -->
|
|
||||||
<view class="video-stats" v-if="showViewCount && value.showViewCount">{{ value.viewCount }}次观看</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- 跳转式视频播放 -->
|
|
||||||
<view v-else @tap.stop="playVideo" class="video-container">
|
|
||||||
<view class="video-cover-wrap" :style="[coverStyle]">
|
|
||||||
<image class="video-cover" :src="$util.img(value.coverUrl)" mode="aspectFill"></image>
|
|
||||||
<view class="channel-play-btn" v-if="showPlayBtn" :style="[playBtnStyle]">
|
|
||||||
<view class="play-icon-css"></view>
|
|
||||||
</view>
|
|
||||||
<view class="video-stats-overlay" v-if="showViewCount && value.showViewCount">
|
|
||||||
{{ value.viewCount }}次观看
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view class="video-info">
|
|
||||||
<!-- 视频标题,支持多行显示控制 -->
|
|
||||||
<view class="video-title" :style="{ '--title-line-clamp': titleLineClamp }">{{ value.videoTitle }}
|
|
||||||
</view>
|
|
||||||
<!-- 视频统计信息,非列表模式下显示 -->
|
|
||||||
<view class="video-stats" v-if="showViewCount && value.showViewCount && !listMode">{{ value.viewCount }}次观看</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
|
|
||||||
import { wechatChannelUtil, wechatChannelConfig } from './js/wechat-channel.js'
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 微信视频号视频卡片组件
|
|
||||||
* 支持嵌入式播放和跳转式播放两种模式
|
|
||||||
* 可配置列表模式、视频高度、标题行数等属性
|
|
||||||
*/
|
|
||||||
export default {
|
|
||||||
name: 'diy-channel-video',
|
|
||||||
props: {
|
|
||||||
/**
|
|
||||||
* 视频数据对象
|
|
||||||
* @type {Object}
|
|
||||||
* @required
|
|
||||||
* @property {string} feedId - 视频 feedId
|
|
||||||
* @property {string} feedToken - 视频 token
|
|
||||||
* @property {string} coverUrl - 视频封面图
|
|
||||||
* @property {string} videoTitle - 视频标题
|
|
||||||
* @property {number} viewCount - 观看次数
|
|
||||||
* @property {boolean} showViewCount - 是否显示观看次数
|
|
||||||
* @property {boolean} embedMode - 是否启用嵌入式播放
|
|
||||||
*/
|
|
||||||
value: {
|
|
||||||
type: Object,
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* 是否为列表模式
|
|
||||||
* @type {boolean}
|
|
||||||
* @default false
|
|
||||||
*/
|
|
||||||
listMode: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
/** 是否显示观看次数,由父组件可以整体配置 */
|
|
||||||
showViewCount: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* 标题显示行数
|
|
||||||
* @type {number}
|
|
||||||
* @default 1
|
|
||||||
*/
|
|
||||||
titleLineClamp: {
|
|
||||||
type: Number,
|
|
||||||
default: 1
|
|
||||||
},
|
|
||||||
/** 是否显示播放按钮 */
|
|
||||||
showPlayBtn: {
|
|
||||||
type: Boolean,
|
|
||||||
default: true
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* 视频封面图样式
|
|
||||||
* 采用 16:9 比例的响应式高度
|
|
||||||
*/
|
|
||||||
coverStyle: {
|
|
||||||
type: Object,
|
|
||||||
default: () => ({
|
|
||||||
width: '100%',
|
|
||||||
height: '0',
|
|
||||||
paddingTop: '56.25%' // 16:9 比例
|
|
||||||
})
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* 播放按钮样式
|
|
||||||
*/
|
|
||||||
playBtnStyle: {
|
|
||||||
type: Object,
|
|
||||||
default: () => ({
|
|
||||||
width: '60rpx',
|
|
||||||
height: '60rpx',
|
|
||||||
borderRadius: '30rpx',
|
|
||||||
backgroundColor: 'rgba(0, 0, 0, 0.6)'
|
|
||||||
})
|
|
||||||
},
|
|
||||||
/** 是否自动播放 */
|
|
||||||
autoPlay: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
/**
|
|
||||||
* 是否支持嵌入式播放
|
|
||||||
* @returns {boolean}
|
|
||||||
*/
|
|
||||||
canUseEmbedMode() {
|
|
||||||
// #ifdef MP-WEIXIN
|
|
||||||
const enableEmbedMode = Boolean(this.value?.embedMode)
|
|
||||||
&& Boolean(this.value?.feedToken)
|
|
||||||
&& wechatChannelUtil.isEmbedModeSupported();
|
|
||||||
console.log('enableEmbedMode', enableEmbedMode);
|
|
||||||
return enableEmbedMode;
|
|
||||||
// #endif
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
/**
|
|
||||||
* 播放视频
|
|
||||||
* 触发 video-play 事件,由父组件处理具体播放逻辑
|
|
||||||
*/
|
|
||||||
async playVideo() {
|
|
||||||
this.$emit('video-play', this.value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped lang="scss">
|
|
||||||
@import './css/common-channel.scss';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 视频卡片容器样式
|
|
||||||
* 包含卡片基础样式、悬停效果和列表模式样式
|
|
||||||
*/
|
|
||||||
.channel-video {
|
|
||||||
position: relative;
|
|
||||||
background-color: #fff;
|
|
||||||
border-radius: 12rpx;
|
|
||||||
overflow: hidden;
|
|
||||||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08);
|
|
||||||
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
height: 100%;
|
|
||||||
|
|
||||||
// 悬停效果
|
|
||||||
&:hover {
|
|
||||||
transform: translateY(-4rpx);
|
|
||||||
box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.15);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 列表模式样式调整
|
|
||||||
&.list-mode {
|
|
||||||
border-radius: 10rpx;
|
|
||||||
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.08);
|
|
||||||
|
|
||||||
.video-info {
|
|
||||||
padding: 14rpx;
|
|
||||||
|
|
||||||
.video-title {
|
|
||||||
font-size: 24rpx;
|
|
||||||
margin-bottom: 6rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 视频容器样式
|
|
||||||
* 用于跳转式播放模式
|
|
||||||
*/
|
|
||||||
.video-container {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 嵌入式视频容器样式
|
|
||||||
* 与视频容器样式保持一致
|
|
||||||
*/
|
|
||||||
.embed-video-container {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 视频封面容器
|
|
||||||
*/
|
|
||||||
.video-cover-wrap {
|
|
||||||
position: relative;
|
|
||||||
width: 100%;
|
|
||||||
padding-top: 56.25%;
|
|
||||||
/* 16:9 比例 */
|
|
||||||
height: 0;
|
|
||||||
overflow: hidden;
|
|
||||||
border-radius: 12rpx 12rpx 0 0;
|
|
||||||
transition: transform 0.3s ease;
|
|
||||||
|
|
||||||
// 悬停时缩放效果
|
|
||||||
.channel-video:hover & {
|
|
||||||
transform: scale(1.02);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 列表模式下的边框圆角调整
|
|
||||||
.channel-video.list-mode & {
|
|
||||||
border-radius: 10rpx 10rpx 0 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 视频封面图片
|
|
||||||
* 绝对定位填充整个容器
|
|
||||||
*/
|
|
||||||
.video-cover {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
object-fit: cover;
|
|
||||||
transition: transform 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 视频统计信息遮罩
|
|
||||||
* 显示在视频封面底部
|
|
||||||
*/
|
|
||||||
.video-stats-overlay {
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
background: linear-gradient(transparent, rgba(0, 0, 0, 0.7));
|
|
||||||
padding: 12rpx 16rpx;
|
|
||||||
color: #fff;
|
|
||||||
font-size: 20rpx;
|
|
||||||
text-align: right;
|
|
||||||
font-weight: 500;
|
|
||||||
transition: opacity 0.3s ease;
|
|
||||||
|
|
||||||
// 悬停时的透明度变化
|
|
||||||
.channel-video:hover & {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.channel-video:not(:hover) & {
|
|
||||||
opacity: 0.8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 视频信息区域
|
|
||||||
* 包含标题和统计信息
|
|
||||||
*/
|
|
||||||
.video-info {
|
|
||||||
padding: 16rpx;
|
|
||||||
flex: 1;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: space-between;
|
|
||||||
background-color: #fff;
|
|
||||||
transition: background-color 0.3s ease;
|
|
||||||
|
|
||||||
// 悬停时的背景色变化
|
|
||||||
.channel-video:hover & {
|
|
||||||
background-color: #fafafa;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 视频标题
|
|
||||||
* 支持多行显示控制和渐变遮罩效果
|
|
||||||
*/
|
|
||||||
.video-title {
|
|
||||||
font-size: 28rpx;
|
|
||||||
font-weight: 600;
|
|
||||||
color: #222;
|
|
||||||
margin-bottom: 10rpx;
|
|
||||||
line-height: 1.4;
|
|
||||||
display: -webkit-box;
|
|
||||||
-webkit-line-clamp: var(--title-line-clamp, 2);
|
|
||||||
-webkit-box-orient: vertical;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
transition: color 0.3s ease;
|
|
||||||
position: relative;
|
|
||||||
word-break: break-all;
|
|
||||||
word-wrap: break-word;
|
|
||||||
white-space: normal;
|
|
||||||
|
|
||||||
// 悬停时的颜色变化
|
|
||||||
.channel-video:hover & {
|
|
||||||
color: #000;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 列表模式下的样式调整
|
|
||||||
.channel-video.list-mode & {
|
|
||||||
-webkit-line-clamp: var(--title-line-clamp, 1);
|
|
||||||
font-size: 24rpx;
|
|
||||||
margin-bottom: 6rpx;
|
|
||||||
font-weight: 500;
|
|
||||||
color: #333;
|
|
||||||
line-height: 1.3;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 添加渐变遮罩效果,让过长的文字有柔和的结束
|
|
||||||
&::after {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0;
|
|
||||||
right: 0;
|
|
||||||
width: 40rpx;
|
|
||||||
height: 1.4em;
|
|
||||||
background: linear-gradient(to right, transparent, #fff 90%);
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 列表模式下的遮罩高度调整
|
|
||||||
.channel-video.list-mode &::after {
|
|
||||||
height: 1.3em;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 根据行数调整遮罩高度
|
|
||||||
&[style*="--title-line-clamp: 1"]::after {
|
|
||||||
height: 1.4em;
|
|
||||||
}
|
|
||||||
|
|
||||||
&[style*="--title-line-clamp: 3"]::after {
|
|
||||||
height: 4.2em;
|
|
||||||
}
|
|
||||||
|
|
||||||
&[style*="--title-line-clamp: 4"]::after {
|
|
||||||
height: 5.6em;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 列表模式下的多行遮罩高度调整
|
|
||||||
.channel-video.list-mode &[style*="--title-line-clamp: 1"]::after {
|
|
||||||
height: 1.3em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.channel-video.list-mode &[style*="--title-line-clamp: 3"]::after {
|
|
||||||
height: 3.9em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.channel-video.list-mode &[style*="--title-line-clamp: 4"]::after {
|
|
||||||
height: 5.2em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 视频统计信息
|
|
||||||
* 显示观看次数等数据
|
|
||||||
*/
|
|
||||||
.video-stats {
|
|
||||||
font-size: 22rpx;
|
|
||||||
color: #999;
|
|
||||||
margin-top: 6rpx;
|
|
||||||
transition: color 0.3s ease;
|
|
||||||
|
|
||||||
// 悬停时的颜色变化
|
|
||||||
.channel-video:hover & {
|
|
||||||
color: #666;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 列表模式下的播放按钮样式
|
|
||||||
* 更小的尺寸和悬停效果
|
|
||||||
*/
|
|
||||||
.channel-video.list-mode .channel-play-btn {
|
|
||||||
width: 50rpx;
|
|
||||||
height: 50rpx;
|
|
||||||
background-color: rgba(0, 0, 0, 0.5);
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
|
|
||||||
// 悬停效果
|
|
||||||
&:hover {
|
|
||||||
background-color: rgba(0, 0, 0, 0.7);
|
|
||||||
transform: scale(1.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 播放图标尺寸
|
|
||||||
.play-icon {
|
|
||||||
width: 25rpx;
|
|
||||||
height: 25rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 通用播放按钮样式优化
|
|
||||||
* 添加悬停效果
|
|
||||||
*/
|
|
||||||
.channel-play-btn {
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
|
|
||||||
// 悬停效果
|
|
||||||
&:hover {
|
|
||||||
background-color: rgba(0, 0, 0, 0.6);
|
|
||||||
transform: scale(1.05);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 纯 CSS 播放按钮图标
|
|
||||||
*/
|
|
||||||
.play-icon-css {
|
|
||||||
width: 0;
|
|
||||||
height: 0;
|
|
||||||
border-top: 12rpx solid transparent;
|
|
||||||
border-bottom: 12rpx solid transparent;
|
|
||||||
border-left: 18rpx solid #fff;
|
|
||||||
margin-left: 4rpx;
|
|
||||||
transition: transform 0.3s ease;
|
|
||||||
|
|
||||||
// 悬停时的缩放效果
|
|
||||||
.channel-play-btn:hover & {
|
|
||||||
transform: scale(1.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 列表模式下的尺寸调整
|
|
||||||
.channel-video.list-mode & {
|
|
||||||
border-top: 10rpx solid transparent;
|
|
||||||
border-bottom: 10rpx solid transparent;
|
|
||||||
border-left: 15rpx solid #fff;
|
|
||||||
margin-left: 3rpx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 原生组件样式控制
|
|
||||||
* 确保 native-component 和 channel-video 正确填充容器
|
|
||||||
*/
|
|
||||||
native-component {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* channel-video 组件样式控制
|
|
||||||
* 避免受到 wx-channel-video 全局样式的影响
|
|
||||||
*/
|
|
||||||
channel-video {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
min-width: 100%;
|
|
||||||
min-height: 100%;
|
|
||||||
max-width: 100%;
|
|
||||||
max-height: 100%;
|
|
||||||
object-fit: cover;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
backgroundImage: 'url(' + $util.img('public/uniapp/coupon/style1-bg.png') + ')',
|
backgroundImage: 'url(' + $util.img('public/uniapp/coupon/style1-bg.png') + ')',
|
||||||
marginRight: couponItemHeight + 'px',
|
marginRight: couponItemHeight + 'px',
|
||||||
marginLeft: couponItemHeight + 'px'
|
marginLeft: couponItemHeight + 'px'
|
||||||
}" @tap.stop="couponAction(item, index)">
|
}" @click="couponAction(item, index)">
|
||||||
|
|
||||||
<view class="coupon-info">
|
<view class="coupon-info">
|
||||||
<view class="coupon-num" :style="{ color: value.moneyColor }"
|
<view class="coupon-num" :style="{ color: value.moneyColor }"
|
||||||
@@ -52,7 +52,7 @@
|
|||||||
backgroundImage: 'url(' + $util.img('public/uniapp/coupon/coupon_bg1.png') + ')',
|
backgroundImage: 'url(' + $util.img('public/uniapp/coupon/coupon_bg1.png') + ')',
|
||||||
marginRight: couponItemHeight + 'px',
|
marginRight: couponItemHeight + 'px',
|
||||||
marginLeft: couponItemHeight + 'px'
|
marginLeft: couponItemHeight + 'px'
|
||||||
}" @tap.stop="couponAction(item, index)">
|
}" @click="couponAction(item, index)">
|
||||||
<view class="coupon-info">
|
<view class="coupon-info">
|
||||||
<view class="coupon-num" :style="{ color: value.moneyColor }"
|
<view class="coupon-num" :style="{ color: value.moneyColor }"
|
||||||
v-if="!parseInt(item.discount)">
|
v-if="!parseInt(item.discount)">
|
||||||
@@ -87,7 +87,7 @@
|
|||||||
backgroundImage: 'url(' + $util.img('public/uniapp/coupon/coupon_shu.png') + ')',
|
backgroundImage: 'url(' + $util.img('public/uniapp/coupon/coupon_shu.png') + ')',
|
||||||
marginRight: couponItemHeight + 'px',
|
marginRight: couponItemHeight + 'px',
|
||||||
marginLeft: couponItemHeight + 'px'
|
marginLeft: couponItemHeight + 'px'
|
||||||
}" @tap.stop="couponAction(item, index)">
|
}" @click="couponAction(item, index)">
|
||||||
<view class="coupon-num" :style="{ color: value.moneyColor }"
|
<view class="coupon-num" :style="{ color: value.moneyColor }"
|
||||||
v-if="!parseInt(item.discount)">
|
v-if="!parseInt(item.discount)">
|
||||||
<text class="font-size-tag coupon-sign">¥</text>
|
<text class="font-size-tag coupon-sign">¥</text>
|
||||||
@@ -124,7 +124,7 @@
|
|||||||
backgroundImage: 'url(' + $util.img('public/uniapp/coupon/style4_bg.png') + ')',
|
backgroundImage: 'url(' + $util.img('public/uniapp/coupon/style4_bg.png') + ')',
|
||||||
marginRight: couponItemHeight + 'px',
|
marginRight: couponItemHeight + 'px',
|
||||||
marginLeft: couponItemHeight + 'px'
|
marginLeft: couponItemHeight + 'px'
|
||||||
}" @tap.stop="couponAction(item, index)">
|
}" @click="couponAction(item, index)">
|
||||||
<view class="coupon-info">
|
<view class="coupon-info">
|
||||||
<view class="coupon-num" :style="{ color: value.moneyColor }"
|
<view class="coupon-num" :style="{ color: value.moneyColor }"
|
||||||
v-if="!parseInt(item.discount)">
|
v-if="!parseInt(item.discount)">
|
||||||
@@ -153,7 +153,7 @@
|
|||||||
<view class="coupon-all">
|
<view class="coupon-all">
|
||||||
<view class="coupon-box">
|
<view class="coupon-box">
|
||||||
<view class="coupon-list" v-for="(item, index) in computedCouponList" :key="index"
|
<view class="coupon-list" v-for="(item, index) in computedCouponList" :key="index"
|
||||||
@tap.stop="couponAction(item, index)">
|
@click="couponAction(item, index)">
|
||||||
<image :src="$util.img('public/uniapp/coupon/style5_bg.png')"></image>
|
<image :src="$util.img('public/uniapp/coupon/style5_bg.png')"></image>
|
||||||
<view class="coupon">
|
<view class="coupon">
|
||||||
<view class="coupon-info">
|
<view class="coupon-info">
|
||||||
@@ -199,7 +199,7 @@
|
|||||||
backgroundImage: 'url(' + $util.img('public/uniapp/coupon/style6-bg-1.png') + ')',
|
backgroundImage: 'url(' + $util.img('public/uniapp/coupon/style6-bg-1.png') + ')',
|
||||||
marginRight: couponItemHeight + 'px',
|
marginRight: couponItemHeight + 'px',
|
||||||
marginLeft: couponItemHeight + 'px'
|
marginLeft: couponItemHeight + 'px'
|
||||||
}" @tap.stop="couponAction(item, index)">
|
}" @click="couponAction(item, index)">
|
||||||
<view class="coupon-content">
|
<view class="coupon-content">
|
||||||
<view class="price-wrap">
|
<view class="price-wrap">
|
||||||
<text class="price" :style="{ color: value.moneyColor }">{{ (item.discount == '0.00'
|
<text class="price" :style="{ color: value.moneyColor }">{{ (item.discount == '0.00'
|
||||||
@@ -229,7 +229,7 @@
|
|||||||
<text class="limit" :style="{ color: value.limitColor }" v-else>无门槛使用</text>
|
<text class="limit" :style="{ color: value.limitColor }" v-else>无门槛使用</text>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<div v-if="computedCouponList.length <= 2" @tap.stop="$util.redirectTo('/pages_goods/category')"
|
<div v-if="computedCouponList.length <= 2" @click="$util.redirectTo('/pages_goods/category')"
|
||||||
class="coupon coupon-null" :style="{
|
class="coupon coupon-null" :style="{
|
||||||
color: value.moneyColor,
|
color: value.moneyColor,
|
||||||
backgroundImage: 'url(' + $util.img('public/uniapp/coupon/style6-bg-2.png') + ')',
|
backgroundImage: 'url(' + $util.img('public/uniapp/coupon/style6-bg-2.png') + ')',
|
||||||
@@ -250,7 +250,7 @@
|
|||||||
<scroll-view class="coupon-style-seven" scroll-x="true">
|
<scroll-view class="coupon-style-seven" scroll-x="true">
|
||||||
<view class="wrap">
|
<view class="wrap">
|
||||||
<view class="coupon-list" v-for="(item, index) in computedCouponList" :key="index"
|
<view class="coupon-list" v-for="(item, index) in computedCouponList" :key="index"
|
||||||
@tap.stop="couponAction(item, index)">
|
@click="couponAction(item, index)">
|
||||||
<image :src="$util.img('public/uniapp/coupon/style7_bg.png')"></image>
|
<image :src="$util.img('public/uniapp/coupon/style7_bg.png')"></image>
|
||||||
<view class="coupon">
|
<view class="coupon">
|
||||||
<view class="coupon-info">
|
<view class="coupon-info">
|
||||||
@@ -454,7 +454,7 @@ export default {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
this.$refs.login.open(this.$util.INDEX_PAGE_URL);
|
this.$refs.login.open('/pages/index/index');
|
||||||
this.couponBtnSwitch = false;
|
this.couponBtnSwitch = false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -488,7 +488,7 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 风格一
|
// 风格一
|
||||||
::v-deep .coupon-style-one {
|
/deep/.coupon-style-one {
|
||||||
height: 110rpx;
|
height: 110rpx;
|
||||||
|
|
||||||
.coupon-item-box {
|
.coupon-item-box {
|
||||||
@@ -534,7 +534,7 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 风格二
|
// 风格二
|
||||||
::v-deep .coupon-style-two {
|
/deep/.coupon-style-two {
|
||||||
height: 96rpx;
|
height: 96rpx;
|
||||||
|
|
||||||
.coupon-item-box {
|
.coupon-item-box {
|
||||||
@@ -591,7 +591,7 @@ export default {
|
|||||||
background-size: 100% 100%;
|
background-size: 100% 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
::v-deep .coupon-style-three {
|
/deep/.coupon-style-three {
|
||||||
height: 284rpx;
|
height: 284rpx;
|
||||||
padding: 20rpx;
|
padding: 20rpx;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
@@ -638,7 +638,7 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 风格四
|
// 风格四
|
||||||
::v-deep .coupon-style-four {
|
/deep/.coupon-style-four {
|
||||||
height: 108rpx;
|
height: 108rpx;
|
||||||
|
|
||||||
.coupon-item-box {
|
.coupon-item-box {
|
||||||
@@ -997,7 +997,7 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//风格七
|
//风格七
|
||||||
::v-deep .coupon-style-seven {
|
/deep/ .coupon-style-seven {
|
||||||
.wrap {
|
.wrap {
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
@@ -1075,7 +1075,7 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
::v-deep .uni-scroll-view ::-webkit-scrollbar {
|
/deep/.uni-scroll-view ::-webkit-scrollbar {
|
||||||
/* 隐藏滚动条,但依旧具备可以滚动的功能 */
|
/* 隐藏滚动条,但依旧具备可以滚动的功能 */
|
||||||
display: none;
|
display: none;
|
||||||
width: 0;
|
width: 0;
|
||||||
@@ -1084,7 +1084,7 @@ export default {
|
|||||||
background: transparent;
|
background: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
::v-deep ::-webkit-scrollbar {
|
/deep/::-webkit-scrollbar {
|
||||||
display: none;
|
display: none;
|
||||||
width: 0;
|
width: 0;
|
||||||
height: 0;
|
height: 0;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<view :style="componentStyle" data-component-name="diy-digit">
|
<view :style="componentStyle">
|
||||||
<scroll-view :class="['graphic-nav', value.showStyle == 'fixed' ? 'fixed-layout' : value.showStyle]"
|
<scroll-view :class="['graphic-nav', value.showStyle == 'fixed' ? 'fixed-layout' : value.showStyle]"
|
||||||
:scroll-x="value.showStyle == 'singleSlide'">
|
:scroll-x="value.showStyle == 'singleSlide'">
|
||||||
<view class="uni-scroll-view-content">
|
<view class="uni-scroll-view-content">
|
||||||
@@ -38,10 +38,16 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import uvCountTo from '@/components/uv-count-to/uv-count-to.vue'
|
||||||
|
import nsLogin from '@/components/ns-login/ns-login.vue'
|
||||||
import DiyMinx from './minx.js'
|
import DiyMinx from './minx.js'
|
||||||
// 自定义数字展示
|
// 自定义数字展示
|
||||||
export default {
|
export default {
|
||||||
name: 'diy-digit',
|
name: 'diy-digit',
|
||||||
|
components: {
|
||||||
|
uvCountTo,
|
||||||
|
nsLogin
|
||||||
|
},
|
||||||
props: {
|
props: {
|
||||||
value: {
|
value: {
|
||||||
type: Object,
|
type: Object,
|
||||||
@@ -90,7 +96,7 @@ export default {
|
|||||||
|
|
||||||
// 页面跳转
|
// 页面跳转
|
||||||
redirectTo(item) {
|
redirectTo(item) {
|
||||||
if (!item.wap_url || this.$util.getCurrRoute() != this.$util.MEMBER_PAGE_URL || this.storeToken) {
|
if (!item.wap_url || this.$util.getCurrRoute() != 'pages/member/index' || this.storeToken) {
|
||||||
console.log(item);
|
console.log(item);
|
||||||
this.$util.diyRedirectTo(item);
|
this.$util.diyRedirectTo(item);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<view data-component-name="diy-fenxiao-goods-list" class="diy-fenxiao" v-if="list.length"
|
<view data-component-name="diy-fenxiao-goods-list" class="diy-fenxiao" v-if="list.length"
|
||||||
:class="['goods-list', value.template, value.style]" :style="goodsListWarpCss">
|
:class="['goods-list', value.template, value.style]" :style="goodsListWarpCss">
|
||||||
<view class="goods-item" v-for="(item, index) in list" :key="index" @tap.stop="toDetail(item)"
|
<view class="goods-item" v-for="(item, index) in list" :key="index" @click="toDetail(item)"
|
||||||
:class="[value.ornament.type]" :style="goodsItemCss">
|
:class="[value.ornament.type]" :style="goodsItemCss">
|
||||||
<view class="goods-img" :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }">
|
<view class="goods-img" :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }">
|
||||||
<image :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }"
|
<image :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }"
|
||||||
@@ -32,14 +32,14 @@
|
|||||||
background: value.btnStyle.theme == 'diy' ? 'linear-gradient(to right,' + value.btnStyle.bgColorStart + ',' + value.btnStyle.bgColorEnd + ')' : '',
|
background: value.btnStyle.theme == 'diy' ? 'linear-gradient(to right,' + value.btnStyle.bgColorStart + ',' + value.btnStyle.bgColorEnd + ')' : '',
|
||||||
color: value.btnStyle.theme == 'diy' ? value.btnStyle.textColor : '',
|
color: value.btnStyle.theme == 'diy' ? value.btnStyle.textColor : '',
|
||||||
borderRadius: value.btnStyle.aroundRadius * 2 + 'rpx'
|
borderRadius: value.btnStyle.aroundRadius * 2 + 'rpx'
|
||||||
}" @tap.stop="followGoods(item, index)">
|
}" @click.stop="followGoods(item, index)">
|
||||||
关注
|
关注
|
||||||
</view>
|
</view>
|
||||||
<view class="sale-btn" v-if="value.btnStyle.control && item.is_collect == 1" :style="{
|
<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 + ')' : '',
|
background: value.btnStyle.theme == 'diy' ? 'linear-gradient(to right,' + value.btnStyle.bgColorStart + ',' + value.btnStyle.bgColorEnd + ')' : '',
|
||||||
color: value.btnStyle.theme == 'diy' ? value.btnStyle.textColor : '',
|
color: value.btnStyle.theme == 'diy' ? value.btnStyle.textColor : '',
|
||||||
borderRadius: value.btnStyle.aroundRadius * 2 + 'rpx'
|
borderRadius: value.btnStyle.aroundRadius * 2 + 'rpx'
|
||||||
}" @tap.stop="delFollowTip(item, index)">
|
}" @click.stop="delFollowTip(item, index)">
|
||||||
取消关注
|
取消关注
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@@ -75,7 +75,7 @@ export default {
|
|||||||
this.currentRoute = '/' + currentPage.route;
|
this.currentRoute = '/' + currentPage.route;
|
||||||
if (!this.storeToken) {
|
if (!this.storeToken) {
|
||||||
this.$util.redirectTo(
|
this.$util.redirectTo(
|
||||||
this.$util.LOGIN_PAGE_URL,
|
'/pages_tool/login/login',
|
||||||
{
|
{
|
||||||
back: this.currentRoute
|
back: this.currentRoute
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
:class="{ left_top: value.bottomPosition == 1, right_top: value.bottomPosition == 2, left_bottom: value.bottomPosition == 3, right_bottom: value.bottomPosition == 4 }"
|
:class="{ left_top: value.bottomPosition == 1, right_top: value.bottomPosition == 2, left_bottom: value.bottomPosition == 3, right_bottom: value.bottomPosition == 4 }"
|
||||||
:style="style">
|
:style="style">
|
||||||
<block v-for="(item, index) in value.list" :key="index">
|
<block v-for="(item, index) in value.list" :key="index">
|
||||||
<view class="button-box" @tap.stop="$util.diyRedirectTo(item.link)"
|
<view class="button-box" @click="$util.diyRedirectTo(item.link)"
|
||||||
:style="{ width: value.imageSize + 'px', height: value.imageSize + 'px', fontSize: value.imageSize + 'px' }">
|
:style="{ width: value.imageSize + 'px', height: value.imageSize + 'px', fontSize: value.imageSize + 'px' }">
|
||||||
<image v-if="!item.iconType || item.iconType == 'img'" :src="$util.img(item.imageUrl)" mode="aspectFit"
|
<image v-if="!item.iconType || item.iconType == 'img'" :src="$util.img(item.imageUrl)" mode="aspectFit"
|
||||||
:show-menu-by-longpress="true" />
|
:show-menu-by-longpress="true" />
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view @tap.stop="submitform" class="fui-btn btn-danger block mtop">提交信息</view>
|
<view @click="submitform" class="fui-btn btn-danger block mtop">提交信息</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
<view class="ul-wrap">
|
<view class="ul-wrap">
|
||||||
<view class="li-item" v-for="(item, index) in list" :key="index">
|
<view class="li-item" v-for="(item, index) in list" :key="index">
|
||||||
<image class="brand-pic" :src="$util.img(item.image_url)" mode="aspectFit"
|
<image class="brand-pic" :src="$util.img(item.image_url)" mode="aspectFit"
|
||||||
@tap.stop="handlerClick(item)" @error="imgError(index)"
|
@click="handlerClick(item)" @tap="handlerClick(item)" @error="imgError(index)"
|
||||||
:style="itemCss" />
|
:style="itemCss" />
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@@ -19,6 +19,8 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
// 商品品牌
|
// 商品品牌
|
||||||
|
import uniGrid from '@/components/uni-grid/uni-grid.vue';
|
||||||
|
import uniGridItem from '@/components/uni-grid-item/uni-grid-item.vue';
|
||||||
|
|
||||||
import DiyMinx from './minx.js'
|
import DiyMinx from './minx.js'
|
||||||
// 自定义商品品牌展示
|
// 自定义商品品牌展示
|
||||||
@@ -29,6 +31,10 @@ export default {
|
|||||||
type: Object
|
type: Object
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
components: {
|
||||||
|
uniGrid,
|
||||||
|
uniGridItem
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
list: [],
|
list: [],
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
<x-skeleton data-component-name="diy-goods-list" :type="skeletonType" :loading="loading" :configs="skeletonConfig">
|
<x-skeleton data-component-name="diy-goods-list" :type="skeletonType" :loading="loading" :configs="skeletonConfig">
|
||||||
<view :class="['goods-list', goodsValue.template, goodsValue.style]" :style="goodsListWarpCss">
|
<view :class="['goods-list', goodsValue.template, goodsValue.style]" :style="goodsListWarpCss">
|
||||||
<template v-if="goodsValue.template != 'horizontal-slide'">
|
<template v-if="goodsValue.template != 'horizontal-slide'">
|
||||||
<view class="goods-item" v-for="(item, index) in list" :key="index" @tap.stop="handlerClick(item)"
|
<view class="goods-item" v-for="(item, index) in list" :key="index" @click="handlerClick(item)"
|
||||||
:class="[goodsValue.ornament.type]" :style="goodsItemCss">
|
@tap="handlerClick(item)" :class="[goodsValue.ornament.type]" :style="goodsItemCss">
|
||||||
<view class="goods-img-wrap">
|
<view class="goods-img-wrap">
|
||||||
<image class="goods-img"
|
<image class="goods-img"
|
||||||
:src="$util.img(item.goods_image, { size: goodsValue.template == 'large-mode' ? 'big' : 'mid' })"
|
:src="$util.img(item.goods_image, { size: goodsValue.template == 'large-mode' ? 'big' : 'mid' })"
|
||||||
@@ -70,7 +70,7 @@
|
|||||||
color: goodsValue.btnStyle.theme == 'diy' ? goodsValue.btnStyle.textColor : '',
|
color: goodsValue.btnStyle.theme == 'diy' ? goodsValue.btnStyle.textColor : '',
|
||||||
borderColor: goodsValue.btnStyle.theme == 'diy' ? goodsValue.btnStyle.textColor : ''
|
borderColor: goodsValue.btnStyle.theme == 'diy' ? goodsValue.btnStyle.textColor : ''
|
||||||
}" class="cart shopping-cart-btn iconfont icon-gouwuche click-wrap" :id="'goods-' + item.id"
|
}" class="cart shopping-cart-btn iconfont icon-gouwuche click-wrap" :id="'goods-' + item.id"
|
||||||
@tap.stop="$refs.goodsSkuIndex.addCart(goodsValue.btnStyle.cartEvent, item, $event)">
|
@click.stop="$refs.goodsSkuIndex.addCart(goodsValue.btnStyle.cartEvent, item, $event)">
|
||||||
<view class="click-event"></view>
|
<view class="click-event"></view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
@@ -79,7 +79,7 @@
|
|||||||
color: goodsValue.btnStyle.theme == 'diy' ? goodsValue.btnStyle.textColor : '',
|
color: goodsValue.btnStyle.theme == 'diy' ? goodsValue.btnStyle.textColor : '',
|
||||||
borderColor: goodsValue.btnStyle.theme == 'diy' ? goodsValue.btnStyle.textColor : ''
|
borderColor: goodsValue.btnStyle.theme == 'diy' ? goodsValue.btnStyle.textColor : ''
|
||||||
}" class="cart plus-sign-btn iconfont icon-add1 click-wrap" :id="'goods-' + item.id"
|
}" class="cart plus-sign-btn iconfont icon-add1 click-wrap" :id="'goods-' + item.id"
|
||||||
@tap.stop="$refs.goodsSkuIndex.addCart(goodsValue.btnStyle.cartEvent, item, $event)">
|
@click.stop="$refs.goodsSkuIndex.addCart(goodsValue.btnStyle.cartEvent, item, $event)">
|
||||||
<view class="click-event"></view>
|
<view class="click-event"></view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
@@ -90,7 +90,7 @@
|
|||||||
fontWeight: goodsValue.btnStyle.theme == 'diy' ? (goodsValue.btnStyle.fontWeight ? 'bold' : 'normal') : '',
|
fontWeight: goodsValue.btnStyle.theme == 'diy' ? (goodsValue.btnStyle.fontWeight ? 'bold' : 'normal') : '',
|
||||||
padding: goodsValue.btnStyle.theme == 'diy' ? '0 ' + goodsValue.btnStyle.padding * 2 + 'rpx' : ''
|
padding: goodsValue.btnStyle.theme == 'diy' ? '0 ' + goodsValue.btnStyle.padding * 2 + 'rpx' : ''
|
||||||
}" class="cart buy-btn click-wrap" :id="'goods-' + item.id"
|
}" class="cart buy-btn click-wrap" :id="'goods-' + item.id"
|
||||||
@tap.stop="$refs.goodsSkuIndex.addCart(goodsValue.btnStyle.cartEvent, item, $event)">
|
@click.stop="$refs.goodsSkuIndex.addCart(goodsValue.btnStyle.cartEvent, item, $event)">
|
||||||
{{ goodsValue.btnStyle.text }}
|
{{ goodsValue.btnStyle.text }}
|
||||||
<view class="click-event"></view>
|
<view class="click-event"></view>
|
||||||
<!-- <text class="cart-num" v-if="cartList['goods_' + item.goods_id]">{{ cartList['goods_' + item.goods_id].num }}</text> -->
|
<!-- <text class="cart-num" v-if="cartList['goods_' + item.goods_id]">{{ cartList['goods_' + item.goods_id].num }}</text> -->
|
||||||
@@ -100,7 +100,7 @@
|
|||||||
<view v-else-if="goodsValue.btnStyle.style == 'icon-diy'" :style="{
|
<view v-else-if="goodsValue.btnStyle.style == 'icon-diy'" :style="{
|
||||||
color: goodsValue.btnStyle.theme == 'diy' ? goodsValue.btnStyle.textColor : ''
|
color: goodsValue.btnStyle.theme == 'diy' ? goodsValue.btnStyle.textColor : ''
|
||||||
}" class="icon-diy click-wrap" :id="'goods-' + item.id"
|
}" class="icon-diy click-wrap" :id="'goods-' + item.id"
|
||||||
@tap.stop="$refs.goodsSkuIndex.addCart(goodsValue.btnStyle.cartEvent, item, $event)">
|
@click.stop="$refs.goodsSkuIndex.addCart(goodsValue.btnStyle.cartEvent, item, $event)">
|
||||||
<view class="click-event"></view>
|
<view class="click-event"></view>
|
||||||
<diy-icon :icon="goodsValue.btnStyle.iconDiy.icon"
|
<diy-icon :icon="goodsValue.btnStyle.iconDiy.icon"
|
||||||
:value="goodsValue.btnStyle.iconDiy.style ? goodsValue.btnStyle.iconDiy.style : null"></diy-icon>
|
:value="goodsValue.btnStyle.iconDiy.style ? goodsValue.btnStyle.iconDiy.style : null"></diy-icon>
|
||||||
@@ -112,8 +112,8 @@
|
|||||||
</template>
|
</template>
|
||||||
<scroll-view v-if="goodsValue.template == 'horizontal-slide' && goodsValue.slideMode == 'scroll'"
|
<scroll-view v-if="goodsValue.template == 'horizontal-slide' && goodsValue.slideMode == 'scroll'"
|
||||||
class="scroll" :scroll-x="true">
|
class="scroll" :scroll-x="true">
|
||||||
<view class="goods-item" v-for="(item, index) in list" :key="index" @tap.stop="handlerClick(item)"
|
<view class="goods-item" v-for="(item, index) in list" :key="index" @click="handlerClick(item)"
|
||||||
:class="[goodsValue.ornament.type]" :style="goodsItemCss">
|
@tap="handlerClick(item)" :class="[goodsValue.ornament.type]" :style="goodsItemCss">
|
||||||
<view class="goods-img-wrap">
|
<view class="goods-img-wrap">
|
||||||
<image class="goods-img" :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }"
|
<image class="goods-img" :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }"
|
||||||
:src="$util.img(item.goods_image, { size: 'mid' })" mode="widthFix" @error="imgError(index)"
|
:src="$util.img(item.goods_image, { size: 'mid' })" mode="widthFix" @error="imgError(index)"
|
||||||
@@ -179,7 +179,7 @@
|
|||||||
<swiper-item v-for="(pageItem, pageIndex) in page" :key="pageIndex"
|
<swiper-item v-for="(pageItem, pageIndex) in page" :key="pageIndex"
|
||||||
:class="['swiper-item', (list.length && [list[pageIndex].length / 3] >= 1) && 'flex-between']">
|
:class="['swiper-item', (list.length && [list[pageIndex].length / 3] >= 1) && 'flex-between']">
|
||||||
<view class="goods-item" v-for="(dataItem, dataIndex) in list[pageIndex]" :key="dataIndex"
|
<view class="goods-item" v-for="(dataItem, dataIndex) in list[pageIndex]" :key="dataIndex"
|
||||||
@tap.stop="handlerClick(dataItem)"
|
@click="handlerClick(dataItem)" @tap="handlerClick(dataItem)"
|
||||||
:class="[goodsValue.ornament.type]" :style="goodsItemCss">
|
:class="[goodsValue.ornament.type]" :style="goodsItemCss">
|
||||||
<view class="goods-img-wrap">
|
<view class="goods-img-wrap">
|
||||||
<image class="goods-img" :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }"
|
<image class="goods-img" :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }"
|
||||||
@@ -253,12 +253,15 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import nsGoodsSkuIndex from '@/components/ns-goods-sku/ns-goods-sku-index.vue';
|
||||||
import DiyMinx from './minx.js'
|
import DiyMinx from './minx.js'
|
||||||
import util from '@/common/js/util.js'
|
|
||||||
|
|
||||||
// 自定义商品列表展示
|
// 自定义商品列表展示
|
||||||
export default {
|
export default {
|
||||||
name: 'diy-goods-list',
|
name: 'diy-goods-list',
|
||||||
|
components: {
|
||||||
|
nsGoodsSkuIndex
|
||||||
|
},
|
||||||
props: {
|
props: {
|
||||||
value: {
|
value: {
|
||||||
type: Object,
|
type: Object,
|
||||||
@@ -328,7 +331,7 @@ export default {
|
|||||||
if (this.goodsValue.ornament.type == 'stroke') {
|
if (this.goodsValue.ornament.type == 'stroke') {
|
||||||
obj += 'border:' + '2rpx solid ' + this.goodsValue.ornament.color + ';';
|
obj += 'border:' + '2rpx solid ' + this.goodsValue.ornament.color + ';';
|
||||||
}
|
}
|
||||||
let screenWidth = util.getWindowInfo().windowWidth;
|
const screenWidth = uni.getSystemInfoSync().windowWidth;
|
||||||
if (this.value.template == 'horizontal-slide') {
|
if (this.value.template == 'horizontal-slide') {
|
||||||
var width = '';
|
var width = '';
|
||||||
if (this.value.slideMode == 'scroll' && this.value.goodsMarginType == 'diy') width = this.rpxUpPx(
|
if (this.value.slideMode == 'scroll' && this.value.goodsMarginType == 'diy') width = this.rpxUpPx(
|
||||||
@@ -408,7 +411,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
rpxUpPx(res) {
|
rpxUpPx(res) {
|
||||||
const screenWidth = util.getWindowInfo().windowWidth;
|
const screenWidth = uni.getSystemInfoSync().windowWidth;
|
||||||
var data = (screenWidth * parseInt(res)) / 750;
|
var data = (screenWidth * parseInt(res)) / 750;
|
||||||
return Math.floor(data);
|
return Math.floor(data);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
<swiper-item v-for="(item, index) in page" :key="index"
|
<swiper-item v-for="(item, index) in page" :key="index"
|
||||||
:class="['swiper-item', [list[index].length / 3] >= 1 && 'flex-between']">
|
:class="['swiper-item', [list[index].length / 3] >= 1 && 'flex-between']">
|
||||||
<view class="goods-item" v-for="(dataItem, dataIndex) in list[index]" :key="dataIndex"
|
<view class="goods-item" v-for="(dataItem, dataIndex) in list[index]" :key="dataIndex"
|
||||||
@tap.stop="toDetail(dataItem)" :class="[goodsValue.ornament.type]" :style="goodsItemCss">
|
@click="toDetail(dataItem)" :class="[goodsValue.ornament.type]" :style="goodsItemCss">
|
||||||
<div class="goods-img-wrap">
|
<div class="goods-img-wrap">
|
||||||
<image class="goods-img" :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }"
|
<image class="goods-img" :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }"
|
||||||
:src="$util.img(dataItem.goods_image, { size: 'mid' })" mode="widthFix"
|
:src="$util.img(dataItem.goods_image, { size: 'mid' })" mode="widthFix"
|
||||||
|
|||||||
@@ -9,13 +9,13 @@
|
|||||||
<view class="graphic-nav-item" :class="[value.mode]" v-for="(item, index) in value.list"
|
<view class="graphic-nav-item" :class="[value.mode]" v-for="(item, index) in value.list"
|
||||||
:key="index"
|
:key="index"
|
||||||
v-if="index >= [(numItem) * (value.pageCount * value.rowCount)] && index < [(numItem + 1) * (value.pageCount * value.rowCount)]"
|
v-if="index >= [(numItem) * (value.pageCount * value.rowCount)] && index < [(numItem + 1) * (value.pageCount * value.rowCount)]"
|
||||||
:style="{ width: 100 / value.rowCount + '%' }" @tap.stop="redirectTo(item.link)">
|
:style="{ width: 100 / value.rowCount + '%' }" @click="redirectTo(item.link)">
|
||||||
<!-- #endif -->
|
<!-- #endif -->
|
||||||
<!-- #ifdef H5 -->
|
<!-- #ifdef H5 -->
|
||||||
<view class="graphic-nav-item" :class="[value.mode]" v-for="(item, index) in value.list"
|
<view class="graphic-nav-item" :class="[value.mode]" v-for="(item, index) in value.list"
|
||||||
:key="index"
|
:key="index"
|
||||||
v-if="index >= [(numItem - 1) * (value.pageCount * value.rowCount)] && index < [numItem * (value.pageCount * value.rowCount)]"
|
v-if="index >= [(numItem - 1) * (value.pageCount * value.rowCount)] && index < [numItem * (value.pageCount * value.rowCount)]"
|
||||||
:style="{ width: 100 / value.rowCount + '%' }" @tap.stop="redirectTo(item.link)">
|
:style="{ width: 100 / value.rowCount + '%' }" @click="redirectTo(item.link)">
|
||||||
<!-- #endif -->
|
<!-- #endif -->
|
||||||
<view class="graphic-img" v-if="value.mode != 'text'"
|
<view class="graphic-img" v-if="value.mode != 'text'"
|
||||||
:style="{ fontSize: value.imageSize * 2 + 'rpx', width: value.imageSize * 2 + 'rpx', height: value.imageSize * 2 + 'rpx' }">
|
:style="{ fontSize: value.imageSize * 2 + 'rpx', width: value.imageSize * 2 + 'rpx', height: value.imageSize * 2 + 'rpx' }">
|
||||||
@@ -62,7 +62,7 @@
|
|||||||
<!-- #endif -->
|
<!-- #endif -->
|
||||||
|
|
||||||
<view class="graphic-nav-item" :class="[value.mode]" v-for="(item, index) in value.list" :key="index"
|
<view class="graphic-nav-item" :class="[value.mode]" v-for="(item, index) in value.list" :key="index"
|
||||||
:style="{ width: 100 / value.rowCount + '%' }" @tap.stop="redirectTo(item.link)">
|
:style="{ width: 100 / value.rowCount + '%' }" @click="redirectTo(item.link)">
|
||||||
<view class="graphic-img" v-if="value.mode != 'text'"
|
<view class="graphic-img" v-if="value.mode != 'text'"
|
||||||
:style="{ fontSize: value.imageSize * 2 + 'rpx', width: value.imageSize * 2 + 'rpx', height: value.imageSize * 2 + 'rpx' }">
|
:style="{ fontSize: value.imageSize * 2 + 'rpx', width: value.imageSize * 2 + 'rpx', height: value.imageSize * 2 + 'rpx' }">
|
||||||
<image v-if="item.iconType == 'img'"
|
<image v-if="item.iconType == 'img'"
|
||||||
@@ -159,7 +159,7 @@ export default {
|
|||||||
redirectTo(link) {
|
redirectTo(link) {
|
||||||
|
|
||||||
if (link.wap_url) {
|
if (link.wap_url) {
|
||||||
if (this.$util.getCurrRoute() == this.$util.MEMBER_PAGE_URL && !this.storeToken) {
|
if (this.$util.getCurrRoute() == 'pages/member/index' && !this.storeToken) {
|
||||||
this.$refs.login.open(link.wap_url);
|
this.$refs.login.open(link.wap_url);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -251,16 +251,6 @@
|
|||||||
<diy-icon :value="item"></diy-icon>
|
<diy-icon :value="item"></diy-icon>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-if="item.componentName == 'Tab'">
|
|
||||||
<!-- Tab 组件 -->
|
|
||||||
<diy-tab :value="item" :diyGlobal="diyGlobalData"></diy-tab>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<template v-if="['ChannelList', 'WechatChannel'].includes(item.componentName)">
|
|
||||||
<!-- 视频号列表 -->
|
|
||||||
<diy-channel-list :value="item"></diy-channel-list>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<!-- 自定义扩展组件 -->
|
<!-- 自定义扩展组件 -->
|
||||||
<diy-comp-extend :value="item"></diy-comp-extend>
|
<diy-comp-extend :value="item"></diy-comp-extend>
|
||||||
</view>
|
</view>
|
||||||
@@ -270,9 +260,8 @@
|
|||||||
<script>
|
<script>
|
||||||
// 组件组展示
|
// 组件组展示
|
||||||
import DiyMinx from './minx.js'
|
import DiyMinx from './minx.js'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'diy-group',
|
components: {},
|
||||||
props: {
|
props: {
|
||||||
diyData: {
|
diyData: {
|
||||||
type: Object
|
type: Object
|
||||||
@@ -352,12 +341,6 @@ export default {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else data = this.setPagestyle;
|
} else data = this.setPagestyle;
|
||||||
|
|
||||||
console.log(`diy-group ['diyDataArray'] = `, {
|
|
||||||
data: data,
|
|
||||||
diyData: this.diyData,
|
|
||||||
diyGlobalData: this.diyGlobalData,
|
|
||||||
})
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<x-skeleton data-component-name="diy-groupbuy" :type="skeletonType" :loading="loading" :configs="skeletonConfig">
|
<x-skeleton data-component-name="diy-groupbuy" :type="skeletonType" :loading="loading" :configs="skeletonConfig">
|
||||||
<view class="diy-groupbuy" :class="[value.template, value.style]" :style="warpCss">
|
<view class="diy-groupbuy" :class="[value.template, value.style]" :style="warpCss">
|
||||||
<template v-if="value.template == 'row1-of1'">
|
<template v-if="value.template == 'row1-of1'">
|
||||||
<view class="item" v-for="(item, index) in list" :key="index" @tap.stop="toDetail(item)"
|
<view class="item" v-for="(item, index) in list" :key="index" @click="toDetail(item)"
|
||||||
:class="[value.ornament.type]" :style="goodsItemCss">
|
:class="[value.ornament.type]" :style="goodsItemCss">
|
||||||
<view class="img-wrap" :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }">
|
<view class="img-wrap" :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }">
|
||||||
<image :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }"
|
<image :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }"
|
||||||
@@ -39,7 +39,7 @@
|
|||||||
</template>
|
</template>
|
||||||
<template v-if="value.template == 'horizontal-slide'">
|
<template v-if="value.template == 'horizontal-slide'">
|
||||||
<scroll-view v-if="value.slideMode == 'scroll'" class="scroll" :scroll-x="true" :show-scrollbar="false">
|
<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" @tap.stop="toDetail(item)"
|
<view class="item" v-for="(item, index) in list" :key="index" @click="toDetail(item)"
|
||||||
:class="[value.ornament.type]" :style="goodsItemCss">
|
:class="[value.ornament.type]" :style="goodsItemCss">
|
||||||
<view class="img-wrap" :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }">
|
<view class="img-wrap" :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }">
|
||||||
<image :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }"
|
<image :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }"
|
||||||
@@ -81,7 +81,7 @@
|
|||||||
<swiper-item v-for="(pageItem, pageIndex) in page" :key="pageIndex"
|
<swiper-item v-for="(pageItem, pageIndex) in page" :key="pageIndex"
|
||||||
:class="['swiper-item', (list.length && [list[pageIndex].length / 3] >= 1) && 'flex-between']">
|
:class="['swiper-item', (list.length && [list[pageIndex].length / 3] >= 1) && 'flex-between']">
|
||||||
<view class="item" v-for="(item, dataIndex) in list[pageIndex]" :key="dataIndex"
|
<view class="item" v-for="(item, dataIndex) in list[pageIndex]" :key="dataIndex"
|
||||||
@tap.stop="toDetail(item)" :class="[value.ornament.type]" :style="goodsItemCss">
|
@click="toDetail(item)" :class="[value.ornament.type]" :style="goodsItemCss">
|
||||||
<view class="img-wrap" :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }">
|
<view class="img-wrap" :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }">
|
||||||
<image :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }"
|
<image :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }"
|
||||||
:src="$util.img(item.goods_image, { size: 'mid' })" mode="widthFix"
|
:src="$util.img(item.goods_image, { size: 'mid' })" mode="widthFix"
|
||||||
@@ -274,7 +274,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
::v-deep .uni-scroll-view ::-webkit-scrollbar {
|
/deep/.uni-scroll-view ::-webkit-scrollbar {
|
||||||
/* 隐藏滚动条,但依旧具备可以滚动的功能 */
|
/* 隐藏滚动条,但依旧具备可以滚动的功能 */
|
||||||
display: none;
|
display: none;
|
||||||
width: 0;
|
width: 0;
|
||||||
@@ -283,7 +283,7 @@ export default {
|
|||||||
background: transparent;
|
background: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
::v-deep ::-webkit-scrollbar {
|
/deep/::-webkit-scrollbar {
|
||||||
display: none;
|
display: none;
|
||||||
width: 0;
|
width: 0;
|
||||||
height: 0;
|
height: 0;
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
height: mapItem.height + '%',
|
height: mapItem.height + '%',
|
||||||
left: mapItem.left + '%',
|
left: mapItem.left + '%',
|
||||||
top: mapItem.top + '%'
|
top: mapItem.top + '%'
|
||||||
}" @tap.stop="$util.diyRedirectTo(mapItem.link)"></view>
|
}" @click.stop="$util.diyRedirectTo(mapItem.link)"></view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -15,12 +15,12 @@
|
|||||||
'width': (item.imgWidth / 2 + 'rpx') + ';',
|
'width': (item.imgWidth / 2 + 'rpx') + ';',
|
||||||
'height': (item.imgHeight / 2 + 'rpx') + ';'
|
'height': (item.imgHeight / 2 + 'rpx') + ';'
|
||||||
}" :src="$util.img(item.imageUrl) || $util.img('public/uniapp/default_img/goods.png')"
|
}" :src="$util.img(item.imageUrl) || $util.img('public/uniapp/default_img/goods.png')"
|
||||||
:show-menu-by-longpress="true" @tap.stop="redirectTo(item.link)"></image>
|
:show-menu-by-longpress="true" @tap="redirectTo(item.link)"></image>
|
||||||
<image v-else :style="{
|
<image v-else :style="{
|
||||||
'width': (item.imgWidth / 2 + 'rpx') + ';',
|
'width': (item.imgWidth / 2 + 'rpx') + ';',
|
||||||
'height': (item.imgHeight / 2 + 'rpx') + ';'
|
'height': (item.imgHeight / 2 + 'rpx') + ';'
|
||||||
}" :src="$util.img(item.imageUrl) || $util.img('public/uniapp/default_img/goods.png')"
|
}" :src="$util.img(item.imageUrl) || $util.img('public/uniapp/default_img/goods.png')"
|
||||||
:show-menu-by-longpress="true" @tap.stop="previewImg(item.imageUrl)"></image>
|
:show-menu-by-longpress="true" @tap="previewImg(item.imageUrl)"></image>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 文字部分 -->
|
<!-- 文字部分 -->
|
||||||
@@ -38,11 +38,14 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import nsLogin from '@/components/ns-login/ns-login.vue'
|
||||||
import DiyMinx from './minx.js'
|
import DiyMinx from './minx.js'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'diy-image-nav',
|
name: 'diy-image-nav',
|
||||||
|
components: {
|
||||||
|
nsLogin
|
||||||
|
},
|
||||||
props: {
|
props: {
|
||||||
value: {
|
value: {
|
||||||
type: Object,
|
type: Object,
|
||||||
@@ -103,9 +106,20 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
// 预览图片
|
||||||
|
previewImg(imageUrl) {
|
||||||
|
uni.previewImage({
|
||||||
|
current: 0,
|
||||||
|
urls: [this.$util.img(imageUrl)],
|
||||||
|
success: (res) => { },
|
||||||
|
fail: (res) => { },
|
||||||
|
complete: (res) => { }
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
// 页面跳转
|
// 页面跳转
|
||||||
redirectTo(link) {
|
redirectTo(link) {
|
||||||
if (!link.wap_url || this.$util.getCurrRoute() != this.$util.MEMBER_PAGE_URL || this.storeToken) {
|
if (!link.wap_url || this.$util.getCurrRoute() != 'pages/member/index' || this.storeToken) {
|
||||||
this.$util.diyRedirectTo(link);
|
this.$util.diyRedirectTo(link);
|
||||||
} else {
|
} else {
|
||||||
this.$refs.login.open(link.wap_url);
|
this.$refs.login.open(link.wap_url);
|
||||||
|
|||||||
@@ -2,7 +2,8 @@
|
|||||||
<view data-component-name="diy-img-ads" class="single-graph">
|
<view data-component-name="diy-img-ads" class="single-graph">
|
||||||
<view :style="imgAdsMarginWarp" class="swiper-box">
|
<view :style="imgAdsMarginWarp" class="swiper-box">
|
||||||
<block v-if="imgAdsValue.list.length == 1">
|
<block v-if="imgAdsValue.list.length == 1">
|
||||||
<view class="simple-graph-wrap" :style="imgAdsSwiper" @tap.stop="handlerClick(imgAdsValue.list[0].link)">
|
<view class="simple-graph-wrap" :style="imgAdsSwiper" @click="handlerClick(imgAdsValue.list[0].link)"
|
||||||
|
@tap="handlerClick(imgAdsValue.list[0].link)">
|
||||||
<image :style="{ height: imgAdsValue.list[0].imgHeight }"
|
<image :style="{ height: imgAdsValue.list[0].imgHeight }"
|
||||||
:src="$util.img(imgAdsValue.list[0].imageUrl)" mode="widthFix" :show-menu-by-longpress="true" />
|
:src="$util.img(imgAdsValue.list[0].imageUrl)" mode="widthFix" :show-menu-by-longpress="true" />
|
||||||
</view>
|
</view>
|
||||||
@@ -15,7 +16,7 @@
|
|||||||
indicator-color="rgba(130, 130, 130, .5)" :indicator-active-color="imgAdsValue.indicatorColor"
|
indicator-color="rgba(130, 130, 130, .5)" :indicator-active-color="imgAdsValue.indicatorColor"
|
||||||
@change="swiperChange">
|
@change="swiperChange">
|
||||||
<swiper-item class="swiper-item" :style="imgAdsSwiper" v-for="(item, index) in imgAdsValue.list"
|
<swiper-item class="swiper-item" :style="imgAdsSwiper" v-for="(item, index) in imgAdsValue.list"
|
||||||
:key="index" v-if="item.imageUrl" @tap.stop="handlerClick(item.link)">
|
:key="index" v-if="item.imageUrl" @click="handlerClick(item.link)" @tap="handlerClick(item.link)">
|
||||||
<view class="item" :style="imgAdsSwiper + 'height: ' + item.imgHeight">
|
<view class="item" :style="imgAdsSwiper + 'height: ' + item.imgHeight">
|
||||||
<image :src="$util.img(item.imageUrl)" :mode="item.imageMode || 'scaleToFill'"
|
<image :src="$util.img(item.imageUrl)" :mode="item.imageMode || 'scaleToFill'"
|
||||||
:show-menu-by-longpress="true" />
|
:show-menu-by-longpress="true" />
|
||||||
@@ -279,39 +280,39 @@ export default {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 隐藏滚动条,但依旧具备可以滚动的功能 */
|
/* 隐藏滚动条,但依旧具备可以滚动的功能 */
|
||||||
::v-deep .uni-scroll-view::-webkit-scrollbar {
|
/deep/.uni-scroll-view::-webkit-scrollbar {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.swiper ::v-deep .uni-swiper-dots-horizontal {
|
.swiper /deep/ .uni-swiper-dots-horizontal {
|
||||||
bottom: 25rpx;
|
bottom: 25rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.swiper-left ::v-deep .uni-swiper-dots-horizontal {
|
.swiper-left /deep/ .uni-swiper-dots-horizontal {
|
||||||
left: 40rpx;
|
left: 40rpx;
|
||||||
transform: translate(0);
|
transform: translate(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
.swiper-right ::v-deep .uni-swiper-dots-horizontal {
|
.swiper-right /deep/ .uni-swiper-dots-horizontal {
|
||||||
right: 40rpx;
|
right: 40rpx;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
transform: translate(0);
|
transform: translate(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
.carousel-angle ::v-deep .uni-swiper-dots-horizontal .uni-swiper-dot {
|
.carousel-angle /deep/ .uni-swiper-dots-horizontal .uni-swiper-dot {
|
||||||
width: 24rpx;
|
width: 24rpx;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
height: 8rpx;
|
height: 8rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.swiper.ns-indicator-dots ::v-deep .uni-swiper-dot {
|
.swiper.ns-indicator-dots /deep/ .uni-swiper-dot {
|
||||||
width: 18rpx;
|
width: 18rpx;
|
||||||
height: 6rpx;
|
height: 6rpx;
|
||||||
border-radius: 4rpx;
|
border-radius: 4rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.swiper.ns-indicator-dots ::v-deep .uni-swiper-dot-active {
|
.swiper.ns-indicator-dots /deep/ .uni-swiper-dot-active {
|
||||||
width: 36rpx;
|
width: 36rpx;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
:style="{ background: value.backgroundColor ? value.backgroundColor : '', width: 'calc(100% - 48rpx)' }"
|
:style="{ background: value.backgroundColor ? value.backgroundColor : '', width: 'calc(100% - 48rpx)' }"
|
||||||
@touchmove.stop>
|
@touchmove.stop>
|
||||||
<view class="item" :id="'a' + index" v-for="(item, index) in cateList" :key="index"
|
<view class="item" :id="'a' + index" v-for="(item, index) in cateList" :key="index"
|
||||||
@tap.stop="changePageIndex(index)" :class="{ fill: value.styleType == 'fill' }"
|
@click="changePageIndex(index)" :class="{ fill: value.styleType == 'fill' }"
|
||||||
:style="{ background: index == pageIndex && value.styleType == 'fill' ? value.selectColor : '' }">
|
:style="{ background: index == pageIndex && value.styleType == 'fill' ? value.selectColor : '' }">
|
||||||
<view class="text-con" :class="index == pageIndex ? 'active' : ''" :style="{
|
<view class="text-con" :class="index == pageIndex ? 'active' : ''" :style="{
|
||||||
color: index == pageIndex ? '' : value.noColor
|
color: index == pageIndex ? '' : value.noColor
|
||||||
@@ -25,13 +25,13 @@
|
|||||||
</view>
|
</view>
|
||||||
</scroll-view>
|
</scroll-view>
|
||||||
<text class="iconfont icon-unfold unfold-arrows" :style="{ color: value.moreColor }"
|
<text class="iconfont icon-unfold unfold-arrows" :style="{ color: value.moreColor }"
|
||||||
@tap.stop="unfoldMenu"></text>
|
@click="unfoldMenu"></text>
|
||||||
</view>
|
</view>
|
||||||
<uni-popup ref="navTopCategoryPop" type="top" :top="uniPopTop">
|
<uni-popup ref="navTopCategoryPop" type="top" :top="uniPopTop">
|
||||||
<view class="nav-topcategory-pop">
|
<view class="nav-topcategory-pop">
|
||||||
<text v-for="(item, index) in cateList" :key="index"
|
<text v-for="(item, index) in cateList" :key="index"
|
||||||
:class="['category-item', { 'color-base-text color-base-border active': pageIndex == index }]"
|
:class="['category-item', { 'color-base-text color-base-border active': pageIndex == index }]"
|
||||||
@tap.stop="changePageIndex(index)">
|
@click="changePageIndex(index)">
|
||||||
{{ item.short_name ? item.short_name : item.category_name }}
|
{{ item.short_name ? item.short_name : item.category_name }}
|
||||||
</text>
|
</text>
|
||||||
</view>
|
</view>
|
||||||
@@ -55,7 +55,7 @@
|
|||||||
<view class="twoCategory min" v-if="twoCategorylist.length <= 5">
|
<view class="twoCategory min" v-if="twoCategorylist.length <= 5">
|
||||||
<view class="twoCategory-page">
|
<view class="twoCategory-page">
|
||||||
<view class="swiper-item" v-for="(item, index) in twoCategorylist"
|
<view class="swiper-item" v-for="(item, index) in twoCategorylist"
|
||||||
:key="index" @tap.stop="toCateGoodsList(item.category_id_2, 2)">
|
:key="index" @click="toCateGoodsList(item.category_id_2, 2)">
|
||||||
<view class="item-box">
|
<view class="item-box">
|
||||||
<image :src="$util.img(item.image)" v-if="item.image"
|
<image :src="$util.img(item.image)" v-if="item.image"
|
||||||
mode="aspectFill" />
|
mode="aspectFill" />
|
||||||
@@ -70,7 +70,7 @@
|
|||||||
v-if="twoCategorylist.length > 5 && twoCategorylist.length <= 10">
|
v-if="twoCategorylist.length > 5 && twoCategorylist.length <= 10">
|
||||||
<view class="twoCategory-page">
|
<view class="twoCategory-page">
|
||||||
<view class="swiper-item" v-for="(item, index) in twoCategorylist"
|
<view class="swiper-item" v-for="(item, index) in twoCategorylist"
|
||||||
:key="index" @tap.stop="toCateGoodsList(item.category_id_2, 2)">
|
:key="index" @click="toCateGoodsList(item.category_id_2, 2)">
|
||||||
<view class="item-box">
|
<view class="item-box">
|
||||||
<image :src="$util.img(item.image)" v-if="item.image"
|
<image :src="$util.img(item.image)" v-if="item.image"
|
||||||
mode="aspectFill" />
|
mode="aspectFill" />
|
||||||
@@ -86,7 +86,7 @@
|
|||||||
<swiper-item class="twoCategory-page" v-for="page in maxPage" :key="page">
|
<swiper-item class="twoCategory-page" v-for="page in maxPage" :key="page">
|
||||||
<view class="swiper-item" v-for="(item, index) in twoCategorylist"
|
<view class="swiper-item" v-for="(item, index) in twoCategorylist"
|
||||||
:key="index" v-if="index >= (page - 1) * 10 && index < page * 10"
|
:key="index" v-if="index >= (page - 1) * 10 && index < page * 10"
|
||||||
@tap.stop="toCateGoodsList(item.category_id_2, 2)">
|
@click="toCateGoodsList(item.category_id_2, 2)">
|
||||||
<view class="item-box">
|
<view class="item-box">
|
||||||
<image :src="item.image" mode="aspectFill" />
|
<image :src="item.image" mode="aspectFill" />
|
||||||
<view>{{ item.category_name }}</view>
|
<view>{{ item.category_name }}</view>
|
||||||
@@ -108,7 +108,7 @@
|
|||||||
|
|
||||||
<view class="goods-list double-column" v-if="goodsList[pageIndex].list.length">
|
<view class="goods-list double-column" v-if="goodsList[pageIndex].list.length">
|
||||||
<view class="goods-item" v-for="(item, index) in goodsList[pageIndex].list"
|
<view class="goods-item" v-for="(item, index) in goodsList[pageIndex].list"
|
||||||
:key="index" @tap.stop="toDetail(item)">
|
:key="index" @click="toDetail(item)">
|
||||||
<view class="goods-img">
|
<view class="goods-img">
|
||||||
<image :src="goodsImg(item.goods_image)" mode="widthFix"
|
<image :src="goodsImg(item.goods_image)" mode="widthFix"
|
||||||
@error="imgError(index)" />
|
@error="imgError(index)" />
|
||||||
@@ -169,6 +169,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import nsLoading from '@/components/ns-loading/ns-loading.vue';
|
||||||
import DiyMinx from './minx.js'
|
import DiyMinx from './minx.js'
|
||||||
export default {
|
export default {
|
||||||
name: 'diy-index-page',
|
name: 'diy-index-page',
|
||||||
@@ -188,6 +189,9 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
mixins: [DiyMinx],
|
mixins: [DiyMinx],
|
||||||
|
components: {
|
||||||
|
nsLoading
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
pageIndex: 0, //当前选中分类id
|
pageIndex: 0, //当前选中分类id
|
||||||
@@ -732,7 +736,7 @@ export default {
|
|||||||
margin-top: 100rpx;
|
margin-top: 100rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
::v-deep .uni-scroll-view::-webkit-scrollbar {
|
/deep/.uni-scroll-view::-webkit-scrollbar {
|
||||||
/* 隐藏滚动条,但依旧具备可以滚动的功能 */
|
/* 隐藏滚动条,但依旧具备可以滚动的功能 */
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<view data-component-name="diy-kefu" class="diy-kefu" :style="style">
|
<view data-component-name="diy-kefu" class="diy-kefu" :style="style">
|
||||||
<view class="fui-list-group merchgroup" v-for="(item, index) in value.list" :key="index">
|
<view class="fui-list-group merchgroup" v-for="(item, index) in value.list">
|
||||||
<view class="fui-list jump" v-if="index == 0">
|
<view class="fui-list jump" v-if="index == 0">
|
||||||
<view class="fui-list-media">
|
<view class="fui-list-media">
|
||||||
<image class="round" :src="$util.img(item.imageUrl)" style="border-radius:6rpx"></image>
|
<image class="round" :src="$util.img(item.imageUrl)" style="border-radius:6rpx"></image>
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
</view>
|
</view>
|
||||||
<view class="fui-remark jump" style="padding-right: 20rpx; text-align: center; line-height: 140rpx;">
|
<view class="fui-remark jump" style="padding-right: 20rpx; text-align: center; line-height: 140rpx;">
|
||||||
<span style="font-size:24rpx;padding: 14rpx 18rpx;border-radius:8rpx"
|
<span style="font-size:24rpx;padding: 14rpx 18rpx;border-radius:8rpx"
|
||||||
:style="{ background: item.BtBgColor, color: item.BtColor }" @tap.stop="previewSqs()">立即添加</span>
|
:style="{ background: item.BtBgColor, color: item.BtColor }" @click="previewSqs()">立即添加</span>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<template>
|
<template>
|
||||||
<view data-component-name="diy-listmenu" class="diy-listmenu" :style="style">
|
<view data-component-name="diy-picture" class="diy-picture" :style="style">
|
||||||
<view class="fui-cell-group">
|
<view class="fui-cell-group">
|
||||||
<!-- <image mode="widthFix" style="width: 100%;" :src="$util.img(item.imageUrl)"></image> -->
|
<!-- <image mode="widthFix" style="width: 100%;" :src="$util.img(item.imageUrl)"></image> -->
|
||||||
|
|
||||||
<view v-for="(item, index) in value.list" @tap.stop="redirectTo(item.link)" class="fui-cell"
|
<view v-for="(item, index) in value.list" @click="redirectTo(item.link)" class="fui-cell"
|
||||||
:class="item.iconType == 'img' ? 'img-cell' : ''">
|
:class="item.iconType == 'img' ? 'img-cell' : ''">
|
||||||
<view class="fui-cell-icon" :style="{ 'color': item.style ? item.style.iconColor : '#333' }">
|
<view class="fui-cell-icon" :style="{ 'color': item.style ? item.style.iconColor : '#333' }">
|
||||||
<diy-icon v-if="item.iconType == 'icon'" :icon="item.icon" :value="item.style ? item.style : null"
|
<diy-icon v-if="item.iconType == 'icon'" :icon="item.icon" :value="item.style ? item.style : null"
|
||||||
@@ -62,8 +62,8 @@ export default {
|
|||||||
methods: {
|
methods: {
|
||||||
redirectTo(link) {
|
redirectTo(link) {
|
||||||
if (link.wap_url) {
|
if (link.wap_url) {
|
||||||
if (this.$util.getCurrRoute() == this.$util.MEMBER_PAGE_URL && !this.storeToken) {
|
if (this.$util.getCurrRoute() == 'pages/member/index' && !this.storeToken) {
|
||||||
this.$refs?.login?.open(link.wap_url);
|
this.$refs.login.open(link.wap_url);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<x-skeleton data-component-name="diy-live" type="banner" :loading="loading" :configs="skeletonConfig">
|
<x-skeleton data-component-name="diy-live" type="banner" :loading="loading" :configs="skeletonConfig">
|
||||||
<view class="live-wrap" @tap.stop="handlerClick(liveInfo.roomid)"
|
<view class="live-wrap" @click="handlerClick(liveInfo.roomid)" @tap="handlerClick(liveInfo.roomid)"
|
||||||
v-if="liveInfo">
|
v-if="liveInfo">
|
||||||
<view class="banner-wrap">
|
<view class="banner-wrap">
|
||||||
<image
|
<image
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<scroll-view scroll-x="true" class="many-goods-list-head" :scroll-into-view="'a' + cateIndex"
|
<scroll-view scroll-x="true" class="many-goods-list-head" :scroll-into-view="'a' + cateIndex"
|
||||||
:style="manyWrapCss">
|
:style="manyWrapCss">
|
||||||
<view v-for="(item, index) in value.list" class="scroll-item" :class="{ active: index == cateIndex }"
|
<view v-for="(item, index) in value.list" class="scroll-item" :class="{ active: index == cateIndex }"
|
||||||
:id="'a' + index" :key="index" @tap.stop="handlerClick({ item, index })">
|
:id="'a' + index" :key="index" @click="handlerClick({ item, index })" @tap="handlerClick({ item, index })">
|
||||||
<view class="split-line" v-if="index > 0"></view>
|
<view class="split-line" v-if="index > 0"></view>
|
||||||
<view class="cate">
|
<view class="cate">
|
||||||
<view class="name" :style="{ color: value.headStyle.titleColor }">{{ item.title }}</view>
|
<view class="name" :style="{ color: value.headStyle.titleColor }">{{ item.title }}</view>
|
||||||
|
|||||||
@@ -3,18 +3,11 @@
|
|||||||
<view class="fui-list-group merchgroup" style="margin-top:0" v-for="(item, index) in value.list">
|
<view class="fui-list-group merchgroup" style="margin-top:0" v-for="(item, index) in value.list">
|
||||||
<map id="map" style="width: 100%; height:600rpx" scale="12" :markers="markerst" bindupdated="bindupdated"
|
<map id="map" style="width: 100%; height:600rpx" scale="12" :markers="markerst" bindupdated="bindupdated"
|
||||||
:longitude="item.lng" :latitude="item.lat" show-location>
|
:longitude="item.lng" :latitude="item.lat" show-location>
|
||||||
<!-- <cover-view
|
<cover-view
|
||||||
style="position:absolute;right:10px;bottom:30rpx;z-index:99999;background:#4390FF;padding:5px 10px;wxcs_style_padding:10rpx 20rpx;border-radius:8rpx;color: #fff;"
|
style="position:absolute;right:10px;bottom:30rpx;z-index:99999;background:#4390FF;padding:5px 10px;wxcs_style_padding:10rpx 20rpx;border-radius:8rpx;color: #fff;"
|
||||||
@tap.stop="handlerClick(item)" @tap="handlerClick(item)">
|
@click="handlerClick(item)" @tap="handlerClick(item)">
|
||||||
<cover-view style="font-size:24rpx">一键导航</cover-view>
|
<cover-view style="font-size:24rpx">一键导航</cover-view>
|
||||||
</cover-view> -->
|
</cover-view>
|
||||||
|
|
||||||
<!-- 使用非原生cover-view, 解决原生cover-view组件渲染机制z-index失效的问题 -->
|
|
||||||
<div
|
|
||||||
style="position:absolute;right:12rpx;bottom:48rpx;z-index:1;background:#4390FF;padding:0rpx 20rpx;border-radius:8rpx;color: #fff;"
|
|
||||||
@tap.stop="handlerClick(item)">
|
|
||||||
<span style="font-size:24rpx;color: #fff;">一键导航</span>
|
|
||||||
</div>
|
|
||||||
</map>
|
</map>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<view class="common-wrap info-wrap" :class="[`data-style-${value.style}`]">
|
<view class="common-wrap info-wrap" :class="[`data-style-${value.style}`]">
|
||||||
<view class="member-info" :style="memberInfoStyle">
|
<view class="member-info" :style="memberInfoStyle">
|
||||||
<view class="info-wrap" :style="infoStyle" v-if="memberInfo">
|
<view class="info-wrap" :style="infoStyle" v-if="memberInfo">
|
||||||
<view class="headimg" @tap.stop="getWxAuth">
|
<view class="headimg" @click="getWxAuth">
|
||||||
<image :src="memberInfo.headimg ? $util.img(memberInfo.headimg) : $util.getDefaultImage().head"
|
<image :src="memberInfo.headimg ? $util.img(memberInfo.headimg) : $util.getDefaultImage().head"
|
||||||
mode="widthFix" @error="memberInfo.headimg = $util.getDefaultImage().head" />
|
mode="widthFix" @error="memberInfo.headimg = $util.getDefaultImage().head" />
|
||||||
</view>
|
</view>
|
||||||
@@ -12,10 +12,10 @@
|
|||||||
<!-- #ifdef MP -->
|
<!-- #ifdef MP -->
|
||||||
<block
|
<block
|
||||||
v-if="(memberInfo.nickname.indexOf('u_') != -1 && memberInfo.nickname == memberInfo.username) || memberInfo.nickname == memberInfo.mobile">
|
v-if="(memberInfo.nickname.indexOf('u_') != -1 && memberInfo.nickname == memberInfo.username) || memberInfo.nickname == memberInfo.mobile">
|
||||||
<view class="nickname"><text class="name" @tap.stop="getWxAuth">点击授权头像昵称</text></view>
|
<view class="nickname"><text class="name" @click="getWxAuth">点击授权头像昵称</text></view>
|
||||||
</block>
|
</block>
|
||||||
<view class="nickname" v-else>
|
<view class="nickname" v-else>
|
||||||
<text class="name" @tap.stop="getWxAuth">{{ memberInfo.nickname }}</text>
|
<text class="name" @click="getWxAuth">{{ memberInfo.nickname }}</text>
|
||||||
<view class="member-level"
|
<view class="member-level"
|
||||||
v-if="(value.style == 1 || value.style == 2) && memberInfo.member_level">
|
v-if="(value.style == 1 || value.style == 2) && memberInfo.member_level">
|
||||||
<!-- <text class="icondiy icon-system-huangguan"></text> -->
|
<!-- <text class="icondiy icon-system-huangguan"></text> -->
|
||||||
@@ -36,10 +36,10 @@
|
|||||||
<!-- #ifdef H5 -->
|
<!-- #ifdef H5 -->
|
||||||
<block
|
<block
|
||||||
v-if="$util.isWeiXin() && ((memberInfo.nickname.indexOf('u_') != -1 && memberInfo.nickname == memberInfo.username) || memberInfo.nickname == memberInfo.mobile)">
|
v-if="$util.isWeiXin() && ((memberInfo.nickname.indexOf('u_') != -1 && memberInfo.nickname == memberInfo.username) || memberInfo.nickname == memberInfo.mobile)">
|
||||||
<view class="nickname"><text class="name" @tap.stop="getWxAuth">点击获取微信头像</text></view>
|
<view class="nickname"><text class="name" @click="getWxAuth">点击获取微信头像</text></view>
|
||||||
</block>
|
</block>
|
||||||
<view class="nickname" v-else>
|
<view class="nickname" v-else>
|
||||||
<text class="name" @tap.stop="redirect('/pages_tool/member/info')">{{ memberInfo.nickname
|
<text class="name" @click="redirect('/pages_tool/member/info')">{{ memberInfo.nickname
|
||||||
}}</text>
|
}}</text>
|
||||||
<view class="member-level"
|
<view class="member-level"
|
||||||
v-if="(value.style == 1 || value.style == 2) && memberInfo.member_level">
|
v-if="(value.style == 1 || value.style == 2) && memberInfo.member_level">
|
||||||
@@ -61,10 +61,10 @@
|
|||||||
</view>
|
</view>
|
||||||
<view v-if="ischina == 1"
|
<view v-if="ischina == 1"
|
||||||
style="background: #fff;height: 60rpx;width: 60rpx;border-radius: 50rpx;line-height:65rpx;text-align: center;color:#000"
|
style="background: #fff;height: 60rpx;width: 60rpx;border-radius: 50rpx;line-height:65rpx;text-align: center;color:#000"
|
||||||
@tap.stop="modifyInfo()">{{ langIndex == 0 ? 'CN' : 'EN' }}</view>
|
@click.stop="modifyInfo()">{{ langIndex == 0 ? 'CN' : 'EN' }}</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view class="info-wrap" v-else :style="infoStyle" @tap.stop="redirect($util.MEMBER_PAGE_URL)">
|
<view class="info-wrap" v-else :style="infoStyle" @click="redirect('/pages/member/index')">
|
||||||
<view class="headimg">
|
<view class="headimg">
|
||||||
<image :src="$util.getDefaultImage().head" mode="widthFix"></image>
|
<image :src="$util.getDefaultImage().head" mode="widthFix"></image>
|
||||||
</view>
|
</view>
|
||||||
@@ -75,12 +75,12 @@
|
|||||||
|
|
||||||
<view v-if="ischina == 1"
|
<view v-if="ischina == 1"
|
||||||
style="background: #fff;height: 60rpx;width: 60rpx;border-radius: 50rpx;line-height:65rpx;text-align: center;color:#000"
|
style="background: #fff;height: 60rpx;width: 60rpx;border-radius: 50rpx;line-height:65rpx;text-align: center;color:#000"
|
||||||
@tap.stop="modifyInfo()">{{ langIndex == 0 ? 'CN' : 'EN' }}</view>
|
@click.stop="modifyInfo()">{{ langIndex == 0 ? 'CN' : 'EN' }}</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view class="account-info" v-show="value.style == 1"
|
<view class="account-info" v-show="value.style == 1"
|
||||||
:style="{ 'margin-left': parseInt(value.infoMargin) * 2 + 'rpx', 'margin-right': parseInt(value.infoMargin) * 2 + 'rpx' }">
|
:style="{ 'margin-left': parseInt(value.infoMargin) * 2 + 'rpx', 'margin-right': parseInt(value.infoMargin) * 2 + 'rpx' }">
|
||||||
<view class="account-item" @tap.stop="redirect('/pages_tool/member/balance')">
|
<view class="account-item" @click="redirect('/pages_tool/member/balance')">
|
||||||
<view class="value price-font">
|
<view class="value price-font">
|
||||||
{{ memberInfo ? (parseFloat(memberInfo.balance) +
|
{{ memberInfo ? (parseFloat(memberInfo.balance) +
|
||||||
parseFloat(memberInfo.balance_money)).toFixed(2) : '--' }}
|
parseFloat(memberInfo.balance_money)).toFixed(2) : '--' }}
|
||||||
@@ -88,12 +88,12 @@
|
|||||||
<view class="title">{{ $lang('balance') }}</view>
|
<view class="title">{{ $lang('balance') }}</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="solid"></view>
|
<view class="solid"></view>
|
||||||
<view class="account-item" @tap.stop="redirect('/pages_tool/member/point_detail')">
|
<view class="account-item" @click="redirect('/pages_tool/member/point_detail')">
|
||||||
<view class="value price-font">{{ memberInfo ? parseFloat(memberInfo.point) : '--' }}</view>
|
<view class="value price-font">{{ memberInfo ? parseFloat(memberInfo.point) : '--' }}</view>
|
||||||
<view class="title">{{ $lang('point') }}</view>
|
<view class="title">{{ $lang('point') }}</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="solid"></view>
|
<view class="solid"></view>
|
||||||
<view class="account-item" @tap.stop="redirect('/pages_tool/member/coupon')">
|
<view class="account-item" @click="redirect('/pages_tool/member/coupon')">
|
||||||
<view class="value price-font">
|
<view class="value price-font">
|
||||||
{{ memberInfo && memberInfo.coupon_num != undefined ? memberInfo.coupon_num : '--' }}
|
{{ memberInfo && memberInfo.coupon_num != undefined ? memberInfo.coupon_num : '--' }}
|
||||||
</view>
|
</view>
|
||||||
@@ -110,8 +110,8 @@
|
|||||||
<text>超级会员</text>
|
<text>超级会员</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="super-text">
|
<view class="super-text">
|
||||||
<text class="see" v-if="memberInfo && memberInfo.member_level_type" @tap.stop="redirectBeforeAuth('/pages_tool/member/card')">查看特权</text>
|
<text class="see" v-if="memberInfo && memberInfo.member_level_type" @click="redirectBeforeAuth('/pages_tool/member/card')">查看特权</text>
|
||||||
<text class="see" v-else @tap.stop="redirectBeforeAuth('/pages_tool/member/card_buy')">会员可享更多权益</text>
|
<text class="see" v-else @click="redirectBeforeAuth('/pages_tool/member/card_buy')">会员可享更多权益</text>
|
||||||
<text class="iconfont icon-right"></text>
|
<text class="iconfont icon-right"></text>
|
||||||
</view>
|
</view>
|
||||||
</block>
|
</block>
|
||||||
@@ -121,8 +121,8 @@
|
|||||||
<view class="desc">开通可享更多权益</view>
|
<view class="desc">开通可享更多权益</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="super-text">
|
<view class="super-text">
|
||||||
<text class="see" v-if="memberInfo && memberInfo.member_level_type" @tap.stop="redirectBeforeAuth('/pages_tool/member/card')">查看特权</text>
|
<text class="see" v-if="memberInfo && memberInfo.member_level_type" @click="redirectBeforeAuth('/pages_tool/member/card')">查看特权</text>
|
||||||
<text class="see" v-else @tap.stop="redirectBeforeAuth('/pages_tool/member/card_buy')">立即开通</text>
|
<text class="see" v-else @click="redirectBeforeAuth('/pages_tool/member/card_buy')">立即开通</text>
|
||||||
</view>
|
</view>
|
||||||
</block>
|
</block>
|
||||||
</view>
|
</view>
|
||||||
@@ -134,25 +134,25 @@
|
|||||||
<view class="desc">开通可享更多权益</view>
|
<view class="desc">开通可享更多权益</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="super-text" :class="{ 'more' : memberInfo && memberInfo.member_level_type }">
|
<view class="super-text" :class="{ 'more' : memberInfo && memberInfo.member_level_type }">
|
||||||
<text class="see" v-if="memberInfo && memberInfo.member_level_type" @tap.stop="redirectBeforeAuth('/pages_tool/member/card')">查看更多权益</text>
|
<text class="see" v-if="memberInfo && memberInfo.member_level_type" @click="redirectBeforeAuth('/pages_tool/member/card')">查看更多权益</text>
|
||||||
<text class="see" v-else @tap.stop="redirectBeforeAuth('/pages_tool/member/card_buy')">立即开通</text>
|
<text class="see" v-else @click="redirectBeforeAuth('/pages_tool/member/card_buy')">立即开通</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="account-info" :style="{ 'margin-left': parseInt(value.infoMargin) * 2 + 'rpx', 'margin-right': parseInt(value.infoMargin) * 2 + 'rpx' }">
|
<view class="account-info" :style="{ 'margin-left': parseInt(value.infoMargin) * 2 + 'rpx', 'margin-right': parseInt(value.infoMargin) * 2 + 'rpx' }">
|
||||||
<view class="account-item" @tap.stop="redirect('/pages_tool/member/balance_detail')">
|
<view class="account-item" @click="redirect('/pages_tool/member/balance_detail')">
|
||||||
<view class="value price-font">
|
<view class="value price-font">
|
||||||
{{ memberInfo ? (parseFloat(memberInfo.balance) + parseFloat(memberInfo.balance_money)).toFixed(2) : '--' }}
|
{{ memberInfo ? (parseFloat(memberInfo.balance) + parseFloat(memberInfo.balance_money)).toFixed(2) : '--' }}
|
||||||
</view>
|
</view>
|
||||||
<view class="title">余额</view>
|
<view class="title">余额</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="solid"></view>
|
<view class="solid"></view>
|
||||||
<view class="account-item" @tap.stop="redirect('/pages_tool/member/point_detail')">
|
<view class="account-item" @click="redirect('/pages_tool/member/point_detail')">
|
||||||
<view class="value price-font">{{ memberInfo ? parseFloat(memberInfo.point) : '--' }}
|
<view class="value price-font">{{ memberInfo ? parseFloat(memberInfo.point) : '--' }}
|
||||||
</view>
|
</view>
|
||||||
<view class="title">积分</view>
|
<view class="title">积分</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="solid"></view>
|
<view class="solid"></view>
|
||||||
<view class="account-item" @tap.stop="redirect('/pages_tool/member/coupon')">
|
<view class="account-item" @click="redirect('/pages_tool/member/coupon')">
|
||||||
<view class="value price-font">
|
<view class="value price-font">
|
||||||
{{ memberInfo && memberInfo.coupon_num != undefined ? memberInfo.coupon_num : '--' }}
|
{{ memberInfo && memberInfo.coupon_num != undefined ? memberInfo.coupon_num : '--' }}
|
||||||
</view>
|
</view>
|
||||||
@@ -161,7 +161,7 @@
|
|||||||
</view>
|
</view>
|
||||||
<view class="style4-other">
|
<view class="style4-other">
|
||||||
<view class="style4-btn-wrap">
|
<view class="style4-btn-wrap">
|
||||||
<view @tap.stop="redirect('/pages_tool/recharge/list')" class="recharge-btn">余额充值</view>
|
<view @click="redirect('/pages_tool/recharge/list')" class="recharge-btn">余额充值</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view> -->
|
</view> -->
|
||||||
@@ -169,18 +169,18 @@
|
|||||||
|
|
||||||
<view class="account-info" v-show="value.style == 2"
|
<view class="account-info" v-show="value.style == 2"
|
||||||
:style="{ 'margin-left': parseInt(value.infoMargin) * 2 + 'rpx', 'margin-right': parseInt(value.infoMargin) * 2 + 'rpx' }">
|
:style="{ 'margin-left': parseInt(value.infoMargin) * 2 + 'rpx', 'margin-right': parseInt(value.infoMargin) * 2 + 'rpx' }">
|
||||||
<view class="account-item" @tap.stop="redirect('/pages_tool/member/balance')">
|
<view class="account-item" @click="redirect('/pages_tool/member/balance')">
|
||||||
<view class="value price-font">{{ memberInfo ? (parseFloat(memberInfo.balance) +
|
<view class="value price-font">{{ memberInfo ? (parseFloat(memberInfo.balance) +
|
||||||
parseFloat(memberInfo.balance_money)).toFixed(2) : '--' }}</view>
|
parseFloat(memberInfo.balance_money)).toFixed(2) : '--' }}</view>
|
||||||
<view class="title">{{ $lang('balance') }}</view>
|
<view class="title">{{ $lang('balance') }}</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="solid"></view>
|
<view class="solid"></view>
|
||||||
<view class="account-item" @tap.stop="redirect('/pages_tool/member/point_detail')">
|
<view class="account-item" @click="redirect('/pages_tool/member/point_detail')">
|
||||||
<view class="value price-font">{{ memberInfo ? parseFloat(memberInfo.point) : '--' }}</view>
|
<view class="value price-font">{{ memberInfo ? parseFloat(memberInfo.point) : '--' }}</view>
|
||||||
<view class="title">{{ $lang('point') }}</view>
|
<view class="title">{{ $lang('point') }}</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="solid"></view>
|
<view class="solid"></view>
|
||||||
<view class="account-item" @tap.stop="redirect('/pages_tool/member/coupon')">
|
<view class="account-item" @click="redirect('/pages_tool/member/coupon')">
|
||||||
<view class="value price-font">
|
<view class="value price-font">
|
||||||
{{ memberInfo && memberInfo.coupon_num != undefined ? memberInfo.coupon_num : '--' }}
|
{{ memberInfo && memberInfo.coupon_num != undefined ? memberInfo.coupon_num : '--' }}
|
||||||
</view>
|
</view>
|
||||||
@@ -196,7 +196,7 @@
|
|||||||
<view class="head">
|
<view class="head">
|
||||||
<text class="title">获取您的昵称、头像</text>
|
<text class="title">获取您的昵称、头像</text>
|
||||||
<text class="color-tip tips">获取用户头像、昵称完善个人资料,主要用于向用户提供具有辨识度的用户中心界面</text>
|
<text class="color-tip tips">获取用户头像、昵称完善个人资料,主要用于向用户提供具有辨识度的用户中心界面</text>
|
||||||
<text class="iconfont icon-close color-tip" @tap.stop="cancelCompleteInfo"></text>
|
<text class="iconfont icon-close color-tip" @click="cancelCompleteInfo"></text>
|
||||||
</view>
|
</view>
|
||||||
<!-- #ifdef MP-WEIXIN -->
|
<!-- #ifdef MP-WEIXIN -->
|
||||||
<view class="item-wrap">
|
<view class="item-wrap">
|
||||||
@@ -227,7 +227,7 @@
|
|||||||
<input type="nickname" placeholder="请输入昵称" v-model="nickName" @blur="blurNickName" />
|
<input type="nickname" placeholder="请输入昵称" v-model="nickName" @blur="blurNickName" />
|
||||||
</view>
|
</view>
|
||||||
<!-- #endif -->
|
<!-- #endif -->
|
||||||
<button type="default" class="save-btn" @tap.stop="saveCompleteInfo" :disabled="isDisabled">保存</button>
|
<button type="default" class="save-btn" @click="saveCompleteInfo" :disabled="isDisabled">保存</button>
|
||||||
</view>
|
</view>
|
||||||
</uni-popup>
|
</uni-popup>
|
||||||
</view>
|
</view>
|
||||||
@@ -243,7 +243,7 @@ let menuButtonInfo = {};
|
|||||||
menuButtonInfo = uni.getMenuButtonBoundingClientRect();
|
menuButtonInfo = uni.getMenuButtonBoundingClientRect();
|
||||||
// #endif
|
// #endif
|
||||||
// 自定义会员中心——会员信息展示
|
// 自定义会员中心——会员信息展示
|
||||||
|
import nsContact from '@/components/ns-contact/ns-contact.vue';
|
||||||
import DiyMinx from './minx.js'
|
import DiyMinx from './minx.js'
|
||||||
export default {
|
export default {
|
||||||
name: 'diy-member-info',
|
name: 'diy-member-info',
|
||||||
@@ -259,6 +259,9 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
mixins: [DiyMinx],
|
mixins: [DiyMinx],
|
||||||
|
components: {
|
||||||
|
nsContact
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
info: null,
|
info: null,
|
||||||
@@ -545,7 +548,7 @@ export default {
|
|||||||
*/
|
*/
|
||||||
redirectBeforeAuth(url) {
|
redirectBeforeAuth(url) {
|
||||||
if (!this.storeToken) {
|
if (!this.storeToken) {
|
||||||
this.$refs.login.open(this.$util.MEMBER_PAGE_URL);
|
this.$refs.login.open('/pages/member/index');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -583,7 +586,7 @@ export default {
|
|||||||
url: '/wechat/api/wechat/authcode',
|
url: '/wechat/api/wechat/authcode',
|
||||||
data: {
|
data: {
|
||||||
scopes: 'snsapi_userinfo',
|
scopes: 'snsapi_userinfo',
|
||||||
redirect_url: this.$config.h5Domain + this.$util.MEMBER_PAGE_URL
|
redirect_url: this.$config.h5Domain + '/pages/member/index'
|
||||||
},
|
},
|
||||||
success: res => {
|
success: res => {
|
||||||
if (res.code >= 0) {
|
if (res.code >= 0) {
|
||||||
@@ -1380,11 +1383,11 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
::v-deep .uni-popup__wrapper.uni-custom .uni-popup__wrapper-box {
|
/deep/ .uni-popup__wrapper.uni-custom .uni-popup__wrapper-box {
|
||||||
background: none !important;
|
background: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
::v-deep .member-info-style4 .uni-popup__wrapper.uni-custom .uni-popup__wrapper-box {
|
/deep/ .member-info-style4 .uni-popup__wrapper.uni-custom .uni-popup__wrapper-box {
|
||||||
background: #fff !important;
|
background: #fff !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1484,8 +1487,8 @@ export default {
|
|||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.member-complete-info-popup ::v-deep .uni-popup__wrapper.bottom,
|
.member-complete-info-popup /deep/ .uni-popup__wrapper.bottom,
|
||||||
.member-complete-info-popup ::v-deep .uni-popup__wrapper.bottom .uni-popup__wrapper-box {
|
.member-complete-info-popup /deep/ .uni-popup__wrapper.bottom .uni-popup__wrapper-box {
|
||||||
border-top-left-radius: 30rpx !important;
|
border-top-left-radius: 30rpx !important;
|
||||||
border-top-right-radius: 30rpx !important;
|
border-top-right-radius: 30rpx !important;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<view data-component-name="diy-member-my-order" class="common-wrap" :style="warpCss">
|
<view data-component-name="diy-member-my-order" class="common-wrap" :style="warpCss">
|
||||||
<view class="order-wrap">
|
<view class="order-wrap">
|
||||||
<view class="status-wrap">
|
<view class="status-wrap">
|
||||||
<view class="item-wrap" @tap.stop="redirect('/pages_order/list?status=waitpay')"
|
<view class="item-wrap" @click="redirect('/pages_order/list?status=waitpay')"
|
||||||
style="margin-right: 10rpx;">
|
style="margin-right: 10rpx;">
|
||||||
<view class="icon-block">
|
<view class="icon-block">
|
||||||
<template v-if="value.style == 3">
|
<template v-if="value.style == 3">
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
</view>
|
</view>
|
||||||
<view class="title">{{ $lang('waitpay') }}</view>
|
<view class="title">{{ $lang('waitpay') }}</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="item-wrap" @tap.stop="redirect('/pages_order/list?status=waitsend')"
|
<view class="item-wrap" @click="redirect('/pages_order/list?status=waitsend')"
|
||||||
style="margin-right: 10rpx;">
|
style="margin-right: 10rpx;">
|
||||||
<view class="icon-block">
|
<view class="icon-block">
|
||||||
<template v-if="value.style == 3">
|
<template v-if="value.style == 3">
|
||||||
@@ -40,7 +40,7 @@
|
|||||||
</view>
|
</view>
|
||||||
<view class="title">{{ $lang('waitsend') }}</view>
|
<view class="title">{{ $lang('waitsend') }}</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="item-wrap" @tap.stop="redirect('/pages_order/list?status=waitconfirm')"
|
<view class="item-wrap" @click="redirect('/pages_order/list?status=waitconfirm')"
|
||||||
style="margin-right: 10rpx;">
|
style="margin-right: 10rpx;">
|
||||||
<view class="icon-block">
|
<view class="icon-block">
|
||||||
<template v-if="value.style == 3">
|
<template v-if="value.style == 3">
|
||||||
@@ -59,7 +59,7 @@
|
|||||||
</view>
|
</view>
|
||||||
<view class="title">{{ $lang('waitconfirm') }}</view>
|
<view class="title">{{ $lang('waitconfirm') }}</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="item-wrap" @tap.stop="redirect('/pages_order/list?status=waitrate')"
|
<view class="item-wrap" @click="redirect('/pages_order/list?status=waitrate')"
|
||||||
style="margin-right: 10rpx;">
|
style="margin-right: 10rpx;">
|
||||||
<view class="icon-block">
|
<view class="icon-block">
|
||||||
<template v-if="value.style == 3">
|
<template v-if="value.style == 3">
|
||||||
@@ -76,7 +76,7 @@
|
|||||||
</view>
|
</view>
|
||||||
<view class="title">{{ $lang('completed') }}</view>
|
<view class="title">{{ $lang('completed') }}</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="item-wrap" @tap.stop="redirect('/pages_tool/order/activist')">
|
<view class="item-wrap" @click="redirect('/pages_tool/order/activist')">
|
||||||
<view class="icon-block">
|
<view class="icon-block">
|
||||||
<template v-if="value.style == 3">
|
<template v-if="value.style == 3">
|
||||||
<image :src="$util.img('public/uniapp/member/order/refunding.png')" mode="widthFix" />
|
<image :src="$util.img('public/uniapp/member/order/refunding.png')" mode="widthFix" />
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<view class="merch-wrap" :style="warpCss">
|
<view class="merch-wrap" :style="warpCss">
|
||||||
<view :class="['list-wrap', value.style]" :style="warpCss">
|
<view :class="['list-wrap', value.style]" :style="warpCss">
|
||||||
<view :class="['item', value.ornament.type]" v-for="(item, index) in list" :key="index"
|
<view :class="['item', value.ornament.type]" v-for="(item, index) in list" :key="index"
|
||||||
:style="itemCss" @tap.stop="handlerClick(item)">
|
:style="itemCss" @click="handlerClick(item)" @tap="handlerClick(item)">
|
||||||
<view class="merch-img">
|
<view class="merch-img">
|
||||||
<image class="cover-img" :src="$util.img(item.merch_image)" mode="widthFix"
|
<image class="cover-img" :src="$util.img(item.merch_image)" mode="widthFix"
|
||||||
@error="imgError(index)" />
|
@error="imgError(index)" />
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
<!-- #endif -->
|
<!-- #endif -->
|
||||||
|
|
||||||
<view class="merch-nav-item graphic" v-for="(item, index) in list" :key="index"
|
<view class="merch-nav-item graphic" v-for="(item, index) in list" :key="index"
|
||||||
:style="{ width: 100 / 4 + '%' }" @tap.stop="handlerClick(item)">
|
:style="{ width: 100 / 4 + '%' }" @click="handlerClick(item)" @tap="handlerClick(item)">
|
||||||
<view class="graphic-img" v-if="value.mode != 'text'"
|
<view class="graphic-img" v-if="value.mode != 'text'"
|
||||||
:style="{ fontSize: value.imageSize * 2 + 'rpx', width: value.imageSize * 2 + 'rpx', height: value.imageSize * 2 + 'rpx' }">
|
:style="{ fontSize: value.imageSize * 2 + 'rpx', width: value.imageSize * 2 + 'rpx', height: value.imageSize * 2 + 'rpx' }">
|
||||||
<image
|
<image
|
||||||
|
|||||||
@@ -3,12 +3,13 @@
|
|||||||
<view class="diy-notes" :style="{ backgroundColor: value.componentBgColor }">
|
<view class="diy-notes" :style="{ backgroundColor: value.componentBgColor }">
|
||||||
<view class="diy-notes-top">
|
<view class="diy-notes-top">
|
||||||
<view class="notes-title" :style="{ color: value.titleTextColor }">{{ value.title }}</view>
|
<view class="notes-title" :style="{ color: value.titleTextColor }">{{ value.title }}</view>
|
||||||
<view class="notes-more" @tap.stop="toMore()" :style="{ color: value.moreTextColor }">{{ value.more }}
|
<view class="notes-more" @click="toMore()" :style="{ color: value.moreTextColor }">{{ value.more }}
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<scroll-view class="diy-notes-box" scroll-x="true" show-scrollbar="true">
|
<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" @tap.stop="handlerClick(item)" :style="notesItemStyle">
|
<view class="notes-box-item" v-for="(item, i) in dataList" :key="i" @click="handlerClick(item)"
|
||||||
|
@tap="handlerClick(item)" :style="notesItemStyle">
|
||||||
<view class="notes-item" v-if="item.status == 1">
|
<view class="notes-item" v-if="item.status == 1">
|
||||||
<view class="notes-item-con">
|
<view class="notes-item-con">
|
||||||
<view class="notes-title">{{ item.note_title }}</view>
|
<view class="notes-title">{{ item.note_title }}</view>
|
||||||
@@ -156,7 +157,7 @@ export default {
|
|||||||
/* 点赞 */
|
/* 点赞 */
|
||||||
giveLike(noteId, index) {
|
giveLike(noteId, index) {
|
||||||
if (!this.storeToken) {
|
if (!this.storeToken) {
|
||||||
this.$refs.login.open(this.$util.INDEX_PAGE_URL);
|
this.$refs.login.open('/pages/index/index');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -41,12 +41,12 @@
|
|||||||
<view @touchmove.prevent.stop>
|
<view @touchmove.prevent.stop>
|
||||||
<uni-popup ref="noticePopup" type="center">
|
<uni-popup ref="noticePopup" type="center">
|
||||||
<view class="notice-popup">
|
<view class="notice-popup">
|
||||||
<view class="head-wrap" @tap.stop="closeNoticePopup">
|
<view class="head-wrap" @click="closeNoticePopup">
|
||||||
<text>公告</text>
|
<text>公告</text>
|
||||||
<text class="iconfont icon-close"></text>
|
<text class="iconfont icon-close"></text>
|
||||||
</view>
|
</view>
|
||||||
<view class="content-wrap">{{ notice }}</view>
|
<view class="content-wrap">{{ notice }}</view>
|
||||||
<button type="primary" @tap.stop="closeNoticePopup">我知道了</button>
|
<button type="primary" @click="closeNoticePopup">我知道了</button>
|
||||||
</view>
|
</view>
|
||||||
</uni-popup>
|
</uni-popup>
|
||||||
</view>
|
</view>
|
||||||
|
|||||||
@@ -7,11 +7,11 @@
|
|||||||
<!-- <text class="iconfont icon-shuaxin"></text> -->
|
<!-- <text class="iconfont icon-shuaxin"></text> -->
|
||||||
</view>
|
</view>
|
||||||
<view class="qrocde-action">
|
<view class="qrocde-action">
|
||||||
<button type="primary" @tap.stop="toLink">
|
<button type="primary" @click="toLink">
|
||||||
<text class="iconfont icon-fukuanma"></text>
|
<text class="iconfont icon-fukuanma"></text>
|
||||||
<text class="action-name">付款码</text>
|
<text class="action-name">付款码</text>
|
||||||
</button>
|
</button>
|
||||||
<button type="primary" @tap.stop="openPaymentPopup">
|
<button type="primary" @click="openPaymentPopup">
|
||||||
<text class="iconfont icon-saomafu"></text>
|
<text class="iconfont icon-saomafu"></text>
|
||||||
<text class="action-name">扫码付</text>
|
<text class="action-name">扫码付</text>
|
||||||
</button>
|
</button>
|
||||||
@@ -26,12 +26,12 @@
|
|||||||
<view @touchmove.prevent.stop>
|
<view @touchmove.prevent.stop>
|
||||||
<uni-popup ref="paymentPopup" type="center">
|
<uni-popup ref="paymentPopup" type="center">
|
||||||
<view class="payment-popup">
|
<view class="payment-popup">
|
||||||
<view class="head-wrap" @tap.stop="closePaymentPopup">
|
<view class="head-wrap" @click="closePaymentPopup">
|
||||||
<text>提示</text>
|
<text>提示</text>
|
||||||
<text class="iconfont icon-close"></text>
|
<text class="iconfont icon-close"></text>
|
||||||
</view>
|
</view>
|
||||||
<view class="content-wrap">扫码付请退出程序后直接使用微信扫一扫或返回上一页使用付款码进行支付</view>
|
<view class="content-wrap">扫码付请退出程序后直接使用微信扫一扫或返回上一页使用付款码进行支付</view>
|
||||||
<button type="primary" @tap.stop="closePaymentPopup">我知道了</button>
|
<button type="primary" @click="closePaymentPopup">我知道了</button>
|
||||||
</view>
|
</view>
|
||||||
</uni-popup>
|
</uni-popup>
|
||||||
</view>
|
</view>
|
||||||
|
|||||||
@@ -3,9 +3,9 @@
|
|||||||
<view class="fui-picture">
|
<view class="fui-picture">
|
||||||
<view v-for="(item, index) in value.list" style="line-height: 0;">
|
<view v-for="(item, index) in value.list" style="line-height: 0;">
|
||||||
<image mode="widthFix" style="width: 100%;height:auto" :src="$util.img(item.imageUrl)"
|
<image mode="widthFix" style="width: 100%;height:auto" :src="$util.img(item.imageUrl)"
|
||||||
v-if="item.link.wap_url" @tap.stop="handlerClick(item)"></image>
|
v-if="item.link.wap_url" @click="handlerClick(item)" @tap="handlerClick(item)"></image>
|
||||||
<image mode="widthFix" style="width: 100%;height:auto" :src="$util.img(item.imageUrl)" v-else
|
<image mode="widthFix" style="width: 100%;height:auto" :src="$util.img(item.imageUrl)" v-else
|
||||||
@tap.stop="handlerClick(item)"></image>
|
@click="handlerClick(item)" @tap="handlerClick(item)"></image>
|
||||||
</view>
|
</view>
|
||||||
<!-- <view wx:if="{{!childitem.linkurl}}" bindtap="previewImg" data-src="{{childitem.imgurl}}" style="padding:{{diyitem.style.paddingtop==0?0:diyitem.style.paddingtop+'rpx'}} {{diyitem.style.paddingleft==0?0:diyitem.style.paddingleft+'rpx'}}" wx:for="{{diyitem.data}}" wx:for-index="childid" wx:for-item="childitem" wx:key="{{childid}}">
|
<!-- <view wx:if="{{!childitem.linkurl}}" bindtap="previewImg" data-src="{{childitem.imgurl}}" style="padding:{{diyitem.style.paddingtop==0?0:diyitem.style.paddingtop+'rpx'}} {{diyitem.style.paddingleft==0?0:diyitem.style.paddingleft+'rpx'}}" wx:for="{{diyitem.data}}" wx:for-index="childid" wx:for-item="childitem" wx:key="{{childid}}">
|
||||||
<image mode="widthFix" src="{{childitem.imgurl}}" style="{{bannerheight?'height:'+bannerheight+'px':'height:auto'}}"></image>
|
<image mode="widthFix" src="{{childitem.imgurl}}" style="{{bannerheight?'height:'+bannerheight+'px':'height:auto'}}"></image>
|
||||||
@@ -52,9 +52,20 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
previewImg(img) {
|
||||||
|
// #ifdef MP-WEIXIN
|
||||||
|
uni.previewImage({
|
||||||
|
current: 0,
|
||||||
|
urls: [this.$util.img(img)],
|
||||||
|
success: function (res) { },
|
||||||
|
fail: function (res) { },
|
||||||
|
complete: function (res) { },
|
||||||
|
})
|
||||||
|
// #endif
|
||||||
|
},
|
||||||
redirectTo(link) {
|
redirectTo(link) {
|
||||||
if (link.wap_url) {
|
if (link.wap_url) {
|
||||||
if (this.$util.getCurrRoute() == this.$util.MEMBER_PAGE_URL && !this.storeToken) {
|
if (this.$util.getCurrRoute() == 'pages/member/index' && !this.storeToken) {
|
||||||
this.$refs.login.open(link.wap_url);
|
this.$refs.login.open(link.wap_url);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -66,9 +77,7 @@ export default {
|
|||||||
await this.__$emitEvent({
|
await this.__$emitEvent({
|
||||||
eventName: 'picture-tap', data: item, promiseCallback: (event, handler, awaitedResult) => {
|
eventName: 'picture-tap', data: item, promiseCallback: (event, handler, awaitedResult) => {
|
||||||
if (!awaitedResult) return;
|
if (!awaitedResult) return;
|
||||||
|
if (item.link.wap_url) {
|
||||||
const link = item.link;
|
|
||||||
if (link?.name || link?.wap_url || link?.appid) {
|
|
||||||
this.redirectTo(item.link);
|
this.redirectTo(item.link);
|
||||||
} else {
|
} else {
|
||||||
this.previewImg(item.imageUrl);
|
this.previewImg(item.imageUrl);
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<x-skeleton data-component-name="diy-pinfan" :type="skeletonType" :loading="loading" :configs="skeletonConfig">
|
<x-skeleton data-component-name="diy-pinfan" :type="skeletonType" :loading="loading" :configs="skeletonConfig">
|
||||||
<view class="diy-pinfan" :class="[value.template, value.style]" :style="warpCss">
|
<view class="diy-pinfan" :class="[value.template, value.style]" :style="warpCss">
|
||||||
<template v-if="value.template == 'row1-of1'">
|
<template v-if="value.template == 'row1-of1'">
|
||||||
<view class="item" v-for="(item, index) in list" :key="index" @tap.stop="toDetail(item)"
|
<view class="item" v-for="(item, index) in list" :key="index" @click="toDetail(item)"
|
||||||
:class="[value.ornament.type]" :style="goodsItemCss">
|
:class="[value.ornament.type]" :style="goodsItemCss">
|
||||||
<view class="img-wrap" :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }">
|
<view class="img-wrap" :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }">
|
||||||
<image :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }"
|
<image :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }"
|
||||||
@@ -61,7 +61,7 @@
|
|||||||
|
|
||||||
<template v-if="value.template == 'horizontal-slide'">
|
<template v-if="value.template == 'horizontal-slide'">
|
||||||
<scroll-view v-if="value.slideMode == 'scroll'" class="scroll" :scroll-x="true" :show-scrollbar="false">
|
<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" @tap.stop="toDetail(item)"
|
<view class="item" v-for="(item, index) in list" :key="index" @click="toDetail(item)"
|
||||||
:class="[value.ornament.type]" :style="goodsItemCss">
|
:class="[value.ornament.type]" :style="goodsItemCss">
|
||||||
<view class="img-wrap" :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }">
|
<view class="img-wrap" :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }">
|
||||||
<image :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }"
|
<image :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }"
|
||||||
@@ -113,7 +113,7 @@
|
|||||||
<swiper-item v-for="(pageItem, pageIndex) in page" :key="pageIndex"
|
<swiper-item v-for="(pageItem, pageIndex) in page" :key="pageIndex"
|
||||||
:class="['swiper-item', (list.length && [list[pageIndex].length / 3] >= 1) && 'flex-between']">
|
:class="['swiper-item', (list.length && [list[pageIndex].length / 3] >= 1) && 'flex-between']">
|
||||||
<view class="item" v-for="(item, dataIndex) in list[pageIndex]" :key="dataIndex"
|
<view class="item" v-for="(item, dataIndex) in list[pageIndex]" :key="dataIndex"
|
||||||
@tap.stop="toDetail(item)" :class="[value.ornament.type]" :style="goodsItemCss">
|
@click="toDetail(item)" :class="[value.ornament.type]" :style="goodsItemCss">
|
||||||
<view class="img-wrap" :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }">
|
<view class="img-wrap" :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }">
|
||||||
<image :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }"
|
<image :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }"
|
||||||
:src="$util.img(item.goods_image, { size: 'mid' })" mode="widthFix"
|
:src="$util.img(item.goods_image, { size: 'mid' })" mode="widthFix"
|
||||||
@@ -319,7 +319,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
::v-deep .uni-scroll-view ::-webkit-scrollbar {
|
/deep/.uni-scroll-view ::-webkit-scrollbar {
|
||||||
/* 隐藏滚动条,但依旧具备可以滚动的功能 */
|
/* 隐藏滚动条,但依旧具备可以滚动的功能 */
|
||||||
display: none;
|
display: none;
|
||||||
width: 0;
|
width: 0;
|
||||||
@@ -328,7 +328,7 @@ export default {
|
|||||||
background: transparent;
|
background: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
::v-deep ::-webkit-scrollbar {
|
/deep/::-webkit-scrollbar {
|
||||||
display: none;
|
display: none;
|
||||||
width: 0;
|
width: 0;
|
||||||
height: 0;
|
height: 0;
|
||||||
|
|||||||
@@ -31,14 +31,14 @@
|
|||||||
</view>
|
</view>
|
||||||
<view class="head-right"
|
<view class="head-right"
|
||||||
:style="{ fontSize: value.titleStyle.moreFontSize * 2 + 'rpx', color: value.titleStyle.moreColor }"
|
:style="{ fontSize: value.titleStyle.moreFontSize * 2 + 'rpx', color: value.titleStyle.moreColor }"
|
||||||
@tap.stop="$util.redirectTo('/pages_promotion/pintuan/list')">
|
@click="$util.redirectTo('/pages_promotion/pintuan/list')">
|
||||||
<text>{{ value.titleStyle.more }}</text>
|
<text>{{ value.titleStyle.more }}</text>
|
||||||
<text class="iconfont icon-right"></text>
|
<text class="iconfont icon-right"></text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<template v-if="value.template == 'row1-of1'">
|
<template v-if="value.template == 'row1-of1'">
|
||||||
<view class="item" v-for="(item, index) in list" :key="index" @tap.stop="toDetail(item)"
|
<view class="item" v-for="(item, index) in list" :key="index" @click="toDetail(item)"
|
||||||
:class="[value.ornament.type]" :style="goodsItemCss">
|
:class="[value.ornament.type]" :style="goodsItemCss">
|
||||||
<view class="img-wrap" :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }">
|
<view class="img-wrap" :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }">
|
||||||
<image :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }"
|
<image :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }"
|
||||||
@@ -100,7 +100,7 @@
|
|||||||
|
|
||||||
<template v-if="value.template == 'horizontal-slide'">
|
<template v-if="value.template == 'horizontal-slide'">
|
||||||
<scroll-view v-if="value.slideMode == 'scroll'" class="scroll" :scroll-x="true" :show-scrollbar="false">
|
<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" @tap.stop="toDetail(item)"
|
<view class="item" v-for="(item, index) in list" :key="index" @click="toDetail(item)"
|
||||||
:class="[value.ornament.type]" :style="goodsItemCss">
|
:class="[value.ornament.type]" :style="goodsItemCss">
|
||||||
<view class="img-wrap" :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }">
|
<view class="img-wrap" :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }">
|
||||||
<image :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }"
|
<image :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }"
|
||||||
@@ -161,7 +161,7 @@
|
|||||||
<swiper-item v-for="(pageItem, pageIndex) in page" :key="pageIndex"
|
<swiper-item v-for="(pageItem, pageIndex) in page" :key="pageIndex"
|
||||||
:class="['swiper-item', (list.length && [list[pageIndex].length / 3] >= 1) && 'flex-between']">
|
:class="['swiper-item', (list.length && [list[pageIndex].length / 3] >= 1) && 'flex-between']">
|
||||||
<view class="item" v-for="(item, dataIndex) in list[pageIndex]" :key="dataIndex"
|
<view class="item" v-for="(item, dataIndex) in list[pageIndex]" :key="dataIndex"
|
||||||
@tap.stop="toDetail(item)" :class="[value.ornament.type]" :style="goodsItemCss">
|
@click="toDetail(item)" :class="[value.ornament.type]" :style="goodsItemCss">
|
||||||
<view class="img-wrap" :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }">
|
<view class="img-wrap" :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }">
|
||||||
<image :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }"
|
<image :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }"
|
||||||
:src="$util.img(item.goods_image, { size: 'mid' })" mode="widthFix"
|
:src="$util.img(item.goods_image, { size: 'mid' })" mode="widthFix"
|
||||||
@@ -391,7 +391,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
::v-deep .uni-scroll-view ::-webkit-scrollbar {
|
/deep/.uni-scroll-view ::-webkit-scrollbar {
|
||||||
/* 隐藏滚动条,但依旧具备可以滚动的功能 */
|
/* 隐藏滚动条,但依旧具备可以滚动的功能 */
|
||||||
display: none;
|
display: none;
|
||||||
width: 0;
|
width: 0;
|
||||||
@@ -400,7 +400,7 @@ export default {
|
|||||||
background: transparent;
|
background: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
::v-deep ::-webkit-scrollbar {
|
/deep/::-webkit-scrollbar {
|
||||||
display: none;
|
display: none;
|
||||||
width: 0;
|
width: 0;
|
||||||
height: 0;
|
height: 0;
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
<x-skeleton data-component-name="diy-presale" :type="skeletonType" :loading="loading" :configs="skeletonConfig">
|
<x-skeleton data-component-name="diy-presale" :type="skeletonType" :loading="loading" :configs="skeletonConfig">
|
||||||
<view class="diy-presale" v-if="list.length" :class="[value.template, value.style]" :style="warpCss">
|
<view class="diy-presale" v-if="list.length" :class="[value.template, value.style]" :style="warpCss">
|
||||||
<template v-if="value.template == 'row1-of1'">
|
<template v-if="value.template == 'row1-of1'">
|
||||||
<view class="item" v-for="(item, index) in list" :key="index" @tap.stop="handlerClick(item)"
|
<view class="item" v-for="(item, index) in list" :key="index" @click="handlerClick(item)"
|
||||||
:class="[value.ornament.type]" :style="goodsItemCss">
|
@tap="handlerClick(item)" :class="[value.ornament.type]" :style="goodsItemCss">
|
||||||
<view class="img-wrap" :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }">
|
<view class="img-wrap" :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }">
|
||||||
<image :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }"
|
<image :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }"
|
||||||
:src="$util.img(item.goods_image, { size: 'mid' })" mode="widthFix"
|
:src="$util.img(item.goods_image, { size: 'mid' })" mode="widthFix"
|
||||||
@@ -40,8 +40,8 @@
|
|||||||
</template>
|
</template>
|
||||||
<template v-if="value.template == 'horizontal-slide'">
|
<template v-if="value.template == 'horizontal-slide'">
|
||||||
<scroll-view v-if="value.slideMode == 'scroll'" class="scroll" :scroll-x="true" :show-scrollbar="false">
|
<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" @tap.stop="handlerClick(item)"
|
<view class="item" v-for="(item, index) in list" :key="index" @click="handlerClick(item)"
|
||||||
:class="[value.ornament.type]" :style="goodsItemCss">
|
@tap="handlerClick(item)" :class="[value.ornament.type]" :style="goodsItemCss">
|
||||||
<view class="img-wrap" :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }">
|
<view class="img-wrap" :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }">
|
||||||
<image :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }"
|
<image :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }"
|
||||||
:src="$util.img(item.goods_image, { size: 'mid' })" mode="widthFix"
|
:src="$util.img(item.goods_image, { size: 'mid' })" mode="widthFix"
|
||||||
@@ -75,7 +75,8 @@
|
|||||||
<swiper-item v-for="(pageItem, pageIndex) in page" :key="pageIndex"
|
<swiper-item v-for="(pageItem, pageIndex) in page" :key="pageIndex"
|
||||||
:class="['swiper-item', (list.length && [list[pageIndex].length / 3] >= 1) && 'flex-between']">
|
:class="['swiper-item', (list.length && [list[pageIndex].length / 3] >= 1) && 'flex-between']">
|
||||||
<view class="item" v-for="(item, dataIndex) in list[pageIndex]" :key="dataIndex"
|
<view class="item" v-for="(item, dataIndex) in list[pageIndex]" :key="dataIndex"
|
||||||
@tap.stop="handlerClick(item)" :class="[value.ornament.type]" :style="goodsItemCss">
|
@click="handlerClick(item)" @tap="handlerClick(item)" :class="[value.ornament.type]"
|
||||||
|
:style="goodsItemCss">
|
||||||
<view class="img-wrap" :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }">
|
<view class="img-wrap" :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }">
|
||||||
<image :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }"
|
<image :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }"
|
||||||
:src="$util.img(item.goods_image, { size: 'mid' })" mode="widthFix"
|
:src="$util.img(item.goods_image, { size: 'mid' })" mode="widthFix"
|
||||||
@@ -275,7 +276,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
::v-deep .uni-scroll-view ::-webkit-scrollbar {
|
/deep/.uni-scroll-view ::-webkit-scrollbar {
|
||||||
/* 隐藏滚动条,但依旧具备可以滚动的功能 */
|
/* 隐藏滚动条,但依旧具备可以滚动的功能 */
|
||||||
display: none;
|
display: none;
|
||||||
width: 0;
|
width: 0;
|
||||||
@@ -284,7 +285,7 @@ export default {
|
|||||||
background: transparent;
|
background: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
::v-deep ::-webkit-scrollbar {
|
/deep/::-webkit-scrollbar {
|
||||||
display: none;
|
display: none;
|
||||||
width: 0;
|
width: 0;
|
||||||
height: 0;
|
height: 0;
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<view class="uni-scroll-view-content">
|
<view class="uni-scroll-view-content">
|
||||||
<!-- #endif -->
|
<!-- #endif -->
|
||||||
<view class="quick-nav-item" v-for="(item, index) in value.list" :key="index"
|
<view class="quick-nav-item" v-for="(item, index) in value.list" :key="index"
|
||||||
@tap.stop="handlerClick(item)"
|
@click="handlerClick(item)" @tap="handlerClick(item)"
|
||||||
:style="{ background: 'linear-gradient(to right,' + item.bgColorStart ? item.bgColorStart : '' + ',' + item.bgColorEnd ? item.bgColorEnd : '' + ')' }">
|
:style="{ background: 'linear-gradient(to right,' + item.bgColorStart ? item.bgColorStart : '' + ',' + item.bgColorEnd ? item.bgColorEnd : '' + ')' }">
|
||||||
<view class="quick-img" v-if="item.imageUrl || item.icon">
|
<view class="quick-img" v-if="item.imageUrl || item.icon">
|
||||||
<image v-if="item.iconType == 'img'"
|
<image v-if="item.iconType == 'img'"
|
||||||
@@ -61,7 +61,7 @@ export default {
|
|||||||
methods: {
|
methods: {
|
||||||
redirectTo(link) {
|
redirectTo(link) {
|
||||||
if (link.wap_url) {
|
if (link.wap_url) {
|
||||||
if (this.$util.getCurrRoute() == this.$util.MEMBER_PAGE_URL && !this.storeToken) {
|
if (this.$util.getCurrRoute() == 'pages/member/index' && !this.storeToken) {
|
||||||
this.$refs.login.open(link.wap_url);
|
this.$refs.login.open(link.wap_url);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<view data-component-name="diy-rich-text" class="rich-text-box" :style="richTextWarpCss">
|
<view data-component-name="diy-rich-text" class="rich-text-box" :style="richTextWarpCss">
|
||||||
<rich-text :nodes="html" @tap.stop="handlerClick"></rich-text>
|
<rich-text :nodes="html" @click="handlerClick" @tap="handlerClick"></rich-text>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -8,8 +8,9 @@
|
|||||||
<!-- 1左2右 -->
|
<!-- 1左2右 -->
|
||||||
<template v-if="value.mode == 'row1-lt-of2-rt'">
|
<template v-if="value.mode == 'row1-lt-of2-rt'">
|
||||||
<view class="template-left">
|
<view class="template-left">
|
||||||
<view :class="['item', value.mode]" @tap.stop="handlerClick(value.list[0].link, value.list[0].imageUrl)"
|
<view :class="['item', value.mode]" @click="handlerClick(value.list[0].link)"
|
||||||
:style="{ marginRight: value.imageGap * 2 + 'rpx', width: list[0].imgWidth, height: list[0].imgHeight + 'px' }">
|
@tap="handlerClick(value.list[0].link)"
|
||||||
|
:style="{ marginRight: value.imageGap * 2 + 'rpx', width: list[0].imgWidth, height: list[0].imgHeight + 'px' }">
|
||||||
<image :src="$util.img(value.list[0].imageUrl)" :mode="list[0].imageMode || 'scaleToFill'"
|
<image :src="$util.img(value.list[0].imageUrl)" :mode="list[0].imageMode || 'scaleToFill'"
|
||||||
:style="list[0].pageItemStyle" :show-menu-by-longpress="true" />
|
:style="list[0].pageItemStyle" :show-menu-by-longpress="true" />
|
||||||
</view>
|
</view>
|
||||||
@@ -18,8 +19,9 @@
|
|||||||
<view class="template-right">
|
<view class="template-right">
|
||||||
<template v-for="(item, index) in list">
|
<template v-for="(item, index) in list">
|
||||||
<template v-if="index > 0">
|
<template v-if="index > 0">
|
||||||
<view :key="index" :class="['item', value.mode]" @tap.stop="handlerClick(item.link, item.imageUrl)"
|
<view :key="index" :class="['item', value.mode]" @click="handlerClick(item.link)"
|
||||||
:style="{ marginBottom: value.imageGap * 2 + 'rpx', width: item.imgWidth, height: item.imgHeight + 'px' }">
|
@tap="handlerClick(item.link)"
|
||||||
|
:style="{ marginBottom: value.imageGap * 2 + 'rpx', width: item.imgWidth, height: item.imgHeight + 'px' }">
|
||||||
<image :src="$util.img(item.imageUrl)" :mode="item.imageMode || 'scaleToFill'"
|
<image :src="$util.img(item.imageUrl)" :mode="item.imageMode || 'scaleToFill'"
|
||||||
:style="item.pageItemStyle" :show-menu-by-longpress="true" />
|
:style="item.pageItemStyle" :show-menu-by-longpress="true" />
|
||||||
</view>
|
</view>
|
||||||
@@ -32,8 +34,8 @@
|
|||||||
<template v-else-if="value.mode == 'row1-lt-of1-tp-of2-bm'">
|
<template v-else-if="value.mode == 'row1-lt-of1-tp-of2-bm'">
|
||||||
<view class="template-left">
|
<view class="template-left">
|
||||||
<view :class="['item', value.mode]"
|
<view :class="['item', value.mode]"
|
||||||
:style="{ marginRight: value.imageGap * 2 + 'rpx', width: list[0].imgWidth, height: list[0].imgHeight + 'px' }"
|
:style="{ marginRight: value.imageGap * 2 + 'rpx', width: list[0].imgWidth, height: list[0].imgHeight + 'px' }"
|
||||||
@tap.stop="handlerClick(value.list[0].link, value.list[0].imageUrl)">
|
@click="handlerClick(value.list[0].link)" @tap="handlerClick(value.list[0].link)">
|
||||||
<image :src="$util.img(value.list[0].imageUrl)" :mode="list[0].imageMode || 'scaleToFill'"
|
<image :src="$util.img(value.list[0].imageUrl)" :mode="list[0].imageMode || 'scaleToFill'"
|
||||||
:style="list[0].pageItemStyle" :show-menu-by-longpress="true" />
|
:style="list[0].pageItemStyle" :show-menu-by-longpress="true" />
|
||||||
</view>
|
</view>
|
||||||
@@ -41,19 +43,20 @@
|
|||||||
|
|
||||||
<view class="template-right">
|
<view class="template-right">
|
||||||
<view :class="['item', value.mode]"
|
<view :class="['item', value.mode]"
|
||||||
:style="{ marginBottom: value.imageGap * 2 + 'rpx', width: list[1].imgWidth, height: list[1].imgHeight + 'px' }"
|
:style="{ marginBottom: value.imageGap * 2 + 'rpx', width: list[1].imgWidth, height: list[1].imgHeight + 'px' }"
|
||||||
@tap.stop="handlerClick(value.list[1].link, value.list[1].imageUrl)">
|
@click="handlerClick(value.list[1].link)" @tap="handlerClick(value.list[1].link)">
|
||||||
<image :src="$util.img(value.list[1].imageUrl)" :mode="list[1].imageMode || 'scaleToFill'"
|
<image :src="$util.img(value.list[1].imageUrl)" :mode="list[1].imageMode || 'scaleToFill'"
|
||||||
:style="list[1].pageItemStyle" :show-menu-by-longpress="true" />
|
:style="list[1].pageItemStyle" :show-menu-by-longpress="true" />
|
||||||
</view>
|
</view>
|
||||||
<view class="template-bottom">
|
<view class="template-bottom">
|
||||||
<template v-for="(item, index) in list">
|
<template v-for="(item, index) in list">
|
||||||
<template v-if="index > 1">
|
<template v-if="index > 1">
|
||||||
<view :key="index" :class="['item', value.mode]" @tap.stop="handlerClick(item.link, item.imageUrl)" :style="{
|
<view :key="index" :class="['item', value.mode]" @click="handlerClick(item.link)"
|
||||||
marginRight: value.imageGap * 2 + 'rpx',
|
@tap="handlerClick(item.link)" :style="{
|
||||||
width: item.imgWidth,
|
marginRight: value.imageGap * 2 + 'rpx',
|
||||||
height: item.imgHeight + 'px'
|
width: item.imgWidth,
|
||||||
}">
|
height: item.imgHeight + 'px'
|
||||||
|
}">
|
||||||
<image :src="$util.img(item.imageUrl)" :mode="item.imageMode || 'scaleToFill'"
|
<image :src="$util.img(item.imageUrl)" :mode="item.imageMode || 'scaleToFill'"
|
||||||
:style="item.pageItemStyle" :show-menu-by-longpress="true" />
|
:style="item.pageItemStyle" :show-menu-by-longpress="true" />
|
||||||
</view>
|
</view>
|
||||||
@@ -65,8 +68,8 @@
|
|||||||
|
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<view :class="['item', value.mode]" v-for="(item, index) in list" :key="index"
|
<view :class="['item', value.mode]" v-for="(item, index) in list" :key="index"
|
||||||
@tap.stop="handlerClick(item.link, item.imageUrl)"
|
@click="handlerClick(item.link)" @tap="handlerClick(item.link)"
|
||||||
:style="{ marginRight: value.imageGap * 2 + 'rpx', marginBottom: value.imageGap * 2 + 'rpx', width: item.widthStyle, height: item.imgHeight + 'px' }">
|
:style="{ marginRight: value.imageGap * 2 + 'rpx', marginBottom: value.imageGap * 2 + 'rpx', width: item.widthStyle, height: item.imgHeight + 'px' }">
|
||||||
<image :src="$util.img(item.imageUrl)" :mode="item.imageMode || 'scaleToFill'"
|
<image :src="$util.img(item.imageUrl)" :mode="item.imageMode || 'scaleToFill'"
|
||||||
:style="item.pageItemStyle" :show-menu-by-longpress="true" />
|
:style="item.pageItemStyle" :show-menu-by-longpress="true" />
|
||||||
</view>
|
</view>
|
||||||
@@ -371,16 +374,11 @@ export default {
|
|||||||
return obj;
|
return obj;
|
||||||
},
|
},
|
||||||
|
|
||||||
async handlerClick(link, imageUrl) {
|
async handlerClick(link) {
|
||||||
await this.__$emitEvent({
|
await this.__$emitEvent({
|
||||||
eventName: 'rubik-cube-tap', data: link, promiseCallback: (event, handler, awaitedResult) => {
|
eventName: 'rubik-cube-tap', data: link, promiseCallback: (event, handler, awaitedResult) => {
|
||||||
if (!awaitedResult) return;
|
if (!awaitedResult) return;
|
||||||
|
this.$util.diyRedirectTo(link);
|
||||||
if (link?.name || link?.wap_url || link?.appid) {
|
|
||||||
this.$util.diyRedirectTo(link);
|
|
||||||
} else if (imageUrl){
|
|
||||||
this.previewImg(imageUrl);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<view data-component-name="diy-search" class="diy-search">
|
<view data-component-name="diy-search" class="diy-search">
|
||||||
<view class="diy-search-wrap" :class="value.positionWay" :style="fixedCss">
|
<view class="diy-search-wrap" :class="value.positionWay" :style="fixedCss">
|
||||||
<view :class="['search-box', 'search-box-' + value.searchStyle]" :style="searchWrapCss"
|
<view :class="['search-box', 'search-box-' + value.searchStyle]" :style="searchWrapCss"
|
||||||
@tap.stop="handlerSearchClick">
|
@click="handlerSearchClick" @tap="handlerSearchClick">
|
||||||
<block v-if="[1, 2].includes(value.searchStyle)">
|
<block v-if="[1, 2].includes(value.searchStyle)">
|
||||||
<view class="img" v-if="value.searchStyle == 2 && value.iconType == 'img'">
|
<view class="img" v-if="value.searchStyle == 2 && value.iconType == 'img'">
|
||||||
<image :src="$util.img(value.imageUrl)" mode="heightFix" />
|
<image :src="$util.img(value.imageUrl)" mode="heightFix" />
|
||||||
@@ -14,30 +14,32 @@
|
|||||||
<input type="text" class="uni-input ns-font-size-base" maxlength="50" :placeholder="value.title"
|
<input type="text" class="uni-input ns-font-size-base" maxlength="50" :placeholder="value.title"
|
||||||
v-model="searchText" @confirm="handlerSearchClick" disabled="true"
|
v-model="searchText" @confirm="handlerSearchClick" disabled="true"
|
||||||
:placeholderStyle="placeholderStyle" />
|
:placeholderStyle="placeholderStyle" />
|
||||||
<text class="iconfont icon-sousuo3" @tap.stop="handlerSearchClick"
|
<text class="iconfont icon-sousuo3" @click.stop="handlerSearchClick" @tap="handlerSearchClick"
|
||||||
:style="{ color: value.textColor ? value.textColor : 'rgba(0,0,0,0)' }"></text>
|
:style="{ color: value.textColor ? value.textColor : 'rgba(0,0,0,0)' }"></text>
|
||||||
</view>
|
</view>
|
||||||
</block>
|
</block>
|
||||||
<block v-if="value.searchStyle == 3">
|
<block v-if="value.searchStyle == 3">
|
||||||
<view class="search-content" :style="inputStyle"
|
<view class="search-content" :style="inputStyle" @click.stop="handlerSearchClick"
|
||||||
@tap.stop="handlerSearchClick">
|
@tap="handlerSearchClick">
|
||||||
<text class="iconfont icon-sousuo3"
|
<text class="iconfont icon-sousuo3"
|
||||||
:style="{ color: value.textColor ? value.textColor : 'rgba(0,0,0,0)' }"></text>
|
:style="{ color: value.textColor ? value.textColor : 'rgba(0,0,0,0)' }"></text>
|
||||||
<input type="text" class="uni-input ns-font-size-base" maxlength="50" :placeholder="value.title"
|
<input type="text" class="uni-input ns-font-size-base" maxlength="50" :placeholder="value.title"
|
||||||
v-model="searchText" @confirm="handlerSearchClick" disabled="true"
|
v-model="searchText" @confirm="handlerSearchClick" disabled="true"
|
||||||
@tap.stop="handlerSearchClick"
|
@click.stop="handlerSearchClick" @tap="handlerSearchClick"
|
||||||
:placeholderStyle="placeholderStyle" />
|
:placeholderStyle="placeholderStyle" />
|
||||||
<text class="search-content-btn" @tap.stop="handlerSearchClick"
|
<text class="search-content-btn" @click.stop="handlerSearchClick" @tap="handlerSearchClick"
|
||||||
:style="{ 'backgroundColor': value.pageBgColor ? value.pageBgColor : 'rgba(0,0,0,0)' }">搜索</text>
|
:style="{ 'backgroundColor': value.pageBgColor ? value.pageBgColor : 'rgba(0,0,0,0)' }">搜索</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="img" v-if="value.iconType == 'img'"
|
<view class="img" v-if="value.iconType == 'img'"
|
||||||
@tap.stop="handlerRedirectToClick(value.searchLink)">
|
@click.stop="handlerRedirectToClick(value.searchLink)"
|
||||||
|
@tap="handlerRedirectToClick(value.searchLink)">
|
||||||
<image :src="$util.img(value.imageUrl)" mode="heightFix" />
|
<image :src="$util.img(value.imageUrl)" mode="heightFix" />
|
||||||
</view>
|
</view>
|
||||||
<diy-icon class="icon" v-if="value.iconType == 'icon'" :icon="value.icon"
|
<diy-icon class="icon" v-if="value.iconType == 'icon'" :icon="value.icon"
|
||||||
:value="value.style ? value.style : 'null'"
|
:value="value.style ? value.style : 'null'"
|
||||||
:style="{ maxWidth: 30 * 2 + 'rpx', maxHeight: 30 * 2 + 'rpx' }"
|
:style="{ maxWidth: 30 * 2 + 'rpx', maxHeight: 30 * 2 + 'rpx' }"
|
||||||
@tap.stop="handlerRedirectToClick(value.searchLink)"></diy-icon>
|
@click.stop="handlerRedirectToClick(value.searchLink)"
|
||||||
|
@tap="handlerRedirectToClick(value.searchLink)"></diy-icon>
|
||||||
</block>
|
</block>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@@ -196,7 +198,7 @@ export default {
|
|||||||
},
|
},
|
||||||
redirectTo(link) {
|
redirectTo(link) {
|
||||||
if (link.wap_url) {
|
if (link.wap_url) {
|
||||||
if (this.$util.getCurrRoute() == this.$util.MEMBER_PAGE_URL && !this.storeToken) {
|
if (this.$util.getCurrRoute() == 'pages/member/index' && !this.storeToken) {
|
||||||
this.$refs.login.open(link.wap_url);
|
this.$refs.login.open(link.wap_url);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -255,7 +257,7 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
::v-deep .uni-input-placeholder {
|
/deep/ .uni-input-placeholder {
|
||||||
overflow: initial;
|
overflow: initial;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
</view>
|
</view>
|
||||||
<view class="marketimg-box-title-right" v-if="value.titleStyle.moreSupport"
|
<view class="marketimg-box-title-right" v-if="value.titleStyle.moreSupport"
|
||||||
:style="{ fontSize: value.titleStyle.moreFontSize * 2 + 'rpx', color: value.titleStyle.moreColor }"
|
:style="{ fontSize: value.titleStyle.moreFontSize * 2 + 'rpx', color: value.titleStyle.moreColor }"
|
||||||
@tap.stop="toMore">
|
@click="toMore">
|
||||||
<text>{{ value.titleStyle.more }}</text>
|
<text>{{ value.titleStyle.more }}</text>
|
||||||
<text class="iconfont icon-right"></text>
|
<text class="iconfont icon-right"></text>
|
||||||
</view>
|
</view>
|
||||||
@@ -35,7 +35,7 @@
|
|||||||
|
|
||||||
<view class="content-wrap">
|
<view class="content-wrap">
|
||||||
<template v-if="value.template == 'row1-of1'">
|
<template v-if="value.template == 'row1-of1'">
|
||||||
<view class="item" v-for="(item, index) in dataList" :key="index" @tap.stop="toDetail(item.id)"
|
<view class="item" v-for="(item, index) in dataList" :key="index" @click="toDetail(item.id)"
|
||||||
:class="[value.ornament.type]" :style="goodsItemCss">
|
:class="[value.ornament.type]" :style="goodsItemCss">
|
||||||
<view class="img-wrap" :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }">
|
<view class="img-wrap" :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }">
|
||||||
<image :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }"
|
<image :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }"
|
||||||
@@ -105,7 +105,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-if="value.template == 'row1-of2'">
|
<template v-if="value.template == 'row1-of2'">
|
||||||
<view class="item" v-for="(item, index) in dataList" :key="index" @tap.stop="toDetail(item.id)"
|
<view class="item" v-for="(item, index) in dataList" :key="index" @click="toDetail(item.id)"
|
||||||
:class="[value.ornament.type]" :style="goodsItemCss">
|
:class="[value.ornament.type]" :style="goodsItemCss">
|
||||||
<view class="img-wrap" :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }">
|
<view class="img-wrap" :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }">
|
||||||
<image :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }"
|
<image :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }"
|
||||||
@@ -150,7 +150,7 @@
|
|||||||
<template v-if="value.template == 'horizontal-slide'">
|
<template v-if="value.template == 'horizontal-slide'">
|
||||||
<scroll-view v-if="value.slideMode == 'scroll'" class="scroll" :scroll-x="true"
|
<scroll-view v-if="value.slideMode == 'scroll'" class="scroll" :scroll-x="true"
|
||||||
:show-scrollbar="false">
|
:show-scrollbar="false">
|
||||||
<view class="item" v-for="(item, index) in dataList" :key="index" @tap.stop="toDetail(item.id)"
|
<view class="item" v-for="(item, index) in dataList" :key="index" @click="toDetail(item.id)"
|
||||||
:class="[value.ornament.type]" :style="goodsItemCss">
|
:class="[value.ornament.type]" :style="goodsItemCss">
|
||||||
<view class="img-wrap" :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }">
|
<view class="img-wrap" :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }">
|
||||||
<image :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }"
|
<image :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }"
|
||||||
@@ -190,7 +190,7 @@
|
|||||||
<swiper-item v-for="(pageItem, pageIndex) in page" :key="pageIndex"
|
<swiper-item v-for="(pageItem, pageIndex) in page" :key="pageIndex"
|
||||||
:class="['swiper-item', dataList[pageIndex] && [dataList[pageIndex].length / 3].length >= 1 && 'flex-between']">
|
:class="['swiper-item', dataList[pageIndex] && [dataList[pageIndex].length / 3].length >= 1 && 'flex-between']">
|
||||||
<view class="item" v-for="(item, dataIndex) in dataList[pageIndex]" :key="dataIndex"
|
<view class="item" v-for="(item, dataIndex) in dataList[pageIndex]" :key="dataIndex"
|
||||||
@tap.stop="toDetail(item.id)" :class="[value.ornament.type]" :style="goodsItemCss">
|
@click="toDetail(item.id)" :class="[value.ornament.type]" :style="goodsItemCss">
|
||||||
<view class="img-wrap" :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }">
|
<view class="img-wrap" :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }">
|
||||||
<image :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }"
|
<image :style="{ borderRadius: value.imgAroundRadius * 2 + 'rpx' }"
|
||||||
:src="$util.img(item.goods_image, { size: 'mid' })" mode="widthFix"
|
:src="$util.img(item.goods_image, { size: 'mid' })" mode="widthFix"
|
||||||
@@ -536,7 +536,7 @@ scroll-view ::-webkit-scrollbar {
|
|||||||
touch-action: none;
|
touch-action: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
::v-deep .uni-scroll-view ::-webkit-scrollbar {
|
/deep/.uni-scroll-view ::-webkit-scrollbar {
|
||||||
/* 隐藏滚动条,但依旧具备可以滚动的功能 */
|
/* 隐藏滚动条,但依旧具备可以滚动的功能 */
|
||||||
display: none;
|
display: none;
|
||||||
width: 0;
|
width: 0;
|
||||||
@@ -545,7 +545,7 @@ scroll-view ::-webkit-scrollbar {
|
|||||||
background: transparent;
|
background: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
::v-deep ::-webkit-scrollbar {
|
/deep/::-webkit-scrollbar {
|
||||||
display: none;
|
display: none;
|
||||||
width: 0;
|
width: 0;
|
||||||
height: 0;
|
height: 0;
|
||||||
|
|||||||
@@ -140,7 +140,7 @@ export default {
|
|||||||
display: flex;
|
display: flex;
|
||||||
align-items: baseline;
|
align-items: baseline;
|
||||||
|
|
||||||
::v-deep .uni-scroll-view-content {
|
/deep/ .uni-scroll-view-content {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
@@ -148,7 +148,7 @@ export default {
|
|||||||
&.between {
|
&.between {
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
|
||||||
::v-deep .uni-scroll-view-content {
|
/deep/.uni-scroll-view-content {
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<block v-if="value.style == 1">
|
<block v-if="value.style == 1">
|
||||||
<view class="store-box store-one">
|
<view class="store-box store-one">
|
||||||
<view class="store-info">
|
<view class="store-info">
|
||||||
<view class="info-box" :style="{ color: value.textColor }" @tap.stop="toStoreList()">
|
<view class="info-box" :style="{ color: value.textColor }" @click="toStoreList()">
|
||||||
<block v-if="globalStoreInfo && globalStoreInfo.store_id">
|
<block v-if="globalStoreInfo && globalStoreInfo.store_id">
|
||||||
<text class="title">{{ globalStoreInfo.store_name }}</text>
|
<text class="title">{{ globalStoreInfo.store_name }}</text>
|
||||||
<text>
|
<text>
|
||||||
@@ -15,12 +15,12 @@
|
|||||||
</view>
|
</view>
|
||||||
<view class="address-wrap" :style="{ color: value.textColor }">
|
<view class="address-wrap" :style="{ color: value.textColor }">
|
||||||
<text class="iconfont icon-dizhi"></text>
|
<text class="iconfont icon-dizhi"></text>
|
||||||
<text v-if="globalStoreInfo && globalStoreInfo.store_id" @tap.stop="mapRoute" class="address">{{
|
<text v-if="globalStoreInfo && globalStoreInfo.store_id" @click="mapRoute" class="address">{{
|
||||||
globalStoreInfo.show_address }}</text>
|
globalStoreInfo.show_address }}</text>
|
||||||
<text v-else>获取当前位置...</text>
|
<text v-else>获取当前位置...</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="store-image" @tap.stop="selectStore()">
|
<view class="store-image" @click="selectStore()">
|
||||||
<image :src="$util.img(globalStoreInfo.store_image)"
|
<image :src="$util.img(globalStoreInfo.store_image)"
|
||||||
v-if="globalStoreInfo && globalStoreInfo.store_image" mode="aspectFill"></image>
|
v-if="globalStoreInfo && globalStoreInfo.store_image" mode="aspectFill"></image>
|
||||||
<image :src="$util.getDefaultImage().store" v-else mode="aspectFill"></image>
|
<image :src="$util.getDefaultImage().store" v-else mode="aspectFill"></image>
|
||||||
@@ -29,9 +29,9 @@
|
|||||||
</block>
|
</block>
|
||||||
|
|
||||||
<block v-if="value.style == 2">
|
<block v-if="value.style == 2">
|
||||||
<view class="store-box store-three" @tap.stop="toStoreList()">
|
<view class="store-box store-three" @click="toStoreList()">
|
||||||
<view class="store-info">
|
<view class="store-info">
|
||||||
<view class="store-image" @tap.stop="selectStore()">
|
<view class="store-image" @click="selectStore()">
|
||||||
<image :src="$util.img(globalStoreInfo.store_image)"
|
<image :src="$util.img(globalStoreInfo.store_image)"
|
||||||
v-if="globalStoreInfo && globalStoreInfo.store_image" mode="aspectFill"></image>
|
v-if="globalStoreInfo && globalStoreInfo.store_image" mode="aspectFill"></image>
|
||||||
<image :src="$util.getDefaultImage().store" v-else mode="aspectFill"></image>
|
<image :src="$util.getDefaultImage().store" v-else mode="aspectFill"></image>
|
||||||
@@ -47,13 +47,13 @@
|
|||||||
<text class="title" v-else>定位中...</text>
|
<text class="title" v-else>定位中...</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="store-icon" @tap.stop="search()"><text class="iconfont icon-sousuo3"
|
<view class="store-icon" @click.stop="search()"><text class="iconfont icon-sousuo3"
|
||||||
:style="{ color: value.textColor }"></text></view>
|
:style="{ color: value.textColor }"></text></view>
|
||||||
</view>
|
</view>
|
||||||
</block>
|
</block>
|
||||||
|
|
||||||
<block v-if="value.style == 3">
|
<block v-if="value.style == 3">
|
||||||
<view class="store-box store-four" @tap.stop="toStoreList()">
|
<view class="store-box store-four" @click="toStoreList()">
|
||||||
<view class="store-left-wrap">
|
<view class="store-left-wrap">
|
||||||
<block v-if="globalStoreInfo && globalStoreInfo.store_id">
|
<block v-if="globalStoreInfo && globalStoreInfo.store_id">
|
||||||
<text class="iconfont icon-weizhi" :style="{ color: value.textColor }"></text>
|
<text class="iconfont icon-weizhi" :style="{ color: value.textColor }"></text>
|
||||||
@@ -64,8 +64,8 @@
|
|||||||
</view>
|
</view>
|
||||||
<view class="store-right-search">
|
<view class="store-right-search">
|
||||||
<input type="text" class="uni-input font-size-tag" disabled placeholder="商品搜索"
|
<input type="text" class="uni-input font-size-tag" disabled placeholder="商品搜索"
|
||||||
@tap.stop="search()" />
|
@click.stop="search()" />
|
||||||
<text class="iconfont icon-sousuo3" @tap.stop="search()"></text>
|
<text class="iconfont icon-sousuo3" @click.stop="search()"></text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</block>
|
</block>
|
||||||
|
|||||||
@@ -1,834 +0,0 @@
|
|||||||
<template>
|
|
||||||
<!-- DIY 标签页组件 - 支持多种样式和位置的标签页切换 -->
|
|
||||||
<view data-component-name="diy-tab" class="diy-tab" :class="'tab-position-' + mergedValue.tabPosition"
|
|
||||||
:style="[getCustomStyle('container')]">
|
|
||||||
<!-- 标签导航栏 -->
|
|
||||||
<view class="tab-nav" :style="[tabNavStyle, getCustomStyle('nav')]">
|
|
||||||
<!-- 标签项循环渲染 -->
|
|
||||||
<view v-for="(tab, index) in mergedValue.tabs" :key="tab.id || index"
|
|
||||||
:class="['tab-item', mergedValue.tabStyle, { active: activeTab === index }]" @tap="switchTab(index)"
|
|
||||||
:style="[tabItemStyle(index), getCustomStyle('tabItem'), activeTab === index ? getCustomStyle('tabItemActive') : {}]">
|
|
||||||
<!-- 标签文本 -->
|
|
||||||
<text
|
|
||||||
:style="[tabTextStyle(index), getCustomStyle('tabText'), activeTab === index ? getCustomStyle('tabTextActive') : {}]">{{
|
|
||||||
getTabTitle(tab.title) }}</text>
|
|
||||||
<!-- 标签指示器(底部线条) -->
|
|
||||||
<view v-if="mergedValue.showIndicator" class="tab-indicator"
|
|
||||||
:style="[tabIndicatorStyle(index), getCustomStyle('indicator')]"></view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- 标签内容区域 -->
|
|
||||||
<view class="tab-content" :style="[tabContentStyle, getCustomStyle('content')]">
|
|
||||||
<!-- 标签面板循环渲染 -->
|
|
||||||
<view v-for="(tab, index) in mergedValue.tabs" :key="index"
|
|
||||||
:class="['tab-panel', { active: activeTab === index }]"
|
|
||||||
:style="[tabPanelStyle(index), getCustomStyle('panel'), activeTab === index ? getCustomStyle('panelActive') : {}]">
|
|
||||||
<!-- 渲染每个标签下的组件 -->
|
|
||||||
<diy-group v-if="tab.components" :diyData="{ value: tab.components, global: diyGlobal }"
|
|
||||||
:scrollTop="tab.scrollTop || 0" />
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
// 导入 DIY 混入
|
|
||||||
import DiyMinx from './minx.js'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'diy-tab',
|
|
||||||
|
|
||||||
// 组件注册 - 使用懒加载解决循环依赖
|
|
||||||
components: {
|
|
||||||
diyGroup: () => import('./diy-group.vue')
|
|
||||||
},
|
|
||||||
|
|
||||||
// 组件属性定义
|
|
||||||
props: {
|
|
||||||
// 标签页配置对象
|
|
||||||
value: {
|
|
||||||
type: Object,
|
|
||||||
default: () => ({})
|
|
||||||
},
|
|
||||||
// 全局配置对象
|
|
||||||
diyGlobal: {
|
|
||||||
type: Object,
|
|
||||||
default: () => ({})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// 混入
|
|
||||||
mixins: [DiyMinx],
|
|
||||||
|
|
||||||
// 组件数据
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
activeTab: this.value?.activeTabIndex ?? 0, // 设置当前激活的标签索引
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
// 组件创建钩子
|
|
||||||
created() {
|
|
||||||
console.log(`diy-tab-create`, {
|
|
||||||
value: this.mergedValue,
|
|
||||||
tabs: this.mergedValue.tabs
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
// 计算属性
|
|
||||||
computed: {
|
|
||||||
// 合并默认值和传入值
|
|
||||||
mergedValue() {
|
|
||||||
// 标签页数据配置
|
|
||||||
const tabsConfig = {
|
|
||||||
/**
|
|
||||||
* 标签页数据配置
|
|
||||||
* @type {Array<{title: string|Object, scrollTop: number, components: Array}>}
|
|
||||||
* @property {string} id 标签唯一标识
|
|
||||||
* @property {string|Object} title - 标签标题
|
|
||||||
* • 字符串: 普通文本或国际化键(如 'tab.home')
|
|
||||||
* • 对象: 多语言映射(如 { 'zh-cn': '首页', 'en-us': 'Home' })
|
|
||||||
* @property {number} scrollTop - 标签滚动位置
|
|
||||||
* @property {Array} components - 标签下的组件列表
|
|
||||||
*/
|
|
||||||
tabs: []
|
|
||||||
};
|
|
||||||
|
|
||||||
// 基础配置
|
|
||||||
const baseConfig = {
|
|
||||||
/**
|
|
||||||
* 是否显示指示器
|
|
||||||
* @type {boolean}
|
|
||||||
* @default true
|
|
||||||
*/
|
|
||||||
showIndicator: true,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 激活的标签索引
|
|
||||||
* @type {number}
|
|
||||||
* @default 0
|
|
||||||
*/
|
|
||||||
activeTabIndex: 0,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 标签样式
|
|
||||||
* @type {string}
|
|
||||||
* @default 'default'
|
|
||||||
* @values 'default', 'underline', 'card'
|
|
||||||
*/
|
|
||||||
tabStyle: 'default',
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 标签位置
|
|
||||||
* @type {string}
|
|
||||||
* @default 'top'
|
|
||||||
* @values 'top', 'bottom', 'left', 'right'
|
|
||||||
*/
|
|
||||||
tabPosition: 'top'
|
|
||||||
};
|
|
||||||
|
|
||||||
// 导航栏样式
|
|
||||||
const navConfig = {
|
|
||||||
/**
|
|
||||||
* 标签栏高度
|
|
||||||
* @type {number|string}
|
|
||||||
* @default 24
|
|
||||||
* @unit 像素(当为数字时)
|
|
||||||
* @range 建议值:20-80
|
|
||||||
* @format
|
|
||||||
* • 数字: 像素值(如 24)
|
|
||||||
* • 字符串: CSS长度值(如 '24px', '3rem', '4em')
|
|
||||||
* • CSS变量: 'var(--tab-height)'
|
|
||||||
* • 百分比: '10%' (相对父元素高度)
|
|
||||||
*/
|
|
||||||
tabHeight: 24,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 标签栏背景色
|
|
||||||
* @type {string}
|
|
||||||
* @default '#ffffff'
|
|
||||||
* @format CSS颜色值
|
|
||||||
*/
|
|
||||||
tabBgColor: '#ffffff',
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 标签栏内边距
|
|
||||||
* @type {string}
|
|
||||||
* @default '0'
|
|
||||||
* @format CSS padding值
|
|
||||||
* @examples
|
|
||||||
* • 单个值: '0', '10px', '1rem' (四向相同)
|
|
||||||
* • 两个值: '10px 20px' (上下 左右)
|
|
||||||
* • 三个值: '10px 20px 30px' (上 左右 下)
|
|
||||||
* • 四个值: '10px 20px 30px 40px' (上 右 下 左)
|
|
||||||
* • CSS变量: 'var(--tab-padding)'
|
|
||||||
* • 百分比: '5% 10%' (相对父元素宽度)
|
|
||||||
* @note 卡片样式下会忽略此配置,自动使用基于 tabGap 的内边距
|
|
||||||
*/
|
|
||||||
tabPadding: '0'
|
|
||||||
};
|
|
||||||
|
|
||||||
// 标签项样式
|
|
||||||
const tabItemConfig = {
|
|
||||||
/**
|
|
||||||
* 标签间距
|
|
||||||
* @type {number|string}
|
|
||||||
* @default 10
|
|
||||||
* @unit 像素(当为数字时)
|
|
||||||
* @range 建议值:0-30
|
|
||||||
* @format
|
|
||||||
* • 数字: 像素值(如 10)
|
|
||||||
* • 字符串: CSS长度值(如 '10px', '0.5rem', '1em')
|
|
||||||
* • CSS变量: 'var(--tab-gap)'
|
|
||||||
* • 百分比: '5%' (相对父元素宽度)
|
|
||||||
*/
|
|
||||||
tabGap: 10,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 字体大小
|
|
||||||
* @type {number|string}
|
|
||||||
* @default 14
|
|
||||||
* @unit 像素(当为数字时)
|
|
||||||
* @range 建议值:10-20
|
|
||||||
* @format
|
|
||||||
* • 数字: 像素值(如 14)
|
|
||||||
* • 字符串: CSS长度值(如 '14px', '0.875rem', '1.4em')
|
|
||||||
* • CSS变量: 'var(--font-size)'
|
|
||||||
*/
|
|
||||||
fontSize: 14,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 激活状态颜色
|
|
||||||
* @type {string}
|
|
||||||
* @default '#ff4444'
|
|
||||||
* @format CSS颜色值
|
|
||||||
*/
|
|
||||||
activeColor: '#ff4444',
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 非激活状态颜色
|
|
||||||
* @type {string}
|
|
||||||
* @default '#666666'
|
|
||||||
* @format CSS颜色值
|
|
||||||
*/
|
|
||||||
inactiveColor: '#666666'
|
|
||||||
};
|
|
||||||
|
|
||||||
// 卡片样式
|
|
||||||
const cardConfig = {
|
|
||||||
/**
|
|
||||||
* 卡片默认背景色
|
|
||||||
* @type {string}
|
|
||||||
* @default '#f5f5f5'
|
|
||||||
* @format CSS颜色值
|
|
||||||
*/
|
|
||||||
cardBgColor: '#f5f5f5',
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 卡片激活背景色
|
|
||||||
* @type {string}
|
|
||||||
* @default '#ff4444'
|
|
||||||
* @format CSS颜色值
|
|
||||||
*/
|
|
||||||
cardActiveBgColor: '#ff4444',
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 卡片默认文字颜色
|
|
||||||
* @type {string}
|
|
||||||
* @default '#666666'
|
|
||||||
* @format CSS颜色值
|
|
||||||
*/
|
|
||||||
cardTextColor: '#666666',
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 卡片激活文字颜色
|
|
||||||
* @type {string}
|
|
||||||
* @default '#ffffff'
|
|
||||||
* @format CSS颜色值
|
|
||||||
*/
|
|
||||||
cardActiveTextColor: '#ffffff',
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 卡片圆角大小
|
|
||||||
* @type {string}
|
|
||||||
* @default '16px'
|
|
||||||
* @format CSS长度值
|
|
||||||
*/
|
|
||||||
cardBorderRadius: '16px',
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 卡片外边距
|
|
||||||
* @type {string}
|
|
||||||
* @default '0 5px'
|
|
||||||
* @format CSS margin值
|
|
||||||
*/
|
|
||||||
cardMargin: '0 5px',
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 卡片内边距
|
|
||||||
* @type {string}
|
|
||||||
* @default '0 10px'
|
|
||||||
* @format CSS padding值
|
|
||||||
*/
|
|
||||||
cardPadding: '0 10px'
|
|
||||||
};
|
|
||||||
|
|
||||||
// 下划线样式
|
|
||||||
const underlineConfig = {
|
|
||||||
/**
|
|
||||||
* 下划线颜色
|
|
||||||
* @type {string}
|
|
||||||
* @default '#ff4444'
|
|
||||||
* @format CSS颜色值
|
|
||||||
*/
|
|
||||||
underlineColor: '#ff4444',
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 下划线高度
|
|
||||||
* @type {number}
|
|
||||||
* @default 2
|
|
||||||
* @unit 像素
|
|
||||||
*/
|
|
||||||
underlineHeight: 2,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 下划线圆角大小
|
|
||||||
* @type {string}
|
|
||||||
* @default '1px'
|
|
||||||
* @format CSS长度值
|
|
||||||
*/
|
|
||||||
underlineBorderRadius: '1px',
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 下划线左右边距
|
|
||||||
* @type {number}
|
|
||||||
* @default 10
|
|
||||||
* @unit 像素
|
|
||||||
*/
|
|
||||||
underlineMargin: 10
|
|
||||||
};
|
|
||||||
|
|
||||||
// 指示器样式
|
|
||||||
const indicatorConfig = {
|
|
||||||
/**
|
|
||||||
* 指示器颜色
|
|
||||||
* @type {string}
|
|
||||||
* @default '#ff4444'
|
|
||||||
* @format CSS颜色值
|
|
||||||
*/
|
|
||||||
indicatorColor: '#ff4444',
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 指示器高度
|
|
||||||
* @type {number}
|
|
||||||
* @default 2
|
|
||||||
* @unit 像素
|
|
||||||
*/
|
|
||||||
indicatorHeight: 2
|
|
||||||
};
|
|
||||||
|
|
||||||
// 内容区域样式
|
|
||||||
const contentConfig = {
|
|
||||||
/**
|
|
||||||
* 内容区内边距
|
|
||||||
* @type {number|string}
|
|
||||||
* @default 10
|
|
||||||
* @unit 像素(当为数字时)
|
|
||||||
* @range 建议值:0-50
|
|
||||||
* @format
|
|
||||||
* • 数字: 像素值(如 10)
|
|
||||||
* • 字符串: CSS长度值(如 '10px', '1rem', '2em')
|
|
||||||
* • CSS变量: 'var(--content-padding)'
|
|
||||||
* • 百分比: '5%' (相对父元素宽度)
|
|
||||||
*/
|
|
||||||
contentPadding: 10,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 内容区背景色
|
|
||||||
* @type {string}
|
|
||||||
* @default '#f5f5f5'
|
|
||||||
* @format CSS颜色值
|
|
||||||
* @examples
|
|
||||||
* • 十六进制: '#ffffff', '#f5f5f5'
|
|
||||||
* • RGB: 'rgb(255, 255, 255)'
|
|
||||||
* • RGBA: 'rgba(255, 255, 255, 0.5)'
|
|
||||||
* • HSL: 'hsl(0, 0%, 100%)'
|
|
||||||
* • CSS变量: 'var(--content-bg-color)'
|
|
||||||
* • 预定义颜色: 'white', 'black', 'gray'
|
|
||||||
*/
|
|
||||||
contentBgColor: '#f5f5f5',
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 内容区最小高度
|
|
||||||
* @type {number|string}
|
|
||||||
* @default 200
|
|
||||||
* @unit 像素(当为数字时)
|
|
||||||
* @range 建议值:50-1000
|
|
||||||
* @format
|
|
||||||
* • 数字: 像素值(如 200)
|
|
||||||
* • 字符串: CSS长度值(如 '200px', '20vh', '5rem')
|
|
||||||
* • CSS变量: 'var(--content-min-height)'
|
|
||||||
* • 百分比: '50%' (相对父元素高度)
|
|
||||||
*/
|
|
||||||
contentMinHeight: 200
|
|
||||||
};
|
|
||||||
|
|
||||||
// 自定义样式配置
|
|
||||||
const customStylesConfig = {
|
|
||||||
/**
|
|
||||||
* 自定义样式配置
|
|
||||||
* @type {Object}
|
|
||||||
* @description 允许外部通过完整的 CSS 样式对象完全覆盖各个部分的样式
|
|
||||||
* @property {Object} container - 容器样式
|
|
||||||
* @example { width: '100%', height: '500px', backgroundColor: '#f0f0f0' }
|
|
||||||
* @property {Object} nav - 导航栏样式
|
|
||||||
* @example { backgroundColor: '#ffffff', borderBottom: '1px solid #e0e0e0' }
|
|
||||||
* @property {Object} tabItem - 标签项样式(非激活状态)
|
|
||||||
* @example { padding: '10px 20px', borderRadius: '4px' }
|
|
||||||
* @property {Object} tabItemActive - 标签项激活样式
|
|
||||||
* @example { backgroundColor: '#ff4444', color: '#ffffff' }
|
|
||||||
* @property {Object} tabText - 标签文本样式(非激活状态)
|
|
||||||
* @example { fontSize: '14px', color: '#666666' }
|
|
||||||
* @property {Object} tabTextActive - 标签文本激活样式
|
|
||||||
* @example { fontSize: '16px', color: '#ffffff', fontWeight: 'bold' }
|
|
||||||
* @property {Object} indicator - 指示器样式
|
|
||||||
* @example { backgroundColor: '#ff4444', height: '3px' }
|
|
||||||
* @property {Object} content - 内容区域样式
|
|
||||||
* @example { padding: '20px', backgroundColor: '#f9f9f9' }
|
|
||||||
* @property {Object} panel - 标签面板样式(非激活状态)
|
|
||||||
* @example { opacity: 0.5, transform: 'translateY(10px)' }
|
|
||||||
* @property {Object} panelActive - 标签面板激活样式
|
|
||||||
* @example { opacity: 1, transform: 'translateY(0)' }
|
|
||||||
*/
|
|
||||||
customStyles: {
|
|
||||||
container: {},
|
|
||||||
nav: {},
|
|
||||||
tabItem: {},
|
|
||||||
tabItemActive: {},
|
|
||||||
tabText: {},
|
|
||||||
tabTextActive: {},
|
|
||||||
indicator: {},
|
|
||||||
content: {},
|
|
||||||
panel: {},
|
|
||||||
panelActive: {}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 合并所有配置
|
|
||||||
const defaults = {
|
|
||||||
...tabsConfig,
|
|
||||||
...baseConfig,
|
|
||||||
...navConfig,
|
|
||||||
...tabItemConfig,
|
|
||||||
...cardConfig,
|
|
||||||
...underlineConfig,
|
|
||||||
...indicatorConfig,
|
|
||||||
...contentConfig,
|
|
||||||
...customStylesConfig
|
|
||||||
};
|
|
||||||
|
|
||||||
// 使用展开运算符合并默认值和传入值
|
|
||||||
return { ...defaults, ...this.value };
|
|
||||||
},
|
|
||||||
|
|
||||||
// 判断是否为水平布局(顶部或底部)
|
|
||||||
isHorizontal() {
|
|
||||||
return ['top', 'bottom'].includes(this.mergedValue.tabPosition);
|
|
||||||
},
|
|
||||||
|
|
||||||
// 判断是否为垂直布局(左侧或右侧)
|
|
||||||
isVertical() {
|
|
||||||
return ['left', 'right'].includes(this.mergedValue.tabPosition);
|
|
||||||
},
|
|
||||||
|
|
||||||
// 判断是否为卡片样式
|
|
||||||
isCardStyle() {
|
|
||||||
return this.mergedValue.tabStyle === 'card';
|
|
||||||
},
|
|
||||||
|
|
||||||
// 判断是否为下划线样式
|
|
||||||
isUnderlineStyle() {
|
|
||||||
return this.mergedValue.tabStyle === 'underline';
|
|
||||||
},
|
|
||||||
|
|
||||||
// 计算标签导航栏样式
|
|
||||||
tabNavStyle() {
|
|
||||||
const style = {
|
|
||||||
backgroundColor: this.mergedValue.tabBgColor || '#ffffff'
|
|
||||||
};
|
|
||||||
|
|
||||||
// 根据布局方向设置尺寸
|
|
||||||
if (this.isHorizontal) {
|
|
||||||
// 水平布局:设置高度
|
|
||||||
style.height = this.mergedValue.tabHeight + 'px';
|
|
||||||
} else {
|
|
||||||
// 垂直布局:设置宽度和高度
|
|
||||||
style.width = this.mergedValue.tabHeight + 'px';
|
|
||||||
style.height = '100%';
|
|
||||||
style.flexDirection = 'column';
|
|
||||||
}
|
|
||||||
|
|
||||||
// 设置导航栏内边距
|
|
||||||
if (this.mergedValue.tabPadding) {
|
|
||||||
style.padding = this.mergedValue.tabPadding;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 卡片样式下使用标签间距作为内边距
|
|
||||||
if (this.isCardStyle) {
|
|
||||||
style.padding = this.getPadding(this.mergedValue.tabGap);
|
|
||||||
}
|
|
||||||
|
|
||||||
return style;
|
|
||||||
},
|
|
||||||
|
|
||||||
// 计算标签项样式(返回函数)
|
|
||||||
tabItemStyle() {
|
|
||||||
return (index) => {
|
|
||||||
const style = {};
|
|
||||||
|
|
||||||
if (!this.isCardStyle) {
|
|
||||||
// 非卡片样式:设置内边距
|
|
||||||
style.padding = this.getPadding(this.mergedValue.tabGap);
|
|
||||||
} else {
|
|
||||||
// 卡片样式:设置外边距、内边距、圆角和背景色
|
|
||||||
style.margin = this.getCardMargin();
|
|
||||||
style.padding = this.getCardPadding();
|
|
||||||
style.borderRadius = this.mergedValue.cardBorderRadius || '16px';
|
|
||||||
// 根据激活状态设置不同的背景色
|
|
||||||
style.backgroundColor = index === this.activeTab
|
|
||||||
? (this.mergedValue.cardActiveBgColor || this.mergedValue.activeColor)
|
|
||||||
: (this.mergedValue.cardBgColor || '#f5f5f5');
|
|
||||||
}
|
|
||||||
|
|
||||||
return style;
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
// 计算标签内容区域样式
|
|
||||||
tabContentStyle() {
|
|
||||||
return {
|
|
||||||
padding: this.mergedValue.contentPadding + 'px',
|
|
||||||
backgroundColor: this.mergedValue.contentBgColor || '#f5f5f5',
|
|
||||||
minHeight: (this.mergedValue.contentMinHeight || 200) + 'px'
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
// 计算标签文本样式(返回函数)
|
|
||||||
tabTextStyle() {
|
|
||||||
return (index) => ({
|
|
||||||
color: this.activeColor(index),
|
|
||||||
fontSize: (this.mergedValue.fontSize || 14) + 'px'
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
// 计算标签指示器样式(返回函数)
|
|
||||||
tabIndicatorStyle() {
|
|
||||||
return (index) => {
|
|
||||||
const style = {
|
|
||||||
backgroundColor: this.mergedValue.indicatorColor || this.mergedValue.activeColor,
|
|
||||||
transform: index === this.activeTab ? 'scaleX(1)' : 'scaleX(0)',
|
|
||||||
opacity: index === this.activeTab ? 1 : 0
|
|
||||||
};
|
|
||||||
|
|
||||||
// 卡片样式下隐藏指示器
|
|
||||||
if (this.isCardStyle) {
|
|
||||||
style.display = 'none';
|
|
||||||
} else if (this.isUnderlineStyle) {
|
|
||||||
// 下划线样式使用下划线颜色
|
|
||||||
style.backgroundColor = this.mergedValue.underlineColor || this.mergedValue.activeColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 根据样式类型选择指示器尺寸
|
|
||||||
const indicatorSize = (this.isUnderlineStyle ? this.mergedValue.underlineHeight : this.mergedValue.indicatorHeight) || 2;
|
|
||||||
|
|
||||||
// 根据布局方向设置指示器样式
|
|
||||||
if (this.isHorizontal) {
|
|
||||||
// 水平布局:设置高度,使用 scaleX 动画
|
|
||||||
style.height = indicatorSize + 'px';
|
|
||||||
style.transform = index === this.activeTab ? 'scaleX(1)' : 'scaleX(0)';
|
|
||||||
} else {
|
|
||||||
// 垂直布局:设置宽度,使用 scaleY 动画
|
|
||||||
style.width = indicatorSize + 'px';
|
|
||||||
style.height = 'auto';
|
|
||||||
style.transform = index === this.activeTab ? 'scaleY(1)' : 'scaleY(0)';
|
|
||||||
}
|
|
||||||
|
|
||||||
return style;
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
// 计算标签面板样式(返回函数)
|
|
||||||
tabPanelStyle() {
|
|
||||||
return (index) => {
|
|
||||||
const isActive = index === this.activeTab;
|
|
||||||
const style = {
|
|
||||||
display: isActive ? 'block' : 'none',
|
|
||||||
opacity: isActive ? 1 : 0
|
|
||||||
};
|
|
||||||
|
|
||||||
// 根据标签位置定义不同的动画效果
|
|
||||||
const transformMap = {
|
|
||||||
top: ['translateY(0)', 'translateY(10px)'], // 顶部:从下往上滑入
|
|
||||||
bottom: ['translateY(0)', 'translateY(-10px)'], // 底部:从上往下滑入
|
|
||||||
left: ['translateX(0)', 'translateX(10px)'], // 左侧:从右往左滑入
|
|
||||||
right: ['translateX(0)', 'translateX(-10px)'] // 右侧:从左往右滑入
|
|
||||||
};
|
|
||||||
|
|
||||||
// 获取对应的变换值,默认使用无变换
|
|
||||||
const transforms = transformMap[this.mergedValue.tabPosition] || ['translate(0)', 'translate(0)'];
|
|
||||||
// 根据激活状态应用不同的变换
|
|
||||||
style.transform = isActive ? transforms[0] : transforms[1];
|
|
||||||
|
|
||||||
return style;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// 组件方法
|
|
||||||
methods: {
|
|
||||||
// 获取自定义样式
|
|
||||||
getCustomStyle(type) {
|
|
||||||
const customStyles = this.mergedValue.customStyles || {};
|
|
||||||
return customStyles[type] || {};
|
|
||||||
},
|
|
||||||
|
|
||||||
// 获取标签文字颜色
|
|
||||||
activeColor(index) {
|
|
||||||
if (this.isCardStyle) {
|
|
||||||
// 卡片样式:使用卡片文字颜色
|
|
||||||
return index === this.activeTab
|
|
||||||
? (this.mergedValue.cardActiveTextColor || '#ffffff')
|
|
||||||
: (this.mergedValue.cardTextColor || this.mergedValue.inactiveColor);
|
|
||||||
}
|
|
||||||
// 其他样式:使用通用文字颜色
|
|
||||||
return index === this.activeTab ? this.mergedValue.activeColor : this.mergedValue.inactiveColor;
|
|
||||||
},
|
|
||||||
|
|
||||||
// 根据布局方向获取内边距
|
|
||||||
getPadding(gap) {
|
|
||||||
return this.isHorizontal ? `0 ${gap}px` : `${gap}px 0`;
|
|
||||||
},
|
|
||||||
|
|
||||||
// 根据布局方向获取外边距
|
|
||||||
getMargin(gap) {
|
|
||||||
return this.isHorizontal ? `0 ${gap}px` : `${gap}px 0`;
|
|
||||||
},
|
|
||||||
|
|
||||||
// 获取卡片外边距
|
|
||||||
getCardMargin() {
|
|
||||||
return this.mergedValue.cardMargin || this.getMargin(this.mergedValue.tabGap / 2);
|
|
||||||
},
|
|
||||||
|
|
||||||
// 获取卡片内边距
|
|
||||||
getCardPadding() {
|
|
||||||
return this.mergedValue.cardPadding || (this.isHorizontal ? '0 10px' : '10px 0');
|
|
||||||
},
|
|
||||||
|
|
||||||
// 切换标签
|
|
||||||
switchTab(index) {
|
|
||||||
this.activeTab = index;
|
|
||||||
},
|
|
||||||
|
|
||||||
// 国际化方法:获取标签标题
|
|
||||||
getTabTitle(title) {
|
|
||||||
const locale = this.$langConfig.getCurrentLocale();
|
|
||||||
|
|
||||||
// 如果 title 是对象,根据当前语言返回对应值
|
|
||||||
if (typeof title === 'object' && title !== null) {
|
|
||||||
return title[locale] || title['zh-cn'] || Object.values(title)[0] || '';
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果 title 是字符串,保持原有逻辑
|
|
||||||
if (typeof title === 'string' && title.includes('.')) {
|
|
||||||
// 包含点号的标题视为国际化键,使用全局挂载的 $lang 方法翻译
|
|
||||||
return this.$lang ? this.$lang(title) : title;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 不包含点号的标题直接返回
|
|
||||||
return title;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
// ===== 标签布局 Mixin =====
|
|
||||||
// 用于定义不同位置标签的布局方式
|
|
||||||
@mixin tab-layout($direction, $nav-order, $content-order) {
|
|
||||||
flex-direction: $direction;
|
|
||||||
|
|
||||||
.tab-nav {
|
|
||||||
order: $nav-order;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab-content {
|
|
||||||
order: $content-order;
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ===== 指示器位置 Mixin =====
|
|
||||||
// 用于定义不同位置指示器的定位
|
|
||||||
@mixin indicator-position($position, $start, $end) {
|
|
||||||
#{$position}: 0;
|
|
||||||
#{$start}: 0;
|
|
||||||
#{$end}: 0;
|
|
||||||
width: 2px;
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ===== 主容器样式 =====
|
|
||||||
.diy-tab {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
overflow: hidden;
|
|
||||||
display: flex;
|
|
||||||
|
|
||||||
// 默认顶部布局
|
|
||||||
@include tab-layout(column, 1, 2);
|
|
||||||
|
|
||||||
// 底部布局
|
|
||||||
&.tab-position-bottom {
|
|
||||||
@include tab-layout(column, 2, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 左侧布局
|
|
||||||
&.tab-position-left {
|
|
||||||
@include tab-layout(row, 1, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 右侧布局
|
|
||||||
&.tab-position-right {
|
|
||||||
@include tab-layout(row, 2, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ===== 标签导航栏样式 =====
|
|
||||||
.tab-nav {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: flex-start;
|
|
||||||
overflow-x: auto; // 水平滚动
|
|
||||||
overflow-y: hidden; // 禁止垂直滚动
|
|
||||||
white-space: nowrap; // 不换行
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
// 隐藏滚动条(Webkit 浏览器)
|
|
||||||
&::-webkit-scrollbar {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 隐藏滚动条(IE/Edge)
|
|
||||||
-ms-overflow-style: none;
|
|
||||||
// 隐藏滚动条(Firefox)
|
|
||||||
scrollbar-width: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ===== 标签项样式 =====
|
|
||||||
.tab-item {
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
position: relative;
|
|
||||||
padding: 0 16px;
|
|
||||||
height: 100%;
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
|
|
||||||
// 激活状态
|
|
||||||
&.active {
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 减少动画效果(针对偏好减少动画的用户)
|
|
||||||
@media (prefers-reduced-motion: reduce) {
|
|
||||||
transition: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 左右布局下的标签项样式
|
|
||||||
&.tab-position-left .tab-item,
|
|
||||||
&.tab-position-right .tab-item {
|
|
||||||
width: 100%;
|
|
||||||
height: auto;
|
|
||||||
padding: 10px 0;
|
|
||||||
white-space: normal; // 允许换行
|
|
||||||
}
|
|
||||||
|
|
||||||
// ===== 标签文本样式 =====
|
|
||||||
.tab-text {
|
|
||||||
font-size: 14px;
|
|
||||||
transition: color 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ===== 标签指示器样式 =====
|
|
||||||
.tab-indicator {
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0;
|
|
||||||
left: 16px;
|
|
||||||
right: 16px;
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
transform-origin: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 左侧布局的指示器
|
|
||||||
&.tab-position-left .tab-indicator {
|
|
||||||
@include indicator-position(left, top, bottom);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 右侧布局的指示器
|
|
||||||
&.tab-position-right .tab-indicator {
|
|
||||||
@include indicator-position(right, top, bottom);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ===== 标签内容区域样式 =====
|
|
||||||
.tab-content {
|
|
||||||
width: 100%;
|
|
||||||
overflow: hidden;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ===== 标签面板样式 =====
|
|
||||||
.tab-panel {
|
|
||||||
width: 100%;
|
|
||||||
min-height: 200px;
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
|
|
||||||
// 减少动画效果
|
|
||||||
@media (prefers-reduced-motion: reduce) {
|
|
||||||
transition: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ===== 默认和下划线样式 =====
|
|
||||||
.tab-item.default,
|
|
||||||
.tab-item.underline {
|
|
||||||
padding: 0 10px;
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
|
|
||||||
&.active {
|
|
||||||
color: #ff4444;
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 下划线样式的伪元素
|
|
||||||
.tab-item.underline.active::after {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0;
|
|
||||||
left: 10px;
|
|
||||||
right: 10px;
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ===== 卡片样式 =====
|
|
||||||
.tab-item.card {
|
|
||||||
border-radius: 16px;
|
|
||||||
transition: all 0.3s ease;
|
|
||||||
|
|
||||||
&.active {
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<view data-component-name="diy-text" class="diy-text" @tap="handlerClick(value.link)" :style="warpCss">
|
<view data-component-name="diy-text" class="diy-text" @click="handlerClick(value.link)"
|
||||||
|
@tap="handlerClick(value.link)" :style="warpCss">
|
||||||
<view :class="value.style == 'style-8' ? 'title2' : 'title'"
|
<view :class="value.style == 'style-8' ? 'title2' : 'title'"
|
||||||
:style="{ fontSize: value.fontSize * 2 + 'rpx', color: value.textColor }">
|
:style="{ fontSize: value.fontSize * 2 + 'rpx', color: value.textColor }">
|
||||||
<block v-if="value.style == 'style-0'" style="height: 40rpx; line-height: 40rpx;">
|
<block v-if="value.style == 'style-0'" style="height: 40rpx; line-height: 40rpx;">
|
||||||
@@ -99,13 +100,13 @@
|
|||||||
<image :src="$util.img('public/uniapp/diy/style9-2.png')" />
|
<image :src="$util.img('public/uniapp/diy/style9-2.png')" />
|
||||||
</view>
|
</view>
|
||||||
<view class="style9-more" v-if="value.more.isShow" :style="{ color: value.more.color }"
|
<view class="style9-more" v-if="value.more.isShow" :style="{ color: value.more.color }"
|
||||||
@tap.stop="handlerClick(value.more.link)">
|
@click.stop="handlerClick(value.more.link)" @tap="handlerClick(value.more.link)">
|
||||||
{{ value.more.text }}
|
{{ value.more.text }}
|
||||||
<view class="iconfont icon-right" :style="{ color: value.more.color }"></view>
|
<view class="iconfont icon-right" :style="{ color: value.more.color }"></view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<text class="sub-title" :style="{ color: value.subTitle.color }">{{ value.subTitle.text
|
<text class="sub-title" :style="{ color: value.subTitle.color }">{{ value.subTitle.text
|
||||||
}}</text>
|
}}</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</block>
|
</block>
|
||||||
@@ -131,13 +132,13 @@
|
|||||||
<image :src="$util.img('public/uniapp/diy/style10-2.png')"></image>
|
<image :src="$util.img('public/uniapp/diy/style10-2.png')"></image>
|
||||||
</view>
|
</view>
|
||||||
<view class="style10-more" v-if="value.more.isShow" :style="{ color: value.more.color }"
|
<view class="style10-more" v-if="value.more.isShow" :style="{ color: value.more.color }"
|
||||||
@tap.stop="handlerClick(value.more.link)">
|
@click.stop="handlerClick(value.more.link)" @tap="handlerClick(value.more.link)">
|
||||||
{{ value.more.text }}
|
{{ value.more.text }}
|
||||||
<view class="iconfont icon-right" :style="{ color: value.more.color }"></view>
|
<view class="iconfont icon-right" :style="{ color: value.more.color }"></view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<text class="sub-title" :style="{ color: value.subTitle.color }">{{ value.subTitle.text
|
<text class="sub-title" :style="{ color: value.subTitle.color }">{{ value.subTitle.text
|
||||||
}}</text>
|
}}</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</block>
|
</block>
|
||||||
@@ -158,7 +159,7 @@
|
|||||||
value.subTitle.text }}</view>
|
value.subTitle.text }}</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="style11-more" v-if="value.more.isShow" :style="{ color: value.more.color }"
|
<view class="style11-more" v-if="value.more.isShow" :style="{ color: value.more.color }"
|
||||||
@tap.stop="$util.diyRedirectTo(value.more.link)">
|
@click.stop="$util.diyRedirectTo(value.more.link)">
|
||||||
{{ value.more.text }}
|
{{ value.more.text }}
|
||||||
<view class="iconfont icon-right" :style="{ color: value.more.color }"></view>
|
<view class="iconfont icon-right" :style="{ color: value.more.color }"></view>
|
||||||
</view>
|
</view>
|
||||||
@@ -182,9 +183,9 @@
|
|||||||
{{ value.text }}
|
{{ value.text }}
|
||||||
</view>
|
</view>
|
||||||
<text class="style12-sub-title" :style="{ color: value.subTitle.color }">{{ value.subTitle.text
|
<text class="style12-sub-title" :style="{ color: value.subTitle.color }">{{ value.subTitle.text
|
||||||
}}</text>
|
}}</text>
|
||||||
<view class="style12-more" v-if="value.more.isShow" :style="{ color: value.more.color }"
|
<view class="style12-more" v-if="value.more.isShow" :style="{ color: value.more.color }"
|
||||||
@tap.stop="$util.diyRedirectTo(value.more.link)">
|
@click.stop="$util.diyRedirectTo(value.more.link)">
|
||||||
<text>{{ value.more.text }}</text>
|
<text>{{ value.more.text }}</text>
|
||||||
<view class="iconfont icon-right" :style="{ color: value.more.color }"></view>
|
<view class="iconfont icon-right" :style="{ color: value.more.color }"></view>
|
||||||
</view>
|
</view>
|
||||||
@@ -277,7 +278,7 @@
|
|||||||
<text :style="{ fontWeight: value.subTitle.fontWeight }">{{ value.subTitle.text }}</text>
|
<text :style="{ fontWeight: value.subTitle.fontWeight }">{{ value.subTitle.text }}</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="style16-more" v-if="value.more.isShow" :style="{ color: value.more.color }"
|
<view class="style16-more" v-if="value.more.isShow" :style="{ color: value.more.color }"
|
||||||
@tap.stop="$util.diyRedirectTo(value.more.link)">
|
@click.stop="$util.diyRedirectTo(value.more.link)">
|
||||||
<text>{{ value.more.text }}</text>
|
<text>{{ value.more.text }}</text>
|
||||||
<view class="iconfont icon-right" :style="{ color: value.more.color }"></view>
|
<view class="iconfont icon-right" :style="{ color: value.more.color }"></view>
|
||||||
</view>
|
</view>
|
||||||
@@ -323,7 +324,7 @@ export default {
|
|||||||
await this.__$emitEvent({
|
await this.__$emitEvent({
|
||||||
eventName: 'text-tap', data: link, promiseCallback: (event, handler, awaitedResult) => {
|
eventName: 'text-tap', data: link, promiseCallback: (event, handler, awaitedResult) => {
|
||||||
if (!awaitedResult) return;
|
if (!awaitedResult) return;
|
||||||
this.$util.diyRedirectTo(link);
|
$util.diyRedirectTo(link);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,10 +62,13 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import uniPopup from '@/components/uni-popup/uni-popup.vue'
|
||||||
import DiyMinx from './minx.js'
|
import DiyMinx from './minx.js'
|
||||||
export default {
|
export default {
|
||||||
name: 'diy-video-list',
|
name: 'diy-video-list',
|
||||||
|
components: {
|
||||||
|
uniPopup
|
||||||
|
},
|
||||||
props: {
|
props: {
|
||||||
value: {
|
value: {
|
||||||
type: Object,
|
type: Object,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<video data-component-name="diy-video" class="diy-video" :src="$util.img(value.videoUrl)"
|
<video data-component-name="diy-video" class="diy-video" :src="$util.img(value.videoUrl)"
|
||||||
:poster="$util.img(value.imageUrl)" :style="videoWarpCss" objectFit="cover"
|
:poster="$util.img(value.imageUrl)" :style="videoWarpCss" objectFit="cover"
|
||||||
@tap="handlerClick(value.videoUrl)"></video>
|
@click="handlerClick(value.videoUrl)" @tap="handlerClick(value.videoUrl)"></video>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|||||||
@@ -1,188 +0,0 @@
|
|||||||
// 微信视频号组件配置
|
|
||||||
export const wechatChannelConfig = {
|
|
||||||
// 图标相关
|
|
||||||
icon: {
|
|
||||||
defaultSize: 80, // 默认图标尺寸(rpx)
|
|
||||||
smallSize: 60, // 小图标尺寸(rpx)
|
|
||||||
channelArrowSize: 24, // 频道箭头图标尺寸(rpx)
|
|
||||||
channelArrow: 'addon/personnel/shop/view/enterprise/arrow.png', // 频道箭头图标路径
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
// 视频相关配置
|
|
||||||
video: {
|
|
||||||
defaultHeight: 320, // 默认视频高度(rpx)
|
|
||||||
minHeight: 200, // 最小视频高度(rpx)
|
|
||||||
maxHeight: 500, // 最大视频高度(rpx)
|
|
||||||
defaultCoverUrl: 'addon/personnel/shop/view/enterprise/default-video-cover.png', // 默认视频封面
|
|
||||||
},
|
|
||||||
|
|
||||||
// 播放按钮配置
|
|
||||||
playButton: {
|
|
||||||
size: 80, // 标准尺寸(rpx)
|
|
||||||
smallSize: 60, // 小尺寸(rpx)
|
|
||||||
iconSize: 40, // 标准图标尺寸(rpx)
|
|
||||||
smallIconSize: 30, // 小图标尺寸(rpx)
|
|
||||||
background: 'rgba(0, 0, 0, 0.4)', // 背景颜色
|
|
||||||
},
|
|
||||||
|
|
||||||
// 布局配置
|
|
||||||
layout: {
|
|
||||||
borderRadius: 12, // 圆角(rpx)
|
|
||||||
padding: 16, // 内边距(rpx)
|
|
||||||
margin: 10, // 外边距(rpx)
|
|
||||||
},
|
|
||||||
|
|
||||||
// 字体配置
|
|
||||||
font: {
|
|
||||||
channelNameSize: 28, // 频道名称字体大小(rpx)
|
|
||||||
videoTitleSize: 28, // 视频标题字体大小(rpx)
|
|
||||||
statsSize: 24, // 统计信息字体大小(rpx)
|
|
||||||
},
|
|
||||||
|
|
||||||
// 颜色配置
|
|
||||||
color: {
|
|
||||||
channelName: '#333', // 频道名称颜色
|
|
||||||
videoTitle: '#333', // 视频标题颜色
|
|
||||||
stats: '#999', // 统计信息颜色
|
|
||||||
border: '#f0f0f0', // 边框颜色
|
|
||||||
},
|
|
||||||
|
|
||||||
// 微信相关配置
|
|
||||||
wechat: {
|
|
||||||
minSdkVersion: '2.19.2', // 最小微信基础库版本
|
|
||||||
embedComponent: 'channel-video', // 嵌入式视频组件名称
|
|
||||||
},
|
|
||||||
|
|
||||||
// 错误提示配置
|
|
||||||
error: {
|
|
||||||
notWechat: '当前环境不是微信小程序',
|
|
||||||
lowVersion: '当前微信基础库版本过低,需要 2.19.2 或以上版本',
|
|
||||||
notSupported: '当前环境不支持微信视频号',
|
|
||||||
missingFields: '缺少必要字段: {field}',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
// 获取配置项的辅助函数
|
|
||||||
export const getwechatChannelConfig = (key, defaultValue = null) => {
|
|
||||||
const keys = key.split('.');
|
|
||||||
let config = wechatChannelConfig;
|
|
||||||
|
|
||||||
for (const k of keys) {
|
|
||||||
if (config[k] === undefined) {
|
|
||||||
return defaultValue;
|
|
||||||
}
|
|
||||||
config = config[k];
|
|
||||||
}
|
|
||||||
|
|
||||||
return config;
|
|
||||||
};
|
|
||||||
|
|
||||||
// 微信视频号工具函数
|
|
||||||
export const wechatChannelUtil = {
|
|
||||||
// 版本比较
|
|
||||||
versionCompare(v1, v2) {
|
|
||||||
const arr1 = v1.split('.');
|
|
||||||
const arr2 = v2.split('.');
|
|
||||||
for (let i = 0; i < Math.max(arr1.length, arr2.length); i++) {
|
|
||||||
const num1 = parseInt(arr1[i] || 0);
|
|
||||||
const num2 = parseInt(arr2[i] || 0);
|
|
||||||
if (num1 > num2) return 1;
|
|
||||||
if (num1 < num2) return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
},
|
|
||||||
|
|
||||||
// 检查是否支持嵌入式播放
|
|
||||||
isEmbedModeSupported() {
|
|
||||||
return typeof wx !== 'undefined' && wx.canIUse(wechatChannelConfig.wechat.embedComponent);
|
|
||||||
},
|
|
||||||
|
|
||||||
// 获取默认视频封面
|
|
||||||
getDefaultCoverUrl() {
|
|
||||||
return wechatChannelConfig.video.defaultCoverUrl;
|
|
||||||
},
|
|
||||||
|
|
||||||
// 数据校验
|
|
||||||
validateVideoData(item) {
|
|
||||||
const requiredFields = ['feedId', 'finderUserName'];
|
|
||||||
for (const field of requiredFields) {
|
|
||||||
if (!item[field]) {
|
|
||||||
throw new Error(`缺少必要字段: ${field}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
|
|
||||||
// 播放视频
|
|
||||||
playVideo(item) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
try {
|
|
||||||
// 数据校验
|
|
||||||
this.validateVideoData(item);
|
|
||||||
} catch (err) {
|
|
||||||
this.handleError(err, item);
|
|
||||||
reject(err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查微信环境
|
|
||||||
if (typeof wx === 'undefined') {
|
|
||||||
const err = new Error(wechatChannelConfig.error.notWechat);
|
|
||||||
this.handleError(err, item);
|
|
||||||
reject(err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查基础库版本
|
|
||||||
const systemInfo = wx.getSystemInfoSync();
|
|
||||||
const SDKVersion = systemInfo.SDKVersion;
|
|
||||||
if (this.versionCompare(SDKVersion, wechatChannelConfig.wechat.minSdkVersion) < 0) {
|
|
||||||
const err = new Error(wechatChannelConfig.error.lowVersion);
|
|
||||||
this.handleError(err, item);
|
|
||||||
reject(err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 调用微信视频号播放API
|
|
||||||
if (wx.openChannelsActivity) {
|
|
||||||
wx.openChannelsActivity({
|
|
||||||
feedId: item.feedId,
|
|
||||||
finderUserName: item.finderUserName,
|
|
||||||
success: (res) => {
|
|
||||||
console.log('打开视频号成功', res);
|
|
||||||
resolve(res);
|
|
||||||
},
|
|
||||||
fail: (err) => {
|
|
||||||
this.handleError(err, item);
|
|
||||||
reject(err);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
const err = new Error(wechatChannelConfig.error.notSupported);
|
|
||||||
this.handleError(err, item);
|
|
||||||
reject(err);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
// 统一错误处理
|
|
||||||
handleError(err, item) {
|
|
||||||
console.error('微信视频号错误:', err);
|
|
||||||
const { message = '', errMsg = '微信视频播放失败!', errCode = -1 } = err;
|
|
||||||
|
|
||||||
// 错误码5: 表示用户点击了取消. openChannelsActivity:fail cancel
|
|
||||||
if ([5].includes(errCode)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const showErrorToast = (otherMsgs = []) => {
|
|
||||||
uni.showToast({
|
|
||||||
title: [errMsg, message,...otherMsgs].join('\n'),
|
|
||||||
icon: 'none',
|
|
||||||
duration: 2000
|
|
||||||
});
|
|
||||||
}
|
|
||||||
showErrorToast();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -5,18 +5,5 @@ export default {
|
|||||||
// console.log('__$emitEvent', payload)
|
// console.log('__$emitEvent', payload)
|
||||||
await this.$eventBus.emit(payload.eventName, payload.data, payload.promiseCallback)
|
await this.$eventBus.emit(payload.eventName, payload.data, payload.promiseCallback)
|
||||||
},
|
},
|
||||||
|
|
||||||
// 预览图片
|
|
||||||
previewImg(img) {
|
|
||||||
// #ifdef MP-WEIXIN
|
|
||||||
uni.previewImage({
|
|
||||||
current: 0,
|
|
||||||
urls: [this.$util.img(img)],
|
|
||||||
success: function (res) { },
|
|
||||||
fail: function (res) { },
|
|
||||||
complete: function (res) { },
|
|
||||||
})
|
|
||||||
// #endif
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
6
components/ai-chat-message/ai-chat-message.json
Normal file
6
components/ai-chat-message/ai-chat-message.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"component": true,
|
||||||
|
"usingComponents": {
|
||||||
|
"ns-loading": "../ns-loading/ns-loading"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -357,10 +357,14 @@
|
|||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
|
import nsLoading from '@/components/ns-loading/ns-loading.vue'
|
||||||
import aiService from '@/common/js/ai-service.js'
|
import aiService from '@/common/js/ai-service.js'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'ai-chat-message',
|
name: 'ai-chat-message',
|
||||||
|
components: {
|
||||||
|
nsLoading
|
||||||
|
},
|
||||||
props: {
|
props: {
|
||||||
// 初始消息列表
|
// 初始消息列表
|
||||||
initialMessages: {
|
initialMessages: {
|
||||||
@@ -441,14 +445,6 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
onShow() {
|
onShow() {
|
||||||
// 如果不是 AI 客服,立即退出并跳转
|
|
||||||
if (customerServiceType !== 'ai') {
|
|
||||||
uni.showToast({ title: '当前客服类型不支持此页面', icon: 'none' });
|
|
||||||
setTimeout(() => {
|
|
||||||
uni.navigateBack({ delta: 1 }); // 或 redirectTo 首页
|
|
||||||
}, 1000);
|
|
||||||
return; // ⚠️ 关键:阻止后续初始化
|
|
||||||
}
|
|
||||||
// 优先读取本地缓存的会话 ID
|
// 优先读取本地缓存的会话 ID
|
||||||
const localConvId = this.getConversationIdFromLocal();
|
const localConvId = this.getConversationIdFromLocal();
|
||||||
if (localConvId) {
|
if (localConvId) {
|
||||||
@@ -818,121 +814,65 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
// 发送流式消息
|
// 发送流式消息
|
||||||
// 发送流式消息(自动适配 H5 / 微信小程序)
|
async sendStreamMessage(userMessage) {
|
||||||
async sendStreamMessage(userMessage) {
|
// 创建流式消息对象
|
||||||
// 创建流式消息对象
|
const streamMessage = {
|
||||||
const streamMessage = {
|
id: ++this.messageId,
|
||||||
id: ++this.messageId,
|
role: 'ai',
|
||||||
role: 'ai',
|
type: 'text',
|
||||||
type: 'text',
|
content: '',
|
||||||
content: '',
|
timestamp: Date.now(),
|
||||||
timestamp: Date.now(),
|
isStreaming: true
|
||||||
isStreaming: true
|
}
|
||||||
};
|
|
||||||
|
// 移除加载状态,添加流式消息
|
||||||
// 移除加载状态,添加流式消息
|
this.messages = this.messages.filter(msg => msg.type !== 'loading')
|
||||||
this.messages = this.messages.filter(msg => msg.type !== 'loading');
|
this.shouldScrollToBottom = true
|
||||||
this.shouldScrollToBottom = true;
|
this.messages.push(streamMessage)
|
||||||
this.messages.push(streamMessage);
|
|
||||||
|
// 开始流式响应
|
||||||
try {
|
await aiService.sendStreamMessage(
|
||||||
// #ifdef H5
|
|
||||||
// ===== H5: 使用 POST + 流式 (fetch readable stream) =====
|
|
||||||
await aiService.sendHttpStream(
|
|
||||||
userMessage,
|
userMessage,
|
||||||
|
// 流式数据回调
|
||||||
(chunk) => {
|
(chunk) => {
|
||||||
// 实时更新内容
|
streamMessage.content += chunk
|
||||||
streamMessage.content += chunk;
|
this.$forceUpdate() // 或 this.$nextTick()
|
||||||
this.$forceUpdate(); // 强制更新视图
|
|
||||||
},
|
},
|
||||||
|
// 完成回调:处理对象或字符串
|
||||||
(completeResult) => {
|
(completeResult) => {
|
||||||
// 流结束回调
|
|
||||||
let finalContent = '';
|
let finalContent = '';
|
||||||
let convId = '';
|
let convId = '';
|
||||||
|
|
||||||
|
// 判断是对象还是字符串
|
||||||
if (typeof completeResult === 'string') {
|
if (typeof completeResult === 'string') {
|
||||||
finalContent = completeResult;
|
finalContent = completeResult;
|
||||||
} else {
|
} else {
|
||||||
finalContent = completeResult.content || '';
|
finalContent = completeResult.content || '';
|
||||||
convId = completeResult.conversation_id || '';
|
convId = completeResult.conversation_id || ''; // 👈 关键:提取 conversation_id
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新最终内容
|
// 更新消息状态
|
||||||
streamMessage.isStreaming = false;
|
streamMessage.isStreaming = false;
|
||||||
streamMessage.content = finalContent;
|
streamMessage.content = finalContent;
|
||||||
|
|
||||||
// 添加操作按钮
|
// 添加操作按钮
|
||||||
streamMessage.actions = [
|
streamMessage.actions = [
|
||||||
{ id: 1, text: '有帮助', type: 'like' },
|
{ id: 1, text: '有帮助', type: 'like' },
|
||||||
{ id: 2, text: '没帮助', type: 'dislike' }
|
{ id: 2, text: '没帮助', type: 'dislike' }
|
||||||
];
|
];
|
||||||
|
|
||||||
// 保存会话 ID
|
// 保存 conversation_id 到本地
|
||||||
if (convId) {
|
if (convId) {
|
||||||
this.currentConversationId = convId;
|
|
||||||
aiService.setConversationId(convId);
|
aiService.setConversationId(convId);
|
||||||
this.saveConversationIdToLocal(convId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 触发事件
|
// 触发事件
|
||||||
this.$emit('ai-response', streamMessage);
|
this.$emit('ai-response', streamMessage);
|
||||||
|
this.saveConversationIdToLocal(convId);
|
||||||
|
this.currentConversationId = convId;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
// #endif
|
},
|
||||||
|
|
||||||
// #ifdef MP-WEIXIN
|
|
||||||
// ===== 微信小程序: 使用 WebSocket =====
|
|
||||||
await aiService.sendStreamMessage(
|
|
||||||
userMessage,
|
|
||||||
(chunk) => {
|
|
||||||
// 实时更新内容
|
|
||||||
streamMessage.content += chunk;
|
|
||||||
this.$forceUpdate();
|
|
||||||
},
|
|
||||||
(completeResult) => {
|
|
||||||
// 流结束回调
|
|
||||||
let finalContent = completeResult?.content || '';
|
|
||||||
let convId = completeResult?.conversation_id || '';
|
|
||||||
|
|
||||||
// 更新最终内容
|
|
||||||
streamMessage.isStreaming = false;
|
|
||||||
streamMessage.content = finalContent;
|
|
||||||
|
|
||||||
// 添加操作按钮
|
|
||||||
streamMessage.actions = [
|
|
||||||
{ id: 1, text: '有帮助', type: 'like' },
|
|
||||||
{ id: 2, text: '没帮助', type: 'dislike' }
|
|
||||||
];
|
|
||||||
|
|
||||||
// 保存会话 ID
|
|
||||||
if (convId) {
|
|
||||||
this.currentConversationId = convId;
|
|
||||||
aiService.setConversationId(convId);
|
|
||||||
this.saveConversationIdToLocal(convId);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 触发事件
|
|
||||||
this.$emit('ai-response', streamMessage);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
// #endif
|
|
||||||
} catch (error) {
|
|
||||||
console.error('流式请求失败:', error);
|
|
||||||
// 移除流式消息
|
|
||||||
this.messages = this.messages.filter(msg => msg.id !== streamMessage.id);
|
|
||||||
// 显示错误
|
|
||||||
const errorMsg = {
|
|
||||||
id: ++this.messageId,
|
|
||||||
role: 'ai',
|
|
||||||
type: 'text',
|
|
||||||
content: '抱歉,服务暂时不可用,请稍后重试。',
|
|
||||||
timestamp: Date.now(),
|
|
||||||
actions: [{ id: 1, text: '重试', type: 'retry' }]
|
|
||||||
};
|
|
||||||
this.messages.push(errorMsg);
|
|
||||||
this.$emit('ai-response', errorMsg);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
generateAIResponse(userMessage) {
|
generateAIResponse(userMessage) {
|
||||||
const responses = {
|
const responses = {
|
||||||
'你好': '您好!我是AI智能客服,很高兴为您服务!有什么可以帮助您的吗?',
|
'你好': '您好!我是AI智能客服,很高兴为您服务!有什么可以帮助您的吗?',
|
||||||
@@ -1452,7 +1392,7 @@ $radius-lg: 36rpx;
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
/* 仅新增:科技感粉蓝渐变背景 + 流动动画 */
|
/* 仅新增:科技感粉蓝渐变背景 + 流动动画 */
|
||||||
background: white; /* 白色 */
|
background: linear-gradient(135deg, #fde6f7 0%, #f8b7e8 20%, #c4e0ff 50%, #8cb4ff 80%, #ffffff 100%);
|
||||||
background-size: 200% 200%;
|
background-size: 200% 200%;
|
||||||
animation: gradient-flow 15s ease infinite;
|
animation: gradient-flow 15s ease infinite;
|
||||||
/* 原有样式保持不变 */
|
/* 原有样式保持不变 */
|
||||||
@@ -1514,6 +1454,25 @@ $radius-lg: 36rpx;
|
|||||||
min-width: 0;
|
min-width: 0;
|
||||||
width: 0; /* 添加这个属性防止flex元素溢出 */
|
width: 0; /* 添加这个属性防止flex元素溢出 */
|
||||||
|
|
||||||
|
.message-nickname {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: $color-text-light;
|
||||||
|
margin-bottom: 8rpx;
|
||||||
|
letter-spacing: 0.5rpx;
|
||||||
|
// 用户昵称右对齐,AI昵称左对齐
|
||||||
|
&:not(.ai-message .message-nickname) {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
// AI昵称专属样式 - 左移到气泡上方
|
||||||
|
&.ai-nickname {
|
||||||
|
text-align: left;
|
||||||
|
margin-left: 0;
|
||||||
|
padding-left: 0;
|
||||||
|
align-self: flex-start;
|
||||||
|
margin-bottom: 4rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.message-bubble {
|
.message-bubble {
|
||||||
padding: 24rpx 32rpx;
|
padding: 24rpx 32rpx;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
@@ -1933,28 +1892,6 @@ $radius-lg: 36rpx;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========== 关键修复:拆分 .message-nickname 样式 ========== */
|
|
||||||
.message-nickname {
|
|
||||||
font-size: 24rpx;
|
|
||||||
color: $color-text-light;
|
|
||||||
margin-bottom: 8rpx;
|
|
||||||
letter-spacing: 0.5rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 用户昵称:右对齐 */
|
|
||||||
.user-message .message-nickname {
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* AI 昵称:使用 .ai-nickname 类控制 */
|
|
||||||
.ai-nickname {
|
|
||||||
text-align: left;
|
|
||||||
margin-left: 0;
|
|
||||||
padding-left: 0;
|
|
||||||
align-self: flex-start;
|
|
||||||
margin-bottom: 4rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 用户消息特有样式 */
|
/* 用户消息特有样式 */
|
||||||
.user-message {
|
.user-message {
|
||||||
flex-direction: row-reverse;
|
flex-direction: row-reverse;
|
||||||
@@ -1965,20 +1902,20 @@ $radius-lg: 36rpx;
|
|||||||
text-align: right;
|
text-align: right;
|
||||||
|
|
||||||
.message-bubble {
|
.message-bubble {
|
||||||
background: #c4e0ff !important; /* 浅蓝色 */
|
background: linear-gradient(135deg, #ffadd2, #f783ac) !important; /* 粉色渐变 */
|
||||||
color: black !important;
|
color: white !important;
|
||||||
border-radius: 16rpx 16rpx 4rpx 16rpx; /* 右对齐气泡尖角适配 */
|
border-radius: 16rpx 16rpx 4rpx 16rpx; /* 右对齐气泡尖角适配 */
|
||||||
box-shadow: 0 8rpx 20rpx rgba(196, 224, 255, 0.3) !important;
|
box-shadow: 0 8rpx 20rpx rgba(247, 131, 172, 0.3) !important;
|
||||||
border: none !important;
|
border: none !important;
|
||||||
/* ✅ 关键:允许内容撑开高度 */
|
/* ✅ 关键:允许内容撑开高度 */
|
||||||
min-height: auto;
|
min-height: auto;
|
||||||
height: auto;
|
height: auto;
|
||||||
padding: 24rpx 32rpx; /* 保留内边距 */
|
padding: 24rpx 32rpx; /* 保留内边距 */
|
||||||
display: inline-block; /* 让宽度也随内容收缩(可选) */
|
display: inline-block; /* 让宽度也随内容收缩(可选) */
|
||||||
max-width: 80%; /* 防止过宽 */
|
max-width: 80%; /* 防止过宽 */
|
||||||
word-break: break-word;
|
word-break: break-word;
|
||||||
white-space: pre-wrap; /* 保留用户输入的换行符 */
|
white-space: pre-wrap; /* 保留用户输入的换行符 */
|
||||||
line-height: 1.6;
|
line-height: 1.6;
|
||||||
&::before {
|
&::before {
|
||||||
content: '';
|
content: '';
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@@ -2019,19 +1956,19 @@ $radius-lg: 36rpx;
|
|||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
|
|
||||||
.message-bubble {
|
.message-bubble {
|
||||||
background: white !important; /* 白色 */
|
background: linear-gradient(135deg, #dbeafe, #bfdbfe) !important; /* 蓝色浅渐变 */
|
||||||
color: black !important;
|
color: #2c3e50 !important;
|
||||||
border-radius: 16rpx 16rpx 16rpx 4rpx; /* 左对齐气泡尖角适配 */
|
border-radius: 16rpx 16rpx 16rpx 4rpx; /* 左对齐气泡尖角适配 */
|
||||||
box-shadow: 0 8rpx 20rpx rgba(0, 0, 0, 0.1) !important;
|
box-shadow: 0 8rpx 20rpx rgba(191, 219, 254, 0.4) !important;
|
||||||
border: 1rpx solid #e0e0e0 !important;
|
border: 1rpx solid #dbeafe !important;
|
||||||
min-height: auto;
|
min-height: auto;
|
||||||
height: auto;
|
height: auto;
|
||||||
padding: 24rpx 32rpx;
|
padding: 24rpx 32rpx;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
max-width: 80%;
|
max-width: 80%;
|
||||||
word-break: break-word;
|
word-break: break-word;
|
||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
line-height: 1.6;
|
line-height: 1.6;
|
||||||
&::before {
|
&::before {
|
||||||
content: '';
|
content: '';
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@@ -2055,7 +1992,7 @@ $radius-lg: 36rpx;
|
|||||||
|
|
||||||
/* 输入区域 */
|
/* 输入区域 */
|
||||||
.input-area {
|
.input-area {
|
||||||
background: #c4e0ff; /* 浅蓝色 */
|
background: linear-gradient(135deg, #fde6f7 0%, #f8b7e8 20%, #c4e0ff 50%, #8cb4ff 80%, #ffffff 100%);
|
||||||
border-top: 2rpx solid #f0f4f8;
|
border-top: 2rpx solid #f0f4f8;
|
||||||
padding: 24rpx 32rpx;
|
padding: 24rpx 32rpx;
|
||||||
/* 确保在微信小程序中紧贴底部 */
|
/* 确保在微信小程序中紧贴底部 */
|
||||||
@@ -2139,10 +2076,10 @@ $radius-lg: 36rpx;
|
|||||||
font-size: 28rpx;
|
font-size: 28rpx;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
border: none;
|
border: none;
|
||||||
text-align: center; /* 兼容多端文字居中 */
|
text-align: center; /* 兼容多端文字居中 */
|
||||||
white-space: nowrap; /* 强制文字单行横向显示 */
|
white-space: nowrap; /* 强制文字单行横向显示 */
|
||||||
line-height: 1; /* 重置行高,避免文字垂直偏移 */
|
line-height: 1; /* 重置行高,避免文字垂直偏移 */
|
||||||
top: -10px;
|
top:-10px;
|
||||||
|
|
||||||
&.disabled {
|
&.disabled {
|
||||||
background-color: $color-primary-light;
|
background-color: $color-primary-light;
|
||||||
@@ -2826,4 +2763,4 @@ $radius-lg: 36rpx;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -635,6 +635,7 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import payment from './payment.js';
|
import payment from './payment.js';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'common-payment',
|
name: 'common-payment',
|
||||||
data() {
|
data() {
|
||||||
@@ -270,7 +270,7 @@ export default {
|
|||||||
});
|
});
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
this.$util.redirectTo(this.$util.INDEX_PAGE_URL);
|
this.$util.redirectTo('/pages/index/index');
|
||||||
}, 1000)
|
}, 1000)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3,21 +3,16 @@
|
|||||||
<view scroll-y="true" class="goods-detail" :class="isIphoneX ? 'active' : ''">
|
<view scroll-y="true" class="goods-detail" :class="isIphoneX ? 'active' : ''">
|
||||||
<view class="goods-container">
|
<view class="goods-container">
|
||||||
<!-- 弹幕 -->
|
<!-- 弹幕 -->
|
||||||
<pengpai-fadein-out v-if="goodsSkuDetail.barrage_show && goodsSkuDetail.barrageData" ref="pengpai"
|
<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"/>
|
||||||
:duration="1600" :wait="1900" :top="200" :left="0" :radius="60" :loop="true"
|
|
||||||
:info="goodsSkuDetail.barrageData" />
|
|
||||||
|
|
||||||
<!-- 商品媒体信息 -->
|
<!-- 商品媒体信息 -->
|
||||||
<view class="goods-media" :style="{ height: goodsSkuDetail.swiperHeight }">
|
<view class="goods-media" :style="{height: goodsSkuDetail.swiperHeight}">
|
||||||
<!-- 商品图片 -->
|
<!-- 商品图片 -->
|
||||||
<view class="goods-img" :class="{ show: switchMedia == 'img' }">
|
<view class="goods-img" :class="{ show: switchMedia == 'img' }">
|
||||||
<swiper class="swiper" @change="swiperChange" :interval="swiperInterval"
|
<swiper class="swiper" @change="swiperChange" :interval="swiperInterval" :autoplay="swiperAutoplay" autoplay="true" interval="4000" circular="true">
|
||||||
: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">
|
||||||
<swiper-item v-for="(item, index) in goodsSkuDetail.sku_images" :key="index"
|
|
||||||
:item-id="'goods_id_' + index">
|
|
||||||
<view class="item" @click="previewMedia(index)">
|
<view class="item" @click="previewMedia(index)">
|
||||||
<image :src="$util.img(item, { size: 'big' })" @error="swiperImageError(index)"
|
<image :src="$util.img(item, { size: 'big' })" @error="swiperImageError(index)" mode="aspectFit" />
|
||||||
mode="aspectFit" />
|
|
||||||
</view>
|
</view>
|
||||||
</swiper-item>
|
</swiper-item>
|
||||||
</swiper>
|
</swiper>
|
||||||
@@ -29,16 +24,13 @@
|
|||||||
|
|
||||||
<!-- 商品视频 -->
|
<!-- 商品视频 -->
|
||||||
<view class="goods-video" :class="{ show: switchMedia == 'video' }">
|
<view class="goods-video" :class="{ show: switchMedia == 'video' }">
|
||||||
<video id="goodsVideo" :src="$util.img(goodsSkuDetail.video_url)"
|
<video id="goodsVideo" :src="$util.img(goodsSkuDetail.video_url)" :poster="$util.img(goodsSkuDetail.sku_image, { size: 'big' })" objectFit="cover"></video>
|
||||||
:poster="$util.img(goodsSkuDetail.sku_image, { size: 'big' })" objectFit="cover"></video>
|
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 切换视频、图片 -->
|
<!-- 切换视频、图片 -->
|
||||||
<view class="media-mode" v-if="goodsSkuDetail.video_url != ''">
|
<view class="media-mode" v-if="goodsSkuDetail.video_url != ''">
|
||||||
<text :class="{ 'color-base-bg': switchMedia == 'video' }" @click="switchMedia = 'video'">{{
|
<text :class="{ 'color-base-bg': switchMedia == 'video' }" @click="switchMedia = 'video'">{{ $lang('video') }}</text>
|
||||||
$lang('video') }}</text>
|
<text :class="{ 'color-base-bg': switchMedia == 'img' }" @click="(switchMedia = 'img'), videoContext.pause()">{{ $lang('image') }}</text>
|
||||||
<text :class="{ 'color-base-bg': switchMedia == 'img' }"
|
|
||||||
@click="(switchMedia = 'img'), videoContext.pause()">{{ $lang('image') }}</text>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
@@ -48,20 +40,19 @@
|
|||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view class="newdetail margin-bottom" v-if="goodsSkuDetail.isinformation == 0">
|
<view class="newdetail margin-bottom" v-if="goodsSkuDetail.isinformation == 0">
|
||||||
|
|
||||||
<!-- 入口区域 -->
|
<!-- 入口区域 -->
|
||||||
<slot name="entrance"></slot>
|
<slot name="entrance"></slot>
|
||||||
|
|
||||||
<!-- 配送 -->
|
<!-- 配送 -->
|
||||||
<!-- @click="$refs.deliveryType.open()" -->
|
<!-- @click="$refs.deliveryType.open()" -->
|
||||||
<view class="item delivery-type" v-if="goodsSkuDetail.is_virtual == 0">
|
<view class="item delivery-type" v-if="goodsSkuDetail.is_virtual == 0" >
|
||||||
<view class="label">{{ $lang('send') }}</view>
|
<view class="label">{{$lang('send')}}</view>
|
||||||
<block v-if="deliveryType">
|
<block v-if="deliveryType">
|
||||||
<view class="box">
|
<view class="box">
|
||||||
<block v-for="(item, index) in deliveryType" :key="index">
|
<block v-for="(item, index) in deliveryType" :key="index">
|
||||||
<text
|
<text v-if="goodsSkuDetail.support_trade_type.indexOf(index) != -1">{{$lang('express')}}</text>
|
||||||
v-if="goodsSkuDetail.support_trade_type.indexOf(index) != -1">{{ $lang('express') }}</text>
|
<!-- {{ item.name }} -->
|
||||||
<!-- {{ item.name }} -->
|
|
||||||
</block>
|
</block>
|
||||||
</view>
|
</view>
|
||||||
<text class="iconfont icon-right"></text>
|
<text class="iconfont icon-right"></text>
|
||||||
@@ -72,7 +63,7 @@
|
|||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 门店 -->
|
<!-- 门店 -->
|
||||||
<!-- <view class="item store-wrap" @click="openStoreListPopup()" v-if="addonIsExist.store && globalStoreInfo && isShowStore">
|
<!-- <view class="item store-wrap" @click="openStoreListPopup()" v-if="addonIsExist.store && globalStoreInfo && isShowStore">
|
||||||
<view class="label">门店</view>
|
<view class="label">门店</view>
|
||||||
<view class="list-wrap">
|
<view class="list-wrap">
|
||||||
<view class="name-wrap">
|
<view class="name-wrap">
|
||||||
@@ -89,21 +80,15 @@
|
|||||||
<text class="iconfont icon-right"></text>
|
<text class="iconfont icon-right"></text>
|
||||||
</view> -->
|
</view> -->
|
||||||
|
|
||||||
<view class="item service" @click="openMerchantsServicePopup()"
|
<view class="item service" @click="openMerchantsServicePopup()" v-if="goodsSkuDetail.goods_service.length">
|
||||||
v-if="goodsSkuDetail.goods_service.length">
|
|
||||||
<view class="label">服务</view>
|
<view class="label">服务</view>
|
||||||
<view class="list-wrap">
|
<view class="list-wrap">
|
||||||
<view class="item-wrap" v-for="(item, index) in goodsSkuDetail.goods_service" :key="index"
|
<view class="item-wrap" v-for="(item, index) in goodsSkuDetail.goods_service" :key="index" v-if="index < 3">
|
||||||
v-if="index < 3">
|
|
||||||
<view class="item-wrap-box">
|
<view class="item-wrap-box">
|
||||||
<view class="item-wrap-icon">
|
<view class="item-wrap-icon">
|
||||||
<text class="iconfont icon-dui"
|
<text class="iconfont icon-dui" v-if="!item.icon || (!item.icon.imageUrl && !item.icon.icon)"></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)" />
|
||||||
<image class="icon-img" v-else-if="item.icon.iconType == 'img'"
|
<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>
|
||||||
: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>
|
||||||
<text>{{ item.service_name }}</text>
|
<text>{{ item.service_name }}</text>
|
||||||
</view>
|
</view>
|
||||||
@@ -111,32 +96,30 @@
|
|||||||
</view>
|
</view>
|
||||||
<text class="iconfont icon-right"></text>
|
<text class="iconfont icon-right"></text>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!--多规格区域-->
|
<!--多规格区域-->
|
||||||
<view class="newdetail margin-bottom" v-if="goodsSkuDetail.sku_spec_format">
|
<view class="newdetail margin-bottom" v-if="goodsSkuDetail.sku_spec_format">
|
||||||
<!-- 入口区域 -->
|
<!-- 入口区域 -->
|
||||||
<slot name="skuspec"></slot>
|
<slot name="skuspec"></slot>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
|
|
||||||
<view class="newdetail margin-bottom" v-if="goodsSkuDetail.merch_id > 0">
|
<view class="newdetail margin-bottom" v-if="goodsSkuDetail.merch_id > 0">
|
||||||
<!-- 入口区域 -->
|
<!-- 入口区域 -->
|
||||||
<slot name="entrance"></slot>
|
<slot name="entrance"></slot>
|
||||||
<!-- 商家 -->
|
<!-- 商家 -->
|
||||||
<view class="item store-wrap"
|
<view class="item store-wrap" @click="$util.redirectTo('/pages_promotion/merch/detail', { merch_id: goodsSkuDetail.merch_id })">
|
||||||
@click="$util.redirectTo('/pages_promotion/merch/detail', { merch_id: goodsSkuDetail.merch_id })">
|
|
||||||
<view class="list-wrap" style="display: flex;">
|
<view class="list-wrap" style="display: flex;">
|
||||||
<view class="name-wrap">
|
<view class="name-wrap">
|
||||||
<image :src="$util.img(goodsSkuDetail.merchinfo.merch_image)" mode="widthFix"
|
<image :src="$util.img(goodsSkuDetail.merchinfo.merch_image)" mode="widthFix" style="width: 100rpx;height: 100rpx;border-radius: 50rpx;"></image>
|
||||||
style="width: 100rpx;height: 100rpx;border-radius: 50rpx;"></image>
|
|
||||||
</view>
|
</view>
|
||||||
<view class="other-wrap">
|
<view class="other-wrap">
|
||||||
<view class="address" style="margin-left: 30rpx;">
|
<view class="address" style="margin-left: 30rpx;">
|
||||||
<view>{{ goodsSkuDetail.merchinfo.merch_name }}</view>
|
<view>{{goodsSkuDetail.merchinfo.merch_name}}</view>
|
||||||
<view style="font-size: 24rpx;color: #888;">官方认证商家,值得信赖!</view>
|
<view style="font-size: 24rpx;color: #888;">官方认证商家,值得信赖!</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<text class="iconfont icon-right"></text>
|
<text class="iconfont icon-right"></text>
|
||||||
@@ -153,8 +136,7 @@
|
|||||||
</view>
|
</view>
|
||||||
<scroll-view scroll-y class="type-body">
|
<scroll-view scroll-y class="type-body">
|
||||||
<block v-for="(item, index) in deliveryType" :key="index">
|
<block v-for="(item, index) in deliveryType" :key="index">
|
||||||
<view class="type-item"
|
<view class="type-item" :class="{ 'not-support': goodsSkuDetail.support_trade_type.indexOf(index) == -1 }">
|
||||||
:class="{ 'not-support': goodsSkuDetail.support_trade_type.indexOf(index) == -1 }">
|
|
||||||
<text class="iconfont" :class="item.icon"></text>
|
<text class="iconfont" :class="item.icon"></text>
|
||||||
<view class="content">
|
<view class="content">
|
||||||
<view class="title">{{ item.name }}</view>
|
<view class="title">{{ item.name }}</view>
|
||||||
@@ -176,16 +158,11 @@
|
|||||||
<text class="iconfont icon-close"></text>
|
<text class="iconfont icon-close"></text>
|
||||||
</view>
|
</view>
|
||||||
<scroll-view scroll-y>
|
<scroll-view scroll-y>
|
||||||
<view class="item" :class="{ 'empty-desc': !item.desc }"
|
<view class="item" :class="{ 'empty-desc': !item.desc }" v-for="(item, index) in goodsSkuDetail.goods_service" :key="index">
|
||||||
v-for="(item, index) in goodsSkuDetail.goods_service" :key="index">
|
<view class="item-icon" :class="{'empty-desc':!item.desc}">
|
||||||
<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>
|
||||||
<text class="iconfont icon-dui color-base-text"
|
<image class="icon-img" v-else-if="item.icon.iconType == 'img'" :src=" $util.img(item.icon.imageUrl)" />
|
||||||
v-if="!item.icon || (!item.icon.imageUrl && !item.icon.icon)"></text>
|
<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>
|
||||||
<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>
|
||||||
<view class="info-wrap">
|
<view class="info-wrap">
|
||||||
<text class="title">{{ item.service_name }}</text>
|
<text class="title">{{ item.service_name }}</text>
|
||||||
@@ -210,19 +187,17 @@
|
|||||||
</view>
|
</view>
|
||||||
<scroll-view scroll-y>
|
<scroll-view scroll-y>
|
||||||
<view class="store-list-content">
|
<view class="store-list-content">
|
||||||
<view class="list-item" v-for="(item, index) in storeList.data" :key="index"
|
<view class="list-item" v-for="(item, index) in storeList.data" :key="index" @click="selectStore(item)">
|
||||||
@click="selectStore(item)">
|
|
||||||
<view class="item-box">
|
<view class="item-box">
|
||||||
<view class="item-image">
|
<view class="item-image">
|
||||||
<image :src="$util.img(item.store_image)" v-if="item.store_image" />
|
<image :src="$util.img(item.store_image)" v-if="item.store_image"/>
|
||||||
<image :src="$util.getDefaultImage().store" v-else />
|
<image :src="$util.getDefaultImage().store" v-else/>
|
||||||
</view>
|
</view>
|
||||||
<view class="item-info">
|
<view class="item-info">
|
||||||
<view class="item-title">
|
<view class="item-title">
|
||||||
<text class="title">{{ item.store_name }}</text>
|
<text class="title">{{ item.store_name }}</text>
|
||||||
<text class="distance color-base-text" v-if="item.distance">
|
<text class="distance color-base-text" v-if="item.distance">
|
||||||
距离{{ item.distance > 1 ? item.distance + 'km' : item.distance *
|
距离{{ item.distance > 1 ? item.distance + 'km' : item.distance * 1000 + 'm' }}
|
||||||
1000 + 'm' }}
|
|
||||||
</text>
|
</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="item-time" v-if="item.open_date">营业时间:{{ item.open_date }}
|
<view class="item-time" v-if="item.open_date">营业时间:{{ item.open_date }}
|
||||||
@@ -253,7 +228,7 @@
|
|||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 促销 -->
|
<!-- 促销 -->
|
||||||
<!-- <view class="community-model" @touchmove.prevent.stop @click.stop="onCloseCommunity()" v-show="isCommunity">
|
<!-- <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" @click.stop>
|
||||||
<view class="community-model-content-radius">
|
<view class="community-model-content-radius">
|
||||||
<view>添加社群</view>
|
<view>添加社群</view>
|
||||||
@@ -272,8 +247,7 @@
|
|||||||
<slot name="articipation"></slot>
|
<slot name="articipation"></slot>
|
||||||
|
|
||||||
<!-- 商品评价 -->
|
<!-- 商品评价 -->
|
||||||
<view class="group-wrap" v-if="evaluateConfig.evaluate_show == 1 && goodsSkuDetail.isinformation == 0"
|
<view class="group-wrap" v-if="evaluateConfig.evaluate_show == 1 && goodsSkuDetail.isinformation == 0" style="display: none;">
|
||||||
style="display: none;">
|
|
||||||
<view class="goods-evaluate" @click="toEvaluateDetail(goodsSkuDetail.goods_id)">
|
<view class="goods-evaluate" @click="toEvaluateDetail(goodsSkuDetail.goods_id)">
|
||||||
<view class="tit">
|
<view class="tit">
|
||||||
<!-- <view class="tit" :class="{ active: goodsEvaluate.content }"> -->
|
<!-- <view class="tit" :class="{ active: goodsEvaluate.content }"> -->
|
||||||
@@ -294,18 +268,12 @@
|
|||||||
<view class="evaluator">
|
<view class="evaluator">
|
||||||
<view class="evaluator-info">
|
<view class="evaluator-info">
|
||||||
<view class="evaluator-face">
|
<view class="evaluator-face">
|
||||||
<image v-if="item.member_headimg" :src="$util.img(item.member_headimg)"
|
<image v-if="item.member_headimg" :src="$util.img(item.member_headimg)" @error="item.member_headimg = $util.getDefaultImage().head" mode="aspectFill" />
|
||||||
@error="item.member_headimg = $util.getDefaultImage().head"
|
<image v-else :src="$util.getDefaultImage().head" @error="item.member_headimg = $util.getDefaultImage().head" mode="aspectFill" />
|
||||||
mode="aspectFill" />
|
|
||||||
<image v-else :src="$util.getDefaultImage().head"
|
|
||||||
@error="item.member_headimg = $util.getDefaultImage().head"
|
|
||||||
mode="aspectFill" />
|
|
||||||
</view>
|
</view>
|
||||||
<view class="evaluator-name-wrap">
|
<view class="evaluator-name-wrap">
|
||||||
<text class="evaluator-name using-hidden"
|
<text class="evaluator-name using-hidden" v-if="item.member_name.length > 2 && item.is_anonymous == 1">
|
||||||
v-if="item.member_name.length > 2 && item.is_anonymous == 1">
|
{{ item.member_name[0] }}***{{ item.member_name[item.member_name.length - 1] }}
|
||||||
{{ item.member_name[0] }}***{{ item.member_name[item.member_name.length - 1]
|
|
||||||
}}
|
|
||||||
</text>
|
</text>
|
||||||
<text class="evaluator-name using-hidden" v-else>{{ item.member_name }}</text>
|
<text class="evaluator-name using-hidden" v-else>{{ item.member_name }}</text>
|
||||||
<view v-if="item.scores" class="evaluator-xing">
|
<view v-if="item.scores" class="evaluator-xing">
|
||||||
@@ -318,8 +286,7 @@
|
|||||||
<view class="cont margin-top">{{ item.content }}</view>
|
<view class="cont margin-top">{{ item.content }}</view>
|
||||||
<scroll-view scroll-x="true">
|
<scroll-view scroll-x="true">
|
||||||
<view class="evaluate-img" v-if="item.images">
|
<view class="evaluate-img" v-if="item.images">
|
||||||
<view class="img-box" v-for="(img, img_index) in item.images" :key="img_index"
|
<view class="img-box" v-for="(img, img_index) in item.images" :key="img_index" @click="previewEvaluate(index, img_index, 'images')">
|
||||||
@click="previewEvaluate(index, img_index, 'images')">
|
|
||||||
<image :src="$util.img(img)" mode="aspectFill" />
|
<image :src="$util.img(img)" mode="aspectFill" />
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@@ -327,9 +294,8 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view class="goods-attr"
|
<view class="goods-attr" v-if="goodsSkuDetail.goods_attr_format && goodsSkuDetail.goods_attr_format.length > 0">
|
||||||
v-if="goodsSkuDetail.goods_attr_format && goodsSkuDetail.goods_attr_format.length > 0">
|
|
||||||
<view class="title">规格属性</view>
|
<view class="title">规格属性</view>
|
||||||
<view class="attr-wrap">
|
<view class="attr-wrap">
|
||||||
<block v-for="(item, index) in goodsSkuDetail.goods_attr_format" :key="index">
|
<block v-for="(item, index) in goodsSkuDetail.goods_attr_format" :key="index">
|
||||||
@@ -338,8 +304,7 @@
|
|||||||
<text class="value-name">{{ item.attr_value_name }}</text>
|
<text class="value-name">{{ item.attr_value_name }}</text>
|
||||||
</view>
|
</view>
|
||||||
</block>
|
</block>
|
||||||
<view class="attr-action" v-if="goodsSkuDetail.goods_attr_format.length > 4"
|
<view class="attr-action" v-if="goodsSkuDetail.goods_attr_format.length > 4" @click="switchGoodsAttr">
|
||||||
@click="switchGoodsAttr">
|
|
||||||
<block v-if="!goodsAttrShow">
|
<block v-if="!goodsAttrShow">
|
||||||
展开<text class="iconfont icon-iconangledown"></text>
|
展开<text class="iconfont icon-iconangledown"></text>
|
||||||
</block>
|
</block>
|
||||||
@@ -350,25 +315,24 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!-- 详情 -->
|
<!-- 详情 -->
|
||||||
<view class="goods-detail-tab">
|
<view class="goods-detail-tab">
|
||||||
<view class="detail-tab">
|
<view class="detail-tab">
|
||||||
<view class="tab-item">{{ $lang('details') }}</view>
|
<view class="tab-item">{{$lang('details')}}</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="detail-content active">
|
<view class="detail-content active">
|
||||||
<view class="detail-content-item">
|
<view class="detail-content-item">
|
||||||
<view class="goods-details" v-if="goodsSkuDetail.goods_content">
|
<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> -->
|
<!-- <rich-text :nodes="goodsSkuDetail.goods_content" @click="showImg($event)" :data-nodes="goodsSkuDetail.goods_content"></rich-text> -->
|
||||||
<!-- {{goodsSkuDetail.goods_content}} -->
|
<!-- {{goodsSkuDetail.goods_content}} -->
|
||||||
<mp-html :content="goodsSkuDetail.goods_content" />
|
<mp-html :content="goodsSkuDetail.goods_content" />
|
||||||
<!-- :loading="loading" @preview="preview" @navigate="navigate" -->
|
<!-- :loading="loading" @preview="preview" @navigate="navigate" -->
|
||||||
</view>
|
</view>
|
||||||
<view class="goods-details active" v-else></view>
|
<view class="goods-details active" v-else></view>
|
||||||
<view class="goods-details" v-if="service && service.is_display == 1 && service.content">
|
<view class="goods-details" v-if="service && service.is_display == 1 && service.content">
|
||||||
<rich-text :nodes="service.content" @click="showImg($event)"
|
<rich-text :nodes="service.content" @click="showImg($event)" :data-nodes="service.content"></rich-text>
|
||||||
:data-nodes="service.content"></rich-text>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@@ -455,30 +419,37 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
// 商品详情视图
|
// 商品详情视图
|
||||||
import scroll from '@/common/js/scroll-view.js';
|
import uniPopup from '@/components/uni-popup/uni-popup.vue';
|
||||||
import detail from './detail.js';
|
import nsGoodsRecommend from '@/components/ns-goods-recommend/ns-goods-recommend.vue';
|
||||||
|
import pengpaiFadeinOut from '@/components/pengpai-fadein-out/pengpai-fadein-out.vue';
|
||||||
|
import xiaoStarComponent from '@/components/xiao-star-component/xiao-star-component.vue';
|
||||||
|
import scroll from '@/common/js/scroll-view.js';
|
||||||
|
import toTop from '@/components/toTop/toTop.vue';
|
||||||
|
import detail from './detail.js';
|
||||||
|
|
||||||
import pengpaiFadeinOut from '../pengpai-fadein-out/pengpai-fadein-out.vue';
|
export default {
|
||||||
|
name: 'goods-detail-view',
|
||||||
export default {
|
props: {
|
||||||
name: 'goods-detail-view',
|
goodsSkuDetail: {
|
||||||
props: {
|
type: Object,
|
||||||
goodsSkuDetail: {
|
default: () => {
|
||||||
type: Object,
|
return {};
|
||||||
default: () => {
|
}
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
},
|
components: {
|
||||||
components: {
|
uniPopup,
|
||||||
pengpaiFadeinOut
|
nsGoodsRecommend,
|
||||||
},
|
pengpaiFadeinOut,
|
||||||
mixins: [scroll, detail]
|
toTop,
|
||||||
};
|
xiaoStarComponent
|
||||||
|
},
|
||||||
|
mixins: [scroll, detail]
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@import '@/common/css/goods_detail.scss';
|
@import '@/common/css/goods_detail.scss';
|
||||||
</style>
|
</style>
|
||||||
<style scoped></style>
|
<style scoped></style>
|
||||||
@@ -1,412 +1,246 @@
|
|||||||
<template>
|
<template>
|
||||||
<view v-if="pageCount == 1 || need" class="fixed-box"
|
<!-- 悬浮按钮 -->
|
||||||
:style="[customContainerStyle, {
|
<view v-if="pageCount == 1 || need" class="fixed-box"
|
||||||
height: containerHeight,
|
:style="[{ height: fixBtnShow ? '400rpx' : '320rpx' }, customContainerStyle]">
|
||||||
backgroundImage: bgUrl ? `url( $ {bgUrl})` : '',
|
<!-- <view class="btn-item" v-if="fixBtnShow" @click="$util.redirectTo('/pages/index/index')"> -->
|
||||||
backgroundSize: 'cover'
|
<!-- 切换语言按钮 -->
|
||||||
}]">
|
<button class="btn-item" v-if="fixBtnShow && isLanguageSwitchEnabled" @click="toggleLanguage()"
|
||||||
|
:style="[{ backgroundSize: '100% 100%' }, customButtonStyle]">
|
||||||
|
<text :style="customTextStyle">{{ currentLangDisplayName }}</text>
|
||||||
|
</button>
|
||||||
|
<!-- 客服按钮 -->
|
||||||
|
<!-- #ifdef MP-WEIXIN -->
|
||||||
|
<button class="btn-item" v-if="fixBtnShow" hoverClass="none" openType="contact" sessionFrom="weapp"
|
||||||
|
showMessageCard="true"
|
||||||
|
:style="[{ backgroundImage: 'url(' + (kefuimg ? kefuimg : '') + ')', backgroundSize: '100% 100%' }, customButtonStyle]">
|
||||||
|
<text class="icox icox-kefu" v-if="!kefuimg"></text>
|
||||||
|
<!-- <view>首页</view> -->
|
||||||
|
</button>
|
||||||
|
<!-- #endif -->
|
||||||
|
<view class="btn-item" v-if="fixBtnShow" @click="call()"
|
||||||
|
:style="[{ backgroundImage: 'url(' + (phoneimg ? phoneimg : '') + ')', backgroundSize: '100% 100%' }, customButtonStyle]">
|
||||||
|
<text class="iconfont icon-dianhua" v-if="!phoneimg"></text>
|
||||||
|
<!-- <view>我的</view> -->
|
||||||
|
</view>
|
||||||
|
|
||||||
<!-- ✅ 统一客服入口(根据后台配置自动适配 AI / 企业微信 / 第三方等) -->
|
<!-- <view class="btn-item icon-xiala" v-if="fixBtnShow" @click="fixBtnShow ? (fixBtnShow = false) : (fixBtnShow = true)">
|
||||||
<!-- 微信官方客服需要使用 button open-type="contact" -->
|
<text class="iconfont icon-unfold"></text>
|
||||||
<button
|
</view>
|
||||||
v-if="fixBtnShow && isWeappOfficialKefu"
|
<view class="btn-item switch" v-else :class="{ show: fixBtnShow }"
|
||||||
class="btn-item common-bg"
|
@click="fixBtnShow ? (fixBtnShow = false) : (fixBtnShow = true)">
|
||||||
open-type="contact"
|
<view class="">快捷</view>
|
||||||
:style="{ backgroundImage: currentKefuImg ? `url( $ {currentKefuImg})` : '', backgroundSize: '100% 100%' }"
|
<view>导航</view>
|
||||||
>
|
</view> -->
|
||||||
<text class="ai-icon" v-if="!currentKefuImg">🤖</text>
|
</view>
|
||||||
</button>
|
|
||||||
<!-- 其他类型客服使用普通 view -->
|
|
||||||
<view
|
|
||||||
v-else-if="fixBtnShow"
|
|
||||||
class="btn-item common-bg"
|
|
||||||
@click="handleUnifiedKefuClick"
|
|
||||||
:style="{ backgroundImage: currentKefuImg ? `url( $ {currentKefuImg})` : '', backgroundSize: '100% 100%' }"
|
|
||||||
>
|
|
||||||
<text class="ai-icon" v-if="!currentKefuImg">🤖</text>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- ✅ 新增:小程序系统客服按钮(当附加设置开启时显示) -->
|
|
||||||
<button
|
|
||||||
v-if="fixBtnShow && showWeappSystemKefu"
|
|
||||||
class="btn-item common-bg"
|
|
||||||
open-type="contact"
|
|
||||||
:style="{ backgroundImage: currentKefuImg ? `url( $ {currentKefuImg})` : '', backgroundSize: '100% 100%' }"
|
|
||||||
>
|
|
||||||
<text class="ai-icon" v-if="!currentKefuImg">💬</text>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<!-- 中英文切换按钮 -->
|
|
||||||
<view
|
|
||||||
v-if="isLanguageSwitchEnabled && fixBtnShow"
|
|
||||||
class="btn-item common-bg"
|
|
||||||
@click="toggleLanguage"
|
|
||||||
>
|
|
||||||
<text>{{ currentLangDisplayName }}</text>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- 电话按钮(始终显示) -->
|
|
||||||
<view
|
|
||||||
v-if="fixBtnShow"
|
|
||||||
class="btn-item common-bg"
|
|
||||||
@click="call()"
|
|
||||||
:style="[{ backgroundImage: phoneimg ? `url( $ {phoneimg})` : '', backgroundSize: '100% 100%' }, customButtonStyle]"
|
|
||||||
>
|
|
||||||
<text class="iconfont icon-dianhua" v-if="!phoneimg"></text>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
</view>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { createCustomerService } from '@/common/js/customer-service.js';
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'hover-nav',
|
name: 'hover-nav',
|
||||||
props: {
|
props: {
|
||||||
need: { type: Boolean, default: false }
|
need: {
|
||||||
},
|
type: Boolean,
|
||||||
data() {
|
default: false
|
||||||
return {
|
}
|
||||||
pageCount: 0,
|
},
|
||||||
fixBtnShow: true,
|
data() {
|
||||||
shopInfo: null,
|
return {
|
||||||
currentLangIndex: 0,
|
pageCount: 0,
|
||||||
langIndexMap: {},
|
fixBtnShow: true,
|
||||||
kefuList: [
|
tel: '',
|
||||||
{ id: 'weixin-official', name: '微信官方客服', isOfficial: true, type: 'weapp' },
|
kefuimg: '',
|
||||||
{ id: 'custom-kefu', name: '自定义在线客服', isOfficial: false, type: 'custom' },
|
phoneimg: '',
|
||||||
{ id: 'qyweixin-kefu', name: '企业微信客服', isOfficial: false, type: 'qyweixin' }
|
shopInfo: null, // 店铺信息对象
|
||||||
],
|
|
||||||
selectedKefu: null,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
bgUrl() {
|
|
||||||
return this.shopInfo?.bgUrl || '';
|
|
||||||
},
|
|
||||||
aiAgentimg() {
|
|
||||||
return this.shopInfo?.aiAgentimg || '';
|
|
||||||
},
|
|
||||||
kefuimg() {
|
|
||||||
return this.shopInfo?.kefuimg || this. $util.getDefaultImage().kefu;
|
|
||||||
},
|
|
||||||
phoneimg() {
|
|
||||||
return this.shopInfo?.phoneimg || this. $util.getDefaultImage().phone;
|
|
||||||
},
|
|
||||||
tel() {
|
|
||||||
return this.shopInfo?.mobile || '';
|
|
||||||
},
|
|
||||||
isLanguageSwitchEnabled() {
|
|
||||||
return !!this.shopInfo?.ischina;
|
|
||||||
},
|
|
||||||
currentLangDisplayName() {
|
|
||||||
const lang = this.langIndexMap[this.currentLangIndex];
|
|
||||||
return lang === 'zh-cn' ? 'EN' : 'CN';
|
|
||||||
},
|
|
||||||
customContainerStyle() {
|
|
||||||
return this.shopInfo?.floatingButton?.container || {};
|
|
||||||
},
|
|
||||||
customButtonStyle() {
|
|
||||||
return this.shopInfo?.floatingButton?.button || {};
|
|
||||||
},
|
|
||||||
unreadCount() {
|
|
||||||
return this. $store.state.aiUnreadCount || 0;
|
|
||||||
},
|
|
||||||
|
|
||||||
// ✅ 新增:根据当前客服类型动态返回图标
|
// --- 语言切换相关 ---
|
||||||
currentKefuImg() {
|
currentLangIndex: 0, // 当前选中的语言索引
|
||||||
if (!this.shopInfo) return '';
|
langIndexMap: {}, // 语言索引到语言值的映射
|
||||||
|
isLanguageSwitchEnabled: false, // 是否启用语言切换
|
||||||
|
|
||||||
const customerService = createCustomerService(this);
|
// --- 其他 ---
|
||||||
const config = customerService.getPlatformConfig();
|
};
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
// 初始化语言设置
|
||||||
|
this.initLanguage();
|
||||||
|
|
||||||
if (config?.type === 'aikefu') {
|
this.kefuimg = this.$util.getDefaultImage().kefu
|
||||||
return this.aiAgentimg;
|
this.phoneimg = this.$util.getDefaultImage().phone
|
||||||
} else if (config?.type === 'wxwork' || config?.type === 'qyweixin') {
|
this.pageCount = getCurrentPages().length;
|
||||||
// 企业微信客服专用图标
|
|
||||||
return this.aiAgentimg;
|
|
||||||
}
|
|
||||||
// 默认客服图标
|
|
||||||
return this.kefuimg;
|
|
||||||
},
|
|
||||||
// ✅ 新增:判断是否为微信官方客服
|
|
||||||
isWeappOfficialKefu() {
|
|
||||||
if (!this.shopInfo) return false;
|
|
||||||
const customerService = createCustomerService(this);
|
|
||||||
const config = customerService.getPlatformConfig();
|
|
||||||
return config?.type === 'weapp';
|
|
||||||
},
|
|
||||||
// ✅ 新增:判断是否需要同时显示小程序系统客服
|
|
||||||
showWeappSystemKefu() {
|
|
||||||
if (!this.shopInfo) return false;
|
|
||||||
const customerService = createCustomerService(this);
|
|
||||||
const config = customerService.getPlatformConfig();
|
|
||||||
// 检查附加设置是否开启了同时显示小程序系统客服,且当前客服类型不是小程序系统客服
|
|
||||||
return (config?.show_system_service === true || config?.show_system_service === '1') && config?.type !== 'weapp';
|
|
||||||
},
|
|
||||||
//根据显示的按钮数量动态计算容器高度
|
|
||||||
containerHeight() {
|
|
||||||
if (!this.fixBtnShow) return '320rpx';
|
|
||||||
|
|
||||||
let buttonCount = 1;
|
|
||||||
if (this.isLanguageSwitchEnabled) buttonCount++;
|
|
||||||
if (this.showWeappSystemKefu) buttonCount++;
|
|
||||||
buttonCount++;
|
|
||||||
const totalRpx = 94 * buttonCount - 14;
|
|
||||||
const pxValue = Math.round(totalRpx * 0.5);
|
|
||||||
|
|
||||||
return ` $ {pxValue}px`;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
shopInfo: {
|
|
||||||
handler(newVal) {
|
|
||||||
// 可在此添加额外逻辑(如埋点、通知等),当前无需操作
|
|
||||||
},
|
|
||||||
immediate: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
this.initLanguage();
|
|
||||||
this.pageCount = getCurrentPages().length;
|
|
||||||
|
|
||||||
uni.getStorage({
|
// 从店铺信息中获取相关信息
|
||||||
key: 'shopInfo',
|
uni.getStorage({
|
||||||
success: (e) => {
|
key: 'shopInfo',
|
||||||
console.log('【调试】当前 shopInfo:', e.data);
|
success: (e) => {
|
||||||
this.shopInfo = e.data;
|
console.log(`获取到的shopInfo:${JSON.stringify(e.data)}`)
|
||||||
},
|
this.shopInfo = e.data;
|
||||||
fail: () => {
|
|
||||||
console.warn('未获取到 shopInfo,使用默认设置');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
|
|
||||||
/**
|
// 从店铺信息中获取手机号
|
||||||
* 初始化多语言配置
|
this.tel = e.data.mobile
|
||||||
*/
|
// 从店铺信息中获取是否启用语言切换
|
||||||
initLanguage() {
|
this.isLanguageSwitchEnabled = e.data.ischina;
|
||||||
this.langList = this.$langConfig.list();
|
}
|
||||||
this.langIndexMap = {};
|
})
|
||||||
for (let i = 0; i < this.langList.length; i++) {
|
|
||||||
this.langIndexMap[i] = this.langList[i].value;
|
|
||||||
}
|
|
||||||
const savedLang = this.$langConfig.getCurrentLocale();
|
|
||||||
if (savedLang) {
|
|
||||||
for (let i = 0; i < this.langList.length; i++) {
|
|
||||||
if (this.langList[i].value === savedLang) {
|
|
||||||
this.currentLangIndex = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.currentLangIndex = 0;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
},
|
||||||
* 电话联系客服
|
computed: {
|
||||||
*/
|
currentLangDisplayName() {
|
||||||
call() {
|
// 语言切换按钮显示名称,当前语言为中文时显示EN,否则显示CN
|
||||||
this.customerService.makePhoneCall(this.tel);
|
// 根据 langIndexMap 获取当前语言值
|
||||||
},
|
const lang = this.langIndexMap[this.currentLangIndex];
|
||||||
|
return lang == 'zh-cn' ? 'EN' : 'CN';
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
// 获取容器的自定义样式
|
||||||
* 切换中英文语言,并刷新当前页面(保留所有参数)
|
customContainerStyle() {
|
||||||
*/
|
// 只返回非空的样式属性,确保不覆盖原有的默认样式
|
||||||
toggleLanguage() {
|
return this.shopInfo?.floatingButton?.container || {};
|
||||||
this.currentLangIndex = this.currentLangIndex === 0 ? 1 : 0;
|
},
|
||||||
const targetLang = this.langIndexMap[this.currentLangIndex];
|
|
||||||
|
|
||||||
// 调用语言切换逻辑(设置 storage + 清空缓存)
|
// 获取按钮的自定义样式
|
||||||
this.$langConfig.change(targetLang);
|
customButtonStyle() {
|
||||||
},
|
// 只返回非空的样式属性,确保不覆盖原有的默认样式
|
||||||
|
return this.shopInfo?.floatingButton?.button || {};
|
||||||
/**
|
},
|
||||||
* 打开 AI 智能助手
|
|
||||||
*/
|
|
||||||
openAIChat() {
|
|
||||||
this.$util.redirectTo(this.$util.AI_CHAT_PAGE_URL);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
// 获取文本的自定义样式
|
||||||
* 打开客服选择对话框
|
customTextStyle() {
|
||||||
*/
|
// 只返回非空的样式属性,确保不覆盖原有的默认样式
|
||||||
openCustomerSelectPopup() {
|
return this.shopInfo?.floatingButton?.text || {};
|
||||||
this.customerService.openCustomerSelectPopupDialog();
|
}
|
||||||
},
|
},
|
||||||
|
methods: {
|
||||||
|
initLanguage() {
|
||||||
|
// 初始化语言列表
|
||||||
|
this.langList = this.$langConfig.list();
|
||||||
|
|
||||||
// ✅ 核心方法:统一客服入口
|
// 初始化语言索引映射
|
||||||
handleUnifiedKefuClick() {
|
for (let i = 0; i < this.langList.length; i++) {
|
||||||
const customerService = createCustomerService(this);
|
this.langIndexMap[i] = this.langList[i].value;
|
||||||
const validation = customerService.validateConfig();
|
}
|
||||||
|
|
||||||
console.log('【客服配置验证】', validation);
|
// 获取存储的语言设置
|
||||||
|
const savedLang = uni.getStorageSync('lang');
|
||||||
|
if (savedLang) {
|
||||||
|
for (let i = 0; i < this.langList.length; i++) {
|
||||||
|
if (this.langList[i].value == savedLang) {
|
||||||
|
this.currentLangIndex = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.currentLangIndex = 0;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
//拨打电话
|
||||||
|
call() {
|
||||||
|
uni.makePhoneCall({
|
||||||
|
phoneNumber: this.tel + ''
|
||||||
|
})
|
||||||
|
},
|
||||||
|
toggleLanguage() {
|
||||||
|
// 切换语言索引
|
||||||
|
this.currentLangIndex = this.currentLangIndex == 0 ? 1 : 0;
|
||||||
|
const targetLang = this.langIndexMap[this.currentLangIndex];
|
||||||
|
|
||||||
if (!validation.isValid) {
|
// 获取当前页面路由
|
||||||
console.error('客服配置无效:', validation.errors);
|
let currentRoute = this.$util.getCurrentRoute().path;
|
||||||
uni.showToast({ title: '客服暂不可用', icon: 'none' });
|
// 切换语言并重新加载当前页面
|
||||||
return;
|
this.$langConfig.change(targetLang, currentRoute);
|
||||||
}
|
|
||||||
|
|
||||||
if (validation.warnings.length > 0) {
|
}
|
||||||
console.warn('客服配置警告:', validation.warnings);
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
const platformConfig = customerService.getPlatformConfig();
|
|
||||||
console.log('【当前客服配置】', platformConfig);
|
|
||||||
|
|
||||||
// 检查企业微信配置
|
|
||||||
if (platformConfig.type === 'wxwork') {
|
|
||||||
const wxworkConfig = customerService.getWxworkConfig();
|
|
||||||
console.log('【企业微信配置】', wxworkConfig);
|
|
||||||
|
|
||||||
// #ifdef MP-WEIXIN
|
|
||||||
if (!wxworkConfig?.enable || !wxworkConfig?.contact_url) {
|
|
||||||
console.warn('企业微信配置不完整,使用原生客服');
|
|
||||||
uni.showToast({ title: '企业微信配置不完整', icon: 'none' });
|
|
||||||
}
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
// #ifdef H5
|
|
||||||
if (!wxworkConfig?.contact_url && !platformConfig.wxwork_url) {
|
|
||||||
console.error('企业微信链接未配置');
|
|
||||||
uni.showToast({ title: '企业微信链接未配置', icon: 'none' });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// #endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// 直接调用统一处理方法,由 CustomerService 内部根据配置路由
|
|
||||||
try {
|
|
||||||
customerService.handleCustomerClick({
|
|
||||||
sendMessageTitle: '来自悬浮按钮的咨询',
|
|
||||||
sendMessagePath: '/pages/index/index'
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
console.error('客服处理失败:', error);
|
|
||||||
uni.showToast({ title: '打开客服失败', icon: 'none' });
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
// 以下方法保留用于 actionSheet(如仍需手动选择)
|
|
||||||
openKefuSelectPopup() {
|
|
||||||
const kefuNames = this.kefuList.map(item => item.name);
|
|
||||||
uni.showActionSheet({
|
|
||||||
itemList: kefuNames,
|
|
||||||
success: (res) => {
|
|
||||||
this.selectedKefu = this.kefuList[res.tapIndex];
|
|
||||||
const cs = createCustomerService(this, this.selectedKefu);
|
|
||||||
if (this.selectedKefu.isOfficial) {
|
|
||||||
uni.openCustomerServiceConversation({
|
|
||||||
sessionFrom: 'weapp',
|
|
||||||
showMessageCard: true
|
|
||||||
});
|
|
||||||
} else if (this.selectedKefu.id === 'qyweixin-kefu') {
|
|
||||||
// 处理企业微信客服
|
|
||||||
if (uni.getSystemInfoSync().platform === 'wechat') {
|
|
||||||
// 小程序端:跳转到企业微信客服
|
|
||||||
uni.navigateTo({
|
|
||||||
url: '/pages_tool/qyweixin-kefu/index'
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// H5端:跳转到企业微信链接
|
|
||||||
const qyweixinUrl = this.shopInfo.qyweixinUrl; // 后端返回的企业微信链接
|
|
||||||
if (qyweixinUrl) {
|
|
||||||
window.location.href = qyweixinUrl;
|
|
||||||
} else {
|
|
||||||
uni.showToast({ title: '企业微信客服未配置', icon: 'none' });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
cs.handleCustomerClick();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss">
|
||||||
|
.container-box {
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
.item-wrap {
|
||||||
|
border-radius: 10rpx;
|
||||||
|
|
||||||
|
.image-box {
|
||||||
|
border-radius: 10rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
image {
|
||||||
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
|
border-radius: 10rpx;
|
||||||
|
will-change: transform;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//悬浮按钮
|
||||||
.fixed-box {
|
.fixed-box {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
right: 0rpx;
|
right: 0rpx;
|
||||||
bottom: 240rpx;
|
bottom: 240rpx;
|
||||||
/* #ifdef H5 */
|
// #ifdef H5
|
||||||
bottom: 320rpx;
|
bottom: 320rpx;
|
||||||
/* #endif */
|
// #endif
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
border-radius: 120rpx;
|
// background: #fff;
|
||||||
padding: 20rpx 0;
|
// box-shadow: 2rpx 2rpx 22rpx rgba(0, 0, 0, 0.3);
|
||||||
display: flex;
|
border-radius: 120rpx;
|
||||||
justify-content: center;
|
padding: 20rpx 0;
|
||||||
flex-direction: column;
|
display: flex;
|
||||||
width: 100rpx;
|
justify-content: center;
|
||||||
box-sizing: border-box;
|
flex-direction: column;
|
||||||
transition: 0.3s;
|
width: 100rpx;
|
||||||
overflow: hidden;
|
box-sizing: border-box;
|
||||||
}
|
transition: 0.3s;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
.btn-item {
|
.btn-item {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
margin: 14rpx 0;
|
margin: 14rpx 0;
|
||||||
transition: 0.1s;
|
transition: 0.1s;
|
||||||
color: var(--hover-nav-text-color);
|
background: #c6251b;
|
||||||
border-radius: 40rpx;
|
color: #fff;
|
||||||
width: 80rpx;
|
border-radius: 40rpx;
|
||||||
height: 80rpx;
|
width: 80rpx;
|
||||||
padding: 0;
|
height: 80rpx;
|
||||||
overflow: hidden;
|
padding: 0;
|
||||||
}
|
overflow: hidden;
|
||||||
|
|
||||||
/* 定义共同的背景颜色 */
|
text {
|
||||||
.common-bg {
|
font-size: 28rpx;
|
||||||
background-color: var(--hover-nav-bg-color);
|
}
|
||||||
/* 使用变量以保持一致性 */
|
.iconfont,
|
||||||
}
|
.icox {
|
||||||
|
font-size: 36rpx;
|
||||||
|
font-weight: bold;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
border-radius: 40rpx;
|
||||||
|
/* 确保图标本身也是圆形 */
|
||||||
|
}
|
||||||
|
|
||||||
.btn-item text {
|
view {
|
||||||
font-size: 28rpx;
|
font-size: 26rpx;
|
||||||
}
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
.iconfont,
|
&.show {
|
||||||
.icox {
|
transform: rotate(180deg);
|
||||||
font-size: 36rpx;
|
}
|
||||||
font-weight: bold;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
margin: 14rpx 0;
|
|
||||||
border-radius: 50rpx;
|
|
||||||
width: 80rpx;
|
|
||||||
height: 80rpx;
|
|
||||||
padding: 0;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.iconfont text,
|
&.switch {}
|
||||||
.icox text {
|
|
||||||
font-size: 36rpx;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
&.icon-xiala {
|
||||||
|
margin: 0;
|
||||||
.ai-icon {
|
margin-top: 0.1rpx;
|
||||||
font-size: 40rpx;
|
}
|
||||||
width: 100%;
|
}
|
||||||
height: 100%;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -62,6 +62,8 @@
|
|||||||
// 引入回到顶部组件
|
// 引入回到顶部组件
|
||||||
import MescrollTop from './components/mescroll-top.vue';
|
import MescrollTop from './components/mescroll-top.vue';
|
||||||
|
|
||||||
|
import nsLoading from '@/components/ns-loading/ns-loading.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'mescroll-uni',
|
name: 'mescroll-uni',
|
||||||
components: {
|
components: {
|
||||||
|
|||||||
@@ -1,120 +1,120 @@
|
|||||||
<template>
|
<template>
|
||||||
<view v-if="advList.length" :class="['container-box',className]">
|
<view v-if="advList.length" :class="['container-box',className]">
|
||||||
<swiper :indicator-dots="advList.length > 1" indicator-active-color="#ffffff" :autoplay="true" :interval="3000" :duration="1000" v-if="advList.length > 1" @change="changeSwiper" :current="currentIndex" :style="{ height: swiperHeight + 'px' }" class="item-wrap">
|
<swiper :indicator-dots="advList.length > 1" indicator-active-color="#ffffff" :autoplay="true" :interval="3000" :duration="1000" v-if="advList.length > 1" @change="changeSwiper" :current="currentIndex" :style="{ height: swiperHeight + 'px' }" class="item-wrap">
|
||||||
<swiper-item v-for="(item, index) in advList" :key="index" @click="jumppage(item.adv_url)">
|
<swiper-item v-for="(item, index) in advList" :key="index" @click="jumppage(item.adv_url)">
|
||||||
<view class="image-box">
|
<view class="image-box">
|
||||||
<image :src="$util.img(item.adv_image)" mode="widthFix" :id="'content-wrap' + index"/>
|
<image :src="$util.img(item.adv_image)" mode="widthFix" :id="'content-wrap' + index"/>
|
||||||
</view>
|
</view>
|
||||||
</swiper-item>
|
</swiper-item>
|
||||||
</swiper>
|
</swiper>
|
||||||
<view v-else class="container-box item-wrap">
|
<view v-else class="container-box item-wrap">
|
||||||
<image :src="$util.img(advList[0]['adv_image'])" mode="widthFix" lazy-load="true" @load="imageLoad" @click="jumppage(advList[0].adv_url)"/>
|
<image :src="$util.img(advList[0]['adv_image'])" mode="widthFix" lazy-load="true" @load="imageLoad" @click="jumppage(advList[0].adv_url)"/>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
name: 'ns-advert',
|
name: 'ns-advert',
|
||||||
props: {
|
props: {
|
||||||
keyword: {
|
keyword: {
|
||||||
type: String
|
type: String
|
||||||
},
|
},
|
||||||
className: {
|
className: {
|
||||||
type: String
|
type: String
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
advList: [],
|
advList: [],
|
||||||
isImage: false,
|
isImage: false,
|
||||||
//滑块的高度(单位px)
|
//滑块的高度(单位px)
|
||||||
swiperHeight: 150,
|
swiperHeight: 150,
|
||||||
//当前索引
|
//当前索引
|
||||||
currentIndex: 0,
|
currentIndex: 0,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.getAdvList();
|
this.getAdvList();
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
//获取广告位
|
//获取广告位
|
||||||
getAdvList() {
|
getAdvList() {
|
||||||
var item = {
|
var item = {
|
||||||
adv_image: '',
|
adv_image: '',
|
||||||
adv_url: ''
|
adv_url: ''
|
||||||
};
|
};
|
||||||
this.$api.sendRequest({
|
this.$api.sendRequest({
|
||||||
url: '/api/adv/detail',
|
url: '/api/adv/detail',
|
||||||
data: {
|
data: {
|
||||||
keyword: this.keyword
|
keyword: this.keyword
|
||||||
},
|
},
|
||||||
success: res => {
|
success: res => {
|
||||||
if (res.code == 0) {
|
if (res.code == 0) {
|
||||||
var data = res.data.adv_list;
|
var data = res.data.adv_list;
|
||||||
for (var index in data) {
|
for (var index in data) {
|
||||||
if (data[index].adv_url) data[index].adv_url = JSON.parse(data[index].adv_url);
|
if (data[index].adv_url) data[index].adv_url = JSON.parse(data[index].adv_url);
|
||||||
}
|
}
|
||||||
this.advList = res.data.adv_list;
|
this.advList = res.data.adv_list;
|
||||||
|
|
||||||
//动态设置swiper的高度
|
//动态设置swiper的高度
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.setSwiperHeight();
|
this.setSwiperHeight();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
jumppage(e) {
|
jumppage(e) {
|
||||||
this.$util.diyRedirectTo(e);
|
this.$util.diyRedirectTo(e);
|
||||||
},
|
},
|
||||||
imageLoad(data) {
|
imageLoad(data) {
|
||||||
this.isImage = true;
|
this.isImage = true;
|
||||||
},
|
},
|
||||||
//手动切换题目
|
//手动切换题目
|
||||||
changeSwiper(e) {
|
changeSwiper(e) {
|
||||||
this.currentIndex = e.detail.current;
|
this.currentIndex = e.detail.current;
|
||||||
//动态设置swiper的高度,使用nextTick延时设置
|
//动态设置swiper的高度,使用nextTick延时设置
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.setSwiperHeight();
|
this.setSwiperHeight();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
//动态设置swiper的高度
|
//动态设置swiper的高度
|
||||||
setSwiperHeight() {
|
setSwiperHeight() {
|
||||||
if (this.advList.length > 1) {
|
if (this.advList.length > 1) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
let element = "#content-wrap" + this.currentIndex;
|
let element = "#content-wrap" + this.currentIndex;
|
||||||
let query = uni.createSelectorQuery().in(this);
|
let query = uni.createSelectorQuery().in(this);
|
||||||
query.select(element).boundingClientRect();
|
query.select(element).boundingClientRect();
|
||||||
query.exec((res) => {
|
query.exec((res) => {
|
||||||
if (res && res[0]) {
|
if (res && res[0]) {
|
||||||
this.swiperHeight = res[0].height;
|
this.swiperHeight = res[0].height;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}, 10);
|
}, 10);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.container-box {
|
.container-box {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
.item-wrap {
|
.item-wrap {
|
||||||
border-radius: 10rpx;
|
border-radius: 10rpx;
|
||||||
|
|
||||||
.image-box {
|
.image-box {
|
||||||
border-radius: 10rpx;
|
border-radius: 10rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
image {
|
image {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: auto;
|
height: auto;
|
||||||
border-radius: 10rpx;
|
border-radius: 10rpx;
|
||||||
will-change: transform;
|
will-change: transform;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -80,10 +80,14 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import uniPopup from '../uni-popup/uni-popup.vue';
|
||||||
|
|
||||||
// 注册奖励弹出层
|
// 注册奖励弹出层
|
||||||
export default {
|
export default {
|
||||||
name: 'ns-birthday-gift',
|
name: 'ns-birthday-gift',
|
||||||
|
components: {
|
||||||
|
uniPopup
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
birthday: {
|
birthday: {
|
||||||
@@ -161,7 +165,7 @@
|
|||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.register-box ::v-deep .uni-scroll-view {
|
.register-box /deep/ .uni-scroll-view {
|
||||||
background: unset !important;
|
background: unset !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -171,11 +175,11 @@
|
|||||||
/* margin-top:350rpx; */
|
/* margin-top:350rpx; */
|
||||||
}
|
}
|
||||||
|
|
||||||
::v-deep .uni-popup__wrapper-box {
|
/deep/ .uni-popup__wrapper-box {
|
||||||
background-color: transparent !important;
|
background-color: transparent !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
::v-deep .birthday-title-hint uni-image {
|
/deep/ .birthday-title-hint uni-image {
|
||||||
width: 113rpx !important;
|
width: 113rpx !important;
|
||||||
height: 24rpx !important;
|
height: 24rpx !important;
|
||||||
}
|
}
|
||||||
@@ -1,170 +1,171 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="contact-wrap">
|
<view class="contact-wrap">
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
<!-- #ifdef MP-ALIPAY -->
|
<!-- #ifdef MP-ALIPAY -->
|
||||||
<view class="contact-button" @click="contactServicer">
|
<view class="contact-button" @click="contactServicer">
|
||||||
<contact-button :tnt-inst-id="config.instid" :scene="config.scene" size="1000rpx"
|
<contact-button :tnt-inst-id="config.instid" :scene="config.scene" size="1000rpx" v-if="config.type == 'aliapp'"/>
|
||||||
v-if="config.type == 'aliapp'" />
|
</view>
|
||||||
</view>
|
<!-- #endif -->
|
||||||
<!-- #endif -->
|
<!-- #ifndef MP-ALIPAY -->
|
||||||
|
<button
|
||||||
<!-- #ifdef MP-WEIXIN -->
|
type="default"
|
||||||
<!-- 微信小程序官方客服按钮 -->
|
hover-class="none"
|
||||||
<button v-if="useOfficialService" type="default" hover-class="none" open-type="contact"
|
:open-type="openType"
|
||||||
class="contact-button" sessionFrom="weapp" showMessageCard="true"
|
class="contact-button"
|
||||||
:send-message-title="sendMessageTitle" :send-message-path="sendMessagePath"
|
@click="contactServicer"
|
||||||
:send-message-img="sendMessageImg"></button>
|
:send-message-title="sendMessageTitle"
|
||||||
|
:send-message-path="sendMessagePath"
|
||||||
<!-- 微信小程序自定义客服按钮 -->
|
:send-message-img="sendMessageImg"
|
||||||
<button v-else type="default" hover-class="none" class="contact-button" @click="contactServicer"></button>
|
:show-message-card="true"></button>
|
||||||
<!-- #endif -->
|
<!-- #endif -->
|
||||||
|
<uni-popup ref="servicePopup" type="center">
|
||||||
<!-- #ifndef MP-WEIXIN && MP-ALIPAY -->
|
<view class="service-popup-wrap">
|
||||||
<!-- 其他平台保持原逻辑 -->
|
<view class="head-wrap" @click="$refs.servicePopup.close()">
|
||||||
<button type="default" hover-class="none" :open-type="openType" class="contact-button" @click="contactServicer"
|
<text>联系客服</text>
|
||||||
:send-message-title="sendMessageTitle" :send-message-path="sendMessagePath"
|
<text class="iconfont icon-close"></text>
|
||||||
:send-message-img="sendMessageImg" :show-message-card="true"></button>
|
</view>
|
||||||
<!-- #endif -->
|
<view class="body-wrap">{{ siteInfo.site_tel ? '请联系客服,客服电话是' + siteInfo.site_tel : '抱歉,商家暂无客服,请线下联系' }}</view>
|
||||||
|
</view>
|
||||||
<uni-popup ref="servicePopup" type="center">
|
</uni-popup>
|
||||||
<view class="service-popup-wrap">
|
</view>
|
||||||
<view class="head-wrap" @click="$refs.servicePopup.close()">
|
</template>
|
||||||
<text>联系客服</text>
|
|
||||||
<text class="iconfont icon-close"></text>
|
<!-- 客服组件 -->
|
||||||
</view>
|
<script>
|
||||||
<view class="body-wrap">{{ siteInfo.site_tel ? '请联系客服,客服电话是' + siteInfo.site_tel : '抱歉,商家暂无客服,请线下联系' }}
|
export default {
|
||||||
</view>
|
name: 'ns-contact',
|
||||||
</view>
|
props: {
|
||||||
</uni-popup>
|
niushop: {
|
||||||
</view>
|
type: Object,
|
||||||
</template>
|
default: function() {
|
||||||
|
return {};
|
||||||
<!-- 客服组件 -->
|
}
|
||||||
<script>
|
},
|
||||||
import { createCustomerService } from '@/common/js/customer-service.js';
|
sendMessageTitle: {
|
||||||
|
type: String,
|
||||||
export default {
|
default: ''
|
||||||
name: 'ns-contact',
|
},
|
||||||
props: {
|
sendMessagePath: {
|
||||||
niushop: {
|
type: String,
|
||||||
type: Object,
|
default: ''
|
||||||
default: function () {
|
},
|
||||||
return {};
|
sendMessageImg: {
|
||||||
}
|
type: String,
|
||||||
},
|
default: ''
|
||||||
sendMessageTitle: {
|
}
|
||||||
type: String,
|
},
|
||||||
default: ''
|
data() {
|
||||||
},
|
return {
|
||||||
sendMessagePath: {
|
config: null,
|
||||||
type: String,
|
openType: ''
|
||||||
default: ''
|
};
|
||||||
},
|
},
|
||||||
sendMessageImg: {
|
created() {
|
||||||
type: String,
|
if (this.servicerConfig) {
|
||||||
default: ''
|
// #ifdef H5
|
||||||
}
|
this.config = this.servicerConfig.h5;
|
||||||
},
|
// #endif
|
||||||
data() {
|
|
||||||
return {
|
// #ifdef MP-WEIXIN
|
||||||
customerService: null,
|
this.config = this.servicerConfig.weapp;
|
||||||
buttonConfig: null
|
if (this.config.type == 'weapp') this.openType = 'contact';
|
||||||
};
|
// #endif
|
||||||
},
|
|
||||||
computed: {
|
// #ifdef MP-ALIPAY
|
||||||
/**
|
this.config = this.servicerConfig.aliapp;
|
||||||
* 是否使用官方客服
|
if (this.config.type == 'aliapp') this.openType = 'contact';
|
||||||
*/
|
// #endif
|
||||||
useOfficialService() {
|
}
|
||||||
if (!this.buttonConfig) return true;
|
},
|
||||||
|
methods: {
|
||||||
// #ifdef MP-WEIXIN
|
/**
|
||||||
// 如果是微信小程序,检查配置
|
* 联系客服
|
||||||
if (this.buttonConfig.type === 'weapp') {
|
*/
|
||||||
// 默认使用官方客服,除非明确设置为false
|
contactServicer() {
|
||||||
return this.buttonConfig.useOfficial !== false;
|
if (this.config.type == 'none') {
|
||||||
}
|
this.$refs.servicePopup.open();
|
||||||
// #endif
|
}
|
||||||
|
if (this.openType == 'contact') return;
|
||||||
return false;
|
|
||||||
},
|
switch (this.config.type) {
|
||||||
|
case 'wxwork':
|
||||||
/**
|
// #ifdef H5
|
||||||
* 客服配置
|
location.href = this.config.wxwork_url;
|
||||||
*/
|
// #endif
|
||||||
config() {
|
// #ifdef MP-WEIXIN
|
||||||
return this.customerService?.getPlatformConfig() || {};
|
wx.openCustomerServiceChat({
|
||||||
},
|
extInfo: { url: this.config.wxwork_url },
|
||||||
|
corpId: this.config.corpid,
|
||||||
/**
|
showMessageCard: true,
|
||||||
* 打开类型
|
sendMessageTitle: this.sendMessageTitle,
|
||||||
*/
|
sendMessagePath: this.sendMessagePath,
|
||||||
openType() {
|
sendMessageImg: this.sendMessageImg
|
||||||
return this.buttonConfig?.openType || '';
|
});
|
||||||
}
|
// #endif
|
||||||
},
|
break;
|
||||||
created() {
|
case 'third':
|
||||||
// 初始化客服服务
|
location.href = this.config.third_url;
|
||||||
this.customerService = createCustomerService(this);
|
break;
|
||||||
this.buttonConfig = this.customerService.getButtonConfig();
|
case 'niushop':
|
||||||
},
|
this.$util.redirectTo('/pages_tool/chat/room', this.niushop);
|
||||||
methods: {
|
break;
|
||||||
/**
|
default:
|
||||||
* 联系客服
|
this.makePhoneCall();
|
||||||
*/
|
}
|
||||||
contactServicer() {
|
},
|
||||||
// 如果是微信/支付宝小程序客服,由系统自动处理
|
/**
|
||||||
if (this.buttonConfig.openType === 'contact') {
|
* 店铺联系方式
|
||||||
return;
|
*/
|
||||||
}
|
makePhoneCall() {
|
||||||
|
this.$api.sendRequest({
|
||||||
// 使用统一客服处理
|
url: '/api/site/shopcontact',
|
||||||
this.customerService.handleCustomerClick({
|
success: res => {
|
||||||
niushop: this.niushop,
|
if (res.code == 0 && res.data.mobile) uni.makePhoneCall({
|
||||||
sendMessageTitle: this.sendMessageTitle,
|
phoneNumber: res.data
|
||||||
sendMessagePath: this.sendMessagePath,
|
.mobile
|
||||||
sendMessageImg: this.sendMessageImg
|
});
|
||||||
});
|
}
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
</script>
|
};
|
||||||
|
</script>
|
||||||
<style lang="scss">
|
|
||||||
.contact-wrap {
|
<style lang="scss">
|
||||||
width: 100%;
|
.contact-wrap {
|
||||||
height: 100%;
|
width: 100%;
|
||||||
position: relative;
|
height: 100%;
|
||||||
|
position: relative;
|
||||||
.contact-button {
|
|
||||||
width: 100%;
|
.contact-button {
|
||||||
height: 100%;
|
width: 100%;
|
||||||
position: absolute;
|
height: 100%;
|
||||||
left: 0;
|
position: absolute;
|
||||||
top: 0;
|
left: 0;
|
||||||
z-index: 5;
|
top: 0;
|
||||||
padding: 0;
|
z-index: 5;
|
||||||
margin: 0;
|
padding: 0;
|
||||||
opacity: 0;
|
margin: 0;
|
||||||
overflow: hidden;
|
opacity: 0;
|
||||||
}
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
.service-popup-wrap {
|
|
||||||
width: 600rpx;
|
.service-popup-wrap {
|
||||||
|
width: 600rpx;
|
||||||
.head-wrap {
|
|
||||||
display: flex;
|
.head-wrap {
|
||||||
justify-content: space-between;
|
display: flex;
|
||||||
align-items: center;
|
justify-content: space-between;
|
||||||
padding: 0 30rpx;
|
align-items: center;
|
||||||
height: 90rpx;
|
padding: 0 30rpx;
|
||||||
}
|
height: 90rpx;
|
||||||
|
}
|
||||||
.body-wrap {
|
|
||||||
text-align: center;
|
.body-wrap {
|
||||||
padding: 30rpx;
|
text-align: center;
|
||||||
height: 100rpx;
|
padding: 30rpx;
|
||||||
}
|
height: 100rpx;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -45,7 +45,7 @@ export default {
|
|||||||
if (this.emptyBtn.url) {
|
if (this.emptyBtn.url) {
|
||||||
this.$util.redirectTo(this.emptyBtn.url, {}, 'redirectTo');
|
this.$util.redirectTo(this.emptyBtn.url, {}, 'redirectTo');
|
||||||
} else {
|
} else {
|
||||||
this.$util.redirectTo(this.$util.INDEX_PAGE_URL);
|
this.$util.redirectTo('/pages/index/index');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
re(text) {
|
re(text) {
|
||||||
|
|||||||
@@ -200,8 +200,12 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import pickRegions from '@/components/pick-regions/pick-regions.vue';
|
||||||
export default {
|
export default {
|
||||||
name: 'ns-form',
|
name: 'ns-form',
|
||||||
|
components: {
|
||||||
|
pickRegions
|
||||||
|
},
|
||||||
props: {
|
props: {
|
||||||
data: {
|
data: {
|
||||||
type: Array,
|
type: Array,
|
||||||
|
|||||||
@@ -1,96 +1,96 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="action-buttom-wrap disabled" v-if="disabled" @click="clickEvent">{{ disabledText }}</view>
|
<view class="action-buttom-wrap disabled" v-if="disabled" @click="clickEvent">{{ disabledText }}</view>
|
||||||
<view class="action-buttom-wrap"
|
<view class="action-buttom-wrap"
|
||||||
:class="[backgroundClass, textPrice ? 'has-second' : '', background ? 'color-join-cart' : 'color-base-bg']"
|
:class="[backgroundClass, textPrice ? 'has-second' : '', background ? 'color-join-cart' : 'color-base-bg']"
|
||||||
:style="{background:backgroundColor+'!important', 'color':textColor ? textColor : '#ffffff'}" v-else
|
:style="{background:backgroundColor+'!important', 'color':textColor ? textColor : '#ffffff'}" v-else
|
||||||
@click="clickEvent">
|
@click="clickEvent">
|
||||||
<text class="price-font">{{ textPrice }}</text>
|
<text class="price-font">{{ textPrice }}</text>
|
||||||
<text>{{ text }}</text>
|
<text>{{ text }}</text>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
name: 'ns-goods-action-button',
|
name: 'ns-goods-action-button',
|
||||||
props: {
|
props: {
|
||||||
// 商品底部按钮文字
|
// 商品底部按钮文字
|
||||||
text: {
|
text: {
|
||||||
type: String,
|
type: String,
|
||||||
default: ''
|
default: ''
|
||||||
},
|
},
|
||||||
// 商品底部按钮价格文字
|
// 商品底部按钮价格文字
|
||||||
textPrice: {
|
textPrice: {
|
||||||
type: String,
|
type: String,
|
||||||
default: ''
|
default: ''
|
||||||
},
|
},
|
||||||
// 背景色
|
// 背景色
|
||||||
background: {
|
background: {
|
||||||
type: String,
|
type: String,
|
||||||
default: ''
|
default: ''
|
||||||
},
|
},
|
||||||
// 背景色样式
|
// 背景色样式
|
||||||
backgroundClass: {
|
backgroundClass: {
|
||||||
type: String,
|
type: String,
|
||||||
default: ''
|
default: ''
|
||||||
},
|
},
|
||||||
//
|
//
|
||||||
backgroundColor: {
|
backgroundColor: {
|
||||||
type: String,
|
type: String,
|
||||||
default: ''
|
default: ''
|
||||||
},
|
},
|
||||||
// 是否禁用
|
// 是否禁用
|
||||||
disabled: {
|
disabled: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false
|
||||||
},
|
},
|
||||||
// 禁用文字提示
|
// 禁用文字提示
|
||||||
disabledText: {
|
disabledText: {
|
||||||
type: String,
|
type: String,
|
||||||
default: ''
|
default: ''
|
||||||
},
|
},
|
||||||
// 文字颜色
|
// 文字颜色
|
||||||
textColor: {
|
textColor: {
|
||||||
type: String,
|
type: String,
|
||||||
default: ''
|
default: ''
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
computed: {},
|
computed: {},
|
||||||
methods: {
|
methods: {
|
||||||
clickEvent() {
|
clickEvent() {
|
||||||
this.$emit('click');
|
this.$emit('click');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.action-buttom-wrap {
|
.action-buttom-wrap {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
height: 70rpx;
|
height: 70rpx;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
font-size: 30rpx;
|
font-size: 30rpx;
|
||||||
line-height: 70rpx;
|
line-height: 70rpx;
|
||||||
border: none;
|
border: none;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
border-radius: 10rpx;
|
border-radius: 10rpx;
|
||||||
margin-right: 20rpx;
|
margin-right: 20rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.action-buttom-wrap.has-second {
|
.action-buttom-wrap.has-second {
|
||||||
line-height: 50rpx;
|
line-height: 50rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.action-buttom-wrap.has-second text {
|
.action-buttom-wrap.has-second text {
|
||||||
display: block;
|
display: block;
|
||||||
line-height: 1.2;
|
line-height: 1.2;
|
||||||
}
|
}
|
||||||
|
|
||||||
.action-buttom-wrap:active {
|
.action-buttom-wrap:active {
|
||||||
opacity: 0.8;
|
opacity: 0.8;
|
||||||
}
|
}
|
||||||
|
|
||||||
.action-buttom-wrap.disabled {
|
.action-buttom-wrap.disabled {
|
||||||
background: $color-disabled;
|
background: $color-disabled;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -20,6 +20,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import nsContact from '@/components/ns-contact/ns-contact.vue';
|
||||||
export default {
|
export default {
|
||||||
name: 'ns-goods-action-icon',
|
name: 'ns-goods-action-icon',
|
||||||
props: {
|
props: {
|
||||||
@@ -71,6 +72,9 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
components:{
|
||||||
|
nsContact
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
clickEvent() {
|
clickEvent() {
|
||||||
this.$emit('click');
|
this.$emit('click');
|
||||||
|
|||||||
@@ -3,9 +3,16 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import nsLoading from '@/components/ns-loading/ns-loading.vue';
|
||||||
|
import nsGoodsSkuIndex from '@/components/ns-goods-sku/ns-goods-sku-index.vue';
|
||||||
|
|
||||||
// 商品推荐
|
// 商品推荐
|
||||||
export default {
|
export default {
|
||||||
name: 'ns-goods-recommend',
|
name: 'ns-goods-recommend',
|
||||||
|
components: {
|
||||||
|
nsLoading,
|
||||||
|
nsGoodsSkuIndex
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
list: [],
|
list: [],
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -2,233 +2,235 @@
|
|||||||
<view class="goods-sku">
|
<view class="goods-sku">
|
||||||
<ns-login ref="login"></ns-login>
|
<ns-login ref="login"></ns-login>
|
||||||
<!-- sku选择 -->
|
<!-- sku选择 -->
|
||||||
<ns-goods-sku v-if="goodsDetail.goods_id" ref="goodsSku" :goods-id="goodsDetail.goods_id"
|
<ns-goods-sku v-if="goodsDetail.goods_id" ref="goodsSku" :goods-id="goodsDetail.goods_id" :goods-detail="goodsDetail" :max-buy="goodsDetail.max_buy" :min-buy="goodsDetail.min_buy" @refresh="refreshGoodsSkuDetail"></ns-goods-sku>
|
||||||
:goods-detail="goodsDetail" :max-buy="goodsDetail.max_buy" :min-buy="goodsDetail.min_buy"
|
|
||||||
@refresh="refreshGoodsSkuDetail"></ns-goods-sku>
|
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
// 商品SKU
|
import nsGoodsSku from '@/components/ns-goods-sku/ns-goods-sku.vue';
|
||||||
export default {
|
// 商品SKU
|
||||||
name: 'ns-goods-sku-index',
|
export default {
|
||||||
data() {
|
name: 'ns-goods-sku-index',
|
||||||
return {
|
components: {
|
||||||
timeout: {},
|
nsGoodsSku
|
||||||
isRepeat: false,
|
|
||||||
goodsDetail: {}
|
|
||||||
};
|
|
||||||
},
|
|
||||||
created() { },
|
|
||||||
methods: {
|
|
||||||
/**
|
|
||||||
* 添加购物车
|
|
||||||
* @param {Object} config 购物车事件(detail-详情,cart-加入购物车)
|
|
||||||
* @param {Object} data 商品项
|
|
||||||
*/
|
|
||||||
addCart(config, data, event) {
|
|
||||||
if (!this.storeToken) {
|
|
||||||
this.$refs.login.open(this.$util.INDEX_PAGE_URL);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (config == "detail" || data.is_virtual) {
|
|
||||||
this.$util.redirectTo('/pages_goods/detail', {
|
|
||||||
goods_id: data.goods_id
|
|
||||||
});
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// 多规格
|
|
||||||
if (data.goods_spec_format) {
|
|
||||||
this.multiSpecificationGoods(data);
|
|
||||||
} else {
|
|
||||||
this.singleSpecificationGoods(data, event);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
/**
|
data() {
|
||||||
* 单规格
|
return {
|
||||||
* @param {Object} data 商品项
|
timeout: {},
|
||||||
*/
|
isRepeat: false,
|
||||||
singleSpecificationGoods(data, event) {
|
goodsDetail: {}
|
||||||
let cart =
|
};
|
||||||
this.cartList['goods_' + data.goods_id] && this.cartList['goods_' + data.goods_id]['sku_' + data
|
},
|
||||||
.sku_id
|
created() {},
|
||||||
] ?
|
methods: {
|
||||||
|
/**
|
||||||
|
* 添加购物车
|
||||||
|
* @param {Object} config 购物车事件(detail-详情,cart-加入购物车)
|
||||||
|
* @param {Object} data 商品项
|
||||||
|
*/
|
||||||
|
addCart(config, data, event) {
|
||||||
|
if (!this.storeToken) {
|
||||||
|
this.$refs.login.open('/pages/index/index')
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (config == "detail" || data.is_virtual) {
|
||||||
|
this.$util.redirectTo('/pages_goods/detail', {
|
||||||
|
goods_id: data.goods_id
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// 多规格
|
||||||
|
if (data.goods_spec_format) {
|
||||||
|
this.multiSpecificationGoods(data);
|
||||||
|
} else {
|
||||||
|
this.singleSpecificationGoods(data, event);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 单规格
|
||||||
|
* @param {Object} data 商品项
|
||||||
|
*/
|
||||||
|
singleSpecificationGoods(data, event) {
|
||||||
|
let cart =
|
||||||
|
this.cartList['goods_' + data.goods_id] && this.cartList['goods_' + data.goods_id]['sku_' + data
|
||||||
|
.sku_id
|
||||||
|
] ?
|
||||||
this.cartList['goods_' + data.goods_id]['sku_' + data.sku_id] :
|
this.cartList['goods_' + data.goods_id]['sku_' + data.sku_id] :
|
||||||
null;
|
null;
|
||||||
|
|
||||||
let cartNum = cart ? cart.num : 0;
|
let cartNum = cart ? cart.num : 0;
|
||||||
let api = cart && cart.cart_id ? '/api/cart/edit' : '/api/cart/add';
|
let api = cart && cart.cart_id ? '/api/cart/edit' : '/api/cart/add';
|
||||||
let minBuy = data.min_buy > 0 ? data.min_buy : 1;
|
let minBuy = data.min_buy > 0 ? data.min_buy : 1;
|
||||||
let num = cartNum >= minBuy ? cartNum : minBuy;
|
let num = cartNum >= minBuy ? cartNum : minBuy;
|
||||||
let _num = num;
|
let _num = num;
|
||||||
if (cart && cart.cart_id) {
|
if(cart && cart.cart_id){
|
||||||
_num = _num + (data.min_buy > 0 ? data.min_buy : 1)
|
_num = _num + (data.min_buy > 0 ? data.min_buy : 1)
|
||||||
}
|
}
|
||||||
let cart_id = cart ? cart.cart_id : 0;
|
let cart_id = cart ? cart.cart_id : 0;
|
||||||
if (_num > parseInt(data.stock)) {
|
if (_num > parseInt(data.stock)) {
|
||||||
this.$util.showToast({
|
this.$util.showToast({
|
||||||
title: '商品库存不足'
|
title: '商品库存不足'
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (data.is_limit && data.max_buy && _num > parseInt(data.max_buy)) {
|
if (data.is_limit && data.max_buy && _num > parseInt(data.max_buy)) {
|
||||||
this.$util.showToast({
|
this.$util.showToast({
|
||||||
title: `该商品每人限购${data.max_buy}${data.unit || '件'}`
|
title: `该商品每人限购${data.max_buy}${data.unit || '件'}`
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
if (cart) {
|
|
||||||
this.cartList['goods_' + data.goods_id]['sku_' + data.sku_id].num = _num;
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// 如果商品第一次添加,则初始化数据
|
|
||||||
if (!this.cartList['goods_' + data.goods_id]) {
|
|
||||||
this.cartList['goods_' + data.goods_id] = {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let discount_price = data.discount_price;
|
if (cart) {
|
||||||
if (data.member_price > 0 && Number(data.member_price) <= Number(data.discount_price)) {
|
this.cartList['goods_' + data.goods_id]['sku_' + data.sku_id].num = _num;
|
||||||
discount_price = data.member_price;
|
} else {
|
||||||
}
|
|
||||||
|
|
||||||
this.cartList['goods_' + data.goods_id]['sku_' + data.sku_id] = {
|
// 如果商品第一次添加,则初始化数据
|
||||||
cart_id,
|
if (!this.cartList['goods_' + data.goods_id]) {
|
||||||
goods_id: data.goods_id,
|
this.cartList['goods_' + data.goods_id] = {};
|
||||||
sku_id: data.sku_id,
|
|
||||||
num: _num,
|
|
||||||
discount_price
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.isRepeat) return;
|
|
||||||
this.isRepeat = true;
|
|
||||||
|
|
||||||
this.$emit('addCart', event.currentTarget.id);
|
|
||||||
|
|
||||||
this.$api.sendRequest({
|
|
||||||
url: api,
|
|
||||||
data: {
|
|
||||||
cart_id,
|
|
||||||
sku_id: data.sku_id,
|
|
||||||
num: _num
|
|
||||||
},
|
|
||||||
success: res => {
|
|
||||||
this.isRepeat = false;
|
|
||||||
if (res.code == 0) {
|
|
||||||
if (cart_id == 0) {
|
|
||||||
this.cartList['goods_' + data.goods_id]['sku_' + data.sku_id].cart_id =
|
|
||||||
res.data;
|
|
||||||
}
|
|
||||||
this.$util.showToast({
|
|
||||||
title: "商品添加购物车成功"
|
|
||||||
});
|
|
||||||
this.$store.commit('setCartChange');
|
|
||||||
this.$store.dispatch('cartCalculate');
|
|
||||||
this.$emit("cartListChange", this.cartList);
|
|
||||||
} else {
|
|
||||||
this.$util.showToast({
|
|
||||||
title: res.message
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let discount_price = data.discount_price;
|
||||||
|
if (data.member_price > 0 && Number(data.member_price) <= Number(data.discount_price)) {
|
||||||
|
discount_price = data.member_price;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.cartList['goods_' + data.goods_id]['sku_' + data.sku_id] = {
|
||||||
|
cart_id,
|
||||||
|
goods_id: data.goods_id,
|
||||||
|
sku_id: data.sku_id,
|
||||||
|
num: _num,
|
||||||
|
discount_price
|
||||||
|
};
|
||||||
}
|
}
|
||||||
});
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* 多规格
|
|
||||||
* @param {Object} data 商品项
|
|
||||||
*/
|
|
||||||
multiSpecificationGoods(data) {
|
|
||||||
this.$api.sendRequest({
|
|
||||||
url: '/api/goodssku/getInfoForCategory',
|
|
||||||
data: {
|
|
||||||
sku_id: data.sku_id
|
|
||||||
},
|
|
||||||
success: res => {
|
|
||||||
if (res.code >= 0) {
|
|
||||||
let item = res.data;
|
|
||||||
item.unit = item.unit || '件';
|
|
||||||
|
|
||||||
if (item.sku_images) item.sku_images = item.sku_images.split(',');
|
if (this.isRepeat) return;
|
||||||
else item.sku_images = [];
|
this.isRepeat = true;
|
||||||
|
|
||||||
// 多规格时合并主图
|
this.$emit('addCart', event.currentTarget.id);
|
||||||
if (item.goods_spec_format && item.goods_image) {
|
|
||||||
item.goods_image = item.goods_image.split(',');
|
this.$api.sendRequest({
|
||||||
item.sku_images = item.goods_image.concat(item.sku_images);
|
url: api,
|
||||||
|
data: {
|
||||||
|
cart_id,
|
||||||
|
sku_id: data.sku_id,
|
||||||
|
num: _num
|
||||||
|
},
|
||||||
|
success: res => {
|
||||||
|
this.isRepeat = false;
|
||||||
|
if (res.code == 0) {
|
||||||
|
if (cart_id == 0) {
|
||||||
|
this.cartList['goods_' + data.goods_id]['sku_' + data.sku_id].cart_id =
|
||||||
|
res.data;
|
||||||
|
}
|
||||||
|
this.$util.showToast({
|
||||||
|
title: "商品添加购物车成功"
|
||||||
|
});
|
||||||
|
this.$store.commit('setCartChange');
|
||||||
|
this.$store.dispatch('cartCalculate');
|
||||||
|
this.$emit("cartListChange", this.cartList);
|
||||||
|
} else {
|
||||||
|
this.$util.showToast({
|
||||||
|
title: res.message
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 多规格
|
||||||
|
* @param {Object} data 商品项
|
||||||
|
*/
|
||||||
|
multiSpecificationGoods(data) {
|
||||||
|
this.$api.sendRequest({
|
||||||
|
url: '/api/goodssku/getInfoForCategory',
|
||||||
|
data: {
|
||||||
|
sku_id: data.sku_id
|
||||||
|
},
|
||||||
|
success: res => {
|
||||||
|
if (res.code >= 0) {
|
||||||
|
let item = res.data;
|
||||||
|
item.unit = item.unit || '件';
|
||||||
|
|
||||||
// 当前商品SKU规格
|
if (item.sku_images) item.sku_images = item.sku_images.split(',');
|
||||||
if (item.sku_spec_format) item.sku_spec_format = JSON.parse(item.sku_spec_format);
|
else item.sku_images = [];
|
||||||
|
|
||||||
// 商品SKU格式
|
// 多规格时合并主图
|
||||||
if (item.goods_spec_format) item.goods_spec_format = JSON.parse(item.goods_spec_format);
|
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.promotion_type == 1) {
|
if (item.sku_spec_format) item.sku_spec_format = JSON.parse(item.sku_spec_format);
|
||||||
item.discountTimeMachine = this.$util.countDown(item.end_time - res.timestamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (item.promotion_type == 1 && item.discountTimeMachine) {
|
// 商品SKU格式
|
||||||
if (item.member_price > 0 && Number(item.member_price) <= Number(item.discount_price)) {
|
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;
|
item.show_price = item.member_price;
|
||||||
} else {
|
} else {
|
||||||
item.show_price = item.discount_price;
|
item.show_price = item.price;
|
||||||
}
|
}
|
||||||
} else if (item.member_price > 0) {
|
this.goodsDetail = item;
|
||||||
item.show_price = item.member_price;
|
|
||||||
} else {
|
|
||||||
item.show_price = item.price;
|
|
||||||
}
|
|
||||||
this.goodsDetail = item;
|
|
||||||
|
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
if (this.$refs.goodsSku) {
|
if (this.$refs.goodsSku) {
|
||||||
this.$refs.goodsSku.show("join_cart", (res) => {
|
this.$refs.goodsSku.show("join_cart", (res) => {
|
||||||
|
|
||||||
let goods = this.cartList['goods_' + res.goods_id];
|
let goods = this.cartList['goods_' + res.goods_id];
|
||||||
let cart = null;
|
let cart = null;
|
||||||
if (goods && goods['sku_' + res.sku_id]) {
|
if (goods && goods['sku_' + res.sku_id]) {
|
||||||
cart = goods['sku_' + res.sku_id];
|
cart = goods['sku_' + res.sku_id];
|
||||||
}
|
|
||||||
|
|
||||||
if (cart) {
|
|
||||||
this.cartList['goods_' + res.goods_id]['sku_' + res.sku_id].num = res.num;
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// 如果商品第一次添加,则初始化数据
|
|
||||||
if (!this.cartList['goods_' + res.goods_id]) {
|
|
||||||
this.cartList['goods_' + res.goods_id] = {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.cartList['goods_' + res.goods_id]['sku_' + res.sku_id] = {
|
if (cart) {
|
||||||
cart_id: res.cart_id,
|
this.cartList['goods_' + res.goods_id]['sku_' + res.sku_id].num = res.num;
|
||||||
goods_id: res.goods_id,
|
} else {
|
||||||
sku_id: res.sku_id,
|
|
||||||
num: res.num,
|
|
||||||
discount_price: res.discount_price
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
// 如果商品第一次添加,则初始化数据
|
||||||
|
if (!this.cartList['goods_' + res.goods_id]) {
|
||||||
|
this.cartList['goods_' + res.goods_id] = {};
|
||||||
|
}
|
||||||
|
|
||||||
this.$store.dispatch('cartCalculate');
|
this.cartList['goods_' + res.goods_id]['sku_' + res.sku_id] = {
|
||||||
this.$emit("cartListChange", this.cartList);
|
cart_id: res.cart_id,
|
||||||
|
goods_id: res.goods_id,
|
||||||
|
sku_id: res.sku_id,
|
||||||
|
num: res.num,
|
||||||
|
discount_price: res.discount_price
|
||||||
|
};
|
||||||
|
|
||||||
// 加入购物车动效
|
}
|
||||||
setTimeout(() => {
|
|
||||||
this.$store.commit('setCartChange');
|
|
||||||
}, 100);
|
|
||||||
|
|
||||||
});
|
this.$store.dispatch('cartCalculate');
|
||||||
}
|
this.$emit("cartListChange", this.cartList);
|
||||||
});
|
|
||||||
|
// 加入购物车动效
|
||||||
|
setTimeout(() => {
|
||||||
|
this.$store.commit('setCartChange');
|
||||||
|
}, 100);
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
});
|
},
|
||||||
},
|
refreshGoodsSkuDetail(data) {
|
||||||
refreshGoodsSkuDetail(data) {
|
this.goodsDetail = Object.assign({}, this.goodsDetail, data);
|
||||||
this.goodsDetail = Object.assign({}, this.goodsDetail, data);
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="goods-sku" @touchmove.prevent.stop>
|
<view class="goods-sku" @touchmove.prevent.stop>
|
||||||
<uni-popup-sku ref="skuPopup" type="bottom" class="sku-layer" @change="popclose">
|
<uni-popup ref="skuPopup" type="bottom" class="sku-layer" @change="popclose">
|
||||||
<view class="sku-info" :style="{ height: skuHeight }">
|
<view class="sku-info" :style="{ height: skuHeight }">
|
||||||
<view class="header">
|
<view class="header">
|
||||||
<block v-if="type == 'point' && goodsDetail.type && goodsDetail.type != 1">
|
<block v-if="type == 'point' && goodsDetail.type && goodsDetail.type != 1">
|
||||||
@@ -208,15 +208,19 @@
|
|||||||
<button type="primary" v-else disabled="true">该商品已下架</button>
|
<button type="primary" v-else disabled="true">该商品已下架</button>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</uni-popup-sku>
|
</uni-popup>
|
||||||
<ns-login ref="login"></ns-login>
|
<ns-login ref="login"></ns-login>
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import uniPopup from '@/components/uni-popup/uni-popup-sku.vue';
|
||||||
// 商品SKU
|
// 商品SKU
|
||||||
export default {
|
export default {
|
||||||
name: 'ns-goods-sku',
|
name: 'ns-goods-sku',
|
||||||
|
components: {
|
||||||
|
uniPopup
|
||||||
|
},
|
||||||
props: {
|
props: {
|
||||||
goodsId: {
|
goodsId: {
|
||||||
type: [Number, String],
|
type: [Number, String],
|
||||||
@@ -266,7 +270,7 @@
|
|||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.isIphoneX = this.$util.uniappIsIPhoneX();
|
this.isIphoneX = this.$util.uniappIsIPhoneX();
|
||||||
this.systemInfo = this.$util.getDeviceInfo();
|
this.systemInfo = uni.getSystemInfoSync();
|
||||||
this.isLoad = true;
|
this.isLoad = true;
|
||||||
if (this.goodsId && this.goodsDetail.goods_spec_format) {
|
if (this.goodsId && this.goodsDetail.goods_spec_format) {
|
||||||
this.skuId = this.goodsDetail.sku_id;
|
this.skuId = this.goodsDetail.sku_id;
|
||||||
@@ -413,7 +417,7 @@
|
|||||||
this.isLoad = false;
|
this.isLoad = false;
|
||||||
if (callback) callback();
|
if (callback) callback();
|
||||||
} else {
|
} else {
|
||||||
this.$util.redirectTo(this.$util.INDEX_PAGE_URL);
|
this.$util.redirectTo('/pages/index/index');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -441,7 +445,7 @@
|
|||||||
this.skuId = res.data[0].sku_id;
|
this.skuId = res.data[0].sku_id;
|
||||||
this.goodsSkuInfo = obj;
|
this.goodsSkuInfo = obj;
|
||||||
} else {
|
} else {
|
||||||
this.$util.redirectTo(this.$util.INDEX_PAGE_URL);
|
this.$util.redirectTo('/pages/index/index');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -467,7 +471,7 @@
|
|||||||
this.skuId = res.data[0].sku_id;
|
this.skuId = res.data[0].sku_id;
|
||||||
this.goodsSkuInfo = obj;
|
this.goodsSkuInfo = obj;
|
||||||
} else {
|
} else {
|
||||||
this.$util.redirectTo(this.$util.INDEX_PAGE_URL);
|
this.$util.redirectTo('/pages/index/index');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -500,7 +504,7 @@
|
|||||||
this.skuId = res.data[0].sku_id;
|
this.skuId = res.data[0].sku_id;
|
||||||
this.goodsSkuInfo = obj;
|
this.goodsSkuInfo = obj;
|
||||||
} else {
|
} else {
|
||||||
this.$util.redirectTo(this.$util.INDEX_PAGE_URL);
|
this.$util.redirectTo('/pages/index/index');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -527,7 +531,7 @@
|
|||||||
this.skuId = res.data[0].sku_id;
|
this.skuId = res.data[0].sku_id;
|
||||||
this.goodsSkuInfo = obj;
|
this.goodsSkuInfo = obj;
|
||||||
} else {
|
} else {
|
||||||
this.$util.redirectTo(this.$util.INDEX_PAGE_URL);
|
this.$util.redirectTo('/pages/index/index');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -553,7 +557,7 @@
|
|||||||
this.skuId = res.data[0].sku_id;
|
this.skuId = res.data[0].sku_id;
|
||||||
this.goodsSkuInfo = obj;
|
this.goodsSkuInfo = obj;
|
||||||
} else {
|
} else {
|
||||||
this.$util.redirectTo(this.$util.INDEX_PAGE_URL);
|
this.$util.redirectTo('/pages/index/index');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -579,7 +583,7 @@
|
|||||||
this.skuId = res.data[0].sku_id;
|
this.skuId = res.data[0].sku_id;
|
||||||
this.goodsSkuInfo = obj;
|
this.goodsSkuInfo = obj;
|
||||||
} else {
|
} else {
|
||||||
this.$util.redirectTo(this.$util.INDEX_PAGE_URL);
|
this.$util.redirectTo('/pages/index/index');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -606,7 +610,7 @@
|
|||||||
this.skuId = res.data[0].sku_id;
|
this.skuId = res.data[0].sku_id;
|
||||||
this.goodsSkuInfo = obj;
|
this.goodsSkuInfo = obj;
|
||||||
} else {
|
} else {
|
||||||
this.$util.redirectTo(this.$util.INDEX_PAGE_URL);
|
this.$util.redirectTo('/pages/index/index');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -630,7 +634,7 @@
|
|||||||
this.skuId = res.data[0].sku_id;
|
this.skuId = res.data[0].sku_id;
|
||||||
this.goodsSkuInfo = obj;
|
this.goodsSkuInfo = obj;
|
||||||
} else {
|
} else {
|
||||||
this.$util.redirectTo(this.$util.INDEX_PAGE_URL);
|
this.$util.redirectTo('/pages/index/index');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.mp-html{
|
.mp-html{
|
||||||
::v-deep img{
|
/deep/ img{
|
||||||
width:100% !important;
|
width:100% !important;
|
||||||
display:block;
|
display:block;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,8 +75,12 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import uniPopup from '../uni-popup/uni-popup.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
components: {
|
||||||
|
uniPopup
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
newgift: {
|
newgift: {
|
||||||
@@ -168,17 +172,17 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
::v-deep .newgift-content uni-image {
|
/deep/ .newgift-content uni-image {
|
||||||
width: 113rpx !important;
|
width: 113rpx !important;
|
||||||
height: 24rpx !important;
|
height: 24rpx !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
::v-deep .reward-popup .uni-popup__wrapper.uni-custom.center .uni-popup__wrapper-box {
|
/deep/ .reward-popup .uni-popup__wrapper.uni-custom.center .uni-popup__wrapper-box {
|
||||||
max-height: unset !important;
|
max-height: unset !important;
|
||||||
overflow-y: unset;
|
overflow-y: unset;
|
||||||
}
|
}
|
||||||
|
|
||||||
.register-box ::v-deep .uni-scroll-view {
|
.register-box /deep/ .uni-scroll-view {
|
||||||
background: unset !important;
|
background: unset !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -278,8 +278,13 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import pickRegions from '@/components/pick-regions/pick-regions.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'ns-form',
|
name: 'ns-form',
|
||||||
|
components: {
|
||||||
|
pickRegions
|
||||||
|
},
|
||||||
props: {
|
props: {
|
||||||
data: {
|
data: {
|
||||||
type: Array,
|
type: Array,
|
||||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user