662 lines
16 KiB
Vue
662 lines
16 KiB
Vue
<!-- eslint-disable vue/no-v-html -->
|
||
<template>
|
||
<CommonPage show-footer :title="$route.title">
|
||
<!-- {{ queryParams }} -->
|
||
<n-grid class="mb-10" x-gap="12">
|
||
<n-gi span="12" mt-10 flex items-center>
|
||
<span w-100>筛选条件:</span>
|
||
<n-input-group>
|
||
<n-select
|
||
v-model:value="queryParams.selectKey"
|
||
:style="{ width: '25%' }"
|
||
:options="selectOptions"
|
||
placeholder="请选择"
|
||
/>
|
||
<n-input v-model:value="queryParams.word" :style="{ width: '50%' }" />
|
||
</n-input-group>
|
||
</n-gi>
|
||
<n-gi :span="24" mt-10>
|
||
<div>
|
||
<span>审核状态:</span>
|
||
<n-radio-group v-model:value="queryParams.status">
|
||
<n-radio-button
|
||
v-for="song in [
|
||
{
|
||
label: '已审核',
|
||
value: 1,
|
||
},
|
||
{
|
||
label: '拒绝',
|
||
value: 2,
|
||
},
|
||
{
|
||
label: '待审核',
|
||
value: 3,
|
||
},
|
||
]"
|
||
:key="song.value"
|
||
:value="song.value"
|
||
:label="song.label"
|
||
/>
|
||
</n-radio-group>
|
||
</div>
|
||
</n-gi>
|
||
<n-gi :span="24" mt-10>
|
||
<div>
|
||
<span>商品类型:</span>
|
||
<n-radio-group v-model:value="queryParams.type">
|
||
<n-radio-button
|
||
v-for="song in [
|
||
{
|
||
label: '普通商品',
|
||
value: 0,
|
||
},
|
||
{
|
||
label: '活动商品',
|
||
value: 1,
|
||
},
|
||
{
|
||
label: '积分商品',
|
||
value: 2,
|
||
},
|
||
{
|
||
label: '摇球商品',
|
||
value: 3,
|
||
},
|
||
]"
|
||
:key="song.value"
|
||
:value="song.value"
|
||
:label="song.label"
|
||
/>
|
||
</n-radio-group>
|
||
</div>
|
||
</n-gi>
|
||
<n-gi span="24" mt-10 flex items-center>
|
||
<n-button type="primary" @click="getList">查询</n-button>
|
||
<n-button ml-10 @click="clear">重置</n-button>
|
||
</n-gi>
|
||
<n-gi span="24" mt-10 flex items-center>
|
||
<n-button strong secondary type="primary" @click="veeifys()">批量审核</n-button>
|
||
<n-button strong secondary ml-10 type="primary" @click="changeGoodsType(0)">
|
||
设为普通商品
|
||
</n-button>
|
||
<n-button strong secondary ml-10 type="warning" @click="changeGoodsType(1)">
|
||
设为活动商品
|
||
</n-button>
|
||
<n-button strong secondary ml-10 type="info" @click="changeGoodsType(2)">
|
||
设为兑换商品
|
||
</n-button>
|
||
<n-button strong secondary ml-10 type="error" @click="changeGoodsType(3)">
|
||
设为摇球机活动商品
|
||
</n-button>
|
||
</n-gi>
|
||
</n-grid>
|
||
|
||
<n-data-table
|
||
:loading="loading"
|
||
:columns="columns"
|
||
:data="data"
|
||
:pagination="pagination"
|
||
:bordered="false"
|
||
:row-key="(row) => row.gid"
|
||
:checked-row-keys="queryParams.checkedRowKeysRef"
|
||
remote
|
||
@update:checked-row-keys="handleCheck"
|
||
/>
|
||
<!-- 拒绝 -->
|
||
<n-modal v-model:show="isNoteModel">
|
||
<n-card
|
||
style="width: 500px"
|
||
title="拒绝信息"
|
||
:bordered="false"
|
||
size="huge"
|
||
role="dialog"
|
||
aria-modal="true"
|
||
>
|
||
<n-input v-model:value="notesVal" type="textarea" placeholder="请输入拒绝理由...." />
|
||
<div m-auto p-10>
|
||
<n-button type="primary" @click="veeify">确定</n-button>
|
||
<n-button ml-10 @click="clear">取消</n-button>
|
||
</div>
|
||
</n-card>
|
||
</n-modal>
|
||
<!-- 豆子设置 -->
|
||
<n-modal v-model:show="isDzModel">
|
||
<n-card
|
||
style="width: 500px"
|
||
title="赠送/比例"
|
||
:bordered="false"
|
||
size="huge"
|
||
role="dialog"
|
||
aria-modal="true"
|
||
>
|
||
<n-form ref="formRef" :model="nowRow" :rules="rules" label-placement="left">
|
||
<n-grid :cols="24">
|
||
<n-form-item-gi :span="20" label="商品赠送豆子" path="pulse">
|
||
<n-input-number
|
||
v-model:value="nowRow.pulse"
|
||
clearable
|
||
placeholder="请输入赠送豆子数量...."
|
||
:min="0"
|
||
/>
|
||
</n-form-item-gi>
|
||
<n-form-item-gi :span="20" label="商品赠送积分" path="integral">
|
||
<n-input-number
|
||
v-model:value="nowRow.integral"
|
||
clearable
|
||
placeholder="请输入赠送积分数量...."
|
||
:min="0"
|
||
/>
|
||
</n-form-item-gi>
|
||
<n-form-item-gi :span="18" label="商品分佣类型" path="commission_type">
|
||
<n-select
|
||
v-model:value="nowRow.commission_type"
|
||
placeholder="请选择分佣类型"
|
||
clearable
|
||
:options="[
|
||
{
|
||
label: '百分比',
|
||
value: 1,
|
||
},
|
||
{
|
||
label: '数值',
|
||
value: 2,
|
||
},
|
||
]"
|
||
/>
|
||
</n-form-item-gi>
|
||
<n-form-item-gi :span="20" label="商品分佣比例" path="commission">
|
||
<n-input-number
|
||
v-model:value="nowRow.commission"
|
||
clearable
|
||
placeholder="请输入分佣比例...."
|
||
:min="0"
|
||
/>
|
||
</n-form-item-gi>
|
||
<n-form-item-gi :span="20" label="豆子过期时间" path="expiration">
|
||
<n-input-number
|
||
v-model:value="nowRow.expiration"
|
||
clearable
|
||
placeholder="请输入豆子过期时间"
|
||
:min="0"
|
||
/>
|
||
</n-form-item-gi>
|
||
<n-form-item-gi :span="12">
|
||
<div m-auto p-10>
|
||
<n-button type="primary" @click="veeify">确定</n-button>
|
||
<n-button ml-10 @click="clear">取消</n-button>
|
||
</div>
|
||
</n-form-item-gi>
|
||
</n-grid>
|
||
</n-form>
|
||
</n-card>
|
||
</n-modal>
|
||
<!-- 商品详情 -->
|
||
<n-drawer v-model:show="showDrawer" :width="502">
|
||
<n-drawer-content title="商品详情" closable>
|
||
<n-space vertical>
|
||
<div>
|
||
<span>商品分类:</span>
|
||
<span>{{ goodInfo.class_name }}</span>
|
||
</div>
|
||
<div>
|
||
<span>商品名称:</span>
|
||
<span>{{ goodInfo.name }}</span>
|
||
</div>
|
||
<div flex items-center>
|
||
<span>封面:</span>
|
||
<n-image width="100" :src="goodInfo.cover" />
|
||
</div>
|
||
<div flex items-center>
|
||
<span>轮播图:</span>
|
||
<div w-400 overflow-auto>
|
||
<n-image
|
||
v-for="(url, index) in goodInfo.rotation?.split(',')"
|
||
:key="index"
|
||
width="100"
|
||
:src="url"
|
||
/>
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<span>商品价格:</span>
|
||
<span>{{ goodInfo.number }}</span>
|
||
</div>
|
||
<div>
|
||
<span>市场价格:</span>
|
||
<span>{{ goodInfo.market_num }}</span>
|
||
</div>
|
||
<div>
|
||
<span>商品库存:</span>
|
||
<span>{{ goodInfo.stock }}</span>
|
||
</div>
|
||
<div>
|
||
<span>商品简介:</span>
|
||
<span>{{ goodInfo.profile }}</span>
|
||
</div>
|
||
<div>
|
||
<span>商品详情:</span>
|
||
<div v-html="goodInfo.details"></div>
|
||
</div>
|
||
</n-space>
|
||
</n-drawer-content>
|
||
</n-drawer>
|
||
</CommonPage>
|
||
</template>
|
||
|
||
<script setup>
|
||
import api from './api'
|
||
import { NButton, NImage, NSpace, NEllipsis, NTag } from 'naive-ui'
|
||
import { h, withDirectives, resolveDirective } from 'vue'
|
||
|
||
const vPerms = resolveDirective('perms')
|
||
|
||
const loading = ref(false)
|
||
|
||
const isNoteModel = ref(false)
|
||
|
||
const isDzModel = ref(false)
|
||
|
||
const goodInfo = ref({})
|
||
|
||
const showDrawer = ref(false)
|
||
|
||
const notesVal = ref('')
|
||
|
||
const formRef = ref(null)
|
||
|
||
const selectOptions = ref([
|
||
{
|
||
label: '商品名称',
|
||
value: 0,
|
||
},
|
||
{
|
||
label: '商家名称',
|
||
value: 1,
|
||
},
|
||
])
|
||
|
||
const queryParams = ref({
|
||
selectKey: 0,
|
||
word: '',
|
||
type: '',
|
||
status: 0,
|
||
checkedRowKeysRef: [],
|
||
})
|
||
|
||
const handleCheck = (row) => {
|
||
queryParams.value.checkedRowKeysRef = row
|
||
}
|
||
|
||
const changeGoodsType = async (type) => {
|
||
if (queryParams.value.checkedRowKeysRef.length === 0) return $message.info('没有选中商品')
|
||
await api.updateType({
|
||
type: type,
|
||
gid: queryParams.value.checkedRowKeysRef,
|
||
})
|
||
getList()
|
||
queryParams.value.checkedRowKeysRef = []
|
||
}
|
||
|
||
const rules = {
|
||
pulse: {
|
||
required: true,
|
||
type: 'number',
|
||
message: '请输入赠送豆子数量',
|
||
trigger: 'blur',
|
||
},
|
||
integral: {
|
||
required: true,
|
||
type: 'number',
|
||
message: '请输入赠送积分数量',
|
||
trigger: 'blur',
|
||
},
|
||
commission_type: {
|
||
required: true,
|
||
type: 'number',
|
||
message: '请选择分佣类型',
|
||
trigger: 'change',
|
||
},
|
||
commission: {
|
||
required: true,
|
||
type: 'number',
|
||
message: '请输入分佣比例',
|
||
trigger: 'blur',
|
||
},
|
||
}
|
||
|
||
const nowRow = ref({})
|
||
const nowKey = ref(null)
|
||
|
||
const columns = ref([
|
||
{
|
||
type: 'selection',
|
||
},
|
||
{
|
||
title: '商品名称',
|
||
slot: 'name',
|
||
align: 'center',
|
||
render: (row) => {
|
||
return h(
|
||
NEllipsis,
|
||
{
|
||
style: 'max-width: 200px',
|
||
},
|
||
{
|
||
default: () => row.name,
|
||
}
|
||
)
|
||
},
|
||
},
|
||
{
|
||
title: '商家名称',
|
||
slot: 'store_name',
|
||
align: 'center',
|
||
render: (row) => {
|
||
return h(
|
||
'span',
|
||
{},
|
||
{
|
||
default: () => row.Store.name,
|
||
}
|
||
)
|
||
},
|
||
},
|
||
{
|
||
title: '商品封面',
|
||
slot: 'cover',
|
||
align: 'center',
|
||
render(row) {
|
||
return h(NImage, {
|
||
src: row.cover,
|
||
width: '30',
|
||
})
|
||
},
|
||
},
|
||
{
|
||
title: '商品分类',
|
||
slot: 'Classify',
|
||
align: 'center',
|
||
render(row) {
|
||
return h(
|
||
'div',
|
||
{},
|
||
{
|
||
default: () => row.Classify.name,
|
||
}
|
||
)
|
||
},
|
||
},
|
||
{
|
||
title: '商品类型',
|
||
slot: 'type',
|
||
align: 'center',
|
||
render(row) {
|
||
const obj = {
|
||
0: {
|
||
type: 'success',
|
||
text: '普通商品',
|
||
},
|
||
1: {
|
||
type: 'warning',
|
||
text: '活动商品',
|
||
},
|
||
2: {
|
||
type: 'info',
|
||
text: '兑换商品',
|
||
},
|
||
3: {
|
||
type: 'error',
|
||
text: '摇球机活动商品',
|
||
},
|
||
}
|
||
return h(
|
||
NTag,
|
||
{
|
||
type: obj[row.type].type,
|
||
},
|
||
{
|
||
default: () => obj[row.type].text,
|
||
}
|
||
)
|
||
},
|
||
},
|
||
{
|
||
title: '商品价格(元)',
|
||
key: 'number',
|
||
align: 'center',
|
||
},
|
||
{
|
||
title: '商品库存',
|
||
key: 'stock',
|
||
align: 'center',
|
||
},
|
||
{
|
||
title: '赠送豆子',
|
||
key: 'pulse',
|
||
align: 'center',
|
||
},
|
||
{
|
||
title: '赠送积分',
|
||
key: 'integral',
|
||
align: 'center',
|
||
},
|
||
{
|
||
title: '分佣类型',
|
||
slot: 'commission_type',
|
||
align: 'center',
|
||
render(row) {
|
||
return row.commission_type === 1 ? '百分比' : '数值'
|
||
},
|
||
},
|
||
{
|
||
title: '分佣比例',
|
||
key: 'commission',
|
||
align: 'center',
|
||
},
|
||
{
|
||
title: '商品状态',
|
||
slot: 'status',
|
||
align: 'center',
|
||
render(row) {
|
||
return row.status === 3 ? '待审核' : row.status === 1 ? '已审核' : '已拒绝'
|
||
},
|
||
},
|
||
{
|
||
title: '备注',
|
||
key: 'notes',
|
||
align: 'center',
|
||
},
|
||
{
|
||
title: '操作',
|
||
slot: 'action',
|
||
align: 'center',
|
||
render(row) {
|
||
let el = []
|
||
if (row.status === 3) {
|
||
el = [
|
||
h(
|
||
NSpace,
|
||
{
|
||
justify: 'center',
|
||
},
|
||
{
|
||
default: () => [
|
||
withDirectives(
|
||
h(
|
||
NButton,
|
||
{
|
||
type: 'primary',
|
||
text: true,
|
||
onClick: () => {
|
||
nowKey.value = 1
|
||
nowRow.value = { ...row }
|
||
veeify()
|
||
},
|
||
},
|
||
() => '审核通过'
|
||
),
|
||
[[vPerms, ['/admin/goods/process']]]
|
||
),
|
||
withDirectives(
|
||
h(
|
||
NButton,
|
||
{
|
||
type: 'error',
|
||
text: true,
|
||
onClick: () => {
|
||
nowKey.value = 2
|
||
nowRow.value = { ...row }
|
||
isNoteModel.value = true
|
||
},
|
||
},
|
||
() => '审核拒绝'
|
||
),
|
||
[[vPerms, ['/admin/goods/process']]]
|
||
),
|
||
withDirectives(
|
||
h(
|
||
NButton,
|
||
{
|
||
type: 'warning',
|
||
text: true,
|
||
onClick: () => {
|
||
nowKey.value = 3
|
||
goodInfo.value = { ...row }
|
||
showDrawer.value = true
|
||
},
|
||
},
|
||
() => '商品详情'
|
||
),
|
||
[[vPerms, ['/admin/goods/process']]]
|
||
),
|
||
],
|
||
}
|
||
),
|
||
]
|
||
} else {
|
||
el = [
|
||
withDirectives(
|
||
h(
|
||
NButton,
|
||
{
|
||
type: 'info',
|
||
text: true,
|
||
onClick: () => {
|
||
nowRow.value = { ...row }
|
||
nowKey.value = 3
|
||
isDzModel.value = true
|
||
},
|
||
},
|
||
{
|
||
default: () => '赠送/比例',
|
||
}
|
||
),
|
||
[[vPerms, ['/admin/goods/process']]]
|
||
),
|
||
]
|
||
}
|
||
|
||
return el
|
||
},
|
||
},
|
||
])
|
||
|
||
const data = ref([])
|
||
|
||
const pagination = ref({
|
||
page: 1,
|
||
pageSize: 10,
|
||
itemCount: 0,
|
||
onChange: (page) => {
|
||
pagination.value.page = page
|
||
getList()
|
||
},
|
||
onUpdatePageSize: (pageSize) => {
|
||
pagination.value.pageSize = pageSize
|
||
pagination.value.page = 1
|
||
getList()
|
||
},
|
||
})
|
||
|
||
onMounted(() => {
|
||
getList()
|
||
})
|
||
|
||
const getList = async () => {
|
||
loading.value = true
|
||
try {
|
||
const query_data = {
|
||
status: queryParams.value.status,
|
||
type: queryParams.value.type,
|
||
}
|
||
|
||
query_data[queryParams.value.selectKey === 0 ? 'name' : 'store_name'] = queryParams.value.word
|
||
|
||
const res = await api.getHotlist({
|
||
pageNum: pagination.value.page,
|
||
pageSize: pagination.value.pageSize,
|
||
...query_data,
|
||
})
|
||
data.value = res.data.data.sort((a, b) => b.status - a.status) || []
|
||
pagination.value.itemCount = res.data.total
|
||
} catch (error) {
|
||
$message.error(error.msg)
|
||
}
|
||
loading.value = false
|
||
}
|
||
|
||
const clear = () => {
|
||
isNoteModel.value = false
|
||
isDzModel.value = false
|
||
notesVal.value = ''
|
||
nowRow.value = {}
|
||
queryParams.value = {
|
||
selectKey: 0,
|
||
word: '',
|
||
type: '',
|
||
status: 0,
|
||
checkedRowKeysRef: [],
|
||
}
|
||
getList()
|
||
}
|
||
|
||
const veeify = async () => {
|
||
let data = {}
|
||
if (nowKey.value === 1 || nowKey.value === 2) {
|
||
data = {
|
||
gid: [nowRow.value.gid],
|
||
status: nowKey.value,
|
||
notes: notesVal.value,
|
||
}
|
||
await api.getHotStatus(data)
|
||
await getList()
|
||
clear()
|
||
} else {
|
||
formRef.value?.validate(async (errors) => {
|
||
if (!errors) {
|
||
data = {
|
||
...nowRow.value,
|
||
gid: [nowRow.value.gid],
|
||
}
|
||
await api.getHotStatus(data)
|
||
await getList()
|
||
clear()
|
||
}
|
||
})
|
||
}
|
||
}
|
||
|
||
const veeifys = async () => {
|
||
if (queryParams.value.checkedRowKeysRef.length === 0) return $message.info('没有选中商品')
|
||
await api.getHotStatus({
|
||
gid: queryParams.value.checkedRowKeysRef,
|
||
status: 1,
|
||
notes: '',
|
||
})
|
||
clear()
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped></style>
|