mirror of
https://gitee.com/ShopeX/ECShopX_admin-frontend
synced 2026-08-09 05:55:58 +08:00
merge webdecoration
This commit is contained in:
@@ -282,7 +282,7 @@ export function getAppcenterUrl(params) {
|
||||
export function loginUsercenter(params) {
|
||||
return fetch({
|
||||
url: '/company/usercenter/login',
|
||||
method: 'get',
|
||||
method: 'post',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
<el-button type="text" style="margin-right: 10px" @click="handleShowConfig">
|
||||
<i class="el-icon-setting" style="color: #8080ff" /> {{ $t('6880d32e.701fa5') }}
|
||||
</el-button>
|
||||
<!-- ECX-8712: 总部/店铺模版装修隐藏导航配置 -->
|
||||
<el-button type="text" @click="handleShowTabConfig">
|
||||
<i class="el-icon-setting" style="color: #8080ff" /> {{ $t('6880d32e.f9a598') }}
|
||||
</el-button>
|
||||
@@ -134,9 +135,12 @@
|
||||
<span class="btn" @click="copyTemplate(item.pages_template_id)">{{
|
||||
$t('6880d32e.79d3ab')
|
||||
}}</span>
|
||||
<!-- ECX-8712: 总部/店铺模版装修隐藏导航配置 -->
|
||||
<!--
|
||||
<span class="btn" @click="handleClickNav(item.pages_template_id)">{{
|
||||
$t('6880d32e.056f2d')
|
||||
}}</span>
|
||||
-->
|
||||
<span class="btn" @click="abandonTemplate(item.pages_template_id)">{{
|
||||
$t('6880d32e.0044f6')
|
||||
}}</span>
|
||||
|
||||
@@ -41,11 +41,6 @@
|
||||
</style>
|
||||
<template>
|
||||
<div class="picker-link">
|
||||
<!-- <SpFilterForm :model="formData" size="small" @onSearch="onSearch" @onReset="onSearch">
|
||||
<SpFilterFormItem prop="keywords">
|
||||
<el-input v-model="formData.keywords" placeholder="请输入页面名称" />
|
||||
</SpFilterFormItem>
|
||||
</SpFilterForm> -->
|
||||
<SpFinder
|
||||
ref="finder"
|
||||
:show-pager="false"
|
||||
@@ -71,6 +66,36 @@
|
||||
import { i18n } from '@/i18n'
|
||||
import BasePicker from './base'
|
||||
import PageMixin from '../mixins/page'
|
||||
|
||||
const BASE_LINK_PAGES = [
|
||||
{ id: 'vipgrades', titleKey: '223cc8af.f035ca' },
|
||||
{ id: 'applyChief', titleKey: '223cc8af.38d966' },
|
||||
{ id: 'recharge', titleKey: '223cc8af.1200d5' },
|
||||
{ id: 'purchase', titleKey: '223cc8af.d0465c' },
|
||||
{ id: 'pointShop', titleKey: '223cc8af.a13364' },
|
||||
{ id: 'registActivity', titleKey: '223cc8af.7fb92b' },
|
||||
{ id: 'group', titleKey: '223cc8af.75a1d2' },
|
||||
{ id: 'coupon_list', titleKey: '223cc8af.2f3635' },
|
||||
{ id: 'my_coupon', titleKey: '223cc8af.a8f3e2' },
|
||||
{ id: 'my_collect', titleKey: '223cc8af.975ff6' },
|
||||
{ id: 'address', titleKey: '223cc8af.bca1ea' },
|
||||
{ id: 'groups_list', titleKey: '223cc8af.f38e72' },
|
||||
{ id: 'hottopic', titleKey: '223cc8af.26b2d6' },
|
||||
{ id: 'zitiOrder', titleKey: '223cc8af.d50361' },
|
||||
{ id: 'homeSearch', titleKey: '223cc8af.e5f71f' },
|
||||
{ id: 'settings', titleKey: '223cc8af.e366cc' },
|
||||
{ id: 'kujiale', titleKey: '223cc8af.f2d3e5' },
|
||||
{ id: 'nearby_store', titleKey: '223cc8af.3b02dd' },
|
||||
{ id: 'itemList', titleKey: '223cc8af.437974' }
|
||||
]
|
||||
|
||||
function mapPageTitles(vm, items) {
|
||||
return items.map(({ id, titleKey }) => ({
|
||||
id,
|
||||
title: vm.$t(titleKey)
|
||||
}))
|
||||
}
|
||||
|
||||
export default {
|
||||
name: 'PickerLink',
|
||||
extends: BasePicker,
|
||||
@@ -87,54 +112,42 @@ export default {
|
||||
formData: {
|
||||
keywords: ''
|
||||
},
|
||||
list: [
|
||||
{ id: 'vipgrades', title: this.$t('223cc8af.f035ca') },
|
||||
{ id: 'applyChief', title: this.$t('223cc8af.38d966') },
|
||||
{ id: 'recharge', title: this.$t('223cc8af.1200d5') },
|
||||
{ id: 'purchase', title: this.$t('223cc8af.d0465c') },
|
||||
{ id: 'pointShop', title: this.$t('223cc8af.a13364') },
|
||||
{ id: 'registActivity', title: this.$t('223cc8af.7fb92b') },
|
||||
{ id: 'group', title: this.$t('223cc8af.75a1d2') },
|
||||
{ id: 'coupon_list', title: this.$t('223cc8af.2f3635') },
|
||||
{ id: 'my_coupon', title: this.$t('223cc8af.a8f3e2') },
|
||||
{ id: 'my_collect', title: this.$t('223cc8af.975ff6') },
|
||||
{ id: 'address', title: this.$t('223cc8af.bca1ea') },
|
||||
{ id: 'groups_list', title: this.$t('223cc8af.f38e72') },
|
||||
{ id: 'hottopic', title: this.$t('223cc8af.26b2d6') },
|
||||
{ id: 'zitiOrder', title: this.$t('223cc8af.d50361') },
|
||||
{ id: 'homeSearch', title: this.$t('223cc8af.e5f71f') },
|
||||
{ id: 'settings', title: this.$t('223cc8af.e366cc') },
|
||||
{ id: 'kujiale', title: this.$t('223cc8af.f2d3e5') },
|
||||
{ id: 'nearby_store', title: this.$t('223cc8af.3b02dd') },
|
||||
{ id: 'nearby_store', title: this.$t('223cc8af.3b02dd') },
|
||||
{ id: 'itemList', title: '商品列表' }
|
||||
],
|
||||
multiple: this.value?.multiple ?? true
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
list() {
|
||||
// 依赖 locale,切换语言后页面名称会重新翻译
|
||||
const locale = this.$i18n?.locale
|
||||
void locale
|
||||
|
||||
if (this.value?.guide === 'share_page') {
|
||||
return mapPageTitles(this, [
|
||||
{ id: 'coupon_list', titleKey: '223cc8af.9c356b' },
|
||||
{ id: 'my_coupon', titleKey: '223cc8af.a8f3e2' },
|
||||
{ id: 'page_index', titleKey: '223cc8af.db1c89' },
|
||||
{ id: 'category', titleKey: '223cc8af.d0771a' },
|
||||
{ id: 'hottopic', titleKey: '223cc8af.26b2d6' }
|
||||
])
|
||||
}
|
||||
|
||||
const items = [...BASE_LINK_PAGES]
|
||||
if (!this.VERSION_PLATFORM() && !this.VERSION_B2C()) {
|
||||
items.push(
|
||||
{ id: 'boost_activity', titleKey: '223cc8af.5c34aa' },
|
||||
{ id: 'boost_order', titleKey: '223cc8af.94b1e6' }
|
||||
)
|
||||
}
|
||||
if (!this.VERSION_STANDARD()) {
|
||||
items.push({ id: 'tenants', titleKey: '223cc8af.1107a8' })
|
||||
}
|
||||
if (!this.VERSION_IN_PURCHASE()) {
|
||||
items.push({ id: 'community_group_enable', titleKey: '223cc8af.d0f121' })
|
||||
}
|
||||
return mapPageTitles(this, items)
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
if (!this.VERSION_PLATFORM() && !this.VERSION_B2C()) {
|
||||
// 平台版&b2c隐藏助力活动和助力订单
|
||||
this.list.push(
|
||||
{ id: 'boost_activity', title: this.$t('223cc8af.5c34aa') },
|
||||
{ id: 'boost_order', title: this.$t('223cc8af.94b1e6') }
|
||||
)
|
||||
}
|
||||
if (!this.VERSION_STANDARD()) {
|
||||
this.list.push({ id: 'tenants', title: this.$t('223cc8af.1107a8') })
|
||||
}
|
||||
if (!this.VERSION_IN_PURCHASE()) {
|
||||
this.list.push({ id: 'community_group_enable', title: this.$t('223cc8af.d0f121') })
|
||||
}
|
||||
if (this.value.guide == 'share_page') {
|
||||
this.list = [
|
||||
{ id: 'coupon_list', title: this.$t('223cc8af.9c356b') },
|
||||
{ id: 'my_coupon', title: this.$t('223cc8af.a8f3e2') },
|
||||
{ id: 'page_index', title: this.$t('223cc8af.db1c89') },
|
||||
{ id: 'category', title: this.$t('223cc8af.d0771a') },
|
||||
{ id: 'hottopic', title: this.$t('223cc8af.26b2d6') }
|
||||
]
|
||||
}
|
||||
const raw = this.value?.data
|
||||
if (raw == null || raw === '') return
|
||||
const selectedIds = Array.isArray(raw) ? raw : [raw]
|
||||
@@ -155,11 +168,9 @@ export default {
|
||||
// this.updateVal(selection)
|
||||
} else {
|
||||
const { finderTable } = this.$refs.finder.$refs
|
||||
console.log('finderTable:', finderTable)
|
||||
finderTable.clearSelection()
|
||||
setTimeout(() => {
|
||||
finderTable.$refs.finderTable.setSelection([row])
|
||||
// this.updateVal([row])
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
@@ -4,9 +4,12 @@
|
||||
class="box-border flex min-h-14 items-center justify-between gap-3 border-b border-[#e6e9ef] bg-white/95 px-[14px] py-2 max-[1360px]:flex-wrap max-[1360px]:items-stretch"
|
||||
>
|
||||
<div class="flex min-w-0 items-center gap-2.5">
|
||||
<el-button class="!shrink-0" circle size="mini" @click="$emit('back')">
|
||||
<ArrowLeft :size="16" class="text-[#606266]" :stroke-width="2" />
|
||||
</el-button>
|
||||
<span
|
||||
class="inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-[#eef4ff] text-[#2563eb]"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<LayoutTemplate :size="18" :stroke-width="2" />
|
||||
</span>
|
||||
<div class="flex min-w-0 flex-col items-start gap-0.5">
|
||||
<div class="text-sm font-semibold leading-5 text-[#18222f]">{{ titleText }}</div>
|
||||
<div class="flex items-center gap-2 whitespace-nowrap text-[11px] text-[#6b7785]">
|
||||
|
||||
@@ -98,22 +98,6 @@
|
||||
@input="updateField('tab_label', $event)"
|
||||
/>
|
||||
</section>
|
||||
|
||||
<section class="space-y-2">
|
||||
<div class="text-sm text-muted-foreground">规格</div>
|
||||
<el-select
|
||||
:value="settings.size || sectionSize"
|
||||
size="small"
|
||||
class="w-full"
|
||||
@change="updateSize"
|
||||
>
|
||||
<el-option value="xsmall" label="特小" />
|
||||
<el-option value="small" label="小" />
|
||||
<el-option value="medium" label="中" />
|
||||
<el-option value="large" label="大" />
|
||||
<el-option value="xlarge" label="特大" />
|
||||
</el-select>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -154,10 +138,6 @@ export default {
|
||||
return this.selectedProducts.map(
|
||||
(id) => snapshotMap.get(id) || { item_id: id, item_name: id }
|
||||
)
|
||||
},
|
||||
sectionSize() {
|
||||
const value = this.section?.settings?.size
|
||||
return ['xsmall', 'small', 'medium', 'large', 'xlarge'].includes(value) ? value : 'medium'
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@@ -173,9 +153,6 @@ export default {
|
||||
product_snapshots: snapshots
|
||||
})
|
||||
},
|
||||
updateSize(value) {
|
||||
this.$emit('change', { size: value, size_override: true })
|
||||
},
|
||||
clearProducts() {
|
||||
this.$emit('change', { product_ids: [], product_snapshots: [] })
|
||||
},
|
||||
|
||||
@@ -367,6 +367,13 @@ export function serializeDsl(dsl) {
|
||||
const nextDsl = cloneValue(dsl)
|
||||
Object.keys(nextDsl.sections || {}).forEach((sectionId) => {
|
||||
const section = nextDsl.sections[sectionId]
|
||||
Object.keys(section.blocks || {}).forEach((blockId) => {
|
||||
const block = section.blocks[blockId]
|
||||
if (block?.type === 'product-tab' && block.settings) {
|
||||
delete block.settings.size
|
||||
delete block.settings.size_override
|
||||
}
|
||||
})
|
||||
section.block_order = cloneValue(section.blockOrder || [])
|
||||
})
|
||||
return nextDsl
|
||||
|
||||
@@ -51,16 +51,8 @@ export function normalizeProductTabBlockSettings(settings = {}) {
|
||||
nextSettings.limit = Number.isFinite(Number(nextSettings.limit))
|
||||
? Math.min(24, Math.max(2, Number(nextSettings.limit)))
|
||||
: 8
|
||||
if (
|
||||
nextSettings.size !== undefined &&
|
||||
!['xsmall', 'small', 'medium', 'large', 'xlarge'].includes(nextSettings.size)
|
||||
) {
|
||||
delete nextSettings.size
|
||||
delete nextSettings.size_override
|
||||
}
|
||||
if (!nextSettings.size_override) {
|
||||
delete nextSettings.size_override
|
||||
}
|
||||
delete nextSettings.size
|
||||
delete nextSettings.size_override
|
||||
if (nextSettings.columns !== undefined) {
|
||||
nextSettings.columns = [2, 3, 4].includes(Number(nextSettings.columns))
|
||||
? Number(nextSettings.columns)
|
||||
|
||||
@@ -17960,6 +17960,8 @@
|
||||
"39e3acc2.45394d": "مشاركة النشاط",
|
||||
"39e3acc2.5925d6": "يظهر عند المشاركة عبر بطاقة البرنامج. مقاس 300*240، png/jpg، 2M كحد أقصى",
|
||||
"39e3acc2.9742f1": "يرجى اختيار صورة النشاط",
|
||||
"39e3acc2.a8c1e2": "ملصق قائمة النشاط",
|
||||
"39e3acc2.b9d3f4": "يرجى رفع ملصق قائمة النشاط",
|
||||
"39e3acc2.98fbb0": "ملصق النشاط",
|
||||
"39e3acc2.818403": "مقترح: عرض 640px، ارتفاع تلقائي",
|
||||
"39e3acc2.90a4b4": "يرجى اختيار ملصق النشاط",
|
||||
@@ -18000,8 +18002,8 @@
|
||||
"39e3acc2.040c4d": "قائمة السلع / التفاصيل",
|
||||
"39e3acc2.c017be": "السلة",
|
||||
"39e3acc2.482b55": "الدفع",
|
||||
"39e3acc2.028f5b": "وصف الخصم",
|
||||
"39e3acc2.8e568f": "عرض وصف الخصم في صفحة الدفع عند التفعيل",
|
||||
"39e3acc2.028f5b": "تذكير الشراء الداخلي",
|
||||
"39e3acc2.8e568f": "عرض تذكير الشراء الداخلي في صفحة الدفع عند التفعيل",
|
||||
"39e3acc2.d0bea4": "تذكير الشراء للموظفين",
|
||||
"39e3acc2.6a03e7": "مواضع العرض: صفحة تفاصيل المنتج، صفحة سلة التسوق، صفحة الدفع",
|
||||
"39e3acc2.592c59": "وقت البداية",
|
||||
@@ -22590,8 +22592,9 @@
|
||||
"223cc8af.d50361": "طلب استلام ذاتي",
|
||||
"223cc8af.e5f71f": "بحث",
|
||||
"223cc8af.e366cc": "تبديل اللغة",
|
||||
"223cc8af.f2d3e5": "",
|
||||
"223cc8af.3b02dd": "",
|
||||
"223cc8af.f2d3e5": "مكتبة حالات Kujiale",
|
||||
"223cc8af.3b02dd": "قائمة جميع المتاجر",
|
||||
"223cc8af.437974": "قائمة المنتجات",
|
||||
"223cc8af.5c34aa": "دعم الفعالية",
|
||||
"223cc8af.94b1e6": "طلبات التعزيز",
|
||||
"223cc8af.1107a8": "انضمام التاجر",
|
||||
|
||||
@@ -17962,6 +17962,8 @@
|
||||
"39e3acc2.45394d": "Share activity",
|
||||
"39e3acc2.5925d6": "Shown when sharing via mini-program card. Recommended 300*240, png/jpg, max 2M",
|
||||
"39e3acc2.9742f1": "Please select activity image",
|
||||
"39e3acc2.a8c1e2": "Activity list poster",
|
||||
"39e3acc2.b9d3f4": "Please upload activity list poster",
|
||||
"39e3acc2.98fbb0": "Activity poster",
|
||||
"39e3acc2.818403": "Recommended: width 640px, height auto",
|
||||
"39e3acc2.90a4b4": "Please select activity poster",
|
||||
@@ -18002,8 +18004,8 @@
|
||||
"39e3acc2.040c4d": "Goods list / detail",
|
||||
"39e3acc2.c017be": "Cart",
|
||||
"39e3acc2.482b55": "Checkout",
|
||||
"39e3acc2.028f5b": "Discount description",
|
||||
"39e3acc2.8e568f": "Show discount description on checkout when enabled",
|
||||
"39e3acc2.028f5b": "Internal purchase reminder",
|
||||
"39e3acc2.8e568f": "Show internal purchase reminder on checkout when enabled",
|
||||
"39e3acc2.d0bea4": "Employee purchase reminder",
|
||||
"39e3acc2.6a03e7": "Display locations: product detail page, shopping cart, checkout page",
|
||||
"39e3acc2.592c59": "Start time",
|
||||
@@ -22591,8 +22593,9 @@
|
||||
"223cc8af.d50361": "Self-pickup order",
|
||||
"223cc8af.e5f71f": "Search",
|
||||
"223cc8af.e366cc": "Switch language",
|
||||
"223cc8af.f2d3e5": "",
|
||||
"223cc8af.3b02dd": "",
|
||||
"223cc8af.f2d3e5": "Kujiale case library",
|
||||
"223cc8af.3b02dd": "All store list",
|
||||
"223cc8af.437974": "Product list",
|
||||
"223cc8af.5c34aa": "Support the event",
|
||||
"223cc8af.94b1e6": "Boost orders",
|
||||
"223cc8af.1107a8": "Merchant entry",
|
||||
|
||||
@@ -18052,6 +18052,8 @@
|
||||
"39e3acc2.45394d": "分享活动",
|
||||
"39e3acc2.5925d6": "员工通过小程序卡片分享活动时展示,建议尺寸300*240,支持 png、jpg 格式,文件大小为 2M 内",
|
||||
"39e3acc2.9742f1": "请选择活动图片",
|
||||
"39e3acc2.a8c1e2": "活动列表海报",
|
||||
"39e3acc2.b9d3f4": "请上传活动列表海报",
|
||||
"39e3acc2.98fbb0": "活动海报",
|
||||
"39e3acc2.818403": "建议尺寸:(宽度640px,高度自适应)",
|
||||
"39e3acc2.90a4b4": "请选择活动海报",
|
||||
@@ -18092,8 +18094,8 @@
|
||||
"39e3acc2.040c4d": "商品列表/商详页面",
|
||||
"39e3acc2.c017be": "购物车",
|
||||
"39e3acc2.482b55": "结算页",
|
||||
"39e3acc2.028f5b": "优惠说明",
|
||||
"39e3acc2.8e568f": "开启优惠说明展示在结算页,关闭不展示",
|
||||
"39e3acc2.028f5b": "内购提醒",
|
||||
"39e3acc2.8e568f": "开启内购提醒展示在结算页,关闭不展示",
|
||||
"39e3acc2.d0bea4": "内购提醒",
|
||||
"39e3acc2.6a03e7": "显示位置:商品详情页、购物车页面、结算页",
|
||||
"39e3acc2.592c59": "开始时间",
|
||||
@@ -22593,6 +22595,7 @@
|
||||
"223cc8af.e366cc": "切换语言",
|
||||
"223cc8af.f2d3e5": "酷家乐案例库",
|
||||
"223cc8af.3b02dd": "所有门店列表",
|
||||
"223cc8af.437974": "商品列表",
|
||||
"223cc8af.5c34aa": "助力活动",
|
||||
"223cc8af.94b1e6": "助力订单",
|
||||
"223cc8af.1107a8": "商家入驻",
|
||||
|
||||
@@ -438,6 +438,17 @@ const routes = [
|
||||
permissions: ['applications.kujiale.kujiale-products']
|
||||
},
|
||||
component: () => import('@/views/applications/kujiale/list')
|
||||
},
|
||||
{
|
||||
name: 'appcenter',
|
||||
path: 'shopex/appcenter',
|
||||
meta: {
|
||||
aliasName: 'shopex-appcenter',
|
||||
icon: 'icon-products',
|
||||
title: '商派应用中心',
|
||||
permissions: ['applications.shopex-appcenter']
|
||||
},
|
||||
component: () => import('@/views/applications/application-center/shopex-appcenter')
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -405,6 +405,11 @@ export default {
|
||||
path: 'community/chiefupload',
|
||||
name: '5286ac37.5ad881',
|
||||
component: () => import('@/view/member/members/upload_chief')
|
||||
},
|
||||
{
|
||||
path: 'shopex/appcenter',
|
||||
name: '商派用户中心',
|
||||
component: () => import('@/views/applications/application-center/shopex-appcenter')
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -360,9 +360,11 @@ export default {
|
||||
findWidgetForPersistedName(persistedName) {
|
||||
const key = String(persistedName || '').toLowerCase()
|
||||
if (!key || !this.widgets.length) return null
|
||||
let w = this.widgets.find((item) => (item.name || '').toLowerCase() === key)
|
||||
// 附近商家已合并到店铺挂件,历史数据 name 仍为 nearbyShop
|
||||
const lookupKey = key === 'nearbyshop' ? 'shop' : key
|
||||
let w = this.widgets.find((item) => (item.name || '').toLowerCase() === lookupKey)
|
||||
if (w) return w
|
||||
w = this.widgets.find((item) => String(item.config?.name || '').toLowerCase() === key)
|
||||
w = this.widgets.find((item) => String(item.config?.name || '').toLowerCase() === lookupKey)
|
||||
if (w) return w
|
||||
if (String(this.localScene) === '1005' && key === 'goods') {
|
||||
return (
|
||||
|
||||
@@ -9,7 +9,6 @@ import WgtFilm from './wgt_film'
|
||||
import WgtCoupon from './wgt_coupon'
|
||||
import WgtShop from './wgt_shop'
|
||||
import WgtMarquees from './wgt_marquees'
|
||||
import WgtNearbyShop from './wgt_nearbyShop'
|
||||
import WgtGoodsCard from './wgt_goodsCard'
|
||||
import WgtWriting from './wgt_writing'
|
||||
import WgtHeading from './wgt_heading'
|
||||
|
||||
@@ -3,6 +3,60 @@ import { i18n } from '@/i18n'
|
||||
import AttrStore from './attr-store'
|
||||
import { transformInBase, createTransformOutBase } from '../../comps/transform-utils'
|
||||
|
||||
const NEARBY_SETTING_KEYS = [
|
||||
'title',
|
||||
'subtitle',
|
||||
'padded',
|
||||
'show_nearby_merchants',
|
||||
'merchantsNumber',
|
||||
'quantityNumber'
|
||||
]
|
||||
|
||||
const SHARED_BASE_KEYS = [
|
||||
'dataType',
|
||||
'outerMargin',
|
||||
'innerPadding',
|
||||
'outerBackground',
|
||||
'innerBackground',
|
||||
'wgtCustName',
|
||||
'track',
|
||||
...NEARBY_SETTING_KEYS
|
||||
]
|
||||
|
||||
function isNearbyDataType(v, raw = {}) {
|
||||
if (raw.name === 'nearbyShop') return true
|
||||
const base = raw.base || {}
|
||||
return (base.dataType || v.dataType) === 'nearby'
|
||||
}
|
||||
|
||||
function buildNearbySetting() {
|
||||
return [
|
||||
{ label: i18n.t('9b7fb994.4707ba'), key: 'padded', component: 'switch', value: false },
|
||||
{
|
||||
label: i18n.t('9b7fb994.f417a5'),
|
||||
key: 'show_nearby_merchants',
|
||||
component: 'switch',
|
||||
value: false
|
||||
},
|
||||
{
|
||||
label: i18n.t('9b7fb994.35f408'),
|
||||
key: 'merchantsNumber',
|
||||
component: 'number',
|
||||
value: 4,
|
||||
min: 1,
|
||||
max: 100
|
||||
},
|
||||
{
|
||||
label: i18n.t('9b7fb994.81756c'),
|
||||
key: 'quantityNumber',
|
||||
component: 'number',
|
||||
value: 4,
|
||||
min: 1,
|
||||
max: 100
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
const config = {
|
||||
name: 'shop',
|
||||
setting: [
|
||||
@@ -22,13 +76,17 @@ const config = {
|
||||
label: i18n.t('ca99873f.185f7b'),
|
||||
key: 'dataType',
|
||||
component: 'select',
|
||||
options: [{ label: i18n.t('ca99873f.fcf7d8'), value: 'specify' }],
|
||||
options: [
|
||||
{ label: i18n.t('ca99873f.fcf7d8'), value: 'specify' },
|
||||
{ label: i18n.t('5e1ae7f2.0c0d95'), value: 'nearby' }
|
||||
],
|
||||
value: 'specify',
|
||||
onchange: function (e, vm) {
|
||||
vm.value.data = []
|
||||
if (e === 'nearby') {
|
||||
vm.value.data = []
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
label: i18n.t('ca99873f.e7af71'),
|
||||
key: 'data',
|
||||
@@ -38,117 +96,86 @@ const config = {
|
||||
v-model={this.value[key]}
|
||||
on-change={() => {
|
||||
if (this.value[key].id === '') {
|
||||
this.value['items'] = []
|
||||
this.value['tags'] = []
|
||||
this.value.items = []
|
||||
this.value.tags = []
|
||||
}
|
||||
}}
|
||||
/>
|
||||
)
|
||||
},
|
||||
value: [],
|
||||
isShow: function () {
|
||||
isShow() {
|
||||
return this.value.dataType === 'specify'
|
||||
}
|
||||
}
|
||||
// {
|
||||
// label: '组件外边距',
|
||||
// key: 'outerMargin',
|
||||
// component: function (h, { key }) {
|
||||
// return (
|
||||
// <CompStyle
|
||||
// showBgsetting={false}
|
||||
// v-model={this.value[key]}
|
||||
// uuid={this.value.uuid}
|
||||
// showLabel={false}
|
||||
// showLeft={false}
|
||||
// showRight={false}
|
||||
// />
|
||||
// )
|
||||
// },
|
||||
// value: {
|
||||
// paddedt: 10,
|
||||
// paddedb: 10
|
||||
// }
|
||||
// },
|
||||
// {
|
||||
// label: '组件内边距',
|
||||
// key: 'innerPadding',
|
||||
// component: function (h, { key }) {
|
||||
// return (
|
||||
// <CompStyle
|
||||
// showBgsetting={false}
|
||||
// v-model={this.value[key]}
|
||||
// uuid={this.value.uuid}
|
||||
// showLabel={false}
|
||||
// />
|
||||
// )
|
||||
// },
|
||||
// value: {
|
||||
// paddedt: 10,
|
||||
// paddedb: 10,
|
||||
// paddedl: 10,
|
||||
// paddedr: 10
|
||||
// }
|
||||
// },
|
||||
// {
|
||||
// label: '组件外背景',
|
||||
// key: 'outerBackground',
|
||||
// component: function (h, { key }) {
|
||||
// return <CompOuter v-model={this.value[key]} uuid={this.value.uuid} />
|
||||
// },
|
||||
// value: { color: '#f8f8f8', image: '' }
|
||||
// },
|
||||
// {
|
||||
// label: '组件内背景',
|
||||
// key: 'innerBackground',
|
||||
// component: function (h, { key }) {
|
||||
// return <CompInner v-model={this.value[key]} uuid={this.value.uuid} />
|
||||
// },
|
||||
// value: { type: 'solid', color: '#ffffff', startColor: '#ffffff', endColor: '#ffffff' }
|
||||
// }
|
||||
},
|
||||
...buildNearbySetting().map((item) => ({
|
||||
...item,
|
||||
isShow() {
|
||||
return this.value.dataType === 'nearby'
|
||||
}
|
||||
}))
|
||||
],
|
||||
transformIn: (v) => {
|
||||
const { name, base, data, meber_tags = [], no_meber_tags = [], tagsType } = v
|
||||
// 使用公共函数处理 base 中的样式数据转换
|
||||
const nearby = isNearbyDataType(v, v)
|
||||
const base = v.base || {}
|
||||
const transformedBase = transformInBase(base, ['outerMargin', 'innerPadding'])
|
||||
return {
|
||||
const tags = {
|
||||
type: v.tagsType || '2',
|
||||
meber_tags: v.meber_tags || [],
|
||||
no_meber_tags: v.no_meber_tags || []
|
||||
}
|
||||
const common = {
|
||||
id: v?.id,
|
||||
name,
|
||||
name: 'shop',
|
||||
dataType: nearby ? 'nearby' : base.dataType || 'specify',
|
||||
...transformedBase,
|
||||
data: data,
|
||||
tags: {
|
||||
type: tagsType || '2',
|
||||
meber_tags: meber_tags || [],
|
||||
no_meber_tags: no_meber_tags || []
|
||||
wgtCustName: base.wgtCustName ?? '',
|
||||
track: v.track ?? base.track ?? '',
|
||||
tags
|
||||
}
|
||||
if (nearby) {
|
||||
return {
|
||||
...common,
|
||||
data: [],
|
||||
title: base.title ?? '',
|
||||
subtitle: base.subtitle ?? '',
|
||||
padded: base.padded ?? false,
|
||||
show_nearby_merchants: base.show_nearby_merchants ?? false,
|
||||
merchantsNumber: base.merchantsNumber ?? 4,
|
||||
quantityNumber: base.quantityNumber ?? 4
|
||||
}
|
||||
}
|
||||
return {
|
||||
...common,
|
||||
data: v.data || [],
|
||||
padded: false,
|
||||
show_nearby_merchants: false,
|
||||
merchantsNumber: 4,
|
||||
quantityNumber: 4,
|
||||
title: '',
|
||||
subtitle: ''
|
||||
}
|
||||
},
|
||||
transformOut: (v, wgtList, regionauth_id) => {
|
||||
return pickBy(v, {
|
||||
const nearby = v.dataType === 'nearby'
|
||||
const baseKeys = nearby
|
||||
? SHARED_BASE_KEYS
|
||||
: SHARED_BASE_KEYS.filter((k) => !NEARBY_SETTING_KEYS.includes(k))
|
||||
const out = {
|
||||
id: 'id',
|
||||
name: 'name',
|
||||
base: (v) => {
|
||||
// 使用公共函数处理 outerMargin 和 innerPadding 转换,同时保留其他字段
|
||||
const baseData = createTransformOutBase(
|
||||
[
|
||||
'dataType',
|
||||
'outerMargin',
|
||||
'innerPadding',
|
||||
'outerBackground',
|
||||
'innerBackground',
|
||||
'wgtCustName',
|
||||
'track'
|
||||
],
|
||||
['outerMargin', 'innerPadding']
|
||||
)(v)
|
||||
return baseData
|
||||
},
|
||||
data: 'data',
|
||||
name: () => 'shop',
|
||||
base: createTransformOutBase(baseKeys, ['outerMargin', 'innerPadding']),
|
||||
meber_tags: 'tags.meber_tags',
|
||||
no_meber_tags: 'tags.no_meber_tags',
|
||||
tagsType: 'tags.type',
|
||||
noRegionauth: !regionauth_id
|
||||
})
|
||||
}
|
||||
if (nearby) {
|
||||
out.data = () => []
|
||||
} else {
|
||||
out.data = 'data'
|
||||
}
|
||||
return pickBy(v, out)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,21 +4,21 @@
|
||||
<div
|
||||
:class="[
|
||||
'wgt-shop-container-list',
|
||||
{ 'wgt-shop-container-list-single': value.data.length == 1 }
|
||||
{ 'wgt-shop-container-list-single': displayShops.length == 1 }
|
||||
]"
|
||||
>
|
||||
<div
|
||||
v-for="(item, index) in value.data"
|
||||
:key="index"
|
||||
v-for="(shop, index) in displayShops"
|
||||
:key="shopRowKey(shop, index)"
|
||||
class="wgt-shop-item"
|
||||
:style="innerStyle"
|
||||
>
|
||||
<div class="shop-header">
|
||||
<div class="shop-info">
|
||||
<div class="shop-logo">
|
||||
<img :src="value.distributor?.logo || defaultShopLogo" alt="店铺logo" />
|
||||
<img :src="shopLogo(shop)" alt="店铺logo" />
|
||||
</div>
|
||||
<div class="shop-name">{{ item?.name || 'ADIDAS' }}</div>
|
||||
<div class="shop-name">{{ shopName(shop) }}</div>
|
||||
</div>
|
||||
<div class="shop-actions">
|
||||
<div class="favorite-btn">
|
||||
@@ -28,19 +28,23 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="shop-products">
|
||||
<div v-for="(item, index) in distributorData" :key="index" class="product-item">
|
||||
<div
|
||||
v-for="(product, pIndex) in productsForShop(shop)"
|
||||
:key="`${index}-${pIndex}`"
|
||||
class="product-item"
|
||||
>
|
||||
<div class="product-image">
|
||||
<el-image
|
||||
:src="item?.pics && item?.pics.length > 0 ? item?.pics[0] : ''"
|
||||
:src="productImage(product)"
|
||||
alt="商品图片"
|
||||
>
|
||||
<div slot="error" class="image-slot" />
|
||||
</el-image>
|
||||
</div>
|
||||
<div class="product-title">{{ item?.item_name || i18n.t('1d819fcf.1fd1d5') }}</div>
|
||||
<div class="product-title">{{ product?.item_name || i18n.t('1d819fcf.1fd1d5') }}</div>
|
||||
<div class="product-tags">
|
||||
<span
|
||||
v-for="(tag, tagIndex) in item?.tags || ['4折', '活动标']"
|
||||
v-for="(tag, tagIndex) in productTags(product)"
|
||||
:key="tagIndex"
|
||||
class="tag"
|
||||
:class="'tag-' + tagIndex"
|
||||
@@ -49,8 +53,8 @@
|
||||
</div>
|
||||
<div class="product-price">
|
||||
<span class="current-price-symbol">¥</span>
|
||||
<span class="current-price">{{ item?.price / 100 }}</span>
|
||||
<span class="original-price">{{ item?.market_price / 100 }}</span>
|
||||
<span class="current-price">{{ (product?.price || 0) / 100 }}</span>
|
||||
<span class="original-price">{{ (product?.market_price || 0) / 100 }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -63,7 +67,23 @@
|
||||
import { i18n } from '@/i18n'
|
||||
import config from './config'
|
||||
import { getOuterStyle, getInnerStyle } from '../../comps/style-utils'
|
||||
|
||||
const defaultShopLogo = require('@/assets/imgs/decorate/default-shop-logo.png')
|
||||
|
||||
const NEARBY_PLACEHOLDER_PRODUCT = {
|
||||
item_name: '',
|
||||
price: 19900,
|
||||
market_price: 29900,
|
||||
pics: [],
|
||||
tags: ['4折', '活动标']
|
||||
}
|
||||
|
||||
function clampCount(n, fallback = 4, max = 100) {
|
||||
const num = Number(n)
|
||||
if (!Number.isFinite(num) || num < 1) return fallback
|
||||
return Math.min(Math.floor(num), max)
|
||||
}
|
||||
|
||||
export default {
|
||||
name: 'Shop',
|
||||
wgtName: i18n.t('1d819fcf.295713'),
|
||||
@@ -75,9 +95,32 @@ export default {
|
||||
value: [Object, Array]
|
||||
},
|
||||
data() {
|
||||
return { i18n, currentIndex: 1, defaultShopLogo, distributorData: null }
|
||||
return {
|
||||
i18n,
|
||||
defaultShopLogo,
|
||||
distributorData: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isNearbyType() {
|
||||
return this.value?.dataType === 'nearby'
|
||||
},
|
||||
nearbyMerchantsCount() {
|
||||
return clampCount(this.value?.merchantsNumber)
|
||||
},
|
||||
nearbyProductsCount() {
|
||||
return clampCount(this.value?.quantityNumber)
|
||||
},
|
||||
displayShops() {
|
||||
if (this.isNearbyType) {
|
||||
return Array.from({ length: this.nearbyMerchantsCount }, (_, index) => ({
|
||||
_placeholder: true,
|
||||
distributor_id: `nearby-placeholder-${index}`,
|
||||
name: i18n.t('5e1ae7f2.0c0d95')
|
||||
}))
|
||||
}
|
||||
return this.value?.data || []
|
||||
},
|
||||
outerStyle() {
|
||||
return getOuterStyle(this.value)
|
||||
},
|
||||
@@ -86,32 +129,61 @@ export default {
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value: {
|
||||
handler(newVal) {},
|
||||
immediate: true,
|
||||
deep: true
|
||||
},
|
||||
'value.data': {
|
||||
handler(newVal) {
|
||||
if (newVal.length > 0) {
|
||||
this.getList()
|
||||
if (!this.isNearbyType && newVal && newVal.length > 0) {
|
||||
this.loadSpecifyGoods()
|
||||
} else if (!this.isNearbyType) {
|
||||
this.distributorData = []
|
||||
}
|
||||
},
|
||||
immediate: true,
|
||||
deep: true
|
||||
},
|
||||
'value.dataType'() {
|
||||
if (!this.isNearbyType) {
|
||||
this.loadSpecifyGoods()
|
||||
} else {
|
||||
this.distributorData = []
|
||||
}
|
||||
}
|
||||
},
|
||||
created() {},
|
||||
methods: {
|
||||
async getList() {
|
||||
const query = {
|
||||
data_type: 'distributor',
|
||||
data_value: this.value?.data[0]?.distributor_id
|
||||
shopRowKey(shop, index) {
|
||||
return shop.distributor_id || shop.id || `shop-${index}`
|
||||
},
|
||||
shopLogo(shop) {
|
||||
return shop.logo || this.defaultShopLogo
|
||||
},
|
||||
shopName(shop) {
|
||||
return shop.name || shop.distributor_name || 'ADIDAS'
|
||||
},
|
||||
productsForShop(shop) {
|
||||
if (this.isNearbyType) {
|
||||
return Array.from({ length: this.nearbyProductsCount }, () => ({
|
||||
...NEARBY_PLACEHOLDER_PRODUCT,
|
||||
item_name: i18n.t('1d819fcf.1fd1d5')
|
||||
}))
|
||||
}
|
||||
console.log(this.value?.data, 'getSeckdistributorilldata')
|
||||
const res = await this.$api.template.getShelvesGoods(query)
|
||||
console.log(res, 'getSeckdistributorilldata')
|
||||
this.distributorData = res
|
||||
return this.distributorData || []
|
||||
},
|
||||
productImage(product) {
|
||||
return product?.pics && product.pics.length > 0 ? product.pics[0] : ''
|
||||
},
|
||||
productTags(product) {
|
||||
return product?.tags || ['4折', '活动标']
|
||||
},
|
||||
async loadSpecifyGoods() {
|
||||
const first = this.value?.data?.[0]
|
||||
if (!first?.distributor_id) {
|
||||
this.distributorData = []
|
||||
return
|
||||
}
|
||||
const res = await this.$api.template.getShelvesGoods({
|
||||
data_type: 'distributor',
|
||||
data_value: first.distributor_id
|
||||
})
|
||||
this.distributorData = res || []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,6 +187,8 @@
|
||||
<el-form-item :label="$t('4d1aec94.53c3dd')">
|
||||
<el-switch
|
||||
v-model="aftersalesRemindForm.is_open"
|
||||
active-value="true"
|
||||
inactive-value="false"
|
||||
active-color="#13ce66"
|
||||
inactive-color="#ff4949"
|
||||
/>
|
||||
@@ -282,7 +284,7 @@ export default {
|
||||
],
|
||||
aftersalesRemindForm: {
|
||||
intro: '',
|
||||
is_open: false
|
||||
is_open: 'false'
|
||||
},
|
||||
aftersalesRemindVisible: false,
|
||||
aftersalesRemindTitle: i18n.t('4d1aec94.117b5a'),
|
||||
@@ -816,11 +818,17 @@ export default {
|
||||
})
|
||||
}
|
||||
},
|
||||
normalizeAftersalesRemindIsOpen(value) {
|
||||
return value === 'true' || value === true || value === 1 || value === '1' ? 'true' : 'false'
|
||||
},
|
||||
async aftersalesRemindAction() {
|
||||
// 请求提醒数据
|
||||
const data = await this.$api.aftersales.getAftersalesRemind()
|
||||
if (data) {
|
||||
this.aftersalesRemindForm = data
|
||||
this.aftersalesRemindForm = {
|
||||
intro: data.intro || '',
|
||||
is_open: this.normalizeAftersalesRemindIsOpen(data.is_open)
|
||||
}
|
||||
}
|
||||
this.aftersalesRemindVisible = true
|
||||
},
|
||||
@@ -830,12 +838,12 @@ export default {
|
||||
handleCancel() {
|
||||
this.aftersalesRemindVisible = false
|
||||
this.aftersalesRemindForm.intro = ''
|
||||
this.aftersalesRemindForm.is_open = false
|
||||
this.aftersalesRemindForm.is_open = 'false'
|
||||
},
|
||||
async submitAftersalesRemind() {
|
||||
let params = {
|
||||
intro: this.aftersalesRemindForm.intro,
|
||||
is_open: this.aftersalesRemindForm.is_open
|
||||
is_open: this.normalizeAftersalesRemindIsOpen(this.aftersalesRemindForm.is_open)
|
||||
}
|
||||
await this.$api.aftersales.setAftersalesRemind(params)
|
||||
this.$message({
|
||||
@@ -843,6 +851,9 @@ export default {
|
||||
message: this.$t('4d1aec94.3b1083')
|
||||
})
|
||||
this.aftersalesRemindVisible = false
|
||||
this.$nextTick(() => {
|
||||
this.$refs.finder?.refresh()
|
||||
})
|
||||
},
|
||||
handleSelectionChange(val) {
|
||||
console.log('handleSelectionChange', val)
|
||||
|
||||
@@ -346,6 +346,7 @@ export default {
|
||||
title: '',
|
||||
linkHome: null,
|
||||
share_pic: '',
|
||||
list_pic: '',
|
||||
pic: ''
|
||||
},
|
||||
formBaseList: [],
|
||||
@@ -506,6 +507,19 @@ export default {
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
label: t('39e3acc2.a8c1e2'),
|
||||
key: 'list_pic',
|
||||
component: () => <SpImagePicker v-model={self.formBase.list_pic} />,
|
||||
tip: t('39e3acc2.818403'),
|
||||
validator: (rule, value, callback) => {
|
||||
if (isEmpty(self.formBase.list_pic)) {
|
||||
callback(new Error(t('39e3acc2.b9d3f4')))
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
label: t('39e3acc2.98fbb0'),
|
||||
key: 'pic',
|
||||
@@ -1091,6 +1105,7 @@ export default {
|
||||
title: res.title,
|
||||
linkHome,
|
||||
share_pic: res.share_pic,
|
||||
list_pic: res.list_pic || res.pic || '',
|
||||
pic: res.pic
|
||||
}
|
||||
|
||||
@@ -1158,11 +1173,31 @@ export default {
|
||||
enterprise_id: res.enterprise_id
|
||||
})
|
||||
|
||||
// res.price_display_config = {"cart_page": {"sale_price": "true", "market_price": "false", "activity_price": "false"}, "items_page": {"sale_price": "true", "market_price": "true", "activity_price": "false"}, "checkout_page": {"sale_price": "true", "market_price": "false", "activity_price": "false"}, "order_detail_page": {"sale_price": "true", "market_price": "false", "activity_price": "true"}}
|
||||
//价格展示处理
|
||||
const priceData = this.priceShowData(res.price_display_config, 'detail')
|
||||
|
||||
console.log('priceData', priceData)
|
||||
const phraseMap = {}
|
||||
;(res.passphrase_enterprises || []).forEach((pe) => {
|
||||
const eid = pe.enterprise_id
|
||||
phraseMap[eid] = {
|
||||
participate_quota: pe.participate_quota,
|
||||
passphrase_code: pe.passphrase_code || '',
|
||||
passphrase_limitfee:
|
||||
pe.passphrase_limitfee != null && pe.passphrase_limitfee !== ''
|
||||
? Number(pe.passphrase_limitfee) / 100
|
||||
: ''
|
||||
}
|
||||
})
|
||||
const passphraseRows = list.map((c) => {
|
||||
const pm = phraseMap[c.id]
|
||||
return {
|
||||
enterprise_id: c.id,
|
||||
name: c.name,
|
||||
enterprise_sn: c.enterprise_sn || '',
|
||||
participate_quota: pm ? pm.participate_quota : '',
|
||||
passphrase_code: pm ? pm.passphrase_code : '',
|
||||
passphrase_limitfee: pm ? pm.passphrase_limitfee : ''
|
||||
}
|
||||
})
|
||||
|
||||
const phraseMap = {}
|
||||
;(res.passphrase_enterprises || []).forEach((pe) => {
|
||||
@@ -1383,33 +1418,48 @@ export default {
|
||||
this.passphraseBatchCodeGenerating = false
|
||||
}
|
||||
},
|
||||
priceShowData(form, isDetail) {
|
||||
//接口需要
|
||||
// cart_page: {sale_price: "true", market_price: "false", activity_price: "false"},
|
||||
// items_page: {sale_price: "true", market_price: "false", activity_price: "false"},
|
||||
// checkout_page: {sale_price: "true", market_price: "false", activity_price: "false"},
|
||||
// order_detail_page: {sale_price: "true", market_price: "false", activity_price: "false"}
|
||||
|
||||
let keys = ['items_page', 'cart_page', 'order_detail_page', 'checkout_page']
|
||||
let prices = ['sale_price', 'market_price', 'activity_price']
|
||||
if (isDetail) {
|
||||
//编辑获取详情数据处理
|
||||
return keys.reduce((prev, cur) => {
|
||||
let _arr = []
|
||||
prices.forEach((item) => {
|
||||
_arr = Object.keys(form[cur]).filter((item2) => form[cur][item2] == 'true')
|
||||
console.log(Object.keys(form[cur]))
|
||||
})
|
||||
prev[cur] = _arr
|
||||
return prev
|
||||
}, {})
|
||||
normalizePriceDisplayConfig(raw) {
|
||||
const defaultChecked = ['sale_price', 'activity_price']
|
||||
const pageKeys = ['items_page', 'cart_page', 'order_detail_page', 'checkout_page']
|
||||
const priceKeys = ['sale_price', 'market_price', 'activity_price']
|
||||
let config = raw
|
||||
if (config == null || config === '') {
|
||||
config = {}
|
||||
} else if (typeof config === 'string') {
|
||||
try {
|
||||
config = JSON.parse(config)
|
||||
} catch (e) {
|
||||
config = {}
|
||||
}
|
||||
}
|
||||
return keys.reduce((prev, cur) => {
|
||||
let _obj = {}
|
||||
prices.forEach((item) => {
|
||||
_obj[item] = form[cur].includes(item) + ''
|
||||
})
|
||||
prev[cur] = _obj
|
||||
if (typeof config !== 'object') {
|
||||
config = {}
|
||||
}
|
||||
return pageKeys.reduce((prev, pageKey) => {
|
||||
const pageConfig = config[pageKey]
|
||||
if (pageConfig && typeof pageConfig === 'object' && !Array.isArray(pageConfig)) {
|
||||
prev[pageKey] = priceKeys.filter((k) => pageConfig[k] === 'true' || pageConfig[k] === true)
|
||||
} else if (Array.isArray(pageConfig)) {
|
||||
prev[pageKey] = pageConfig
|
||||
} else {
|
||||
prev[pageKey] = defaultChecked.slice()
|
||||
}
|
||||
return prev
|
||||
}, {})
|
||||
},
|
||||
priceShowData(form, isDetail) {
|
||||
const pageKeys = ['items_page', 'cart_page', 'order_detail_page', 'checkout_page']
|
||||
const priceKeys = ['sale_price', 'market_price', 'activity_price']
|
||||
if (isDetail) {
|
||||
return this.normalizePriceDisplayConfig(form)
|
||||
}
|
||||
const normalized = this.normalizePriceDisplayConfig(form)
|
||||
return pageKeys.reduce((prev, cur) => {
|
||||
const checked = normalized[cur] || []
|
||||
prev[cur] = priceKeys.reduce((obj, item) => {
|
||||
obj[item] = String(checked.includes(item))
|
||||
return obj
|
||||
}, {})
|
||||
return prev
|
||||
}, {})
|
||||
},
|
||||
@@ -1421,6 +1471,7 @@ export default {
|
||||
title,
|
||||
linkHome: { pages_template_id },
|
||||
share_pic,
|
||||
list_pic,
|
||||
pic
|
||||
} = this.formBase
|
||||
const {
|
||||
@@ -1458,6 +1509,7 @@ export default {
|
||||
title,
|
||||
pages_template_id,
|
||||
share_pic: share_pic,
|
||||
list_pic: list_pic,
|
||||
pic: pic,
|
||||
enterprise_id: companyList.map((item) => item.id),
|
||||
display_time: preheatMoment.unix(),
|
||||
|
||||
@@ -138,12 +138,15 @@
|
||||
<span class="btn" @click="copyTemplate(item.pages_template_id)">{{
|
||||
$t('a066f499.79d3ab')
|
||||
}}</span>
|
||||
<!-- ECX-8712: 总部/店铺模版装修隐藏导航配置 -->
|
||||
<!--
|
||||
<span
|
||||
v-if="!isDistributorTemplate"
|
||||
class="btn"
|
||||
@click="handleClickNav(item.pages_template_id)"
|
||||
>{{ $t('a066f499.056f2d') }}</span
|
||||
>
|
||||
-->
|
||||
<span class="btn" @click="abandonTemplate(item.pages_template_id)">{{
|
||||
$t('a066f499.0044f6')
|
||||
}}</span>
|
||||
|
||||
546
src/views/applications/application-center/shopex-appcenter.vue
Normal file
546
src/views/applications/application-center/shopex-appcenter.vue
Normal file
@@ -0,0 +1,546 @@
|
||||
<!--
|
||||
Copyright © ShopeX (http://www.shopex.cn). All rights reserved.
|
||||
See LICENSE file for license details.
|
||||
-->
|
||||
|
||||
<template>
|
||||
<SpPage
|
||||
v-loading="loading && viewMode !== 'iframe'"
|
||||
class="user-center-page"
|
||||
:no-sticky="true"
|
||||
>
|
||||
<div v-if="viewMode === 'goods'" v-loading="loading" class="appcenter-embed">
|
||||
<div class="appcenter-workspace">
|
||||
<div class="appcenter-tabs appcenter-tabs--no-user">
|
||||
<div class="appcenter-tabs-main">
|
||||
<button type="button" class="appcenter-tab active">应用市场</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="appcenter-tab-panel active">
|
||||
<div
|
||||
v-if="!loading && goodsList.length === 0"
|
||||
class="appcenter-empty"
|
||||
>
|
||||
{{ pageInfo.empty_text || '暂无可展示应用' }}
|
||||
</div>
|
||||
<div v-else class="appcenter-items appcenter-layout-grid">
|
||||
<div
|
||||
v-for="item in goodsList"
|
||||
:key="item.goods_bn"
|
||||
class="appcenter-card"
|
||||
:data-goods-bn="item.goods_bn"
|
||||
>
|
||||
<div class="appcenter-card-main">
|
||||
<h2>{{ item.display_name || item.goods?.name }}</h2>
|
||||
<p>{{ item.goods_bn }}</p>
|
||||
<div class="appcenter-meta">
|
||||
<span>商品 BN:{{ item.goods?.bn || item.goods_bn }}</span>
|
||||
<span>价格:¥{{ formatPrice(item.goods?.price) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<form
|
||||
class="appcenter-buy-form"
|
||||
@submit.prevent="handleAppClick(item)"
|
||||
>
|
||||
<button
|
||||
type="submit"
|
||||
class="appcenter-action"
|
||||
:disabled="openingBn === item.goods_bn"
|
||||
data-appcenter-buy="1"
|
||||
>
|
||||
{{ openingBn === item.goods_bn ? '处理中...' : '立即购买' }}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-else class="usercenter-iframe-wrap">
|
||||
<iframe
|
||||
v-if="iframeUrl"
|
||||
:key="iframeUrl"
|
||||
:src="iframeUrl"
|
||||
class="usercenter-iframe"
|
||||
frameborder="0"
|
||||
scrolling="auto"
|
||||
title="应用中心"
|
||||
/>
|
||||
<div v-else v-loading="loading" class="usercenter-iframe-placeholder" />
|
||||
</div>
|
||||
|
||||
<el-dialog
|
||||
title="用户中心授权"
|
||||
:visible.sync="authDialogVisible"
|
||||
width="480px"
|
||||
top="12vh"
|
||||
append-to-body
|
||||
destroy-on-close
|
||||
custom-class="usercenter-auth-dialog"
|
||||
@closed="handleAuthDialogClosed"
|
||||
>
|
||||
<iframe
|
||||
v-if="authIframeUrl"
|
||||
ref="authIframe"
|
||||
:key="authIframeUrl"
|
||||
:src="authIframeUrl"
|
||||
class="usercenter-auth-iframe"
|
||||
frameborder="0"
|
||||
scrolling="auto"
|
||||
title="用户中心授权"
|
||||
@load="onAuthIframeLoad"
|
||||
/>
|
||||
</el-dialog>
|
||||
</SpPage>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
getAppcenterUrl,
|
||||
getUsercenterAuthorizeUrl,
|
||||
getAppcenterGoods,
|
||||
getCertificate,
|
||||
loginUsercenter
|
||||
} from '@/api/company'
|
||||
import { setUsercenterLoginSuccess } from '@/utils/usercenter-storage'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
openingBn: '',
|
||||
pageInfo: {},
|
||||
goodsList: [],
|
||||
channel: 'ecshopx',
|
||||
viewMode: 'goods',
|
||||
iframeUrl: '',
|
||||
authDialogVisible: false,
|
||||
authIframeUrl: '',
|
||||
authRedirecting: false,
|
||||
codeLoginPromise: null
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.initPage()
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.codeLoginPromise = null
|
||||
},
|
||||
methods: {
|
||||
async initPage() {
|
||||
const code = (this.$route.query.code || '').trim()
|
||||
if (code) {
|
||||
// 授权回调会先落在弹窗 iframe 内,避免在 iframe 中重复换票
|
||||
if (window.self !== window.top) {
|
||||
return
|
||||
}
|
||||
|
||||
if (this.codeLoginPromise) {
|
||||
await this.codeLoginPromise
|
||||
return
|
||||
}
|
||||
|
||||
this.codeLoginPromise = this.handleOAuthCallback(code)
|
||||
try {
|
||||
await this.codeLoginPromise
|
||||
} finally {
|
||||
this.codeLoginPromise = null
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if (await this.hasAppcenterCertificate()) {
|
||||
await this.openAppcenterIframe()
|
||||
return
|
||||
}
|
||||
|
||||
await this.bootstrapGoodsView()
|
||||
},
|
||||
async handleOAuthCallback(code) {
|
||||
const ok = await this.exchangeCodeAndLogin(code)
|
||||
if (ok) {
|
||||
await this.openAppcenterIframe()
|
||||
} else {
|
||||
await this.bootstrapGoodsView()
|
||||
}
|
||||
},
|
||||
async hasAppcenterCertificate() {
|
||||
try {
|
||||
const response = await getCertificate()
|
||||
const data = response?.data?.data || {}
|
||||
const nodeId = String(data.node_id || '').trim()
|
||||
const shopexUid = String(data.shopex_uid || '').trim()
|
||||
return !!(nodeId && shopexUid)
|
||||
} catch (error) {
|
||||
return false
|
||||
}
|
||||
},
|
||||
async bootstrapGoodsView() {
|
||||
this.viewMode = 'goods'
|
||||
this.iframeUrl = ''
|
||||
this.authDialogVisible = false
|
||||
this.authIframeUrl = ''
|
||||
await this.loadGoods()
|
||||
},
|
||||
async exchangeCodeAndLogin(code) {
|
||||
this.loading = true
|
||||
try {
|
||||
await loginUsercenter({ code })
|
||||
setUsercenterLoginSuccess()
|
||||
await this.$router.replace({ path: this.$route.path, query: {} })
|
||||
this.$message.success('授权登录成功')
|
||||
return true
|
||||
} catch (error) {
|
||||
this.$message.error(this.resolveErrorMessage(error))
|
||||
await this.$router.replace({ path: this.$route.path, query: {} })
|
||||
return false
|
||||
} finally {
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
async openAppcenterIframe() {
|
||||
this.authDialogVisible = false
|
||||
this.authIframeUrl = ''
|
||||
this.viewMode = 'iframe'
|
||||
this.iframeUrl = ''
|
||||
this.loading = true
|
||||
try {
|
||||
this.iframeUrl = await this.fetchAppcenterUrl()
|
||||
} catch (error) {
|
||||
this.$message.error(this.resolveErrorMessage(error))
|
||||
await this.bootstrapGoodsView()
|
||||
} finally {
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
async fetchAppcenterUrl() {
|
||||
const urlResponse = await getAppcenterUrl()
|
||||
const urlData = urlResponse?.data?.data
|
||||
const url =
|
||||
(typeof urlData === 'string' ? urlData : '') || urlData?.url || ''
|
||||
if (!url) {
|
||||
throw new Error('获取应用中心地址失败')
|
||||
}
|
||||
return url
|
||||
},
|
||||
async loadGoods() {
|
||||
this.loading = true
|
||||
try {
|
||||
const goodsRes = await getAppcenterGoods()
|
||||
const data = goodsRes?.data?.data || {}
|
||||
this.pageInfo = data.page || {}
|
||||
this.goodsList = Array.isArray(data.items) ? data.items : []
|
||||
this.channel = data.channel || 'ecshopx'
|
||||
} catch (error) {
|
||||
this.$message.error(this.resolveErrorMessage(error))
|
||||
this.goodsList = []
|
||||
} finally {
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
async handleAppClick(item) {
|
||||
if (this.openingBn) return
|
||||
this.openingBn = item.goods_bn
|
||||
try {
|
||||
const response = await getUsercenterAuthorizeUrl()
|
||||
const data = response?.data?.data
|
||||
const url = (typeof data === 'string' ? data : '') || data?.url || ''
|
||||
if (!url) {
|
||||
this.$message.error('获取授权链接失败')
|
||||
return
|
||||
}
|
||||
this.authRedirecting = false
|
||||
this.authIframeUrl = url
|
||||
this.authDialogVisible = true
|
||||
} catch (error) {
|
||||
this.$message.error(this.resolveErrorMessage(error))
|
||||
} finally {
|
||||
this.openingBn = ''
|
||||
}
|
||||
},
|
||||
handleAuthDialogClosed() {
|
||||
this.authIframeUrl = ''
|
||||
this.authRedirecting = false
|
||||
},
|
||||
onAuthIframeLoad() {
|
||||
if (!this.authDialogVisible || this.authRedirecting) return
|
||||
|
||||
try {
|
||||
const iframe = this.$refs.authIframe
|
||||
const loc = iframe?.contentWindow?.location
|
||||
if (!loc?.href) return
|
||||
|
||||
const code = new URL(loc.href).searchParams.get('code')
|
||||
if (!code) return
|
||||
|
||||
const callbackPath = this.$route.path
|
||||
if (!loc.pathname.endsWith(callbackPath)) return
|
||||
|
||||
this.authRedirecting = true
|
||||
window.location.href = loc.href
|
||||
} catch (e) {
|
||||
// 授权页跨域阶段无法读取 iframe 地址,待回调至同源 redirect_uri 后再处理
|
||||
}
|
||||
},
|
||||
formatPrice(price) {
|
||||
const num = Number(price)
|
||||
if (Number.isNaN(num)) return price || '0.00'
|
||||
return num.toFixed(2)
|
||||
},
|
||||
resolveErrorMessage(error) {
|
||||
return (
|
||||
error?.data?.data?.message ||
|
||||
error?.data?.message ||
|
||||
error?.response?.data?.data?.message ||
|
||||
error?.response?.data?.message ||
|
||||
error?.message ||
|
||||
'操作失败'
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.sp-page.user-center-page {
|
||||
min-height: 0;
|
||||
background: #fff;
|
||||
border-radius: 6px;
|
||||
overflow: hidden;
|
||||
|
||||
.sp-page__content {
|
||||
padding: 14px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.appcenter-embed {
|
||||
box-sizing: border-box;
|
||||
min-height: calc(100vh - 160px);
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background: #f5f7fb;
|
||||
overflow: hidden;
|
||||
color: #263445;
|
||||
font-family: 'PingFang SC', 'Microsoft YaHei', Arial, sans-serif;
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
text-align: left;
|
||||
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
|
||||
.appcenter-workspace {
|
||||
position: relative;
|
||||
margin: 14px;
|
||||
background: #fff;
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 1px 5px rgba(20, 35, 60, 0.05);
|
||||
}
|
||||
|
||||
.appcenter-tabs {
|
||||
min-height: 0;
|
||||
padding: 0 16px;
|
||||
border-bottom: 1px solid #e5ebf3;
|
||||
background: #fbfcfe;
|
||||
border-radius: 8px 8px 0 0;
|
||||
|
||||
&.appcenter-tabs--no-user {
|
||||
padding-right: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.appcenter-tabs-main {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.appcenter-tab {
|
||||
display: inline-block;
|
||||
margin: 0 22px 0 0;
|
||||
padding: 11px 2px 9px;
|
||||
border: 0;
|
||||
border-bottom: 2px solid transparent;
|
||||
background: transparent;
|
||||
color: #667789;
|
||||
font-size: 14px;
|
||||
cursor: default;
|
||||
outline: none;
|
||||
appearance: none;
|
||||
-webkit-appearance: none;
|
||||
|
||||
&.active {
|
||||
border-bottom-color: #263445;
|
||||
color: #1f2d3d;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
.appcenter-tab-panel {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.appcenter-items {
|
||||
padding: 18px;
|
||||
}
|
||||
|
||||
.appcenter-layout-grid {
|
||||
font-size: 0;
|
||||
|
||||
.appcenter-card {
|
||||
display: inline-block;
|
||||
width: 48%;
|
||||
margin-right: 1.5%;
|
||||
vertical-align: top;
|
||||
min-height: 142px;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.appcenter-card {
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
margin-bottom: 14px;
|
||||
padding: 16px;
|
||||
background: #fff;
|
||||
border: 1px solid #e4e9f1;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 1px 5px rgba(20, 35, 60, 0.06);
|
||||
|
||||
h2 {
|
||||
margin: 0 0 8px;
|
||||
padding: 0;
|
||||
font-size: 17px;
|
||||
font-weight: 600;
|
||||
color: #1f2d3d;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0 0 12px;
|
||||
padding: 0;
|
||||
color: #697789;
|
||||
font-size: 13px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
}
|
||||
|
||||
.appcenter-meta {
|
||||
color: #8a97a6;
|
||||
font-size: 12px;
|
||||
|
||||
span {
|
||||
display: inline-block;
|
||||
margin-right: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.appcenter-buy-form {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.appcenter-action {
|
||||
display: inline-block;
|
||||
margin-top: 14px;
|
||||
padding: 7px 14px;
|
||||
border: 0;
|
||||
border-radius: 4px;
|
||||
background: #263445;
|
||||
color: #fff;
|
||||
font-size: 13px;
|
||||
line-height: 1.4;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
outline: none;
|
||||
appearance: none;
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
button.appcenter-action[disabled] {
|
||||
background: #a6b0bd;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.appcenter-empty {
|
||||
margin: 22px 18px;
|
||||
padding: 36px 16px;
|
||||
border: 1px dashed #ccd5e2;
|
||||
border-radius: 8px;
|
||||
background: #fff;
|
||||
color: #8a97a6;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.appcenter-card-main {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.usercenter-iframe-wrap {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: calc(100vh - 160px);
|
||||
background: #f5f7fb;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.usercenter-iframe {
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
min-height: 520px;
|
||||
border: 0;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.usercenter-iframe-placeholder {
|
||||
flex: 1;
|
||||
min-height: 520px;
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.sp-page__content {
|
||||
padding: 14px;
|
||||
}
|
||||
|
||||
.appcenter-layout-grid .appcenter-card {
|
||||
display: block;
|
||||
width: auto;
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.usercenter-auth-dialog {
|
||||
max-width: calc(100vw - 32px);
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
|
||||
.el-dialog__header {
|
||||
padding: 14px 20px 10px;
|
||||
}
|
||||
|
||||
.el-dialog__title {
|
||||
font-size: 16px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.el-dialog__body {
|
||||
padding: 0;
|
||||
height: 420px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.usercenter-auth-iframe {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 420px;
|
||||
border: 0;
|
||||
background: #fff;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -27,7 +27,6 @@
|
||||
:scene="scene"
|
||||
:template-id="templateId"
|
||||
:title="decorationTitle"
|
||||
@back="decorationHandleBack"
|
||||
@save="decorationHandleSave"
|
||||
/>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user