chore:悬浮按钮可以后台自定义调节
This commit is contained in:
@@ -257,7 +257,7 @@ const localDevConfig = ({
|
||||
// })['2811']; // 本地
|
||||
// })['5g-317']; // 电磁兼容
|
||||
// })['5g-351']; //
|
||||
})['2843']; // 本地
|
||||
})['5g-97']; // 本地
|
||||
// })['local-2']; // 本地
|
||||
// })['local-11']; // 本地
|
||||
// })['1-test']; // test
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<view
|
||||
v-if="isLanguageSwitchEnabled && hasLangButton"
|
||||
class="btn-item common-bg"
|
||||
:style="[btnItemStyle, { order: orderIndex.lang }]"
|
||||
:style="[btnItemStyle, { order: orderIndex.lang }, perBtnStyle.lang]"
|
||||
@click="handleLangButtonClick"
|
||||
>
|
||||
<view class="lang-btn-text">{{ langButtonText }}</view>
|
||||
@@ -22,7 +22,7 @@
|
||||
<button
|
||||
v-if="hasKefuButton && hasValidKefuConfig && isWeappOfficialKefu"
|
||||
class="btn-item common-bg"
|
||||
:style="[btnItemStyle, { order: orderIndex.kefu }]"
|
||||
:style="[btnItemStyle, { order: orderIndex.kefu }, perBtnStyle.kefu]"
|
||||
open-type="contact"
|
||||
>
|
||||
<text class="icox icox-kefu" v-if="!kefuimg"></text>
|
||||
@@ -32,7 +32,7 @@
|
||||
<view
|
||||
v-if="hasKefuButton && hasValidKefuConfig && !isWeappOfficialKefu && !showWeappSystemKefu"
|
||||
class="btn-item common-bg"
|
||||
:style="[btnItemStyle, { order: orderIndex.kefu }]"
|
||||
:style="[btnItemStyle, { order: orderIndex.kefu }, perBtnStyle.kefu]"
|
||||
@click="handleUnifiedKefuClick"
|
||||
>
|
||||
<image
|
||||
@@ -50,7 +50,7 @@
|
||||
<view
|
||||
v-if="hasKefuButton && hasValidKefuConfig && !isWeappOfficialKefu && showWeappSystemKefu"
|
||||
class="btn-item common-bg"
|
||||
:style="[btnItemStyle, { order: orderIndex.kefu }]"
|
||||
:style="[btnItemStyle, { order: orderIndex.kefu }, perBtnStyle.kefu]"
|
||||
@click="handleUnifiedKefuClick"
|
||||
>
|
||||
<image
|
||||
@@ -68,7 +68,7 @@
|
||||
<button
|
||||
v-if="hasKefuButton && hasValidKefuConfig && showWeappSystemKefu"
|
||||
class="btn-item common-bg"
|
||||
:style="[btnItemStyle, { order: orderIndex.kefu }]"
|
||||
:style="[btnItemStyle, { order: orderIndex.kefu }, perBtnStyle.kefu]"
|
||||
open-type="contact"
|
||||
>
|
||||
<text class="icox icox-kefu" v-if="!kefuimg"></text>
|
||||
@@ -78,7 +78,7 @@
|
||||
<view
|
||||
v-if="hasPhoneButton"
|
||||
class="btn-item common-bg"
|
||||
:style="[btnItemStyle, { order: orderIndex.phone }, { backgroundImage: phoneimg ? `url(${phoneimg})` : '', backgroundSize: '100% 100%' }, customButtonStyle]"
|
||||
:style="[btnItemStyle, { order: orderIndex.phone }, { backgroundImage: phoneimg ? `url(${phoneimg})` : '', backgroundSize: '100% 100%' }, customButtonStyle, perBtnStyle.phone]"
|
||||
@click="call"
|
||||
>
|
||||
<text class="iconfont icon-dianhua" v-if="!phoneimg"></text>
|
||||
@@ -175,6 +175,10 @@ export default {
|
||||
return {
|
||||
pageCount: 0,
|
||||
currentRoute: '', // 当前页面路由(onShow / created 时刷新, 供页面范围判定)
|
||||
// 每个按钮的专属样式(来源: 主题 token hover_nav_{key}_bg_color/_text_color/_size,
|
||||
// 由 _parsePerButtonStyle 从 themeColor 的 CSS 变量串解析, 全平台可用)
|
||||
// key: lang/kefu/phone, value: { backgroundColor?, color?, width?... } , 空 = 走全局 token
|
||||
perBtnStyle: { lang: {}, kefu: {}, phone: {} },
|
||||
shopInfo: null,
|
||||
currentLangIndex: 0,
|
||||
langIndexMap: {},
|
||||
@@ -365,11 +369,24 @@ export default {
|
||||
const b = this.visibleButtons;
|
||||
if (b && b.length === 0) return '0rpx';
|
||||
|
||||
const extraKefuSlot = (this.hasKefuButton && this.showWeappSystemKefu) ? 1 : 0;
|
||||
const buttonCount = b
|
||||
? b.length + extraKefuSlot
|
||||
: 1 + (this.isLanguageSwitchEnabled ? 1 : 0) + extraKefuSlot;
|
||||
const totalRpx = buttonCount * 100 + 40;
|
||||
// 汇总实际渲染的按钮列表 (b 存在 = 新配置; null = 老行为兜底, 与旧计数等价)
|
||||
const rendered = [];
|
||||
if (b) {
|
||||
for (let i = 0; i < b.length; i++) rendered.push(b[i]);
|
||||
} else {
|
||||
if (this.isLanguageSwitchEnabled) rendered.push('lang');
|
||||
rendered.push('kefu');
|
||||
if (this.showWeappSystemKefu) rendered.push('kefu');
|
||||
rendered.push('phone');
|
||||
}
|
||||
|
||||
// 槽位高度按每个按钮的实际尺寸算(72rpx 默认 + 28rpx 上下 margin),
|
||||
// token 单独调大某个按钮时容器高度自动跟随, 不出现裁切/空白
|
||||
let slotsRpx = 0;
|
||||
for (let i = 0; i < rendered.length; i++) {
|
||||
slotsRpx += this.btnSizeRpx(rendered[i]) + 28;
|
||||
}
|
||||
const totalRpx = slotsRpx + 40;
|
||||
|
||||
return `${totalRpx}rpx`;
|
||||
},
|
||||
@@ -624,6 +641,9 @@ export default {
|
||||
* 内部会去重,不会频繁触发)。
|
||||
*/
|
||||
_applyThemeColor(tc) {
|
||||
// 0) 解析每个按钮的专属 token (颜色/尺寸) — 必须放在 $el 早退之前,
|
||||
// 小程序端 $el 可能不可用, 但 inline-style 解析不依赖 DOM, 全平台都要执行
|
||||
this._parsePerButtonStyle(tc);
|
||||
if (!this.$el || !this.$el.style) return;
|
||||
// 1) 剥离旧注入(避免重复 + 处理主题切换场景)
|
||||
if (this._appliedThemeColor) {
|
||||
@@ -640,6 +660,63 @@ export default {
|
||||
this.$el.style.cssText = (this.$el.style.cssText || '') + ';' + tc;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 从 themeColor 的 CSS 变量串(--xxx:value;...)中解析每个悬浮按钮的专属 token:
|
||||
* --hover-nav-{key}-bg-color → backgroundColor
|
||||
* --hover-nav-{key}-text-color → color
|
||||
* --hover-nav-{key}-size → width/height/min-max 等尺寸属性
|
||||
* key ∈ lang / kefu / phone; token 未配置(或空值被 sanitize 剔除)时对应样式为空,
|
||||
* CSS/inline 回退到全局 hover_nav_bg_color / hover_nav_text_color / 72rpx。
|
||||
*/
|
||||
_parsePerButtonStyle(tc) {
|
||||
const result = { lang: {}, kefu: {}, phone: {} };
|
||||
if (tc && typeof tc === 'string') {
|
||||
const pick = (name) => {
|
||||
const m = tc.match(new RegExp('--hover-nav-' + name + '\\s*:\\s*([^;]+);'));
|
||||
return m ? m[1].trim() : '';
|
||||
};
|
||||
for (const key of ['lang', 'kefu', 'phone']) {
|
||||
const s = {};
|
||||
const bg = pick(key + '-bg-color');
|
||||
const text = pick(key + '-text-color');
|
||||
const size = pick(key + '-size');
|
||||
if (bg) s.backgroundColor = bg;
|
||||
if (text) s.color = text;
|
||||
if (size) {
|
||||
s.width = size;
|
||||
s.height = size;
|
||||
s['min-width'] = size;
|
||||
s['min-height'] = size;
|
||||
s['max-width'] = size;
|
||||
s['max-height'] = size;
|
||||
}
|
||||
result[key] = s;
|
||||
}
|
||||
}
|
||||
this.perBtnStyle = result;
|
||||
},
|
||||
|
||||
/**
|
||||
* 取某个按钮当前的尺寸数值(rpx 基准, 供容器高度计算)。
|
||||
* token 值可能是 rpx(小程序/H5 主题串原样)或 px(H5 端 themeColorSet 已把 rpx 换算成 px),
|
||||
* px 时按 windowWidth 折算回 rpx; 无 token 时回退默认 72rpx。
|
||||
*/
|
||||
btnSizeRpx(key) {
|
||||
const s = this.perBtnStyle && this.perBtnStyle[key];
|
||||
const v = s && s.width;
|
||||
if (!v) return 72;
|
||||
const m = String(v).match(/^([\d.]+)\s*(rpx|px)?$/i);
|
||||
if (!m) return 72;
|
||||
let n = parseFloat(m[1]);
|
||||
if ((m[2] || 'rpx').toLowerCase() === 'px') {
|
||||
try {
|
||||
const w = (uni.getSystemInfoSync() || {}).windowWidth;
|
||||
if (w) n = n * 750 / w;
|
||||
} catch (e) { /* 保持原值 */ }
|
||||
}
|
||||
return n;
|
||||
},
|
||||
initLanguage() {
|
||||
// 数据源优先级:
|
||||
// 1) shopInfo.langList(后端按租户/店铺动态下发的语言配置,推荐)
|
||||
|
||||
Reference in New Issue
Block a user