merge(scope): consolidate picker, goods, i18n, and layout updates

This commit is contained in:
moyayu
2026-05-09 15:36:32 +08:00
parent fa5f9f7d19
commit 55d147b44f
30 changed files with 356 additions and 290 deletions

View File

@@ -1,15 +1,23 @@
## 本次变更总结
**时间**: 2026-04-14
**时间**: 2026-05-06
**涉及文件**:
- `src/view/decorate/wgts/wgt_hotzone/config.js` (修改)
- `src/view/decorate/wgts/wgt_hotzone/index.vue` (修改)
- `src/view/mall/goods/physical/list.vue` (修改)
- `src/view/mall/goods/physical/supplier_goods_check.vue` (修改)
- `src/components/sp-picker/pickers/picker-marketing.vue` (修改)
- `src/components/template_links/comps/list.vue` (修改)
- `src/i18n/locales/zh-CN.json` (修改)
- `src/i18n/locales/en.json` (修改)
- `src/i18n/locales/ar.json` (修改)
**主要改动**:
- **审核状态列**:驳回原因展示条件由未定义的 `loginType == 'supplier'` 改为 **`IS_SUPPLIER()`**,消除 `ReferenceError: loginType is not defined`,避免表格渲染失败
- **批量提交审核**`$confirm` 正文不再使用与「自定义运费」冲突的 **`d41d8cd9.b2c3d4`**;新增专用键 **`d41d8cd9.b1a2c3`**(中/英/阿),并删除 zh-CN 中重复的 `b2c3d4` 条目,保留「自定义运费」定义
- **热区挂件**:修正后台「横向/纵向」选项与 `animation` 取值、图片占位高度计算及预览样式类的对应关系,使「横向滚动」场景下高度与样式一致
- **实物商品列表**:批量停售/开售二次确认改用独立文案键(`g8h9i0j1` / `k2l3m4n5`),弹窗标题使用 `d41d8cd9.02d981`,避免与其它功能共用键导致文案错乱
- **zh-CN 国际化**:删除重复的 `d41d8cd9.p0q1r2` 等四条易冲突键;`en`/`ar` 补充上述停售确认相关翻译。
- **供应商商品审核**:审核弹窗关闭时重置表单;切换为「通过」时清空驳回原因;提交批量审核时使用临时 `payload`,避免把 `item_ids` 写回持久表单状态。
- **装修/链接**:页面路径中 `coupon_list` 的展示名由「优惠券」统一为「领券中心」(`223cc8af.2f3635` 三语言);营销页选择器与模板链接列表与该键对齐。
**一句话概括**: fix: 自营商品列表审核列 loginType 与批量审核确认文案
**一句话概括**: fix: 热区横纵向与供应商审核、领券中心路径文案

View File

@@ -28,40 +28,20 @@ git diff
### 2) 写出总结(中文)
按下面结构写一段**本次变更总结**,并**生成新的总结文档**(不覆盖旧文档):
在**当前对话回复**中按下面结构输出本次变更总结即可(**不要**在仓库内新建或修改 `.cursor/commit-summary/` 下的任何总结文档,包括 `YYYY-MM-DD-*.md``last-summary.md` 等)。
**文档命名**`YYYY-MM-DD-{tb号}.md`,保存到 `.cursor/commit-summary/` 目录。
- 示例:`2026-03-06-ECX-8058.md`
- 若用户当次对话中提供了 Teambition/需求单号(如 ECX-xxxx则用该 tb 号作为文件名后半部分。
- 若未提供 tb 号,则使用 `YYYY-MM-DD-summary.md`,或根据「一句话概括」生成简短英文标识(如 `coupon-list-i18n`)。
**回复中建议包含**
**总结文档结构**
```markdown
## 本次变更总结
**时间**: YYYY-MM-DD
**涉及文件**:
- 路径1 (新增/修改/删除)
- 路径2 (修改)
- ...
**主要改动**:
- 模块/功能1简要说明
- 模块/功能2简要说明
- ...
**一句话概括**: (用作 commit message 的简短描述)
```
- **涉及文件**:列出主要路径(新增/修改/删除)
- **主要改动**:按模块或功能分点说明
- **一句话概括**:用作 commit message 标题(首行 ≤50 字)
- 总结要基于实际 diff不要编造。
- 若用户有特殊要求(如按「功能/修复/文档」分类),按用户要求组织。
- 每次总结都写入**新文件**,便于按日期和 tb 号追溯;可同时更新 `last-summary.md` 为本次内容(便于「最近一次」查看)。
### 3) 是否执行提交
- **仅总结、不提交**:用户只说「总结」「记录」时,只输出总结并(可选)写入 `last-summary.md`,不执行 `git add` / `git commit`。可追问:「需要我帮你直接提交吗?」
- **仅总结、不提交**:用户只说「总结」「记录」时,只输出上述总结,不执行 `git add` / `git commit`。可追问:「需要我帮你直接提交吗?」
- **总结并提交**:用户明确说「并提交」「直接 commit」「帮我 commit」时继续执行步骤 4。
### 4) 执行提交(仅在用户要求提交时)
@@ -90,6 +70,6 @@ git diff
## 示例对话
- 用户:「帮我总结这次改了什么并提交」→ 获取 diff → 写总结**新建** `.cursor/commit-summary/YYYY-MM-DD-{tb号}.md`(无 tb 号则用 `YYYY-MM-DD-summary.md`)→ 可选更新 last-summary.md → git add → git commit。
- 用户:「先总结一下我改了啥」→ 只执行获取 diff 与写总结,并生成新的日期+tb号总结文档,不 commit可问「需要我帮你直接提交吗」。
- 用户:「记录一下然后 commit」→ 写总结、生成新总结文档并执行 commit。
- 用户:「帮我总结这次改了什么并提交」→ 获取 diff → 在对话中写总结 → git add → git commit。
- 用户:「先总结一下我改了啥」→ 获取 diff → 在对话中写总结,不 commit可问「需要我帮你直接提交吗」。
- 用户:「记录一下然后 commit」→ 在对话中写总结并执行 commit。

View File

@@ -11,26 +11,9 @@
.sp-finder-hd {
display: none;
}
.sp-finder {
&.no-multiple {
.sp-finder-bd {
.el-table__fixed-header-wrapper {
table thead {
tr {
th {
&:nth-child(1) {
.el-checkbox {
display: none;
}
}
}
}
}
}
}
.el-table__fixed-body-wrapper {
top: 38px !important;
}
.disableheadselection {
> .cell .el-checkbox__inner {
display: none;
}
}
.el-pagination {
@@ -48,13 +31,18 @@
</SpFilterForm> -->
<SpFinder
ref="finder"
:class="['shop-finder', { 'no-multiple': !multiple }]"
:other-config="{
'max-height': 460
'max-height': 460,
'header-cell-class-name': cellClass
}"
url="/article/management"
:fixed-row-action="true"
:setting="articleSetting"
:setting="{
columns: [
{ name: 'ID', key: 'article_id', width: 80 },
{ name: $t('9bbe0bc6.7526a0'), key: 'title' }
]
}"
:hooks="{
beforeSearch: beforeSearch,
afterSearch: afterSearch
@@ -69,23 +57,13 @@
import BasePicker from './base'
import PageMixin from '../mixins/page'
export default {
name: 'PickerPages',
name: 'PickerArticle',
extends: BasePicker,
mixins: [PageMixin],
config: {
title: '选择文章'
},
props: ['value'],
computed: {
articleSetting() {
return {
columns: [
{ name: 'ID', key: 'article_id', width: 80 },
{ name: this.$t('9bbe0bc6.7526a0'), key: 'title' }
]
}
}
},
data() {
return {
formData: {
@@ -110,13 +88,16 @@ export default {
},
afterSearch(response) {
const { list } = response.data.data
if (this.value.data) {
const selectRows = list.filter((item) => this.value.data.includes(item.article_id))
const { finderTable } = this.$refs.finder.$refs
setTimeout(() => {
finderTable.$refs.finderTable.setSelection(selectRows)
})
}
const raw = this.value?.data
if (raw == null || raw === '') return
const selectedIds = Array.isArray(raw) ? raw : [raw]
const selectRows = list.filter((item) => selectedIds.map(String).includes(String(item.article_id)))
if (!selectRows.length) return
const finderTable = this.$refs.finder?.$refs?.finderTable
if (!finderTable?.$refs?.finderTable) return
setTimeout(() => {
finderTable.$refs.finderTable.setSelection(selectRows)
})
},
onSearch() {
this.$refs.finder.refresh(true)

View File

@@ -197,13 +197,16 @@ export default {
},
afterSearch(response) {
const { list } = response.data.data
if (this.value.data) {
const selectRows = list.filter((item) => this.value?.data.includes(item.card_id))
const { finderTable } = this.$refs.finder.$refs
setTimeout(() => {
finderTable.$refs.finderTable.setSelection(selectRows)
})
}
const raw = this.value?.data
if (raw == null || raw === '') return
const selectedIds = Array.isArray(raw) ? raw : [raw]
const selectRows = list.filter((item) => selectedIds.map(String).includes(String(item.card_id)))
if (!selectRows.length) return
const finderTable = this.$refs.finder?.$refs?.finderTable
if (!finderTable?.$refs?.finderTable) return
setTimeout(() => {
finderTable.$refs.finderTable.setSelection(selectRows)
})
},
onSearch() {
this.$refs.finder.refresh()

View File

@@ -254,7 +254,8 @@ export default {
}
},
created() {
this.localSelection = this.value.data || []
const raw = this.value?.data
this.localSelection = raw == null || raw === '' ? [] : Array.isArray(raw) ? raw : [raw]
this.$options.config.title = this.$t('a7e61545.43d1e2')
},
mounted() {

View File

@@ -72,7 +72,7 @@ import { i18n } from '@/i18n'
import BasePicker from './base'
import PageMixin from '../mixins/page'
export default {
name: 'PickerPages',
name: 'PickerLink',
extends: BasePicker,
mixins: [PageMixin],
config: {
@@ -96,6 +96,7 @@ export default {
{ 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') },
@@ -128,18 +129,22 @@ export default {
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') }
]
}
if (this.value.data) {
const selectRows = this.list.filter((item) => this.value.data.includes(item.id))
const { finderTable } = this.$refs.finder.$refs
setTimeout(() => {
finderTable.$refs.finderTable.setSelection(selectRows)
})
}
const raw = this.value?.data
if (raw == null || raw === '') return
const selectedIds = Array.isArray(raw) ? raw : [raw]
const selectRows = this.list.filter((item) => selectedIds.map(String).includes(String(item.id)))
if (!selectRows.length) return
const finderTable = this.$refs.finder?.$refs?.finderTable
if (!finderTable?.$refs?.finderTable) return
setTimeout(() => {
finderTable.$refs.finderTable.setSelection(selectRows)
})
},
methods: {
onSearch() {

View File

@@ -70,7 +70,7 @@ import { i18n } from '@/i18n'
import BasePicker from './base'
import PageMixin from '../mixins/page'
export default {
name: 'PickerPages',
name: 'PickerLive',
extends: BasePicker,
mixins: [PageMixin],
config: {
@@ -109,16 +109,16 @@ export default {
},
afterSearch(response) {
const { list } = response.data.data
if (this.value.data && Array.isArray(this.value.data) && this.value.data.length > 0) {
const selectRows = list.filter((item) => this.value.data.includes(item.roomid))
const { finderTable } = this.$refs.finder.$refs
// 只有当找到匹配的项时才设置选中状态,避免清空其他选中项
if (selectRows.length > 0) {
setTimeout(() => {
finderTable.$refs.finderTable.setSelection(selectRows)
})
}
}
const raw = this.value?.data
if (raw == null || raw === '') return
const selectedIds = Array.isArray(raw) ? raw : [raw]
const selectRows = list.filter((item) => selectedIds.map(String).includes(String(item.roomid)))
if (!selectRows.length) return
const finderTable = this.$refs.finder?.$refs?.finderTable
if (!finderTable?.$refs?.finderTable) return
setTimeout(() => {
finderTable.$refs.finderTable.setSelection(selectRows)
})
},
onSearch() {
this.$refs.finder.refresh(true)

View File

@@ -117,14 +117,16 @@ export default {
},
afterSearch(response) {
const { list = [] } = response.data.data
const _data = this.value?.data || []
if (_data?.length) {
const selectRows = list.filter((item) => _data?.includes(item.id))
const { finderTable } = this.$refs.finder.$refs
setTimeout(() => {
finderTable.$refs.finderTable.setSelection(selectRows)
})
}
const raw = this.value?.data
if (raw == null || raw === '') return
const selectedIds = Array.isArray(raw) ? raw : [raw]
const selectRows = list.filter((item) => selectedIds.map(String).includes(String(item.id)))
if (!selectRows.length) return
const finderTable = this.$refs.finder?.$refs?.finderTable
if (!finderTable?.$refs?.finderTable) return
setTimeout(() => {
finderTable.$refs.finderTable.setSelection(selectRows)
})
},
onSearch() {
this.$refs.finder.refresh(true)

View File

@@ -89,7 +89,8 @@ export default {
const t = this.$t.bind(this)
return [
{ id: 'groups_list', title: t('9ef219f6.f38e72') },
{ id: 'coupon_list', title: t('9ef219f6.2f3635') }
{ id: 'coupon_list', title: t('223cc8af.2f3635') },
{ id: 'my_coupon', title: t('223cc8af.a8f3e2') }
]
},
marketingSetting() {

View File

@@ -123,13 +123,16 @@ export default {
},
afterSearch(response) {
const { list } = response.data.data
if (this.value.data) {
const selectRows = list.filter((item) => this.value.data.includes(item.id))
const { finderTable } = this.$refs.finder.$refs
setTimeout(() => {
finderTable.$refs.finderTable.setSelection(selectRows)
})
}
const raw = this.value?.data
if (raw == null || raw === '') return
const selectedIds = Array.isArray(raw) ? raw : [raw]
const selectRows = list.filter((item) => selectedIds.map(String).includes(String(item.id)))
if (!selectRows.length) return
const finderTable = this.$refs.finder?.$refs?.finderTable
if (!finderTable?.$refs?.finderTable) return
setTimeout(() => {
finderTable.$refs.finderTable.setSelection(selectRows)
})
},
onSearch() {
this.$refs.finder.refresh(true)

View File

@@ -92,13 +92,16 @@ export default {
},
afterSearch(response) {
const { list } = response.data.data
if (this.value.data) {
const selectRows = list.filter((item) => this.value.data.includes(item.article_id))
const { finderTable } = this.$refs.finder.$refs
setTimeout(() => {
finderTable.$refs.finderTable.setSelection(selectRows)
})
}
const raw = this.value?.data
if (raw == null || raw === '') return
const selectedIds = Array.isArray(raw) ? raw : [raw]
const selectRows = list.filter((item) => selectedIds.map(String).includes(String(item.article_id)))
if (!selectRows.length) return
const finderTable = this.$refs.finder?.$refs?.finderTable
if (!finderTable?.$refs?.finderTable) return
setTimeout(() => {
finderTable.$refs.finderTable.setSelection(selectRows)
})
},
onSearch() {
this.$refs.finder.refresh(true)

View File

@@ -70,7 +70,7 @@ import BasePicker from './base'
import PageMixin from '../mixins/page'
import moment from 'moment'
export default {
name: 'PickerPages',
name: 'PickerPurchaseActivity',
extends: BasePicker,
mixins: [PageMixin],
config: {
@@ -118,14 +118,16 @@ export default {
},
afterSearch(response) {
const { list } = response.data.data
if (this.value.data) {
const valueData = this.multiple ? valueData : this.value.data + ''
const selectRows = list.filter((item) => valueData.includes(item.id))
const { finderTable } = this.$refs.finder.$refs
setTimeout(() => {
finderTable.$refs.finderTable.setSelection(selectRows)
})
}
const raw = this.value?.data
if (raw == null || raw === '') return
const selectedIds = Array.isArray(raw) ? raw : [raw]
const selectRows = list.filter((item) => selectedIds.map(String).includes(String(item.id)))
if (!selectRows.length) return
const finderTable = this.$refs.finder?.$refs?.finderTable
if (!finderTable?.$refs?.finderTable) return
setTimeout(() => {
finderTable.$refs.finderTable.setSelection(selectRows)
})
},
onSearch() {
this.$refs.finder.refresh(true)

View File

@@ -69,7 +69,7 @@
import BasePicker from './base'
import PageMixin from '../mixins/page'
export default {
name: 'PickerPages',
name: 'PickerRegactivity',
extends: BasePicker,
mixins: [PageMixin],
config: {
@@ -120,13 +120,16 @@ export default {
},
afterSearch(response) {
const { list } = response.data.data
if (this.value.data) {
const selectRows = list.filter((item) => this.value.data.includes(item.activity_id))
const { finderTable } = this.$refs.finder.$refs
setTimeout(() => {
finderTable.$refs.finderTable.setSelection(selectRows)
})
}
const raw = this.value?.data
if (raw == null || raw === '') return
const selectedIds = Array.isArray(raw) ? raw : [raw]
const selectRows = list.filter((item) => selectedIds.map(String).includes(String(item.activity_id)))
if (!selectRows.length) return
const finderTable = this.$refs.finder?.$refs?.finderTable
if (!finderTable?.$refs?.finderTable) return
setTimeout(() => {
finderTable.$refs.finderTable.setSelection(selectRows)
})
},
onSearch() {
this.$refs.finder.refresh(true)

View File

@@ -118,13 +118,16 @@ export default {
},
afterSearch(response) {
const { list } = response.data.data
if (this.value.data) {
const selectRows = list.filter((item) => this.value.data.includes(item.id))
const { finderTable } = this.$refs.finder.$refs
setTimeout(() => {
finderTable.$refs.finderTable.setSelection(selectRows)
})
}
const raw = this.value?.data
if (raw == null || raw === '') return
const selectedIds = Array.isArray(raw) ? raw : [raw]
const selectRows = list.filter((item) => selectedIds.map(String).includes(String(item.id)))
if (!selectRows.length) return
const finderTable = this.$refs.finder?.$refs?.finderTable
if (!finderTable?.$refs?.finderTable) return
setTimeout(() => {
finderTable.$refs.finderTable.setSelection(selectRows)
})
},
onSearch() {
this.$refs.finder.refresh(true)

View File

@@ -202,13 +202,16 @@ export default {
},
afterSearch(response) {
const { list } = response.data.data
if (this.value.data) {
const selectRows = list.filter((item) => this.value.data.includes(item.distributor_id))
const { finderTable } = this.$refs.finder.$refs
setTimeout(() => {
finderTable.$refs.finderTable.setSelection(selectRows)
})
}
const raw = this.value?.data
if (raw == null || raw === '') return
const selectedIds = Array.isArray(raw) ? raw : [raw]
const selectRows = list.filter((item) => selectedIds.map(String).includes(String(item.distributor_id)))
if (!selectRows.length) return
const finderTable = this.$refs.finder?.$refs?.finderTable
if (!finderTable?.$refs?.finderTable) return
setTimeout(() => {
finderTable.$refs.finderTable.setSelection(selectRows)
})
},
onSearch() {
this.$refs.finder.refresh(true)

View File

@@ -141,13 +141,16 @@ export default {
},
afterSearch(response) {
const { list } = response.data.data
if (this.value.data) {
const selectRows = list.filter((item) => this.value.data.includes(item.tag_id))
const { finderTable } = this.$refs.finder.$refs
setTimeout(() => {
finderTable.$refs.finderTable.setSelection(selectRows)
})
}
const raw = this.value?.data
if (raw == null || raw === '') return
const selectedIds = Array.isArray(raw) ? raw : [raw]
const selectRows = list.filter((item) => selectedIds.map(String).includes(String(item.tag_id)))
if (!selectRows.length) return
const finderTable = this.$refs.finder?.$refs?.finderTable
if (!finderTable?.$refs?.finderTable) return
setTimeout(() => {
finderTable.$refs.finderTable.setSelection(selectRows)
})
},
onSearch() {
this.$refs.finder.refresh(true)

View File

@@ -106,12 +106,15 @@ export default {
},
afterSearch(response) {
const { list } = response.data.data
const { data = [] } = this.value
const selectRow = list.filter((item) => data.includes(item.pages_template_id))
const finderTable = this.$refs['finder'].$refs.finderTable.$refs.finderTable
const raw = this.value?.data
if (raw == null || raw === '') return
const selectedIds = Array.isArray(raw) ? raw : [raw]
const selectRow = list.filter((item) => selectedIds.map(String).includes(String(item.pages_template_id)))
if (!selectRow.length) return
const finderTable = this.$refs.finder?.$refs?.finderTable
if (!finderTable?.$refs?.finderTable) return
setTimeout(() => {
finderTable.setSelection(selectRow)
finderTable.$refs.finderTable.setSelection(selectRow)
})
},
onSearch() {

View File

@@ -87,6 +87,7 @@ export default {
name: 'PickerWxapp',
extends: BasePicker,
mixins: [PageMixin],
props: ['value'],
data() {
return {
formData: {},
@@ -101,15 +102,16 @@ export default {
beforeSearch() {},
afterSearch(response) {
const { list } = response.data.data
if (this.value.data) {
const selectRows = list.filter((item) =>
this.value.data.includes(item.wx_external_routes_id)
)
const { finderTable } = this.$refs.finder.$refs
setTimeout(() => {
finderTable.$refs.finderTable.setSelection(selectRows)
})
}
const raw = this.value?.data
if (raw == null || raw === '') return
const selectedIds = Array.isArray(raw) ? raw : [raw]
const selectRows = list.filter((item) => selectedIds.map(String).includes(String(item.wx_external_routes_id)))
if (!selectRows.length) return
const finderTable = this.$refs.finder?.$refs?.finderTable
if (!finderTable?.$refs?.finderTable) return
setTimeout(() => {
finderTable.$refs.finderTable.setSelection(selectRows)
})
},
onSearch() {
this.$refs.finder.refresh(true)

View File

@@ -333,7 +333,7 @@ export default {
case 'link':
let list = [
{
title: '会员开通',
title: this.$t('223cc8af.f035ca'),
id: 'vipgrades'
},
// {
@@ -341,7 +341,7 @@ export default {
// id: 'pointitems'
// },
{
title: '社区团长申请',
title: this.$t('223cc8af.38d966'),
id: 'applyChief'
}
]
@@ -358,12 +358,16 @@ export default {
case 'marketing':
this.list = [
{
title: '限时团购',
title: this.$t('223cc8af.f38e72'),
id: 'groups_list'
},
{
title: '优惠券',
title: this.$t('223cc8af.2f3635'),
id: 'coupon_list'
},
{
title: this.$t('223cc8af.a8f3e2'),
id: 'my_coupon'
}
]
this.total = 1

View File

@@ -7623,6 +7623,8 @@
"d41d8cd9.389203": "تعيين كغير هدية",
"d41d8cd9.965407": "إيقاف البيع",
"d41d8cd9.1cc97f": "بدء البيع",
"d41d8cd9.g8h9i0j1": "المنتجات المحددة، هل تريد المتابعة؟",
"d41d8cd9.k2l3m4n5": "جميع المنتجات، هل تريد المتابعة؟",
"d41d8cd9.78a38b": "تحميل المنتجات إلى جوشويتان",
"d41d8cd9.fe2216": "تحميل المنتجات إلى وانغديانتونغ",
"d41d8cd9.e8b3c6": "متعدد",
@@ -22529,7 +22531,8 @@
"223cc8af.a13364": "متجر المكافآت",
"223cc8af.7fb92b": "التسجيل في النشاط",
"223cc8af.75a1d2": "تسوقي الجماعي",
"223cc8af.2f3635": "قسائم",
"223cc8af.2f3635": "مركز استلام الكوبونات",
"223cc8af.a8f3e2": "قسائمي",
"223cc8af.975ff6": "مفضلاتي",
"223cc8af.bca1ea": "إدارة العناوين",
"223cc8af.f38e72": "شراء جماعي لفترة محدودة",

View File

@@ -7623,6 +7623,8 @@
"d41d8cd9.389203": "Set as non-gift",
"d41d8cd9.965407": "Stop selling",
"d41d8cd9.1cc97f": "Start selling",
"d41d8cd9.g8h9i0j1": "Selected products, continue?",
"d41d8cd9.k2l3m4n5": "All products, continue?",
"d41d8cd9.78a38b": "Upload products to Jushuitan",
"d41d8cd9.fe2216": "Upload products to Wangdiantong",
"d41d8cd9.e8b3c6": "Multi",
@@ -22530,7 +22532,8 @@
"223cc8af.a13364": "Rewards Mall",
"223cc8af.7fb92b": "Sign up for the event",
"223cc8af.75a1d2": "My Group Buying",
"223cc8af.2f3635": "Coupons",
"223cc8af.2f3635": "Voucher Collection Center",
"223cc8af.a8f3e2": "My coupons",
"223cc8af.975ff6": "My Favorites",
"223cc8af.bca1ea": "Address Management",
"223cc8af.f38e72": "Limited-time group purchase",

View File

@@ -7640,6 +7640,8 @@
"d41d8cd9.389203": "设为非赠品",
"d41d8cd9.965407": "停售",
"d41d8cd9.1cc97f": "开售",
"d41d8cd9.g8h9i0j1": "选中商品, 是否继续?",
"d41d8cd9.k2l3m4n5": "所有商品, 是否继续?",
"d41d8cd9.78a38b": "上传商品到聚水潭",
"d41d8cd9.fe2216": "上传商品到旺店通",
"d41d8cd9.e3c004": "* 0-100之间最多两位小数",
@@ -7695,10 +7697,6 @@
"d41d8cd9.g1h2i3": "批量改价",
"d41d8cd9.j4k5l6": "操作成功",
"d41d8cd9.m7n8o9": "操作失败",
"d41d8cd9.p0q1r2": "选中商品, 是否继续?",
"d41d8cd9.s3t4u5": "提示",
"d41d8cd9.v6w7x8": "所有商品, 是否继续?",
"d41d8cd9.y9z0a1": "是否将所有商品的都同步至店铺?",
"6f19b2ab.6b3d7e": "是否将所有商品同步至店铺?",
"d41d8cd9.e5f6g7": "已加入执行队列,请在设置-导出列表中下载",
"d41d8cd9.h8i9j0": "导出失败",
@@ -22641,7 +22639,8 @@
"223cc8af.a13364": "积分商城",
"223cc8af.7fb92b": "报名活动",
"223cc8af.75a1d2": "我的拼团",
"223cc8af.2f3635": "优惠券",
"223cc8af.2f3635": "领券中心",
"223cc8af.a8f3e2": "我的优惠券",
"223cc8af.975ff6": "我的收藏",
"223cc8af.bca1ea": "地址管理",
"223cc8af.f38e72": "限时团购",

View File

@@ -21,20 +21,30 @@
:key="item.alias_name"
class="main-menu-item py-2 mx-1 my-1 flex flex-col items-center cursor-pointer"
:class="{ 'main-menu-item--active': activeMainMenu === item.alias_name }"
@click="handleMainMenuClick(item)"
>
<!-- {{ computedMenuIcon(item) }} -->
<SpIcon
class="menu-icon"
:name="computedMenuIcon(item)"
:size="18"
:fill="activeMainMenu === item.alias_name ? computedPrimaryColor : '#333'"
/>
<span
class="text-sm mt-1 text-center"
:style="{ color: activeMainMenu === item.alias_name ? computedPrimaryColor : '#333' }"
>{{ menuDisplayName(item) }}</span
<router-link
:to="getMainMenuPath(item)"
custom
v-slot="{ href }"
>
<a
:href="href"
class="main-menu-item__link flex flex-col items-center no-underline text-inherit w-full"
@click="onMainMenuLinkClick($event, item)"
>
<SpIcon
class="menu-icon"
:name="computedMenuIcon(item)"
:size="18"
:fill="activeMainMenu === item.alias_name ? computedPrimaryColor : '#333'"
/>
<span
class="text-sm mt-1 text-center"
:style="{ color: activeMainMenu === item.alias_name ? computedPrimaryColor : '#333' }"
>{{ menuDisplayName(item) }}</span
>
</a>
</router-link>
</li>
<!-- <li @click="handleMainMenuClick({ alias_name: 'license' })" class="text-center text-gray-500 text-sm mt-2 mb-2 cursor-pointer">License</li> -->
</ul>
@@ -76,9 +86,10 @@
v-if="child.is_menu"
:key="child.alias_name"
:index="child.alias_name"
@click="handleSubMenuClick(child)"
>
<span>{{ menuDisplayName(child) }}</span>
<router-link class="sub-menu-link" :to="getSubMenuPath(child)">
{{ menuDisplayName(child) }}
</router-link>
</el-menu-item>
</template>
</el-submenu>
@@ -89,9 +100,10 @@
v-if="item.is_menu"
:key="item.alias_name"
:index="item.alias_name"
@click="handleSubMenuClick(item)"
>
<span>{{ menuDisplayName(item) }}</span>
<router-link class="sub-menu-link" :to="getSubMenuPath(item)">
{{ menuDisplayName(item) }}
</router-link>
</el-menu-item>
</template>
</template>
@@ -220,49 +232,60 @@ export default {
resolveChildren(children) {
return children && children.length > 0 && children.some((child) => child.is_menu)
},
/** 一级菜单下第一个可展示子菜单的 permission与跳转逻辑一致供 href 使用) */
resolveMainMenuFirstPermission(item) {
const subMenus = item?.children || []
const firstChild = (_submenu) => {
for (const it of _submenu) {
if (it.children) {
const result = firstChild(it.children)
if (result) return result
} else if (it.is_menu) {
return it?.permission
}
}
return null
}
if (subMenus.length === 0) {
return item.permission
}
return firstChild(subMenus)
},
getNotFoundPath() {
const basePath = getBasePath()
return basePath ? `/${basePath}/not-found` : '/not-found'
},
/** 主导航在新标签页打开时的目标路径 */
getMainMenuPath(item) {
const permission = this.resolveMainMenuFirstPermission(item)
const route = permission ? this.findRouteByPermission(permission) : null
return route?.path || this.getNotFoundPath()
},
/** 侧栏子菜单在新标签页打开时的目标路径(与旧 layout.vue 中 router-link 行为一致) */
getSubMenuPath(menuItem) {
const route = this.findRouteByPermission(menuItem.permission)
return route?.path || this.getNotFoundPath()
},
onMainMenuLinkClick(e, item) {
if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey || e.button !== 0) {
return
}
e.preventDefault()
this.handleMainMenuClick(item)
},
handleMainMenuClick(item) {
if (item.alias_name == this.$route.matched?.[0]?.meta?.aliasName) {
return
}
this.subMenus = item?.children || []
// 获取第一个子路由
const firstChild = (_submenu) => {
for (const item of _submenu) {
if (item.children) {
const result = firstChild(item.children)
if (result) return result
} else if (item.is_menu) {
return item?.permission
}
}
return null
}
// 如果只有一级菜单,就直接那当前一级菜单的权限
let permission = ''
if (this.subMenus.length === 0) {
permission = item.permission
} else {
permission = firstChild(this.subMenus)
}
const route = this.findRouteByPermission(permission)
const permission = this.resolveMainMenuFirstPermission(item)
const route = permission ? this.findRouteByPermission(permission) : null
if (route) {
this.$router.push({ path: route.path })
} else {
this.toNotFound()
}
},
handleSubMenuClick(item) {
const route = this.findRouteByPermission(item.permission)
if (route) {
if (this.$route.path === route.path) {
return
}
this.$router.push({ path: route.path })
} else {
this.toNotFound()
}
},
findRouteByPermission(permission) {
return this.$router.getRoutes().find((route) => route.meta?.permissions?.includes(permission))
},
@@ -518,6 +541,19 @@ export default {
</script>
<style scoped lang="scss">
.main-menu-item__link {
outline: none;
}
:deep(.el-menu-item .sub-menu-link) {
color: inherit;
text-decoration: none;
display: flex;
align-items: center;
width: 100%;
height: 100%;
}
.main-menu-list {
.main-menu-item {
&:hover {

View File

@@ -16,7 +16,7 @@ const config = {
{ name: i18n.t('7a0ee76a.4f9974'), label: 'vertical' }
],
tips: i18n.t('7a0ee76a.cc9f07'),
value: 'horizontal'
value: 'vertical'
},
{
group: i18n.t('7a0ee76a.eeb8e8'),

View File

@@ -36,17 +36,11 @@
</style>
<template>
<div class="wgt-hotzone" :style="outerStyle">
<div
class="wgt-hotzone-bd"
:class="{ 'wgt-hotzone-bd-vertical': value.animation === 'vertical' }"
>
<el-image
:src="value.data.imgUrl"
:style="{
height: value.animation === 'vertical' ? value.imgHeight + 'px' : 'auto',
display: 'block'
}"
>
<div class="wgt-hotzone-bd" :class="{ 'wgt-hotzone-bd-vertical': value.animation === 'vertical' }">
<el-image :src="value.data.imgUrl" :style="{
height: value.animation === 'vertical' ? value.imgHeight + 'px' : 'auto',
display: 'block'
}">
<div slot="error" class="wgt-hotzone-error">
<img :src="dImage" width="100%" height="100%" style="object-fit: cover" />
</div>
@@ -81,7 +75,7 @@ export default {
return getOuterStyle(this.value)
}
},
created() {},
created() { },
methods: {}
}
</script>

View File

@@ -587,25 +587,25 @@ export default {
item.item_spec?.map((el) => el.spec_custom_value_name || el.spec_value_name) || []
return {
sku_id: vKey.join('_') || '',
spec_name: specName?.join(' ') || '',
item_id: item.item_id || '',
spec_name: specName?.join(' ') ?? '',
item_id: item.item_id ?? '',
is_default: false,
approve_status: item.approve_status || '',
store: item.store || '',
max_num: item.max_num || '',
item_bn: item.item_bn || '',
weight: item.weight || '',
approve_status: item.approve_status ?? '',
store: item.store ?? '',
max_num: item.max_num ?? '',
item_bn: item.item_bn ?? '',
weight: item.weight ?? '',
item_spec: item.item_spec || [],
delivery_time: item.delivery_time || '',
volume: item.volume || '',
delivery_time: item.delivery_time ?? '',
volume: item.volume ?? '',
price: isNaN(item.price / 100) ? '' : item.price / 100,
cost_price: isNaN(item.cost_price / 100) ? '' : item.cost_price / 100,
market_price: isNaN(item.market_price / 100) ? '' : item.market_price / 100,
start_num: item.start_num || '',
barcode: item.barcode || '',
point_num: item.point_num || '',
supplier_goods_bn: item.supplier_goods_bn || '',
tax_rate: item.tax_rate || ''
start_num: item.start_num ?? '',
barcode: item.barcode ?? '',
point_num: item.point_num ?? '',
supplier_goods_bn: item.supplier_goods_bn ?? '',
tax_rate: item.tax_rate ?? ''
}
})
}
@@ -641,21 +641,21 @@ export default {
sku_id: key,
spec_name: this.getSpecName(item),
is_default: false,
approve_status: item.approve_status || '',
store: item.store || '',
max_num: item.max_num || '',
item_bn: item.item_bn || '',
weight: item.weight || '',
volume: item.volume || '',
approve_status: item.approve_status ?? '',
store: item.store ?? '',
max_num: item.max_num ?? '',
item_bn: item.item_bn ?? '',
weight: item.weight ?? '',
volume: item.volume ?? '',
price: isNaN(item.price / 100) ? '' : item.price / 100,
cost_price: isNaN(item.cost_price / 100) ? '' : item.cost_price / 100,
market_price: isNaN(item.market_price / 100) ? '' : item.market_price / 100,
start_num: item.start_num || '',
barcode: item.barcode || '',
point_num: item.point_num || '',
supplier_goods_bn: item.supplier_goods_bn || '',
tax_rate: item.tax_rate || '',
delivery_time: item.delivery_time || '',
start_num: item.start_num ?? '',
barcode: item.barcode ?? '',
point_num: item.point_num ?? '',
supplier_goods_bn: item.supplier_goods_bn ?? '',
tax_rate: item.tax_rate ?? '',
delivery_time: item.delivery_time ?? '',
item_spec: item.item_spec || []
})
}

View File

@@ -746,10 +746,11 @@ export default {
validator: async (rule, value, callback) => {
if (this.form.isSpecs) {
const { specItems, skus } = value
const approveStatus = specItems.find(({ approve_status }) => !!approve_status)
const store = specItems.find(({ store }) => !!store)
const price = specItems.find(({ price }) => !!price)
const max_num = specItems.find(({ max_num }) => !!max_num)
const isSkuFieldFilled = (v) => v != null && v !== ''
const approveStatus = specItems.find(({ approve_status }) => isSkuFieldFilled(approve_status))
const store = specItems.find(({ store }) => isSkuFieldFilled(store))
const price = specItems.find(({ price }) => isSkuFieldFilled(price))
const max_num = specItems.find(({ max_num }) => isSkuFieldFilled(max_num))
const isSkusUnChecked = skus?.some((item) => !item.checkedSku.length)
if (isSkusUnChecked) {

View File

@@ -79,7 +79,7 @@ const [ParamsForm, ParamsFormApi] = useForm({
fieldName: 'is_show',
label: i18n.t('07504bf6.91bb21'),
component: 'radio',
value: true,
value: false,
componentProps: {
options: [
{ label: i18n.t('07504bf6.159985'), value: true },
@@ -172,7 +172,7 @@ export default {
attribute_id: '',
attribute_name: '',
attribute_memo: '',
is_show: true,
is_show: false,
attribute_values: []
},
searchParams: {
@@ -214,7 +214,7 @@ export default {
ParamsFormApi.setFieldsValue({
attribute_name: '',
attribute_memo: '',
is_show: true,
is_show: false,
attribute_values: []
})
}
@@ -226,7 +226,7 @@ export default {
attribute_id: '',
attribute_name: '',
attribute_memo: '',
is_show: true,
is_show: false,
attribute_values: []
}
},

View File

@@ -1794,9 +1794,9 @@ export default {
if (this.selectionItems.length > 0) {
await this.$confirm(
`${status == 'stop' ? this.$t('d41d8cd9.965407') : this.$t('d41d8cd9.1cc97f')}${this.$t(
'd41d8cd9.p0q1r2'
'd41d8cd9.g8h9i0j1'
)}`,
this.$t('d41d8cd9.s3t4u5')
this.$t('d41d8cd9.02d981')
)
const params = {
goods_id: this.selectionItems.map((item) => item.goods_id),
@@ -1809,9 +1809,9 @@ export default {
} else {
await this.$confirm(
`${status == 'stop' ? this.$t('d41d8cd9.965407') : this.$t('d41d8cd9.1cc97f')}${this.$t(
'd41d8cd9.v6w7x8'
'd41d8cd9.k2l3m4n5'
)}`,
this.$t('d41d8cd9.s3t4u5')
this.$t('d41d8cd9.02d981')
)
const params = {
is_market: status == 'stop' ? '0' : '1',

View File

@@ -339,10 +339,15 @@
</el-table>
</SpDrawer>
<el-dialog :title="$t('d41d8cd9.s6t7u8')" :visible.sync="dialogVisibleExamine" width="30%">
<el-dialog
:title="$t('d41d8cd9.s6t7u8')"
:visible.sync="dialogVisibleExamine"
width="30%"
@closed="resetExamineForm"
>
<el-form ref="form" :model="examineForm" label-width="80px">
<el-form-item :label="$t('d41d8cd9.v9w0x1')">
<el-radio-group v-model="examineForm.audit_status">
<el-radio-group v-model="examineForm.audit_status" @change="onExamineAuditStatusChange">
<el-radio label="approved"> {{ $t('d41d8cd9.y2z3a4') }} </el-radio>
<el-radio label="rejected"> {{ $t('d41d8cd9.b5c6d7') }} </el-radio>
</el-radio-group>
@@ -1090,6 +1095,17 @@ export default {
this.$message.error(this.$t('58789194.ace302'))
}
},
resetExamineForm() {
this.examineForm = {
audit_status: 'approved',
audit_reason: ''
}
},
onExamineAuditStatusChange(val) {
if (val === 'approved') {
this.examineForm.audit_reason = ''
}
},
// 批量审批
Examine() {
if (this.selectionItems.length === 0) {
@@ -1097,13 +1113,17 @@ export default {
return false
}
this.resetExamineForm()
this.dialogVisibleExamine = true
},
// 审核确定
onSubmitExamine() {
this.examineForm.item_ids = this.selectionItems.map((item) => item.item_id).join(',')
const payload = {
...this.examineForm,
item_ids: this.selectionItems.map((item) => item.item_id).join(',')
}
this.examineLoading = true
batchReviewItems(this.examineForm)
batchReviewItems(payload)
.then((res) => {
this.$message.success(this.$t('58789194.3b1083'))
this.dialogVisibleExamine = false