feat: 新增多语言国际化页面配置,修复部分页面硬编码文案
1. 新增了zh-cn和en-us两套语言下的大量页面国际化配置文件,覆盖商品、订单、会员、营销活动等多个业务模块 2. 修复了分销页面、VR页面、支付页面、商品不存在页面的硬编码提示文案,替换为国际化调用 3. 删除了原有的i18n检查脚本文件
This commit is contained in:
@@ -74,6 +74,10 @@ const localDevConfig = ({
|
||||
uniacid: 11,
|
||||
domain: 'https://5g.aigc-quickapp.com/',
|
||||
},
|
||||
'5g-206': {
|
||||
uniacid: 206,
|
||||
domain: 'https://5g.aigc-quickapp.com/',
|
||||
},
|
||||
'47': { // 修改弹窗
|
||||
uniacid: 47,
|
||||
domain: 'https://5g.aigc-quickapp.com/',
|
||||
|
||||
@@ -182,91 +182,20 @@ function processRoutePath(route) {
|
||||
}
|
||||
|
||||
// 加载语言包(同步方式)
|
||||
// 2026-06-24 升级为多文件结构:lang/<locale>/index.js 聚合各业务模块
|
||||
// 同时保留旧单文件 lang/<locale>.js 作为过渡,新结构优先,旧结构兜底
|
||||
// path 参数保留仅为兼容旧调用签名(忽略值)。
|
||||
function loadLangPackSync(lang, path) {
|
||||
try {
|
||||
const cacheKey = `${lang}__single`;
|
||||
if (loadedLangPacks[cacheKey]) {
|
||||
return loadedLangPacks[cacheKey];
|
||||
if (loadedLangPacks[`${lang}_${path}`]) {
|
||||
return loadedLangPacks[`${lang}_${path}`];
|
||||
}
|
||||
// 1. 先加载旧单文件(兜底)
|
||||
let legacyData = {};
|
||||
try {
|
||||
legacyData = require(`@/lang/${lang}.js`).lang || {};
|
||||
} catch (e) {
|
||||
// 旧文件不存在也没关系
|
||||
}
|
||||
// 2. 再加载新多文件聚合(优先)
|
||||
let modularData = {};
|
||||
try {
|
||||
modularData = require(`@/lang/${lang}/index.js`).lang || {};
|
||||
} catch (e) {
|
||||
// 新文件不存在也没关系
|
||||
}
|
||||
// 3. 深度合并:新结构覆盖旧结构
|
||||
const langData = deepMergeLang(legacyData, modularData);
|
||||
loadedLangPacks[cacheKey] = langData;
|
||||
const langData = require(`@/lang/${lang}/${path}.js`).lang;
|
||||
loadedLangPacks[`${lang}_${path}`] = langData;
|
||||
return langData;
|
||||
} catch (error) {
|
||||
// console.error(`加载语言包 ${lang} 失败:`, error);
|
||||
// console.error(`加载语言包 ${lang}/${path} 失败:`, error);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
// 深度合并语言包对象,新值覆盖旧值
|
||||
function deepMergeLang(target, source) {
|
||||
const result = { ...target };
|
||||
for (const key of Object.keys(source)) {
|
||||
const srcVal = source[key];
|
||||
const tgtVal = result[key];
|
||||
if (srcVal && typeof srcVal === 'object' && !Array.isArray(srcVal)
|
||||
&& tgtVal && typeof tgtVal === 'object' && !Array.isArray(tgtVal)) {
|
||||
result[key] = deepMergeLang(tgtVal, srcVal);
|
||||
} else {
|
||||
result[key] = srcVal;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// 检测 page module 是否覆盖 common 已有 key。
|
||||
// 自 2026-06-23 起强制:page 覆盖 common 直接 throw 阻断,防止 AI 默默改文案。
|
||||
// 历史上 commit f258987 / 47098bd 都曾让 page 覆盖 common 引发翻译错乱。
|
||||
function detectShadowing(commonLang, pageLang, langPath) {
|
||||
if (!pageLang || typeof pageLang !== 'object') return;
|
||||
if (!commonLang || typeof commonLang !== 'object') return;
|
||||
const conflicts = [];
|
||||
const walk = (pageNode, commonNode, prefix) => {
|
||||
if (!pageNode || typeof pageNode !== 'object') return;
|
||||
if (!commonNode || typeof commonNode !== 'object') return;
|
||||
for (const k of Object.keys(pageNode)) {
|
||||
const fullKey = prefix ? `${prefix}.${k}` : k;
|
||||
if (Object.prototype.hasOwnProperty.call(commonNode, k)) {
|
||||
const pageVal = pageNode[k];
|
||||
const commonVal = commonNode[k];
|
||||
// 仅当 page 想覆盖 common 的"叶子"值(字符串)时报错
|
||||
if (typeof pageVal === 'string' && typeof commonVal === 'string' && pageVal !== commonVal) {
|
||||
conflicts.push({ key: fullKey, commonVal, pageVal });
|
||||
} else if (typeof pageVal === 'object' && pageVal !== null && typeof commonVal === 'object' && commonVal !== null) {
|
||||
// 嵌套结构继续递归
|
||||
walk(pageVal, commonVal, fullKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
walk(pageLang, commonLang, '');
|
||||
if (conflicts.length > 0) {
|
||||
const list = conflicts.map(c => ` - "${c.key}": common="${c.commonVal}" vs page="${c.pageVal}"`).join('\n');
|
||||
throw new Error(
|
||||
`[i18n] page module "${langPath || 'unknown'}" overrides common.js keys:\n${list}\n` +
|
||||
`Fix: rename the page key with a business namespace prefix, e.g. "<namespace>.${conflicts[0].key.split('.').pop()}"\n` +
|
||||
`See docs/i18n-rules.md for the rule.`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获得当前本地语言
|
||||
* @returns
|
||||
@@ -634,20 +563,12 @@ export default {
|
||||
let mergedLang = _mergedLangCache[mergeCacheKey];
|
||||
if (!mergedLang) {
|
||||
try {
|
||||
// 自 2026-06-23 起:只加载单一权威 lang/<locale>.js
|
||||
// page module 已废弃,因此不再读取 lang/<locale>/<page>.js
|
||||
const lang = loadLangPackSync(locale, langPath);
|
||||
const currentPageLang = {}; // 兼容旧调用;旧 page module 已废弃
|
||||
// detectShadowing 在 page 部分为空时直接返回,不抛错
|
||||
detectShadowing(lang, currentPageLang, langPath);
|
||||
const lang = loadLangPackSync(locale, 'common');
|
||||
const currentPageLang = langPath ? loadLangPackSync(locale, langPath) : {};
|
||||
mergedLang = Object.assign(deepCloneLang(lang), deepCloneLang(currentPageLang));
|
||||
const ovr = overrideCache[getOverrideMemKey(locale)];
|
||||
if (ovr && ovr.map) applyOverrides(mergedLang, ovr.map);
|
||||
} catch (e) {
|
||||
// detectShadowing 抛错时不应该被静默吞掉——直接重抛
|
||||
if (e && e.message && e.message.startsWith('[i18n]')) {
|
||||
throw e;
|
||||
}
|
||||
console.error('解析语言包失败:', e, { langPath, field, locale });
|
||||
mergedLang = {};
|
||||
}
|
||||
@@ -759,15 +680,7 @@ export default {
|
||||
_refreshInProgress = true;
|
||||
try {
|
||||
let _page = getCurrentPages()[getCurrentPages().length - 1];
|
||||
if (_page) {
|
||||
// 自 2026-06-23 起:每个 page 的 title 集中到 pageTitles.<route> 命名空间
|
||||
// processRoutePath() 已经把 route 映射成 langPath(如 'order/list')
|
||||
const _langPath = processRoutePath(_page.route || (_page.$page && _page.$page.path) || '');
|
||||
const _titleKey = _langPath ? `pageTitles.${_langPath.replace(/\//g, '.')}` : 'pageTitles';
|
||||
const _title = this.lang(_titleKey);
|
||||
// 兜底:旧 page module 仍可能在 lang 包外自定义 title,没匹配时用通用 title
|
||||
this.title(_title && _title !== _titleKey ? _title : this.lang('title'));
|
||||
}
|
||||
if (_page) this.title(this.lang("title"));
|
||||
|
||||
if (emit) {
|
||||
// 远端 i18n 翻译更新后,推送重渲染信号;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -12,7 +12,7 @@
|
||||
</view>
|
||||
<image v-else class="left-img" :src="$util.img(value.titleStyle.leftImg)" mode="heightFix" show-menu-by-longpress></image>
|
||||
<view class="head-content" v-if="value.titleStyle.style == 'style-1'"
|
||||
:style="{ color: value.titleStyle.textColor }">{{ $lang("diy.diy-bargain.l15.t0") }}</view>
|
||||
:style="{ color: value.titleStyle.textColor }">低至0元免费拿</view>
|
||||
<view class="head-right"
|
||||
:style="{ fontSize: value.titleStyle.moreFontSize * 2 + 'rpx', color: value.titleStyle.moreColor }"
|
||||
@tap.stop="$util.redirectTo('/pages_promotion/bargain/list')">
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
:class="{ 'screen-category-4': value.template == 4 }" :scroll-with-animation="true"
|
||||
:scroll-into-view="scrollIntoView">
|
||||
<view class="item" id="category-2--1" :class="{ selected: categoryId == -1 }"
|
||||
@tap.stop="selectCategory(-1)">{{ $lang("diy.diy-category-item.l47.t0") }}</view>
|
||||
@tap.stop="selectCategory(-1)">全部</view>
|
||||
<view class="item" :id="'category-2-' + oneIndex"
|
||||
:class="{ selected: categoryId == oneIndex }" @tap.stop="selectCategory(oneIndex)"
|
||||
v-for="(one, oneIndex) in category.child_list" :key="oneIndex">
|
||||
@@ -57,7 +57,7 @@
|
||||
<view class="screen-category-popup" @tap.stop="$refs.screenCategoryPopup.close()">
|
||||
<scroll-view scroll-y="true" class="screen-category"
|
||||
:class="{ 'screen-category-4': value.template == 4 }">
|
||||
<view class="title">{{ $lang("diy.diy-category-item.l47.t0") }}</view>
|
||||
<view class="title">全部</view>
|
||||
<view class="item" :class="{ selected: categoryId == oneIndex }"
|
||||
@tap.stop="selectCategory(oneIndex)" v-for="(one, oneIndex) in category.child_list"
|
||||
:key="oneIndex">
|
||||
@@ -125,11 +125,11 @@
|
||||
|
||||
<!-- <view class="right-wrap" v-if="value.template == 2 || value.template == 4">
|
||||
<block v-if="item.is_virtual">
|
||||
<view class="color-base-bg select-sku" @tap.stop="toDetail(item)">{{ $lang("common.ns-goods-sku.l195.t0") }}</view>
|
||||
<view class="color-base-bg select-sku" @tap.stop="toDetail(item)">立即购买</view>
|
||||
</block>
|
||||
<block v-else>
|
||||
<view v-if="item.goods_spec_format" class="color-base-bg select-sku" @tap.stop="selectSku(item)">
|
||||
<text>{{ $lang("diy.diy-category-item.l132.t0") }}</text>
|
||||
<text>选规格</text>
|
||||
<text class="num-tag" v-if="item.num">{{ item.num }}</text>
|
||||
</view>
|
||||
<block v-else>
|
||||
@@ -151,7 +151,7 @@
|
||||
</block>
|
||||
</view> -->
|
||||
<!-- <view class="right-wrap" v-if="value.template == 3">
|
||||
<view class="color-base-bg select-sku" @tap.stop="toDetail(item)">{{ $lang("common.ns-goods-sku.l195.t0") }}</view>
|
||||
<view class="color-base-bg select-sku" @tap.stop="toDetail(item)">立即购买</view>
|
||||
</view> -->
|
||||
</view>
|
||||
</view>
|
||||
@@ -160,7 +160,7 @@
|
||||
<view class="category-empty" v-else>
|
||||
<image :src="$util.img('public/uniapp/category/empty.png')" mode="widthFix" show-menu-by-longpress />
|
||||
</view>
|
||||
<!-- <view class="end-tips" ref="endTips" v-if="last && (categoryId == -1 || !category.child_list || (category.child_list && categoryId == category.child_list.length - 1))">{{ $lang("diy.diy-category-item.l163.t0") }}</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')">
|
||||
<text class="iconfont icon-xiangshangzhanhang"></text>
|
||||
上滑查看下一分类
|
||||
@@ -219,12 +219,12 @@
|
||||
|
||||
<view class="right-wrap" v-if="value.template == 2">
|
||||
<block v-if="item.is_virtual">
|
||||
<view class="color-base-bg select-sku" @tap.stop="toDetail(item)">{{ $lang("common.ns-goods-sku.l195.t0") }}</view>
|
||||
<view class="color-base-bg select-sku" @tap.stop="toDetail(item)">立即购买</view>
|
||||
</block>
|
||||
<block v-else>
|
||||
<view v-if="item.goods_spec_format" class="color-base-bg select-sku"
|
||||
@tap.stop="selectSku(item)">
|
||||
<text>{{ $lang("diy.diy-category-item.l132.t0") }}</text>
|
||||
<text>选规格</text>
|
||||
<text class="num-tag" v-if="item.num">{{ item.num }}</text>
|
||||
</view>
|
||||
<block v-else>
|
||||
@@ -250,7 +250,7 @@
|
||||
</block>
|
||||
</view>
|
||||
<view class="right-wrap" v-if="value.template == 3">
|
||||
<view class="color-base-bg select-sku" @tap.stop="toDetail(item)">{{ $lang("common.ns-goods-sku.l195.t0") }}</view>
|
||||
<view class="color-base-bg select-sku" @tap.stop="toDetail(item)">立即购买</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -517,7 +517,7 @@ export default {
|
||||
|
||||
if (_num > parseInt(data.stock)) {
|
||||
this.$util.showToast({
|
||||
title: $lang('common.ns-goods-sku.ns-goods-sku-index.l70.t0')
|
||||
title: '商品库存不足'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -5,18 +5,18 @@
|
||||
<!-- <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-content">
|
||||
<input type="text" class="uni-input font-size-tag" maxlength="50" :placeholder="$lang('common.button.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" @tap.stop="onClickSearch()" disabled="true" />
|
||||
<text class="iconfont icon-sousuo3"></text>
|
||||
</view>
|
||||
</view>
|
||||
<view :style="navbarInnerStyle" v-if="!value.search">{{ $lang("diy.diy-category.l12.t0") }}</view>
|
||||
<view :style="navbarInnerStyle" v-if="!value.search">商品分类</view>
|
||||
</block> -->
|
||||
<block v-if="value.template != 4">
|
||||
<!-- <view :style="navbarInnerStyle">{{ $lang("diy.diy-category.l12.t0") }}</view> -->
|
||||
<!-- <view :style="navbarInnerStyle">商品分类</view> -->
|
||||
<view class="search-box" v-if="value.search" @tap.stop="onClickSearch()"
|
||||
:style="wxSearchHeight">
|
||||
<view class="search-content">
|
||||
<input type="text" class="uni-input" maxlength="50" :placeholder="$lang('common.button.search')"
|
||||
<input type="text" class="uni-input" maxlength="50" :placeholder="$lang('search')"
|
||||
confirm-type="search" @tap.stop="onClickSearch()"
|
||||
disabled="true" />
|
||||
<text class="iconfont icon-sousuo3"></text>
|
||||
@@ -29,7 +29,7 @@
|
||||
<!-- #ifdef H5 -->
|
||||
<view class="search-box" v-if="value.search" @tap.stop="onClickSearch()">
|
||||
<view class="search-content">
|
||||
<input type="text" class="uni-input" maxlength="50" :placeholder="$lang('common.button.search')" confirm-type="search"
|
||||
<input type="text" class="uni-input" maxlength="50" :placeholder="$lang('search')" confirm-type="search"
|
||||
@tap.stop="onClickSearch()" disabled="true" />
|
||||
<text class="iconfont icon-sousuo3"></text>
|
||||
</view>
|
||||
@@ -51,7 +51,7 @@
|
||||
</scroll-view>
|
||||
<view class="category-item-all" @tap.stop="$refs.templateFourPopup.open()">
|
||||
<view class="category-item-all-wrap">
|
||||
<text class="text">{{ $lang("diy.diy-category.l54.t0") }}</text>
|
||||
<text class="text">展开</text>
|
||||
<image class="img" :src="$util.img('/public/uniapp/category/unfold.png')" mode="aspectFill" show-menu-by-longpress></image>
|
||||
</view>
|
||||
</view>
|
||||
@@ -68,7 +68,7 @@
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view class="pack-up" @tap.stop="$refs.templateFourPopup.close()">
|
||||
<text>{{ $lang("diy.diy-category.l71.t0") }}</text>
|
||||
<text>点击收起</text>
|
||||
<text class="iconfont icon-iconangledown-copy"></text>
|
||||
</view>
|
||||
</view>
|
||||
@@ -102,7 +102,7 @@
|
||||
@tologin="toLogin" @selectsku="selectSku($event, index)" @addCart="addCartPoint"
|
||||
@loadfinish="getHeightArea"></diy-category-item>
|
||||
</view>
|
||||
<view class="end-tips" ref="endTips" :style="{ opacity: endTips }">{{ $lang("diy.diy-category-item.l163.t0") }}</view>
|
||||
<view class="end-tips" ref="endTips" :style="{ opacity: endTips }">已经到底了~</view>
|
||||
</scroll-view>
|
||||
|
||||
<view class="content-wrap"
|
||||
@@ -120,12 +120,12 @@
|
||||
</block>
|
||||
<view class="category-empty" v-else>
|
||||
<image :src="$util.img('public/uniapp/category/empty.png')" mode="widthFix" show-menu-by-longpress></image>
|
||||
<view class="tips">{{ $lang("diy.diy-category.l123.t0") }}</view>
|
||||
<view class="tips">暂时没有分类哦!</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="category-empty" v-else>
|
||||
<image :src="$util.img('public/uniapp/category/empty.png')" mode="widthFix" show-menu-by-longpress></image>
|
||||
<view class="tips">{{ $lang("diy.diy-category.l123.t0") }}</view>
|
||||
<view class="tips">暂时没有分类哦!</view>
|
||||
</view>
|
||||
|
||||
<!-- <view class="cart-box" v-if="(value.template == 2 || value.template == 4) && value.quickBuy && storeToken && categoryTree && categoryTree.length">
|
||||
@@ -135,13 +135,13 @@
|
||||
<view class="num" v-if="cartNumber">{{ cartNumber < 99 ? cartNumber : '99+' }}</view>
|
||||
</view>
|
||||
<view class="price">
|
||||
<text class="title">{{ $lang("diy.diy-category.l138.t0") }}</text>
|
||||
<text class="title">总计:</text>
|
||||
<text class="unit font-size-tag price-font">¥</text>
|
||||
<text class="money font-size-toolbar price-font">{{ cartTotalMoney[0] }}</text>
|
||||
<text class="unit font-size-tag price-font">.{{ cartTotalMoney[1] ? cartTotalMoney[1] : '00' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="right-wrap"><button type="primary" class="settlement-btn" @tap.stop="settlement">{{ $lang("diy.diy-category.l144.t0") }}</button>
|
||||
<view class="right-wrap"><button type="primary" class="settlement-btn" @tap.stop="settlement">去结算</button>
|
||||
</view>
|
||||
</view> -->
|
||||
|
||||
@@ -409,7 +409,7 @@ export default {
|
||||
success: res => {
|
||||
if (res.code >= 0) {
|
||||
let item = res.data;
|
||||
item.unit = item.unit || $lang('common.ns-goods-sku.ns-goods-sku-index.l150.t0');
|
||||
item.unit = item.unit || '件';
|
||||
|
||||
if (item.sku_images) item.sku_images = item.sku_images.split(',');
|
||||
else item.sku_images = [];
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -26,16 +26,16 @@
|
||||
</view>
|
||||
<view class="coupon-num" :style="{ color: value.moneyColor }" v-else>
|
||||
<text class="coupon-size">{{ item.discount | moneyConduct }}</text>
|
||||
<text class="font-size-tag coupon-sign">{{ $lang("common.register-reward.l60.t1") }}</text>
|
||||
<text class="font-size-tag coupon-sign">折</text>
|
||||
</view>
|
||||
<view class="coupon-type font-size-tag" :style="{ color: value.limitColor }">
|
||||
{{ item.at_least > 0 ? $lang('diy.diy-coupon.l32.t0') + Number(item.at_least) + '元可用' : $lang('diy.diy-coupon.l32.t2') }}
|
||||
{{ item.at_least > 0 ? '满' + Number(item.at_least) + '元可用' : '无门槛优惠券' }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="coupon-get" :style="couponBtnStyle" v-if="item.useState == 0">
|
||||
{{ value.btnStyle.text }}
|
||||
</view>
|
||||
<view class="coupon-get" :style="couponBtnStyle" v-if="parseInt(item.useState)">{{ $lang("diy.diy-coupon.l38.t0") }}</view>
|
||||
<view class="coupon-get" :style="couponBtnStyle" v-if="parseInt(item.useState)">去使用</view>
|
||||
</view>
|
||||
|
||||
</swiper-item>
|
||||
@@ -61,14 +61,14 @@
|
||||
</view>
|
||||
<view class="coupon-num" :style="{ color: value.moneyColor }" v-else>
|
||||
<text class="coupon-size">{{ item.discount | moneyConduct }}</text>
|
||||
<text class="font-size-tag coupon-sign">{{ $lang("common.register-reward.l60.t1") }}</text>
|
||||
<text class="font-size-tag coupon-sign">折</text>
|
||||
</view>
|
||||
<view class="coupon-type font-size-tag" :style="{ color: value.limitColor }">
|
||||
{{ item.at_least > 0 ? $lang('diy.diy-coupon.l32.t0') + Number(item.at_least) + '元可用' : $lang('diy.diy-coupon.l32.t2') }}
|
||||
{{ item.at_least > 0 ? '满' + Number(item.at_least) + '元可用' : '无门槛优惠券' }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="coupon-get" :style="couponBtnStyle" v-if="item.useState == 0">
|
||||
{{ value.btnStyle.text || $lang('diy.diy-coupon.l71.t0') }}
|
||||
{{ value.btnStyle.text || '领取' }}
|
||||
</view>
|
||||
<view class="coupon-get use" :style="couponBtnStyle" v-if="parseInt(item.useState)">去使用
|
||||
</view>
|
||||
@@ -95,20 +95,20 @@
|
||||
</view>
|
||||
<view class="coupon-num" :style="{ color: value.moneyColor }" v-else>
|
||||
<text class="coupon-size">{{ item.discount | moneyConduct }}</text>
|
||||
<text class="font-size-tag coupon-sign">{{ $lang("common.register-reward.l60.t1") }}</text>
|
||||
<text class="font-size-tag coupon-sign">折</text>
|
||||
</view>
|
||||
<view class="coupon-type font-size-tag">
|
||||
<text :style="{ color: value.limitColor }">{{ item.at_least > 0 ? $lang('diy.diy-coupon.l32.t0') +
|
||||
Number(item.at_least) + '元可用' : $lang('diy.diy-coupon.l32.t2') }}</text>
|
||||
<view class="item-text" v-if="item.goods_type == 1">{{ $lang("diy.diy-coupon.l103.t0") }}</view>
|
||||
<view class="item-text" v-else-if="item.goods_type == 2">{{ $lang("diy.diy-coupon.l104.t0") }}</view>
|
||||
<view class="item-text" v-else-if="item.goods_type == 3">{{ $lang("diy.diy-coupon.l105.t0") }}</view>
|
||||
<text :style="{ color: value.limitColor }">{{ item.at_least > 0 ? '满' +
|
||||
Number(item.at_least) + '元可用' : '无门槛优惠券' }}</text>
|
||||
<view class="item-text" v-if="item.goods_type == 1">所有商品可用</view>
|
||||
<view class="item-text" v-else-if="item.goods_type == 2">指定商品可用</view>
|
||||
<view class="item-text" v-else-if="item.goods_type == 3">指定商品不可用</view>
|
||||
</view>
|
||||
|
||||
<view class="coupon-get" :style="couponBtnStyle" v-if="item.useState == 0">
|
||||
{{ value.btnStyle.text || $lang('diy.diy-coupon.l71.t0') }}
|
||||
{{ value.btnStyle.text || '领取' }}
|
||||
</view>
|
||||
<view class="coupon-get" :style="couponBtnStyle" v-if="parseInt(item.useState)">{{ $lang("diy.diy-coupon.l38.t0") }}</view>
|
||||
<view class="coupon-get" :style="couponBtnStyle" v-if="parseInt(item.useState)">去使用</view>
|
||||
</view>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
@@ -133,16 +133,16 @@
|
||||
</view>
|
||||
<view class="coupon-num" :style="{ color: value.moneyColor }" v-else>
|
||||
<text class="coupon-size">{{ item.discount | moneyConduct }}</text>
|
||||
<text class="font-size-tag coupon-sign">{{ $lang("common.register-reward.l60.t1") }}</text>
|
||||
<text class="font-size-tag coupon-sign">折</text>
|
||||
</view>
|
||||
<view class="coupon-type font-size-tag" :style="{ color: value.limitColor }">
|
||||
{{ item.at_least > 0 ? $lang('diy.diy-coupon.l32.t0') + Number(item.at_least) + '元可用' : $lang('diy.diy-coupon.l32.t2') }}
|
||||
{{ item.at_least > 0 ? '满' + Number(item.at_least) + '元可用' : '无门槛优惠券' }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="coupon-get" :style="couponBtnStyle" v-if="item.useState == 0">
|
||||
{{ value.btnStyle.text || $lang('diy.diy-coupon.l143.t0') }}
|
||||
{{ value.btnStyle.text || '立即使用' }}
|
||||
</view>
|
||||
<view class="coupon-get" :style="couponBtnStyle" v-if="parseInt(item.useState)">{{ $lang("diy.diy-coupon.l38.t0") }}</view>
|
||||
<view class="coupon-get" :style="couponBtnStyle" v-if="parseInt(item.useState)">去使用</view>
|
||||
</view>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
@@ -160,11 +160,11 @@
|
||||
<view class="coupon-num" v-if="item.discount == '0.00'"
|
||||
:style="{ color: value.moneyColor }">
|
||||
<text class="coupon-size">{{ item.money | moneyConduct }}</text>
|
||||
<text class="font-size-tag coupon-sign">{{ $lang("common.register-reward.l45.t0") }}</text>
|
||||
<text class="font-size-tag coupon-sign">元</text>
|
||||
</view>
|
||||
<view class="coupon-num" v-else :style="{ color: value.moneyColor }">
|
||||
<text class="coupon-size">{{ item.discount | moneyConduct }}</text>
|
||||
<text class="font-size-tag coupon-sign">{{ $lang("common.register-reward.l60.t1") }}</text>
|
||||
<text class="font-size-tag coupon-sign">折</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="coupon-line"></view>
|
||||
@@ -173,12 +173,12 @@
|
||||
<view class="coupon-name" :style="{ color: value.nameColor }">{{
|
||||
item.coupon_name }}</view>
|
||||
<text class="coupon-least" :style="{ color: value.limitColor }"
|
||||
v-if="item.at_least > 0">{ $lang("diy.diy-coupon.l32.t0") } Number(item.at_least) }}元可用</text>
|
||||
v-if="item.at_least > 0">满{{ Number(item.at_least) }}元可用</text>
|
||||
<text class="coupon-least" :style="{ color: value.limitColor }"
|
||||
v-else>{{ $lang("diy.diy-coupon.l32.t2") }}</text>
|
||||
v-else>无门槛优惠券</text>
|
||||
</view>
|
||||
<view class="coupon-get" :style="couponBtnStyle" v-if="item.useState == 0">{{
|
||||
value.btnStyle.text || $lang('diy.diy-coupon.l181.t0') }}</view>
|
||||
value.btnStyle.text || '立即领取' }}</view>
|
||||
<view class="coupon-get" :style="couponBtnStyle" v-if="parseInt(item.useState)">
|
||||
去使用</view>
|
||||
</view>
|
||||
@@ -204,9 +204,9 @@
|
||||
<view class="price-wrap">
|
||||
<text class="price" :style="{ color: value.moneyColor }">{{ (item.discount == '0.00'
|
||||
? item.money : item.discount) | moneyConduct }}</text>
|
||||
<text class="unit">{{ item.discount == '0.00' ? '元' : $lang('common.register-reward.l60.t1') }}</text>
|
||||
<text class="unit">{{ item.discount == '0.00' ? '元' : '折' }}</text>
|
||||
</view>
|
||||
<text class="text">{{ $lang("diy.diy-coupon.l209.t0") }}</text>
|
||||
<text class="text">优惠券</text>
|
||||
</view>
|
||||
<text class="btn" v-if="item.useState == 0" :style="{
|
||||
color: value.btnStyle.textColor,
|
||||
@@ -222,11 +222,11 @@
|
||||
borderTopLeftRadius: value.btnStyle.aroundRadius * 2 + 'rpx',
|
||||
borderBottomLeftRadius: value.btnStyle.aroundRadius * 2 + 'rpx'
|
||||
}">
|
||||
<text class="btn-content">{{ $lang("diy.diy-coupon.l38.t0") }}</text>
|
||||
<text class="btn-content">去使用</text>
|
||||
</text>
|
||||
<text class="limit" :style="{ color: value.limitColor }"
|
||||
v-if="parseFloat(item.at_least) > 0">{ $lang("diy.diy-coupon.l32.t0") } item.at_least | moneyConduct }}元使用</text>
|
||||
<text class="limit" :style="{ color: value.limitColor }" v-else>{{ $lang("diy.diy-coupon.l229.t0") }}</text>
|
||||
v-if="parseFloat(item.at_least) > 0">满{{ item.at_least | moneyConduct }}元使用</text>
|
||||
<text class="limit" :style="{ color: value.limitColor }" v-else>无门槛使用</text>
|
||||
</view>
|
||||
|
||||
<div v-if="computedCouponList.length <= 2" @tap.stop="$util.redirectTo('/pages_goods/category')"
|
||||
@@ -238,9 +238,9 @@
|
||||
}">
|
||||
<div class="coupon-content" :style="{ color: value.moneyColor }">
|
||||
<span class="price">+</span>
|
||||
<span class="text">{{ $lang("diy.diy-coupon.l241.t0") }}</span>
|
||||
<span class="text">暂无优惠券</span>
|
||||
</div>
|
||||
<span class="limit" :style="{ color: value.limitColor }">{{ $lang("common.ns-empty.l31.t0") }}</span>
|
||||
<span class="limit" :style="{ color: value.limitColor }">去逛逛</span>
|
||||
</div>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
@@ -257,23 +257,23 @@
|
||||
<view class="coupon-num" v-if="item.discount == '0.00'"
|
||||
:style="{ color: value.moneyColor }">
|
||||
<text class="coupon-size">{{ item.money | moneyConduct }}</text>
|
||||
<text class="font-size-tag coupon-sign">{{ $lang("common.register-reward.l45.t0") }}</text>
|
||||
<text class="font-size-tag coupon-sign">元</text>
|
||||
</view>
|
||||
<view class="coupon-num" v-else :style="{ color: value.moneyColor }">
|
||||
<text class="coupon-size">{{ item.discount | moneyConduct }}</text>
|
||||
<text class="font-size-tag coupon-sign">{{ $lang("common.register-reward.l60.t1") }}</text>
|
||||
<text class="font-size-tag coupon-sign">折</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="coupon-type">
|
||||
<text class="coupon-name" :style="{ color: value.limitColor }"
|
||||
v-if="item.at_least > 0">{ $lang("diy.diy-coupon.l32.t0") } Number(item.at_least) }}元可用</text>
|
||||
<text class="coupon-name" :style="{ color: value.limitColor }" v-else>{{ $lang("diy.diy-coupon.l32.t2") }}</text>
|
||||
v-if="item.at_least > 0">满{{ Number(item.at_least) }}元可用</text>
|
||||
<text class="coupon-name" :style="{ color: value.limitColor }" v-else>无门槛优惠券</text>
|
||||
<view class="coupon-least" :style="{ color: value.limitColor }">有效期至{{
|
||||
$util.timeStampTurnTime(item.end_time, 'yearmonthday') }}</view>
|
||||
</view>
|
||||
<view class="coupon-line"></view>
|
||||
<view class="coupon-get" :style="couponBtnStyle" v-if="item.useState == 0">
|
||||
{{ value.btnStyle.text || $lang('diy.diy-coupon.l181.t0') }}
|
||||
{{ value.btnStyle.text || '立即领取' }}
|
||||
</view>
|
||||
<view class="coupon-get" :style="couponBtnStyle" v-if="parseInt(item.useState)">去使用
|
||||
</view>
|
||||
@@ -404,7 +404,7 @@ export default {
|
||||
couponTap(item, index) {
|
||||
if (item.count == item.lead_count) {
|
||||
this.$util.showToast({
|
||||
title: $lang('diy.diy-coupon.l407.t0')
|
||||
title: '该优惠券已抢光'
|
||||
});
|
||||
return;
|
||||
}
|
||||
@@ -427,7 +427,7 @@ export default {
|
||||
var data = res.data;
|
||||
let msg = res.message;
|
||||
if (res.code == 0) {
|
||||
msg = $lang('diy.diy-coupon.l430.t0');
|
||||
msg = '领取成功';
|
||||
if (res.data.is_exist == 1) {
|
||||
for (let i = 0; i < that.couponList.length; i++) {
|
||||
if (that.couponList[i].coupon_type_id == item.coupon_type_id) {
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<view class="discount-price">
|
||||
<view class="price-wrap" v-if="value.priceStyle.mainControl">
|
||||
<text class="unit price-style small"
|
||||
:style="{ color: value.theme == 'diy' ? value.priceStyle.mainColor : '' }">{{ $lang("diy.diy-fenxiao-goods-list.l23.t0") }}</text>
|
||||
:style="{ color: value.theme == 'diy' ? value.priceStyle.mainColor : '' }">赚 ¥</text>
|
||||
<text class="price price-style large"
|
||||
:style="{ color: value.theme == 'diy' ? value.priceStyle.mainColor : '' }">{{
|
||||
item.commission_money.split('.')[0] }}</text>
|
||||
@@ -138,7 +138,7 @@ export default {
|
||||
},
|
||||
success: res => {
|
||||
if (res.code >= 0) {
|
||||
this.$util.showToast({ title: $lang('diy.diy-fenxiao-goods-list.l141.t0') });
|
||||
this.$util.showToast({ title: '关注成功' });
|
||||
this.list[index].is_collect = 1;
|
||||
this.list[index].collect_id = res.data;
|
||||
}
|
||||
@@ -149,8 +149,8 @@ export default {
|
||||
//取消关注
|
||||
delFollowTip(e, index) {
|
||||
uni.showModal({
|
||||
title: $lang('common.wxwork-contact.l202.t0'),
|
||||
content: $lang('diy.diy-fenxiao-goods-list.l153.t0'),
|
||||
title: '提示',
|
||||
content: '确认取消关注该商品吗',
|
||||
success: res => {
|
||||
if (res.confirm) {
|
||||
this.delFollow(e.collect_id, index);
|
||||
@@ -167,7 +167,7 @@ export default {
|
||||
success: res => {
|
||||
let msg = '';
|
||||
if (res.code == 0) {
|
||||
msg = $lang('diy.diy-fenxiao-goods-list.l170.t0');
|
||||
msg = '取消成功';
|
||||
} else {
|
||||
msg = res.message;
|
||||
}
|
||||
|
||||
@@ -139,7 +139,7 @@ export default {
|
||||
// 提交按钮文字:与后端 design.html <button>提交</button> 默认对齐,开放给 formConfig 覆盖
|
||||
// 走 mergedFormConfig(兼容 camelCase / snake_case),让 formConfig.submitText 能正确覆盖
|
||||
submitText() {
|
||||
return this.mergedFormConfig.submitText || $lang('diy.diy-form.l142.t0');
|
||||
return this.mergedFormConfig.submitText || '提交';
|
||||
},
|
||||
// 后端把表单样式配置统一存放在 data.formConfig 子对象中(与后端 design.js getDefaultFormData().formConfig 字段名一致)。
|
||||
// 这里做一次归一化:优先取 formConfig;如果历史数据是扁平结构(直接挂在 value 上),也做兼容。
|
||||
@@ -298,12 +298,12 @@ export default {
|
||||
form_id: this.value.form_id || 0,
|
||||
form_data: JSON.stringify(submitData),
|
||||
component_id: this.value.id || '',
|
||||
form_name: this.value.form_name || $lang('diy.diy-form.l301.t0')
|
||||
form_name: this.value.form_name || '默认表单'
|
||||
},
|
||||
success: function(res) {
|
||||
if (res.code === 0) {
|
||||
uni.showToast({
|
||||
title: $lang('diy.diy-form.l306.t0'),
|
||||
title: '提交成功',
|
||||
icon: 'success'
|
||||
});
|
||||
// 重置表单
|
||||
@@ -312,7 +312,7 @@ export default {
|
||||
}
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: res.message || $lang('diy.diy-form.l315.t0'),
|
||||
title: res.message || '提交失败',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
</view>
|
||||
<view class="sale" v-if="goodsValue.saleStyle.control"
|
||||
:style="{ color: goodsValue.theme == 'diy' ? goodsValue.saleStyle.color : '' }">
|
||||
已售{{ item.sale_num }}{{ item.unit ? item.unit : $lang('common.ns-goods-sku.ns-goods-sku-index.l150.t0') }}
|
||||
已售{{ item.sale_num }}{{ item.unit ? item.unit : '件' }}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -168,7 +168,7 @@
|
||||
</view>
|
||||
<view class="sale" v-if="goodsValue.saleStyle.control"
|
||||
:style="{ color: goodsValue.theme == 'diy' ? goodsValue.saleStyle.color : '' }">
|
||||
已售{{ item.sale_num }}{{ item.unit ? item.unit : $lang('common.ns-goods-sku.ns-goods-sku-index.l150.t0') }}
|
||||
已售{{ item.sale_num }}{{ item.unit ? item.unit : '件' }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -238,7 +238,7 @@
|
||||
</view>
|
||||
<view class="sale" v-if="goodsValue.saleStyle.control"
|
||||
:style="{ color: goodsValue.theme == 'diy' ? goodsValue.saleStyle.color : '' }">
|
||||
已售{{ dataItem.sale_num }}{{ dataItem.unit ? dataItem.unit : $lang('common.ns-goods-sku.ns-goods-sku-index.l150.t0') }}
|
||||
已售{{ dataItem.sale_num }}{{ dataItem.unit ? dataItem.unit : '件' }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
¥{{ showMarketPrice(dataItem) }}</view>
|
||||
<view class="sale" v-if="goodsValue.saleStyle.control"
|
||||
:style="{ color: goodsValue.theme == 'diy' ? goodsValue.saleStyle.color : '' }">
|
||||
售{{ dataItem.sale_num }}{{ dataItem.unit ? dataItem.unit : $lang('common.ns-goods-sku.ns-goods-sku-index.l150.t0') }}
|
||||
售{{ dataItem.sale_num }}{{ dataItem.unit ? dataItem.unit : '件' }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -14,7 +14,7 @@
|
||||
</view>
|
||||
<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"
|
||||
:style="{ background: item.BtBgColor, color: item.BtColor }" @tap.stop="previewSqs()">{{ $lang("diy.diy-kefu.l17.t0") }}</span>
|
||||
:style="{ background: item.BtBgColor, color: item.BtColor }" @tap.stop="previewSqs()">立即添加</span>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
style="border-radius:6rpx;width: 60rpx;"></image>
|
||||
</view>
|
||||
<view class="fui-cell-text" style="color:#333;">{{ item.title }}</view>
|
||||
<view class="fui-cell-remark" style="font-size: 24rpx;">{{ lang == 'en-us' ? 'view' : $lang('diy.diy-listmenu.l15.t0') }}</view>
|
||||
<view class="fui-cell-remark" style="font-size: 24rpx;">{{ lang == 'en-us' ? 'view' : '查看' }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -26,11 +26,11 @@
|
||||
<image
|
||||
:src="liveInfo.anchor_img != '' ? $util.img(liveInfo.anchor_img) : $util.getDefaultImage().head"
|
||||
class="anchor-img" @error="liveInfo.anchor_img = $util.getDefaultImage().head" show-menu-by-longpress/>
|
||||
<text class="anchor-name">{ $lang("diy.diy-live.l29.t0") } liveInfo.anchor_name }}</text>
|
||||
<text class="anchor-name">主播:{{ liveInfo.anchor_name }}</text>
|
||||
</block>
|
||||
<text class="separate" v-if="value.isShowAnchorInfo && value.isShowLiveGood">|</text>
|
||||
<block v-if="value.isShowLiveGood">
|
||||
<text class="goods-text">{ $lang("diy.diy-live.l33.t0") } liveInfo.goods.length }}</text>
|
||||
<text class="goods-text">直播商品:{{ liveInfo.goods.length }}</text>
|
||||
</block>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -6,14 +6,14 @@
|
||||
<!-- <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;"
|
||||
@tap.stop="handlerClick(item)" @tap="handlerClick(item)">
|
||||
<cover-view style="font-size:24rpx">{{ $lang("diy.diy-map.l9.t0") }}</cover-view>
|
||||
<cover-view style="font-size:24rpx">一键导航</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;">{{ $lang("diy.diy-map.l9.t0") }}</span>
|
||||
<span style="font-size:24rpx;color: #fff;">一键导航</span>
|
||||
</div>
|
||||
</map>
|
||||
</view>
|
||||
@@ -71,7 +71,7 @@ export default {
|
||||
uni.openLocation({
|
||||
latitude: parseFloat(item.lat),
|
||||
longitude: parseFloat(item.lng),
|
||||
name: $lang("diy.diy-map.l9.t0"),
|
||||
name: "一键导航",
|
||||
})
|
||||
},
|
||||
async handlerClick(item) {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -19,7 +19,7 @@
|
||||
> 99 ? '99+' :
|
||||
orderNum.waitpay }}</text>
|
||||
</view>
|
||||
<view class="title">{{ $lang('order.list.waitpay') }}</view>
|
||||
<view class="title">{{ $lang('waitpay') }}</view>
|
||||
</view>
|
||||
<view class="item-wrap" @tap.stop="redirect('/pages_order/list?status=waitsend')"
|
||||
style="margin-right: 10rpx;">
|
||||
@@ -38,7 +38,7 @@
|
||||
orderNum.waitsend > 99 ? '99+'
|
||||
: orderNum.waitsend }}</text>
|
||||
</view>
|
||||
<view class="title">{{ $lang('order.list.waitsend') }}</view>
|
||||
<view class="title">{{ $lang('waitsend') }}</view>
|
||||
</view>
|
||||
<view class="item-wrap" @tap.stop="redirect('/pages_order/list?status=waitconfirm')"
|
||||
style="margin-right: 10rpx;">
|
||||
@@ -57,7 +57,7 @@
|
||||
orderNum.waitconfirm > 99 ?
|
||||
'99+' : orderNum.waitconfirm }}</text>
|
||||
</view>
|
||||
<view class="title">{{ $lang('order.list.waitconfirm') }}</view>
|
||||
<view class="title">{{ $lang('waitconfirm') }}</view>
|
||||
</view>
|
||||
<view class="item-wrap" @tap.stop="redirect('/pages_order/list?status=waitrate')"
|
||||
style="margin-right: 10rpx;">
|
||||
@@ -74,7 +74,7 @@
|
||||
</template>
|
||||
<!-- <text v-if="orderNum.wait_use > 0" class="order-num color-base-bg price-font">{{ orderNum.wait_use > 99 ? '99+' : orderNum.wait_use }}</text> -->
|
||||
</view>
|
||||
<view class="title">{{ $lang('order.list.completed') }}</view>
|
||||
<view class="title">{{ $lang('completed') }}</view>
|
||||
</view>
|
||||
<view class="item-wrap" @tap.stop="redirect('/pages_tool/order/activist')">
|
||||
<view class="icon-block">
|
||||
@@ -92,7 +92,7 @@
|
||||
orderNum.refunding > 99 ?
|
||||
'99+' : orderNum.refunding }}</text>
|
||||
</view>
|
||||
<view class="title">{{ $lang('order.list.activist') }}</view>
|
||||
<view class="title">{{ $lang('activist') }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -63,31 +63,31 @@ export default {
|
||||
return {
|
||||
list: [
|
||||
/*{
|
||||
merch_name:$lang('diy.diy-merch-list.l66.t0'),
|
||||
merch_name:'品牌',
|
||||
merch_image:'https://saas.cn//upload/4/common/images/20240824/20240824040223172448654356147.jpg'
|
||||
},
|
||||
{
|
||||
merch_name:$lang('diy.diy-merch-list.l66.t0'),
|
||||
merch_name:'品牌',
|
||||
merch_image:'https://saas.cn//upload/4/common/images/20240824/20240824040223172448654356147.jpg'
|
||||
},
|
||||
{
|
||||
merch_name:$lang('diy.diy-merch-list.l66.t0'),
|
||||
merch_name:'品牌',
|
||||
merch_image:'https://saas.cn//upload/4/common/images/20240824/20240824040223172448654356147.jpg'
|
||||
},
|
||||
{
|
||||
merch_name:$lang('diy.diy-merch-list.l66.t0'),
|
||||
merch_name:'品牌',
|
||||
merch_image:'https://saas.cn//upload/4/common/images/20240824/20240824040223172448654356147.jpg'
|
||||
},
|
||||
{
|
||||
merch_name:$lang('diy.diy-merch-list.l66.t0'),
|
||||
merch_name:'品牌',
|
||||
merch_image:'https://saas.cn//upload/4/common/images/20240824/20240824040223172448654356147.jpg'
|
||||
},
|
||||
{
|
||||
merch_name:$lang('diy.diy-merch-list.l66.t0'),
|
||||
merch_name:'品牌',
|
||||
merch_image:'https://saas.cn//upload/4/common/images/20240824/20240824040223172448654356147.jpg'
|
||||
},
|
||||
{
|
||||
merch_name:$lang('diy.diy-merch-list.l66.t0'),
|
||||
merch_name:'品牌',
|
||||
merch_image:'https://saas.cn//upload/4/common/images/20240824/20240824040223172448654356147.jpg'
|
||||
}*/
|
||||
],
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
</view>
|
||||
<view class="notes-intro">
|
||||
<text class="notes-label color-base-text">#{{ item.note_type == 'goods_item' ? '单品介绍' :
|
||||
$lang('diy.diy-notes.l21.t0') }}#</text>
|
||||
'掌柜说' }}#</text>
|
||||
{{ item.note_abstract }}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -42,11 +42,11 @@
|
||||
<uni-popup ref="noticePopup" type="center">
|
||||
<view class="notice-popup">
|
||||
<view class="head-wrap" @tap.stop="closeNoticePopup">
|
||||
<text>{{ $lang("diy.diy-notice.l45.t0") }}</text>
|
||||
<text>公告</text>
|
||||
<text class="iconfont icon-close"></text>
|
||||
</view>
|
||||
<view class="content-wrap">{{ notice }}</view>
|
||||
<button type="primary" @tap.stop="closeNoticePopup">{{ $lang("diy.diy-notice.l49.t0") }}</button>
|
||||
<button type="primary" @tap.stop="closeNoticePopup">我知道了</button>
|
||||
</view>
|
||||
</uni-popup>
|
||||
</view>
|
||||
|
||||
@@ -3,23 +3,23 @@
|
||||
<view class="payment-qrocde-box">
|
||||
<view class="qrocde-left">
|
||||
<view class="qrocde-desc">
|
||||
<text>{{ $lang("diy.diy-payment-qrcode.l6.t0") }}</text>
|
||||
<text>门店消费时使用,支付时点击下方展示付款码</text>
|
||||
<!-- <text class="iconfont icon-shuaxin"></text> -->
|
||||
</view>
|
||||
<view class="qrocde-action">
|
||||
<button type="primary" @tap.stop="toLink">
|
||||
<text class="iconfont icon-fukuanma"></text>
|
||||
<text class="action-name">{{ $lang("diy.diy-payment-qrcode.l12.t0") }}</text>
|
||||
<text class="action-name">付款码</text>
|
||||
</button>
|
||||
<button type="primary" @tap.stop="openPaymentPopup">
|
||||
<text class="iconfont icon-saomafu"></text>
|
||||
<text class="action-name">{{ $lang("diy.diy-payment-qrcode.l16.t0") }}</text>
|
||||
<text class="action-name">扫码付</text>
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
<view class="qrocde-right">
|
||||
<text class="iconfont icon-zhifu"></text>
|
||||
<text class="name">{{ $lang("diy.diy-payment-qrcode.l22.t0") }}</text>
|
||||
<text class="name">门店支付</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -27,11 +27,11 @@
|
||||
<uni-popup ref="paymentPopup" type="center">
|
||||
<view class="payment-popup">
|
||||
<view class="head-wrap" @tap.stop="closePaymentPopup">
|
||||
<text>{{ $lang("common.wxwork-contact.l202.t0") }}</text>
|
||||
<text>提示</text>
|
||||
<text class="iconfont icon-close"></text>
|
||||
</view>
|
||||
<view class="content-wrap">{{ $lang("diy.diy-payment-qrcode.l33.t0") }}</view>
|
||||
<button type="primary" @tap.stop="closePaymentPopup">{{ $lang("diy.diy-notice.l49.t0") }}</button>
|
||||
<view class="content-wrap">扫码付请退出程序后直接使用微信扫一扫或返回上一页使用付款码进行支付</view>
|
||||
<button type="primary" @tap.stop="closePaymentPopup">我知道了</button>
|
||||
</view>
|
||||
</uni-popup>
|
||||
</view>
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
</view>
|
||||
<view v-if="value.saleStyle.control"
|
||||
:style="{ color: value.theme == 'diy' ? value.saleStyle.color : '', borderColor: value.theme == 'diy' ? value.saleStyle.color : '' }">
|
||||
<text>{ $lang("diy.diy-pinfan.l28.t0") } item.order_num }}件</text>
|
||||
<text>已拼{{ item.order_num }}件</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="price-wrap">
|
||||
@@ -49,10 +49,10 @@
|
||||
borderRadius: value.btnStyle.aroundRadius * 2 + 'rpx'
|
||||
}">
|
||||
<text class="text">{{ value.btnStyle.text }}</text>
|
||||
<text class="fan" v-if="item.reward_type == 4">{ $lang("diy.diy-pinfan.l52.t0") } item.reward_type_num }}积分</text>
|
||||
<text class="fan" v-if="item.reward_type == 4">返{{ item.reward_type_num }}积分</text>
|
||||
<text class="fan" v-if="item.reward_type == 1 || item.reward_type == 2">返¥{{
|
||||
item.reward_type_num }}</text>
|
||||
<text class="fan" v-if="item.reward_type == 3">{{ $lang("diy.diy-pinfan.l55.t0") }}</text>
|
||||
<text class="fan" v-if="item.reward_type == 3">返优惠券</text>
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
@@ -92,7 +92,7 @@
|
||||
</text>
|
||||
<text class="content-tuan-price"
|
||||
:style="{ color: value.theme == 'diy' ? value.groupStyle.bgColor : '' }"
|
||||
v-if="item.reward_type == 3">{{ $lang("diy.diy-pinfan.l55.t0") }}</text>
|
||||
v-if="item.reward_type == 3">返优惠券</text>
|
||||
</view>
|
||||
<view class="price-wrap" v-if="value.priceStyle.mainControl">
|
||||
<text class="unit price-style small"
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
</view>
|
||||
<view :style="{ color: value.titleStyle.textColor }">
|
||||
<text>{{ value.titleStyle.virtualNum || headData.pintuan_count }}</text>
|
||||
<text>{{ value.titleStyle.style == 'style-2' ? '人参与' : $lang('diy.diy-pintuan.l29.t1') }}</text>
|
||||
<text>{{ value.titleStyle.style == 'style-2' ? '人参与' : '人拼团成功' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="head-right"
|
||||
@@ -63,7 +63,7 @@
|
||||
</view>
|
||||
<view v-if="value.saleStyle.control"
|
||||
:style="{ color: value.theme == 'diy' ? value.saleStyle.color : '', borderColor: value.theme == 'diy' ? value.saleStyle.color : '' }">
|
||||
<text>{ $lang("diy.diy-pinfan.l28.t0") } item.order_num }}件</text>
|
||||
<text>已拼{{ item.order_num }}件</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -148,10 +148,10 @@
|
||||
{{ '.' + item.pintuan_price.split('.')[1] }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="sale-action">{{ $lang("diy.diy-pintuan.l151.t0") }}</view>
|
||||
<view class="sale-action">去参团</view>
|
||||
</view>
|
||||
|
||||
<view class="sale-num" v-if="value.style == 'style-2'">{ $lang("diy.diy-pinfan.l28.t0") } item.sale_num }}件</view>
|
||||
<view class="sale-num" v-if="value.style == 'style-2'">已拼{{ item.sale_num }}件</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
@@ -192,7 +192,7 @@
|
||||
{{ '.' + item.pintuan_price.split('.')[1] }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="sale-num" v-if="value.style == 'style-2'">{ $lang("diy.diy-pinfan.l28.t0") } item.sale_num }}件</view>
|
||||
<view class="sale-num" v-if="value.style == 'style-2'">已拼{{ item.sale_num }}件</view>
|
||||
</view>
|
||||
</view>
|
||||
</swiper-item>
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
@tap.stop="handlerSearchClick"
|
||||
:placeholderStyle="placeholderStyle" />
|
||||
<text class="search-content-btn" @tap.stop="handlerSearchClick"
|
||||
:style="{ 'backgroundColor': value.pageBgColor ? value.pageBgColor : 'rgba(0,0,0,0)' }">{{ $lang("diy.diy-search.l31.t0") }}</text>
|
||||
:style="{ 'backgroundColor': value.pageBgColor ? value.pageBgColor : 'rgba(0,0,0,0)' }">搜索</text>
|
||||
</view>
|
||||
<view class="img" v-if="value.iconType == 'img'"
|
||||
@tap.stop="handlerRedirectToClick(value.searchLink)">
|
||||
|
||||
@@ -13,10 +13,10 @@
|
||||
</view>
|
||||
<image v-else class="title-img" :src="$util.img(value.titleStyle.leftImg)" mode="heightFix" show-menu-by-longpress/>
|
||||
<text v-if="value.titleStyle.style == 'style-2' && isFuture"
|
||||
:style="{ color: value.titleStyle.textColor }" class="seckill-style-name">{{ $lang("diy.diy-seckill.l16.t0") }}</text>
|
||||
:style="{ color: value.titleStyle.textColor }" class="seckill-style-name">距离开始</text>
|
||||
<view class="time" :style="{ background: value.titleStyle.timeBgColor }">
|
||||
<text :style="{ color: value.titleStyle.textColor }" class="seckill-title-name text">{{ isFuture ?
|
||||
'距离开始' : $lang('diy.diy-seckill.l19.t0') }}</text>
|
||||
'距离开始' : '距离结束' }}</text>
|
||||
<text v-if="value.titleStyle.timeImageUrl"
|
||||
:class="['seckill-title-name icon', value.titleStyle.timeImageUrl]"></text>
|
||||
<text class="hour number" :style="titleTimeStyle">{{ seckillH ? seckillH : '00' }}</text>
|
||||
@@ -87,7 +87,7 @@
|
||||
</view>
|
||||
<view class="price-font" v-else>
|
||||
<text
|
||||
:style="{ color: value.theme == 'diy' ? value.priceStyle.lineColor : '' }">{{ $lang("diy.diy-seckill.l90.t0") }}</text>
|
||||
:style="{ color: value.theme == 'diy' ? value.priceStyle.lineColor : '' }">原价:</text>
|
||||
<text :style="{ color: value.theme == 'diy' ? value.priceStyle.lineColor : '' }"
|
||||
class="original-price">¥{{ item.price }}</text>
|
||||
</view>
|
||||
@@ -502,7 +502,7 @@ export default {
|
||||
toDetail(id) {
|
||||
if (this.isFuture) {
|
||||
this.$util.showToast({
|
||||
title: $lang('diy.diy-seckill.l505.t0')
|
||||
title: '秒杀活动即将开启,敬请期待!'
|
||||
});
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -7,17 +7,17 @@
|
||||
<block v-if="globalStoreInfo && globalStoreInfo.store_id">
|
||||
<text class="title">{{ globalStoreInfo.store_name }}</text>
|
||||
<text>
|
||||
<text class="change margin-left">{{ $lang("diy.diy-store.l10.t0") }}</text>
|
||||
<text class="change margin-left">切换</text>
|
||||
<text class="iconfont icon-right"></text>
|
||||
</text>
|
||||
</block>
|
||||
<text class="title" v-else>{{ $lang("common.ns-navbar.l39.t0") }}</text>
|
||||
<text class="title" v-else>定位中...</text>
|
||||
</view>
|
||||
<view class="address-wrap" :style="{ color: value.textColor }">
|
||||
<text class="iconfont icon-dizhi"></text>
|
||||
<text v-if="globalStoreInfo && globalStoreInfo.store_id" @tap.stop="mapRoute" class="address">{{
|
||||
globalStoreInfo.show_address }}</text>
|
||||
<text v-else>{{ $lang("diy.diy-store.l20.t0") }}</text>
|
||||
<text v-else>获取当前位置...</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="store-image" @tap.stop="selectStore()">
|
||||
@@ -40,11 +40,11 @@
|
||||
<block v-if="globalStoreInfo && globalStoreInfo.store_id">
|
||||
<text class="title">{{ globalStoreInfo.store_name }}</text>
|
||||
<text>
|
||||
<text class="change margin-left">{{ $lang("diy.diy-store.l10.t0") }}</text>
|
||||
<text class="change margin-left">切换</text>
|
||||
<text class="iconfont icon-right"></text>
|
||||
</text>
|
||||
</block>
|
||||
<text class="title" v-else>{{ $lang("common.ns-navbar.l39.t0") }}</text>
|
||||
<text class="title" v-else>定位中...</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="store-icon" @tap.stop="search()"><text class="iconfont icon-sousuo3"
|
||||
@@ -60,10 +60,10 @@
|
||||
<text class="title" :style="{ color: value.textColor }">{{ globalStoreInfo.store_name }}</text>
|
||||
<text class="iconfont icon-unfold" :style="{ color: value.textColor }"></text>
|
||||
</block>
|
||||
<text class="title" v-else>{{ $lang("common.ns-navbar.l39.t0") }}</text>
|
||||
<text class="title" v-else>定位中...</text>
|
||||
</view>
|
||||
<view class="store-right-search">
|
||||
<input type="text" class="uni-input font-size-tag" disabled placeholder=$lang("diy.diy-store.l66.t0")
|
||||
<input type="text" class="uni-input font-size-tag" disabled placeholder="商品搜索"
|
||||
@tap.stop="search()" />
|
||||
<text class="iconfont icon-sousuo3" @tap.stop="search()"></text>
|
||||
</view>
|
||||
|
||||
@@ -208,7 +208,7 @@
|
||||
{{ value.text }}
|
||||
</text>
|
||||
<text class="zone"
|
||||
:style="{ fontSize: value.fontSize * 2 + 'rpx', fontWeight: value.fontWeight }">{{ $lang("diy.diy-text.l211.t0") }}</text>
|
||||
:style="{ fontSize: value.fontSize * 2 + 'rpx', fontWeight: value.fontWeight }">专区</text>
|
||||
</view>
|
||||
<text class="iconfont icon-danxuan-xuanzhong"
|
||||
:style="{ color: value.textColor, fontWeight: value.fontWeight }"></text>
|
||||
|
||||
@@ -143,7 +143,7 @@ export default {
|
||||
});
|
||||
|
||||
video.addEventListener('error', (e) => {
|
||||
console.error($lang('diy.diy-video.l146.t0'), e);
|
||||
console.error('H5端预加载视频失败:', e);
|
||||
});
|
||||
|
||||
// 触发加载
|
||||
@@ -184,7 +184,7 @@ export default {
|
||||
|
||||
// 视频错误事件
|
||||
onVideoError(event) {
|
||||
console.error($lang('diy.diy-video.l187.t0'), event);
|
||||
console.error('视频加载失败:', event);
|
||||
},
|
||||
|
||||
async handlerClick(videoUrl) {
|
||||
|
||||
@@ -1,187 +1,187 @@
|
||||
// 微信视频号组件配置
|
||||
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: $lang('diy.js.wechat-channel.l59.t0'),
|
||||
lowVersion: $lang('diy.js.wechat-channel.l60.t0'),
|
||||
notSupported: $lang('diy.js.wechat-channel.l61.t0'),
|
||||
missingFields: $lang('diy.js.wechat-channel.l62.t0'),
|
||||
},
|
||||
};
|
||||
|
||||
// 获取配置项的辅助函数
|
||||
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($lang(`diy.js.wechat-channel.l111.t0`));
|
||||
}
|
||||
}
|
||||
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) => {
|
||||
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($lang('diy.js.wechat-channel.l170.t0'), 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();
|
||||
}
|
||||
// 微信视频号组件配置
|
||||
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) => {
|
||||
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();
|
||||
}
|
||||
};
|
||||
@@ -1,333 +1,333 @@
|
||||
<template>
|
||||
<view class="chat-message">
|
||||
<block v-if="message.contentType == 'sendGood'">
|
||||
<ns-chat-goods :skuId="message.sku_id" :goodsDetail="message.goodsDetail" @sendMsg="sendGood"></ns-chat-goods>
|
||||
</block>
|
||||
<block v-if="message.contentType == 'sendOrder'">
|
||||
<ns-chat-order :orderId="message.order_id" :orderdetails="message.orderDetail" @sendMsg="sendOrder"></ns-chat-order>
|
||||
</block>
|
||||
<block v-if="message.contentType == 'goodssku'">
|
||||
<ns-chat-receiveGoods :skuId="message.sku_id"></ns-chat-receiveGoods>
|
||||
</block>
|
||||
<view class="message" v-if="message.contentType == 'string'">
|
||||
<view class="message-item " :class="message.isItMe ? 'right' : 'left'">
|
||||
<block v-if="message.isItMe">
|
||||
<view class="head_img">
|
||||
<image class="img" :src="myHeadImg" v-if="myHeadImg" @error="myHeadImgError" mode="aspectFit" show-menu-by-longpress/>
|
||||
<image class="img" :src="defaultHead" mode="aspectFit" v-else show-menu-by-longpress/>
|
||||
</view>
|
||||
</block>
|
||||
<block v-else>
|
||||
<view class="head_img">
|
||||
<image class="img" :src="avatar" mode="aspectFit" v-if="avatar" show-menu-by-longpress></image>
|
||||
<image class="img" :src="defaultHead" mode="aspectFit" v-else show-menu-by-longpress></image>
|
||||
</view>
|
||||
</block>
|
||||
<view class="chat_text">
|
||||
<text class="iconfont icon-warn margin-right color-base-text" v-if="message.isItMe && !message.sendStatus"></text>
|
||||
<view class="content"><rich-text :nodes="stringToEmjoy(message.content)"></rich-text></view>
|
||||
<!-- <text class="iconfont icon-warn margin-left" v-if="!message.isItMe && !message.sendStatus"></text> -->
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="message" v-if="message.contentType == 'image'">
|
||||
<view class="message-item " :class="message.isItMe ? 'right' : 'left'">
|
||||
<block v-if="message.isItMe">
|
||||
<view class="head_img">
|
||||
<image class="img" :src="myHeadImg" v-if="myHeadImg" mode="aspectFit" show-menu-by-longpress></image>
|
||||
<image class="img" :src="defaultHead" mode="aspectFit" v-else show-menu-by-longpress></image>
|
||||
</view>
|
||||
</block>
|
||||
<block v-else>
|
||||
<view class="head_img">
|
||||
<image class="img" :src="avatar" mode="aspectFit" v-if="avatar" show-menu-by-longpress></image>
|
||||
<image class="img" :src="defaultHead" mode="aspectFit" v-else show-menu-by-longpress></image>
|
||||
</view>
|
||||
</block>
|
||||
<view class="chat_img">
|
||||
<text class="iconfont icon-warn margin-right color-base-text" v-if="message.isItMe && !message.sendStatus"></text>
|
||||
<view class="content_img" @click="previewMedia($util.img(message.image))" :style="{ backgroundImage: 'url(' + $util.img(message.image) + ')' }">
|
||||
<!-- <image class="img_img" :src="$util.img(message.image)" mode="aspectFit" show-menu-by-longpress></image> -->
|
||||
</view>
|
||||
<!-- <text class="iconfont icon-warn margin-left" v-if="!message.isItMe && !message.sendStatus"></text> -->
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-else-if="message.contentType == 'goods'"><ns-chat-goods :isCanSend="false" :skuId="message.sku_id"></ns-chat-goods></view>
|
||||
<view v-else-if="message.contentType == 'order'"><ns-chat-order :isCanSend="false" :orderId="message.order_id"></ns-chat-order></view>
|
||||
|
||||
<view class="no-connect-box" v-if="message.contentType == 'noline'">
|
||||
<view class="no-connect">{{ $lang("common.chat-message.l60.t0") }}</view>
|
||||
</view>
|
||||
<view class="no-connect-box" v-if="message.contentType == 'online'">
|
||||
<view class="no-connect">{{ $lang("common.chat-message.l63.t0") }}</view>
|
||||
</view>
|
||||
<uni-popup ref="imgPopup" type="center">
|
||||
<view class="imagePop">
|
||||
<image :src="$util.img(currImg)" mode="aspectFit" show-menu-by-longpress></image>
|
||||
</view>
|
||||
</uni-popup>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import htmlParser from '@/common/js/html-parser';
|
||||
import emjoy from '@/common/js/emjoy.js';
|
||||
|
||||
export default {
|
||||
name: 'chat-message',
|
||||
props: {
|
||||
message: {
|
||||
type: Object
|
||||
},
|
||||
send: {
|
||||
type: Boolean
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
avatar: '', //店铺头像
|
||||
defaultAvatar: this.$util.getDefaultImage().store,
|
||||
myHeadImg: '', //我的头像
|
||||
defaultHead: this.$util.getDefaultImage().head,
|
||||
emjoyList: emjoy.emjoyList,
|
||||
currImg: ''
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.avatar = this.$util.img(this.siteInfo.logo_square);
|
||||
this.myHeadImg = this.$util.img(this.memberInfo.headimg);
|
||||
},
|
||||
methods: {
|
||||
// 预览图片
|
||||
previewMedia(img_url) {
|
||||
var paths = [img_url];
|
||||
uni.previewImage({
|
||||
current: 0,
|
||||
urls: paths
|
||||
});
|
||||
},
|
||||
sendGood() {
|
||||
this.$emit('sendGood', 'goods');
|
||||
},
|
||||
sendOrder() {
|
||||
this.$emit('sendOrder', 'order');
|
||||
},
|
||||
// 处理图片错误
|
||||
myHeadImgError() {
|
||||
this.myHeadImg = this.defaultHead;
|
||||
},
|
||||
stringToEmjoy(value) {
|
||||
if (!value) return;
|
||||
// 兼容旧版本图片
|
||||
var reg = RegExp(/\[/);
|
||||
if (reg.test(value)) {
|
||||
let string = value; // 需要把和匹配出来
|
||||
let reg = new RegExp('\\[emjoy_(.+?)\\]', 'g');
|
||||
let emjoyString = string.replace(reg, v => {
|
||||
let emjoy = '';
|
||||
for (let index in this.emjoyList) {
|
||||
if (v == index) {
|
||||
let _url = this.$util.img(this.emjoyList[index]);
|
||||
emjoy = "<img class='message-img' src='" + _url + "'/>";
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (emjoy) {
|
||||
return emjoy;
|
||||
} else {
|
||||
return v;
|
||||
}
|
||||
});
|
||||
let content = htmlParser(emjoyString);
|
||||
content.forEach(v => {
|
||||
if (v.name == 'img') {
|
||||
v.attrs.style = 'display: inline-block;width: 32rpx !important;height: 32rpx !important;padding:0 2rpx;';
|
||||
}
|
||||
});
|
||||
return content;
|
||||
} else {
|
||||
let content = value;
|
||||
return content;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
::v-deep .uni-popup__wrapper.uni-custom .uni-popup__wrapper-box {
|
||||
background-color: #000;
|
||||
}
|
||||
|
||||
::v-deep .uni-popup__wrapper.uni-custom.center .uni-popup__wrapper-box {
|
||||
max-width: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.imagePop {
|
||||
height: 50vh;
|
||||
width: 100vw;
|
||||
text-align: center;
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.chat-message {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: white; /* 白色 */
|
||||
|
||||
.message {
|
||||
padding: 13rpx 20rpx;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.left .content {
|
||||
padding: 20rpx;
|
||||
max-width: 450rpx;
|
||||
border-radius: 10rpx;
|
||||
font-size: 30rpx;
|
||||
}
|
||||
|
||||
.right .content {
|
||||
padding: 20rpx;
|
||||
max-width: 450rpx;
|
||||
border-radius: 10rpx;
|
||||
font-size: 30rpx;
|
||||
}
|
||||
|
||||
.content_img {
|
||||
height: 200rpx;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
text-align: right;
|
||||
margin-left: 28rpx;
|
||||
background-position: center right;
|
||||
background-repeat: no-repeat;
|
||||
background-size: contain;
|
||||
|
||||
image {
|
||||
min-height: 80rpx;
|
||||
min-width: 80rpx;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.right .content_img {
|
||||
margin-right: 28rpx;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.message-item {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: flex-start;
|
||||
align-content: flex-start;
|
||||
flex-wrap: nowrap;
|
||||
flex-direction: row;
|
||||
|
||||
.head_img {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
|
||||
.img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
//图片
|
||||
.contentType3 {
|
||||
padding: 0;
|
||||
border-radius: 2rpx;
|
||||
background-color: transparent !important;
|
||||
|
||||
.img {
|
||||
width: 200rpx;
|
||||
height: auto;
|
||||
max-width: 300rpx;
|
||||
max-height: 400rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.contentType3::after {
|
||||
border: none !important;
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.content-type-right {
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
|
||||
&.right {
|
||||
flex-direction: row-reverse;
|
||||
|
||||
.content {
|
||||
background-color: #c4e0ff; /* 浅蓝色 */
|
||||
margin-right: 28rpx;
|
||||
word-break: break-all;
|
||||
line-height: 36rpx;
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
|
||||
&.left {
|
||||
.content {
|
||||
background-color: #ffffff;
|
||||
margin-left: 28rpx;
|
||||
word-break: break-all;
|
||||
line-height: 36rpx;
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.next {
|
||||
width: 100%;
|
||||
height: 20rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.no-connect-box {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
margin: 20rpx 0 50rpx;
|
||||
|
||||
.no-connect {
|
||||
display: inline-block;
|
||||
padding: 0 20rpx;
|
||||
height: 40rpx;
|
||||
background: red;
|
||||
margin: 0 auto;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
border-radius: 9rpx;
|
||||
text-align: center;
|
||||
line-height: 40rpx;
|
||||
font-size: 22rpx;
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
|
||||
.chat_text,
|
||||
.chat_img {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.iconfont {
|
||||
font-size: 36rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.chat_img {
|
||||
width: 30%;
|
||||
height: 200rpx;
|
||||
}
|
||||
<template>
|
||||
<view class="chat-message">
|
||||
<block v-if="message.contentType == 'sendGood'">
|
||||
<ns-chat-goods :skuId="message.sku_id" :goodsDetail="message.goodsDetail" @sendMsg="sendGood"></ns-chat-goods>
|
||||
</block>
|
||||
<block v-if="message.contentType == 'sendOrder'">
|
||||
<ns-chat-order :orderId="message.order_id" :orderdetails="message.orderDetail" @sendMsg="sendOrder"></ns-chat-order>
|
||||
</block>
|
||||
<block v-if="message.contentType == 'goodssku'">
|
||||
<ns-chat-receiveGoods :skuId="message.sku_id"></ns-chat-receiveGoods>
|
||||
</block>
|
||||
<view class="message" v-if="message.contentType == 'string'">
|
||||
<view class="message-item " :class="message.isItMe ? 'right' : 'left'">
|
||||
<block v-if="message.isItMe">
|
||||
<view class="head_img">
|
||||
<image class="img" :src="myHeadImg" v-if="myHeadImg" @error="myHeadImgError" mode="aspectFit" show-menu-by-longpress/>
|
||||
<image class="img" :src="defaultHead" mode="aspectFit" v-else show-menu-by-longpress/>
|
||||
</view>
|
||||
</block>
|
||||
<block v-else>
|
||||
<view class="head_img">
|
||||
<image class="img" :src="avatar" mode="aspectFit" v-if="avatar" show-menu-by-longpress></image>
|
||||
<image class="img" :src="defaultHead" mode="aspectFit" v-else show-menu-by-longpress></image>
|
||||
</view>
|
||||
</block>
|
||||
<view class="chat_text">
|
||||
<text class="iconfont icon-warn margin-right color-base-text" v-if="message.isItMe && !message.sendStatus"></text>
|
||||
<view class="content"><rich-text :nodes="stringToEmjoy(message.content)"></rich-text></view>
|
||||
<!-- <text class="iconfont icon-warn margin-left" v-if="!message.isItMe && !message.sendStatus"></text> -->
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="message" v-if="message.contentType == 'image'">
|
||||
<view class="message-item " :class="message.isItMe ? 'right' : 'left'">
|
||||
<block v-if="message.isItMe">
|
||||
<view class="head_img">
|
||||
<image class="img" :src="myHeadImg" v-if="myHeadImg" mode="aspectFit" show-menu-by-longpress></image>
|
||||
<image class="img" :src="defaultHead" mode="aspectFit" v-else show-menu-by-longpress></image>
|
||||
</view>
|
||||
</block>
|
||||
<block v-else>
|
||||
<view class="head_img">
|
||||
<image class="img" :src="avatar" mode="aspectFit" v-if="avatar" show-menu-by-longpress></image>
|
||||
<image class="img" :src="defaultHead" mode="aspectFit" v-else show-menu-by-longpress></image>
|
||||
</view>
|
||||
</block>
|
||||
<view class="chat_img">
|
||||
<text class="iconfont icon-warn margin-right color-base-text" v-if="message.isItMe && !message.sendStatus"></text>
|
||||
<view class="content_img" @click="previewMedia($util.img(message.image))" :style="{ backgroundImage: 'url(' + $util.img(message.image) + ')' }">
|
||||
<!-- <image class="img_img" :src="$util.img(message.image)" mode="aspectFit" show-menu-by-longpress></image> -->
|
||||
</view>
|
||||
<!-- <text class="iconfont icon-warn margin-left" v-if="!message.isItMe && !message.sendStatus"></text> -->
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-else-if="message.contentType == 'goods'"><ns-chat-goods :isCanSend="false" :skuId="message.sku_id"></ns-chat-goods></view>
|
||||
<view v-else-if="message.contentType == 'order'"><ns-chat-order :isCanSend="false" :orderId="message.order_id"></ns-chat-order></view>
|
||||
|
||||
<view class="no-connect-box" v-if="message.contentType == 'noline'">
|
||||
<view class="no-connect">客服不在线</view>
|
||||
</view>
|
||||
<view class="no-connect-box" v-if="message.contentType == 'online'">
|
||||
<view class="no-connect">客服在线</view>
|
||||
</view>
|
||||
<uni-popup ref="imgPopup" type="center">
|
||||
<view class="imagePop">
|
||||
<image :src="$util.img(currImg)" mode="aspectFit" show-menu-by-longpress></image>
|
||||
</view>
|
||||
</uni-popup>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import htmlParser from '@/common/js/html-parser';
|
||||
import emjoy from '@/common/js/emjoy.js';
|
||||
|
||||
export default {
|
||||
name: 'chat-message',
|
||||
props: {
|
||||
message: {
|
||||
type: Object
|
||||
},
|
||||
send: {
|
||||
type: Boolean
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
avatar: '', //店铺头像
|
||||
defaultAvatar: this.$util.getDefaultImage().store,
|
||||
myHeadImg: '', //我的头像
|
||||
defaultHead: this.$util.getDefaultImage().head,
|
||||
emjoyList: emjoy.emjoyList,
|
||||
currImg: ''
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.avatar = this.$util.img(this.siteInfo.logo_square);
|
||||
this.myHeadImg = this.$util.img(this.memberInfo.headimg);
|
||||
},
|
||||
methods: {
|
||||
// 预览图片
|
||||
previewMedia(img_url) {
|
||||
var paths = [img_url];
|
||||
uni.previewImage({
|
||||
current: 0,
|
||||
urls: paths
|
||||
});
|
||||
},
|
||||
sendGood() {
|
||||
this.$emit('sendGood', 'goods');
|
||||
},
|
||||
sendOrder() {
|
||||
this.$emit('sendOrder', 'order');
|
||||
},
|
||||
// 处理图片错误
|
||||
myHeadImgError() {
|
||||
this.myHeadImg = this.defaultHead;
|
||||
},
|
||||
stringToEmjoy(value) {
|
||||
if (!value) return;
|
||||
// 兼容旧版本图片
|
||||
var reg = RegExp(/\[/);
|
||||
if (reg.test(value)) {
|
||||
let string = value; // 需要把和匹配出来
|
||||
let reg = new RegExp('\\[emjoy_(.+?)\\]', 'g');
|
||||
let emjoyString = string.replace(reg, v => {
|
||||
let emjoy = '';
|
||||
for (let index in this.emjoyList) {
|
||||
if (v == index) {
|
||||
let _url = this.$util.img(this.emjoyList[index]);
|
||||
emjoy = "<img class='message-img' src='" + _url + "'/>";
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (emjoy) {
|
||||
return emjoy;
|
||||
} else {
|
||||
return v;
|
||||
}
|
||||
});
|
||||
let content = htmlParser(emjoyString);
|
||||
content.forEach(v => {
|
||||
if (v.name == 'img') {
|
||||
v.attrs.style = 'display: inline-block;width: 32rpx !important;height: 32rpx !important;padding:0 2rpx;';
|
||||
}
|
||||
});
|
||||
return content;
|
||||
} else {
|
||||
let content = value;
|
||||
return content;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
::v-deep .uni-popup__wrapper.uni-custom .uni-popup__wrapper-box {
|
||||
background-color: #000;
|
||||
}
|
||||
|
||||
::v-deep .uni-popup__wrapper.uni-custom.center .uni-popup__wrapper-box {
|
||||
max-width: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.imagePop {
|
||||
height: 50vh;
|
||||
width: 100vw;
|
||||
text-align: center;
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.chat-message {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: white; /* 白色 */
|
||||
|
||||
.message {
|
||||
padding: 13rpx 20rpx;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.left .content {
|
||||
padding: 20rpx;
|
||||
max-width: 450rpx;
|
||||
border-radius: 10rpx;
|
||||
font-size: 30rpx;
|
||||
}
|
||||
|
||||
.right .content {
|
||||
padding: 20rpx;
|
||||
max-width: 450rpx;
|
||||
border-radius: 10rpx;
|
||||
font-size: 30rpx;
|
||||
}
|
||||
|
||||
.content_img {
|
||||
height: 200rpx;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
text-align: right;
|
||||
margin-left: 28rpx;
|
||||
background-position: center right;
|
||||
background-repeat: no-repeat;
|
||||
background-size: contain;
|
||||
|
||||
image {
|
||||
min-height: 80rpx;
|
||||
min-width: 80rpx;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.right .content_img {
|
||||
margin-right: 28rpx;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.message-item {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: flex-start;
|
||||
align-content: flex-start;
|
||||
flex-wrap: nowrap;
|
||||
flex-direction: row;
|
||||
|
||||
.head_img {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
border-radius: 50%;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
|
||||
.img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
//图片
|
||||
.contentType3 {
|
||||
padding: 0;
|
||||
border-radius: 2rpx;
|
||||
background-color: transparent !important;
|
||||
|
||||
.img {
|
||||
width: 200rpx;
|
||||
height: auto;
|
||||
max-width: 300rpx;
|
||||
max-height: 400rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.contentType3::after {
|
||||
border: none !important;
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.content-type-right {
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
|
||||
&.right {
|
||||
flex-direction: row-reverse;
|
||||
|
||||
.content {
|
||||
background-color: #c4e0ff; /* 浅蓝色 */
|
||||
margin-right: 28rpx;
|
||||
word-break: break-all;
|
||||
line-height: 36rpx;
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
|
||||
&.left {
|
||||
.content {
|
||||
background-color: #ffffff;
|
||||
margin-left: 28rpx;
|
||||
word-break: break-all;
|
||||
line-height: 36rpx;
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.next {
|
||||
width: 100%;
|
||||
height: 20rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.no-connect-box {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
margin: 20rpx 0 50rpx;
|
||||
|
||||
.no-connect {
|
||||
display: inline-block;
|
||||
padding: 0 20rpx;
|
||||
height: 40rpx;
|
||||
background: red;
|
||||
margin: 0 auto;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
border-radius: 9rpx;
|
||||
text-align: center;
|
||||
line-height: 40rpx;
|
||||
font-size: 22rpx;
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
|
||||
.chat_text,
|
||||
.chat_img {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.iconfont {
|
||||
font-size: 36rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.chat_img {
|
||||
width: 30%;
|
||||
height: 200rpx;
|
||||
}
|
||||
</style>
|
||||
@@ -1,329 +1,329 @@
|
||||
<template>
|
||||
<view v-if="pageCount === 1 || need" class="fixed-box"
|
||||
:style="[customContainerStyle, {
|
||||
height: containerHeight,
|
||||
backgroundImage: bgUrl ? `url(${bgUrl})` : '',
|
||||
backgroundSize: 'cover'
|
||||
}]">
|
||||
<!-- 中英文切换按钮 -->
|
||||
<view
|
||||
v-if="isLanguageSwitchEnabled && fixBtnShow"
|
||||
class="btn-item common-bg"
|
||||
@click="toggleLanguage"
|
||||
>
|
||||
<text>{{ currentLangDisplayName }}</text>
|
||||
</view>
|
||||
<!-- 微信官方客服按钮-->
|
||||
<button
|
||||
v-if="fixBtnShow && hasValidKefuConfig && isWeappOfficialKefu"
|
||||
class="btn-item common-bg"
|
||||
open-type="contact"
|
||||
>
|
||||
<text class="icox icox-kefu" v-if="!kefuimg"></text>
|
||||
</button>
|
||||
|
||||
<!-- 其他类型客服按钮(智能客服、企业微信等)-->
|
||||
<view
|
||||
v-if="fixBtnShow && hasValidKefuConfig && !isWeappOfficialKefu && !showWeappSystemKefu"
|
||||
class="btn-item common-bg"
|
||||
@click="handleUnifiedKefuClick"
|
||||
>
|
||||
<image
|
||||
v-if="currentKefuImg"
|
||||
:src="currentKefuImg"
|
||||
mode="aspectFill"
|
||||
class="kefu-img"
|
||||
show-menu-by-longpress></image>
|
||||
<text class="ai-icon" v-if="isAIKefu && !currentKefuImg">🤖</text>
|
||||
<text class="ai-icon" v-if="isWxworkKefu && !currentKefuImg">💬</text>
|
||||
<text class="ai-icon" v-if="!isAIKefu && !isWxworkKefu && !currentKefuImg">👤</text>
|
||||
</view>
|
||||
|
||||
<!-- 智能客服按钮(当同时显示小程序系统客服时)-->
|
||||
<view
|
||||
v-if="fixBtnShow && hasValidKefuConfig && !isWeappOfficialKefu && showWeappSystemKefu"
|
||||
class="btn-item common-bg"
|
||||
@click="handleUnifiedKefuClick"
|
||||
>
|
||||
<image
|
||||
v-if="currentKefuImg"
|
||||
:src="currentKefuImg"
|
||||
mode="aspectFill"
|
||||
class="kefu-img"
|
||||
show-menu-by-longpress></image>
|
||||
<text class="ai-icon" v-if="isAIKefu && !currentKefuImg">🤖</text>
|
||||
<text class="ai-icon" v-if="isWxworkKefu && !currentKefuImg">💬</text>
|
||||
<text class="ai-icon" v-if="!isAIKefu && !isWxworkKefu && !currentKefuImg">👤</text>
|
||||
</view>
|
||||
|
||||
<!-- 小程序系统客服按钮 -->
|
||||
<button
|
||||
v-if="fixBtnShow && hasValidKefuConfig && showWeappSystemKefu"
|
||||
class="btn-item common-bg"
|
||||
open-type="contact"
|
||||
>
|
||||
<text class="icox icox-kefu" v-if="!kefuimg"></text>
|
||||
</button>
|
||||
|
||||
|
||||
|
||||
<!-- 电话按钮 -->
|
||||
<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>
|
||||
|
||||
<script>
|
||||
import { createCustomerService } from '@/common/js/customer-service.js';
|
||||
|
||||
export default {
|
||||
name: 'hover-nav',
|
||||
props: {
|
||||
need: { type: Boolean, default: false }
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
pageCount: 0,
|
||||
fixBtnShow: true,
|
||||
shopInfo: null,
|
||||
currentLangIndex: 0,
|
||||
langIndexMap: {},
|
||||
customerService: 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() {
|
||||
const customerService = createCustomerService(this);
|
||||
return customerService.getUnreadCount();
|
||||
},
|
||||
currentKefuImg() {
|
||||
const customerService = createCustomerService(this);
|
||||
return customerService.getKefuButtonIcon();
|
||||
},
|
||||
isWeappOfficialKefu() {
|
||||
const customerService = createCustomerService(this);
|
||||
return customerService.isWeappOfficialKefu();
|
||||
},
|
||||
isAIKefu() {
|
||||
const customerService = createCustomerService(this);
|
||||
return customerService.isAIKefu();
|
||||
},
|
||||
isWxworkKefu() {
|
||||
const customerService = createCustomerService(this);
|
||||
return customerService.isWxworkKefu();
|
||||
},
|
||||
isThirdKefu() {
|
||||
const customerService = createCustomerService(this);
|
||||
return customerService.isThirdKefu();
|
||||
},
|
||||
showWeappSystemKefu() {
|
||||
const customerService = createCustomerService(this);
|
||||
return customerService.shouldShowExtraWeappSystemKefu();
|
||||
},
|
||||
hasValidKefuConfig() {
|
||||
const customerService = createCustomerService(this);
|
||||
return customerService.hasValidKefuConfig();
|
||||
},
|
||||
//根据显示的按钮数量动态计算容器高度
|
||||
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',
|
||||
success: (e) => {
|
||||
this.shopInfo = e.data;
|
||||
},
|
||||
fail: () => {
|
||||
console.warn($lang('common.hover-nav.l192.t0'));
|
||||
}
|
||||
});
|
||||
// 初始化 customerService 实例
|
||||
this.customerService = createCustomerService(this);
|
||||
},
|
||||
methods: {
|
||||
initLanguage() {
|
||||
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;
|
||||
}
|
||||
},
|
||||
|
||||
call() {
|
||||
this.customerService.makePhoneCallByNumber(this.tel);
|
||||
},
|
||||
|
||||
toggleLanguage() {
|
||||
this.currentLangIndex = this.currentLangIndex === 0 ? 1 : 0;
|
||||
const targetLang = this.langIndexMap[this.currentLangIndex];
|
||||
|
||||
uni.setStorageSync("lang", targetLang);
|
||||
|
||||
const pages = getCurrentPages();
|
||||
const currentPage = pages[pages.length - 1];
|
||||
const currentRoute = currentPage.route;
|
||||
|
||||
uni.reLaunch({
|
||||
url: '/' + currentRoute
|
||||
});
|
||||
},
|
||||
|
||||
handleUnifiedKefuClick() {
|
||||
this.customerService.handleUnifiedKefuClick({
|
||||
sendMessageTitle: $lang('common.hover-nav.l239.t0'),
|
||||
sendMessagePath: '/pages/index/index'
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.fixed-box {
|
||||
position: fixed;
|
||||
right: 0rpx;
|
||||
bottom: 240rpx;
|
||||
/* #ifdef H5 */
|
||||
bottom: 320rpx;
|
||||
/* #endif */
|
||||
z-index: 10;
|
||||
border-radius: 120rpx;
|
||||
padding: 20rpx 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
width: 100rpx;
|
||||
box-sizing: border-box;
|
||||
transition: 0.3s;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.btn-item {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
flex-direction: column;
|
||||
line-height: 1;
|
||||
margin: 14rpx 0;
|
||||
transition: 0.1s;
|
||||
color: var(--hover-nav-text-color);
|
||||
border-radius: 50%;
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.common-bg {
|
||||
background-color: var(--hover-nav-bg-color);
|
||||
}
|
||||
|
||||
.btn-item text {
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.iconfont,
|
||||
.icox {
|
||||
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,
|
||||
.icox text {
|
||||
font-size: 36rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.kefu-img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.ai-icon {
|
||||
font-size: 40rpx;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
<template>
|
||||
<view v-if="pageCount === 1 || need" class="fixed-box"
|
||||
:style="[customContainerStyle, {
|
||||
height: containerHeight,
|
||||
backgroundImage: bgUrl ? `url(${bgUrl})` : '',
|
||||
backgroundSize: 'cover'
|
||||
}]">
|
||||
<!-- 中英文切换按钮 -->
|
||||
<view
|
||||
v-if="isLanguageSwitchEnabled && fixBtnShow"
|
||||
class="btn-item common-bg"
|
||||
@click="toggleLanguage"
|
||||
>
|
||||
<text>{{ currentLangDisplayName }}</text>
|
||||
</view>
|
||||
<!-- 微信官方客服按钮-->
|
||||
<button
|
||||
v-if="fixBtnShow && hasValidKefuConfig && isWeappOfficialKefu"
|
||||
class="btn-item common-bg"
|
||||
open-type="contact"
|
||||
>
|
||||
<text class="icox icox-kefu" v-if="!kefuimg"></text>
|
||||
</button>
|
||||
|
||||
<!-- 其他类型客服按钮(智能客服、企业微信等)-->
|
||||
<view
|
||||
v-if="fixBtnShow && hasValidKefuConfig && !isWeappOfficialKefu && !showWeappSystemKefu"
|
||||
class="btn-item common-bg"
|
||||
@click="handleUnifiedKefuClick"
|
||||
>
|
||||
<image
|
||||
v-if="currentKefuImg"
|
||||
:src="currentKefuImg"
|
||||
mode="aspectFill"
|
||||
class="kefu-img"
|
||||
show-menu-by-longpress></image>
|
||||
<text class="ai-icon" v-if="isAIKefu && !currentKefuImg">🤖</text>
|
||||
<text class="ai-icon" v-if="isWxworkKefu && !currentKefuImg">💬</text>
|
||||
<text class="ai-icon" v-if="!isAIKefu && !isWxworkKefu && !currentKefuImg">👤</text>
|
||||
</view>
|
||||
|
||||
<!-- 智能客服按钮(当同时显示小程序系统客服时)-->
|
||||
<view
|
||||
v-if="fixBtnShow && hasValidKefuConfig && !isWeappOfficialKefu && showWeappSystemKefu"
|
||||
class="btn-item common-bg"
|
||||
@click="handleUnifiedKefuClick"
|
||||
>
|
||||
<image
|
||||
v-if="currentKefuImg"
|
||||
:src="currentKefuImg"
|
||||
mode="aspectFill"
|
||||
class="kefu-img"
|
||||
show-menu-by-longpress></image>
|
||||
<text class="ai-icon" v-if="isAIKefu && !currentKefuImg">🤖</text>
|
||||
<text class="ai-icon" v-if="isWxworkKefu && !currentKefuImg">💬</text>
|
||||
<text class="ai-icon" v-if="!isAIKefu && !isWxworkKefu && !currentKefuImg">👤</text>
|
||||
</view>
|
||||
|
||||
<!-- 小程序系统客服按钮 -->
|
||||
<button
|
||||
v-if="fixBtnShow && hasValidKefuConfig && showWeappSystemKefu"
|
||||
class="btn-item common-bg"
|
||||
open-type="contact"
|
||||
>
|
||||
<text class="icox icox-kefu" v-if="!kefuimg"></text>
|
||||
</button>
|
||||
|
||||
|
||||
|
||||
<!-- 电话按钮 -->
|
||||
<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>
|
||||
|
||||
<script>
|
||||
import { createCustomerService } from '@/common/js/customer-service.js';
|
||||
|
||||
export default {
|
||||
name: 'hover-nav',
|
||||
props: {
|
||||
need: { type: Boolean, default: false }
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
pageCount: 0,
|
||||
fixBtnShow: true,
|
||||
shopInfo: null,
|
||||
currentLangIndex: 0,
|
||||
langIndexMap: {},
|
||||
customerService: 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() {
|
||||
const customerService = createCustomerService(this);
|
||||
return customerService.getUnreadCount();
|
||||
},
|
||||
currentKefuImg() {
|
||||
const customerService = createCustomerService(this);
|
||||
return customerService.getKefuButtonIcon();
|
||||
},
|
||||
isWeappOfficialKefu() {
|
||||
const customerService = createCustomerService(this);
|
||||
return customerService.isWeappOfficialKefu();
|
||||
},
|
||||
isAIKefu() {
|
||||
const customerService = createCustomerService(this);
|
||||
return customerService.isAIKefu();
|
||||
},
|
||||
isWxworkKefu() {
|
||||
const customerService = createCustomerService(this);
|
||||
return customerService.isWxworkKefu();
|
||||
},
|
||||
isThirdKefu() {
|
||||
const customerService = createCustomerService(this);
|
||||
return customerService.isThirdKefu();
|
||||
},
|
||||
showWeappSystemKefu() {
|
||||
const customerService = createCustomerService(this);
|
||||
return customerService.shouldShowExtraWeappSystemKefu();
|
||||
},
|
||||
hasValidKefuConfig() {
|
||||
const customerService = createCustomerService(this);
|
||||
return customerService.hasValidKefuConfig();
|
||||
},
|
||||
//根据显示的按钮数量动态计算容器高度
|
||||
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',
|
||||
success: (e) => {
|
||||
this.shopInfo = e.data;
|
||||
},
|
||||
fail: () => {
|
||||
console.warn('未获取到 shopInfo,使用默认设置');
|
||||
}
|
||||
});
|
||||
// 初始化 customerService 实例
|
||||
this.customerService = createCustomerService(this);
|
||||
},
|
||||
methods: {
|
||||
initLanguage() {
|
||||
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;
|
||||
}
|
||||
},
|
||||
|
||||
call() {
|
||||
this.customerService.makePhoneCallByNumber(this.tel);
|
||||
},
|
||||
|
||||
toggleLanguage() {
|
||||
this.currentLangIndex = this.currentLangIndex === 0 ? 1 : 0;
|
||||
const targetLang = this.langIndexMap[this.currentLangIndex];
|
||||
|
||||
uni.setStorageSync("lang", targetLang);
|
||||
|
||||
const pages = getCurrentPages();
|
||||
const currentPage = pages[pages.length - 1];
|
||||
const currentRoute = currentPage.route;
|
||||
|
||||
uni.reLaunch({
|
||||
url: '/' + currentRoute
|
||||
});
|
||||
},
|
||||
|
||||
handleUnifiedKefuClick() {
|
||||
this.customerService.handleUnifiedKefuClick({
|
||||
sendMessageTitle: '来自悬浮按钮的咨询',
|
||||
sendMessagePath: '/pages/index/index'
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.fixed-box {
|
||||
position: fixed;
|
||||
right: 0rpx;
|
||||
bottom: 240rpx;
|
||||
/* #ifdef H5 */
|
||||
bottom: 320rpx;
|
||||
/* #endif */
|
||||
z-index: 10;
|
||||
border-radius: 120rpx;
|
||||
padding: 20rpx 0;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
width: 100rpx;
|
||||
box-sizing: border-box;
|
||||
transition: 0.3s;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.btn-item {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
text-align: center;
|
||||
flex-direction: column;
|
||||
line-height: 1;
|
||||
margin: 14rpx 0;
|
||||
transition: 0.1s;
|
||||
color: var(--hover-nav-text-color);
|
||||
border-radius: 50%;
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.common-bg {
|
||||
background-color: var(--hover-nav-bg-color);
|
||||
}
|
||||
|
||||
.btn-item text {
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.iconfont,
|
||||
.icox {
|
||||
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,
|
||||
.icox text {
|
||||
font-size: 36rpx;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.kefu-img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.ai-icon {
|
||||
font-size: 40rpx;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
</style>
|
||||
@@ -37,7 +37,7 @@ export default {
|
||||
getText() {
|
||||
let self = this;
|
||||
let timeVal = _time_.getFormatTime(self.textVal, self.maxDate);
|
||||
if (timeVal && (timeVal.endsWith($lang('common.l-time.l40.t0')) || timeVal.endsWith($lang('common.l-time.l40.t1')))) {
|
||||
if (timeVal && (timeVal.endsWith('刚刚') || timeVal.endsWith('分钟前'))) {
|
||||
setTimeout(() => {
|
||||
let temp = self.textVal;
|
||||
self.textVal = '';
|
||||
|
||||
@@ -1,161 +1,161 @@
|
||||
Function.prototype.asyAfter = function(afterfn) {
|
||||
var _self = this;
|
||||
return function() {
|
||||
var ret = _self.apply(this, arguments);
|
||||
if (ret === 'next') {
|
||||
return afterfn.apply(this, arguments);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
Date.prototype.pattern = function(fmt) {
|
||||
var o = {
|
||||
"M+": this.getMonth() + 1, //月份
|
||||
"d+": this.getDate(), //日
|
||||
"h+": this.getHours() % 12 == 0 ? 12 : this.getHours() % 12, //小时
|
||||
"H+": this.getHours(), //小时
|
||||
"m+": this.getMinutes(), //分
|
||||
"s+": this.getSeconds(), //秒
|
||||
"q+": Math.floor((this.getMonth() + 3) / 3), //季度
|
||||
"S": this.getMilliseconds() //毫秒
|
||||
};
|
||||
var week = {
|
||||
"0": "\u65e5",
|
||||
"1": "\u4e00",
|
||||
"2": "\u4e8c",
|
||||
"3": "\u4e09",
|
||||
"4": "\u56db",
|
||||
"5": "\u4e94",
|
||||
"6": "\u516d"
|
||||
};
|
||||
if (/(y+)/.test(fmt)) {
|
||||
fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
|
||||
}
|
||||
if (/(E+)/.test(fmt)) {
|
||||
fmt = fmt.replace(RegExp.$1, ((RegExp.$1.length > 1) ? (RegExp.$1.length > 2 ? "\u661f\u671f" : "\u5468") :
|
||||
"") +
|
||||
week[this.getDay() + ""]);
|
||||
}
|
||||
for (var k in o) {
|
||||
if (new RegExp("(" + k + ")").test(fmt)) {
|
||||
fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k])
|
||||
.length)));
|
||||
}
|
||||
}
|
||||
return fmt;
|
||||
}
|
||||
|
||||
const isType = type => (/^\[object\s(.*)\]$/.exec(Object.prototype.toString.call(type)))[1];
|
||||
let Time = function() {};
|
||||
let timeProto = Time.prototype;
|
||||
|
||||
//获取当前时间戳
|
||||
timeProto.getUnix = function() {
|
||||
return new Date().getTime();
|
||||
}
|
||||
|
||||
//获取当天0点0分0秒时间戳
|
||||
timeProto.getTodayUnix = function() {
|
||||
let date = new Date();
|
||||
let myDate = `${date.getFullYear()}/${(date.getMonth() + 1)}/${date.getDate()} 00:00:00`;
|
||||
return new Date(myDate).getTime();
|
||||
}
|
||||
|
||||
//获取今年1月1日0点0分0秒时间戳
|
||||
timeProto.getYearUnix = function() {
|
||||
let date = new Date();
|
||||
date.setMonth(0);
|
||||
date.setDate(1);
|
||||
date.setHours(0);
|
||||
date.setMinutes(0);
|
||||
date.setSeconds(0);
|
||||
date.setMilliseconds(0);
|
||||
return date.getTime();
|
||||
}
|
||||
|
||||
//获取当前时间标准年月日
|
||||
timeProto.getLastDate = function(constTime) {
|
||||
if (!constTime) {
|
||||
return;
|
||||
}
|
||||
let date = new Date(constTime);
|
||||
if (date.pattern) {
|
||||
return date.pattern("yyyy-MM-dd");
|
||||
}
|
||||
|
||||
let month = date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1;
|
||||
let day = date.getDate() < 10 ? '0' + date.getDate() : date.getDate();
|
||||
return date.getFullYear() + '-' + month + '-' + day;
|
||||
}
|
||||
|
||||
const resDateStr = function(timer, constTime) {
|
||||
let _just = function(timer) {
|
||||
|
||||
if (timer <= 0 || Math.floor(timer / 60) <= 0) {
|
||||
return $lang("common.l-time.l40.t0")
|
||||
} else return 'next';
|
||||
}
|
||||
|
||||
let _mm = function(timer) {
|
||||
if (timer < 3600) {
|
||||
return Math.floor(timer / 60) + $lang("common.l-time.l40.t1")
|
||||
} else return 'next';
|
||||
}
|
||||
let _hh = function(timer, constTime) {
|
||||
let today = _time_.getTodayUnix();
|
||||
if (timer >= 3600 && (constTime - today >= 0)) {
|
||||
//可切换显示模式
|
||||
// return "今天 " + new Date(constTime).pattern("HH:mm");
|
||||
return Math.floor(timer / 60 / 60) + $lang("common.l-time.time.l110.t0");
|
||||
} else {
|
||||
return 'next'
|
||||
};
|
||||
}
|
||||
let _dd = function(timer, constTime) {
|
||||
let today = _time_.getTodayUnix();
|
||||
timer = (today - constTime) / 1000;
|
||||
if (timer / 86400 <= 31) {
|
||||
return Math.ceil(timer / 86400) + $lang("common.l-time.time.l119.t0")
|
||||
} else return 'next';
|
||||
}
|
||||
let _dlast = function(timer, constTime) {
|
||||
return _time_.getLastDate(constTime);
|
||||
}
|
||||
|
||||
let dateFilter = _just.asyAfter(_mm).asyAfter(_hh).asyAfter(_dd).asyAfter(_dlast);
|
||||
return dateFilter(timer, constTime);
|
||||
}
|
||||
|
||||
|
||||
//转换时间
|
||||
const reg = new RegExp("-", "g");
|
||||
timeProto.getFormatTime = function(constTime, max) {
|
||||
if (!constTime) {
|
||||
return "";
|
||||
}
|
||||
|
||||
switch (isType(constTime)) {
|
||||
case 'Date':
|
||||
constTime = constTime.getTime();
|
||||
break;
|
||||
case 'String':
|
||||
constTime = constTime.replace(reg, "/");
|
||||
default:
|
||||
constTime = new Date(constTime).getTime();
|
||||
break;
|
||||
}
|
||||
|
||||
let now = this.getUnix();
|
||||
let year = this.getYearUnix();
|
||||
let timer = (now - constTime) / 1000;
|
||||
if (constTime > now && max) {
|
||||
return this.getLastDate(constTime);
|
||||
}
|
||||
|
||||
let _t = this;
|
||||
return resDateStr(timer, constTime);
|
||||
}
|
||||
|
||||
const _time_ = new Time();
|
||||
export default _time_;
|
||||
Function.prototype.asyAfter = function(afterfn) {
|
||||
var _self = this;
|
||||
return function() {
|
||||
var ret = _self.apply(this, arguments);
|
||||
if (ret === 'next') {
|
||||
return afterfn.apply(this, arguments);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
Date.prototype.pattern = function(fmt) {
|
||||
var o = {
|
||||
"M+": this.getMonth() + 1, //月份
|
||||
"d+": this.getDate(), //日
|
||||
"h+": this.getHours() % 12 == 0 ? 12 : this.getHours() % 12, //小时
|
||||
"H+": this.getHours(), //小时
|
||||
"m+": this.getMinutes(), //分
|
||||
"s+": this.getSeconds(), //秒
|
||||
"q+": Math.floor((this.getMonth() + 3) / 3), //季度
|
||||
"S": this.getMilliseconds() //毫秒
|
||||
};
|
||||
var week = {
|
||||
"0": "\u65e5",
|
||||
"1": "\u4e00",
|
||||
"2": "\u4e8c",
|
||||
"3": "\u4e09",
|
||||
"4": "\u56db",
|
||||
"5": "\u4e94",
|
||||
"6": "\u516d"
|
||||
};
|
||||
if (/(y+)/.test(fmt)) {
|
||||
fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
|
||||
}
|
||||
if (/(E+)/.test(fmt)) {
|
||||
fmt = fmt.replace(RegExp.$1, ((RegExp.$1.length > 1) ? (RegExp.$1.length > 2 ? "\u661f\u671f" : "\u5468") :
|
||||
"") +
|
||||
week[this.getDay() + ""]);
|
||||
}
|
||||
for (var k in o) {
|
||||
if (new RegExp("(" + k + ")").test(fmt)) {
|
||||
fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k])
|
||||
.length)));
|
||||
}
|
||||
}
|
||||
return fmt;
|
||||
}
|
||||
|
||||
const isType = type => (/^\[object\s(.*)\]$/.exec(Object.prototype.toString.call(type)))[1];
|
||||
let Time = function() {};
|
||||
let timeProto = Time.prototype;
|
||||
|
||||
//获取当前时间戳
|
||||
timeProto.getUnix = function() {
|
||||
return new Date().getTime();
|
||||
}
|
||||
|
||||
//获取当天0点0分0秒时间戳
|
||||
timeProto.getTodayUnix = function() {
|
||||
let date = new Date();
|
||||
let myDate = `${date.getFullYear()}/${(date.getMonth() + 1)}/${date.getDate()} 00:00:00`;
|
||||
return new Date(myDate).getTime();
|
||||
}
|
||||
|
||||
//获取今年1月1日0点0分0秒时间戳
|
||||
timeProto.getYearUnix = function() {
|
||||
let date = new Date();
|
||||
date.setMonth(0);
|
||||
date.setDate(1);
|
||||
date.setHours(0);
|
||||
date.setMinutes(0);
|
||||
date.setSeconds(0);
|
||||
date.setMilliseconds(0);
|
||||
return date.getTime();
|
||||
}
|
||||
|
||||
//获取当前时间标准年月日
|
||||
timeProto.getLastDate = function(constTime) {
|
||||
if (!constTime) {
|
||||
return;
|
||||
}
|
||||
let date = new Date(constTime);
|
||||
if (date.pattern) {
|
||||
return date.pattern("yyyy-MM-dd");
|
||||
}
|
||||
|
||||
let month = date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1;
|
||||
let day = date.getDate() < 10 ? '0' + date.getDate() : date.getDate();
|
||||
return date.getFullYear() + '-' + month + '-' + day;
|
||||
}
|
||||
|
||||
const resDateStr = function(timer, constTime) {
|
||||
let _just = function(timer) {
|
||||
|
||||
if (timer <= 0 || Math.floor(timer / 60) <= 0) {
|
||||
return "刚刚"
|
||||
} else return 'next';
|
||||
}
|
||||
|
||||
let _mm = function(timer) {
|
||||
if (timer < 3600) {
|
||||
return Math.floor(timer / 60) + "分钟前"
|
||||
} else return 'next';
|
||||
}
|
||||
let _hh = function(timer, constTime) {
|
||||
let today = _time_.getTodayUnix();
|
||||
if (timer >= 3600 && (constTime - today >= 0)) {
|
||||
//可切换显示模式
|
||||
// return "今天 " + new Date(constTime).pattern("HH:mm");
|
||||
return Math.floor(timer / 60 / 60) + "小时前";
|
||||
} else {
|
||||
return 'next'
|
||||
};
|
||||
}
|
||||
let _dd = function(timer, constTime) {
|
||||
let today = _time_.getTodayUnix();
|
||||
timer = (today - constTime) / 1000;
|
||||
if (timer / 86400 <= 31) {
|
||||
return Math.ceil(timer / 86400) + "天前"
|
||||
} else return 'next';
|
||||
}
|
||||
let _dlast = function(timer, constTime) {
|
||||
return _time_.getLastDate(constTime);
|
||||
}
|
||||
|
||||
let dateFilter = _just.asyAfter(_mm).asyAfter(_hh).asyAfter(_dd).asyAfter(_dlast);
|
||||
return dateFilter(timer, constTime);
|
||||
}
|
||||
|
||||
|
||||
//转换时间
|
||||
const reg = new RegExp("-", "g");
|
||||
timeProto.getFormatTime = function(constTime, max) {
|
||||
if (!constTime) {
|
||||
return "";
|
||||
}
|
||||
|
||||
switch (isType(constTime)) {
|
||||
case 'Date':
|
||||
constTime = constTime.getTime();
|
||||
break;
|
||||
case 'String':
|
||||
constTime = constTime.replace(reg, "/");
|
||||
default:
|
||||
constTime = new Date(constTime).getTime();
|
||||
break;
|
||||
}
|
||||
|
||||
let now = this.getUnix();
|
||||
let year = this.getYearUnix();
|
||||
let timer = (now - constTime) / 1000;
|
||||
if (constTime > now && max) {
|
||||
return this.getLastDate(constTime);
|
||||
}
|
||||
|
||||
let _t = this;
|
||||
return resDateStr(timer, constTime);
|
||||
}
|
||||
|
||||
const _time_ = new Time();
|
||||
export default _time_;
|
||||
|
||||
@@ -3,15 +3,15 @@
|
||||
const GlobalOption = {
|
||||
down: {
|
||||
// 其他down的配置参数也可以写,这里只展示了常用的配置:
|
||||
textInOffset: $lang('common.mescroll.mescroll-uni-option.l6.t0'), // 下拉的距离在offset范围内的提示文本
|
||||
textOutOffset: $lang('common.mescroll.mescroll-uni-option.l7.t0'), // 下拉的距离大于offset范围的提示文本
|
||||
textLoading: $lang('common.mescroll.mescroll-uni-option.l8.t0'), // 加载中的提示文本
|
||||
textInOffset: '下拉刷新', // 下拉的距离在offset范围内的提示文本
|
||||
textOutOffset: '释放更新', // 下拉的距离大于offset范围的提示文本
|
||||
textLoading: '加载中 ...', // 加载中的提示文本
|
||||
offset: 80, // 在列表顶部,下拉大于80px,松手即可触发下拉刷新的回调
|
||||
native: false // 是否使用系统自带的下拉刷新; 默认false; 仅在mescroll-body生效 (值为true时,还需在pages配置enablePullDownRefresh:true;详请参考mescroll-native的案例)
|
||||
},
|
||||
up: {
|
||||
// 其他up的配置参数也可以写,这里只展示了常用的配置:
|
||||
textLoading: $lang('common.mescroll.mescroll-uni-option.l8.t0'), // 加载中的提示文本
|
||||
textLoading: '加载中 ...', // 加载中的提示文本
|
||||
textNoMore: '', // 没有更多数据的提示文本
|
||||
// textNoMore: '— 我是有底线的 —', // 没有更多数据的提示文本
|
||||
offset: 80, // 距底部多远时,触发upCallback
|
||||
@@ -27,7 +27,7 @@ const GlobalOption = {
|
||||
empty: {
|
||||
use: true, // 是否显示空布局
|
||||
icon: "https://www.mescroll.com/img/mescroll-empty.png?v=1", // 图标路径 (建议放入static目录, 如 /static/img/mescroll-empty.png )
|
||||
tip: $lang('common.mescroll.mescroll-uni-option.l30.t0') // 提示
|
||||
tip: '~ 暂无相关数据 ~' // 提示
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,158 +1,158 @@
|
||||
<template>
|
||||
<!-- top="xxx"下拉布局往下偏移,防止被悬浮菜单遮住 -->
|
||||
<!-- 鸿蒙下不要用 v-if="isInit",会导致内层 mescroll 创建被严重延迟,先 onReady 后 inner created -->
|
||||
<mescroll
|
||||
:top="top"
|
||||
:down="downOption"
|
||||
:fixed="fixed"
|
||||
:topbar="topbar"
|
||||
:background="background"
|
||||
:paddingBoth="paddingBoth"
|
||||
@down="downCallback"
|
||||
:up="upOption"
|
||||
@up="upCallback"
|
||||
@emptyclick="emptyClick"
|
||||
@init="mescrollInit"
|
||||
>
|
||||
<!-- 数据列表 - 鸿蒙下用 key 强制重建 slot DOM,绕过 ArkUI slot 响应式失效问题 -->
|
||||
<view :key="listSlotKey">
|
||||
<slot name="list"></slot>
|
||||
</view>
|
||||
</mescroll>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Mescroll from './mescroll-uni.vue';
|
||||
export default {
|
||||
components: {
|
||||
Mescroll
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
mescroll: null, //mescroll实例对象
|
||||
downOption: {
|
||||
auto: false // 不自动加载
|
||||
},
|
||||
upOption: {
|
||||
auto: false, // 不自动加载
|
||||
page: {
|
||||
num: 0, // 当前页码,默认0,回调之前会加1,即callback(page)会从1开始
|
||||
size: 10 // 每页数据的数量
|
||||
},
|
||||
noMoreSize: 2, //如果列表已无数据,可设置列表的总数量要大于半页才显示无更多数据;避免列表数据过少(比如只有一条数据),显示无更多数据会不好看; 默认5
|
||||
empty: {
|
||||
tip: $lang('common.mescroll.my-list-mescroll.l44.t0'), // 提示
|
||||
btnText: $lang('common.mescroll.my-list-mescroll.l45.t0')
|
||||
},
|
||||
onScroll: true
|
||||
},
|
||||
scrollY: 0,
|
||||
// 鸿蒙下直接初始化为 true,避免 v-if 阻塞子组件创建导致 onReady 先于 inner mounted
|
||||
isInit: true,
|
||||
// 鸿蒙下用来强制重建 slot DOM 的 key
|
||||
listSlotKey: 0
|
||||
};
|
||||
},
|
||||
props: {
|
||||
top: [String, Number],
|
||||
size: [String, Number],
|
||||
fixed: {
|
||||
// 是否通过fixed固定mescroll的高度, 默认true
|
||||
type: Boolean,
|
||||
default() {
|
||||
return true;
|
||||
}
|
||||
},
|
||||
background: String,
|
||||
topbar: Boolean,
|
||||
paddingBoth: {
|
||||
type: [String, Number],
|
||||
default() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
if (this.size) this.upOption.page.size = this.size;
|
||||
// 鸿蒙下 ArkUI 对 slot 内 Vue 响应式更新失效,数据加载后强制重建 slot DOM
|
||||
// 通过把 listSlotKey 自增,使 :key 变化,触发整个 slot 子树销毁重建
|
||||
const oldUpCallback = this.upCallback;
|
||||
this.upCallback = function() {
|
||||
const ret = oldUpCallback.apply(this, arguments);
|
||||
// 数据回来后 200ms 自增 key,强制 slot DOM 重建
|
||||
setTimeout(() => {
|
||||
this.listSlotKey = (this.listSlotKey || 0) + 1;
|
||||
}, 200);
|
||||
return ret;
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
// 统一在 watcher 里触发首屏 resetUpScroll,这里不做任何事情
|
||||
// (H5/微信下 mescroll 已在 mounted 前就绪;鸿蒙下 mounted 时机不可靠,所以都不在这里调)
|
||||
},
|
||||
watch: {
|
||||
// 统一在 mescroll 实例就绪时触发首屏 resetUpScroll
|
||||
// H5/微信下 inner 的 $emit('init') 同步触发,watcher 在 mounted 之前就 fire,正常加载
|
||||
// 鸿蒙下 $emit 被延迟到 onReady 之后,watcher 在那时 fire,也能加载
|
||||
mescroll: {
|
||||
immediate: false,
|
||||
handler(newVal) {
|
||||
if (newVal && typeof newVal.resetUpScroll === 'function') {
|
||||
// 避免重复触发
|
||||
if (this._autoLoadTriggered) return;
|
||||
this._autoLoadTriggered = true;
|
||||
// 等下一个 tick,确保 outer 已挂载、meScroll 内部 setBodyHeight 等已执行
|
||||
setTimeout(() => {
|
||||
if (this.mescroll && typeof this.mescroll.resetUpScroll === 'function') {
|
||||
this.mescroll.resetUpScroll();
|
||||
this.listenRefresh();
|
||||
}
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// mescroll组件初始化的回调,可获取到mescroll对象
|
||||
mescrollInit(mescroll) {
|
||||
this.mescroll = mescroll;
|
||||
},
|
||||
/*下拉刷新的回调 */
|
||||
downCallback() {
|
||||
// 这里加载你想下拉刷新的数据, 比如刷新轮播数据
|
||||
// loadSwiper();
|
||||
// 下拉刷新的回调,默认重置上拉加载列表为第一页 (自动执行 mescroll.num=1, 再触发upCallback方法 )
|
||||
this.mescroll.resetUpScroll();
|
||||
this.listenRefresh();
|
||||
},
|
||||
/*上拉加载的回调: mescroll携带page的参数, 其中num:当前页 从1开始, size:每页数据条数,默认10 */
|
||||
upCallback() {
|
||||
//联网加载数据
|
||||
this.$emit('getData', this.mescroll);
|
||||
},
|
||||
//点击空布局按钮的回调
|
||||
emptyClick() {
|
||||
this.$emit('emptytap', this.mescroll);
|
||||
},
|
||||
//刷新
|
||||
refresh() {
|
||||
this.mescroll.resetUpScroll();
|
||||
this.listenRefresh();
|
||||
},
|
||||
myScrollTo(y, t) {
|
||||
this.mescroll.myScrollTo(y, t);
|
||||
},
|
||||
listenRefresh() {
|
||||
this.$emit('listenRefresh', true);
|
||||
},
|
||||
/**
|
||||
* 主动重建 slot DOM。
|
||||
* 鸿蒙下通过 :key 变化重建的 .goods-item 元素 @click 事件绑定会丢失,
|
||||
* 通过自增 listSlotKey 走 slot 重建路径可恢复事件绑定。
|
||||
*/
|
||||
forceSlotRebuild() {
|
||||
this.listSlotKey = (this.listSlotKey || 0) + 1;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<!-- top="xxx"下拉布局往下偏移,防止被悬浮菜单遮住 -->
|
||||
<!-- 鸿蒙下不要用 v-if="isInit",会导致内层 mescroll 创建被严重延迟,先 onReady 后 inner created -->
|
||||
<mescroll
|
||||
:top="top"
|
||||
:down="downOption"
|
||||
:fixed="fixed"
|
||||
:topbar="topbar"
|
||||
:background="background"
|
||||
:paddingBoth="paddingBoth"
|
||||
@down="downCallback"
|
||||
:up="upOption"
|
||||
@up="upCallback"
|
||||
@emptyclick="emptyClick"
|
||||
@init="mescrollInit"
|
||||
>
|
||||
<!-- 数据列表 - 鸿蒙下用 key 强制重建 slot DOM,绕过 ArkUI slot 响应式失效问题 -->
|
||||
<view :key="listSlotKey">
|
||||
<slot name="list"></slot>
|
||||
</view>
|
||||
</mescroll>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Mescroll from './mescroll-uni.vue';
|
||||
export default {
|
||||
components: {
|
||||
Mescroll
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
mescroll: null, //mescroll实例对象
|
||||
downOption: {
|
||||
auto: false // 不自动加载
|
||||
},
|
||||
upOption: {
|
||||
auto: false, // 不自动加载
|
||||
page: {
|
||||
num: 0, // 当前页码,默认0,回调之前会加1,即callback(page)会从1开始
|
||||
size: 10 // 每页数据的数量
|
||||
},
|
||||
noMoreSize: 2, //如果列表已无数据,可设置列表的总数量要大于半页才显示无更多数据;避免列表数据过少(比如只有一条数据),显示无更多数据会不好看; 默认5
|
||||
empty: {
|
||||
tip: '~ 空空如也 ~', // 提示
|
||||
btnText: '去看看'
|
||||
},
|
||||
onScroll: true
|
||||
},
|
||||
scrollY: 0,
|
||||
// 鸿蒙下直接初始化为 true,避免 v-if 阻塞子组件创建导致 onReady 先于 inner mounted
|
||||
isInit: true,
|
||||
// 鸿蒙下用来强制重建 slot DOM 的 key
|
||||
listSlotKey: 0
|
||||
};
|
||||
},
|
||||
props: {
|
||||
top: [String, Number],
|
||||
size: [String, Number],
|
||||
fixed: {
|
||||
// 是否通过fixed固定mescroll的高度, 默认true
|
||||
type: Boolean,
|
||||
default() {
|
||||
return true;
|
||||
}
|
||||
},
|
||||
background: String,
|
||||
topbar: Boolean,
|
||||
paddingBoth: {
|
||||
type: [String, Number],
|
||||
default() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {
|
||||
if (this.size) this.upOption.page.size = this.size;
|
||||
// 鸿蒙下 ArkUI 对 slot 内 Vue 响应式更新失效,数据加载后强制重建 slot DOM
|
||||
// 通过把 listSlotKey 自增,使 :key 变化,触发整个 slot 子树销毁重建
|
||||
const oldUpCallback = this.upCallback;
|
||||
this.upCallback = function() {
|
||||
const ret = oldUpCallback.apply(this, arguments);
|
||||
// 数据回来后 200ms 自增 key,强制 slot DOM 重建
|
||||
setTimeout(() => {
|
||||
this.listSlotKey = (this.listSlotKey || 0) + 1;
|
||||
}, 200);
|
||||
return ret;
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
// 统一在 watcher 里触发首屏 resetUpScroll,这里不做任何事情
|
||||
// (H5/微信下 mescroll 已在 mounted 前就绪;鸿蒙下 mounted 时机不可靠,所以都不在这里调)
|
||||
},
|
||||
watch: {
|
||||
// 统一在 mescroll 实例就绪时触发首屏 resetUpScroll
|
||||
// H5/微信下 inner 的 $emit('init') 同步触发,watcher 在 mounted 之前就 fire,正常加载
|
||||
// 鸿蒙下 $emit 被延迟到 onReady 之后,watcher 在那时 fire,也能加载
|
||||
mescroll: {
|
||||
immediate: false,
|
||||
handler(newVal) {
|
||||
if (newVal && typeof newVal.resetUpScroll === 'function') {
|
||||
// 避免重复触发
|
||||
if (this._autoLoadTriggered) return;
|
||||
this._autoLoadTriggered = true;
|
||||
// 等下一个 tick,确保 outer 已挂载、meScroll 内部 setBodyHeight 等已执行
|
||||
setTimeout(() => {
|
||||
if (this.mescroll && typeof this.mescroll.resetUpScroll === 'function') {
|
||||
this.mescroll.resetUpScroll();
|
||||
this.listenRefresh();
|
||||
}
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// mescroll组件初始化的回调,可获取到mescroll对象
|
||||
mescrollInit(mescroll) {
|
||||
this.mescroll = mescroll;
|
||||
},
|
||||
/*下拉刷新的回调 */
|
||||
downCallback() {
|
||||
// 这里加载你想下拉刷新的数据, 比如刷新轮播数据
|
||||
// loadSwiper();
|
||||
// 下拉刷新的回调,默认重置上拉加载列表为第一页 (自动执行 mescroll.num=1, 再触发upCallback方法 )
|
||||
this.mescroll.resetUpScroll();
|
||||
this.listenRefresh();
|
||||
},
|
||||
/*上拉加载的回调: mescroll携带page的参数, 其中num:当前页 从1开始, size:每页数据条数,默认10 */
|
||||
upCallback() {
|
||||
//联网加载数据
|
||||
this.$emit('getData', this.mescroll);
|
||||
},
|
||||
//点击空布局按钮的回调
|
||||
emptyClick() {
|
||||
this.$emit('emptytap', this.mescroll);
|
||||
},
|
||||
//刷新
|
||||
refresh() {
|
||||
this.mescroll.resetUpScroll();
|
||||
this.listenRefresh();
|
||||
},
|
||||
myScrollTo(y, t) {
|
||||
this.mescroll.myScrollTo(y, t);
|
||||
},
|
||||
listenRefresh() {
|
||||
this.$emit('listenRefresh', true);
|
||||
},
|
||||
/**
|
||||
* 主动重建 slot DOM。
|
||||
* 鸿蒙下通过 :key 变化重建的 .goods-item 元素 @click 事件绑定会丢失,
|
||||
* 通过自增 listSlotKey 走 slot 重建路径可恢复事件绑定。
|
||||
*/
|
||||
forceSlotRebuild() {
|
||||
this.listSlotKey = (this.listSlotKey || 0) + 1;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -1,142 +1,142 @@
|
||||
<template>
|
||||
<view class="message">
|
||||
<view class="goods-item" v-if="goodsInfo.goods_name || goodsInfo.en_goods_name">
|
||||
<image :src="$util.img(goodsInfo.sku_image)" mode="aspectFill" show-menu-by-longpress></image>
|
||||
<view class="goods-info">
|
||||
<view class="goods-name">{{ goodsInfo.sku_name ? goodsInfo.sku_name : (isEnEnv ? goodsInfo.en_goods_name : goodsInfo.goods_name) }}</view>
|
||||
<view class="goods-bottom">
|
||||
<view class="goods-price">
|
||||
<text class="goods-price-sign color-base-text">¥</text>
|
||||
<text class="color-base-text">{{ goodsInfo.price }}</text>
|
||||
</view>
|
||||
<view class="goods-option font-size-goods-tag disabled">{{ $lang("common.ns-chat.ns-chat-goods.l12.t0") }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="goods-item" v-else-if="goodsDetail">
|
||||
<image :src="$util.img(goodsDetail.sku_image)" mode="aspectFill" show-menu-by-longpress></image>
|
||||
<view class="goods-info">
|
||||
<view class="goods-name">{{ goodsDetail.sku_name ? goodsDetail.sku_name : (isEnEnv ? goodsDetail.en_goods_name : goodsDetail.goods_name) }}</view>
|
||||
<view class="goods-bottom">
|
||||
<view class="goods-price">
|
||||
<text class="goods-price-sign color-base-text">¥</text>
|
||||
<text class="color-base-text">{{ goodsDetail.price }}</text>
|
||||
</view>
|
||||
<view class="goods-option font-size-goods-tag color-base-bg" @click="sendMsg('goods')">{{ $lang("common.ns-chat.ns-chat-goods.l25.t0") }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'ns-chat-goods',
|
||||
props: {
|
||||
skuId: {
|
||||
type: [Number, String]
|
||||
},
|
||||
goodsDetail: {
|
||||
type: [Object]
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
goodsInfo: {}
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.getGoodsInfo();
|
||||
},
|
||||
methods: {
|
||||
getGoodsInfo() {
|
||||
this.$api.sendRequest({
|
||||
url: '/api/goodssku/detail',
|
||||
data: {
|
||||
sku_id: this.skuId
|
||||
},
|
||||
success: res => {
|
||||
if (res.code >= 0) {
|
||||
this.goodsInfo = res.data.goods_sku_detail;
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
sendMsg() {
|
||||
this.$emit('sendMsg', 'goods');
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.message {
|
||||
padding: 13rpx 20rpx;
|
||||
box-sizing: border-box;
|
||||
width: 100vw;
|
||||
position: relative;
|
||||
.goods-item {
|
||||
width: 100%;
|
||||
height: 220rpx;
|
||||
|
||||
background: #ffffff;
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-radius: 20rpx;
|
||||
margin: 0 auto;
|
||||
padding: $padding;
|
||||
box-sizing: border-box;
|
||||
image {
|
||||
width: 180rpx;
|
||||
height: 180rpx;
|
||||
min-width: 180rpx;
|
||||
}
|
||||
.goods-info {
|
||||
width: 100%;
|
||||
height: 180rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
padding-left: 20rpx;
|
||||
box-sizing: border-box;
|
||||
.goods-name {
|
||||
width: 100%;
|
||||
line-height: 1.4;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
overflow: hidden;
|
||||
}
|
||||
.goods-bottom {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-end;
|
||||
text {
|
||||
line-height: 1;
|
||||
}
|
||||
.goods-price {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
padding-bottom: 10rpx;
|
||||
font-weight: 500;
|
||||
.goods-price-sign {
|
||||
font-size: $font-size-activity-tag;
|
||||
}
|
||||
}
|
||||
.goods-option {
|
||||
width: 150rpx;
|
||||
height: 50rpx;
|
||||
line-height: 50rpx;
|
||||
text-align: center;
|
||||
border-radius: $border-radius;
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
}
|
||||
.disabled {
|
||||
background: #e5e5e5;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<template>
|
||||
<view class="message">
|
||||
<view class="goods-item" v-if="goodsInfo.goods_name || goodsInfo.en_goods_name">
|
||||
<image :src="$util.img(goodsInfo.sku_image)" mode="aspectFill" show-menu-by-longpress></image>
|
||||
<view class="goods-info">
|
||||
<view class="goods-name">{{ goodsInfo.sku_name ? goodsInfo.sku_name : (isEnEnv ? goodsInfo.en_goods_name : goodsInfo.goods_name) }}</view>
|
||||
<view class="goods-bottom">
|
||||
<view class="goods-price">
|
||||
<text class="goods-price-sign color-base-text">¥</text>
|
||||
<text class="color-base-text">{{ goodsInfo.price }}</text>
|
||||
</view>
|
||||
<view class="goods-option font-size-goods-tag disabled">已发送</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="goods-item" v-else-if="goodsDetail">
|
||||
<image :src="$util.img(goodsDetail.sku_image)" mode="aspectFill" show-menu-by-longpress></image>
|
||||
<view class="goods-info">
|
||||
<view class="goods-name">{{ goodsDetail.sku_name ? goodsDetail.sku_name : (isEnEnv ? goodsDetail.en_goods_name : goodsDetail.goods_name) }}</view>
|
||||
<view class="goods-bottom">
|
||||
<view class="goods-price">
|
||||
<text class="goods-price-sign color-base-text">¥</text>
|
||||
<text class="color-base-text">{{ goodsDetail.price }}</text>
|
||||
</view>
|
||||
<view class="goods-option font-size-goods-tag color-base-bg" @click="sendMsg('goods')">发送</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'ns-chat-goods',
|
||||
props: {
|
||||
skuId: {
|
||||
type: [Number, String]
|
||||
},
|
||||
goodsDetail: {
|
||||
type: [Object]
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
goodsInfo: {}
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.getGoodsInfo();
|
||||
},
|
||||
methods: {
|
||||
getGoodsInfo() {
|
||||
this.$api.sendRequest({
|
||||
url: '/api/goodssku/detail',
|
||||
data: {
|
||||
sku_id: this.skuId
|
||||
},
|
||||
success: res => {
|
||||
if (res.code >= 0) {
|
||||
this.goodsInfo = res.data.goods_sku_detail;
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
sendMsg() {
|
||||
this.$emit('sendMsg', 'goods');
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.message {
|
||||
padding: 13rpx 20rpx;
|
||||
box-sizing: border-box;
|
||||
width: 100vw;
|
||||
position: relative;
|
||||
.goods-item {
|
||||
width: 100%;
|
||||
height: 220rpx;
|
||||
|
||||
background: #ffffff;
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-radius: 20rpx;
|
||||
margin: 0 auto;
|
||||
padding: $padding;
|
||||
box-sizing: border-box;
|
||||
image {
|
||||
width: 180rpx;
|
||||
height: 180rpx;
|
||||
min-width: 180rpx;
|
||||
}
|
||||
.goods-info {
|
||||
width: 100%;
|
||||
height: 180rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
padding-left: 20rpx;
|
||||
box-sizing: border-box;
|
||||
.goods-name {
|
||||
width: 100%;
|
||||
line-height: 1.4;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
overflow: hidden;
|
||||
}
|
||||
.goods-bottom {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-end;
|
||||
text {
|
||||
line-height: 1;
|
||||
}
|
||||
.goods-price {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
padding-bottom: 10rpx;
|
||||
font-weight: 500;
|
||||
.goods-price-sign {
|
||||
font-size: $font-size-activity-tag;
|
||||
}
|
||||
}
|
||||
.goods-option {
|
||||
width: 150rpx;
|
||||
height: 50rpx;
|
||||
line-height: 50rpx;
|
||||
text-align: center;
|
||||
border-radius: $border-radius;
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
}
|
||||
.disabled {
|
||||
background: #e5e5e5;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,149 +1,149 @@
|
||||
<template>
|
||||
<view class="message">
|
||||
<view class="goods-item" v-if="orderdetails">
|
||||
<image :src="$util.img(orderdetails.order_goods ? orderdetails.order_goods[0].sku_image : '')" mode="aspectFill" show-menu-by-longpress></image>
|
||||
<view class="goods-info">
|
||||
<view class="goods-name">{{ orderdetails.order_goods ? orderdetails.order_goods[0].sku_name : '' }}</view>
|
||||
<view class="font-size-goods-tag">{ $lang("common.ns-chat.ns-chat-order.l7.t0") } orderdetails.order_status_name }}</view>
|
||||
<view class="font-size-goods-tag">{ $lang("common.ns-chat.ns-chat-order.l8.t0") } orderdetails.delivery_type_name }}</view>
|
||||
<view class="goods-bottom">
|
||||
<view class="goods-price color-base-text">
|
||||
<text class="goods-price-sign">¥</text>
|
||||
<text>{{ orderdetails.order_goods ? orderdetails.order_goods[0].price : '' }}</text>
|
||||
</view>
|
||||
<view class="goods-option font-size-goods-tag color-base-bg" @click="sendMsg('order')">{{ $lang("common.ns-chat.ns-chat-goods.l25.t0") }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="goods-item" v-else-if="orderInfo">
|
||||
<image :src="$util.img(orderInfo.order_goods ? orderInfo.order_goods[0].sku_image : '')" mode="aspectFill" show-menu-by-longpress></image>
|
||||
<view class="goods-info">
|
||||
<view class="goods-name">{{ orderInfo.order_goods ? orderInfo.order_goods[0].sku_name : '' }}</view>
|
||||
<view class="font-size-goods-tag">{ $lang("common.ns-chat.ns-chat-order.l7.t0") } orderInfo.order_status_name }}</view>
|
||||
<view class="font-size-goods-tag">{ $lang("common.ns-chat.ns-chat-order.l8.t0") } orderInfo.delivery_type_name }}</view>
|
||||
<view class="goods-bottom">
|
||||
<view class="goods-price color-base-text">
|
||||
<text class="goods-price-sign">¥</text>
|
||||
<text>{{ orderInfo.order_goods ? orderInfo.order_goods[0].price : '' }}</text>
|
||||
</view>
|
||||
<view class="goods-option font-size-goods-tag disabled">{{ $lang("common.ns-chat.ns-chat-goods.l12.t0") }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'ns-chat-order',
|
||||
props: {
|
||||
orderId: {
|
||||
type: [Number, String]
|
||||
},
|
||||
isCanSend: Boolean,
|
||||
orderdetails: {
|
||||
type: [Object]
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
orderInfo: {}
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.getGoodsInfo();
|
||||
},
|
||||
methods: {
|
||||
getGoodsInfo() {
|
||||
if (this.orderId) {
|
||||
this.$api.sendRequest({
|
||||
url: '/api/order/detail',
|
||||
data: {
|
||||
order_id: this.orderId
|
||||
},
|
||||
success: res => {
|
||||
if (res.code >= 0) {
|
||||
this.orderInfo = res.data;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
sendMsg() {
|
||||
this.$emit('sendMsg', 'order');
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.message {
|
||||
padding: 13rpx 20rpx;
|
||||
box-sizing: border-box;
|
||||
width: 100vw;
|
||||
position: relative;
|
||||
.goods-item {
|
||||
width: 100%;
|
||||
height: 220rpx;
|
||||
background: #ffffff;
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-radius: 20rpx;
|
||||
margin: 0 auto;
|
||||
padding: $padding;
|
||||
box-sizing: border-box;
|
||||
image {
|
||||
width: 180rpx;
|
||||
height: 180rpx;
|
||||
}
|
||||
.goods-info {
|
||||
width: 100%;
|
||||
height: 180rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
padding-left: 20rpx;
|
||||
box-sizing: border-box;
|
||||
.goods-name {
|
||||
width: 100%;
|
||||
line-height: 1.4;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 1;
|
||||
overflow: hidden;
|
||||
// font-size: $font-size-tag;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
.goods-bottom {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-end;
|
||||
text {
|
||||
line-height: 1;
|
||||
}
|
||||
.goods-price {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
padding-bottom: 10rpx;
|
||||
font-weight: 500;
|
||||
.goods-price-sign {
|
||||
font-size: 20rpx;
|
||||
}
|
||||
}
|
||||
.goods-option {
|
||||
width: 150rpx;
|
||||
height: 50rpx;
|
||||
line-height: 50rpx;
|
||||
text-align: center;
|
||||
border-radius: $border-radius;
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
}
|
||||
.disabled {
|
||||
background: #e5e5e5;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<template>
|
||||
<view class="message">
|
||||
<view class="goods-item" v-if="orderdetails">
|
||||
<image :src="$util.img(orderdetails.order_goods ? orderdetails.order_goods[0].sku_image : '')" mode="aspectFill" show-menu-by-longpress></image>
|
||||
<view class="goods-info">
|
||||
<view class="goods-name">{{ orderdetails.order_goods ? orderdetails.order_goods[0].sku_name : '' }}</view>
|
||||
<view class="font-size-goods-tag">订单状态:{{ orderdetails.order_status_name }}</view>
|
||||
<view class="font-size-goods-tag">配送方式:{{ orderdetails.delivery_type_name }}</view>
|
||||
<view class="goods-bottom">
|
||||
<view class="goods-price color-base-text">
|
||||
<text class="goods-price-sign">¥</text>
|
||||
<text>{{ orderdetails.order_goods ? orderdetails.order_goods[0].price : '' }}</text>
|
||||
</view>
|
||||
<view class="goods-option font-size-goods-tag color-base-bg" @click="sendMsg('order')">发送</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="goods-item" v-else-if="orderInfo">
|
||||
<image :src="$util.img(orderInfo.order_goods ? orderInfo.order_goods[0].sku_image : '')" mode="aspectFill" show-menu-by-longpress></image>
|
||||
<view class="goods-info">
|
||||
<view class="goods-name">{{ orderInfo.order_goods ? orderInfo.order_goods[0].sku_name : '' }}</view>
|
||||
<view class="font-size-goods-tag">订单状态:{{ orderInfo.order_status_name }}</view>
|
||||
<view class="font-size-goods-tag">配送方式:{{ orderInfo.delivery_type_name }}</view>
|
||||
<view class="goods-bottom">
|
||||
<view class="goods-price color-base-text">
|
||||
<text class="goods-price-sign">¥</text>
|
||||
<text>{{ orderInfo.order_goods ? orderInfo.order_goods[0].price : '' }}</text>
|
||||
</view>
|
||||
<view class="goods-option font-size-goods-tag disabled">已发送</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'ns-chat-order',
|
||||
props: {
|
||||
orderId: {
|
||||
type: [Number, String]
|
||||
},
|
||||
isCanSend: Boolean,
|
||||
orderdetails: {
|
||||
type: [Object]
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
orderInfo: {}
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.getGoodsInfo();
|
||||
},
|
||||
methods: {
|
||||
getGoodsInfo() {
|
||||
if (this.orderId) {
|
||||
this.$api.sendRequest({
|
||||
url: '/api/order/detail',
|
||||
data: {
|
||||
order_id: this.orderId
|
||||
},
|
||||
success: res => {
|
||||
if (res.code >= 0) {
|
||||
this.orderInfo = res.data;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
sendMsg() {
|
||||
this.$emit('sendMsg', 'order');
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.message {
|
||||
padding: 13rpx 20rpx;
|
||||
box-sizing: border-box;
|
||||
width: 100vw;
|
||||
position: relative;
|
||||
.goods-item {
|
||||
width: 100%;
|
||||
height: 220rpx;
|
||||
background: #ffffff;
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-radius: 20rpx;
|
||||
margin: 0 auto;
|
||||
padding: $padding;
|
||||
box-sizing: border-box;
|
||||
image {
|
||||
width: 180rpx;
|
||||
height: 180rpx;
|
||||
}
|
||||
.goods-info {
|
||||
width: 100%;
|
||||
height: 180rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
padding-left: 20rpx;
|
||||
box-sizing: border-box;
|
||||
.goods-name {
|
||||
width: 100%;
|
||||
line-height: 1.4;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 1;
|
||||
overflow: hidden;
|
||||
// font-size: $font-size-tag;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
.goods-bottom {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-end;
|
||||
text {
|
||||
line-height: 1;
|
||||
}
|
||||
.goods-price {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
padding-bottom: 10rpx;
|
||||
font-weight: 500;
|
||||
.goods-price-sign {
|
||||
font-size: 20rpx;
|
||||
}
|
||||
}
|
||||
.goods-option {
|
||||
width: 150rpx;
|
||||
height: 50rpx;
|
||||
line-height: 50rpx;
|
||||
text-align: center;
|
||||
border-radius: $border-radius;
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
}
|
||||
.disabled {
|
||||
background: #e5e5e5;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<view class="title">{{ isEnEnv ? goodsInfo.en_goods_name : goodsInfo.goods_name }}</view>
|
||||
<view class="goods-sku">
|
||||
库存:{{ goodsInfo.stock }}
|
||||
<text>{ $lang("common.ns-chat.ns-chat-receiveGoods.l9.t0") } goodsInfo.sale_num }}</text>
|
||||
<text>销量:{{ goodsInfo.sale_num }}</text>
|
||||
</view>
|
||||
<view class="goods-price">
|
||||
<view class="price color-base-text">
|
||||
|
||||
@@ -29,10 +29,10 @@
|
||||
<uni-popup ref="servicePopup" type="center">
|
||||
<view class="service-popup-wrap">
|
||||
<view class="head-wrap" @click="$refs.servicePopup.close()">
|
||||
<text>{{ $lang("common.ns-contact.l32.t0") }}</text>
|
||||
<text>联系客服</text>
|
||||
<text class="iconfont icon-close"></text>
|
||||
</view>
|
||||
<view class="body-wrap">{{ siteInfo.site_tel ? $lang('common.ns-contact.l35.t0') + siteInfo.site_tel : $lang('common.ns-contact.l35.t1') }}
|
||||
<view class="body-wrap">{{ siteInfo.site_tel ? '请联系客服,客服电话是' + siteInfo.site_tel : '抱歉,商家暂无客服,请线下联系' }}
|
||||
</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
|
||||
@@ -1,142 +1,142 @@
|
||||
<template>
|
||||
<view class="copyrigt-wrap" v-if="copyright && (showLogo || showBeian)">
|
||||
<!-- <view class="copyright-info" v-if="showLogo">
|
||||
<view class="copyright-pic" v-if="copyright.logo" @click="link(copyright.copyright_link)">
|
||||
<image :src="$util.img(copyright.logo)" @error="error" mode="widthFix"></image>
|
||||
</view>
|
||||
</view>
|
||||
<view class="record-info" v-if="showBeian">
|
||||
<view class="icp" v-if="copyright && copyright.icp" @click="toHref('https://beian.miit.gov.cn')">备案号:{{ copyright.icp }}
|
||||
</view>
|
||||
|
||||
<view v-if="copyright && copyright.gov_record" class="gov-wrap" @click="toHref(copyright.gov_url)" target="_blank">
|
||||
<image :src="$util.img('public/uniapp/common/gov_record.png')" alt=$lang("common.ns-copyright.l13.t0") show-menu-by-longpress/>
|
||||
<text>{{ copyright.gov_record }}</text>
|
||||
</view>
|
||||
</view> -->
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
showLogo: true,
|
||||
};
|
||||
},
|
||||
created() {},
|
||||
computed: {
|
||||
showBeian() {
|
||||
// 如果都为空,则隐藏
|
||||
if (this.copyright && (!this.copyright.icp && !this.copyright.gov_record)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
link(url) {
|
||||
if (url) {
|
||||
this.$util.redirectTo('/pages_tool/webview/webview', {
|
||||
src: encodeURIComponent(url)
|
||||
});
|
||||
}
|
||||
},
|
||||
toHref(url) {
|
||||
location.href = url;
|
||||
},
|
||||
error() {
|
||||
this.showLogo = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.copyrigt-wrap {
|
||||
margin-top: 40rpx;
|
||||
margin-bottom: 40rpx;
|
||||
|
||||
>view {
|
||||
font-size: $font-size-tag;
|
||||
color: #666666;
|
||||
|
||||
&:last-child {
|
||||
margin-top: 10rpx;
|
||||
}
|
||||
|
||||
&:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.copyright-info {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
|
||||
.copyright-pic {
|
||||
image {
|
||||
width: 160rpx;
|
||||
height: 24rpx;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
text {
|
||||
font-size: $font-size-goods-tag;
|
||||
height: 100rpx;
|
||||
line-height: 100rpx;
|
||||
color: $color-tip !important;
|
||||
}
|
||||
|
||||
.copyright-desc {
|
||||
color: lighten($color-tip, 30%);
|
||||
font-size: $font-size-goods-tag;
|
||||
text-shadow: 0 0 2rpx lighten($color-tip, 40%);
|
||||
}
|
||||
}
|
||||
|
||||
.record-info {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
margin-top: 10rpx;
|
||||
|
||||
text {
|
||||
color: #666666;
|
||||
font-size: $font-size-tag;
|
||||
}
|
||||
|
||||
view {
|
||||
font-size: $font-size-tag;
|
||||
color: #666666;
|
||||
|
||||
&:last-child {
|
||||
margin-top: 10rpx;
|
||||
}
|
||||
|
||||
&:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.gov-wrap {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
image {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
<template>
|
||||
<view class="copyrigt-wrap" v-if="copyright && (showLogo || showBeian)">
|
||||
<!-- <view class="copyright-info" v-if="showLogo">
|
||||
<view class="copyright-pic" v-if="copyright.logo" @click="link(copyright.copyright_link)">
|
||||
<image :src="$util.img(copyright.logo)" @error="error" mode="widthFix"></image>
|
||||
</view>
|
||||
</view>
|
||||
<view class="record-info" v-if="showBeian">
|
||||
<view class="icp" v-if="copyright && copyright.icp" @click="toHref('https://beian.miit.gov.cn')">备案号:{{ copyright.icp }}
|
||||
</view>
|
||||
|
||||
<view v-if="copyright && copyright.gov_record" class="gov-wrap" @click="toHref(copyright.gov_url)" target="_blank">
|
||||
<image :src="$util.img('public/uniapp/common/gov_record.png')" alt="公安备案" show-menu-by-longpress/>
|
||||
<text>{{ copyright.gov_record }}</text>
|
||||
</view>
|
||||
</view> -->
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
showLogo: true,
|
||||
};
|
||||
},
|
||||
created() {},
|
||||
computed: {
|
||||
showBeian() {
|
||||
// 如果都为空,则隐藏
|
||||
if (this.copyright && (!this.copyright.icp && !this.copyright.gov_record)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
link(url) {
|
||||
if (url) {
|
||||
this.$util.redirectTo('/pages_tool/webview/webview', {
|
||||
src: encodeURIComponent(url)
|
||||
});
|
||||
}
|
||||
},
|
||||
toHref(url) {
|
||||
location.href = url;
|
||||
},
|
||||
error() {
|
||||
this.showLogo = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.copyrigt-wrap {
|
||||
margin-top: 40rpx;
|
||||
margin-bottom: 40rpx;
|
||||
|
||||
>view {
|
||||
font-size: $font-size-tag;
|
||||
color: #666666;
|
||||
|
||||
&:last-child {
|
||||
margin-top: 10rpx;
|
||||
}
|
||||
|
||||
&:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.copyright-info {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
|
||||
.copyright-pic {
|
||||
image {
|
||||
width: 160rpx;
|
||||
height: 24rpx;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
text {
|
||||
font-size: $font-size-goods-tag;
|
||||
height: 100rpx;
|
||||
line-height: 100rpx;
|
||||
color: $color-tip !important;
|
||||
}
|
||||
|
||||
.copyright-desc {
|
||||
color: lighten($color-tip, 30%);
|
||||
font-size: $font-size-goods-tag;
|
||||
text-shadow: 0 0 2rpx lighten($color-tip, 40%);
|
||||
}
|
||||
}
|
||||
|
||||
.record-info {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
margin-top: 10rpx;
|
||||
|
||||
text {
|
||||
color: #666666;
|
||||
font-size: $font-size-tag;
|
||||
}
|
||||
|
||||
view {
|
||||
font-size: $font-size-tag;
|
||||
color: #666666;
|
||||
|
||||
&:last-child {
|
||||
margin-top: 10rpx;
|
||||
}
|
||||
|
||||
&:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.gov-wrap {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
image {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,95 +1,95 @@
|
||||
<template>
|
||||
<view class="empty" :class="{ fixed: fixed }">
|
||||
<view class="empty_img"><image :src="$util.img('public/uniapp/common/common-empty.png')" mode="aspectFit" show-menu-by-longpress></image></view>
|
||||
<view class="color-tip margin-top title" :style="{ color: textColor + ' !important' }">{{ text }}</view>
|
||||
<view class="color-tip margin-bottom font-size-sub">{{ subText }}</view>
|
||||
<button type="primary" size="mini" class="button mini" @click="goIndex()" v-if="isIndex">{{ emptyBtn.text }}</button>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
props: {
|
||||
text: {
|
||||
type: String,
|
||||
default: $lang('common.ns-empty.l18.t0')
|
||||
},
|
||||
subText: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
isIndex: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
emptyBtn: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return { text: $lang('common.ns-empty.l31.t0') };
|
||||
}
|
||||
},
|
||||
fixed: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
textColor: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
goIndex() {
|
||||
if (this.emptyBtn.url) {
|
||||
this.$util.redirectTo(this.emptyBtn.url, {}, 'redirectTo');
|
||||
} else {
|
||||
this.$util.redirectTo(this.$util.INDEX_PAGE_URL);
|
||||
}
|
||||
},
|
||||
re(text) {
|
||||
this.text = text;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.empty {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: $padding;
|
||||
box-sizing: border-box;
|
||||
justify-content: center;
|
||||
.title {
|
||||
font-size: 30rpx;
|
||||
}
|
||||
.empty_img {
|
||||
width: 50%;
|
||||
height: 450rpx;
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding-bottom: $padding;
|
||||
}
|
||||
}
|
||||
button {
|
||||
min-width: 300rpx;
|
||||
margin-top: 100rpx;
|
||||
height: 70rpx;
|
||||
line-height: 70rpx !important;
|
||||
font-size: $font-size-base;
|
||||
font-weight: bold;
|
||||
border-radius: 100rpx;
|
||||
}
|
||||
}
|
||||
.fixed {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 20vh;
|
||||
}
|
||||
</style>
|
||||
<template>
|
||||
<view class="empty" :class="{ fixed: fixed }">
|
||||
<view class="empty_img"><image :src="$util.img('public/uniapp/common/common-empty.png')" mode="aspectFit" show-menu-by-longpress></image></view>
|
||||
<view class="color-tip margin-top title" :style="{ color: textColor + ' !important' }">{{ text }}</view>
|
||||
<view class="color-tip margin-bottom font-size-sub">{{ subText }}</view>
|
||||
<button type="primary" size="mini" class="button mini" @click="goIndex()" v-if="isIndex">{{ emptyBtn.text }}</button>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
props: {
|
||||
text: {
|
||||
type: String,
|
||||
default: '暂无相关数据'
|
||||
},
|
||||
subText: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
isIndex: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
emptyBtn: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return { text: '去逛逛' };
|
||||
}
|
||||
},
|
||||
fixed: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
textColor: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
goIndex() {
|
||||
if (this.emptyBtn.url) {
|
||||
this.$util.redirectTo(this.emptyBtn.url, {}, 'redirectTo');
|
||||
} else {
|
||||
this.$util.redirectTo(this.$util.INDEX_PAGE_URL);
|
||||
}
|
||||
},
|
||||
re(text) {
|
||||
this.text = text;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.empty {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: $padding;
|
||||
box-sizing: border-box;
|
||||
justify-content: center;
|
||||
.title {
|
||||
font-size: 30rpx;
|
||||
}
|
||||
.empty_img {
|
||||
width: 50%;
|
||||
height: 450rpx;
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding-bottom: $padding;
|
||||
}
|
||||
}
|
||||
button {
|
||||
min-width: 300rpx;
|
||||
margin-top: 100rpx;
|
||||
height: 70rpx;
|
||||
line-height: 70rpx !important;
|
||||
font-size: $font-size-base;
|
||||
font-weight: bold;
|
||||
border-radius: 100rpx;
|
||||
}
|
||||
}
|
||||
.fixed {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 20vh;
|
||||
}
|
||||
</style>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,394 +1,394 @@
|
||||
<template>
|
||||
<view></view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// 商品推荐
|
||||
export default {
|
||||
name: 'ns-goods-recommend',
|
||||
data() {
|
||||
return {
|
||||
list: [],
|
||||
config: {
|
||||
title: $lang('common.ns-goods-recommend.l13.t0'),
|
||||
sources: 'sort',
|
||||
supportPage: [],
|
||||
goodsIds: [],
|
||||
fontWeight: false,
|
||||
padding: 0,
|
||||
cartEvent: 'detail',
|
||||
text: $lang('common.ns-goods-recommend.l20.t0'),
|
||||
textColor: '#FFFFFF',
|
||||
theme: 'default',
|
||||
aroundRadius: 25,
|
||||
control: true,
|
||||
bgColor: '#FF6A00',
|
||||
style: 'button',
|
||||
iconDiy: {
|
||||
iconType: 'icon',
|
||||
icon: '',
|
||||
style: {
|
||||
fontSize: '60',
|
||||
iconBgColor: [],
|
||||
iconBgColorDeg: 0,
|
||||
iconBgImg: '',
|
||||
bgRadius: 0,
|
||||
iconColor: ['#000000'],
|
||||
iconColorDeg: 0
|
||||
}
|
||||
}
|
||||
},
|
||||
page: 1,
|
||||
isAll: true,
|
||||
isClick: true,
|
||||
showLoading: false
|
||||
};
|
||||
},
|
||||
props: {
|
||||
isLike: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
size: {
|
||||
type: [Number, String],
|
||||
default: 10
|
||||
},
|
||||
auto: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
load: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
route: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
if (this.auto) {
|
||||
this.getLikeList();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
this.list = [];
|
||||
this.page = 1;
|
||||
},
|
||||
toDetail(e) {
|
||||
let data = {
|
||||
goods_id: e.goods_id
|
||||
};
|
||||
this.$util.redirectTo('/pages_goods/detail', data);
|
||||
},
|
||||
getLikeList(size) {
|
||||
let that = this;
|
||||
if (!this.isClick) return;
|
||||
if (!this.isAll) return;
|
||||
this.isClick = false;
|
||||
if (this.page > 1) this.showLoading = true;
|
||||
return new Promise((resolve, reject) => {
|
||||
that.$api.sendRequest({
|
||||
url: '/api/goodssku/recommend',
|
||||
data: {
|
||||
page: this.page,
|
||||
page_size: this.auto ? this.size : size,
|
||||
route: this.route
|
||||
},
|
||||
success: res => {
|
||||
this.showLoading = false;
|
||||
this.isClick = true;
|
||||
if (res.code == 0) {
|
||||
if (this.page == 1) {
|
||||
this.list = [];
|
||||
}
|
||||
this.config = res.data.config;
|
||||
this.list = this.list.concat(res.data.list);
|
||||
if (this.list.length == res.data.count) this.isAll = false;
|
||||
this.page += 1;
|
||||
resolve(res.data.list);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
goodsImg(imgStr) {
|
||||
let imgs = imgStr.split(',');
|
||||
return imgs[0] ? this.$util.img(imgs[0], {
|
||||
size: 'mid'
|
||||
}) : this.$util.getDefaultImage().goods;
|
||||
},
|
||||
imgError(index) {
|
||||
this.list[index].goods_image = this.$util.getDefaultImage().goods;
|
||||
},
|
||||
showPrice(data) {
|
||||
let price = data.discount_price;
|
||||
if (data.member_price && parseFloat(data.member_price) < parseFloat(price)) price = data.member_price;
|
||||
return price;
|
||||
},
|
||||
showMarketPrice(item) {
|
||||
if (item.market_price_show) {
|
||||
let price = this.showPrice(item);
|
||||
if (item.market_price > 0) {
|
||||
return item.market_price;
|
||||
} else if (parseFloat(item.price) > parseFloat(price)) {
|
||||
return item.price;
|
||||
}
|
||||
}
|
||||
return '';
|
||||
},
|
||||
goodsTag(data) {
|
||||
return data.label_name || '';
|
||||
},
|
||||
// 监听加入购物车变化
|
||||
cartListChange(e) {
|
||||
if (this.route == 'cart' && this.storeToken) {
|
||||
this.$root.getCartData();
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 添加购物车回调
|
||||
*/
|
||||
addCart(id) {}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.goods-recommend {
|
||||
margin-top: 74rpx;
|
||||
width: 100vw;
|
||||
|
||||
.goods-recommend-title {
|
||||
text-align: center;
|
||||
margin-bottom: 40rpx;
|
||||
|
||||
.title {
|
||||
font-size: 30rpx;
|
||||
font-weight: 500;
|
||||
position: relative;
|
||||
color: #333;
|
||||
|
||||
&::before,
|
||||
&::after {
|
||||
content: ' ';
|
||||
width: 80rpx;
|
||||
border-top: 2rpx solid #969696;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
&::before {
|
||||
left: 0;
|
||||
transform: translateX(-130%);
|
||||
}
|
||||
|
||||
&::after {
|
||||
right: 0;
|
||||
transform: translateX(130%);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.hr-view {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
max-width: 100%;
|
||||
box-sizing: content-box;
|
||||
font-size: $font-size-toolbar;
|
||||
}
|
||||
|
||||
.hr-view .hr {
|
||||
width: 36%;
|
||||
height: 2rpx;
|
||||
background: #e5e5e5;
|
||||
}
|
||||
|
||||
.hr-view .title {
|
||||
padding: 0 $padding;
|
||||
}
|
||||
|
||||
// 商品列表双列样式
|
||||
.goods-list.double-column {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
margin: 0 24rpx;
|
||||
|
||||
.goods-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
background-color: #fff;
|
||||
width: calc(50% - 10rpx);
|
||||
margin-bottom: $margin-updown;
|
||||
border-radius: $border-radius;
|
||||
|
||||
&:nth-child(2n) {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.goods-img {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
padding-top: 100%;
|
||||
border-top-left-radius: $border-radius;
|
||||
border-top-right-radius: $border-radius;
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
// top: 50%;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
// transform: translateY(-50%);
|
||||
}
|
||||
}
|
||||
|
||||
.goods-tag {
|
||||
color: #fff;
|
||||
line-height: 1;
|
||||
padding: 8rpx 16rpx;
|
||||
position: absolute;
|
||||
border-bottom-right-radius: $border-radius;
|
||||
top: 0;
|
||||
left: 0;
|
||||
font-size: $font-size-goods-tag;
|
||||
}
|
||||
|
||||
.goods-tag-img {
|
||||
position: absolute;
|
||||
border-top-left-radius: $border-radius;
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 5;
|
||||
overflow: hidden;
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.info-wrap {
|
||||
padding: 20rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.goods-name {
|
||||
font-size: $font-size-base;
|
||||
line-height: 1.3;
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
|
||||
.lineheight-clear {
|
||||
margin-top: 16rpx;
|
||||
}
|
||||
|
||||
.discount-price {
|
||||
display: inline-block;
|
||||
font-weight: bold;
|
||||
line-height: 1;
|
||||
color: var(--price-color);
|
||||
|
||||
.unit {
|
||||
margin-right: 6rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.pro-info {
|
||||
display: flex;
|
||||
margin-top: auto;
|
||||
align-items: center;
|
||||
|
||||
.block-wrap {
|
||||
flex: 1;
|
||||
line-height: 1;
|
||||
margin-right: 20rpx;
|
||||
|
||||
.sale {
|
||||
font-size: $font-size-tag !important;
|
||||
}
|
||||
}
|
||||
|
||||
.cart-action-wrap {
|
||||
position: relative;
|
||||
|
||||
.shopping-cart-btn {
|
||||
font-size: 36rpx;
|
||||
border: 2rpx solid $base-color;
|
||||
border-radius: 50%;
|
||||
padding: 10rpx;
|
||||
color: $base-color;
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
text-align: center;
|
||||
line-height: 36rpx;
|
||||
}
|
||||
|
||||
.plus-sign-btn {
|
||||
font-size: 36rpx;
|
||||
border: 2rpx solid $base-color;
|
||||
border-radius: 50%;
|
||||
padding: 10rpx;
|
||||
color: $base-color;
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
text-align: center;
|
||||
line-height: 36rpx;
|
||||
}
|
||||
|
||||
.buy-btn {
|
||||
background-color: $base-color;
|
||||
color: var(--btn-text-color);
|
||||
border-radius: 50rpx;
|
||||
font-size: $font-size-tag;
|
||||
padding: 12rpx 30rpx;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.icon-diy {
|
||||
font-size: 80rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.delete-price {
|
||||
display: inline-block;
|
||||
margin-left: 6rpx;
|
||||
float: right;
|
||||
text-decoration: line-through;
|
||||
|
||||
.unit {
|
||||
margin-right: 6rpx;
|
||||
}
|
||||
|
||||
text {
|
||||
line-height: 1;
|
||||
font-size: $font-size-tag !important;
|
||||
}
|
||||
}
|
||||
|
||||
.member-price-tag {
|
||||
display: inline-block;
|
||||
width: 60rpx;
|
||||
line-height: 1;
|
||||
margin-left: 6rpx;
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
<template>
|
||||
<view></view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// 商品推荐
|
||||
export default {
|
||||
name: 'ns-goods-recommend',
|
||||
data() {
|
||||
return {
|
||||
list: [],
|
||||
config: {
|
||||
title: '猜你喜欢',
|
||||
sources: 'sort',
|
||||
supportPage: [],
|
||||
goodsIds: [],
|
||||
fontWeight: false,
|
||||
padding: 0,
|
||||
cartEvent: 'detail',
|
||||
text: '购买',
|
||||
textColor: '#FFFFFF',
|
||||
theme: 'default',
|
||||
aroundRadius: 25,
|
||||
control: true,
|
||||
bgColor: '#FF6A00',
|
||||
style: 'button',
|
||||
iconDiy: {
|
||||
iconType: 'icon',
|
||||
icon: '',
|
||||
style: {
|
||||
fontSize: '60',
|
||||
iconBgColor: [],
|
||||
iconBgColorDeg: 0,
|
||||
iconBgImg: '',
|
||||
bgRadius: 0,
|
||||
iconColor: ['#000000'],
|
||||
iconColorDeg: 0
|
||||
}
|
||||
}
|
||||
},
|
||||
page: 1,
|
||||
isAll: true,
|
||||
isClick: true,
|
||||
showLoading: false
|
||||
};
|
||||
},
|
||||
props: {
|
||||
isLike: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
size: {
|
||||
type: [Number, String],
|
||||
default: 10
|
||||
},
|
||||
auto: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
load: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
route: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
if (this.auto) {
|
||||
this.getLikeList();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
this.list = [];
|
||||
this.page = 1;
|
||||
},
|
||||
toDetail(e) {
|
||||
let data = {
|
||||
goods_id: e.goods_id
|
||||
};
|
||||
this.$util.redirectTo('/pages_goods/detail', data);
|
||||
},
|
||||
getLikeList(size) {
|
||||
let that = this;
|
||||
if (!this.isClick) return;
|
||||
if (!this.isAll) return;
|
||||
this.isClick = false;
|
||||
if (this.page > 1) this.showLoading = true;
|
||||
return new Promise((resolve, reject) => {
|
||||
that.$api.sendRequest({
|
||||
url: '/api/goodssku/recommend',
|
||||
data: {
|
||||
page: this.page,
|
||||
page_size: this.auto ? this.size : size,
|
||||
route: this.route
|
||||
},
|
||||
success: res => {
|
||||
this.showLoading = false;
|
||||
this.isClick = true;
|
||||
if (res.code == 0) {
|
||||
if (this.page == 1) {
|
||||
this.list = [];
|
||||
}
|
||||
this.config = res.data.config;
|
||||
this.list = this.list.concat(res.data.list);
|
||||
if (this.list.length == res.data.count) this.isAll = false;
|
||||
this.page += 1;
|
||||
resolve(res.data.list);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
goodsImg(imgStr) {
|
||||
let imgs = imgStr.split(',');
|
||||
return imgs[0] ? this.$util.img(imgs[0], {
|
||||
size: 'mid'
|
||||
}) : this.$util.getDefaultImage().goods;
|
||||
},
|
||||
imgError(index) {
|
||||
this.list[index].goods_image = this.$util.getDefaultImage().goods;
|
||||
},
|
||||
showPrice(data) {
|
||||
let price = data.discount_price;
|
||||
if (data.member_price && parseFloat(data.member_price) < parseFloat(price)) price = data.member_price;
|
||||
return price;
|
||||
},
|
||||
showMarketPrice(item) {
|
||||
if (item.market_price_show) {
|
||||
let price = this.showPrice(item);
|
||||
if (item.market_price > 0) {
|
||||
return item.market_price;
|
||||
} else if (parseFloat(item.price) > parseFloat(price)) {
|
||||
return item.price;
|
||||
}
|
||||
}
|
||||
return '';
|
||||
},
|
||||
goodsTag(data) {
|
||||
return data.label_name || '';
|
||||
},
|
||||
// 监听加入购物车变化
|
||||
cartListChange(e) {
|
||||
if (this.route == 'cart' && this.storeToken) {
|
||||
this.$root.getCartData();
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 添加购物车回调
|
||||
*/
|
||||
addCart(id) {}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.goods-recommend {
|
||||
margin-top: 74rpx;
|
||||
width: 100vw;
|
||||
|
||||
.goods-recommend-title {
|
||||
text-align: center;
|
||||
margin-bottom: 40rpx;
|
||||
|
||||
.title {
|
||||
font-size: 30rpx;
|
||||
font-weight: 500;
|
||||
position: relative;
|
||||
color: #333;
|
||||
|
||||
&::before,
|
||||
&::after {
|
||||
content: ' ';
|
||||
width: 80rpx;
|
||||
border-top: 2rpx solid #969696;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
&::before {
|
||||
left: 0;
|
||||
transform: translateX(-130%);
|
||||
}
|
||||
|
||||
&::after {
|
||||
right: 0;
|
||||
transform: translateX(130%);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.hr-view {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
max-width: 100%;
|
||||
box-sizing: content-box;
|
||||
font-size: $font-size-toolbar;
|
||||
}
|
||||
|
||||
.hr-view .hr {
|
||||
width: 36%;
|
||||
height: 2rpx;
|
||||
background: #e5e5e5;
|
||||
}
|
||||
|
||||
.hr-view .title {
|
||||
padding: 0 $padding;
|
||||
}
|
||||
|
||||
// 商品列表双列样式
|
||||
.goods-list.double-column {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
margin: 0 24rpx;
|
||||
|
||||
.goods-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
background-color: #fff;
|
||||
width: calc(50% - 10rpx);
|
||||
margin-bottom: $margin-updown;
|
||||
border-radius: $border-radius;
|
||||
|
||||
&:nth-child(2n) {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.goods-img {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
padding-top: 100%;
|
||||
border-top-left-radius: $border-radius;
|
||||
border-top-right-radius: $border-radius;
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
// top: 50%;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
// transform: translateY(-50%);
|
||||
}
|
||||
}
|
||||
|
||||
.goods-tag {
|
||||
color: #fff;
|
||||
line-height: 1;
|
||||
padding: 8rpx 16rpx;
|
||||
position: absolute;
|
||||
border-bottom-right-radius: $border-radius;
|
||||
top: 0;
|
||||
left: 0;
|
||||
font-size: $font-size-goods-tag;
|
||||
}
|
||||
|
||||
.goods-tag-img {
|
||||
position: absolute;
|
||||
border-top-left-radius: $border-radius;
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 5;
|
||||
overflow: hidden;
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.info-wrap {
|
||||
padding: 20rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.goods-name {
|
||||
font-size: $font-size-base;
|
||||
line-height: 1.3;
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
|
||||
.lineheight-clear {
|
||||
margin-top: 16rpx;
|
||||
}
|
||||
|
||||
.discount-price {
|
||||
display: inline-block;
|
||||
font-weight: bold;
|
||||
line-height: 1;
|
||||
color: var(--price-color);
|
||||
|
||||
.unit {
|
||||
margin-right: 6rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.pro-info {
|
||||
display: flex;
|
||||
margin-top: auto;
|
||||
align-items: center;
|
||||
|
||||
.block-wrap {
|
||||
flex: 1;
|
||||
line-height: 1;
|
||||
margin-right: 20rpx;
|
||||
|
||||
.sale {
|
||||
font-size: $font-size-tag !important;
|
||||
}
|
||||
}
|
||||
|
||||
.cart-action-wrap {
|
||||
position: relative;
|
||||
|
||||
.shopping-cart-btn {
|
||||
font-size: 36rpx;
|
||||
border: 2rpx solid $base-color;
|
||||
border-radius: 50%;
|
||||
padding: 10rpx;
|
||||
color: $base-color;
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
text-align: center;
|
||||
line-height: 36rpx;
|
||||
}
|
||||
|
||||
.plus-sign-btn {
|
||||
font-size: 36rpx;
|
||||
border: 2rpx solid $base-color;
|
||||
border-radius: 50%;
|
||||
padding: 10rpx;
|
||||
color: $base-color;
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
text-align: center;
|
||||
line-height: 36rpx;
|
||||
}
|
||||
|
||||
.buy-btn {
|
||||
background-color: $base-color;
|
||||
color: var(--btn-text-color);
|
||||
border-radius: 50rpx;
|
||||
font-size: $font-size-tag;
|
||||
padding: 12rpx 30rpx;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.icon-diy {
|
||||
font-size: 80rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.delete-price {
|
||||
display: inline-block;
|
||||
margin-left: 6rpx;
|
||||
float: right;
|
||||
text-decoration: line-through;
|
||||
|
||||
.unit {
|
||||
margin-right: 6rpx;
|
||||
}
|
||||
|
||||
text {
|
||||
line-height: 1;
|
||||
font-size: $font-size-tag !important;
|
||||
}
|
||||
}
|
||||
|
||||
.member-price-tag {
|
||||
display: inline-block;
|
||||
width: 60rpx;
|
||||
line-height: 1;
|
||||
margin-left: 6rpx;
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,234 +1,234 @@
|
||||
<template>
|
||||
<view class="goods-sku">
|
||||
<ns-login ref="login"></ns-login>
|
||||
<!-- sku选择 -->
|
||||
<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>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// 商品SKU
|
||||
export default {
|
||||
name: 'ns-goods-sku-index',
|
||||
data() {
|
||||
return {
|
||||
timeout: {},
|
||||
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);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 单规格
|
||||
* @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] :
|
||||
null;
|
||||
|
||||
let cartNum = cart ? cart.num : 0;
|
||||
let api = cart && cart.cart_id ? '/api/cart/edit' : '/api/cart/add';
|
||||
let minBuy = data.min_buy > 0 ? data.min_buy : 1;
|
||||
let num = cartNum >= minBuy ? cartNum : minBuy;
|
||||
let _num = num;
|
||||
if (cart && cart.cart_id) {
|
||||
_num = _num + (data.min_buy > 0 ? data.min_buy : 1)
|
||||
}
|
||||
let cart_id = cart ? cart.cart_id : 0;
|
||||
if (_num > parseInt(data.stock)) {
|
||||
this.$util.showToast({
|
||||
title: $lang('common.ns-goods-sku.ns-goods-sku-index.l70.t0')
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (data.is_limit && data.max_buy && _num > parseInt(data.max_buy)) {
|
||||
this.$util.showToast({
|
||||
title: `该商品每人限购${data.max_buy}${data.unit || '件'}`
|
||||
});
|
||||
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 (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
|
||||
};
|
||||
}
|
||||
|
||||
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: $lang("common.ns-goods-sku.ns-goods-sku-index.l124.t0")
|
||||
});
|
||||
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 || $lang('common.ns-goods-sku.ns-goods-sku-index.l150.t0');
|
||||
|
||||
if (item.sku_images) item.sku_images = item.sku_images.split(',');
|
||||
else item.sku_images = [];
|
||||
|
||||
// 多规格时合并主图
|
||||
if (item.goods_spec_format && item.goods_image) {
|
||||
item.goods_image = item.goods_image.split(',');
|
||||
item.sku_images = item.goods_image.concat(item.sku_images);
|
||||
}
|
||||
|
||||
// 当前商品SKU规格
|
||||
if (item.sku_spec_format) item.sku_spec_format = JSON.parse(item.sku_spec_format);
|
||||
|
||||
// 商品SKU格式
|
||||
if (item.goods_spec_format) item.goods_spec_format = JSON.parse(item.goods_spec_format);
|
||||
|
||||
// 限时折扣
|
||||
if (item.promotion_type == 1) {
|
||||
item.discountTimeMachine = this.$util.countDown(item.end_time - res.timestamp);
|
||||
}
|
||||
|
||||
if (item.promotion_type == 1 && item.discountTimeMachine) {
|
||||
if (item.member_price > 0 && Number(item.member_price) <= Number(item.discount_price)) {
|
||||
item.show_price = item.member_price;
|
||||
} else {
|
||||
item.show_price = item.discount_price;
|
||||
}
|
||||
} else if (item.member_price > 0) {
|
||||
item.show_price = item.member_price;
|
||||
} else {
|
||||
item.show_price = item.price;
|
||||
}
|
||||
this.goodsDetail = item;
|
||||
|
||||
this.$nextTick(() => {
|
||||
if (this.$refs.goodsSku) {
|
||||
this.$refs.goodsSku.show("join_cart", (res) => {
|
||||
|
||||
let goods = this.cartList['goods_' + res.goods_id];
|
||||
let cart = null;
|
||||
if (goods && 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] = {
|
||||
cart_id: res.cart_id,
|
||||
goods_id: res.goods_id,
|
||||
sku_id: res.sku_id,
|
||||
num: res.num,
|
||||
discount_price: res.discount_price
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
this.$store.dispatch('cartCalculate');
|
||||
this.$emit("cartListChange", this.cartList);
|
||||
|
||||
// 加入购物车动效
|
||||
setTimeout(() => {
|
||||
this.$store.commit('setCartChange');
|
||||
}, 100);
|
||||
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
refreshGoodsSkuDetail(data) {
|
||||
this.goodsDetail = Object.assign({}, this.goodsDetail, data);
|
||||
}
|
||||
}
|
||||
};
|
||||
<template>
|
||||
<view class="goods-sku">
|
||||
<ns-login ref="login"></ns-login>
|
||||
<!-- sku选择 -->
|
||||
<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>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// 商品SKU
|
||||
export default {
|
||||
name: 'ns-goods-sku-index',
|
||||
data() {
|
||||
return {
|
||||
timeout: {},
|
||||
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);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 单规格
|
||||
* @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] :
|
||||
null;
|
||||
|
||||
let cartNum = cart ? cart.num : 0;
|
||||
let api = cart && cart.cart_id ? '/api/cart/edit' : '/api/cart/add';
|
||||
let minBuy = data.min_buy > 0 ? data.min_buy : 1;
|
||||
let num = cartNum >= minBuy ? cartNum : minBuy;
|
||||
let _num = num;
|
||||
if (cart && cart.cart_id) {
|
||||
_num = _num + (data.min_buy > 0 ? data.min_buy : 1)
|
||||
}
|
||||
let cart_id = cart ? cart.cart_id : 0;
|
||||
if (_num > parseInt(data.stock)) {
|
||||
this.$util.showToast({
|
||||
title: '商品库存不足'
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (data.is_limit && data.max_buy && _num > parseInt(data.max_buy)) {
|
||||
this.$util.showToast({
|
||||
title: `该商品每人限购${data.max_buy}${data.unit || '件'}`
|
||||
});
|
||||
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 (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
|
||||
};
|
||||
}
|
||||
|
||||
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
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
/**
|
||||
* 多规格
|
||||
* @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(',');
|
||||
else item.sku_images = [];
|
||||
|
||||
// 多规格时合并主图
|
||||
if (item.goods_spec_format && item.goods_image) {
|
||||
item.goods_image = item.goods_image.split(',');
|
||||
item.sku_images = item.goods_image.concat(item.sku_images);
|
||||
}
|
||||
|
||||
// 当前商品SKU规格
|
||||
if (item.sku_spec_format) item.sku_spec_format = JSON.parse(item.sku_spec_format);
|
||||
|
||||
// 商品SKU格式
|
||||
if (item.goods_spec_format) item.goods_spec_format = JSON.parse(item.goods_spec_format);
|
||||
|
||||
// 限时折扣
|
||||
if (item.promotion_type == 1) {
|
||||
item.discountTimeMachine = this.$util.countDown(item.end_time - res.timestamp);
|
||||
}
|
||||
|
||||
if (item.promotion_type == 1 && item.discountTimeMachine) {
|
||||
if (item.member_price > 0 && Number(item.member_price) <= Number(item.discount_price)) {
|
||||
item.show_price = item.member_price;
|
||||
} else {
|
||||
item.show_price = item.discount_price;
|
||||
}
|
||||
} else if (item.member_price > 0) {
|
||||
item.show_price = item.member_price;
|
||||
} else {
|
||||
item.show_price = item.price;
|
||||
}
|
||||
this.goodsDetail = item;
|
||||
|
||||
this.$nextTick(() => {
|
||||
if (this.$refs.goodsSku) {
|
||||
this.$refs.goodsSku.show("join_cart", (res) => {
|
||||
|
||||
let goods = this.cartList['goods_' + res.goods_id];
|
||||
let cart = null;
|
||||
if (goods && 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] = {
|
||||
cart_id: res.cart_id,
|
||||
goods_id: res.goods_id,
|
||||
sku_id: res.sku_id,
|
||||
num: res.num,
|
||||
discount_price: res.discount_price
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
this.$store.dispatch('cartCalculate');
|
||||
this.$emit("cartListChange", this.cartList);
|
||||
|
||||
// 加入购物车动效
|
||||
setTimeout(() => {
|
||||
this.$store.commit('setCartChange');
|
||||
}, 100);
|
||||
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
refreshGoodsSkuDetail(data) {
|
||||
this.goodsDetail = Object.assign({}, this.goodsDetail, data);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,89 +1,89 @@
|
||||
<template>
|
||||
<view class="mescroll-downwarp">
|
||||
<view class="downwarp-content">
|
||||
<view class="downwarp-progress mescroll-rotate" style="transform" v-if="isRotate"></view>
|
||||
<view class="downwarp-tip">{{ downText }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'ns-loading',
|
||||
props: {
|
||||
downText: {
|
||||
type: String,
|
||||
default: $lang('common.ns-loading.l16.t0')
|
||||
},
|
||||
isRotate: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isShow: true
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
show() {
|
||||
this.isShow = true;
|
||||
},
|
||||
hide() {
|
||||
this.isShow = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
/* 下拉刷新区域 */
|
||||
.mescroll-downwarp {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* 下拉刷新--内容区,定位于区域底部 */
|
||||
.mescroll-downwarp .downwarp-content {
|
||||
width: 100%;
|
||||
min-height: 60rpx;
|
||||
padding: 20rpx 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* 下拉刷新--提示文本 */
|
||||
.mescroll-downwarp .downwarp-tip {
|
||||
display: inline-block;
|
||||
font-size: 28rpx;
|
||||
color: gray;
|
||||
vertical-align: middle;
|
||||
margin-left: 16rpx;
|
||||
}
|
||||
|
||||
/* 下拉刷新--旋转进度条 */
|
||||
.mescroll-downwarp .downwarp-progress {
|
||||
display: inline-block;
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
border-radius: 50%;
|
||||
border: 2rpx solid gray;
|
||||
border-bottom-color: transparent;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
/* 旋转动画 */
|
||||
.mescroll-downwarp .mescroll-rotate {
|
||||
animation: mescrollDownRotate 0.6s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes mescrollDownRotate {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<template>
|
||||
<view class="mescroll-downwarp">
|
||||
<view class="downwarp-content">
|
||||
<view class="downwarp-progress mescroll-rotate" style="transform" v-if="isRotate"></view>
|
||||
<view class="downwarp-tip">{{ downText }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'ns-loading',
|
||||
props: {
|
||||
downText: {
|
||||
type: String,
|
||||
default: '加载中'
|
||||
},
|
||||
isRotate: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isShow: true
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
show() {
|
||||
this.isShow = true;
|
||||
},
|
||||
hide() {
|
||||
this.isShow = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
/* 下拉刷新区域 */
|
||||
.mescroll-downwarp {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* 下拉刷新--内容区,定位于区域底部 */
|
||||
.mescroll-downwarp .downwarp-content {
|
||||
width: 100%;
|
||||
min-height: 60rpx;
|
||||
padding: 20rpx 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* 下拉刷新--提示文本 */
|
||||
.mescroll-downwarp .downwarp-tip {
|
||||
display: inline-block;
|
||||
font-size: 28rpx;
|
||||
color: gray;
|
||||
vertical-align: middle;
|
||||
margin-left: 16rpx;
|
||||
}
|
||||
|
||||
/* 下拉刷新--旋转进度条 */
|
||||
.mescroll-downwarp .downwarp-progress {
|
||||
display: inline-block;
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
border-radius: 50%;
|
||||
border: 2rpx solid gray;
|
||||
border-bottom-color: transparent;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
/* 旋转动画 */
|
||||
.mescroll-downwarp .mescroll-rotate {
|
||||
animation: mescrollDownRotate 0.6s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes mescrollDownRotate {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,404 +1,404 @@
|
||||
<template>
|
||||
<!-- <view class="ns-navbar-wrap" :class="'style-' + data.navStyle">
|
||||
|
||||
<view class="u-navbar" :style="{ backgroundColor: bgColor, paddingTop: navbarHeight + 'px' }">
|
||||
<view class="navbar-inner" :style="navbarInnerStyle">
|
||||
<view class="back-wrap" v-if="isBack && isBackShow" @tap="goBack">
|
||||
<text class="iconfont icon-back_light" :style="{ color: titleColor }"></text>
|
||||
</view>
|
||||
|
||||
<view v-if="data.navStyle == 1" class="content-wrap" :class="[data.textImgPosLink, isBack && isBackShow ? 'have-back' : '']" @click="toLink(data.moreLink.wap_url)">
|
||||
<view class="title-wrap" :style="{ fontSize: '14px', color: data.textNavColor, textAlign: data.textImgPosLink }">
|
||||
{{ data.title }}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-if="data.navStyle == 2" class="content-wrap" @click="toLink(data.moreLink.wap_url)">
|
||||
<view class="title-wrap" :style="{ color: data.textNavColor }">
|
||||
<view>
|
||||
<image :src="$util.img(data.topNavImg)" mode="heightFix" show-menu-by-longpress></image>
|
||||
</view>
|
||||
<view :style="{ color: data.textNavColor }">{{ data.title }}</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-if="data.navStyle == 3" class="content-wrap">
|
||||
<view class="title-wrap" @click="toLink(data.moreLink.wap_url)">
|
||||
<image :src="$util.img(data.topNavImg)" mode="aspectFit" show-menu-by-longpress></image>
|
||||
</view>
|
||||
<view class="search" @click="$util.redirectTo('/pages_tool/goods/search')" :style="{ height: menuButtonInfo.height - 2 + 'px', lineHeight: menuButtonInfo.height - 2 + 'px' }">
|
||||
<text class="iconfont icon-sousuo3"></text>
|
||||
<text>{{ $lang("common.ns-navbar.l31.t0") }}</text>
|
||||
</view>
|
||||
<view :style="{ 'width': capsuleWidth }"></view>
|
||||
</view>
|
||||
|
||||
<view v-if="data.navStyle == 4" class="content-wrap" :class="{ 'have-back': isBack && isBackShow }" @click="chooseOtherStore()">
|
||||
<text class="iconfont icon-dizhi" :style="{ color: data.textNavColor }"></text>
|
||||
<view v-if="globalStoreInfo && globalStoreInfo.store_id" class="title-wrap" :style="{ color: data.textNavColor }">{{ globalStoreInfo.store_name }}</view>
|
||||
<view v-else class="title-wrap" :style="{ color: data.textNavColor }">{{ $lang("common.ns-navbar.l39.t0") }}</view>
|
||||
<text class="iconfont icon-right" :style="{ color: data.textNavColor }"></text>
|
||||
<view class="nearby-store-name" :style="{ color: data.textNavColor }">{{ $lang("common.ns-navbar.l41.t0") }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="u-navbar-placeholder" :style="{ width: '100%', paddingTop: placeholderHeight + 'px' }"></view>
|
||||
|
||||
</view> -->
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// 获取系统状态栏的高度
|
||||
let systemInfo = uni.getSystemInfoSync();
|
||||
let menuButtonInfo = {};
|
||||
// 如果是小程序,获取右上角胶囊的尺寸信息,避免导航栏右侧内容与胶囊重叠(支付宝小程序非本API,尚未兼容)
|
||||
// #ifdef MP-WEIXIN || MP-BAIDU || MP-TOUTIAO || MP-QQ
|
||||
menuButtonInfo = uni.getMenuButtonBoundingClientRect();
|
||||
// #endif
|
||||
|
||||
// 自定义导航栏
|
||||
export default {
|
||||
name: 'ns-navbar',
|
||||
props: {
|
||||
data: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
// 标题的颜色
|
||||
titleColor: {
|
||||
type: String,
|
||||
default: '#606266'
|
||||
},
|
||||
// 自定义返回逻辑
|
||||
customBack: {
|
||||
type: Function,
|
||||
default: null
|
||||
},
|
||||
scrollTop: {
|
||||
type: [String, Number],
|
||||
default: '0'
|
||||
},
|
||||
// 是否显示导航栏左边返回图标和辅助文字
|
||||
isBack: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
menuButtonInfo: menuButtonInfo,
|
||||
isBackShow: false,
|
||||
placeholderHeight: 0
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
// 导航栏内部盒子的样式
|
||||
navbarInnerStyle() {
|
||||
let style = '';
|
||||
// 导航栏宽度,如果在小程序下,导航栏宽度为胶囊的左边到屏幕左边的距离
|
||||
style += 'height:' + menuButtonInfo.height * 2 + 'rpx;';
|
||||
return style;
|
||||
},
|
||||
// 转换字符数值为真正的数值
|
||||
navbarHeight() {
|
||||
// #ifdef APP-PLUS || H5
|
||||
return 25;
|
||||
// #endif
|
||||
// #ifdef MP
|
||||
// 小程序特别处理,让导航栏高度 = 胶囊高度 + 两倍胶囊顶部与状态栏底部的距离之差(相当于同时获得了导航栏底部与胶囊底部的距离)
|
||||
let height = menuButtonInfo.top;
|
||||
return height;
|
||||
// #endif
|
||||
},
|
||||
bgColor() {
|
||||
var color = '';
|
||||
if (this.data.topNavBg) {
|
||||
// 顶部透明
|
||||
color = 'transparent';
|
||||
let top = 0;
|
||||
|
||||
if (this.data.navStyle == 4) {
|
||||
// #ifdef H5
|
||||
top = 15;
|
||||
// #endif
|
||||
// #ifdef MP
|
||||
top = this.navbarHeight - 25;
|
||||
// #endif
|
||||
}
|
||||
|
||||
if (this.scrollTop > top) {
|
||||
color = this.data.topNavColor;
|
||||
} else {
|
||||
color = 'transparent';
|
||||
}
|
||||
} else {
|
||||
color = this.data.topNavColor;
|
||||
}
|
||||
return color;
|
||||
},
|
||||
capsuleWidth() {
|
||||
let width = `calc(100vw - ${this.menuButtonInfo.right}px + ${this.menuButtonInfo.width}px + 10px)`;
|
||||
return width;
|
||||
}
|
||||
},
|
||||
created(e) {
|
||||
// var pages = getCurrentPages();
|
||||
// if (pages.length > 1) {
|
||||
// this.isBackShow = true;
|
||||
// }
|
||||
// this.navbarPlaceholderHeight();
|
||||
},
|
||||
mounted() {
|
||||
// this.setModuleLocationFn();
|
||||
},
|
||||
methods: {
|
||||
toLink(val) {
|
||||
if (val) this.$util.redirectTo(val);
|
||||
},
|
||||
goBack() {
|
||||
// 如果自定义了点击返回按钮的函数,则执行,否则执行返回逻辑
|
||||
if (typeof this.customBack === 'function') {
|
||||
this.customBack();
|
||||
} else {
|
||||
uni.navigateBack();
|
||||
}
|
||||
},
|
||||
// 选择其他门店
|
||||
chooseOtherStore() {
|
||||
if (this.globalStoreConfig && this.globalStoreConfig.is_allow_change == 1) {
|
||||
this.$util.redirectTo('/pages_tool/store/list');
|
||||
} else if (this.globalStoreInfo) {
|
||||
// 禁止切换门店,进入门店详情
|
||||
this.$util.redirectTo('/pages_tool/store/detail', {
|
||||
store_id: this.globalStoreInfo.store_id
|
||||
});
|
||||
}
|
||||
},
|
||||
navbarPlaceholderHeight() {
|
||||
let height = 0;
|
||||
setTimeout(() => {
|
||||
const query = uni.createSelectorQuery().in(this);
|
||||
query
|
||||
.select('.ns-navbar-wrap .u-navbar')
|
||||
.boundingClientRect(data => {
|
||||
// 获取公告自身高度
|
||||
this.placeholderHeight = data.height;
|
||||
})
|
||||
.exec();
|
||||
});
|
||||
},
|
||||
// 向vuex中的diyIndexPositionObj增加公告导航组件定位位置
|
||||
setModuleLocationFn() {
|
||||
const query = uni.createSelectorQuery().in(this);
|
||||
query.select('.ns-navbar-wrap .u-navbar')
|
||||
.boundingClientRect(data => {
|
||||
let diyIndexPage = {
|
||||
originalVal: data.height || 0, //自身高度 px
|
||||
currVal: 0 //定位高度
|
||||
};
|
||||
this.$store.commit('setDiyGroupPositionObj', {
|
||||
'nsNavbar': diyIndexPage
|
||||
});
|
||||
}).exec();
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
/* #ifdef H5 */
|
||||
.style-1,
|
||||
.style-2,
|
||||
.style-3 {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* #endif */
|
||||
|
||||
.u-navbar {
|
||||
width: 100%;
|
||||
transition: background 0.3s;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
z-index: 991;
|
||||
}
|
||||
|
||||
.navbar-inner {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
position: relative;
|
||||
align-items: center;
|
||||
padding-bottom: 20rpx;
|
||||
/* #ifdef H5 */
|
||||
padding-bottom: 40rpx;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.back-wrap {
|
||||
padding: 0 14rpx 0 24rpx;
|
||||
|
||||
.iconfont {
|
||||
font-size: 44rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.content-wrap {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
flex: 1;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
height: 60rpx;
|
||||
text-align: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.title-wrap {
|
||||
line-height: 1;
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
font-size: 32rpx;
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
.ns-navbar-wrap {
|
||||
|
||||
&.style-1 {
|
||||
.content-wrap {
|
||||
.title-wrap {
|
||||
font-size: 27rpx;
|
||||
}
|
||||
|
||||
&.left {
|
||||
left: 30rpx;
|
||||
}
|
||||
|
||||
&.center {
|
||||
left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
&.have-back {
|
||||
left: 90rpx;
|
||||
padding-right: 200rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.style-2 {
|
||||
.content-wrap {
|
||||
.title-wrap {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
text-align: left;
|
||||
|
||||
>view {
|
||||
height: 56rpx;
|
||||
line-height: 56rpx;
|
||||
max-width: 300rpx;
|
||||
margin-left: 30rpx;
|
||||
font-size: 27rpx;
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
overflow: hidden; //超出的文本隐藏
|
||||
text-overflow: ellipsis; //用省略号显示
|
||||
white-space: nowrap; //不换行
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.style-3 {
|
||||
.content-wrap {
|
||||
.title-wrap {
|
||||
height: 60rpx;
|
||||
width: 170rpx;
|
||||
max-width: 170rpx;
|
||||
margin-left: 30rpx;
|
||||
flex: initial;
|
||||
text-align: center;
|
||||
margin-right: 10rpx;
|
||||
|
||||
image {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.search {
|
||||
flex: 1;
|
||||
padding: 0 20rpx;
|
||||
background-color: #fff;
|
||||
text-align: left;
|
||||
border-radius: 60rpx;
|
||||
height: 60rpx;
|
||||
line-height: 60rpx;
|
||||
border: 1px solid #eeeeee;
|
||||
color: rgb(102, 102, 102);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-right: 10rpx;
|
||||
|
||||
.iconfont {
|
||||
color: #909399;
|
||||
font-size: 32rpx;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.style-4 {
|
||||
.icon-dizhi{
|
||||
font-size: 28rpx;
|
||||
}
|
||||
.content-wrap {
|
||||
top: initial;
|
||||
text-align: left;
|
||||
padding-left: 30rpx;
|
||||
|
||||
&.have-back {
|
||||
left: 60rpx;
|
||||
right: 190rpx;
|
||||
}
|
||||
|
||||
.title-wrap {
|
||||
flex: none;
|
||||
margin: 0 10rpx;
|
||||
max-width: 360rpx;
|
||||
font-size: 27rpx;
|
||||
}
|
||||
|
||||
.icon-right {
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.nearby-store-name {
|
||||
margin: 0 10rpx;
|
||||
background: rgba(0, 0, 0, .2);
|
||||
font-size: 22rpx;
|
||||
border-radius: 40rpx;
|
||||
padding: 10rpx 20rpx;
|
||||
line-height: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
<template>
|
||||
<!-- <view class="ns-navbar-wrap" :class="'style-' + data.navStyle">
|
||||
|
||||
<view class="u-navbar" :style="{ backgroundColor: bgColor, paddingTop: navbarHeight + 'px' }">
|
||||
<view class="navbar-inner" :style="navbarInnerStyle">
|
||||
<view class="back-wrap" v-if="isBack && isBackShow" @tap="goBack">
|
||||
<text class="iconfont icon-back_light" :style="{ color: titleColor }"></text>
|
||||
</view>
|
||||
|
||||
<view v-if="data.navStyle == 1" class="content-wrap" :class="[data.textImgPosLink, isBack && isBackShow ? 'have-back' : '']" @click="toLink(data.moreLink.wap_url)">
|
||||
<view class="title-wrap" :style="{ fontSize: '14px', color: data.textNavColor, textAlign: data.textImgPosLink }">
|
||||
{{ data.title }}
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-if="data.navStyle == 2" class="content-wrap" @click="toLink(data.moreLink.wap_url)">
|
||||
<view class="title-wrap" :style="{ color: data.textNavColor }">
|
||||
<view>
|
||||
<image :src="$util.img(data.topNavImg)" mode="heightFix" show-menu-by-longpress></image>
|
||||
</view>
|
||||
<view :style="{ color: data.textNavColor }">{{ data.title }}</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-if="data.navStyle == 3" class="content-wrap">
|
||||
<view class="title-wrap" @click="toLink(data.moreLink.wap_url)">
|
||||
<image :src="$util.img(data.topNavImg)" mode="aspectFit" show-menu-by-longpress></image>
|
||||
</view>
|
||||
<view class="search" @click="$util.redirectTo('/pages_tool/goods/search')" :style="{ height: menuButtonInfo.height - 2 + 'px', lineHeight: menuButtonInfo.height - 2 + 'px' }">
|
||||
<text class="iconfont icon-sousuo3"></text>
|
||||
<text>请输入商品名称</text>
|
||||
</view>
|
||||
<view :style="{ 'width': capsuleWidth }"></view>
|
||||
</view>
|
||||
|
||||
<view v-if="data.navStyle == 4" class="content-wrap" :class="{ 'have-back': isBack && isBackShow }" @click="chooseOtherStore()">
|
||||
<text class="iconfont icon-dizhi" :style="{ color: data.textNavColor }"></text>
|
||||
<view v-if="globalStoreInfo && globalStoreInfo.store_id" class="title-wrap" :style="{ color: data.textNavColor }">{{ globalStoreInfo.store_name }}</view>
|
||||
<view v-else class="title-wrap" :style="{ color: data.textNavColor }">定位中...</view>
|
||||
<text class="iconfont icon-right" :style="{ color: data.textNavColor }"></text>
|
||||
<view class="nearby-store-name" :style="{ color: data.textNavColor }">附近门店</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="u-navbar-placeholder" :style="{ width: '100%', paddingTop: placeholderHeight + 'px' }"></view>
|
||||
|
||||
</view> -->
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// 获取系统状态栏的高度
|
||||
let systemInfo = uni.getSystemInfoSync();
|
||||
let menuButtonInfo = {};
|
||||
// 如果是小程序,获取右上角胶囊的尺寸信息,避免导航栏右侧内容与胶囊重叠(支付宝小程序非本API,尚未兼容)
|
||||
// #ifdef MP-WEIXIN || MP-BAIDU || MP-TOUTIAO || MP-QQ
|
||||
menuButtonInfo = uni.getMenuButtonBoundingClientRect();
|
||||
// #endif
|
||||
|
||||
// 自定义导航栏
|
||||
export default {
|
||||
name: 'ns-navbar',
|
||||
props: {
|
||||
data: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
// 标题的颜色
|
||||
titleColor: {
|
||||
type: String,
|
||||
default: '#606266'
|
||||
},
|
||||
// 自定义返回逻辑
|
||||
customBack: {
|
||||
type: Function,
|
||||
default: null
|
||||
},
|
||||
scrollTop: {
|
||||
type: [String, Number],
|
||||
default: '0'
|
||||
},
|
||||
// 是否显示导航栏左边返回图标和辅助文字
|
||||
isBack: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
menuButtonInfo: menuButtonInfo,
|
||||
isBackShow: false,
|
||||
placeholderHeight: 0
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
// 导航栏内部盒子的样式
|
||||
navbarInnerStyle() {
|
||||
let style = '';
|
||||
// 导航栏宽度,如果在小程序下,导航栏宽度为胶囊的左边到屏幕左边的距离
|
||||
style += 'height:' + menuButtonInfo.height * 2 + 'rpx;';
|
||||
return style;
|
||||
},
|
||||
// 转换字符数值为真正的数值
|
||||
navbarHeight() {
|
||||
// #ifdef APP-PLUS || H5
|
||||
return 25;
|
||||
// #endif
|
||||
// #ifdef MP
|
||||
// 小程序特别处理,让导航栏高度 = 胶囊高度 + 两倍胶囊顶部与状态栏底部的距离之差(相当于同时获得了导航栏底部与胶囊底部的距离)
|
||||
let height = menuButtonInfo.top;
|
||||
return height;
|
||||
// #endif
|
||||
},
|
||||
bgColor() {
|
||||
var color = '';
|
||||
if (this.data.topNavBg) {
|
||||
// 顶部透明
|
||||
color = 'transparent';
|
||||
let top = 0;
|
||||
|
||||
if (this.data.navStyle == 4) {
|
||||
// #ifdef H5
|
||||
top = 15;
|
||||
// #endif
|
||||
// #ifdef MP
|
||||
top = this.navbarHeight - 25;
|
||||
// #endif
|
||||
}
|
||||
|
||||
if (this.scrollTop > top) {
|
||||
color = this.data.topNavColor;
|
||||
} else {
|
||||
color = 'transparent';
|
||||
}
|
||||
} else {
|
||||
color = this.data.topNavColor;
|
||||
}
|
||||
return color;
|
||||
},
|
||||
capsuleWidth() {
|
||||
let width = `calc(100vw - ${this.menuButtonInfo.right}px + ${this.menuButtonInfo.width}px + 10px)`;
|
||||
return width;
|
||||
}
|
||||
},
|
||||
created(e) {
|
||||
// var pages = getCurrentPages();
|
||||
// if (pages.length > 1) {
|
||||
// this.isBackShow = true;
|
||||
// }
|
||||
// this.navbarPlaceholderHeight();
|
||||
},
|
||||
mounted() {
|
||||
// this.setModuleLocationFn();
|
||||
},
|
||||
methods: {
|
||||
toLink(val) {
|
||||
if (val) this.$util.redirectTo(val);
|
||||
},
|
||||
goBack() {
|
||||
// 如果自定义了点击返回按钮的函数,则执行,否则执行返回逻辑
|
||||
if (typeof this.customBack === 'function') {
|
||||
this.customBack();
|
||||
} else {
|
||||
uni.navigateBack();
|
||||
}
|
||||
},
|
||||
// 选择其他门店
|
||||
chooseOtherStore() {
|
||||
if (this.globalStoreConfig && this.globalStoreConfig.is_allow_change == 1) {
|
||||
this.$util.redirectTo('/pages_tool/store/list');
|
||||
} else if (this.globalStoreInfo) {
|
||||
// 禁止切换门店,进入门店详情
|
||||
this.$util.redirectTo('/pages_tool/store/detail', {
|
||||
store_id: this.globalStoreInfo.store_id
|
||||
});
|
||||
}
|
||||
},
|
||||
navbarPlaceholderHeight() {
|
||||
let height = 0;
|
||||
setTimeout(() => {
|
||||
const query = uni.createSelectorQuery().in(this);
|
||||
query
|
||||
.select('.ns-navbar-wrap .u-navbar')
|
||||
.boundingClientRect(data => {
|
||||
// 获取公告自身高度
|
||||
this.placeholderHeight = data.height;
|
||||
})
|
||||
.exec();
|
||||
});
|
||||
},
|
||||
// 向vuex中的diyIndexPositionObj增加公告导航组件定位位置
|
||||
setModuleLocationFn() {
|
||||
const query = uni.createSelectorQuery().in(this);
|
||||
query.select('.ns-navbar-wrap .u-navbar')
|
||||
.boundingClientRect(data => {
|
||||
let diyIndexPage = {
|
||||
originalVal: data.height || 0, //自身高度 px
|
||||
currVal: 0 //定位高度
|
||||
};
|
||||
this.$store.commit('setDiyGroupPositionObj', {
|
||||
'nsNavbar': diyIndexPage
|
||||
});
|
||||
}).exec();
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
/* #ifdef H5 */
|
||||
.style-1,
|
||||
.style-2,
|
||||
.style-3 {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* #endif */
|
||||
|
||||
.u-navbar {
|
||||
width: 100%;
|
||||
transition: background 0.3s;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
z-index: 991;
|
||||
}
|
||||
|
||||
.navbar-inner {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
position: relative;
|
||||
align-items: center;
|
||||
padding-bottom: 20rpx;
|
||||
/* #ifdef H5 */
|
||||
padding-bottom: 40rpx;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
.back-wrap {
|
||||
padding: 0 14rpx 0 24rpx;
|
||||
|
||||
.iconfont {
|
||||
font-size: 44rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.content-wrap {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
flex: 1;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
height: 60rpx;
|
||||
text-align: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.title-wrap {
|
||||
line-height: 1;
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
font-size: 32rpx;
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
.ns-navbar-wrap {
|
||||
|
||||
&.style-1 {
|
||||
.content-wrap {
|
||||
.title-wrap {
|
||||
font-size: 27rpx;
|
||||
}
|
||||
|
||||
&.left {
|
||||
left: 30rpx;
|
||||
}
|
||||
|
||||
&.center {
|
||||
left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
&.have-back {
|
||||
left: 90rpx;
|
||||
padding-right: 200rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.style-2 {
|
||||
.content-wrap {
|
||||
.title-wrap {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
text-align: left;
|
||||
|
||||
>view {
|
||||
height: 56rpx;
|
||||
line-height: 56rpx;
|
||||
max-width: 300rpx;
|
||||
margin-left: 30rpx;
|
||||
font-size: 27rpx;
|
||||
|
||||
image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
overflow: hidden; //超出的文本隐藏
|
||||
text-overflow: ellipsis; //用省略号显示
|
||||
white-space: nowrap; //不换行
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.style-3 {
|
||||
.content-wrap {
|
||||
.title-wrap {
|
||||
height: 60rpx;
|
||||
width: 170rpx;
|
||||
max-width: 170rpx;
|
||||
margin-left: 30rpx;
|
||||
flex: initial;
|
||||
text-align: center;
|
||||
margin-right: 10rpx;
|
||||
|
||||
image {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.search {
|
||||
flex: 1;
|
||||
padding: 0 20rpx;
|
||||
background-color: #fff;
|
||||
text-align: left;
|
||||
border-radius: 60rpx;
|
||||
height: 60rpx;
|
||||
line-height: 60rpx;
|
||||
border: 1px solid #eeeeee;
|
||||
color: rgb(102, 102, 102);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-right: 10rpx;
|
||||
|
||||
.iconfont {
|
||||
color: #909399;
|
||||
font-size: 32rpx;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.style-4 {
|
||||
.icon-dizhi{
|
||||
font-size: 28rpx;
|
||||
}
|
||||
.content-wrap {
|
||||
top: initial;
|
||||
text-align: left;
|
||||
padding-left: 30rpx;
|
||||
|
||||
&.have-back {
|
||||
left: 60rpx;
|
||||
right: 190rpx;
|
||||
}
|
||||
|
||||
.title-wrap {
|
||||
flex: none;
|
||||
margin: 0 10rpx;
|
||||
max-width: 360rpx;
|
||||
font-size: 27rpx;
|
||||
}
|
||||
|
||||
.icon-right {
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.nearby-store-name {
|
||||
margin: 0 10rpx;
|
||||
background: rgba(0, 0, 0, .2);
|
||||
font-size: 22rpx;
|
||||
border-radius: 40rpx;
|
||||
padding: 10rpx 20rpx;
|
||||
line-height: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -50,7 +50,7 @@
|
||||
</view>
|
||||
<view :class="['box', 'box-flex', 'align-right']">
|
||||
<text v-if="item.val != ''">{{ item.val }}</text>
|
||||
<text v-else class="color-tip">{{ item.value.placeholder || $lang('common.ns-form.l37.t0') }}</text>
|
||||
<text v-else class="color-tip">{{ item.value.placeholder || '请选择' }}</text>
|
||||
<text class="iconfont icon-right"></text>
|
||||
</view>
|
||||
</view>
|
||||
@@ -146,7 +146,7 @@
|
||||
@change="bindDateChange($event, index)"
|
||||
>
|
||||
<view :class="['uni-input', !item.val ? 'color-tip' : '']">
|
||||
{{ item.val ? item.val : (item.value.placeholder || $lang('common.ns-newform.l149.t0')) }}
|
||||
{{ item.val ? item.val : (item.value.placeholder || '请选择日期') }}
|
||||
</view>
|
||||
</picker>
|
||||
<text class="iconfont icon-right"></text>
|
||||
@@ -170,7 +170,7 @@
|
||||
>
|
||||
<view class="picker-box">
|
||||
<view :class="['uni-input', !item.start_date ? 'color-tip' : '']">
|
||||
{{ item.start_date ? item.start_date : (item.value.placeholder_start || $lang('common.ns-newform.l173.t0')) }}
|
||||
{{ item.start_date ? item.start_date : (item.value.placeholder_start || '开始日期') }}
|
||||
</view>
|
||||
</view>
|
||||
</picker>
|
||||
@@ -184,7 +184,7 @@
|
||||
>
|
||||
<view class="picker-box">
|
||||
<view :class="['uni-input', !item.end_date ? 'color-tip' : '']">
|
||||
{{ item.end_date ? item.end_date : (item.value.placeholder_end || $lang('common.ns-newform.l187.t0')) }}
|
||||
{{ item.end_date ? item.end_date : (item.value.placeholder_end || '结束日期') }}
|
||||
</view>
|
||||
</view>
|
||||
</picker>
|
||||
@@ -207,7 +207,7 @@
|
||||
@change="bindTimeChange($event, index)"
|
||||
>
|
||||
<view :class="['uni-input', !item.val ? 'color-tip' : '']">
|
||||
{{ item.val ? item.val : (item.value.placeholder || $lang('common.ns-newform.l210.t0')) }}
|
||||
{{ item.val ? item.val : (item.value.placeholder || '请选择时间') }}
|
||||
</view>
|
||||
</picker>
|
||||
<text class="iconfont icon-right"></text>
|
||||
@@ -231,7 +231,7 @@
|
||||
>
|
||||
<view class="picker-box">
|
||||
<view :class="['uni-input', !item.start_time ? 'color-tip' : '']">
|
||||
{{ item.start_time ? item.start_time : (item.value.placeholder_start || $lang('common.ns-newform.l234.t0')) }}
|
||||
{{ item.start_time ? item.start_time : (item.value.placeholder_start || '开始时间') }}
|
||||
</view>
|
||||
</view>
|
||||
</picker>
|
||||
@@ -245,7 +245,7 @@
|
||||
>
|
||||
<view class="picker-box">
|
||||
<view :class="['uni-input', !item.end_time ? 'color-tip' : '']">
|
||||
{{ item.end_time ? item.end_time : (item.value.placeholder_end || $lang('common.ns-newform.l248.t0')) }}
|
||||
{{ item.end_time ? item.end_time : (item.value.placeholder_end || '结束时间') }}
|
||||
</view>
|
||||
</view>
|
||||
</picker>
|
||||
@@ -268,7 +268,7 @@
|
||||
@getRegions="handleGetRegions($event, index)"
|
||||
>
|
||||
<view :class="['select-address', !item.val ? 'empty' : '', !item.val ? 'color-tip' : '']">
|
||||
{{ item.val ? item.val : (item.value.placeholder || (item.value.default_type == 1 ? '请选择省市' : $lang('common.ns-newform.l271.t0'))) }}
|
||||
{{ item.val ? item.val : (item.value.placeholder || (item.value.default_type == 1 ? '请选择省市' : '请选择省市区')) }}
|
||||
</view>
|
||||
</pick-regions>
|
||||
<text class="iconfont icon-right"></text>
|
||||
@@ -788,89 +788,89 @@ export default {
|
||||
|
||||
if (item.controller == 'Text') {
|
||||
if (item.value.required && !item.val) {
|
||||
this.$util.showToast({ title: $lang('common.ns-form.l368.t0') + item.value.title });
|
||||
this.$util.showToast({ title: '请输入' + item.value.title });
|
||||
return false;
|
||||
}
|
||||
|
||||
if (item.name == 'ID_CARD' && !/(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/.test(item.val)) {
|
||||
if (!item.value.required) {
|
||||
this.$util.showToast({ title: $lang('common.ns-form.l378.t0') });
|
||||
this.$util.showToast({ title: '身份证输入不合法' });
|
||||
return false;
|
||||
}
|
||||
if (item.val != '') {
|
||||
this.$util.showToast({ title: $lang('common.ns-form.l378.t0') });
|
||||
this.$util.showToast({ title: '身份证输入不合法' });
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (item.name == 'MOBILE' && !this.$util.verifyMobile(item.val)) {
|
||||
if (!item.value.required) {
|
||||
this.$util.showToast({ title: $lang('common.ns-form.l395.t0') });
|
||||
this.$util.showToast({ title: '手机号输入不合法' });
|
||||
return false;
|
||||
}
|
||||
if (item.val != '') {
|
||||
this.$util.showToast({ title: $lang('common.ns-form.l395.t0') });
|
||||
this.$util.showToast({ title: '手机号输入不合法' });
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (item.controller == 'Textarea' && item.value.required && !item.val) {
|
||||
this.$util.showToast({ title: $lang('common.ns-form.l368.t0') + item.value.title });
|
||||
this.$util.showToast({ title: '请输入' + item.value.title });
|
||||
return false;
|
||||
}
|
||||
|
||||
if (item.controller == 'Select' && item.value.required && !item.val) {
|
||||
this.$util.showToast({ title: $lang('common.ns-form.l37.t0') + item.value.title });
|
||||
this.$util.showToast({ title: '请选择' + item.value.title });
|
||||
return false;
|
||||
}
|
||||
|
||||
if (item.controller == 'Checkbox' && item.value.required && !item.val) {
|
||||
this.$util.showToast({ title: $lang('common.ns-form.l432.t0') + item.value.title });
|
||||
this.$util.showToast({ title: '请至少选择一个' + item.value.title });
|
||||
return false;
|
||||
}
|
||||
|
||||
if (item.controller == 'Img' && item.value.required && !item.val) {
|
||||
this.$util.showToast({ title: $lang('common.ns-form.l442.t0') + item.value.title });
|
||||
this.$util.showToast({ title: '请至少上传一张' + item.value.title });
|
||||
return false;
|
||||
}
|
||||
|
||||
if (item.controller == 'Date' && item.value.required && !item.val) {
|
||||
this.$util.showToast({ title: $lang('common.ns-form.l37.t0') + item.value.title });
|
||||
this.$util.showToast({ title: '请选择' + item.value.title });
|
||||
return false;
|
||||
}
|
||||
|
||||
if (item.controller == 'Datelimit') {
|
||||
if (item.value.required && !item.val) {
|
||||
this.$util.showToast({ title: $lang('common.ns-form.l37.t0') + item.value.title });
|
||||
this.$util.showToast({ title: '请选择' + item.value.title });
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.$util.timeTurnTimeStamp(item.start_date) > this.$util.timeTurnTimeStamp(item.end_date)) {
|
||||
this.$util.showToast({ title: $lang('common.ns-form.l470.t0') });
|
||||
this.$util.showToast({ title: '结束日期不能小于开始日期' });
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (item.controller == 'Time' && item.value.required && !item.val) {
|
||||
this.$util.showToast({ title: $lang('common.ns-form.l37.t0') + item.value.title });
|
||||
this.$util.showToast({ title: '请选择' + item.value.title });
|
||||
return false;
|
||||
}
|
||||
|
||||
if (item.controller == 'Timelimit') {
|
||||
if (item.value.required && !item.val) {
|
||||
this.$util.showToast({ title: $lang('common.ns-form.l37.t0') + item.value.title });
|
||||
this.$util.showToast({ title: '请选择' + item.value.title });
|
||||
return false;
|
||||
}
|
||||
|
||||
if (item.start_time >= item.end_time) {
|
||||
this.$util.showToast({ title: $lang('common.ns-form.l498.t0') });
|
||||
this.$util.showToast({ title: '结束时间必须大于开始时间' });
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (item.controller == 'City' && item.value.required && !item.val) {
|
||||
this.$util.showToast({ title: $lang('common.ns-form.l37.t0') + item.value.title });
|
||||
this.$util.showToast({ title: '请选择' + item.value.title });
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -902,7 +902,7 @@ export default {
|
||||
if (res.length > 0) {
|
||||
res.forEach(function(img) {
|
||||
if (self.formData[index].img_lists.length >= Number(self.formData[index].value.max_count)) {
|
||||
self.$util.showToast({ title: $lang('common.ns-form.l545.t0') + self.formData[index].value.max_count + $lang('common.ns-form.l545.t1') });
|
||||
self.$util.showToast({ title: '最多上传' + self.formData[index].value.max_count + '张图片' });
|
||||
return false;
|
||||
}
|
||||
self.formData[index].img_lists.push(img);
|
||||
@@ -916,7 +916,7 @@ export default {
|
||||
addImg(index) {
|
||||
let self = this;
|
||||
if (this.formData[index].img_lists.length >= Number(this.formData[index].value.max_count)) {
|
||||
this.$util.showToast({ title: $lang('common.ns-form.l545.t0') + this.formData[index].value.max_count + $lang('common.ns-form.l545.t1') });
|
||||
this.$util.showToast({ title: '最多上传' + this.formData[index].value.max_count + '张图片' });
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,365 +1,365 @@
|
||||
<template>
|
||||
<view class="ns-time">
|
||||
<uni-popup type="bottom" ref="selectTime">
|
||||
<view class="box">
|
||||
<view class="title">
|
||||
<block v-if="obj.delivery && obj.delivery.delivery_type == 'local'">{{ $lang("common.ns-select-time.l6.t0") }}</block>
|
||||
<block v-if="obj.delivery && obj.delivery.delivery_type == 'store'">{{ $lang("common.ns-select-time.l7.t0") }}</block>
|
||||
<text class="iconfont icon-close" @click="close"></text>
|
||||
</view>
|
||||
<view class="body">
|
||||
<!-- 左侧日期选择 -->
|
||||
<scroll-view :scroll-y="true" class="left">
|
||||
<view class="item" :class="index == keyJudge ? 'itemDay' : ''" v-for="(item, index) in dayData" :key="index" @click="selectTime('days', index, 'yes')">
|
||||
<block v-if="item.title">{{ item.title }}</block>
|
||||
<block v-else>{{ item.month }}</block>
|
||||
<text class="itemtext">{{ item.Day }}</text>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<!-- 右侧时间选择 -->
|
||||
<scroll-view :scroll-y="true" class="right">
|
||||
<view class="item" :class="key == keyJudge && index == keys ? 'itemTime' : ''" v-for="(item, index) in timeData" :key="index" @click="selectTime('time', index, 'yes')">
|
||||
{{ item }}
|
||||
<text v-if="key == keyJudge && index == keys" class="iconfont icon-yuan_checked color-base-text"></text>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "nsSelectTime",
|
||||
data() {
|
||||
return {
|
||||
//选中日期的键值
|
||||
key: 0,
|
||||
//选中时间的键值
|
||||
keys: 0,
|
||||
//渲染用数据
|
||||
obj: {},
|
||||
//左侧渲染时间
|
||||
dayData: [],
|
||||
// 右侧渲染数据
|
||||
timeData: [],
|
||||
//判断弹窗打开
|
||||
judge: false,
|
||||
//判断左侧列表是否为日期选中列表
|
||||
keyJudge: 0,
|
||||
//当前时间时间戳
|
||||
dayTime: 0
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
refresh(){
|
||||
this.key = 0;
|
||||
this.keys = 0;
|
||||
this.keyJudge = 0;
|
||||
},
|
||||
/**
|
||||
* 弹窗打开
|
||||
*/
|
||||
open(obj, type) {
|
||||
this.dayData = [];
|
||||
this.timeData = [];
|
||||
this.obj = obj;
|
||||
this.toDay(obj.dataTime.time_type, obj.dataTime.time_week);
|
||||
if (this.judge) {
|
||||
if (type == 'no') {
|
||||
this.selectTime('', '', type);
|
||||
} else {
|
||||
this.$refs.selectTime.open();
|
||||
}
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 时间选择
|
||||
*/
|
||||
selectTime(type, index, judge) {
|
||||
if (type == 'days') {
|
||||
this.keyJudge = index;
|
||||
this.toTime();
|
||||
} else if (type == 'time') {
|
||||
this.keys = index;
|
||||
this.key = this.keyJudge;
|
||||
let obj = this.dayData[this.key];
|
||||
obj.time = this.timeData[this.keys];
|
||||
let time = obj.time.replace($lang('common.ns-select-time.l89.t0'),'').replace(')','');
|
||||
|
||||
var dateTime = new Date();
|
||||
var format = time.split('-');
|
||||
var startHours = format[0].split(':');
|
||||
var endHours = format[1].split(':');
|
||||
|
||||
let timeData = obj.month.split($lang('common.ns-select-time.l96.t0'));
|
||||
let month = timeData[0];
|
||||
let date = timeData[1].split($lang('common.ns-select-time.l98.t0'))[0];
|
||||
|
||||
// 开始时间戳
|
||||
dateTime.setHours(startHours[0],startHours[1],0,0);
|
||||
obj.start_time = dateTime.getTime()/1000;
|
||||
obj.start_date = dateTime.getFullYear() + '-' + month + '-' + date + ' ' + format[0];
|
||||
|
||||
// 结束时间戳
|
||||
dateTime.setHours(endHours[0],endHours[1],0,0);
|
||||
obj.end_time = dateTime.getTime()/1000;
|
||||
obj.end_date = dateTime.getFullYear() + '-' + month + '-' + date + ' ' + format[1];
|
||||
|
||||
this.$emit('selectTime', { data: obj, type: judge });
|
||||
this.$refs.selectTime.close();
|
||||
}
|
||||
|
||||
if (judge == 'no') {
|
||||
this.toTime(judge);
|
||||
let obj = this.dayData[0];
|
||||
obj.time = this.timeData[0];
|
||||
this.$emit('selectTime', { data: obj, type: judge });
|
||||
}
|
||||
this.$forceUpdate();
|
||||
},
|
||||
/**
|
||||
* 弹窗关闭
|
||||
*/
|
||||
close() {
|
||||
this.$refs.selectTime.close();
|
||||
},
|
||||
/**
|
||||
* 左侧数据处理
|
||||
*/
|
||||
toDay(type, obj) {
|
||||
let today = new Date();
|
||||
if (this.obj.dataTime.advance_day) {
|
||||
today = new Date(today.getTime() + (this.obj.dataTime.advance_day * 86400000));
|
||||
}
|
||||
let nowYear = today.getFullYear(); //当前年
|
||||
let nowMonth = today.getMonth() + 1; //当前月
|
||||
let nowDate = today.getDate(); //当前日
|
||||
let nowDay = today.getDay(); //当前星期几
|
||||
let endDay = new Date(nowYear, nowMonth, 0).getDate(); //当月多少天
|
||||
let Hours = today.getHours();
|
||||
let Minutes = today.getMinutes();
|
||||
this.dayTime = this.obj.dataTime.advance_day ? 0 : Number(Hours) * 3600 + Number(Minutes) * 60; //获取到当前时分秒的时间戳
|
||||
let judge = false;
|
||||
let num = 1; //记录循环执行过的次数
|
||||
let mostDay = this.obj.dataTime.most_day ? this.obj.dataTime.most_day + 1 : 1; // 最多可预约天数
|
||||
let startTime = parseInt(today.getTime() / 1000);
|
||||
let week = [$lang('common.ns-select-time.l148.t0'), $lang('common.ns-select-time.l148.t1'), $lang('common.ns-select-time.l148.t2'), $lang('common.ns-select-time.l148.t3'), $lang('common.ns-select-time.l148.t4'), $lang('common.ns-select-time.l148.t5'), $lang('common.ns-select-time.l148.t6')];
|
||||
if (obj.time_week && obj.time_week.length == 7) {
|
||||
//判断是否七天全有
|
||||
judge = true;
|
||||
}
|
||||
|
||||
for (let i = 0; i < mostDay; i++) {
|
||||
let objects = {};
|
||||
let dayStr = week[ nowDay ];
|
||||
// 判断最大可预约时间
|
||||
if (this.obj.dataTime.most_day > 0 && ((startTime + num * 86400) > (startTime + this.obj.dataTime.most_day * 86400) ) ) {
|
||||
this.judge = true;
|
||||
break;
|
||||
}
|
||||
//判断当天是否能够配送、自提
|
||||
if (type == 0 || judge || obj.indexOf(nowDay.toString()) != -1) {
|
||||
let endTime = this.obj.dataTime.delivery_time[ (this.obj.dataTime.delivery_time.length - 1) ].end_time;
|
||||
endTime -= this.obj.dataTime.time_interval * 60;
|
||||
switch (num) {
|
||||
case 1:
|
||||
if (i == 0) {
|
||||
if (endTime < this.dayTime) {
|
||||
i = i - 1;
|
||||
} else {
|
||||
objects = {
|
||||
title: this.obj.dataTime.advance_day == 0 ? '今天' : '',
|
||||
type: 'special',
|
||||
month: nowMonth + $lang('common.ns-select-time.l96.t0') + nowDate + $lang('common.ns-select-time.l98.t0'),
|
||||
Day: '(' + dayStr + ')'
|
||||
};
|
||||
this.dayData.push(objects); //左侧日期数据处理
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (i == 0 || i == 1) {
|
||||
objects = {
|
||||
title: this.obj.dataTime.advance_day == 0 ? '明天' : '',
|
||||
month: nowMonth + $lang('common.ns-select-time.l96.t0') + nowDate + $lang('common.ns-select-time.l98.t0'),
|
||||
Day: '(' + dayStr + ')'
|
||||
};
|
||||
this.dayData.push(objects); //左侧日期数据处理
|
||||
}
|
||||
break;
|
||||
default:
|
||||
objects = {
|
||||
title: '',
|
||||
month: nowMonth + $lang('common.ns-select-time.l96.t0') + nowDate + $lang('common.ns-select-time.l98.t0'),
|
||||
Day: '(' + dayStr + ')'
|
||||
};
|
||||
this.dayData.push(objects); //左侧日期数据处理
|
||||
}
|
||||
} else {
|
||||
i = i - 1;
|
||||
}
|
||||
|
||||
if (nowDate != endDay) {
|
||||
nowDate += 1;
|
||||
} else {
|
||||
if (nowMonth != 12) {
|
||||
nowMonth += 1;
|
||||
} else {
|
||||
nowMonth = 1;
|
||||
}
|
||||
nowDate = 1;
|
||||
}
|
||||
|
||||
if (nowDay != 6) {
|
||||
nowDay += 1;
|
||||
} else {
|
||||
nowDay = 0;
|
||||
}
|
||||
num += 1;
|
||||
|
||||
if (this.obj.dataTime.most_day == 0 && i == 0) {
|
||||
this.judge = true;
|
||||
}
|
||||
}
|
||||
|
||||
this.toTime(); //处理右侧时间数据
|
||||
},
|
||||
/**
|
||||
* 处理右侧时间数据
|
||||
*/
|
||||
toTime(judge) {
|
||||
//并非打开弹窗进入时,所有数据置零
|
||||
if (judge == 'no') {
|
||||
this.key = 0;
|
||||
this.keys = 0;
|
||||
this.keyJudge = 0;
|
||||
}
|
||||
|
||||
let timeData = [];
|
||||
|
||||
if (!this.obj.dataTime.delivery_time) {
|
||||
this.obj.dataTime.delivery_time = [ {start_time: this.obj.dataTime.start_time, end_time: this.obj.dataTime.end_time} ]
|
||||
}
|
||||
|
||||
//判断选中是否为当天
|
||||
let remainder = 0;
|
||||
//当天配送自提的话,向后推迟30分钟
|
||||
let newDayTime = JSON.parse(JSON.stringify(this.dayTime));
|
||||
// newDayTime = Math.ceil(this.dayTime / 600) * 600 + 1800;
|
||||
|
||||
//判断选中是否为当天
|
||||
let timeJudage = false;
|
||||
if (this.dayData[this.keyJudge] && this.dayData[this.keyJudge].type && newDayTime > this.obj.dataTime.start_time) timeJudage = true;
|
||||
|
||||
let timeInterval = this.obj.dataTime.time_interval ? this.obj.dataTime.time_interval * 60 : 1200;
|
||||
|
||||
this.obj.dataTime.delivery_time.forEach(item => {
|
||||
item.end_time = item.end_time ? item.end_time : 86400;
|
||||
let num = parseInt((parseInt(item.end_time) - parseInt(item.start_time)) / timeInterval);
|
||||
let time = timeJudage ? parseInt(newDayTime) : parseInt(item.start_time);
|
||||
for (let i = 0; i < num; i++) {
|
||||
if (parseInt(time) + parseInt(timeInterval) > item.end_time) break;
|
||||
if (timeJudage) {
|
||||
if (time >= newDayTime) {
|
||||
if (this.obj.dataTime.time_interval) {
|
||||
if (time <= item.end_time) {
|
||||
let text = '';
|
||||
if (this.obj.delivery.delivery_type == 'local' && i == 0) {
|
||||
text = $lang('common.ns-select-time.l89.t0')+ this.$util.getTimeStr(time) + '-' + this.$util.getTimeStr(time + timeInterval) + ')';
|
||||
} else {
|
||||
text = this.$util.getTimeStr(time) + '-' + this.$util.getTimeStr(time + timeInterval);
|
||||
}
|
||||
timeData.push(text);
|
||||
}
|
||||
} else {
|
||||
timeData.push(this.$util.getTimeStr(time));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (this.obj.dataTime.time_interval) {
|
||||
if (time <= item.end_time) timeData.push(this.$util.getTimeStr(time) + '-' + this.$util.getTimeStr(time + timeInterval));
|
||||
} else {
|
||||
timeData.push(this.$util.getTimeStr(time));
|
||||
}
|
||||
}
|
||||
time = parseInt(time) + timeInterval;
|
||||
}
|
||||
})
|
||||
this.timeData = timeData;
|
||||
this.$forceUpdate();
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.box {
|
||||
height: 728rpx;
|
||||
.title {
|
||||
padding: 0 30rpx;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
font-size: 28rpx;
|
||||
font-weight: bold;
|
||||
position: relative;
|
||||
height: 90rpx;
|
||||
line-height: 90rpx;
|
||||
border-bottom: 1rpx solid #f7f4f4;
|
||||
.icon-close {
|
||||
font-size: 26rpx;
|
||||
color: #909399;
|
||||
position: absolute;
|
||||
right: 30rpx;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
}
|
||||
.body {
|
||||
width: 100%;
|
||||
height: calc(100% - 90rpx);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.left {
|
||||
width: 230rpx;
|
||||
background: #f8f8f8;
|
||||
height: 100%;
|
||||
.item {
|
||||
width: 100%;
|
||||
padding: 16rpx 30rpx;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
font-size: 24rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.itemDay {
|
||||
background: #ffffff;
|
||||
}
|
||||
}
|
||||
.right {
|
||||
width: calc(100% - 230rpx);
|
||||
height: 100%;
|
||||
padding: 0 30rpx;
|
||||
box-sizing: border-box;
|
||||
.item {
|
||||
width: 100%;
|
||||
font-size: 24rpx;
|
||||
border-bottom: 1rpx solid #eeeeee;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 72rpx;
|
||||
.icon-yuan_checked {
|
||||
font-size: 38rpx;
|
||||
margin-right: 30rpx;
|
||||
}
|
||||
}
|
||||
.itemTime {
|
||||
color: var(--main-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<template>
|
||||
<view class="ns-time">
|
||||
<uni-popup type="bottom" ref="selectTime">
|
||||
<view class="box">
|
||||
<view class="title">
|
||||
<block v-if="obj.delivery && obj.delivery.delivery_type == 'local'">选择送达时间</block>
|
||||
<block v-if="obj.delivery && obj.delivery.delivery_type == 'store'">选择自提时间</block>
|
||||
<text class="iconfont icon-close" @click="close"></text>
|
||||
</view>
|
||||
<view class="body">
|
||||
<!-- 左侧日期选择 -->
|
||||
<scroll-view :scroll-y="true" class="left">
|
||||
<view class="item" :class="index == keyJudge ? 'itemDay' : ''" v-for="(item, index) in dayData" :key="index" @click="selectTime('days', index, 'yes')">
|
||||
<block v-if="item.title">{{ item.title }}</block>
|
||||
<block v-else>{{ item.month }}</block>
|
||||
<text class="itemtext">{{ item.Day }}</text>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<!-- 右侧时间选择 -->
|
||||
<scroll-view :scroll-y="true" class="right">
|
||||
<view class="item" :class="key == keyJudge && index == keys ? 'itemTime' : ''" v-for="(item, index) in timeData" :key="index" @click="selectTime('time', index, 'yes')">
|
||||
{{ item }}
|
||||
<text v-if="key == keyJudge && index == keys" class="iconfont icon-yuan_checked color-base-text"></text>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "nsSelectTime",
|
||||
data() {
|
||||
return {
|
||||
//选中日期的键值
|
||||
key: 0,
|
||||
//选中时间的键值
|
||||
keys: 0,
|
||||
//渲染用数据
|
||||
obj: {},
|
||||
//左侧渲染时间
|
||||
dayData: [],
|
||||
// 右侧渲染数据
|
||||
timeData: [],
|
||||
//判断弹窗打开
|
||||
judge: false,
|
||||
//判断左侧列表是否为日期选中列表
|
||||
keyJudge: 0,
|
||||
//当前时间时间戳
|
||||
dayTime: 0
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
refresh(){
|
||||
this.key = 0;
|
||||
this.keys = 0;
|
||||
this.keyJudge = 0;
|
||||
},
|
||||
/**
|
||||
* 弹窗打开
|
||||
*/
|
||||
open(obj, type) {
|
||||
this.dayData = [];
|
||||
this.timeData = [];
|
||||
this.obj = obj;
|
||||
this.toDay(obj.dataTime.time_type, obj.dataTime.time_week);
|
||||
if (this.judge) {
|
||||
if (type == 'no') {
|
||||
this.selectTime('', '', type);
|
||||
} else {
|
||||
this.$refs.selectTime.open();
|
||||
}
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 时间选择
|
||||
*/
|
||||
selectTime(type, index, judge) {
|
||||
if (type == 'days') {
|
||||
this.keyJudge = index;
|
||||
this.toTime();
|
||||
} else if (type == 'time') {
|
||||
this.keys = index;
|
||||
this.key = this.keyJudge;
|
||||
let obj = this.dayData[this.key];
|
||||
obj.time = this.timeData[this.keys];
|
||||
let time = obj.time.replace('立即配送(','').replace(')','');
|
||||
|
||||
var dateTime = new Date();
|
||||
var format = time.split('-');
|
||||
var startHours = format[0].split(':');
|
||||
var endHours = format[1].split(':');
|
||||
|
||||
let timeData = obj.month.split('月');
|
||||
let month = timeData[0];
|
||||
let date = timeData[1].split('日')[0];
|
||||
|
||||
// 开始时间戳
|
||||
dateTime.setHours(startHours[0],startHours[1],0,0);
|
||||
obj.start_time = dateTime.getTime()/1000;
|
||||
obj.start_date = dateTime.getFullYear() + '-' + month + '-' + date + ' ' + format[0];
|
||||
|
||||
// 结束时间戳
|
||||
dateTime.setHours(endHours[0],endHours[1],0,0);
|
||||
obj.end_time = dateTime.getTime()/1000;
|
||||
obj.end_date = dateTime.getFullYear() + '-' + month + '-' + date + ' ' + format[1];
|
||||
|
||||
this.$emit('selectTime', { data: obj, type: judge });
|
||||
this.$refs.selectTime.close();
|
||||
}
|
||||
|
||||
if (judge == 'no') {
|
||||
this.toTime(judge);
|
||||
let obj = this.dayData[0];
|
||||
obj.time = this.timeData[0];
|
||||
this.$emit('selectTime', { data: obj, type: judge });
|
||||
}
|
||||
this.$forceUpdate();
|
||||
},
|
||||
/**
|
||||
* 弹窗关闭
|
||||
*/
|
||||
close() {
|
||||
this.$refs.selectTime.close();
|
||||
},
|
||||
/**
|
||||
* 左侧数据处理
|
||||
*/
|
||||
toDay(type, obj) {
|
||||
let today = new Date();
|
||||
if (this.obj.dataTime.advance_day) {
|
||||
today = new Date(today.getTime() + (this.obj.dataTime.advance_day * 86400000));
|
||||
}
|
||||
let nowYear = today.getFullYear(); //当前年
|
||||
let nowMonth = today.getMonth() + 1; //当前月
|
||||
let nowDate = today.getDate(); //当前日
|
||||
let nowDay = today.getDay(); //当前星期几
|
||||
let endDay = new Date(nowYear, nowMonth, 0).getDate(); //当月多少天
|
||||
let Hours = today.getHours();
|
||||
let Minutes = today.getMinutes();
|
||||
this.dayTime = this.obj.dataTime.advance_day ? 0 : Number(Hours) * 3600 + Number(Minutes) * 60; //获取到当前时分秒的时间戳
|
||||
let judge = false;
|
||||
let num = 1; //记录循环执行过的次数
|
||||
let mostDay = this.obj.dataTime.most_day ? this.obj.dataTime.most_day + 1 : 1; // 最多可预约天数
|
||||
let startTime = parseInt(today.getTime() / 1000);
|
||||
let week = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
|
||||
if (obj.time_week && obj.time_week.length == 7) {
|
||||
//判断是否七天全有
|
||||
judge = true;
|
||||
}
|
||||
|
||||
for (let i = 0; i < mostDay; i++) {
|
||||
let objects = {};
|
||||
let dayStr = week[ nowDay ];
|
||||
// 判断最大可预约时间
|
||||
if (this.obj.dataTime.most_day > 0 && ((startTime + num * 86400) > (startTime + this.obj.dataTime.most_day * 86400) ) ) {
|
||||
this.judge = true;
|
||||
break;
|
||||
}
|
||||
//判断当天是否能够配送、自提
|
||||
if (type == 0 || judge || obj.indexOf(nowDay.toString()) != -1) {
|
||||
let endTime = this.obj.dataTime.delivery_time[ (this.obj.dataTime.delivery_time.length - 1) ].end_time;
|
||||
endTime -= this.obj.dataTime.time_interval * 60;
|
||||
switch (num) {
|
||||
case 1:
|
||||
if (i == 0) {
|
||||
if (endTime < this.dayTime) {
|
||||
i = i - 1;
|
||||
} else {
|
||||
objects = {
|
||||
title: this.obj.dataTime.advance_day == 0 ? '今天' : '',
|
||||
type: 'special',
|
||||
month: nowMonth + '月' + nowDate + '日',
|
||||
Day: '(' + dayStr + ')'
|
||||
};
|
||||
this.dayData.push(objects); //左侧日期数据处理
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (i == 0 || i == 1) {
|
||||
objects = {
|
||||
title: this.obj.dataTime.advance_day == 0 ? '明天' : '',
|
||||
month: nowMonth + '月' + nowDate + '日',
|
||||
Day: '(' + dayStr + ')'
|
||||
};
|
||||
this.dayData.push(objects); //左侧日期数据处理
|
||||
}
|
||||
break;
|
||||
default:
|
||||
objects = {
|
||||
title: '',
|
||||
month: nowMonth + '月' + nowDate + '日',
|
||||
Day: '(' + dayStr + ')'
|
||||
};
|
||||
this.dayData.push(objects); //左侧日期数据处理
|
||||
}
|
||||
} else {
|
||||
i = i - 1;
|
||||
}
|
||||
|
||||
if (nowDate != endDay) {
|
||||
nowDate += 1;
|
||||
} else {
|
||||
if (nowMonth != 12) {
|
||||
nowMonth += 1;
|
||||
} else {
|
||||
nowMonth = 1;
|
||||
}
|
||||
nowDate = 1;
|
||||
}
|
||||
|
||||
if (nowDay != 6) {
|
||||
nowDay += 1;
|
||||
} else {
|
||||
nowDay = 0;
|
||||
}
|
||||
num += 1;
|
||||
|
||||
if (this.obj.dataTime.most_day == 0 && i == 0) {
|
||||
this.judge = true;
|
||||
}
|
||||
}
|
||||
|
||||
this.toTime(); //处理右侧时间数据
|
||||
},
|
||||
/**
|
||||
* 处理右侧时间数据
|
||||
*/
|
||||
toTime(judge) {
|
||||
//并非打开弹窗进入时,所有数据置零
|
||||
if (judge == 'no') {
|
||||
this.key = 0;
|
||||
this.keys = 0;
|
||||
this.keyJudge = 0;
|
||||
}
|
||||
|
||||
let timeData = [];
|
||||
|
||||
if (!this.obj.dataTime.delivery_time) {
|
||||
this.obj.dataTime.delivery_time = [ {start_time: this.obj.dataTime.start_time, end_time: this.obj.dataTime.end_time} ]
|
||||
}
|
||||
|
||||
//判断选中是否为当天
|
||||
let remainder = 0;
|
||||
//当天配送自提的话,向后推迟30分钟
|
||||
let newDayTime = JSON.parse(JSON.stringify(this.dayTime));
|
||||
// newDayTime = Math.ceil(this.dayTime / 600) * 600 + 1800;
|
||||
|
||||
//判断选中是否为当天
|
||||
let timeJudage = false;
|
||||
if (this.dayData[this.keyJudge] && this.dayData[this.keyJudge].type && newDayTime > this.obj.dataTime.start_time) timeJudage = true;
|
||||
|
||||
let timeInterval = this.obj.dataTime.time_interval ? this.obj.dataTime.time_interval * 60 : 1200;
|
||||
|
||||
this.obj.dataTime.delivery_time.forEach(item => {
|
||||
item.end_time = item.end_time ? item.end_time : 86400;
|
||||
let num = parseInt((parseInt(item.end_time) - parseInt(item.start_time)) / timeInterval);
|
||||
let time = timeJudage ? parseInt(newDayTime) : parseInt(item.start_time);
|
||||
for (let i = 0; i < num; i++) {
|
||||
if (parseInt(time) + parseInt(timeInterval) > item.end_time) break;
|
||||
if (timeJudage) {
|
||||
if (time >= newDayTime) {
|
||||
if (this.obj.dataTime.time_interval) {
|
||||
if (time <= item.end_time) {
|
||||
let text = '';
|
||||
if (this.obj.delivery.delivery_type == 'local' && i == 0) {
|
||||
text = '立即配送('+ this.$util.getTimeStr(time) + '-' + this.$util.getTimeStr(time + timeInterval) + ')';
|
||||
} else {
|
||||
text = this.$util.getTimeStr(time) + '-' + this.$util.getTimeStr(time + timeInterval);
|
||||
}
|
||||
timeData.push(text);
|
||||
}
|
||||
} else {
|
||||
timeData.push(this.$util.getTimeStr(time));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (this.obj.dataTime.time_interval) {
|
||||
if (time <= item.end_time) timeData.push(this.$util.getTimeStr(time) + '-' + this.$util.getTimeStr(time + timeInterval));
|
||||
} else {
|
||||
timeData.push(this.$util.getTimeStr(time));
|
||||
}
|
||||
}
|
||||
time = parseInt(time) + timeInterval;
|
||||
}
|
||||
})
|
||||
this.timeData = timeData;
|
||||
this.$forceUpdate();
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.box {
|
||||
height: 728rpx;
|
||||
.title {
|
||||
padding: 0 30rpx;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
font-size: 28rpx;
|
||||
font-weight: bold;
|
||||
position: relative;
|
||||
height: 90rpx;
|
||||
line-height: 90rpx;
|
||||
border-bottom: 1rpx solid #f7f4f4;
|
||||
.icon-close {
|
||||
font-size: 26rpx;
|
||||
color: #909399;
|
||||
position: absolute;
|
||||
right: 30rpx;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
}
|
||||
.body {
|
||||
width: 100%;
|
||||
height: calc(100% - 90rpx);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.left {
|
||||
width: 230rpx;
|
||||
background: #f8f8f8;
|
||||
height: 100%;
|
||||
.item {
|
||||
width: 100%;
|
||||
padding: 16rpx 30rpx;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
font-size: 24rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.itemDay {
|
||||
background: #ffffff;
|
||||
}
|
||||
}
|
||||
.right {
|
||||
width: calc(100% - 230rpx);
|
||||
height: 100%;
|
||||
padding: 0 30rpx;
|
||||
box-sizing: border-box;
|
||||
.item {
|
||||
width: 100%;
|
||||
font-size: 24rpx;
|
||||
border-bottom: 1rpx solid #eeeeee;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
height: 72rpx;
|
||||
.icon-yuan_checked {
|
||||
font-size: 38rpx;
|
||||
margin-right: 30rpx;
|
||||
}
|
||||
}
|
||||
.itemTime {
|
||||
color: var(--main-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,145 +1,145 @@
|
||||
<template>
|
||||
<view class="video-player-popup">
|
||||
<uni-popup ref="videoPopup" type="center" :mask-click="true" @change="onVideoPopupChange">
|
||||
<view class="video-popup-content">
|
||||
<view class="video-popup-header">
|
||||
<text class="video-popup-title">{{ videoTitle }}</text>
|
||||
<text class="iconfont icon-close" @click="close"></text>
|
||||
</view>
|
||||
<view class="video-popup-body">
|
||||
<video
|
||||
v-if="videoUrl"
|
||||
:src="videoUrl"
|
||||
controls
|
||||
autoplay
|
||||
class="video-player"
|
||||
></video>
|
||||
<view v-else class="video-error">{{ $lang("common.ns-video-player-popup.l17.t0") }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'ns-video-player-popup',
|
||||
props: {
|
||||
/**
|
||||
* 当前播放的视频信息
|
||||
* @type {Object}
|
||||
* @property {string} title - 视频标题
|
||||
* @property {string} videoUrl - 视频地址
|
||||
*/
|
||||
currentVideo: {
|
||||
type: Object,
|
||||
default: null
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
videoUrl() {
|
||||
return this.currentVideo?.videoUrl || '';
|
||||
},
|
||||
|
||||
videoTitle() {
|
||||
return this.currentVideo?.title || '';
|
||||
},
|
||||
/**
|
||||
* 视频弹窗是否显示
|
||||
* @type {boolean}
|
||||
*/
|
||||
isVisible() {
|
||||
return this.$refs.videoPopup?.visible || false;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* 打开视频弹窗
|
||||
*/
|
||||
open() {
|
||||
if (this.$refs.videoPopup) {
|
||||
this.$refs.videoPopup.open();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 关闭视频弹窗
|
||||
*/
|
||||
close() {
|
||||
if (this.$refs.videoPopup) {
|
||||
this.$refs.videoPopup.close();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 视频弹窗状态变化
|
||||
* @param {Object} e - 弹窗状态变化事件
|
||||
*/
|
||||
onVideoPopupChange(e) {
|
||||
this.$emit('popup-change', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/* 视频播放弹窗样式 */
|
||||
.video-player-popup {
|
||||
.video-popup-content {
|
||||
width: 90%;
|
||||
max-width: 600rpx;
|
||||
background-color: #fff;
|
||||
border-radius: 12rpx;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.video-popup-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 20rpx;
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
background-color: #fafafa;
|
||||
|
||||
.video-popup-title {
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.icon-close {
|
||||
font-size: 32rpx;
|
||||
color: #999;
|
||||
padding: 0 10rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.video-popup-body {
|
||||
padding: 20rpx;
|
||||
|
||||
.video-player {
|
||||
width: 100%;
|
||||
height: 400rpx;
|
||||
background-color: #000;
|
||||
border-radius: 8rpx;
|
||||
}
|
||||
|
||||
.video-error {
|
||||
width: 100%;
|
||||
height: 400rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: #f5f5f5;
|
||||
border-radius: 8rpx;
|
||||
color: #999;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
<template>
|
||||
<view class="video-player-popup">
|
||||
<uni-popup ref="videoPopup" type="center" :mask-click="true" @change="onVideoPopupChange">
|
||||
<view class="video-popup-content">
|
||||
<view class="video-popup-header">
|
||||
<text class="video-popup-title">{{ videoTitle }}</text>
|
||||
<text class="iconfont icon-close" @click="close"></text>
|
||||
</view>
|
||||
<view class="video-popup-body">
|
||||
<video
|
||||
v-if="videoUrl"
|
||||
:src="videoUrl"
|
||||
controls
|
||||
autoplay
|
||||
class="video-player"
|
||||
></video>
|
||||
<view v-else class="video-error">视频地址不存在</view>
|
||||
</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'ns-video-player-popup',
|
||||
props: {
|
||||
/**
|
||||
* 当前播放的视频信息
|
||||
* @type {Object}
|
||||
* @property {string} title - 视频标题
|
||||
* @property {string} videoUrl - 视频地址
|
||||
*/
|
||||
currentVideo: {
|
||||
type: Object,
|
||||
default: null
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
videoUrl() {
|
||||
return this.currentVideo?.videoUrl || '';
|
||||
},
|
||||
|
||||
videoTitle() {
|
||||
return this.currentVideo?.title || '';
|
||||
},
|
||||
/**
|
||||
* 视频弹窗是否显示
|
||||
* @type {boolean}
|
||||
*/
|
||||
isVisible() {
|
||||
return this.$refs.videoPopup?.visible || false;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* 打开视频弹窗
|
||||
*/
|
||||
open() {
|
||||
if (this.$refs.videoPopup) {
|
||||
this.$refs.videoPopup.open();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 关闭视频弹窗
|
||||
*/
|
||||
close() {
|
||||
if (this.$refs.videoPopup) {
|
||||
this.$refs.videoPopup.close();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* 视频弹窗状态变化
|
||||
* @param {Object} e - 弹窗状态变化事件
|
||||
*/
|
||||
onVideoPopupChange(e) {
|
||||
this.$emit('popup-change', e);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/* 视频播放弹窗样式 */
|
||||
.video-player-popup {
|
||||
.video-popup-content {
|
||||
width: 90%;
|
||||
max-width: 600rpx;
|
||||
background-color: #fff;
|
||||
border-radius: 12rpx;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.video-popup-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 20rpx;
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
background-color: #fafafa;
|
||||
|
||||
.video-popup-title {
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.icon-close {
|
||||
font-size: 32rpx;
|
||||
color: #999;
|
||||
padding: 0 10rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.video-popup-body {
|
||||
padding: 20rpx;
|
||||
|
||||
.video-player {
|
||||
width: 100%;
|
||||
height: 400rpx;
|
||||
background-color: #000;
|
||||
border-radius: 8rpx;
|
||||
}
|
||||
|
||||
.video-error {
|
||||
width: 100%;
|
||||
height: 400rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: #f5f5f5;
|
||||
border-radius: 8rpx;
|
||||
color: #999;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -14,8 +14,8 @@
|
||||
<uni-popup type="bottom" ref="regionsRef">
|
||||
<view class="regions-picker-container">
|
||||
<view class="picker-header">
|
||||
<view class="picker-action cancel" @click="$refs.regionsRef.close()">{{ $lang("common.pick-regions.l17.t0") }}</view>
|
||||
<view class="picker-action confirm" @click="confirmRegions">{{ $lang("common.pick-regions.l18.t0") }}</view>
|
||||
<view class="picker-action cancel" @click="$refs.regionsRef.close()">取消</view>
|
||||
<view class="picker-action confirm" @click="confirmRegions">完成</view>
|
||||
</view>
|
||||
<picker-view :value="multiIndex" @change="pickerViewColumnChange" class="picker-view">
|
||||
<picker-view-column v-if="multiArray[0]">
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<view>
|
||||
<view class="privacy-mask" v-if="showPop">
|
||||
<view class="privacy-wrap">
|
||||
<view class="privacy-title">{{ $lang("common.privacy-popup.l5.t0") }}</view>
|
||||
<view class="privacy-title">用户隐私保护提示</view>
|
||||
<view class="privacy-desc">
|
||||
感谢您使用{{ appName }},在使用前您应当阅读并同意
|
||||
<text class="privacy-link" @tap="openPrivacyContract">{{ privacyContractName }}</text>
|
||||
@@ -12,13 +12,13 @@
|
||||
,当点击同意并继续时,即表示您已理解并同意该条款内容,该条款将对您产生法律约束力;如您不同意,将无法继续使用{{ appName }}相关功能。
|
||||
</view>
|
||||
<view class="privacy-button-flex">
|
||||
<button class="privacy-button-btn bg-disagree" @tap="handleDisagree">{{ $lang("common.privacy-popup.l15.t0") }}</button>
|
||||
<button class="privacy-button-btn bg-disagree" @tap="handleDisagree">不同意</button>
|
||||
<!-- #ifdef QUICKAPP-WEBVIEW || MP-WEIXIN -->
|
||||
<button id="agree-btn" class="privacy-button-btn bg-agree" open-type="agreePrivacyAuthorization"
|
||||
@agreeprivacyauthorization="handleAgree">{{ $lang("common.privacy-popup.l18.t0") }}</button>
|
||||
@agreeprivacyauthorization="handleAgree">同意并继续</button>
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef WEB || H5 -->
|
||||
<button id="agree-btn" class="privacy-button-btn bg-agree" @tap="handleAgree" @click="handleAgree">{{ $lang("common.privacy-popup.l18.t0") }}</button>
|
||||
<button id="agree-btn" class="privacy-button-btn bg-agree" @tap="handleAgree" @click="handleAgree">同意并继续</button>
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
</view>
|
||||
@@ -43,12 +43,12 @@ export default {
|
||||
showPop: false,
|
||||
privacyAuthorization: null,
|
||||
privacyResolves: new Set(),
|
||||
privacyContractName: $lang('common.privacy-popup.l46.t0'),
|
||||
appName: $lang('common.privacy-popup.l47.t0'),
|
||||
privacyContractName: '用户隐私保护指引',
|
||||
appName: '本小程序',
|
||||
// #ifdef WEB || H5
|
||||
appName: $lang('common.privacy-popup.l49.t0'),
|
||||
privacyContractName: $lang('common.ns-login.l51.t0'),
|
||||
privacyServiceName: $lang('common.ns-login.l53.t0'),
|
||||
appName: '本应用',
|
||||
privacyContractName: '《隐私条款》',
|
||||
privacyServiceName: '《用户服务协议》',
|
||||
// #endif
|
||||
}
|
||||
},
|
||||
@@ -79,7 +79,7 @@ export default {
|
||||
}
|
||||
// #endif
|
||||
} catch (e) {
|
||||
console.error($lang("common.privacy-popup.l82.t0"), e)
|
||||
console.error("=========低版本基础库==========", e)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@@ -250,7 +250,7 @@ export default {
|
||||
uni.setStorageSync('privacyAgreed', true);
|
||||
|
||||
uni.showModal({
|
||||
content: $lang('common.privacy-popup.l253.t0'),
|
||||
content: '未同意隐私协议,无法使用相关功能',
|
||||
success: () => {
|
||||
this.$emit('disagree')
|
||||
}
|
||||
|
||||
@@ -1,292 +1,292 @@
|
||||
<template>
|
||||
<view>
|
||||
<view @touchmove.prevent.stop class="reward-popup" v-if="reward">
|
||||
<uni-popup ref="registerReward" type="center" :maskClick="false">
|
||||
<view class="reward-wrap">
|
||||
<image :src="$util.img('public/uniapp/register_reward/register_reward_img.png')" mode="widthFix" class="bg-img-head"/>
|
||||
<image :src="$util.img('public/uniapp/register_reward/register_reward_money.png')" mode="widthFix" class="bg-img-money"/>
|
||||
<image :src="$util.img('public/uniapp/register_reward/register_reward_head.png')" mode="widthFix" class="bg-img"/>
|
||||
<view class="wrap">
|
||||
<view>
|
||||
<scroll-view scroll-y="true" class="register-box">
|
||||
<view class="reward-content">
|
||||
<view class="reward-item" v-if="reward.point > 0">
|
||||
<view class="head">{{ $lang("common.register-reward.l14.t0") }}</view>
|
||||
<view class="content">
|
||||
<view class="info">
|
||||
<view>
|
||||
<text class="num">{{ reward.point }}</text>
|
||||
<text class="type">{{ $lang("common.register-reward.l19.t0") }}</text>
|
||||
</view>
|
||||
<view class="desc">{{ $lang("common.register-reward.l21.t0") }}</view>
|
||||
</view>
|
||||
<view class="tip" @click="closeRewardPopup('point')">{{ $lang("common.register-reward.l23.t0") }}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="reward-item" v-if="reward.growth > 0">
|
||||
<view class="head">{{ $lang("common.register-reward.l27.t0") }}</view>
|
||||
<view class="content">
|
||||
<view class="info">
|
||||
<view>
|
||||
<text class="num">{{ reward.growth }}</text>
|
||||
<text class="type">{{ $lang("common.register-reward.l27.t0") }}</text>
|
||||
</view>
|
||||
<view class="desc">{{ $lang("common.register-reward.l34.t0") }}</view>
|
||||
</view>
|
||||
<view class="tip" @click="closeRewardPopup('growth')">{{ $lang("common.register-reward.l23.t0") }}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="reward-item" v-if="reward.balance > 0">
|
||||
<view class="head">{{ $lang("common.register-reward.l40.t0") }}</view>
|
||||
<view class="content">
|
||||
<view class="info">
|
||||
<view>
|
||||
<text class="num">{{ reward.balance }}</text>
|
||||
<text class="type">{{ $lang("common.register-reward.l45.t0") }}</text>
|
||||
</view>
|
||||
<view class="desc">{{ $lang("common.register-reward.l47.t0") }}</view>
|
||||
</view>
|
||||
<view class="tip" @click="closeRewardPopup('balance')">{{ $lang("common.register-reward.l23.t0") }}</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="reward-item" v-if="reward.coupon_list.length > 0">
|
||||
<view class="head">{{ $lang("common.register-reward.l53.t0") }}</view>
|
||||
<view class="content" v-for="(item, index) in reward.coupon_list" :key="index">
|
||||
<view class="info">
|
||||
<view>
|
||||
<text class="num coupon-name">{{ item.coupon_name }}</text>
|
||||
</view>
|
||||
<view class="desc" v-if="item.at_least > 0">
|
||||
满{{ item.at_least }}{{ item.type == 'discount' ? $lang('common.register-reward.l60.t0') + item.discount + '折' : $lang('common.register-reward.l60.t2') + item.money }}
|
||||
</view>
|
||||
<view class="desc" v-else>
|
||||
无门槛,{{ item.type == 'discount' ? $lang('common.register-reward.l60.t0') + item.discount + '折' : $lang('common.register-reward.l60.t2') + item.money }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="tip" @click="closeRewardPopup('coupon')">{{ $lang("common.register-reward.l23.t0") }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="close-btn" @click="closeRewardPopup()"><text class="iconfont icon-close"></text></view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// 注册奖励弹出层
|
||||
export default {
|
||||
name: 'register-reward',
|
||||
data() {
|
||||
return {
|
||||
reward: null,
|
||||
back: ''
|
||||
};
|
||||
},
|
||||
created() {},
|
||||
methods: {
|
||||
open(back) {
|
||||
if (back) this.back = back;
|
||||
if (this.addonIsExist.memberregister) {
|
||||
this.getRegisterReward();
|
||||
} else {
|
||||
this.closeRewardPopup();
|
||||
}
|
||||
},
|
||||
cancel() {
|
||||
this.$refs.registerReward.close();
|
||||
},
|
||||
/**
|
||||
* 获取新人礼配置
|
||||
*/
|
||||
getRegisterReward() {
|
||||
this.$api.sendRequest({
|
||||
url: '/memberregister/api/Config/Config',
|
||||
success: res => {
|
||||
if (res.code >= 0) {
|
||||
let data = res.data;
|
||||
if (data.is_use == 1 && (data.value.point > 0 || data.value.balance > 0 || data
|
||||
.value.growth > 0 || data.value.coupon_list.length > 0)) {
|
||||
this.reward = data.value;
|
||||
this.$nextTick(() => {
|
||||
if(this.$refs.registerReward) this.$refs.registerReward.open();
|
||||
});
|
||||
}
|
||||
}
|
||||
this.closeRewardPopup();
|
||||
}
|
||||
});
|
||||
},
|
||||
closeRewardPopup(type) {
|
||||
if (this.$refs.registerReward) this.$refs.registerReward.close();
|
||||
switch (type) {
|
||||
case 'point':
|
||||
this.$util.redirectTo('/pages_tool/member/point_detail', {});
|
||||
break;
|
||||
case 'balance':
|
||||
this.$util.redirectTo('/pages_tool/member/balance_detail', {});
|
||||
break;
|
||||
case 'growth':
|
||||
this.$util.redirectTo('/pages_tool/member/level', {});
|
||||
break;
|
||||
case 'coupon':
|
||||
this.$util.redirectTo('/pages_tool/member/coupon', {});
|
||||
break;
|
||||
default:
|
||||
if (this.back) this.$util.redirectTo(decodeURIComponent(this.back), {}, 'redirectTo');
|
||||
else this.$util.redirectTo(this.$util.INDEX_PAGE_URL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style scoped>
|
||||
.register-box ::v-deep .uni-scroll-view {
|
||||
background: unset !important;
|
||||
}
|
||||
|
||||
.register-box {
|
||||
max-height: 630rpx;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
.register-box ::v-deep .uni-popup__wrapper-box {
|
||||
overflow: unset !important;
|
||||
}
|
||||
|
||||
.reward-popup ::v-deep .uni-popup__wrapper {
|
||||
background: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss">
|
||||
.uni-popup__wrapper-box {
|
||||
overflow: unset !important;
|
||||
}
|
||||
|
||||
.close-btn {
|
||||
text-align: center;
|
||||
margin-top: 20rpx;
|
||||
|
||||
.iconfont {
|
||||
color: #fff;
|
||||
font-size: 40rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.reward-wrap {
|
||||
width: 80vw;
|
||||
height: auto;
|
||||
position: relative;
|
||||
// padding-top: 150rpx;
|
||||
|
||||
&>uni-image,
|
||||
.bg-img {
|
||||
width: 100%;
|
||||
will-change: transform;
|
||||
}
|
||||
|
||||
.bg-img-head {
|
||||
position: absolute;
|
||||
top: -150rpx;
|
||||
width: 100vw;
|
||||
left: -10vw;
|
||||
}
|
||||
|
||||
.bg-img-money {
|
||||
position: absolute;
|
||||
width: 93vw;
|
||||
left: -48rpx;
|
||||
top: 100rpx;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.wrap {
|
||||
width: calc(100% - 2rpx);
|
||||
height: 100%;
|
||||
background-color: #ef3030;
|
||||
margin-top: -80rpx;
|
||||
padding-bottom: 30rpx;
|
||||
border-bottom-left-radius: 10rpx;
|
||||
border-bottom-right-radius: 10rpx;
|
||||
|
||||
&>view {
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
|
||||
.reward-content {
|
||||
margin: 0 50rpx 0 50rpx;
|
||||
}
|
||||
|
||||
.reward-item {
|
||||
.head {
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
line-height: 1;
|
||||
margin: 20rpx 0;
|
||||
}
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
padding: 16rpx 26rpx;
|
||||
background: #fff;
|
||||
border-radius: 10rpx;
|
||||
margin-bottom: 10rpx;
|
||||
|
||||
.info {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.tip {
|
||||
color: #ff222d;
|
||||
padding: 10rpx 0 10rpx 30rpx;
|
||||
width: 70rpx;
|
||||
line-height: 1.5;
|
||||
letter-spacing: 2rpx;
|
||||
border-left: 2rpx dashed #e5e5e5;
|
||||
}
|
||||
|
||||
.num {
|
||||
font-size: 52rpx;
|
||||
color: #ff222d;
|
||||
font-weight: bolder;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.coupon-name {
|
||||
font-size: 38rpx;
|
||||
}
|
||||
|
||||
.type {
|
||||
font-size: $font-size-base;
|
||||
margin-left: 10rpx;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.desc {
|
||||
margin-top: 8rpx;
|
||||
color: $color-tip;
|
||||
font-size: $font-size-tag;
|
||||
line-height: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.btn {
|
||||
position: absolute;
|
||||
width: calc(100% - 100rpx);
|
||||
bottom: 40rpx;
|
||||
left: 50rpx;
|
||||
|
||||
.btn-img {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
<template>
|
||||
<view>
|
||||
<view @touchmove.prevent.stop class="reward-popup" v-if="reward">
|
||||
<uni-popup ref="registerReward" type="center" :maskClick="false">
|
||||
<view class="reward-wrap">
|
||||
<image :src="$util.img('public/uniapp/register_reward/register_reward_img.png')" mode="widthFix" class="bg-img-head"/>
|
||||
<image :src="$util.img('public/uniapp/register_reward/register_reward_money.png')" mode="widthFix" class="bg-img-money"/>
|
||||
<image :src="$util.img('public/uniapp/register_reward/register_reward_head.png')" mode="widthFix" class="bg-img"/>
|
||||
<view class="wrap">
|
||||
<view>
|
||||
<scroll-view scroll-y="true" class="register-box">
|
||||
<view class="reward-content">
|
||||
<view class="reward-item" v-if="reward.point > 0">
|
||||
<view class="head">积分奖励</view>
|
||||
<view class="content">
|
||||
<view class="info">
|
||||
<view>
|
||||
<text class="num">{{ reward.point }}</text>
|
||||
<text class="type">积分</text>
|
||||
</view>
|
||||
<view class="desc">用于下单时抵现或兑换商品等</view>
|
||||
</view>
|
||||
<view class="tip" @click="closeRewardPopup('point')">立即查看</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="reward-item" v-if="reward.growth > 0">
|
||||
<view class="head">成长值</view>
|
||||
<view class="content">
|
||||
<view class="info">
|
||||
<view>
|
||||
<text class="num">{{ reward.growth }}</text>
|
||||
<text class="type">成长值</text>
|
||||
</view>
|
||||
<view class="desc">用于提升会员等级</view>
|
||||
</view>
|
||||
<view class="tip" @click="closeRewardPopup('growth')">立即查看</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="reward-item" v-if="reward.balance > 0">
|
||||
<view class="head">红包奖励</view>
|
||||
<view class="content">
|
||||
<view class="info">
|
||||
<view>
|
||||
<text class="num">{{ reward.balance }}</text>
|
||||
<text class="type">元</text>
|
||||
</view>
|
||||
<view class="desc">不可提现下单时可用</view>
|
||||
</view>
|
||||
<view class="tip" @click="closeRewardPopup('balance')">立即查看</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="reward-item" v-if="reward.coupon_list.length > 0">
|
||||
<view class="head">优惠券奖励</view>
|
||||
<view class="content" v-for="(item, index) in reward.coupon_list" :key="index">
|
||||
<view class="info">
|
||||
<view>
|
||||
<text class="num coupon-name">{{ item.coupon_name }}</text>
|
||||
</view>
|
||||
<view class="desc" v-if="item.at_least > 0">
|
||||
满{{ item.at_least }}{{ item.type == 'discount' ? '打' + item.discount + '折' : '减' + item.money }}
|
||||
</view>
|
||||
<view class="desc" v-else>
|
||||
无门槛,{{ item.type == 'discount' ? '打' + item.discount + '折' : '减' + item.money }}
|
||||
</view>
|
||||
</view>
|
||||
<view class="tip" @click="closeRewardPopup('coupon')">立即查看</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="close-btn" @click="closeRewardPopup()"><text class="iconfont icon-close"></text></view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// 注册奖励弹出层
|
||||
export default {
|
||||
name: 'register-reward',
|
||||
data() {
|
||||
return {
|
||||
reward: null,
|
||||
back: ''
|
||||
};
|
||||
},
|
||||
created() {},
|
||||
methods: {
|
||||
open(back) {
|
||||
if (back) this.back = back;
|
||||
if (this.addonIsExist.memberregister) {
|
||||
this.getRegisterReward();
|
||||
} else {
|
||||
this.closeRewardPopup();
|
||||
}
|
||||
},
|
||||
cancel() {
|
||||
this.$refs.registerReward.close();
|
||||
},
|
||||
/**
|
||||
* 获取新人礼配置
|
||||
*/
|
||||
getRegisterReward() {
|
||||
this.$api.sendRequest({
|
||||
url: '/memberregister/api/Config/Config',
|
||||
success: res => {
|
||||
if (res.code >= 0) {
|
||||
let data = res.data;
|
||||
if (data.is_use == 1 && (data.value.point > 0 || data.value.balance > 0 || data
|
||||
.value.growth > 0 || data.value.coupon_list.length > 0)) {
|
||||
this.reward = data.value;
|
||||
this.$nextTick(() => {
|
||||
if(this.$refs.registerReward) this.$refs.registerReward.open();
|
||||
});
|
||||
}
|
||||
}
|
||||
this.closeRewardPopup();
|
||||
}
|
||||
});
|
||||
},
|
||||
closeRewardPopup(type) {
|
||||
if (this.$refs.registerReward) this.$refs.registerReward.close();
|
||||
switch (type) {
|
||||
case 'point':
|
||||
this.$util.redirectTo('/pages_tool/member/point_detail', {});
|
||||
break;
|
||||
case 'balance':
|
||||
this.$util.redirectTo('/pages_tool/member/balance_detail', {});
|
||||
break;
|
||||
case 'growth':
|
||||
this.$util.redirectTo('/pages_tool/member/level', {});
|
||||
break;
|
||||
case 'coupon':
|
||||
this.$util.redirectTo('/pages_tool/member/coupon', {});
|
||||
break;
|
||||
default:
|
||||
if (this.back) this.$util.redirectTo(decodeURIComponent(this.back), {}, 'redirectTo');
|
||||
else this.$util.redirectTo(this.$util.INDEX_PAGE_URL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style scoped>
|
||||
.register-box ::v-deep .uni-scroll-view {
|
||||
background: unset !important;
|
||||
}
|
||||
|
||||
.register-box {
|
||||
max-height: 630rpx;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
.register-box ::v-deep .uni-popup__wrapper-box {
|
||||
overflow: unset !important;
|
||||
}
|
||||
|
||||
.reward-popup ::v-deep .uni-popup__wrapper {
|
||||
background: none;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="scss">
|
||||
.uni-popup__wrapper-box {
|
||||
overflow: unset !important;
|
||||
}
|
||||
|
||||
.close-btn {
|
||||
text-align: center;
|
||||
margin-top: 20rpx;
|
||||
|
||||
.iconfont {
|
||||
color: #fff;
|
||||
font-size: 40rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.reward-wrap {
|
||||
width: 80vw;
|
||||
height: auto;
|
||||
position: relative;
|
||||
// padding-top: 150rpx;
|
||||
|
||||
&>uni-image,
|
||||
.bg-img {
|
||||
width: 100%;
|
||||
will-change: transform;
|
||||
}
|
||||
|
||||
.bg-img-head {
|
||||
position: absolute;
|
||||
top: -150rpx;
|
||||
width: 100vw;
|
||||
left: -10vw;
|
||||
}
|
||||
|
||||
.bg-img-money {
|
||||
position: absolute;
|
||||
width: 93vw;
|
||||
left: -48rpx;
|
||||
top: 100rpx;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.wrap {
|
||||
width: calc(100% - 2rpx);
|
||||
height: 100%;
|
||||
background-color: #ef3030;
|
||||
margin-top: -80rpx;
|
||||
padding-bottom: 30rpx;
|
||||
border-bottom-left-radius: 10rpx;
|
||||
border-bottom-right-radius: 10rpx;
|
||||
|
||||
&>view {
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
|
||||
.reward-content {
|
||||
margin: 0 50rpx 0 50rpx;
|
||||
}
|
||||
|
||||
.reward-item {
|
||||
.head {
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
line-height: 1;
|
||||
margin: 20rpx 0;
|
||||
}
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
padding: 16rpx 26rpx;
|
||||
background: #fff;
|
||||
border-radius: 10rpx;
|
||||
margin-bottom: 10rpx;
|
||||
|
||||
.info {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.tip {
|
||||
color: #ff222d;
|
||||
padding: 10rpx 0 10rpx 30rpx;
|
||||
width: 70rpx;
|
||||
line-height: 1.5;
|
||||
letter-spacing: 2rpx;
|
||||
border-left: 2rpx dashed #e5e5e5;
|
||||
}
|
||||
|
||||
.num {
|
||||
font-size: 52rpx;
|
||||
color: #ff222d;
|
||||
font-weight: bolder;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.coupon-name {
|
||||
font-size: 38rpx;
|
||||
}
|
||||
|
||||
.type {
|
||||
font-size: $font-size-base;
|
||||
margin-left: 10rpx;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.desc {
|
||||
margin-top: 8rpx;
|
||||
color: $color-tip;
|
||||
font-size: $font-size-tag;
|
||||
line-height: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.btn {
|
||||
position: absolute;
|
||||
width: calc(100% - 100rpx);
|
||||
bottom: 40rpx;
|
||||
left: 50rpx;
|
||||
|
||||
.btn-img {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -13,14 +13,14 @@
|
||||
<uni-popup ref="confirmPopup" type="center">
|
||||
<view class="confirm-popup">
|
||||
<view class="popup-header">
|
||||
<text>{{ $lang("common.wxwork-contact.l16.t0") }}</text>
|
||||
<text>添加企业微信客服</text>
|
||||
</view>
|
||||
<view class="popup-body">
|
||||
<text>{{ $lang("common.wxwork-contact.l19.t0") }}</text>
|
||||
<text>点击确定后将跳转至企业微信,添加专业客服为您服务</text>
|
||||
</view>
|
||||
<view class="popup-footer">
|
||||
<button class="cancel-btn" @click="closePopup">{{ $lang("common.pick-regions.l17.t0") }}</button>
|
||||
<button class="confirm-btn" @click="confirmAdd">{{ $lang("common.ns-goods-sku.ns-goods-sku-category.l76.t0") }}</button>
|
||||
<button class="cancel-btn" @click="closePopup">取消</button>
|
||||
<button class="confirm-btn" @click="confirmAdd">确定</button>
|
||||
</view>
|
||||
</view>
|
||||
</uni-popup>
|
||||
@@ -36,7 +36,7 @@
|
||||
// 按钮文字
|
||||
btnText: {
|
||||
type: String,
|
||||
default: $lang('common.wxwork-contact.l16.t0')
|
||||
default: '添加企业微信客服'
|
||||
},
|
||||
// 企业ID(必需)
|
||||
corpId: {
|
||||
@@ -105,11 +105,11 @@
|
||||
});
|
||||
|
||||
if (!initResult) {
|
||||
console.error($lang('common.wxwork-contact.l108.t0'));
|
||||
console.error('企业微信SDK初始化失败');
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error($lang('common.wxwork-contact.l112.t0'), error);
|
||||
console.error('初始化企业微信SDK失败:', error);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -142,7 +142,7 @@
|
||||
// 方案2:使用SDK打开用户资料
|
||||
this.openUserProfile(contactId);
|
||||
} else {
|
||||
this.showError($lang('common.wxwork-contact.l145.t0'));
|
||||
this.showError('未配置企业微信客服信息');
|
||||
}
|
||||
// #endif
|
||||
|
||||
@@ -151,7 +151,7 @@
|
||||
// H5环境直接跳转
|
||||
window.location.href = contactUrl;
|
||||
} else {
|
||||
this.showError($lang('common.wxwork-contact.l145.t0'));
|
||||
this.showError('未配置企业微信客服信息');
|
||||
}
|
||||
// #endif
|
||||
},
|
||||
@@ -165,13 +165,13 @@
|
||||
path: `pages/contacts/externalContactDetail?url=${encodeURIComponent(contactUrl)}`,
|
||||
success: () => {
|
||||
this.$util.showToast({
|
||||
title: $lang('common.wxwork-contact.l168.t0'),
|
||||
title: '跳转成功',
|
||||
icon: 'success'
|
||||
});
|
||||
},
|
||||
fail: (err) => {
|
||||
console.error($lang('common.wxwork-contact.l173.t0'), err);
|
||||
this.showError($lang('common.wxwork-contact.l174.t0'));
|
||||
console.error('跳转企业微信失败:', err);
|
||||
this.showError('跳转失败,请检查企业微信配置');
|
||||
}
|
||||
});
|
||||
},
|
||||
@@ -181,7 +181,7 @@
|
||||
*/
|
||||
openUserProfile(contactId) {
|
||||
if (!this.wxWorkSDK) {
|
||||
this.showError($lang('common.wxwork-contact.l184.t0'));
|
||||
this.showError('企业微信SDK未初始化');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -189,8 +189,8 @@
|
||||
userId: contactId
|
||||
}, (res) => {
|
||||
}, (err) => {
|
||||
console.error($lang('common.wxwork-contact.l192.t0'), err);
|
||||
this.showError($lang('common.wxwork-contact.l193.t0'));
|
||||
console.error('打开用户资料失败:', err);
|
||||
this.showError('打开用户资料失败');
|
||||
});
|
||||
},
|
||||
|
||||
@@ -199,7 +199,7 @@
|
||||
*/
|
||||
showError(message) {
|
||||
uni.showModal({
|
||||
title: $lang('common.wxwork-contact.l202.t0'),
|
||||
title: '提示',
|
||||
content: message,
|
||||
showCancel: false
|
||||
});
|
||||
|
||||
@@ -1,98 +1,98 @@
|
||||
//字符串拼接
|
||||
export function strFormat(str) {
|
||||
return str < 10 ? `0${str}` : str
|
||||
}
|
||||
// 获取当前时间
|
||||
export function currentTime() {
|
||||
const myDate = new Date();
|
||||
const year = myDate.getFullYear()
|
||||
const m = myDate.getMonth() + 1;
|
||||
const d = myDate.getDate();
|
||||
// const date = year + '-' + strFormat(m) + '-' + strFormat(d); // 隐藏年
|
||||
const date = strFormat(m) + '-' + strFormat(d);
|
||||
|
||||
const hour = myDate.getHours()
|
||||
const min = myDate.getMinutes()
|
||||
const secon = myDate.getSeconds()
|
||||
const time = strFormat(hour) + ':' + strFormat(min) + ':' + strFormat(secon);
|
||||
return {
|
||||
year,
|
||||
date,
|
||||
time
|
||||
}
|
||||
}
|
||||
|
||||
//时间戳转日期
|
||||
export function timeStamp(time) {
|
||||
const dates = new Date(time)
|
||||
const year = dates.getFullYear()
|
||||
const month = dates.getMonth() + 1
|
||||
const date = dates.getDate()
|
||||
const day = dates.getDay()
|
||||
const hour = dates.getHours()
|
||||
const min = dates.getMinutes()
|
||||
const days = [$lang('common.ns-select-time.l98.t0'), $lang('common.yuyue-date.l34.t0'), $lang('common.yuyue-date.l34.t1'), $lang('common.yuyue-date.l34.t2'), $lang('common.yuyue-date.l34.t3'), $lang('common.yuyue-date.l34.t4'), $lang('common.yuyue-date.l34.t5')]
|
||||
return {
|
||||
allDate: `${year}/${strFormat(month)}/${strFormat(date)}`,
|
||||
date: `${strFormat(month)}-${strFormat(date)}`, //返回的日期 07-01,${strFormat(year)}-${strFormat(month)}-${strFormat(date)}
|
||||
day: $lang(`common.yuyue-date.l38.t0`), //返回的礼拜天数 星期一
|
||||
hour: strFormat(hour) + ':' + strFormat(min) // + ':00' //返回的时钟 08:00
|
||||
}
|
||||
}
|
||||
|
||||
//获取最近7天的日期和礼拜天数
|
||||
export function initData(appointedDay = '') {
|
||||
const time = []
|
||||
const date = appointedDay ? new Date(appointedDay) : new Date()
|
||||
|
||||
const now = date.getTime() //获取当前日期的时间戳
|
||||
let timeStr = 3600 * 24 * 1000 //一天的时间戳
|
||||
let obj = {
|
||||
0: $lang("common.ns-select-time.l173.t0"),
|
||||
1: $lang("common.ns-select-time.l185.t0"),
|
||||
2: $lang("common.yuyue-date.l53.t0")
|
||||
}
|
||||
for (let i = 0; i < 7; i++) {
|
||||
const timeObj = {}
|
||||
timeObj.date = timeStamp(now + timeStr * i).date //保存日期
|
||||
timeObj.timeStamp = now + timeStr * i //保存时间戳
|
||||
timeObj.week = appointedDay == '' ? (obj[i] ?? timeStamp(now + timeStr * i).day) : timeStamp(now + timeStr * i)
|
||||
.day
|
||||
time.push(timeObj)
|
||||
}
|
||||
return time
|
||||
}
|
||||
|
||||
//时间数组
|
||||
export function initTime(startTime = '09:00', endTime = '18:30', timeInterval = 1) {
|
||||
const time = []
|
||||
const date = timeStamp(Date.now()).allDate
|
||||
const startDate = `${date} ${startTime}`
|
||||
const endDate = `${date} ${endTime}`
|
||||
const startTimeStamp = new Date(startDate).getTime()
|
||||
const endTimeStamp = new Date(endDate).getTime()
|
||||
const timeStr = 3600 * 1000 * timeInterval
|
||||
for (let i = startTimeStamp; i <= endTimeStamp; i = i + timeStr) {
|
||||
const timeObj = {}
|
||||
timeObj.time = timeStamp(i).hour
|
||||
timeObj.disable = false
|
||||
time.push(timeObj)
|
||||
}
|
||||
return time
|
||||
}
|
||||
|
||||
export function weekDate(){
|
||||
var now = new Date(); //当前日期
|
||||
var nowDayOfWeek = now.getDay(); //今天本周的第几天
|
||||
var nowDay = now.getDate(); //当前日
|
||||
var nowMonth = now.getMonth(); //当前月
|
||||
var nowYear = now.getYear(); //当前年
|
||||
|
||||
var weekStartDate = new Date(nowYear, nowMonth, nowDay - nowDayOfWeek + 1);
|
||||
var weekEndDate = new Date(nowYear, nowMonth, nowDay + (7 - nowDayOfWeek));
|
||||
|
||||
var arr = [];
|
||||
arr[0] = strFormat(weekStartDate.getMonth()+1) + '-' + strFormat(weekStartDate.getDate());
|
||||
arr[1] = strFormat(weekEndDate.getMonth()+1) + '-' + strFormat(weekEndDate.getDate());
|
||||
return arr;
|
||||
}
|
||||
//字符串拼接
|
||||
export function strFormat(str) {
|
||||
return str < 10 ? `0${str}` : str
|
||||
}
|
||||
// 获取当前时间
|
||||
export function currentTime() {
|
||||
const myDate = new Date();
|
||||
const year = myDate.getFullYear()
|
||||
const m = myDate.getMonth() + 1;
|
||||
const d = myDate.getDate();
|
||||
// const date = year + '-' + strFormat(m) + '-' + strFormat(d); // 隐藏年
|
||||
const date = strFormat(m) + '-' + strFormat(d);
|
||||
|
||||
const hour = myDate.getHours()
|
||||
const min = myDate.getMinutes()
|
||||
const secon = myDate.getSeconds()
|
||||
const time = strFormat(hour) + ':' + strFormat(min) + ':' + strFormat(secon);
|
||||
return {
|
||||
year,
|
||||
date,
|
||||
time
|
||||
}
|
||||
}
|
||||
|
||||
//时间戳转日期
|
||||
export function timeStamp(time) {
|
||||
const dates = new Date(time)
|
||||
const year = dates.getFullYear()
|
||||
const month = dates.getMonth() + 1
|
||||
const date = dates.getDate()
|
||||
const day = dates.getDay()
|
||||
const hour = dates.getHours()
|
||||
const min = dates.getMinutes()
|
||||
const days = ['日', '一', '二', '三', '四', '五', '六']
|
||||
return {
|
||||
allDate: `${year}/${strFormat(month)}/${strFormat(date)}`,
|
||||
date: `${strFormat(month)}-${strFormat(date)}`, //返回的日期 07-01,${strFormat(year)}-${strFormat(month)}-${strFormat(date)}
|
||||
day: `周${days[day]}`, //返回的礼拜天数 星期一
|
||||
hour: strFormat(hour) + ':' + strFormat(min) // + ':00' //返回的时钟 08:00
|
||||
}
|
||||
}
|
||||
|
||||
//获取最近7天的日期和礼拜天数
|
||||
export function initData(appointedDay = '') {
|
||||
const time = []
|
||||
const date = appointedDay ? new Date(appointedDay) : new Date()
|
||||
|
||||
const now = date.getTime() //获取当前日期的时间戳
|
||||
let timeStr = 3600 * 24 * 1000 //一天的时间戳
|
||||
let obj = {
|
||||
0: "今天",
|
||||
1: "明天",
|
||||
2: "后天"
|
||||
}
|
||||
for (let i = 0; i < 7; i++) {
|
||||
const timeObj = {}
|
||||
timeObj.date = timeStamp(now + timeStr * i).date //保存日期
|
||||
timeObj.timeStamp = now + timeStr * i //保存时间戳
|
||||
timeObj.week = appointedDay == '' ? (obj[i] ?? timeStamp(now + timeStr * i).day) : timeStamp(now + timeStr * i)
|
||||
.day
|
||||
time.push(timeObj)
|
||||
}
|
||||
return time
|
||||
}
|
||||
|
||||
//时间数组
|
||||
export function initTime(startTime = '09:00', endTime = '18:30', timeInterval = 1) {
|
||||
const time = []
|
||||
const date = timeStamp(Date.now()).allDate
|
||||
const startDate = `${date} ${startTime}`
|
||||
const endDate = `${date} ${endTime}`
|
||||
const startTimeStamp = new Date(startDate).getTime()
|
||||
const endTimeStamp = new Date(endDate).getTime()
|
||||
const timeStr = 3600 * 1000 * timeInterval
|
||||
for (let i = startTimeStamp; i <= endTimeStamp; i = i + timeStr) {
|
||||
const timeObj = {}
|
||||
timeObj.time = timeStamp(i).hour
|
||||
timeObj.disable = false
|
||||
time.push(timeObj)
|
||||
}
|
||||
return time
|
||||
}
|
||||
|
||||
export function weekDate(){
|
||||
var now = new Date(); //当前日期
|
||||
var nowDayOfWeek = now.getDay(); //今天本周的第几天
|
||||
var nowDay = now.getDate(); //当前日
|
||||
var nowMonth = now.getMonth(); //当前月
|
||||
var nowYear = now.getYear(); //当前年
|
||||
|
||||
var weekStartDate = new Date(nowYear, nowMonth, nowDay - nowDayOfWeek + 1);
|
||||
var weekEndDate = new Date(nowYear, nowMonth, nowDay + (7 - nowDayOfWeek));
|
||||
|
||||
var arr = [];
|
||||
arr[0] = strFormat(weekStartDate.getMonth()+1) + '-' + strFormat(weekStartDate.getDate());
|
||||
arr[1] = strFormat(weekEndDate.getMonth()+1) + '-' + strFormat(weekEndDate.getDate());
|
||||
return arr;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<!-- <uni-popup ref="timePopup" type="bottom"> -->
|
||||
<view class="content">
|
||||
<!-- <view class="head">
|
||||
<text class="title">{{ $lang("common.yuyue-date.l6.t0") }}</text>
|
||||
<text class="title">选择时间</text>
|
||||
<text class="iconfont iconclose" @click="close()"></text>
|
||||
</view> -->
|
||||
<view class="container">
|
||||
@@ -20,7 +20,7 @@
|
||||
</scroll-view>
|
||||
<div class="appointed-day">
|
||||
<uni-datetime-picker type="date" :start="pickerStartDay" :end="pickerEndDay" @change="change">
|
||||
<text class="day-box">{{ $lang("common.yuyue-date.l23.t0") }}</text>
|
||||
<text class="day-box">指定日期</text>
|
||||
<text class="iconfont iconyoujiantou"></text>
|
||||
</uni-datetime-picker>
|
||||
</div>
|
||||
@@ -54,13 +54,13 @@
|
||||
</view>
|
||||
<!-- <view class="bottom">
|
||||
<view class="show-time" v-if="!isMultiple && !isSection">
|
||||
<text>{{ $lang("common.yuyue-date.l57.t0") }}</text>
|
||||
<text>预约时间:</text>
|
||||
<text class="color-base-text">{{ orderDateTime }}</text>
|
||||
</view>
|
||||
<button form-type="submit" type="primary" size="mini" class="submit-btn" @click="handleSubmit">{{ $lang("common.yuyue-date.l60.t0") }}</button>
|
||||
<button form-type="submit" type="primary" size="mini" class="submit-btn" @click="handleSubmit">确认预约</button>
|
||||
</view> -->
|
||||
</view>
|
||||
<!-- <view class="yuyue-date-desc">{{ $lang("common.yuyue-date.l63.t0") }}</view> -->
|
||||
<!-- <view class="yuyue-date-desc">如不想线上预约,可致电商家电话预约</view> -->
|
||||
<!-- </uni-popup> -->
|
||||
</view>
|
||||
</template>
|
||||
@@ -100,12 +100,12 @@
|
||||
disableText: {
|
||||
//禁用显示的文本
|
||||
type: String,
|
||||
default: $lang('common.yuyue-date.l103.t0')
|
||||
default: '已约满'
|
||||
},
|
||||
undisableText: {
|
||||
//未禁用显示的文本
|
||||
type: String,
|
||||
default: $lang('common.yuyue-date.l108.t0')
|
||||
default: '可预约'
|
||||
},
|
||||
timeInterval: {
|
||||
// 时间间隔,小时为单位
|
||||
@@ -173,7 +173,7 @@
|
||||
return {
|
||||
pickerStartDay: '', // 指定开始日期
|
||||
pickerEndDay: '', // 指定结束日期
|
||||
orderDateTime: $lang('common.yuyue-date.l176.t0'), // 选中时间
|
||||
orderDateTime: '暂无选择', // 选中时间
|
||||
orderTimeArr: {}, //多选的时间
|
||||
dateArr: [], //日期数据
|
||||
timeArr: [], //时间数据
|
||||
@@ -209,11 +209,11 @@
|
||||
let date = e.split("-");
|
||||
date = date[1] + "-" + date[2];
|
||||
if (this.disableWeek.length && date >= weekDate()[0] && date <= weekDate()[1]) {
|
||||
let weekBox = [$lang('common.ns-select-time.l148.t0'), $lang('common.ns-select-time.l148.t1'), $lang('common.ns-select-time.l148.t2'), $lang('common.ns-select-time.l148.t3'), $lang('common.ns-select-time.l148.t4'), $lang('common.ns-select-time.l148.t5'), $lang('common.ns-select-time.l148.t6')];
|
||||
let weekBox = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
|
||||
let index = new Date(e).getDay();
|
||||
if (this.disableWeek.indexOf(weekBox[index]) != -1) {
|
||||
uni.showToast({
|
||||
title: weekBox[index] + $lang('common.yuyue-date.l216.t0'),
|
||||
title: weekBox[index] + '不可以预约',
|
||||
icon: 'none'
|
||||
})
|
||||
return false;
|
||||
@@ -231,7 +231,7 @@
|
||||
// 判断默认是不能选择的周,则都禁止选中
|
||||
if (this.disableWeek.length && this.selectDate >= weekDate()[0] && this.selectDate <=
|
||||
weekDate()[1]) {
|
||||
let weekBox = [$lang('common.ns-select-time.l148.t0'), $lang('common.ns-select-time.l148.t1'), $lang('common.ns-select-time.l148.t2'), $lang('common.ns-select-time.l148.t3'), $lang('common.ns-select-time.l148.t4'), $lang('common.ns-select-time.l148.t5'), $lang('common.ns-select-time.l148.t6')];
|
||||
let weekBox = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
|
||||
let date = currentTime().year + '-' + this.selectDate;
|
||||
let index = new Date(date).getDay();
|
||||
if (this.disableWeek.indexOf(weekBox[index]) != -1) {
|
||||
@@ -297,11 +297,11 @@
|
||||
// 日期选择事件
|
||||
selectDateEvent(index, item) {
|
||||
if (this.disableWeek.length && item.date >= weekDate()[0] && item.date <= weekDate()[1]) {
|
||||
let weekBox = [$lang('common.ns-select-time.l148.t0'), $lang('common.ns-select-time.l148.t1'), $lang('common.ns-select-time.l148.t2'), $lang('common.ns-select-time.l148.t3'), $lang('common.ns-select-time.l148.t4'), $lang('common.ns-select-time.l148.t5'), $lang('common.ns-select-time.l148.t6')];
|
||||
let weekBox = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
|
||||
let index = new Date(item.timeStamp).getDay();
|
||||
if (this.disableWeek.indexOf(weekBox[index]) != -1) {
|
||||
uni.showToast({
|
||||
title: weekBox[index] + $lang('common.yuyue-date.l216.t0'),
|
||||
title: weekBox[index] + '不可以预约',
|
||||
icon: 'none'
|
||||
})
|
||||
return false;
|
||||
|
||||
1911
lang/en-us.js
1911
lang/en-us.js
File diff suppressed because it is too large
Load Diff
104
lang/en-us/ai-chat/index.js
Normal file
104
lang/en-us/ai-chat/index.js
Normal file
@@ -0,0 +1,104 @@
|
||||
export const lang = {
|
||||
//title for each page
|
||||
title: 'AI Customer Service',
|
||||
|
||||
// ====== Common ======
|
||||
cancel: 'Cancel',
|
||||
save: 'Save',
|
||||
send: 'Send',
|
||||
retry: 'Retry',
|
||||
|
||||
// ====== Time Format ======
|
||||
timeFormatToday: 'Today',
|
||||
timeFormatYesterday: 'Yesterday',
|
||||
timeFormatBeforeYesterday: 'Day before yesterday',
|
||||
|
||||
// ====== ai-chat-message ======
|
||||
aiNickname: 'AI Assistant',
|
||||
defaultNickname: 'Me',
|
||||
audioMessage: 'Voice Message',
|
||||
videoMessage: 'Video Message',
|
||||
inputPlaceholder: 'Please enter your question...',
|
||||
expandEditorTitle: 'Edit Content',
|
||||
loadMoreHistory: 'Load more history',
|
||||
loadingHistory: 'Loading history...',
|
||||
aiThinking: 'AI is thinking',
|
||||
receivingReply: 'Receiving reply',
|
||||
aiThinkingStatus1: 'AI is thinking',
|
||||
aiThinkingStatus2: 'AI is analyzing',
|
||||
aiThinkingStatus3: 'AI is searching',
|
||||
aiThinkingStatus4: 'AI is generating',
|
||||
serviceUnavailable: 'Sorry, the AI service is temporarily unavailable. Please try again later.',
|
||||
serviceTemporaryUnavailable: 'Sorry, the service is temporarily unavailable. Please try again later.',
|
||||
noContentToCopy: 'No content to copy',
|
||||
copySuccess: 'Copied',
|
||||
copySelected: 'Copied selected content',
|
||||
copyFail: 'Copy failed',
|
||||
openingFile: 'Opening file...',
|
||||
fileOpenFail: 'Failed to open file',
|
||||
loadHistoryFail: 'Failed to load history',
|
||||
about: '0B',
|
||||
|
||||
// ====== ai-chat-search ======
|
||||
searchEntrance: 'Search',
|
||||
searchPlaceholder: 'Search chat history',
|
||||
searchClose: 'Done',
|
||||
noMatchResult: 'No matching results',
|
||||
searchAtTop: 'Already at top',
|
||||
searchAtBottom: 'Already at bottom',
|
||||
|
||||
// ====== index.vue ======
|
||||
settingsTitle: 'Settings',
|
||||
fallbackWelcome: 'Hello! I am an AI customer service assistant, glad to serve you!\n\nI can help you with:\n• Product-related questions\n• Order issues\n• Technical support\n• Product recommendations\n\nPlease tell me how I can assist you?',
|
||||
changeAvatar: 'Change Avatar',
|
||||
changeAvatarDesc: 'Customize your chat avatar',
|
||||
changeNickname: 'Change Nickname',
|
||||
changeNicknameDesc: 'Customize your nickname',
|
||||
clearChat: 'Clear Chat',
|
||||
exportChat: 'Export Records',
|
||||
help: 'Help',
|
||||
confirmClearChat: 'Are you sure you want to clear the chat?',
|
||||
chatCleared: 'Chat history has been cleared. How can I help you?',
|
||||
featureDeveloping: 'Feature under development',
|
||||
thanksFeedback: 'Thank you for your feedback!',
|
||||
improveService: 'We will improve our service',
|
||||
openLink: 'Open Link',
|
||||
confirmOpenLink: 'Are you sure you want to open this link: ',
|
||||
operationFailed: 'Operation failed, please try again',
|
||||
prompt: 'Prompt',
|
||||
serviceTypeNotSupported: 'Current service type does not support this page',
|
||||
|
||||
// ====== ai-chat-avatar-selector ======
|
||||
avatarSelectorTitle: 'Change Avatar',
|
||||
chooseFromAlbum: 'Choose from Album',
|
||||
avatarChangeSuccess: 'Avatar changed successfully',
|
||||
enableAlbumPermission: 'Please enable album permission',
|
||||
|
||||
// ====== ai-chat-emoji-panel ======
|
||||
emojiTitle: 'Emoji',
|
||||
|
||||
// ====== ai-chat-nickname-editor ======
|
||||
editNickname: 'Edit Nickname',
|
||||
newNicknamePlaceholder: 'Please enter your new nickname',
|
||||
nicknameTip: 'Nickname length 1-12 characters, visible only to you',
|
||||
nicknameChangeSuccess: 'Nickname changed successfully',
|
||||
|
||||
// ====== ai-chat-tools-panel ======
|
||||
moreFunctions: 'More Features',
|
||||
image: 'Image',
|
||||
file: 'File',
|
||||
voice: 'Voice',
|
||||
location: 'Location',
|
||||
|
||||
// ====== ai-chat-voice-panel ======
|
||||
voiceInputTitle: 'Voice Input',
|
||||
recordingTip: 'Recording, release to end',
|
||||
startRecordTip: 'Tap to start recording',
|
||||
voiceInputFailed: 'Voice input failed',
|
||||
|
||||
// ====== index.vue - Menu ======
|
||||
menuClearChat: 'Clear Chat',
|
||||
menuExport: 'Export Records',
|
||||
menuSettings: 'Settings',
|
||||
menuHelp: 'Help'
|
||||
}
|
||||
4
lang/en-us/article/detail.js
Normal file
4
lang/en-us/article/detail.js
Normal file
@@ -0,0 +1,4 @@
|
||||
export const lang = {
|
||||
//title为每个页面的标题
|
||||
title: 'Article Details'
|
||||
}
|
||||
5
lang/en-us/article/list.js
Normal file
5
lang/en-us/article/list.js
Normal file
@@ -0,0 +1,5 @@
|
||||
export const lang = {
|
||||
//title为每个页面的标题
|
||||
title: 'Article List',
|
||||
emptyText: "No article information available currently"
|
||||
}
|
||||
4
lang/en-us/bale/detail.js
Normal file
4
lang/en-us/bale/detail.js
Normal file
@@ -0,0 +1,4 @@
|
||||
export const lang = {
|
||||
//title为每个页面的标题
|
||||
title: ''
|
||||
}
|
||||
4
lang/en-us/bale/payment.js
Normal file
4
lang/en-us/bale/payment.js
Normal file
@@ -0,0 +1,4 @@
|
||||
export const lang = {
|
||||
//title为每个页面的标题
|
||||
title: 'Pending Payment Order'
|
||||
}
|
||||
10
lang/en-us/bargain/detail.js
Normal file
10
lang/en-us/bargain/detail.js
Normal file
@@ -0,0 +1,10 @@
|
||||
export const lang = {
|
||||
//title为每个页面的标题
|
||||
title: '',
|
||||
select: 'Select',
|
||||
params: 'Parameters',
|
||||
service: 'Product Service',
|
||||
allGoods: 'All Products',
|
||||
image: 'Image',
|
||||
video: 'Video',
|
||||
}
|
||||
4
lang/en-us/bargain/launch.js
Normal file
4
lang/en-us/bargain/launch.js
Normal file
@@ -0,0 +1,4 @@
|
||||
export const lang = {
|
||||
//title为每个页面的标题
|
||||
title: 'Bargain Details'
|
||||
}
|
||||
4
lang/en-us/bargain/list.js
Normal file
4
lang/en-us/bargain/list.js
Normal file
@@ -0,0 +1,4 @@
|
||||
export const lang = {
|
||||
//title为每个页面的标题
|
||||
title: 'Bargain Zone'
|
||||
}
|
||||
4
lang/en-us/bargain/my_bargain.js
Normal file
4
lang/en-us/bargain/my_bargain.js
Normal file
@@ -0,0 +1,4 @@
|
||||
export const lang = {
|
||||
//title为每个页面的标题
|
||||
title: 'My Bargain'
|
||||
}
|
||||
4
lang/en-us/bargain/payment.js
Normal file
4
lang/en-us/bargain/payment.js
Normal file
@@ -0,0 +1,4 @@
|
||||
export const lang = {
|
||||
//title为每个页面的标题
|
||||
title: 'Pending Payment Order'
|
||||
}
|
||||
4
lang/en-us/combo/detail.js
Normal file
4
lang/en-us/combo/detail.js
Normal file
@@ -0,0 +1,4 @@
|
||||
export const lang = {
|
||||
//title为每个页面的标题
|
||||
title: 'Combo Package'
|
||||
}
|
||||
4
lang/en-us/combo/payment.js
Normal file
4
lang/en-us/combo/payment.js
Normal file
@@ -0,0 +1,4 @@
|
||||
export const lang = {
|
||||
//title为每个页面的标题
|
||||
title: 'Pending Payment Orders'
|
||||
}
|
||||
37
lang/en-us/common.js
Normal file
37
lang/en-us/common.js
Normal file
@@ -0,0 +1,37 @@
|
||||
export const lang = {
|
||||
|
||||
// 底部选项卡
|
||||
tabBar: {
|
||||
home: 'index',
|
||||
category: 'category',
|
||||
cart: 'cart',
|
||||
member: 'member',
|
||||
},
|
||||
|
||||
//公共
|
||||
common: {
|
||||
//语言包名称
|
||||
name: '英文',
|
||||
mescrollTextInOffset: 'pull to refresh',
|
||||
mescrollTextOutOffset: 'Loading...',
|
||||
mescrollEmpty: "No data available",
|
||||
goodsRecommendTitle: 'Guess you like',
|
||||
currencySymbol: '¥',
|
||||
submit: 'Submit',
|
||||
searchTip: 'Please enter search keywords'
|
||||
},
|
||||
|
||||
//customer service
|
||||
customer: {
|
||||
weChatKefu: 'WeChat Customer Service',
|
||||
systemKefu: 'System Customer Service',
|
||||
weChatWorkKefu: 'WeChat Work Customer Service',
|
||||
},
|
||||
|
||||
getDynacode: 'Get Code',
|
||||
|
||||
login: 'Login/Register',
|
||||
loginTips: 'Click to login and enjoy more exciting information',
|
||||
toLogin: 'Go to login',
|
||||
toGoodsCategoryPage: 'Go shopping',
|
||||
}
|
||||
18
lang/en-us/contact/contact.js
Normal file
18
lang/en-us/contact/contact.js
Normal file
@@ -0,0 +1,18 @@
|
||||
export const lang = {
|
||||
//title为每个页面的标题
|
||||
title: 'Electronic Card',
|
||||
onlineMessage: 'Online Message',
|
||||
call: 'One-click Call',
|
||||
copy: 'Copy',
|
||||
copyFailed: 'Copy Failed',
|
||||
copySuccess: 'Copy Success',
|
||||
oneClickNavigation: 'One-click Navigation',
|
||||
name: 'Name',
|
||||
contactInfo: 'Contact Info',
|
||||
messageContent: 'Message Content',
|
||||
pleaseEnterName: 'Please enter your name',
|
||||
pleaseEnterMobile: 'Please enter your phone number',
|
||||
pleaseEnterMessage: 'Please enter your message',
|
||||
submit: 'Submit',
|
||||
exclusiveCustomerService: 'Exclusive Customer Service'
|
||||
}
|
||||
4
lang/en-us/diy/diy.js
Normal file
4
lang/en-us/diy/diy.js
Normal file
@@ -0,0 +1,4 @@
|
||||
export const lang = {
|
||||
//title为每个页面的标题
|
||||
title: '',
|
||||
}
|
||||
5
lang/en-us/fenxiao/apply.js
Normal file
5
lang/en-us/fenxiao/apply.js
Normal file
@@ -0,0 +1,5 @@
|
||||
export const lang = {
|
||||
//title为每个页面的标题
|
||||
// title: 'Distributor Application'
|
||||
title: ''
|
||||
}
|
||||
4
lang/en-us/fenxiao/bill.js
Normal file
4
lang/en-us/fenxiao/bill.js
Normal file
@@ -0,0 +1,4 @@
|
||||
export const lang = {
|
||||
//title为每个页面的标题
|
||||
title: 'Bill'
|
||||
}
|
||||
4
lang/en-us/fenxiao/follow.js
Normal file
4
lang/en-us/fenxiao/follow.js
Normal file
@@ -0,0 +1,4 @@
|
||||
export const lang = {
|
||||
//title为每个页面的标题
|
||||
title: 'My Following'
|
||||
}
|
||||
5
lang/en-us/fenxiao/goods_list.js
Normal file
5
lang/en-us/fenxiao/goods_list.js
Normal file
@@ -0,0 +1,5 @@
|
||||
export const lang = {
|
||||
//title为每个页面的标题
|
||||
// title: 'Distribution Product List',
|
||||
title: ''
|
||||
}
|
||||
5
lang/en-us/fenxiao/index.js
Normal file
5
lang/en-us/fenxiao/index.js
Normal file
@@ -0,0 +1,5 @@
|
||||
export const lang = {
|
||||
//title为每个页面的标题
|
||||
// title: 'Distribution Center',
|
||||
title: ''
|
||||
}
|
||||
5
lang/en-us/fenxiao/level.js
Normal file
5
lang/en-us/fenxiao/level.js
Normal file
@@ -0,0 +1,5 @@
|
||||
export const lang = {
|
||||
//title为每个页面的标题
|
||||
// title: 'Distributor Level',
|
||||
title: ''
|
||||
}
|
||||
5
lang/en-us/fenxiao/order.js
Normal file
5
lang/en-us/fenxiao/order.js
Normal file
@@ -0,0 +1,5 @@
|
||||
export const lang = {
|
||||
//title为每个页面的标题
|
||||
// title: 'Distribution Orders',
|
||||
title: ''
|
||||
}
|
||||
4
lang/en-us/fenxiao/order_detail.js
Normal file
4
lang/en-us/fenxiao/order_detail.js
Normal file
@@ -0,0 +1,4 @@
|
||||
export const lang = {
|
||||
//title为每个页面的标题
|
||||
title: 'Order Details'
|
||||
}
|
||||
4
lang/en-us/fenxiao/promote_code.js
Normal file
4
lang/en-us/fenxiao/promote_code.js
Normal file
@@ -0,0 +1,4 @@
|
||||
export const lang = {
|
||||
//title为每个页面的标题
|
||||
title: 'Promotion Poster'
|
||||
}
|
||||
5
lang/en-us/fenxiao/team.js
Normal file
5
lang/en-us/fenxiao/team.js
Normal file
@@ -0,0 +1,5 @@
|
||||
export const lang = {
|
||||
//title为每个页面的标题
|
||||
// title: 'My Team'
|
||||
title: ''
|
||||
}
|
||||
5
lang/en-us/fenxiao/withdraw_apply.js
Normal file
5
lang/en-us/fenxiao/withdraw_apply.js
Normal file
@@ -0,0 +1,5 @@
|
||||
export const lang = {
|
||||
//title为每个页面的标题
|
||||
// title: 'Withdrawal Application'
|
||||
title: ''
|
||||
}
|
||||
5
lang/en-us/fenxiao/withdraw_list.js
Normal file
5
lang/en-us/fenxiao/withdraw_list.js
Normal file
@@ -0,0 +1,5 @@
|
||||
export const lang = {
|
||||
//title为每个页面的标题
|
||||
// title: 'Withdrawal Records'
|
||||
title: ''
|
||||
}
|
||||
4
lang/en-us/game/cards.js
Normal file
4
lang/en-us/game/cards.js
Normal file
@@ -0,0 +1,4 @@
|
||||
export const lang = {
|
||||
//title为每个页面的标题
|
||||
title: 'Scratch Card'
|
||||
}
|
||||
4
lang/en-us/game/record.js
Normal file
4
lang/en-us/game/record.js
Normal file
@@ -0,0 +1,4 @@
|
||||
export const lang = {
|
||||
//title为每个页面的标题
|
||||
title: 'Winning Records'
|
||||
}
|
||||
4
lang/en-us/game/smash_eggs.js
Normal file
4
lang/en-us/game/smash_eggs.js
Normal file
@@ -0,0 +1,4 @@
|
||||
export const lang = {
|
||||
//title为每个页面的标题
|
||||
title: 'Smash Golden Eggs'
|
||||
}
|
||||
4
lang/en-us/game/turntable.js
Normal file
4
lang/en-us/game/turntable.js
Normal file
@@ -0,0 +1,4 @@
|
||||
export const lang = {
|
||||
//title为每个页面的标题
|
||||
title: 'Turntable'
|
||||
}
|
||||
4
lang/en-us/goods/brand.js
Normal file
4
lang/en-us/goods/brand.js
Normal file
@@ -0,0 +1,4 @@
|
||||
export const lang = {
|
||||
//title为每个页面的标题
|
||||
title: 'Brand Zone'
|
||||
}
|
||||
13
lang/en-us/goods/cart.js
Normal file
13
lang/en-us/goods/cart.js
Normal file
@@ -0,0 +1,13 @@
|
||||
export const lang = {
|
||||
//title为每个页面的标题
|
||||
title: 'Shopping Cart',
|
||||
complete: 'Complete',
|
||||
edit: 'Manage',
|
||||
allElection: 'Select All',
|
||||
total: 'Total',
|
||||
settlement: 'Checkout',
|
||||
emptyTips: 'No products yet',
|
||||
goForStroll: 'Go shopping',
|
||||
del: 'Delete',
|
||||
login: 'Go to login'
|
||||
}
|
||||
6
lang/en-us/goods/category.js
Normal file
6
lang/en-us/goods/category.js
Normal file
@@ -0,0 +1,6 @@
|
||||
export const lang = {
|
||||
//title为每个页面的标题
|
||||
title: 'Goods Category',
|
||||
search: 'Search',
|
||||
seeMore : 'See More'
|
||||
}
|
||||
4
lang/en-us/goods/consult.js
Normal file
4
lang/en-us/goods/consult.js
Normal file
@@ -0,0 +1,4 @@
|
||||
export const lang = {
|
||||
//title为每个页面的标题
|
||||
title: 'Product Consultation'
|
||||
}
|
||||
4
lang/en-us/goods/consult_edit.js
Normal file
4
lang/en-us/goods/consult_edit.js
Normal file
@@ -0,0 +1,4 @@
|
||||
export const lang = {
|
||||
//title为每个页面的标题
|
||||
title: 'I Want to Consult'
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user