3
This commit is contained in:
@@ -2,32 +2,59 @@
|
||||
<view class="page">
|
||||
<view class="tabs">
|
||||
<view class="tab" :class="{active: tab==='all'}" @click="switchTab('all')">全部</view>
|
||||
<view class="tab" :class="{active: tab==='category'}" @click="switchTab('category')">按类别</view>
|
||||
<view class="tab" :class="{active: tab==='search'}" @click="switchTab('search')">查询</view>
|
||||
<view class="tab extra" @click="goMySubmissions">我的提交</view>
|
||||
</view>
|
||||
|
||||
<view class="search">
|
||||
<input v-model.trim="query.kw" placeholder="输入名称/条码/规格查询" @confirm="reload" />
|
||||
<picker mode="selector" :range="categoryNames" v-if="tab==='category'" @change="onPickCategory">
|
||||
<view class="picker">{{ categoryLabel }}</view>
|
||||
</picker>
|
||||
<view class="search" :class="{ 'template-mode': query.mode==='template' }" v-if="tab==='search'">
|
||||
<view class="mode">
|
||||
<picker mode="selector" :range="['直接查询','名称模糊查询','按模板参数查询']" @change="e => (query.mode = ['direct','nameLike','template'][Number(e.detail.value)] || 'direct')">
|
||||
<view class="picker">{{ modeLabel }}</view>
|
||||
</picker>
|
||||
</view>
|
||||
<block v-if="query.mode==='direct' || query.mode==='nameLike'">
|
||||
<input v-model.trim="query.kw" placeholder="输入名称/条码/规格查询" @confirm="reload" />
|
||||
</block>
|
||||
<block v-if="query.mode==='template'">
|
||||
<view class="picker-row">
|
||||
<picker mode="selector" :range="categoryNames" @change="onPickCategory">
|
||||
<view class="picker">{{ categoryLabel }}</view>
|
||||
</picker>
|
||||
<picker mode="selector" :range="templateNames" @change="onPickTemplate">
|
||||
<view class="picker">{{ templateLabel }}</view>
|
||||
</picker>
|
||||
</view>
|
||||
<view class="params-wrap">
|
||||
<view class="param-row" v-for="(p,idx) in selectedTemplateParams" :key="p.fieldKey">
|
||||
<input v-if="p.type==='string'" v-model.trim="paramValues[p.fieldKey]" :placeholder="'输入' + p.fieldLabel" />
|
||||
<input v-else-if="p.type==='number'" type="number" v-model.number="paramValues[p.fieldKey]" :placeholder="'输入' + p.fieldLabel" />
|
||||
<switch v-else-if="p.type==='boolean'" :checked="!!paramValues[p.fieldKey]" @change="onParamBoolChange(p, $event)" />
|
||||
<picker v-else-if="p.type==='enum'" mode="selector" :range="p.enumOptions||[]" @change="onPickParamEnumWrapper(p, $event)">
|
||||
<view class="picker">{{ displayParamEnum(p) }}</view>
|
||||
</picker>
|
||||
<picker v-else-if="p.type==='date'" mode="date" @change="onParamDateChange(p, $event)">
|
||||
<view class="picker">{{ paramValues[p.fieldKey] || ('选择' + p.fieldLabel) }}</view>
|
||||
</picker>
|
||||
<input v-else v-model.trim="paramValues[p.fieldKey]" :placeholder="'输入' + p.fieldLabel" />
|
||||
</view>
|
||||
</view>
|
||||
</block>
|
||||
<button size="mini" @click="reload">查询</button>
|
||||
</view>
|
||||
|
||||
<scroll-view scroll-y class="list" @scrolltolower="loadMore">
|
||||
<block v-if="items.length">
|
||||
<view class="item" v-for="it in items" :key="it.id" @click="openForm(it.id)">
|
||||
<view class="item" v-for="it in items" :key="it.id" @click="openDetail(it.id)">
|
||||
<image v-if="it.cover" :src="it.cover" class="thumb" mode="aspectFill" />
|
||||
<view class="content">
|
||||
<view class="name">
|
||||
<text>{{ it.name }}</text>
|
||||
<view class="name">
|
||||
<text>{{ it.name }}</text>
|
||||
<text v-if="it.deleted" class="tag-deleted">已删除</text>
|
||||
<text v-if="it.platformStatus==='platform'" class="tag-platform">平台推荐</text>
|
||||
<text v-else-if="it.sourceSubmissionId" class="tag-custom">我的提交</text>
|
||||
</view>
|
||||
<view class="meta">{{ it.brand || '-' }} {{ it.model || '' }} {{ it.spec || '' }}</view>
|
||||
<view class="meta">库存:{{ it.stock ?? 0 }}
|
||||
<text class="price">零售价:¥{{ (it.retailPrice ?? it.price ?? 0).toFixed(2) }}</text>
|
||||
</view>
|
||||
<!-- 隐藏库存与价格展示,按需求仅展示基础信息 -->
|
||||
</view>
|
||||
</view>
|
||||
</block>
|
||||
@@ -47,11 +74,13 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
items: [],
|
||||
query: { kw: '', page: 1, size: 20, categoryId: '' },
|
||||
query: { kw: '', page: 1, size: 20, categoryId: '', mode: 'direct', templateId: '', params: {} },
|
||||
finished: false,
|
||||
loading: false,
|
||||
tab: 'all',
|
||||
categories: []
|
||||
categories: [],
|
||||
templates: [],
|
||||
paramValues: {}
|
||||
}
|
||||
},
|
||||
onLoad() {
|
||||
@@ -76,26 +105,59 @@ export default {
|
||||
categoryLabel() {
|
||||
const c = this.categories.find(x => String(x.id) === String(this.query.categoryId))
|
||||
return c ? '类别:' + c.name : '选择类别'
|
||||
}
|
||||
},
|
||||
modeLabel() {
|
||||
const map = { direct: '直接查询', nameLike: '名称模糊查询', template: '按模板参数查询' }
|
||||
return map[this.query.mode] || '直接查询'
|
||||
},
|
||||
templateNames() { return this.templates.map(t => t.name) },
|
||||
templateLabel() {
|
||||
const t = this.templates.find(x => String(x.id) === String(this.query.templateId))
|
||||
return t ? '模板:' + t.name : '选择模板'
|
||||
},
|
||||
selectedTemplate() { return this.templates.find(t => String(t.id) === String(this.query.templateId)) || null },
|
||||
selectedTemplateParams() { return (this.selectedTemplate && Array.isArray(this.selectedTemplate.params)) ? this.selectedTemplate.params : [] }
|
||||
},
|
||||
methods: {
|
||||
switchTab(t) {
|
||||
this.tab = t
|
||||
this.query.categoryId = ''
|
||||
this.query.templateId = ''
|
||||
this.paramValues = {}
|
||||
this.reload()
|
||||
},
|
||||
onPickCategory(e) {
|
||||
const idx = Number(e.detail.value)
|
||||
const c = this.categories[idx]
|
||||
this.query.categoryId = c ? c.id : ''
|
||||
this.reload()
|
||||
this.fetchTemplates()
|
||||
},
|
||||
onPickTemplate(e) {
|
||||
const idx = Number(e.detail.value)
|
||||
const t = this.templates[idx]
|
||||
this.query.templateId = t ? t.id : ''
|
||||
this.paramValues = {}
|
||||
},
|
||||
onPickParamEnumWrapper(p, e) {
|
||||
const idx = Number(e.detail.value)
|
||||
const arr = p.enumOptions || []
|
||||
this.paramValues[p.fieldKey] = arr[idx]
|
||||
},
|
||||
onParamBoolChange(p, e) { this.paramValues[p.fieldKey] = e?.detail?.value ? true : false },
|
||||
onParamDateChange(p, e) { this.paramValues[p.fieldKey] = e?.detail?.value || '' },
|
||||
async fetchCategories() {
|
||||
try {
|
||||
const res = await get('/api/product-categories', {})
|
||||
this.categories = Array.isArray(res?.list) ? res.list : (Array.isArray(res) ? res : [])
|
||||
} catch (_) {}
|
||||
},
|
||||
async fetchTemplates() {
|
||||
try {
|
||||
const res = await get('/api/product-templates', this.query.categoryId ? { categoryId: this.query.categoryId } : {})
|
||||
const list = Array.isArray(res?.list) ? res.list : (Array.isArray(res) ? res : [])
|
||||
this.templates = list
|
||||
} catch (_) { this.templates = [] }
|
||||
},
|
||||
reload() {
|
||||
this.items = []
|
||||
this.query.page = 1
|
||||
@@ -107,7 +169,16 @@ export default {
|
||||
this.loading = true
|
||||
try {
|
||||
const params = { kw: this.query.kw, page: this.query.page, size: this.query.size }
|
||||
if (this.tab === 'category' && this.query.categoryId) params.categoryId = this.query.categoryId
|
||||
if (this.tab === 'search') {
|
||||
if (this.query.categoryId) params.categoryId = this.query.categoryId
|
||||
if (this.query.templateId) params.templateId = this.query.templateId
|
||||
if (this.paramValues && Object.keys(this.paramValues).length) {
|
||||
for (const k of Object.keys(this.paramValues)) {
|
||||
const v = this.paramValues[k]
|
||||
if (v !== undefined && v !== null && v !== '') params['param_' + k] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
const res = await get('/api/products', params)
|
||||
const list = Array.isArray(res?.list) ? res.list : (Array.isArray(res) ? res : [])
|
||||
this.items = this.items.concat(list)
|
||||
@@ -119,13 +190,26 @@ export default {
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
openForm(id) {
|
||||
const url = '/pages/product/form' + (id ? ('?id=' + id) : '')
|
||||
uni.navigateTo({ url })
|
||||
},
|
||||
goMySubmissions() {
|
||||
openDetail(id) {
|
||||
uni.navigateTo({ url: '/pages/product/product-detail?id=' + id })
|
||||
},
|
||||
goMySubmissions() {
|
||||
uni.navigateTo({ url: '/pages/product/submissions' })
|
||||
}
|
||||
},
|
||||
async remove(it) {
|
||||
try {
|
||||
const r = await new Promise(resolve => {
|
||||
uni.showModal({ content: '确认删除该货品?删除后可在后台恢复', success: resolve })
|
||||
})
|
||||
if (!r || !r.confirm) return
|
||||
const { del } = require('../../common/http.js')
|
||||
await del('/api/products/' + it.id)
|
||||
uni.showToast({ title: '已删除', icon: 'success' })
|
||||
this.reload()
|
||||
} catch (e) {
|
||||
uni.showToast({ title: '删除失败', icon: 'none' })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -139,6 +223,9 @@ export default {
|
||||
.search { display:flex; gap: 12rpx; padding: 16rpx; background:$uni-bg-color-grey; align-items: center; }
|
||||
.search input { flex:1; background:$uni-bg-color-hover; border-radius: 12rpx; padding: 12rpx; color: $uni-text-color; }
|
||||
.picker { padding: 8rpx 12rpx; background:$uni-bg-color-hover; border-radius: 10rpx; color:$uni-text-color-grey; }
|
||||
.template-mode { flex-direction: column; align-items: stretch; gap: 8rpx; }
|
||||
.picker-row { display:flex; gap: 12rpx; }
|
||||
.params-wrap { margin-top: 6rpx; background:$uni-bg-color-grey; border-radius: 12rpx; padding: 8rpx 8rpx; }
|
||||
.list { flex:1; }
|
||||
.item { display:flex; padding: 20rpx; background:$uni-bg-color-grey; border-bottom: 1rpx solid $uni-border-color; }
|
||||
.thumb { width: 120rpx; height: 120rpx; border-radius: 12rpx; margin-right: 16rpx; background:$uni-bg-color-hover; }
|
||||
@@ -146,6 +233,7 @@ export default {
|
||||
.name { color:$uni-text-color; margin-bottom: 6rpx; font-weight: 600; display:flex; align-items:center; gap: 12rpx; }
|
||||
.tag-platform { font-size: 22rpx; color:#fff; background:#2d8cf0; padding: 4rpx 10rpx; border-radius: 8rpx; }
|
||||
.tag-custom { font-size: 22rpx; color:#fff; background:#67c23a; padding: 4rpx 10rpx; border-radius: 8rpx; }
|
||||
.tag-deleted { font-size: 22rpx; color:#fff; background:#909399; padding: 4rpx 10rpx; border-radius: 8rpx; }
|
||||
.meta { color:$uni-text-color-grey; font-size: 24rpx; }
|
||||
.price { margin-left: 20rpx; color:$uni-color-primary; }
|
||||
.empty { height: 60vh; display:flex; align-items:center; justify-content:center; color:$uni-text-color-grey; }
|
||||
|
||||
Reference in New Issue
Block a user