feate:新增套餐管理
This commit is contained in:
@@ -144,4 +144,86 @@ export const updateProductParameterValue = (data) => {
|
|||||||
'Content-Type':'multipart/form-data'
|
'Content-Type':'multipart/form-data'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**---------------------------------- */
|
||||||
|
/**商品套餐管理 */
|
||||||
|
|
||||||
|
/**获取商品套餐列表 */
|
||||||
|
export const getProductPlanList = (params) => {
|
||||||
|
return http2.get('/api/v1/admin/good/plan/list', {params: params})
|
||||||
|
}
|
||||||
|
/**获取商品套餐详情 */
|
||||||
|
export const getProductPlanDetail = (params) => {
|
||||||
|
return http2.get('/api/v1/admin/good/plan/detail', {params: params})
|
||||||
|
}
|
||||||
|
/**创建商品套餐 */
|
||||||
|
export const createProductPlan = (data) => {
|
||||||
|
return http2.post('/api/v1/admin/good/plan/create', data,{
|
||||||
|
headers:{
|
||||||
|
'Content-Type':'multipart/form-data'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/**更新商品套餐 */
|
||||||
|
export const updateProductPlan = (data) => {
|
||||||
|
return http2.post('/api/v1/admin/good/plan/update', data,{
|
||||||
|
headers:{
|
||||||
|
'Content-Type':'multipart/form-data'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/**删除商品套餐 */
|
||||||
|
export const deleteProductPlan = (params) => {
|
||||||
|
return http2.delete('/api/v1/admin/good/plan/delete', {params: params})
|
||||||
|
}
|
||||||
|
/**禁用商品套餐 */
|
||||||
|
export const disableProductPlan = (data) => {
|
||||||
|
return http2.post('/api/v1/admin/good/plan/disable', data,{
|
||||||
|
headers:{
|
||||||
|
'Content-Type':'multipart/form-data'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/**启用商品套餐 */
|
||||||
|
export const enableProductPlan = (data) => {
|
||||||
|
return http2.post('/api/v1/admin/good/plan/enable', data,{
|
||||||
|
headers:{
|
||||||
|
'Content-Type':'multipart/form-data'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**---------------------------------- */
|
||||||
|
/**商品分组标签管理 */
|
||||||
|
|
||||||
|
/**获取商品分组标签列表 */
|
||||||
|
export const getProductGroupTagList = (params) => {
|
||||||
|
return http2.get('/api/v1/admin/good/group_tag/list', {params: params})
|
||||||
|
}
|
||||||
|
/**获取商品分组标签详情 */
|
||||||
|
export const getProductGroupTagDetail = (params) => {
|
||||||
|
return http2.get('/api/v1/admin/good/group_tag/detail', {params: params})
|
||||||
|
}
|
||||||
|
/**创建商品分组标签 */
|
||||||
|
export const createProductGroupTag = (data) => {
|
||||||
|
return http2.post('/api/v1/admin/good/group_tag/create', data,{
|
||||||
|
headers:{
|
||||||
|
'Content-Type':'multipart/form-data'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/**更新商品分组标签 */
|
||||||
|
export const updateProductGroupTag = (data) => {
|
||||||
|
return http2.post('/api/v1/admin/good/group_tag/update', data,{
|
||||||
|
headers:{
|
||||||
|
'Content-Type':'multipart/form-data'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/**删除商品分组标签 */
|
||||||
|
export const deleteProductGroupTag = (params) => {
|
||||||
|
return http2.delete('/api/v1/admin/good/group_tag/delete', {params: params})
|
||||||
}
|
}
|
||||||
@@ -424,7 +424,7 @@ const fetchProductGroupList = async () => {
|
|||||||
try {
|
try {
|
||||||
const res = await getProductGroupList({
|
const res = await getProductGroupList({
|
||||||
page: 1,
|
page: 1,
|
||||||
count: 1000
|
count: 10
|
||||||
})
|
})
|
||||||
console.log('获取商品组列表:', res.data)
|
console.log('获取商品组列表:', res.data)
|
||||||
if (res.data.code === 200) {
|
if (res.data.code === 200) {
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -96,9 +96,10 @@
|
|||||||
</el-tag>
|
</el-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="操作" width="200" fixed="right">
|
<el-table-column label="操作" width="280" fixed="right">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<el-button type="primary" link @click="handleEdit(row)">编辑</el-button>
|
<el-button type="primary" link @click="handleEdit(row)">编辑</el-button>
|
||||||
|
<el-button type="success" link @click="handlePlan(row)">套餐</el-button>
|
||||||
<el-button type="warning" link @click="handleParameter(row)">参数</el-button>
|
<el-button type="warning" link @click="handleParameter(row)">参数</el-button>
|
||||||
<el-button type="danger" link @click="handleDelete(row)">删除</el-button>
|
<el-button type="danger" link @click="handleDelete(row)">删除</el-button>
|
||||||
</template>
|
</template>
|
||||||
@@ -162,19 +163,32 @@
|
|||||||
<el-form-item label="内容" prop="content">
|
<el-form-item label="内容" prop="content">
|
||||||
<el-input v-model="productForm.content" type="textarea" :rows="4" placeholder="请输入内容" />
|
<el-input v-model="productForm.content" type="textarea" :rows="4" placeholder="请输入内容" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="封面ID" prop="cover_id">
|
<el-form-item label="商品封面" prop="cover_id">
|
||||||
<div class="cover-selector">
|
<div class="recommend-user-selector">
|
||||||
<div class="cover-preview" v-if="productForm.cover_id && coverPreviewUrl">
|
<div class="cover-preview-inline" v-if="productForm.cover_id && coverPreviewUrl">
|
||||||
<el-image :src="coverPreviewUrl" fit="cover" style="width: 80px; height: 80px; border-radius: 4px;" />
|
<el-image :src="coverPreviewUrl" fit="cover" style="width: 40px; height: 40px; border-radius: 4px;" />
|
||||||
</div>
|
|
||||||
<div class="cover-actions">
|
|
||||||
<el-button type="primary" @click="openCoverSelector">
|
|
||||||
<el-icon><Picture /></el-icon>
|
|
||||||
{{ productForm.cover_id ? '更换封面' : '选择封面' }}
|
|
||||||
</el-button>
|
|
||||||
<el-button v-if="productForm.cover_id" @click="clearCover">清除</el-button>
|
|
||||||
<span v-if="productForm.cover_id" class="cover-id-text">ID: {{ productForm.cover_id }}</span>
|
|
||||||
</div>
|
</div>
|
||||||
|
<el-input
|
||||||
|
:model-value="productForm.cover_id ? `文件ID: ${productForm.cover_id}` : ''"
|
||||||
|
placeholder="点击选择封面图片"
|
||||||
|
readonly
|
||||||
|
@click="openCoverSelector"
|
||||||
|
>
|
||||||
|
<template #append>
|
||||||
|
<el-button @click="openCoverSelector">
|
||||||
|
<el-icon><Search /></el-icon>
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-input>
|
||||||
|
<el-button
|
||||||
|
v-if="productForm.cover_id"
|
||||||
|
type="danger"
|
||||||
|
link
|
||||||
|
@click="clearCover"
|
||||||
|
class="clear-btn"
|
||||||
|
>
|
||||||
|
清除
|
||||||
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
@@ -206,6 +220,14 @@
|
|||||||
<el-form-item label="推荐返还(%)" prop="recommend_rebate">
|
<el-form-item label="推荐返还(%)" prop="recommend_rebate">
|
||||||
<el-input-number v-model="productForm.recommend_rebate" :min="0" :max="100" placeholder="请输入返还百分比" style="width: 100%" />
|
<el-input-number v-model="productForm.recommend_rebate" :min="0" :max="100" placeholder="请输入返还百分比" style="width: 100%" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item label="参数类型" prop="arg_type">
|
||||||
|
<el-select v-model="productForm.arg_type" placeholder="请选择参数类型" style="width: 100%">
|
||||||
|
<el-option label="所有参数" value="all" />
|
||||||
|
<el-option label="套餐" value="plan" />
|
||||||
|
<el-option label="自定义" value="customize" />
|
||||||
|
</el-select>
|
||||||
|
<div class="form-tip">all: 所有参数 / plan: 套餐 / customize: 自定义</div>
|
||||||
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<el-button @click="dialogVisible = false">取消</el-button>
|
<el-button @click="dialogVisible = false">取消</el-button>
|
||||||
@@ -408,6 +430,122 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
|
<!-- 商品套餐管理对话框 -->
|
||||||
|
<el-dialog
|
||||||
|
v-model="planDialogVisible"
|
||||||
|
:title="`商品套餐管理 - ${currentPlanProductName}`"
|
||||||
|
width="900px"
|
||||||
|
append-to-body
|
||||||
|
>
|
||||||
|
<div class="plan-management">
|
||||||
|
<div class="plan-header">
|
||||||
|
<el-button type="primary" @click="handleAddPlan">
|
||||||
|
<el-icon><Plus /></el-icon>新增套餐
|
||||||
|
</el-button>
|
||||||
|
<el-button type="success" @click="fetchPlanList">
|
||||||
|
<el-icon><Refresh /></el-icon>刷新
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
<el-table
|
||||||
|
v-loading="planLoading"
|
||||||
|
:data="planList"
|
||||||
|
style="width: 100%"
|
||||||
|
:header-cell-style="{ background: '#f8f9fa', color: '#2c3e50', fontWeight: 600 }"
|
||||||
|
>
|
||||||
|
<el-table-column prop="id" label="ID" width="80" />
|
||||||
|
<el-table-column prop="name" label="套餐名称" min-width="120" />
|
||||||
|
<el-table-column label="参数配置" min-width="200">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<div v-if="row.argsParsed && row.argsParsed.length > 0" class="args-list">
|
||||||
|
<el-tag
|
||||||
|
v-for="(arg, index) in row.argsParsed"
|
||||||
|
:key="index"
|
||||||
|
size="small"
|
||||||
|
type="info"
|
||||||
|
style="margin-right: 4px; margin-bottom: 4px;"
|
||||||
|
>
|
||||||
|
{{ arg.name || arg.value || `参数${arg.arg_id}` }}
|
||||||
|
</el-tag>
|
||||||
|
</div>
|
||||||
|
<span v-else class="text-muted">-</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="note" label="说明" min-width="150" show-overflow-tooltip />
|
||||||
|
<el-table-column prop="index" label="排序" width="70" />
|
||||||
|
<el-table-column label="状态" width="80">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-tag :type="row.disable ? 'danger' : 'success'" size="small">
|
||||||
|
{{ row.disable ? '禁用' : '启用' }}
|
||||||
|
</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" width="180">
|
||||||
|
<template #default="{ row }">
|
||||||
|
<el-button type="primary" link @click="handleEditPlan(row)">编辑</el-button>
|
||||||
|
<el-button
|
||||||
|
:type="row.disable ? 'success' : 'warning'"
|
||||||
|
link
|
||||||
|
@click="handleTogglePlanStatus(row)"
|
||||||
|
>
|
||||||
|
{{ row.disable ? '启用' : '禁用' }}
|
||||||
|
</el-button>
|
||||||
|
<el-button type="danger" link @click="handleDeletePlan(row)">删除</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
|
<!-- 套餐表单对话框 -->
|
||||||
|
<el-dialog
|
||||||
|
v-model="planFormDialogVisible"
|
||||||
|
:title="planFormType === 'add' ? '新增套餐' : '编辑套餐'"
|
||||||
|
width="600px"
|
||||||
|
append-to-body
|
||||||
|
>
|
||||||
|
<el-form
|
||||||
|
ref="planFormRef"
|
||||||
|
:model="planForm"
|
||||||
|
:rules="planFormRules"
|
||||||
|
label-width="100px"
|
||||||
|
>
|
||||||
|
<el-form-item label="套餐名称" prop="name">
|
||||||
|
<el-input v-model="planForm.name" placeholder="请输入套餐名称" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="说明" prop="note">
|
||||||
|
<el-input v-model="planForm.note" type="textarea" :rows="3" placeholder="请输入套餐说明" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="参数配置" prop="args">
|
||||||
|
<el-input
|
||||||
|
v-model="planForm.args"
|
||||||
|
type="textarea"
|
||||||
|
:rows="4"
|
||||||
|
placeholder='JSON格式,如:[{"arg_id":1,"name":"参数名","attr_id":1,"value":"值"}]'
|
||||||
|
/>
|
||||||
|
<div class="form-tip">参数配置为JSON数组格式</div>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="额外参数" prop="extra_arg_ids">
|
||||||
|
<el-input v-model="planForm.extra_arg_ids" placeholder="额外参数ID,如:1,2,3" />
|
||||||
|
<div class="form-tip">多个参数ID用英文逗号分隔</div>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="排序索引" prop="index">
|
||||||
|
<el-input-number v-model="planForm.index" :min="0" style="width: 100%" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="状态" prop="disable" v-if="planFormType === 'edit'">
|
||||||
|
<el-radio-group v-model="planForm.disable">
|
||||||
|
<el-radio :value="false">启用</el-radio>
|
||||||
|
<el-radio :value="true">禁用</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<template #footer>
|
||||||
|
<div class="dialog-footer">
|
||||||
|
<el-button @click="planFormDialogVisible = false">取消</el-button>
|
||||||
|
<el-button type="primary" @click="submitPlanForm">确定</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -426,7 +564,14 @@ import { getProductList, createProduct, updateProduct, deleteProduct, getProduct
|
|||||||
deleteProductParameter,
|
deleteProductParameter,
|
||||||
addProductParameterValue,
|
addProductParameterValue,
|
||||||
updateProductParameterValue,
|
updateProductParameterValue,
|
||||||
deleteProductParameterValue
|
deleteProductParameterValue,
|
||||||
|
getProductPlanList,
|
||||||
|
getProductPlanDetail,
|
||||||
|
createProductPlan,
|
||||||
|
updateProductPlan,
|
||||||
|
deleteProductPlan,
|
||||||
|
disableProductPlan,
|
||||||
|
enableProductPlan
|
||||||
} from '@/api/admin/product'
|
} from '@/api/admin/product'
|
||||||
|
|
||||||
// 查询参数
|
// 查询参数
|
||||||
@@ -451,7 +596,8 @@ const productForm = reactive({
|
|||||||
pay_num: 1,
|
pay_num: 1,
|
||||||
expire_time: 0,
|
expire_time: 0,
|
||||||
recommend: false,
|
recommend: false,
|
||||||
recommend_rebate: 0
|
recommend_rebate: 0,
|
||||||
|
arg_type: 'all' // 商品参数类型 all/plan/customize
|
||||||
})
|
})
|
||||||
|
|
||||||
const productRules = {
|
const productRules = {
|
||||||
@@ -613,7 +759,8 @@ const handleAdd = () => {
|
|||||||
pay_num: 1,
|
pay_num: 1,
|
||||||
expire_time: 0,
|
expire_time: 0,
|
||||||
recommend: false,
|
recommend: false,
|
||||||
recommend_rebate: 0
|
recommend_rebate: 0,
|
||||||
|
arg_type: 'all'
|
||||||
})
|
})
|
||||||
productFormRef.value?.resetFields()
|
productFormRef.value?.resetFields()
|
||||||
}
|
}
|
||||||
@@ -637,7 +784,8 @@ const handleEdit = (row) => {
|
|||||||
pay_num: row.payNum,
|
pay_num: row.payNum,
|
||||||
expire_time: row.expireTime,
|
expire_time: row.expireTime,
|
||||||
recommend: row.recommend,
|
recommend: row.recommend,
|
||||||
recommend_rebate: row.recommendRebate
|
recommend_rebate: row.recommendRebate,
|
||||||
|
arg_type: row.argType || 'all'
|
||||||
})
|
})
|
||||||
// 加载封面预览
|
// 加载封面预览
|
||||||
loadCoverPreview(row.coverId)
|
loadCoverPreview(row.coverId)
|
||||||
@@ -732,7 +880,8 @@ const submitForm = () => {
|
|||||||
price: Math.round(productForm.price * 100) || 0, // 元转分
|
price: Math.round(productForm.price * 100) || 0, // 元转分
|
||||||
pay_num: productForm.pay_num || 1,
|
pay_num: productForm.pay_num || 1,
|
||||||
expire_time: productForm.expire_time || 0,
|
expire_time: productForm.expire_time || 0,
|
||||||
recommend_rebate: productForm.recommend_rebate || 0
|
recommend_rebate: productForm.recommend_rebate || 0,
|
||||||
|
arg_type: productForm.arg_type || 'all' // 商品参数类型
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('提交的数据:', submitData) // 调试日志
|
console.log('提交的数据:', submitData) // 调试日志
|
||||||
@@ -1091,6 +1240,219 @@ const submitParamValueForm = () => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ==================== 商品套餐管理 ====================
|
||||||
|
const planDialogVisible = ref(false)
|
||||||
|
const planLoading = ref(false)
|
||||||
|
const planList = ref([])
|
||||||
|
const currentPlanProductId = ref(null)
|
||||||
|
const currentPlanProductName = ref('')
|
||||||
|
|
||||||
|
// 套餐表单
|
||||||
|
const planFormDialogVisible = ref(false)
|
||||||
|
const planFormType = ref('add')
|
||||||
|
const planFormRef = ref(null)
|
||||||
|
const planForm = reactive({
|
||||||
|
plan_id: undefined,
|
||||||
|
name: '',
|
||||||
|
note: '',
|
||||||
|
args: '',
|
||||||
|
extra_arg_ids: '',
|
||||||
|
index: 0,
|
||||||
|
disable: false
|
||||||
|
})
|
||||||
|
|
||||||
|
const planFormRules = {
|
||||||
|
name: [{ required: true, message: '请输入套餐名称', trigger: 'blur' }]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 打开套餐管理
|
||||||
|
const handlePlan = (row) => {
|
||||||
|
currentPlanProductId.value = row.id
|
||||||
|
currentPlanProductName.value = row.name
|
||||||
|
planDialogVisible.value = true
|
||||||
|
fetchPlanList()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解析args JSON字符串
|
||||||
|
const parseArgs = (argsStr) => {
|
||||||
|
if (!argsStr) return []
|
||||||
|
try {
|
||||||
|
const parsed = JSON.parse(argsStr)
|
||||||
|
return Array.isArray(parsed) ? parsed : []
|
||||||
|
} catch (e) {
|
||||||
|
console.error('解析args失败:', e)
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式化显示args
|
||||||
|
const formatArgs = (argsParsed) => {
|
||||||
|
if (!argsParsed || argsParsed.length === 0) return '-'
|
||||||
|
return argsParsed.map(arg => arg.name || arg.value).filter(Boolean).join(', ')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取套餐列表
|
||||||
|
const fetchPlanList = async () => {
|
||||||
|
if (!currentPlanProductId.value) return
|
||||||
|
planLoading.value = true
|
||||||
|
try {
|
||||||
|
const res = await getProductPlanList({ good_id: String(currentPlanProductId.value) })
|
||||||
|
|
||||||
|
if (res.data.code === 200) {
|
||||||
|
// 兼容两种数据结构
|
||||||
|
let data = res.data.data
|
||||||
|
if (Array.isArray(data)) {
|
||||||
|
// 处理args字段,将JSON字符串解析为对象
|
||||||
|
planList.value = data.map(item => ({
|
||||||
|
...item,
|
||||||
|
argsParsed: parseArgs(item.args)
|
||||||
|
}))
|
||||||
|
} else if (data && data.list) {
|
||||||
|
planList.value = data.list.map(item => ({
|
||||||
|
...item,
|
||||||
|
argsParsed: parseArgs(item.args)
|
||||||
|
}))
|
||||||
|
} else if (data && data.data) {
|
||||||
|
planList.value = data.data.map(item => ({
|
||||||
|
...item,
|
||||||
|
argsParsed: parseArgs(item.args)
|
||||||
|
}))
|
||||||
|
} else {
|
||||||
|
planList.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取套餐列表失败:', error)
|
||||||
|
ElMessage.error('获取套餐列表失败')
|
||||||
|
} finally {
|
||||||
|
planLoading.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 新增套餐
|
||||||
|
const handleAddPlan = () => {
|
||||||
|
planFormType.value = 'add'
|
||||||
|
planFormDialogVisible.value = true
|
||||||
|
Object.assign(planForm, {
|
||||||
|
plan_id: undefined,
|
||||||
|
name: '',
|
||||||
|
note: '',
|
||||||
|
args: '',
|
||||||
|
extra_arg_ids: '',
|
||||||
|
index: 0,
|
||||||
|
disable: false
|
||||||
|
})
|
||||||
|
nextTick(() => {
|
||||||
|
planFormRef.value?.resetFields()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 编辑套餐
|
||||||
|
const handleEditPlan = async (row) => {
|
||||||
|
planFormType.value = 'edit'
|
||||||
|
try {
|
||||||
|
const res = await getProductPlanDetail({ good_id: String(currentPlanProductId.value), plan_id: String(row.id) })
|
||||||
|
if (res.data.code === 200) {
|
||||||
|
const data = res.data.data
|
||||||
|
// 处理args字段:如果是字符串先解析,再格式化为漂亮的JSON
|
||||||
|
let argsValue = ''
|
||||||
|
if (data.args) {
|
||||||
|
try {
|
||||||
|
// 如果args是字符串,先解析为对象
|
||||||
|
const argsObj = typeof data.args === 'string' ? JSON.parse(data.args) : data.args
|
||||||
|
// 格式化为漂亮的JSON(带缩进)
|
||||||
|
argsValue = JSON.stringify(argsObj, null, 2)
|
||||||
|
} catch (e) {
|
||||||
|
// 解析失败则保持原值
|
||||||
|
argsValue = data.args
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Object.assign(planForm, {
|
||||||
|
plan_id: data.id,
|
||||||
|
name: data.name || '',
|
||||||
|
note: data.note || '',
|
||||||
|
args: argsValue,
|
||||||
|
extra_arg_ids: data.extraArgIds ? data.extraArgIds.join(',') : '',
|
||||||
|
index: data.index || 0,
|
||||||
|
disable: data.disable || false
|
||||||
|
})
|
||||||
|
planFormDialogVisible.value = true
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
ElMessage.error('获取套餐详情失败')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除套餐
|
||||||
|
const handleDeletePlan = (row) => {
|
||||||
|
ElMessageBox.confirm(`确认删除套餐 ${row.name} 吗?`, '警告', {
|
||||||
|
confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning'
|
||||||
|
}).then(async () => {
|
||||||
|
try {
|
||||||
|
const res = await deleteProductPlan({ good_id: String(currentPlanProductId.value), plan_id: String(row.id) })
|
||||||
|
if (res.data.code === 200) {
|
||||||
|
ElMessage.success('删除成功')
|
||||||
|
fetchPlanList()
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
ElMessage.error('删除失败')
|
||||||
|
}
|
||||||
|
}).catch(() => {})
|
||||||
|
}
|
||||||
|
|
||||||
|
// 切换套餐状态
|
||||||
|
const handleTogglePlanStatus = async (row) => {
|
||||||
|
try {
|
||||||
|
const res = row.disable
|
||||||
|
? await enableProductPlan({ good_id: String(currentPlanProductId.value), plan_id: String(row.id) })
|
||||||
|
: await disableProductPlan({ good_id: String(currentPlanProductId.value), plan_id: String(row.id) })
|
||||||
|
if (res.data.code === 200) {
|
||||||
|
ElMessage.success(row.disable ? '启用成功' : '禁用成功')
|
||||||
|
fetchPlanList()
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
ElMessage.error('操作失败')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提交套餐表单
|
||||||
|
const submitPlanForm = () => {
|
||||||
|
planFormRef.value?.validate(async (valid) => {
|
||||||
|
if (valid) {
|
||||||
|
try {
|
||||||
|
const submitData = {
|
||||||
|
good_id: String(currentPlanProductId.value),
|
||||||
|
name: planForm.name,
|
||||||
|
note: planForm.note || '',
|
||||||
|
args: planForm.args || '',
|
||||||
|
extra_arg_ids: planForm.extra_arg_ids || '',
|
||||||
|
index: Number(planForm.index) || 0
|
||||||
|
}
|
||||||
|
|
||||||
|
let res
|
||||||
|
if (planFormType.value === 'add') {
|
||||||
|
res = await createProductPlan(submitData)
|
||||||
|
} else {
|
||||||
|
submitData.plan_id = String(planForm.plan_id)
|
||||||
|
submitData.disable = planForm.disable
|
||||||
|
res = await updateProductPlan(submitData)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res.data.code === 200) {
|
||||||
|
ElMessage.success(planFormType.value === 'add' ? '新增成功' : '修改成功')
|
||||||
|
planFormDialogVisible.value = false
|
||||||
|
fetchPlanList()
|
||||||
|
} else {
|
||||||
|
ElMessage.error(res.data.message || '操作失败')
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('套餐操作失败:', error)
|
||||||
|
ElMessage.error(error.response?.data?.message || '操作失败')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
@@ -1269,5 +1631,28 @@ const submitParamValueForm = () => {
|
|||||||
color: #909399;
|
color: #909399;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 套餐管理样式 */
|
||||||
|
.plan-management {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.plan-header {
|
||||||
|
display: flex;
|
||||||
|
gap: 12px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-tip {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #909399;
|
||||||
|
margin-top: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.args-list {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 4px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|||||||
@@ -1,104 +0,0 @@
|
|||||||
{
|
|
||||||
"openapi": "3.0.1",
|
|
||||||
"info": {
|
|
||||||
"title": "默认模块",
|
|
||||||
"description": "",
|
|
||||||
"version": "1.0.0"
|
|
||||||
},
|
|
||||||
"tags": [],
|
|
||||||
"paths": {
|
|
||||||
"/api/v1/admin/user/user/update": {
|
|
||||||
"post": {
|
|
||||||
"summary": "更新用户信息",
|
|
||||||
"deprecated": false,
|
|
||||||
"description": "",
|
|
||||||
"tags": [],
|
|
||||||
"parameters": [
|
|
||||||
{
|
|
||||||
"name": "Authorization",
|
|
||||||
"in": "header",
|
|
||||||
"description": "",
|
|
||||||
"example": "Bearer {{token}}",
|
|
||||||
"schema": {
|
|
||||||
"type": "string",
|
|
||||||
"default": "Bearer {{token}}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"requestBody": {
|
|
||||||
"content": {
|
|
||||||
"multipart/form-data": {
|
|
||||||
"schema": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"user_id": {
|
|
||||||
"description": "用户ID",
|
|
||||||
"example": "",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"sex": {
|
|
||||||
"description": "性别 true 男 false 女",
|
|
||||||
"example": "",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"age": {
|
|
||||||
"description": "年龄",
|
|
||||||
"example": "",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"cover_id": {
|
|
||||||
"description": "头像id",
|
|
||||||
"example": "",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"user_name": {
|
|
||||||
"description": "用户名",
|
|
||||||
"example": "",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"recommend_id": {
|
|
||||||
"description": "推介用户id",
|
|
||||||
"example": "",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"phone": {
|
|
||||||
"description": "手机号码",
|
|
||||||
"example": "",
|
|
||||||
"type": "string"
|
|
||||||
},
|
|
||||||
"email": {
|
|
||||||
"description": "邮箱",
|
|
||||||
"example": "",
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"responses": {
|
|
||||||
"200": {
|
|
||||||
"description": "",
|
|
||||||
"content": {
|
|
||||||
"application/json": {
|
|
||||||
"schema": {
|
|
||||||
"type": "object",
|
|
||||||
"properties": {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"headers": {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"security": []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"components": {
|
|
||||||
"schemas": {},
|
|
||||||
"responses": {},
|
|
||||||
"securitySchemes": {}
|
|
||||||
},
|
|
||||||
"servers": [],
|
|
||||||
"security": []
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user