fix:修复部分显示问题
This commit is contained in:
1 parent
875aac6771
commit
6ae3b1e35b
9 files changed
+1067
-1002
No files matched your search
@@ -31,7 +31,7 @@
|
||||
</el-col>
|
||||
|
||||
<el-col :span="12" class="mb20">
|
||||
<el-form-item label="状态(0正常,1下架)" prop="status">
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-radio-group v-model="form.status">
|
||||
<el-radio :label="item.value" v-for="(item, index) in status" border :key="index">{{ item.label }} </el-radio>
|
||||
</el-radio-group>
|
||||
|
||||
@@ -1,84 +1,109 @@
|
||||
<template>
|
||||
<div class="layout-padding">
|
||||
<div class="layout-padding-auto layout-padding-view">
|
||||
<el-row v-show="showSearch">
|
||||
<el-form :model="state.queryForm" ref="queryRef" :inline="true" @keyup.enter="getDataList">
|
||||
<el-form-item label="分类名称" prop="name" >
|
||||
<el-input placeholder="请输入分类名称" v-model="state.queryForm.name" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button icon="search" type="primary" @click="getDataList">
|
||||
查询
|
||||
</el-button>
|
||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<div class="mb8" style="width: 100%">
|
||||
<el-button icon="folder-add" type="primary" class="ml10" @click="formDialogRef.openDialog()"
|
||||
v-auth="'supermarket_mallCategory_add'">
|
||||
新 增
|
||||
</el-button>
|
||||
<el-button plain :disabled="multiple" icon="Delete" type="primary"
|
||||
v-auth="'supermarket_mallCategory_del'" @click="handleDelete(selectObjs)">
|
||||
删除
|
||||
</el-button>
|
||||
<right-toolbar v-model:showSearch="showSearch" :export="'supermarket_mallCategory_export'"
|
||||
@exportExcel="exportExcel" class="ml10 mr20" style="float: right;"
|
||||
@queryTable="getDataList"></right-toolbar>
|
||||
</div>
|
||||
</el-row>
|
||||
<el-table
|
||||
:data="treeData"
|
||||
row-key="id"
|
||||
:tree-props="{ children: 'children' }"
|
||||
v-loading="state.loading"
|
||||
border
|
||||
:cell-style="tableStyle.cellStyle"
|
||||
:header-cell-style="tableStyle.headerCellStyle"
|
||||
@selection-change="selectionChangHandle"
|
||||
@sort-change="sortChangeHandle"
|
||||
>
|
||||
<el-table-column type="selection" width="40" align="center" />
|
||||
<el-table-column type="index" label="#" width="40" />
|
||||
<el-table-column prop="name" label="分类名称" show-overflow-tooltip/>
|
||||
<el-table-column prop="sort" label="排序" show-overflow-tooltip/>
|
||||
<el-table-column prop="status" label="状态(0正常,1下架)" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<dict-tag :options="status" :value="scope.row.status"></dict-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="picUrl" label="分类图片" show-overflow-tooltip/>
|
||||
<el-table-column label="操作" width="150">
|
||||
<template #default="scope">
|
||||
<el-button icon="edit-pen" text type="primary" v-auth="'supermarket_mallCategory_edit'"
|
||||
@click="formDialogRef.openDialog(scope.row.id)">编辑</el-button>
|
||||
<el-button icon="delete" text type="primary" v-auth="'supermarket_mallCategory_del'" @click="handleDelete([scope.row.id])">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- <pagination @size-change="sizeChangeHandle" @current-change="currentChangeHandle" v-bind="state.pagination" /> -->
|
||||
</div>
|
||||
<div class="layout-padding">
|
||||
<div class="layout-padding-auto layout-padding-view">
|
||||
<el-row v-show="showSearch">
|
||||
<el-form :model="state.queryForm" ref="queryRef" :inline="true" @keyup.enter="getDataList">
|
||||
<el-form-item label="分类名称" prop="name">
|
||||
<el-input placeholder="请输入分类名称" v-model="state.queryForm.name" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button icon="search" type="primary" @click="getDataList"> 查询 </el-button>
|
||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<div class="mb8" style="width: 100%">
|
||||
<el-button
|
||||
icon="folder-add"
|
||||
type="primary"
|
||||
class="ml10"
|
||||
@click="formDialogRef.openDialog()"
|
||||
v-auth="'supermarket_mallCategory_add'"
|
||||
>
|
||||
新 增
|
||||
</el-button>
|
||||
<el-button
|
||||
plain
|
||||
:disabled="multiple"
|
||||
icon="Delete"
|
||||
type="primary"
|
||||
v-auth="'supermarket_mallCategory_del'"
|
||||
@click="handleDelete(selectObjs)"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
<right-toolbar
|
||||
v-model:showSearch="showSearch"
|
||||
:export="'supermarket_mallCategory_export'"
|
||||
@exportExcel="exportExcel"
|
||||
class="ml10 mr20"
|
||||
style="float: right"
|
||||
@queryTable="getDataList"
|
||||
></right-toolbar>
|
||||
</div>
|
||||
</el-row>
|
||||
<el-table
|
||||
:data="treeData"
|
||||
row-key="id"
|
||||
:tree-props="{ children: 'children' }"
|
||||
v-loading="state.loading"
|
||||
border
|
||||
:cell-style="tableStyle.cellStyle"
|
||||
:header-cell-style="tableStyle.headerCellStyle"
|
||||
@selection-change="selectionChangHandle"
|
||||
@sort-change="sortChangeHandle"
|
||||
>
|
||||
<el-table-column type="selection" width="50" align="center" />
|
||||
<el-table-column type="index" label="#" width="40" />
|
||||
<el-table-column prop="name" label="分类名称" show-overflow-tooltip />
|
||||
<el-table-column prop="sort" label="排序" show-overflow-tooltip />
|
||||
<el-table-column prop="status" label="状态" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<dict-tag :options="status" :value="scope.row.status"></dict-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="picUrl" label="分类图片" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<preview-image :src="scope.row.picUrl" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="150">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
icon="edit-pen"
|
||||
text
|
||||
type="primary"
|
||||
v-auth="'supermarket_mallCategory_edit'"
|
||||
@click="formDialogRef.openDialog(scope.row.id)"
|
||||
>编辑</el-button
|
||||
>
|
||||
<el-button icon="delete" text type="primary" v-auth="'supermarket_mallCategory_del'" @click="handleDelete([scope.row.id])"
|
||||
>删除</el-button
|
||||
>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- <pagination @size-change="sizeChangeHandle" @current-change="currentChangeHandle" v-bind="state.pagination" /> -->
|
||||
</div>
|
||||
|
||||
<!-- 编辑、新增 -->
|
||||
<form-dialog ref="formDialogRef" @refresh="getDataList()" />
|
||||
|
||||
</div>
|
||||
<!-- 编辑、新增 -->
|
||||
<form-dialog ref="formDialogRef" @refresh="getDataList()" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="systemMallCategory">
|
||||
import { BasicTableProps, useTable } from "/@/hooks/table";
|
||||
import { fetchList, delObjs, tree as fetchTree, putObj } from "/@/api/supermarket/mallCategory";
|
||||
import { useMessage, useMessageBox } from "/@/hooks/message";
|
||||
import { useDict } from '/@/hooks/dict';
|
||||
import { ref, reactive, onMounted, defineExpose } from 'vue';
|
||||
import { BasicTableProps, useTable } from "/@/hooks/table"
|
||||
import { fetchList, delObjs, tree as fetchTree, putObj } from "/@/api/supermarket/mallCategory"
|
||||
import { useMessage, useMessageBox } from "/@/hooks/message"
|
||||
import { useDict } from "/@/hooks/dict"
|
||||
import { ref, reactive, onMounted, defineExpose } from "vue"
|
||||
|
||||
// 引入组件
|
||||
const FormDialog = defineAsyncComponent(() => import('./form.vue'));
|
||||
const FormDialog = defineAsyncComponent(() => import("./form.vue"))
|
||||
// 定义查询字典
|
||||
|
||||
const { status } = useDict('status')
|
||||
const { status } = useDict("status")
|
||||
// 定义变量内容
|
||||
const formDialogRef = ref()
|
||||
// 搜索变量
|
||||
@@ -89,91 +114,85 @@ const selectObjs = ref([]) as any
|
||||
const multiple = ref(true)
|
||||
|
||||
const state: BasicTableProps = reactive<BasicTableProps>({
|
||||
queryForm: {},
|
||||
pageList: fetchList,
|
||||
loading: false,
|
||||
pagination: { total: 0 }
|
||||
queryForm: {},
|
||||
pageList: fetchList,
|
||||
loading: false,
|
||||
pagination: { total: 0 },
|
||||
})
|
||||
|
||||
const treeData = ref<any[]>([])
|
||||
|
||||
function listToTree(list: any[]): any[] {
|
||||
const map = new Map<string, any>();
|
||||
list.forEach((item: any) => {
|
||||
item.children = [];
|
||||
map.set(item.id, item);
|
||||
});
|
||||
const tree: any[] = [];
|
||||
list.forEach((item: any) => {
|
||||
if (item.parentId && item.parentId !== '0' && map.has(item.parentId)) {
|
||||
map.get(item.parentId).children.push(item);
|
||||
} else {
|
||||
tree.push(item);
|
||||
}
|
||||
});
|
||||
return tree;
|
||||
const map = new Map<string, any>()
|
||||
list.forEach((item: any) => {
|
||||
item.children = []
|
||||
map.set(item.id, item)
|
||||
})
|
||||
const tree: any[] = []
|
||||
list.forEach((item: any) => {
|
||||
if (item.parentId && item.parentId !== "0" && map.has(item.parentId)) {
|
||||
map.get(item.parentId).children.push(item)
|
||||
} else {
|
||||
tree.push(item)
|
||||
}
|
||||
})
|
||||
return tree
|
||||
}
|
||||
|
||||
const getDataList = async () => {
|
||||
state.loading = true;
|
||||
try {
|
||||
const res = await fetchTree();
|
||||
treeData.value = res.data || [];
|
||||
(state.pagination as any).total = Array.isArray(res.data) ? res.data.length : 0;
|
||||
} finally {
|
||||
state.loading = false;
|
||||
}
|
||||
state.loading = true
|
||||
try {
|
||||
const res = await fetchTree()
|
||||
treeData.value = res.data || []
|
||||
;(state.pagination as any).total = Array.isArray(res.data) ? res.data.length : 0
|
||||
} finally {
|
||||
state.loading = false
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
getDataList();
|
||||
getDataList()
|
||||
})
|
||||
|
||||
// table hook
|
||||
const {
|
||||
currentChangeHandle,
|
||||
sizeChangeHandle,
|
||||
sortChangeHandle,
|
||||
downBlobFile,
|
||||
tableStyle
|
||||
} = useTable(state)
|
||||
const { currentChangeHandle, sizeChangeHandle, sortChangeHandle, downBlobFile, tableStyle } = useTable(state)
|
||||
|
||||
// 清空搜索条件
|
||||
const resetQuery = () => {
|
||||
queryRef.value?.resetFields()
|
||||
selectObjs.value = []
|
||||
getDataList()
|
||||
queryRef.value?.resetFields()
|
||||
selectObjs.value = []
|
||||
getDataList()
|
||||
}
|
||||
|
||||
// 导出excel
|
||||
const exportExcel = () => {
|
||||
downBlobFile('/supermarket/mallCategory/export', Object.assign(state.queryForm, { ids: selectObjs }), 'mallCategory.xlsx')
|
||||
downBlobFile("/supermarket/mallCategory/export", Object.assign(state.queryForm, { ids: selectObjs }), "mallCategory.xlsx")
|
||||
}
|
||||
|
||||
// 多选事件
|
||||
const selectionChangHandle = (objs: { id: string }[]) => {
|
||||
selectObjs.value = objs.map(({ id }) => id);
|
||||
multiple.value = !objs.length;
|
||||
};
|
||||
selectObjs.value = objs.map(({ id }) => id)
|
||||
multiple.value = !objs.length
|
||||
}
|
||||
|
||||
// 删除操作
|
||||
const handleDelete = async (ids: string[]) => {
|
||||
try {
|
||||
await useMessageBox().confirm('此操作将永久删除');
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await useMessageBox().confirm("此操作将永久删除")
|
||||
} catch {
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
await delObjs(ids);
|
||||
getDataList();
|
||||
useMessage().success('删除成功');
|
||||
} catch (err: any) {
|
||||
useMessage().error(err.msg);
|
||||
}
|
||||
};
|
||||
try {
|
||||
await delObjs(ids)
|
||||
getDataList()
|
||||
useMessage().success("删除成功")
|
||||
} catch (err: any) {
|
||||
useMessage().error(err.msg)
|
||||
}
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
treeData
|
||||
});
|
||||
treeData,
|
||||
})
|
||||
</script>
|
||||
@@ -75,7 +75,7 @@
|
||||
|
||||
<el-col :span="12" class="mb20">
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="form.remark" placeholder="请输入备注" />
|
||||
<el-input type="textarea" v-model="form.remark" placeholder="请输入备注" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
@@ -1,96 +1,125 @@
|
||||
<template>
|
||||
<div class="layout-padding">
|
||||
<div class="layout-padding-auto layout-padding-view">
|
||||
<el-row v-show="showSearch">
|
||||
<el-form :model="state.queryForm" ref="queryRef" :inline="true" @keyup.enter="getDataList">
|
||||
<el-form-item label="商户名称" prop="name" >
|
||||
<el-input placeholder="请输入商户名称" v-model="state.queryForm.name" />
|
||||
</el-form-item>
|
||||
<el-form-item label="联系人" prop="contactName" >
|
||||
<el-input placeholder="请输入联系人" v-model="state.queryForm.contactName" />
|
||||
</el-form-item>
|
||||
<el-form-item label="联系电话" prop="contactPhone" >
|
||||
<el-input placeholder="请输入联系电话" v-model="state.queryForm.contactPhone" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button icon="search" type="primary" @click="getDataList">
|
||||
查询
|
||||
</el-button>
|
||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<div class="mb8" style="width: 100%">
|
||||
<el-button icon="folder-add" type="primary" class="ml10" @click="formDialogRef.openDialog()"
|
||||
v-auth="'supermarket_mallMerchant_add'">
|
||||
新 增
|
||||
</el-button>
|
||||
<el-button plain :disabled="multiple" icon="Delete" type="primary"
|
||||
v-auth="'supermarket_mallMerchant_del'" @click="handleDelete(selectObjs)">
|
||||
删除
|
||||
</el-button>
|
||||
<right-toolbar v-model:showSearch="showSearch" :export="'supermarket_mallMerchant_export'"
|
||||
@exportExcel="exportExcel" class="ml10 mr20" style="float: right;"
|
||||
@queryTable="getDataList"></right-toolbar>
|
||||
</div>
|
||||
</el-row>
|
||||
<el-table :data="state.dataList" v-loading="state.loading" border
|
||||
:cell-style="tableStyle.cellStyle" :header-cell-style="tableStyle.headerCellStyle"
|
||||
<div class="layout-padding">
|
||||
<div class="layout-padding-auto layout-padding-view">
|
||||
<el-row v-show="showSearch">
|
||||
<el-form :model="state.queryForm" ref="queryRef" :inline="true" @keyup.enter="getDataList">
|
||||
<el-form-item label="商户名称" prop="name">
|
||||
<el-input placeholder="请输入商户名称" v-model="state.queryForm.name" />
|
||||
</el-form-item>
|
||||
<el-form-item label="联系人" prop="contactName">
|
||||
<el-input placeholder="请输入联系人" v-model="state.queryForm.contactName" />
|
||||
</el-form-item>
|
||||
<el-form-item label="联系电话" prop="contactPhone">
|
||||
<el-input placeholder="请输入联系电话" v-model="state.queryForm.contactPhone" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button icon="search" type="primary" @click="getDataList"> 查询 </el-button>
|
||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<div class="mb8" style="width: 100%">
|
||||
<el-button
|
||||
icon="folder-add"
|
||||
type="primary"
|
||||
class="ml10"
|
||||
@click="formDialogRef.openDialog()"
|
||||
v-auth="'supermarket_mallMerchant_add'"
|
||||
>
|
||||
新 增
|
||||
</el-button>
|
||||
<el-button
|
||||
plain
|
||||
:disabled="multiple"
|
||||
icon="Delete"
|
||||
type="primary"
|
||||
v-auth="'supermarket_mallMerchant_del'"
|
||||
@click="handleDelete(selectObjs)"
|
||||
>
|
||||
删 除
|
||||
</el-button>
|
||||
<right-toolbar
|
||||
v-model:showSearch="showSearch"
|
||||
:export="'supermarket_mallMerchant_export'"
|
||||
@exportExcel="exportExcel"
|
||||
class="ml10 mr20"
|
||||
style="float: right"
|
||||
@queryTable="getDataList"
|
||||
></right-toolbar>
|
||||
</div>
|
||||
</el-row>
|
||||
<el-table
|
||||
:data="state.dataList"
|
||||
v-loading="state.loading"
|
||||
border
|
||||
:cell-style="tableStyle.cellStyle"
|
||||
:header-cell-style="tableStyle.headerCellStyle"
|
||||
@selection-change="selectionChangHandle"
|
||||
@sort-change="sortChangeHandle">
|
||||
<el-table-column type="selection" width="40" align="center" />
|
||||
<el-table-column type="index" label="#" width="40" />
|
||||
<el-table-column prop="name" label="商户名称" show-overflow-tooltip/>
|
||||
<el-table-column prop="shortName" label="商户简称" show-overflow-tooltip/>
|
||||
<el-table-column prop="contactName" label="联系人" show-overflow-tooltip/>
|
||||
<el-table-column prop="contactPhone" label="联系电话" show-overflow-tooltip/>
|
||||
<el-table-column prop="businessHours" label="营业时间" show-overflow-tooltip/>
|
||||
<!-- <el-table-column prop="email" label="邮箱" show-overflow-tooltip/>-->
|
||||
<el-table-column prop="status" label="状态" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<dict-tag :options="common_data_status" :value="scope.row.status"></dict-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="licenseNo" label="营业执照号" show-overflow-tooltip/>
|
||||
<el-table-column prop="address" label="详细地址" show-overflow-tooltip/>
|
||||
<el-table-column prop="images" label="商户图片" show-overflow-tooltip/>
|
||||
<el-table-column prop="remark" label="备注" show-overflow-tooltip/>
|
||||
<el-table-column label="操作" width="200">
|
||||
<template #default="scope">
|
||||
<el-button icon="edit-pen" text type="primary" v-auth="'supermarket_mallMerchant_edit'"
|
||||
@click="formDialogRef.openDialog(scope.row.id)">编辑</el-button>
|
||||
<el-button icon="user" text type="success"
|
||||
@click="handleBindUsers(scope.row)">绑定用户</el-button>
|
||||
<el-button icon="delete" text type="primary" v-auth="'supermarket_mallMerchant_del'" @click="handleDelete([scope.row.id])">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<pagination @size-change="sizeChangeHandle" @current-change="currentChangeHandle" v-bind="state.pagination" />
|
||||
</div>
|
||||
@sort-change="sortChangeHandle"
|
||||
>
|
||||
<el-table-column type="selection" width="40" align="center" />
|
||||
<el-table-column type="index" label="#" width="40" />
|
||||
<el-table-column prop="name" label="商户名称" show-overflow-tooltip />
|
||||
<el-table-column prop="shortName" label="商户简称" show-overflow-tooltip />
|
||||
<el-table-column prop="contactName" label="联系人" show-overflow-tooltip />
|
||||
<el-table-column prop="contactPhone" label="联系电话" show-overflow-tooltip />
|
||||
<el-table-column prop="businessHours" label="营业时间" show-overflow-tooltip />
|
||||
<!-- <el-table-column prop="email" label="邮箱" show-overflow-tooltip/>-->
|
||||
<el-table-column prop="status" label="状态" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<dict-tag :options="common_data_status" :value="scope.row.status"></dict-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="licenseNo" label="营业执照号" show-overflow-tooltip />
|
||||
<el-table-column prop="address" label="详细地址" show-overflow-tooltip />
|
||||
<el-table-column prop="images" label="商户图片" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<preview-image :src="scope.row.images" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="remark" label="备注" show-overflow-tooltip />
|
||||
<el-table-column label="操作" width="200">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
icon="edit-pen"
|
||||
text
|
||||
type="primary"
|
||||
v-auth="'supermarket_mallMerchant_edit'"
|
||||
@click="formDialogRef.openDialog(scope.row.id)"
|
||||
>编辑</el-button
|
||||
>
|
||||
<el-button icon="user" text type="success" @click="handleBindUsers(scope.row)">绑定用户</el-button>
|
||||
<el-button icon="delete" text type="primary" v-auth="'supermarket_mallMerchant_del'" @click="handleDelete([scope.row.id])"
|
||||
>删除</el-button
|
||||
>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<pagination @size-change="sizeChangeHandle" @current-change="currentChangeHandle" v-bind="state.pagination" />
|
||||
</div>
|
||||
|
||||
<!-- 编辑、新增 -->
|
||||
<form-dialog ref="formDialogRef" @refresh="getDataList(false)" />
|
||||
<!-- 编辑、新增 -->
|
||||
<form-dialog ref="formDialogRef" @refresh="getDataList(false)" />
|
||||
|
||||
<!-- 绑定用户对话框 -->
|
||||
<bind-user-dialog ref="bindUserDialogRef" @refresh="getDataList(false)" />
|
||||
|
||||
</div>
|
||||
<!-- 绑定用户对话框 -->
|
||||
<bind-user-dialog ref="bindUserDialogRef" @refresh="getDataList(false)" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="systemMallMerchant">
|
||||
import { defineAsyncComponent } from 'vue';
|
||||
import { BasicTableProps, useTable } from "/@/hooks/table";
|
||||
import { fetchList, delObjs } from "/@/api/supermarket/mallMerchant";
|
||||
import { useMessage, useMessageBox } from "/@/hooks/message";
|
||||
import { useDict } from '/@/hooks/dict';
|
||||
import { defineAsyncComponent } from "vue"
|
||||
import { BasicTableProps, useTable } from "/@/hooks/table"
|
||||
import { fetchList, delObjs } from "/@/api/supermarket/mallMerchant"
|
||||
import { useMessage, useMessageBox } from "/@/hooks/message"
|
||||
import { useDict } from "/@/hooks/dict"
|
||||
|
||||
// 引入组件
|
||||
const FormDialog = defineAsyncComponent(() => import('./form.vue'));
|
||||
const BindUserDialog = defineAsyncComponent(() => import('./bindUser.vue'));
|
||||
const FormDialog = defineAsyncComponent(() => import("./form.vue"))
|
||||
const BindUserDialog = defineAsyncComponent(() => import("./bindUser.vue"))
|
||||
// 定义查询字典
|
||||
|
||||
const { common_data_status } = useDict('common_data_status')
|
||||
const { common_data_status } = useDict("common_data_status")
|
||||
// 定义变量内容
|
||||
const formDialogRef = ref()
|
||||
const bindUserDialogRef = ref()
|
||||
@@ -102,59 +131,52 @@ const selectObjs = ref([]) as any
|
||||
const multiple = ref(true)
|
||||
|
||||
const state: BasicTableProps = reactive<BasicTableProps>({
|
||||
queryForm: {},
|
||||
pageList: fetchList
|
||||
queryForm: {},
|
||||
pageList: fetchList,
|
||||
})
|
||||
|
||||
// table hook
|
||||
const {
|
||||
getDataList,
|
||||
currentChangeHandle,
|
||||
sizeChangeHandle,
|
||||
sortChangeHandle,
|
||||
downBlobFile,
|
||||
tableStyle
|
||||
} = useTable(state)
|
||||
const { getDataList, currentChangeHandle, sizeChangeHandle, sortChangeHandle, downBlobFile, tableStyle } = useTable(state)
|
||||
|
||||
// 清空搜索条件
|
||||
const resetQuery = () => {
|
||||
// 清空搜索条件
|
||||
queryRef.value?.resetFields()
|
||||
// 清空多选
|
||||
selectObjs.value = []
|
||||
getDataList()
|
||||
// 清空搜索条件
|
||||
queryRef.value?.resetFields()
|
||||
// 清空多选
|
||||
selectObjs.value = []
|
||||
getDataList()
|
||||
}
|
||||
|
||||
// 导出excel
|
||||
const exportExcel = () => {
|
||||
downBlobFile('/supermarket/mallMerchant/export', Object.assign(state.queryForm, { ids: selectObjs }), 'mallMerchant.xlsx')
|
||||
downBlobFile("/supermarket/mallMerchant/export", Object.assign(state.queryForm, { ids: selectObjs }), "mallMerchant.xlsx")
|
||||
}
|
||||
|
||||
// 多选事件
|
||||
const selectionChangHandle = (objs: { id: string }[]) => {
|
||||
selectObjs.value = objs.map(({ id }) => id);
|
||||
multiple.value = !objs.length;
|
||||
};
|
||||
selectObjs.value = objs.map(({ id }) => id)
|
||||
multiple.value = !objs.length
|
||||
}
|
||||
|
||||
// 删除操作
|
||||
const handleDelete = async (ids: string[]) => {
|
||||
try {
|
||||
await useMessageBox().confirm('此操作将永久删除');
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await useMessageBox().confirm("此操作将永久删除")
|
||||
} catch {
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
await delObjs(ids);
|
||||
getDataList();
|
||||
useMessage().success('删除成功');
|
||||
} catch (err: any) {
|
||||
useMessage().error(err.msg);
|
||||
}
|
||||
};
|
||||
try {
|
||||
await delObjs(ids)
|
||||
getDataList()
|
||||
useMessage().success("删除成功")
|
||||
} catch (err: any) {
|
||||
useMessage().error(err.msg)
|
||||
}
|
||||
}
|
||||
|
||||
// 绑定用户操作
|
||||
const handleBindUsers = (merchant: any) => {
|
||||
bindUserDialogRef.value?.openDialog(merchant);
|
||||
};
|
||||
bindUserDialogRef.value?.openDialog(merchant)
|
||||
}
|
||||
</script>
|
||||
@@ -1,590 +1,562 @@
|
||||
<template>
|
||||
<el-dialog :title="form.id ? '编辑商品' : '新增商品'" v-model="visible"
|
||||
:close-on-click-modal="false" draggable width="90%">
|
||||
<el-form ref="dataFormRef" :model="form" :rules="dataRules" formDialogRef label-width="120px" v-loading="loading">
|
||||
<!-- 基本信息 -->
|
||||
<el-tabs v-model="activeTab" type="border-card">
|
||||
<el-tab-pane label="基本信息" name="basic">
|
||||
<el-row :gutter="24">
|
||||
<el-col :span="12" class="mb20">
|
||||
<el-form-item label="商户" prop="merchantId" required>
|
||||
<el-select v-model="form.merchantId" placeholder="请选择商户" clearable @change="onMerchantChange">
|
||||
<el-option
|
||||
v-for="merchant in merchantOptions"
|
||||
:key="merchant.value"
|
||||
:label="merchant.label"
|
||||
:value="merchant.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-dialog :title="form.id ? '编辑商品' : '新增商品'" v-model="visible" :close-on-click-modal="false" draggable width="90%">
|
||||
<el-form ref="dataFormRef" :model="form" :rules="dataRules" formDialogRef label-width="120px" v-loading="loading">
|
||||
<!-- 基本信息 -->
|
||||
<el-tabs v-model="activeTab" type="border-card">
|
||||
<el-tab-pane label="基本信息" name="basic">
|
||||
<el-row :gutter="24">
|
||||
<el-col :span="12" class="mb20">
|
||||
<el-form-item label="商户" prop="merchantId" required>
|
||||
<el-select v-model="form.merchantId" placeholder="请选择商户" clearable @change="onMerchantChange">
|
||||
<el-option v-for="merchant in merchantOptions" :key="merchant.value" :label="merchant.label" :value="merchant.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="12" class="mb20">
|
||||
<el-form-item label="商品分类" prop="categoryId" required>
|
||||
<el-cascader
|
||||
v-model="form.categoryId"
|
||||
:options="categoryOptions"
|
||||
:props="{ value: 'id', label: 'name', children: 'children', checkStrictly: true }"
|
||||
:disabled="!form.merchantId"
|
||||
clearable
|
||||
placeholder="请先选择商户"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12" class="mb20">
|
||||
<el-form-item label="商品分类" prop="categoryId" required>
|
||||
<el-cascader
|
||||
v-model="form.categoryId"
|
||||
:options="categoryOptions"
|
||||
:props="{ value: 'id', label: 'name', children: 'children', checkStrictly: true }"
|
||||
:disabled="!form.merchantId"
|
||||
clearable
|
||||
placeholder="请先选择商户"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="24" class="mb20">
|
||||
<el-form-item label="商品标题" prop="title">
|
||||
<el-input v-model="form.title" placeholder="请输入商品标题" maxlength="100" show-word-limit/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24" class="mb20">
|
||||
<el-form-item label="商品标题" prop="title">
|
||||
<el-input v-model="form.title" placeholder="请输入商品标题" maxlength="100" show-word-limit />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="12" class="mb20">
|
||||
<el-form-item label="计量单位" prop="unit">
|
||||
<el-input v-model="form.unit" placeholder="请输入计量单位"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12" class="mb20">
|
||||
<el-form-item label="计量单位" prop="unit">
|
||||
<el-input v-model="form.unit" placeholder="请输入计量单位" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="12" class="mb20">
|
||||
<el-form-item label="定价方式" prop="priceType">
|
||||
<el-radio-group v-model="form.priceType" @change="onPriceTypeChange">
|
||||
<el-radio :label="1">多SKU模式</el-radio>
|
||||
<el-radio :label="2">单价SPU模式</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12" class="mb20">
|
||||
<el-form-item label="定价方式" prop="priceType">
|
||||
<el-radio-group v-model="form.priceType" @change="onPriceTypeChange">
|
||||
<el-radio :label="1">多SKU模式</el-radio>
|
||||
<el-radio :label="2">单价SPU模式</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="12" class="mb20">
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-radio-group v-model="form.status">
|
||||
<el-radio label="0">上架</el-radio>
|
||||
<el-radio label="1">下架</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12" class="mb20">
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-radio-group v-model="form.status">
|
||||
<el-radio label="0">上架</el-radio>
|
||||
<el-radio label="1">下架</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<!-- 单价SPU模式的价格设置 -->
|
||||
<template v-if="form.priceType === 2">
|
||||
<el-col :span="12" class="mb20">
|
||||
<el-form-item label="SPU售价" prop="spuPrice">
|
||||
<el-input-number v-model="form.spuPrice" :precision="2" :min="0" placeholder="请输入SPU售价" style="width: 100%"/>
|
||||
<span class="price-tip">单位:元</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<!-- 单价SPU模式的价格设置 -->
|
||||
<template v-if="form.priceType === 2">
|
||||
<el-col :span="12" class="mb20">
|
||||
<el-form-item label="SPU售价" prop="spuPrice">
|
||||
<el-input-number v-model="form.spuPrice" :precision="2" :min="0" placeholder="请输入SPU售价" style="width: 100%" />
|
||||
<span class="price-tip">单位:元</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="12" class="mb20">
|
||||
<el-form-item label="划线价" prop="originalPrice">
|
||||
<el-input-number v-model="form.originalPrice" :precision="2" :min="0" placeholder="请输入划线价" style="width: 100%"/>
|
||||
<span class="price-tip">单位:元</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</template>
|
||||
<el-col :span="12" class="mb20">
|
||||
<el-form-item label="划线价" prop="originalPrice">
|
||||
<el-input-number v-model="form.originalPrice" :precision="2" :min="0" placeholder="请输入划线价" style="width: 100%" />
|
||||
<span class="price-tip">单位:元</span>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</template>
|
||||
|
||||
<el-col :span="12" class="mb20">
|
||||
<el-form-item label="开售时间" prop="saleStartTime">
|
||||
<el-date-picker v-model="form.saleStartTime" type="datetime" placeholder="请选择开售时间" style="width: 100%"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12" class="mb20">
|
||||
<el-form-item label="开售时间" prop="saleStartTime">
|
||||
<el-date-picker v-model="form.saleStartTime" type="datetime" placeholder="请选择开售时间" style="width: 100%" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="12" class="mb20">
|
||||
<el-form-item label="停售时间" prop="saleEndTime">
|
||||
<el-date-picker v-model="form.saleEndTime" type="datetime" placeholder="请选择停售时间" style="width: 100%"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12" class="mb20">
|
||||
<el-form-item label="停售时间" prop="saleEndTime">
|
||||
<el-date-picker v-model="form.saleEndTime" type="datetime" placeholder="请选择停售时间" style="width: 100%" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="24" class="mb20">
|
||||
<el-form-item label="主图" prop="coverImage">
|
||||
<upload-img v-model:imageUrl="form.coverImage"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24" class="mb20">
|
||||
<el-form-item label="主图" prop="coverImage">
|
||||
<upload-img v-model:imageUrl="form.coverImage" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="24" class="mb20">
|
||||
<el-form-item label="轮播图" prop="carouselImages">
|
||||
<upload-img v-model:imageUrl="form.carouselImages"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24" class="mb20">
|
||||
<el-form-item label="轮播图" prop="carouselImages">
|
||||
<upload-img v-model:imageUrl="form.carouselImages" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="24" class="mb20">
|
||||
<el-form-item label="详情描述" prop="description">
|
||||
<editor v-if="visible" v-model:get-html="form.description" placeholder="请输入详情描述"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-tab-pane>
|
||||
<el-col :span="24" class="mb20">
|
||||
<el-form-item label="详情描述" prop="description">
|
||||
<editor v-if="visible" v-model:get-html="form.description" placeholder="请输入详情描述" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-tab-pane>
|
||||
|
||||
<!-- SKU信息 -->
|
||||
<el-tab-pane label="SKU信息" name="sku" v-if="form.priceType === 1">
|
||||
<div class="sku-header">
|
||||
<el-button type="primary" @click="addSku" :disabled="loading">
|
||||
<el-icon><Plus /></el-icon>
|
||||
添加SKU
|
||||
</el-button>
|
||||
<span class="sku-tip">多SKU模式:支持不同规格的商品(如不同颜色、尺寸、配置等)</span>
|
||||
</div>
|
||||
<!-- SKU信息 -->
|
||||
<el-tab-pane label="SKU信息" name="sku" v-if="form.priceType === 1">
|
||||
<div class="sku-header">
|
||||
<el-button type="primary" @click="addSku" :disabled="loading">
|
||||
<el-icon><Plus /></el-icon>
|
||||
添加SKU
|
||||
</el-button>
|
||||
<span class="sku-tip">多SKU模式:支持不同规格的商品(如不同颜色、尺寸、配置等)</span>
|
||||
</div>
|
||||
|
||||
<div class="sku-table-container">
|
||||
<el-table :data="form.skuList" border class="sku-table" v-loading="loading">
|
||||
<el-table-column type="index" label="#" width="60" align="center"/>
|
||||
<div class="sku-table-container">
|
||||
<el-table :data="form.skuList" border class="sku-table" v-loading="loading">
|
||||
<el-table-column type="index" label="#" width="60" align="center" />
|
||||
|
||||
<el-table-column label="SKU编码" width="140" align="center">
|
||||
<template #header>
|
||||
<span class="required">*</span> SKU编码
|
||||
</template>
|
||||
<template #default="scope">
|
||||
<div class="sku-cell">
|
||||
<el-input
|
||||
v-model="scope.row.skuCode"
|
||||
placeholder="请输入SKU编码"
|
||||
size="small"
|
||||
:class="{ 'is-error': !scope.row.skuCode && form.skuList.length > 0 }"
|
||||
@blur="validateSkuField(scope.$index, 'skuCode')"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="SKU编码" width="140" align="center">
|
||||
<template #header> <span class="required">*</span> SKU编码 </template>
|
||||
<template #default="scope">
|
||||
<div class="sku-cell">
|
||||
<el-input
|
||||
v-model="scope.row.skuCode"
|
||||
placeholder="请输入SKU编码"
|
||||
size="small"
|
||||
:class="{ 'is-error': !scope.row.skuCode && form.skuList.length > 0 }"
|
||||
@blur="validateSkuField(scope.$index, 'skuCode')"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="SKU名称" min-width="220" align="center" show-overflow-tooltip>
|
||||
<template #header>
|
||||
<span class="required">*</span> SKU名称
|
||||
</template>
|
||||
<template #default="scope">
|
||||
<div class="sku-cell">
|
||||
<el-input
|
||||
v-model="scope.row.skuName"
|
||||
placeholder="请输入SKU名称"
|
||||
size="small"
|
||||
:class="{ 'is-error': !scope.row.skuName && form.skuList.length > 0 }"
|
||||
@blur="validateSkuField(scope.$index, 'skuName')"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="SKU名称" min-width="220" align="center" show-overflow-tooltip>
|
||||
<template #header> <span class="required">*</span> SKU名称 </template>
|
||||
<template #default="scope">
|
||||
<div class="sku-cell">
|
||||
<el-input
|
||||
v-model="scope.row.skuName"
|
||||
placeholder="请输入SKU名称"
|
||||
size="small"
|
||||
:class="{ 'is-error': !scope.row.skuName && form.skuList.length > 0 }"
|
||||
@blur="validateSkuField(scope.$index, 'skuName')"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="售价" width="140" align="center">
|
||||
<template #header>
|
||||
<span class="required">*</span> 售价(元)
|
||||
</template>
|
||||
<template #default="scope">
|
||||
<div class="sku-cell">
|
||||
<el-input-number
|
||||
v-model="scope.row.price"
|
||||
:precision="2"
|
||||
:min="0"
|
||||
size="small"
|
||||
placeholder="0.00"
|
||||
:class="{ 'is-error': (!scope.row.price || scope.row.price <= 0) && form.skuList.length > 0 }"
|
||||
@blur="validateSkuField(scope.$index, 'price')"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="售价" width="140" align="center">
|
||||
<template #header> <span class="required">*</span> 售价(元) </template>
|
||||
<template #default="scope">
|
||||
<div class="sku-cell">
|
||||
<el-input-number
|
||||
v-model="scope.row.price"
|
||||
:precision="2"
|
||||
:min="0"
|
||||
size="small"
|
||||
placeholder="0.00"
|
||||
:class="{ 'is-error': (!scope.row.price || scope.row.price <= 0) && form.skuList.length > 0 }"
|
||||
@blur="validateSkuField(scope.$index, 'price')"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="库存" width="150" align="center">
|
||||
<template #header>
|
||||
<span class="required">*</span> 库存
|
||||
</template>
|
||||
<template #default="scope">
|
||||
<div class="sku-cell">
|
||||
<el-input-number
|
||||
v-model="scope.row.stock"
|
||||
:precision="2"
|
||||
:min="0"
|
||||
size="small"
|
||||
placeholder="0.00"
|
||||
:class="{ 'is-error': (scope.row.stock === undefined || scope.row.stock < 0) && form.skuList.length > 0 }"
|
||||
@blur="validateSkuField(scope.$index, 'stock')"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="库存" width="150" align="center">
|
||||
<template #header> <span class="required">*</span> 库存 </template>
|
||||
<template #default="scope">
|
||||
<div class="sku-cell">
|
||||
<el-input-number
|
||||
v-model="scope.row.stock"
|
||||
:precision="2"
|
||||
:min="0"
|
||||
size="small"
|
||||
placeholder="0.00"
|
||||
:class="{ 'is-error': (scope.row.stock === undefined || scope.row.stock < 0) && form.skuList.length > 0 }"
|
||||
@blur="validateSkuField(scope.$index, 'stock')"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="条码" min-width="150" align="center">
|
||||
<template #default="scope">
|
||||
<div class="sku-cell">
|
||||
<el-input
|
||||
v-model="scope.row.barcode"
|
||||
placeholder="请输入条码"
|
||||
size="small"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="条码" min-width="150" align="center">
|
||||
<template #default="scope">
|
||||
<div class="sku-cell">
|
||||
<el-input v-model="scope.row.barcode" placeholder="请输入条码" size="small" />
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="重量(克)" min-width="120" align="center">
|
||||
<template #default="scope">
|
||||
<div class="sku-cell">
|
||||
<el-input-number
|
||||
v-model="scope.row.weightG"
|
||||
:min="0"
|
||||
size="small"
|
||||
placeholder="0"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="重量(克)" min-width="120" align="center">
|
||||
<template #default="scope">
|
||||
<div class="sku-cell">
|
||||
<el-input-number v-model="scope.row.weightG" :min="0" size="small" placeholder="0" />
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="状态" min-width="100" align="center">
|
||||
<template #default="scope">
|
||||
<div class="sku-cell">
|
||||
<el-radio-group v-model="scope.row.status" size="small">
|
||||
<el-radio label="0">启用</el-radio>
|
||||
<el-radio label="1">停用</el-radio>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" min-width="100" align="center">
|
||||
<template #default="scope">
|
||||
<div class="sku-cell">
|
||||
<el-radio-group v-model="scope.row.status" size="small">
|
||||
<el-radio label="0">启用</el-radio>
|
||||
<el-radio label="1">停用</el-radio>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="操作" width="70" fixed="right" align="center">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
type="danger"
|
||||
size="small"
|
||||
@click="removeSku(scope.$index)"
|
||||
:disabled="form.skuList.length <= 1"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="visible = false">取消</el-button>
|
||||
<el-button type="primary" @click="onSubmit" :disabled="loading">确认</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<el-table-column label="操作" width="80" fixed="right" align="center">
|
||||
<template #default="scope">
|
||||
<el-button type="danger" size="small" @click="removeSku(scope.$index)" :disabled="form.skuList.length <= 1">
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="visible = false">取消</el-button>
|
||||
<el-button type="primary" @click="onSubmit" :disabled="loading">确认</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="MallProductDialog">
|
||||
import { useDict } from '/@/hooks/dict';
|
||||
import { useMessage } from "/@/hooks/message";
|
||||
import { getObj, addObj, putObj } from '/@/api/supermarket/mallProduct'
|
||||
import { Plus } from '@element-plus/icons-vue';
|
||||
import { tree as fetchCategoryTree } from '/@/api/supermarket/mallCategory';
|
||||
import { selectOption as fetchMerchantSelect } from '/@/api/supermarket/mallMerchant';
|
||||
import { useDict } from "/@/hooks/dict"
|
||||
import { useMessage } from "/@/hooks/message"
|
||||
import { getObj, addObj, putObj } from "/@/api/supermarket/mallProduct"
|
||||
import { Plus } from "@element-plus/icons-vue"
|
||||
import { tree as fetchCategoryTree } from "/@/api/supermarket/mallCategory"
|
||||
import { selectOption as fetchMerchantSelect } from "/@/api/supermarket/mallMerchant"
|
||||
|
||||
const emit = defineEmits(['refresh']);
|
||||
const emit = defineEmits(["refresh"])
|
||||
|
||||
// 定义变量内容
|
||||
const dataFormRef = ref();
|
||||
const dataFormRef = ref()
|
||||
const visible = ref(false)
|
||||
const loading = ref(false)
|
||||
const activeTab = ref('basic')
|
||||
const activeTab = ref("basic")
|
||||
|
||||
// 定义字典
|
||||
const { spu_status } = useDict('spu_status')
|
||||
const { spu_status } = useDict("spu_status")
|
||||
|
||||
// 分类选项
|
||||
const categoryOptions = ref<any[]>([]);
|
||||
const categoryOptions = ref<any[]>([])
|
||||
|
||||
// 商户选项
|
||||
const merchantOptions = ref<any[]>([]);
|
||||
const merchantOptions = ref<any[]>([])
|
||||
|
||||
// 加载分类树
|
||||
const loadCategoryTree = async (merchantId?: string) => {
|
||||
if (!merchantId) {
|
||||
categoryOptions.value = [];
|
||||
return;
|
||||
}
|
||||
const res = await fetchCategoryTree({ merchantId });
|
||||
categoryOptions.value = res.data || [];
|
||||
};
|
||||
if (!merchantId) {
|
||||
categoryOptions.value = []
|
||||
return
|
||||
}
|
||||
const res = await fetchCategoryTree({ merchantId })
|
||||
categoryOptions.value = res.data || []
|
||||
}
|
||||
|
||||
// 加载商户选项
|
||||
const loadMerchantOptions = async () => {
|
||||
const res = await fetchMerchantSelect();
|
||||
merchantOptions.value = res.data || [];
|
||||
};
|
||||
const res = await fetchMerchantSelect()
|
||||
merchantOptions.value = res.data || []
|
||||
}
|
||||
|
||||
// 商户选择变化处理
|
||||
const onMerchantChange = (merchantId: string) => {
|
||||
// 清空分类选择
|
||||
form.categoryId = '';
|
||||
// 根据商户ID加载对应的分类树
|
||||
loadCategoryTree(merchantId);
|
||||
};
|
||||
// 清空分类选择
|
||||
form.categoryId = ""
|
||||
// 根据商户ID加载对应的分类树
|
||||
loadCategoryTree(merchantId)
|
||||
}
|
||||
|
||||
// 提交表单数据
|
||||
const form = reactive({
|
||||
id: '',
|
||||
merchantId: '',
|
||||
categoryId: '',
|
||||
title: '',
|
||||
coverImage: '',
|
||||
carouselImages: '',
|
||||
id: "",
|
||||
merchantId: "",
|
||||
categoryId: "",
|
||||
title: "",
|
||||
coverImage: "",
|
||||
carouselImages: "",
|
||||
priceType: 1, // 默认多SKU模式
|
||||
spuPrice: 0,
|
||||
originalPrice: 0,
|
||||
unit: '',
|
||||
status: '0', // 默认上架
|
||||
saleStartTime: '',
|
||||
saleEndTime: '',
|
||||
description: '',
|
||||
skuList: [] as any[] // SKU列表
|
||||
});
|
||||
unit: "",
|
||||
status: "0", // 默认上架
|
||||
saleStartTime: "",
|
||||
saleEndTime: "",
|
||||
description: "",
|
||||
skuList: [] as any[], // SKU列表
|
||||
})
|
||||
|
||||
// SKU验证规则
|
||||
const skuRules = {
|
||||
skuCode: [{ required: true, message: 'SKU编码不能为空', trigger: 'blur' }],
|
||||
skuName: [{ required: true, message: 'SKU名称不能为空', trigger: 'blur' }],
|
||||
price: [{ required: true, message: '售价不能为空', trigger: 'blur' }],
|
||||
stock: [{ required: true, message: '库存不能为空', trigger: 'blur' }]
|
||||
};
|
||||
skuCode: [{ required: true, message: "SKU编码不能为空", trigger: "blur" }],
|
||||
skuName: [{ required: true, message: "SKU名称不能为空", trigger: "blur" }],
|
||||
price: [{ required: true, message: "售价不能为空", trigger: "blur" }],
|
||||
stock: [{ required: true, message: "库存不能为空", trigger: "blur" }],
|
||||
}
|
||||
|
||||
// 定义校验规则
|
||||
const dataRules = ref({
|
||||
merchantId: [{ required: true, message: '商户不能为空', trigger: 'change' }],
|
||||
categoryId: [{ required: true, message: '商品分类不能为空', trigger: 'change' }],
|
||||
title: [{ required: true, message: '商品标题不能为空', trigger: 'blur' }],
|
||||
coverImage: [{ required: true, message: '主图不能为空', trigger: 'blur' }],
|
||||
priceType: [{ required: true, message: '定价方式不能为空', trigger: 'change' }],
|
||||
merchantId: [{ required: true, message: "商户不能为空", trigger: "change" }],
|
||||
categoryId: [{ required: true, message: "商品分类不能为空", trigger: "change" }],
|
||||
title: [{ required: true, message: "商品标题不能为空", trigger: "blur" }],
|
||||
coverImage: [{ required: true, message: "主图不能为空", trigger: "blur" }],
|
||||
priceType: [{ required: true, message: "定价方式不能为空", trigger: "change" }],
|
||||
spuPrice: [
|
||||
{
|
||||
validator: (rule: any, value: any, callback: any) => {
|
||||
if (form.priceType === 2 && (!value || value <= 0)) {
|
||||
callback(new Error('单价SPU模式下,SPU售价不能为空且必须大于0'));
|
||||
callback(new Error("单价SPU模式下,SPU售价不能为空且必须大于0"))
|
||||
} else {
|
||||
callback();
|
||||
callback()
|
||||
}
|
||||
},
|
||||
trigger: 'blur'
|
||||
}
|
||||
trigger: "blur",
|
||||
},
|
||||
],
|
||||
status: [{ required: true, message: '状态不能为空', trigger: 'change' }]
|
||||
});
|
||||
status: [{ required: true, message: "状态不能为空", trigger: "change" }],
|
||||
})
|
||||
|
||||
// 添加SKU
|
||||
const addSku = () => {
|
||||
form.skuList.push({
|
||||
skuCode: '',
|
||||
skuName: '',
|
||||
skuCode: "",
|
||||
skuName: "",
|
||||
price: 0,
|
||||
stock: 0.0,
|
||||
barcode: '',
|
||||
barcode: "",
|
||||
weightG: 0,
|
||||
status: '0'
|
||||
});
|
||||
};
|
||||
status: "0",
|
||||
})
|
||||
}
|
||||
|
||||
// 删除SKU
|
||||
const removeSku = (index: number) => {
|
||||
if (form.skuList.length > 1) {
|
||||
form.skuList.splice(index, 1);
|
||||
form.skuList.splice(index, 1)
|
||||
} else {
|
||||
useMessage().warning('至少需要保留一个SKU');
|
||||
useMessage().warning("至少需要保留一个SKU")
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// 定价方式改变
|
||||
const onPriceTypeChange = (value: number) => {
|
||||
if (value === 1) {
|
||||
// 多SKU模式:确保至少有一个SKU
|
||||
if (form.skuList.length === 0) {
|
||||
addSku();
|
||||
addSku()
|
||||
}
|
||||
} else {
|
||||
// 单价SPU模式:清空SKU列表
|
||||
form.skuList = [];
|
||||
form.skuList = []
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// SKU字段验证
|
||||
const validateSkuField = (index: number, field: string) => {
|
||||
const sku = form.skuList[index];
|
||||
if (!sku) return;
|
||||
const sku = form.skuList[index]
|
||||
if (!sku) return
|
||||
|
||||
// 清除之前的错误状态
|
||||
nextTick(() => {
|
||||
// 这里可以添加具体的验证逻辑
|
||||
});
|
||||
};
|
||||
})
|
||||
}
|
||||
|
||||
// 打开弹窗
|
||||
const openDialog = (id: string) => {
|
||||
visible.value = true
|
||||
form.id = ''
|
||||
activeTab.value = 'basic'
|
||||
form.id = ""
|
||||
activeTab.value = "basic"
|
||||
|
||||
// 重置表单数据
|
||||
nextTick(() => {
|
||||
dataFormRef.value?.resetFields();
|
||||
dataFormRef.value?.resetFields()
|
||||
// 重置表单对象
|
||||
Object.assign(form, {
|
||||
id: '',
|
||||
merchantId: '',
|
||||
categoryId: '',
|
||||
title: '',
|
||||
coverImage: '',
|
||||
carouselImages: '',
|
||||
id: "",
|
||||
merchantId: "",
|
||||
categoryId: "",
|
||||
title: "",
|
||||
coverImage: "",
|
||||
carouselImages: "",
|
||||
priceType: 1,
|
||||
spuPrice: 0,
|
||||
originalPrice: 0,
|
||||
unit: '',
|
||||
status: '0',
|
||||
saleStartTime: '',
|
||||
saleEndTime: '',
|
||||
description: '',
|
||||
skuList: []
|
||||
});
|
||||
unit: "",
|
||||
status: "0",
|
||||
saleStartTime: "",
|
||||
saleEndTime: "",
|
||||
description: "",
|
||||
skuList: [],
|
||||
})
|
||||
// 默认添加一个SKU
|
||||
addSku();
|
||||
});
|
||||
addSku()
|
||||
})
|
||||
|
||||
// 重新加载商户选项
|
||||
loadMerchantOptions();
|
||||
loadMerchantOptions()
|
||||
|
||||
// 获取mallProduct信息
|
||||
if (id) {
|
||||
form.id = id
|
||||
getmallProductData(id)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// 提交
|
||||
const onSubmit = async () => {
|
||||
// 验证基本信息
|
||||
const valid = await dataFormRef.value.validate().catch(() => {});
|
||||
if (!valid) return false;
|
||||
const valid = await dataFormRef.value.validate().catch(() => {})
|
||||
if (!valid) return false
|
||||
|
||||
// 多SKU模式下的额外验证
|
||||
if (form.priceType === 1) {
|
||||
if (!form.skuList || form.skuList.length === 0) {
|
||||
useMessage().error('多SKU模式下至少需要添加一个SKU');
|
||||
activeTab.value = 'sku';
|
||||
return false;
|
||||
useMessage().error("多SKU模式下至少需要添加一个SKU")
|
||||
activeTab.value = "sku"
|
||||
return false
|
||||
}
|
||||
|
||||
// 验证SKU数据
|
||||
for (let i = 0; i < form.skuList.length; i++) {
|
||||
const sku = form.skuList[i];
|
||||
const sku = form.skuList[i]
|
||||
if (!sku.skuCode || !sku.skuName || !sku.price || sku.stock === undefined) {
|
||||
useMessage().error(`第${i + 1}个SKU信息不完整,请检查必填项`);
|
||||
activeTab.value = 'sku';
|
||||
return false;
|
||||
useMessage().error(`第${i + 1}个SKU信息不完整,请检查必填项`)
|
||||
activeTab.value = "sku"
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
loading.value = true;
|
||||
loading.value = true
|
||||
|
||||
// 准备提交数据
|
||||
const submitData = { ...form };
|
||||
const submitData = { ...form }
|
||||
|
||||
// 处理分类ID:如果是数组,取最后一个值
|
||||
if (Array.isArray(form.categoryId)) {
|
||||
submitData.categoryId = form.categoryId.slice(-1)[0];
|
||||
submitData.categoryId = form.categoryId.slice(-1)[0]
|
||||
}
|
||||
|
||||
// 处理时间格式:转换为 LocalDateTime 格式 (yyyy-MM-dd HH:mm:ss)
|
||||
if (form.saleStartTime) {
|
||||
const date = new Date(form.saleStartTime);
|
||||
submitData.saleStartTime = date.toISOString().slice(0, 19).replace('T', ' ');
|
||||
const date = new Date(form.saleStartTime)
|
||||
submitData.saleStartTime = date.toISOString().slice(0, 19).replace("T", " ")
|
||||
}
|
||||
if (form.saleEndTime) {
|
||||
const date = new Date(form.saleEndTime);
|
||||
submitData.saleEndTime = date.toISOString().slice(0, 19).replace('T', ' ');
|
||||
const date = new Date(form.saleEndTime)
|
||||
submitData.saleEndTime = date.toISOString().slice(0, 19).replace("T", " ")
|
||||
}
|
||||
|
||||
// 如果是单价SPU模式,清空SKU列表
|
||||
if (form.priceType === 2) {
|
||||
submitData.skuList = [];
|
||||
submitData.skuList = []
|
||||
}
|
||||
|
||||
// 价格转换:元转分
|
||||
if (submitData.spuPrice) {
|
||||
submitData.spuPrice = Math.round(submitData.spuPrice * 100);
|
||||
submitData.spuPrice = Math.round(submitData.spuPrice * 100)
|
||||
}
|
||||
if (submitData.originalPrice) {
|
||||
submitData.originalPrice = Math.round(submitData.originalPrice * 100);
|
||||
submitData.originalPrice = Math.round(submitData.originalPrice * 100)
|
||||
}
|
||||
if (submitData.skuList && submitData.skuList.length > 0) {
|
||||
submitData.skuList = submitData.skuList.map((sku: any) => ({
|
||||
...sku,
|
||||
price: sku.price ? Math.round(sku.price * 100) : 0
|
||||
}));
|
||||
price: sku.price ? Math.round(sku.price * 100) : 0,
|
||||
}))
|
||||
}
|
||||
|
||||
form.id ? await putObj(submitData) : await addObj(submitData);
|
||||
useMessage().success(form.id ? '修改成功' : '添加成功');
|
||||
visible.value = false;
|
||||
emit('refresh');
|
||||
form.id ? await putObj(submitData) : await addObj(submitData)
|
||||
useMessage().success(form.id ? "修改成功" : "添加成功")
|
||||
visible.value = false
|
||||
emit("refresh")
|
||||
} catch (err: any) {
|
||||
useMessage().error(err.msg);
|
||||
useMessage().error(err.msg)
|
||||
} finally {
|
||||
loading.value = false;
|
||||
loading.value = false
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// 初始化表单数据
|
||||
const getmallProductData = async (id: string) => {
|
||||
// 获取数据
|
||||
loading.value = true
|
||||
try {
|
||||
const res = await getObj(id);
|
||||
Object.assign(form, res.data);
|
||||
const res = await getObj(id)
|
||||
Object.assign(form, res.data)
|
||||
|
||||
// 先根据商户ID加载分类树
|
||||
if (form.merchantId) {
|
||||
await loadCategoryTree(form.merchantId);
|
||||
await loadCategoryTree(form.merchantId)
|
||||
}
|
||||
|
||||
// 价格转换:分转元
|
||||
if (form.spuPrice) {
|
||||
form.spuPrice = form.spuPrice / 100;
|
||||
form.spuPrice = form.spuPrice / 100
|
||||
}
|
||||
if (form.originalPrice) {
|
||||
form.originalPrice = form.originalPrice / 100;
|
||||
form.originalPrice = form.originalPrice / 100
|
||||
}
|
||||
if (form.skuList && form.skuList.length > 0) {
|
||||
form.skuList = form.skuList.map((sku: any) => ({
|
||||
...sku,
|
||||
price: sku.price ? sku.price / 100 : 0
|
||||
}));
|
||||
price: sku.price ? sku.price / 100 : 0,
|
||||
}))
|
||||
}
|
||||
|
||||
// 处理分类ID回显为数组
|
||||
if (res.data.categoryId && categoryOptions.value.length) {
|
||||
form.categoryId = findCategoryPath(categoryOptions.value, res.data.categoryId) as any;
|
||||
form.categoryId = findCategoryPath(categoryOptions.value, res.data.categoryId) as any
|
||||
}
|
||||
|
||||
// 如果没有SKU数据,根据定价方式初始化
|
||||
if (!form.skuList || form.skuList.length === 0) {
|
||||
if (form.priceType === 1) {
|
||||
addSku();
|
||||
addSku()
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// 工具函数:根据分类id查找路径
|
||||
function findCategoryPath(options: any[], targetId: any, path: any[] = []): any[] {
|
||||
for (const item of options) {
|
||||
const newPath = path.concat(item.id);
|
||||
if (item.id === targetId) return newPath;
|
||||
if (item.children) {
|
||||
const childPath = findCategoryPath(item.children, targetId, newPath);
|
||||
if (childPath.length) return childPath;
|
||||
}
|
||||
}
|
||||
return [];
|
||||
for (const item of options) {
|
||||
const newPath = path.concat(item.id)
|
||||
if (item.id === targetId) return newPath
|
||||
if (item.children) {
|
||||
const childPath = findCategoryPath(item.children, targetId, newPath)
|
||||
if (childPath.length) return childPath
|
||||
}
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
// 组件挂载时加载商户选项
|
||||
onMounted(() => {
|
||||
loadMerchantOptions();
|
||||
});
|
||||
loadMerchantOptions()
|
||||
})
|
||||
|
||||
// 暴露变量
|
||||
defineExpose({
|
||||
openDialog
|
||||
});
|
||||
openDialog,
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
@@ -1,212 +1,241 @@
|
||||
<template>
|
||||
<div class="layout-padding">
|
||||
<div class="layout-padding-auto layout-padding-view">
|
||||
<el-row v-show="showSearch">
|
||||
<el-form :model="state.queryForm" ref="queryRef" :inline="true" @keyup.enter="getDataList">
|
||||
<el-form-item label="类目ID" prop="categoryId" >
|
||||
<el-input placeholder="请输入类目ID" v-model="state.queryForm.categoryId" />
|
||||
</el-form-item>
|
||||
<el-form-item label="商品标题" prop="title" >
|
||||
<el-input placeholder="请输入商品标题" v-model="state.queryForm.title" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button icon="search" type="primary" @click="getDataList">
|
||||
查询
|
||||
</el-button>
|
||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<div class="mb8" style="width: 100%">
|
||||
<el-button icon="folder-add" type="primary" class="ml10" @click="formDialogRef.openDialog()"
|
||||
v-auth="'supermarket_mallProduct_add'">
|
||||
新 增
|
||||
</el-button>
|
||||
<el-button plain :disabled="multiple" icon="Delete" type="primary"
|
||||
v-auth="'supermarket_mallProduct_del'" @click="handleDelete(selectObjs)">
|
||||
删除
|
||||
</el-button>
|
||||
<right-toolbar v-model:showSearch="showSearch" :export="'supermarket_mallProduct_export'"
|
||||
@exportExcel="exportExcel" class="ml10 mr20" style="float: right;"
|
||||
@queryTable="getDataList"></right-toolbar>
|
||||
</div>
|
||||
</el-row>
|
||||
<el-table :data="state.dataList" v-loading="state.loading" border
|
||||
:cell-style="tableStyle.cellStyle" :header-cell-style="tableStyle.headerCellStyle"
|
||||
<div class="layout-padding">
|
||||
<div class="layout-padding-auto layout-padding-view">
|
||||
<el-row v-show="showSearch">
|
||||
<el-form :model="state.queryForm" ref="queryRef" :inline="true" @keyup.enter="getDataList">
|
||||
<el-form-item label="类目ID" prop="categoryId">
|
||||
<el-input placeholder="请输入类目ID" v-model="state.queryForm.categoryId" />
|
||||
</el-form-item>
|
||||
<el-form-item label="商品标题" prop="title">
|
||||
<el-input placeholder="请输入商品标题" v-model="state.queryForm.title" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button icon="search" type="primary" @click="getDataList"> 查询 </el-button>
|
||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-row>
|
||||
<el-row>
|
||||
<div class="mb8" style="width: 100%">
|
||||
<el-button
|
||||
icon="folder-add"
|
||||
type="primary"
|
||||
class="ml10"
|
||||
@click="formDialogRef.openDialog()"
|
||||
v-auth="'supermarket_mallProduct_add'"
|
||||
>
|
||||
新 增
|
||||
</el-button>
|
||||
<el-button
|
||||
plain
|
||||
:disabled="multiple"
|
||||
icon="Delete"
|
||||
type="primary"
|
||||
v-auth="'supermarket_mallProduct_del'"
|
||||
@click="handleDelete(selectObjs)"
|
||||
>
|
||||
删 除
|
||||
</el-button>
|
||||
<right-toolbar
|
||||
v-model:showSearch="showSearch"
|
||||
:export="'supermarket_mallProduct_export'"
|
||||
@exportExcel="exportExcel"
|
||||
class="ml10 mr20"
|
||||
style="float: right"
|
||||
@queryTable="getDataList"
|
||||
></right-toolbar>
|
||||
</div>
|
||||
</el-row>
|
||||
<el-table
|
||||
:data="state.dataList"
|
||||
v-loading="state.loading"
|
||||
border
|
||||
:cell-style="tableStyle.cellStyle"
|
||||
:header-cell-style="tableStyle.headerCellStyle"
|
||||
@selection-change="selectionChangHandle"
|
||||
@sort-change="sortChangeHandle">
|
||||
<el-table-column type="selection" width="40" align="center" />
|
||||
<el-table-column type="index" label="#" width="40" />
|
||||
|
||||
<el-table-column prop="title" label="商品标题" width="200" show-overflow-tooltip/>
|
||||
|
||||
<el-table-column prop="merchantId" label="商户" width="150" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
{{ getMerchantName(scope.row.merchantId) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="categoryId" label="商品分类" width="150" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
{{ getCategoryName(scope.row.categoryId) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="priceType" label="定价方式" width="120" align="center">
|
||||
<template #default="scope">
|
||||
<el-tag :type="scope.row.priceType === 1 ? 'primary' : 'success'">
|
||||
{{ scope.row.priceType === 1 ? '多SKU' : '单价SPU' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@sort-change="sortChangeHandle"
|
||||
>
|
||||
<el-table-column type="selection" width="40" align="center" />
|
||||
<el-table-column type="index" label="#" width="40" />
|
||||
|
||||
<el-table-column label="价格信息" width="200">
|
||||
<template #default="scope">
|
||||
<div v-if="scope.row.priceType === 1">
|
||||
<div v-if="scope.row.skuList && scope.row.skuList.length > 0">
|
||||
<div class="price-range">
|
||||
<span class="min-price">¥{{ getMinPrice(scope.row.skuList) }}</span>
|
||||
<span v-if="getMinPrice(scope.row.skuList) !== getMaxPrice(scope.row.skuList)"> - ¥{{ getMaxPrice(scope.row.skuList) }}</span>
|
||||
</div>
|
||||
<div class="sku-count">{{ scope.row.skuList.length }}个SKU</div>
|
||||
</div>
|
||||
<div v-else class="no-sku">暂无SKU</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div class="spu-price">¥{{ ((scope.row.spuPrice || 0) / 100).toFixed(2) }}</div>
|
||||
<div v-if="scope.row.originalPrice" class="original-price">¥{{ ((scope.row.originalPrice || 0) / 100).toFixed(2) }}</div>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="title" label="商品标题" width="200" show-overflow-tooltip />
|
||||
|
||||
<el-table-column label="库存信息" width="120">
|
||||
<template #default="scope">
|
||||
<div v-if="scope.row.priceType === 1">
|
||||
<div v-if="scope.row.skuList && scope.row.skuList.length > 0">
|
||||
<div class="total-stock">{{ getTotalStock(scope.row.skuList) }}</div>
|
||||
<div class="sku-count">{{ scope.row.skuList.length }}个SKU</div>
|
||||
</div>
|
||||
<div v-else class="no-stock">0</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div class="spu-stock">{{ scope.row.totalStock || 0 }}</div>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="merchantId" label="商户" width="150" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
{{ getMerchantName(scope.row.merchantId) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="unit" label="单位" width="80" align="center"/>
|
||||
|
||||
<el-table-column prop="status" label="状态" width="100" align="center">
|
||||
<template #default="scope">
|
||||
<el-tag :type="scope.row.status === '0' ? 'success' : 'danger'">
|
||||
{{ scope.row.status === '0' ? '上架' : '下架' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="categoryId" label="商品分类" width="150" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
{{ getCategoryName(scope.row.categoryId) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="saleStartTime" label="开售时间" width="160" show-overflow-tooltip/>
|
||||
|
||||
<el-table-column prop="saleEndTime" label="停售时间" width="160" show-overflow-tooltip/>
|
||||
<el-table-column prop="priceType" label="定价方式" width="120" align="center">
|
||||
<template #default="scope">
|
||||
<el-tag :type="scope.row.priceType === 1 ? 'primary' : 'success'">
|
||||
{{ scope.row.priceType === 1 ? "多SKU" : "单价SPU" }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="SKU详情" width="120" align="center">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
v-if="scope.row.priceType === 1 && scope.row.skuList && scope.row.skuList.length > 0"
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="showSkuDetail(scope.row)">
|
||||
查看SKU
|
||||
</el-button>
|
||||
<span v-else class="no-sku-detail">-</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="操作" width="180" fixed="right">
|
||||
<template #default="scope">
|
||||
<el-button icon="edit-pen" text type="primary" v-auth="'supermarket_mallProduct_edit'"
|
||||
@click="formDialogRef.openDialog(scope.row.id)">编辑</el-button>
|
||||
<el-button icon="delete" text type="primary" v-auth="'supermarket_mallProduct_del'" @click="handleDelete([scope.row.id])">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<pagination @size-change="sizeChangeHandle" @current-change="currentChangeHandle" v-bind="state.pagination" />
|
||||
</div>
|
||||
<el-table-column label="价格信息" width="200">
|
||||
<template #default="scope">
|
||||
<div v-if="scope.row.priceType === 1">
|
||||
<div v-if="scope.row.skuList && scope.row.skuList.length > 0">
|
||||
<div class="price-range">
|
||||
<span class="min-price">¥{{ getMinPrice(scope.row.skuList) }}</span>
|
||||
<span v-if="getMinPrice(scope.row.skuList) !== getMaxPrice(scope.row.skuList)">
|
||||
- ¥{{ getMaxPrice(scope.row.skuList) }}</span
|
||||
>
|
||||
</div>
|
||||
<div class="sku-count">{{ scope.row.skuList.length }}个SKU</div>
|
||||
</div>
|
||||
<div v-else class="no-sku">暂无SKU</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div class="spu-price">¥{{ ((scope.row.spuPrice || 0) / 100).toFixed(2) }}</div>
|
||||
<div v-if="scope.row.originalPrice" class="original-price">¥{{ ((scope.row.originalPrice || 0) / 100).toFixed(2) }}</div>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<!-- 编辑、新增 -->
|
||||
<form-dialog ref="formDialogRef" @refresh="getDataList(false)" />
|
||||
<el-table-column label="库存信息" width="120">
|
||||
<template #default="scope">
|
||||
<div v-if="scope.row.priceType === 1">
|
||||
<div v-if="scope.row.skuList && scope.row.skuList.length > 0">
|
||||
<div class="total-stock">{{ getTotalStock(scope.row.skuList) }}</div>
|
||||
<div class="sku-count">{{ scope.row.skuList.length }}个SKU</div>
|
||||
</div>
|
||||
<div v-else class="no-stock">0</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div class="spu-stock">{{ scope.row.totalStock || 0 }}</div>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<!-- SKU详情弹窗 -->
|
||||
<el-dialog v-model="skuDetailVisible" title="SKU详情" width="80%" :close-on-click-modal="false">
|
||||
<div v-if="currentProduct">
|
||||
<div class="product-info">
|
||||
<h3>{{ currentProduct.title }}</h3>
|
||||
<p class="product-desc">{{ currentProduct.subTitle }}</p>
|
||||
</div>
|
||||
|
||||
<el-table :data="currentProduct.skuList" border style="margin-top: 20px;">
|
||||
<el-table-column type="index" label="#" width="60" align="center"/>
|
||||
<el-table-column prop="skuCode" label="SKU编码" width="150"/>
|
||||
<el-table-column prop="skuName" label="SKU名称" width="200"/>
|
||||
<el-table-column prop="price" label="售价" width="120" align="right">
|
||||
<template #default="scope">
|
||||
<span class="price">¥{{ ((scope.row.price || 0) / 100).toFixed(2) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="stock" label="库存" width="100" align="center"/>
|
||||
<el-table-column prop="barcode" label="条码" width="150"/>
|
||||
<el-table-column prop="weightG" label="重量(克)" width="120" align="center"/>
|
||||
<el-table-column prop="status" label="状态" width="100" align="center">
|
||||
<template #default="scope">
|
||||
<el-tag :type="scope.row.status === '0' ? 'success' : 'danger'">
|
||||
{{ scope.row.status === '0' ? '启用' : '停用' }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="skuDetailVisible = false">关闭</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<el-table-column prop="unit" label="单位" width="80" align="center" />
|
||||
|
||||
</div>
|
||||
<el-table-column prop="status" label="状态" width="100" align="center">
|
||||
<template #default="scope">
|
||||
<el-tag :type="scope.row.status === '0' ? 'success' : 'danger'">
|
||||
{{ scope.row.status === "0" ? "上架" : "下架" }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column prop="saleStartTime" label="开售时间" width="160" show-overflow-tooltip />
|
||||
|
||||
<el-table-column prop="saleEndTime" label="停售时间" width="160" show-overflow-tooltip />
|
||||
|
||||
<el-table-column label="SKU详情" width="120" align="center">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
v-if="scope.row.priceType === 1 && scope.row.skuList && scope.row.skuList.length > 0"
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="showSkuDetail(scope.row)"
|
||||
>
|
||||
查看SKU
|
||||
</el-button>
|
||||
<span v-else class="no-sku-detail">-</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="操作" width="180" fixed="right">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
icon="edit-pen"
|
||||
text
|
||||
type="primary"
|
||||
v-auth="'supermarket_mallProduct_edit'"
|
||||
@click="formDialogRef.openDialog(scope.row.id)"
|
||||
>编辑</el-button
|
||||
>
|
||||
<el-button icon="delete" text type="primary" v-auth="'supermarket_mallProduct_del'" @click="handleDelete([scope.row.id])"
|
||||
>删除</el-button
|
||||
>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<pagination @size-change="sizeChangeHandle" @current-change="currentChangeHandle" v-bind="state.pagination" />
|
||||
</div>
|
||||
|
||||
<!-- 编辑、新增 -->
|
||||
<form-dialog ref="formDialogRef" @refresh="getDataList(false)" />
|
||||
|
||||
<!-- SKU详情弹窗 -->
|
||||
<el-dialog v-model="skuDetailVisible" title="SKU详情" width="80%" :close-on-click-modal="false">
|
||||
<div v-if="currentProduct">
|
||||
<div class="product-info">
|
||||
<h3>{{ currentProduct.title }}</h3>
|
||||
<p class="product-desc">{{ currentProduct.subTitle }}</p>
|
||||
</div>
|
||||
|
||||
<el-table :data="currentProduct.skuList" border style="margin-top: 20px">
|
||||
<el-table-column type="index" label="#" width="60" align="center" />
|
||||
<el-table-column prop="skuCode" label="SKU编码" width="150" />
|
||||
<el-table-column prop="skuName" label="SKU名称" width="200" />
|
||||
<el-table-column prop="price" label="售价" width="120" align="right">
|
||||
<template #default="scope">
|
||||
<span class="price">¥{{ ((scope.row.price || 0) / 100).toFixed(2) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="stock" label="库存" width="100" align="center" />
|
||||
<el-table-column prop="barcode" label="条码" width="150" />
|
||||
<el-table-column prop="weightG" label="重量(克)" width="120" align="center" />
|
||||
<el-table-column prop="status" label="状态" width="100" align="center">
|
||||
<template #default="scope">
|
||||
<el-tag :type="scope.row.status === '0' ? 'success' : 'danger'">
|
||||
{{ scope.row.status === "0" ? "启用" : "停用" }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click="skuDetailVisible = false">关闭</el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="systemMallProduct">
|
||||
import { BasicTableProps, useTable } from "/@/hooks/table";
|
||||
import { fetchList, delObjs } from "/@/api/supermarket/mallProduct";
|
||||
import { useMessage, useMessageBox } from "/@/hooks/message";
|
||||
import { useDict } from '/@/hooks/dict';
|
||||
import { tree as fetchCategoryTree } from '/@/api/supermarket/mallCategory';
|
||||
import { selectOption as fetchMerchantSelect } from '/@/api/supermarket/mallMerchant';
|
||||
import { BasicTableProps, useTable } from "/@/hooks/table"
|
||||
import { fetchList, delObjs } from "/@/api/supermarket/mallProduct"
|
||||
import { useMessage, useMessageBox } from "/@/hooks/message"
|
||||
import { useDict } from "/@/hooks/dict"
|
||||
import { tree as fetchCategoryTree } from "/@/api/supermarket/mallCategory"
|
||||
import { selectOption as fetchMerchantSelect } from "/@/api/supermarket/mallMerchant"
|
||||
|
||||
// 引入组件
|
||||
const FormDialog = defineAsyncComponent(() => import('./form.vue'));
|
||||
const FormDialog = defineAsyncComponent(() => import("./form.vue"))
|
||||
|
||||
// 定义查询字典
|
||||
const { spu_status } = useDict('spu_status')
|
||||
const { spu_status } = useDict("spu_status")
|
||||
|
||||
// 分类选项
|
||||
const categoryOptions = ref<any[]>([]);
|
||||
const categoryOptions = ref<any[]>([])
|
||||
|
||||
// 商户选项
|
||||
const merchantOptions = ref<any[]>([]);
|
||||
const merchantOptions = ref<any[]>([])
|
||||
|
||||
// 加载分类树
|
||||
const loadCategoryTree = async () => {
|
||||
const res = await fetchCategoryTree();
|
||||
categoryOptions.value = res.data || [];
|
||||
};
|
||||
const res = await fetchCategoryTree()
|
||||
categoryOptions.value = res.data || []
|
||||
}
|
||||
|
||||
// 加载商户选项
|
||||
const loadMerchantOptions = async () => {
|
||||
const res = await fetchMerchantSelect();
|
||||
merchantOptions.value = res.data || [];
|
||||
};
|
||||
const res = await fetchMerchantSelect()
|
||||
merchantOptions.value = res.data || []
|
||||
}
|
||||
|
||||
// 定义变量内容
|
||||
const formDialogRef = ref()
|
||||
@@ -221,173 +250,169 @@ const selectObjs = ref([]) as any
|
||||
const multiple = ref(true)
|
||||
|
||||
const state: BasicTableProps = reactive<BasicTableProps>({
|
||||
queryForm: {},
|
||||
pageList: fetchList
|
||||
queryForm: {},
|
||||
pageList: fetchList,
|
||||
})
|
||||
|
||||
// table hook
|
||||
const {
|
||||
getDataList,
|
||||
currentChangeHandle,
|
||||
sizeChangeHandle,
|
||||
sortChangeHandle,
|
||||
downBlobFile,
|
||||
tableStyle
|
||||
} = useTable(state)
|
||||
const { getDataList, currentChangeHandle, sizeChangeHandle, sortChangeHandle, downBlobFile, tableStyle } = useTable(state)
|
||||
|
||||
// 获取SKU最低价格
|
||||
const getMinPrice = (skuList: any[]) => {
|
||||
if (!skuList || skuList.length === 0) return 0;
|
||||
return (Math.min(...skuList.map(sku => (sku.price || 0) / 100))).toFixed(2);
|
||||
};
|
||||
if (!skuList || skuList.length === 0) return 0
|
||||
return Math.min(...skuList.map((sku) => (sku.price || 0) / 100)).toFixed(2)
|
||||
}
|
||||
|
||||
// 获取SKU最高价格
|
||||
const getMaxPrice = (skuList: any[]) => {
|
||||
if (!skuList || skuList.length === 0) return 0;
|
||||
return (Math.max(...skuList.map(sku => (sku.price || 0) / 100))).toFixed(2);
|
||||
};
|
||||
if (!skuList || skuList.length === 0) return 0
|
||||
return Math.max(...skuList.map((sku) => (sku.price || 0) / 100)).toFixed(2)
|
||||
}
|
||||
|
||||
// 获取SKU总库存
|
||||
const getTotalStock = (skuList: any[]) => {
|
||||
if (!skuList || skuList.length === 0) return 0;
|
||||
return skuList.reduce((total, sku) => total + (sku.stock || 0), 0);
|
||||
};
|
||||
if (!skuList || skuList.length === 0) return 0
|
||||
return skuList.reduce((total, sku) => total + (sku.stock || 0), 0)
|
||||
}
|
||||
|
||||
// 根据分类ID查找分类名称
|
||||
const getCategoryName = (categoryId: any) => {
|
||||
if (!categoryId || !categoryOptions.value.length) return '-';
|
||||
|
||||
const findCategory = (options: any[], targetId: any): any => {
|
||||
for (const item of options) {
|
||||
if (item.id === targetId) return item;
|
||||
if (item.children) {
|
||||
const found = findCategory(item.children, targetId);
|
||||
if (found) return found;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
const category = findCategory(categoryOptions.value, categoryId);
|
||||
return category ? category.name : '-';
|
||||
};
|
||||
if (!categoryId || !categoryOptions.value.length) return "-"
|
||||
|
||||
const findCategory = (options: any[], targetId: any): any => {
|
||||
for (const item of options) {
|
||||
if (item.id === targetId) return item
|
||||
if (item.children) {
|
||||
const found = findCategory(item.children, targetId)
|
||||
if (found) return found
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
const category = findCategory(categoryOptions.value, categoryId)
|
||||
return category ? category.name : "-"
|
||||
}
|
||||
|
||||
// 根据商户ID查找商户名称
|
||||
const getMerchantName = (merchantId: any) => {
|
||||
if (!merchantId || !merchantOptions.value.length) return '-';
|
||||
const merchant = merchantOptions.value.find(item => item.value === merchantId);
|
||||
return merchant ? merchant.label : '-';
|
||||
};
|
||||
if (!merchantId || !merchantOptions.value.length) return "-"
|
||||
const merchant = merchantOptions.value.find((item) => item.value === merchantId)
|
||||
return merchant ? merchant.label : "-"
|
||||
}
|
||||
|
||||
// 显示SKU详情
|
||||
const showSkuDetail = (product: any) => {
|
||||
currentProduct.value = product;
|
||||
skuDetailVisible.value = true;
|
||||
};
|
||||
currentProduct.value = product
|
||||
skuDetailVisible.value = true
|
||||
}
|
||||
|
||||
// 清空搜索条件
|
||||
const resetQuery = () => {
|
||||
// 清空搜索条件
|
||||
queryRef.value?.resetFields()
|
||||
// 清空多选
|
||||
selectObjs.value = []
|
||||
getDataList()
|
||||
// 清空搜索条件
|
||||
queryRef.value?.resetFields()
|
||||
// 清空多选
|
||||
selectObjs.value = []
|
||||
getDataList()
|
||||
}
|
||||
|
||||
// 导出excel
|
||||
const exportExcel = () => {
|
||||
downBlobFile('/supermarket/mallProduct/export', Object.assign(state.queryForm, { ids: selectObjs }), 'mallProduct.xlsx')
|
||||
downBlobFile("/supermarket/mallProduct/export", Object.assign(state.queryForm, { ids: selectObjs }), "mallProduct.xlsx")
|
||||
}
|
||||
|
||||
// 多选事件
|
||||
const selectionChangHandle = (objs: { id: string }[]) => {
|
||||
selectObjs.value = objs.map(({ id }) => id);
|
||||
multiple.value = !objs.length;
|
||||
};
|
||||
selectObjs.value = objs.map(({ id }) => id)
|
||||
multiple.value = !objs.length
|
||||
}
|
||||
|
||||
// 删除操作
|
||||
const handleDelete = async (ids: string[]) => {
|
||||
try {
|
||||
await useMessageBox().confirm('此操作将永久删除');
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await useMessageBox().confirm("此操作将永久删除")
|
||||
} catch {
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
await delObjs(ids);
|
||||
getDataList();
|
||||
useMessage().success('删除成功');
|
||||
} catch (err: any) {
|
||||
useMessage().error(err.msg);
|
||||
}
|
||||
};
|
||||
try {
|
||||
await delObjs(ids)
|
||||
getDataList()
|
||||
useMessage().success("删除成功")
|
||||
} catch (err: any) {
|
||||
useMessage().error(err.msg)
|
||||
}
|
||||
}
|
||||
|
||||
// 组件挂载时加载分类树和商户选项
|
||||
onMounted(() => {
|
||||
loadCategoryTree();
|
||||
loadMerchantOptions();
|
||||
});
|
||||
loadCategoryTree()
|
||||
loadMerchantOptions()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.price-range {
|
||||
font-weight: bold;
|
||||
color: #e6a23c;
|
||||
font-weight: bold;
|
||||
color: #e6a23c;
|
||||
}
|
||||
|
||||
.min-price {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
color: #f56c6c;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
color: #f56c6c;
|
||||
}
|
||||
|
||||
.spu-price {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
color: #f56c6c;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
color: #f56c6c;
|
||||
}
|
||||
|
||||
.original-price {
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
text-decoration: line-through;
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
.total-stock, .spu-stock {
|
||||
font-weight: bold;
|
||||
color: #67c23a;
|
||||
.total-stock,
|
||||
.spu-stock {
|
||||
font-weight: bold;
|
||||
color: #67c23a;
|
||||
}
|
||||
|
||||
.sku-count {
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
.no-sku, .no-stock, .no-sku-detail {
|
||||
color: #c0c4cc;
|
||||
font-style: italic;
|
||||
.no-sku,
|
||||
.no-stock,
|
||||
.no-sku-detail {
|
||||
color: #c0c4cc;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.product-info {
|
||||
margin-bottom: 20px;
|
||||
padding: 15px;
|
||||
background: #f5f7fa;
|
||||
border-radius: 4px;
|
||||
|
||||
h3 {
|
||||
margin: 0 0 8px 0;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.product-desc {
|
||||
margin: 0;
|
||||
color: #606266;
|
||||
font-size: 14px;
|
||||
}
|
||||
margin-bottom: 20px;
|
||||
padding: 15px;
|
||||
background: #f5f7fa;
|
||||
border-radius: 4px;
|
||||
|
||||
h3 {
|
||||
margin: 0 0 8px 0;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.product-desc {
|
||||
margin: 0;
|
||||
color: #606266;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.price {
|
||||
color: #f56c6c;
|
||||
font-weight: bold;
|
||||
color: #f56c6c;
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
@@ -23,9 +23,9 @@
|
||||
</el-col>
|
||||
|
||||
<el-col :span="12" class="mb20">
|
||||
<el-form-item label="状态(0正常,1下架)" prop="status">
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-radio-group v-model="form.status">
|
||||
<el-radio :label="item.value" v-for="(item, index) in status" border :key="index">{{ item.label }} </el-radio>
|
||||
<el-radio :label="item.value" v-for="(item, index) in status" border :key="index">{{ item.label }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
@@ -137,7 +137,7 @@ const getshopCategoryData = (id: string) => {
|
||||
loading.value = true
|
||||
getObj(id)
|
||||
.then((res: any) => {
|
||||
Object.assign(form, res.data)
|
||||
Object.assign(form, res.data, { status: res.data.status.toString() })
|
||||
// 编辑时加载分类并排除自己
|
||||
loadCategories()
|
||||
})
|
||||
|
||||
@@ -1,65 +1,99 @@
|
||||
<template>
|
||||
<div class="layout-padding">
|
||||
<div class="layout-padding-auto layout-padding-view">
|
||||
<el-row>
|
||||
<div class="mb8" style="width: 100%">
|
||||
<el-button icon="folder-add" type="primary" class="ml10" @click="formDialogRef.openDialog()"
|
||||
v-auth="'supermarket_shopSku_add'">
|
||||
新 增
|
||||
</el-button>
|
||||
<el-button plain :disabled="multiple" icon="Delete" type="primary"
|
||||
v-auth="'supermarket_shopSku_del'" @click="handleDelete(selectObjs)">
|
||||
删除
|
||||
</el-button>
|
||||
<right-toolbar v-model:showSearch="showSearch" :export="'supermarket_shopSku_export'"
|
||||
@exportExcel="exportExcel" class="ml10 mr20" style="float: right;"
|
||||
@queryTable="getDataList"></right-toolbar>
|
||||
</div>
|
||||
</el-row>
|
||||
<el-table :data="state.dataList" v-loading="state.loading" border
|
||||
:cell-style="tableStyle.cellStyle" :header-cell-style="tableStyle.headerCellStyle"
|
||||
<div class="layout-padding">
|
||||
<div class="layout-padding-auto layout-padding-view">
|
||||
<el-row>
|
||||
<div class="mb8" style="width: 100%">
|
||||
<!-- <el-button icon="folder-add" type="primary" class="ml10" @click="formDialogRef.openDialog()" v-auth="'supermarket_shopSku_add'">
|
||||
新 增
|
||||
</el-button> -->
|
||||
<el-button
|
||||
plain
|
||||
:disabled="multiple"
|
||||
icon="Delete"
|
||||
type="primary"
|
||||
v-auth="'supermarket_shopSku_del'"
|
||||
@click="handleDelete(selectObjs)"
|
||||
>
|
||||
删 除
|
||||
</el-button>
|
||||
<right-toolbar
|
||||
v-model:showSearch="showSearch"
|
||||
:export="'supermarket_shopSku_export'"
|
||||
@exportExcel="exportExcel"
|
||||
class="ml10 mr20"
|
||||
style="float: right"
|
||||
@queryTable="getDataList"
|
||||
></right-toolbar>
|
||||
</div>
|
||||
</el-row>
|
||||
<el-table
|
||||
:data="state.dataList"
|
||||
v-loading="state.loading"
|
||||
border
|
||||
:cell-style="tableStyle.cellStyle"
|
||||
:header-cell-style="tableStyle.headerCellStyle"
|
||||
@selection-change="selectionChangHandle"
|
||||
@sort-change="sortChangeHandle">
|
||||
<el-table-column type="selection" width="40" align="center" />
|
||||
<el-table-column type="index" label="#" width="40" />
|
||||
<el-table-column prop="barCode" label="条码" show-overflow-tooltip/>
|
||||
<el-table-column prop="spec" label="规格" show-overflow-tooltip/>
|
||||
<el-table-column prop="unit" label="单位" show-overflow-tooltip/>
|
||||
<el-table-column prop="status" label="状态(0正常,1停销)" show-overflow-tooltip/>
|
||||
<el-table-column prop="purchasePrice" label="进价/单位分" show-overflow-tooltip/>
|
||||
<el-table-column prop="retailPrice" label="零售价/单位分" show-overflow-tooltip/>
|
||||
<el-table-column prop="spuId" label="spuID" show-overflow-tooltip/>
|
||||
<el-table-column prop="promotionPrice" label="促销价" show-overflow-tooltip/>
|
||||
<el-table-column prop="stock" label="库存" show-overflow-tooltip/>
|
||||
<el-table-column prop="attribute" label="sku属性" show-overflow-tooltip/>
|
||||
<el-table-column label="操作" width="150">
|
||||
<template #default="scope">
|
||||
<el-button icon="edit-pen" text type="primary" v-auth="'supermarket_shopSku_edit'"
|
||||
@click="formDialogRef.openDialog(scope.row.id)">编辑</el-button>
|
||||
<el-button icon="delete" text type="primary" v-auth="'supermarket_shopSku_del'" @click="handleDelete([scope.row.id])">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<pagination @size-change="sizeChangeHandle" @current-change="currentChangeHandle" v-bind="state.pagination" />
|
||||
</div>
|
||||
@sort-change="sortChangeHandle"
|
||||
>
|
||||
<el-table-column type="selection" width="40" align="center" />
|
||||
<el-table-column type="index" label="#" width="40" />
|
||||
<el-table-column prop="barCode" label="条码" show-overflow-tooltip />
|
||||
<el-table-column prop="spec" label="规格" show-overflow-tooltip />
|
||||
<el-table-column prop="unit" label="单位" show-overflow-tooltip />
|
||||
<el-table-column prop="status" label="状态" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<dict-tag :options="status" :value="scope.row.status"></dict-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- <el-table-column prop="purchasePrice" label="进价/单位分" show-overflow-tooltip /> -->
|
||||
<el-table-column prop="retailPrice" label="零售价(分)" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
{{ displayPrice(row.retailPrice, "") }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="promotionPrice" label="促销价" show-overflow-tooltip>
|
||||
<template #default="{ row }">
|
||||
{{ displayPrice(row.promotionPrice, "") }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="stock" label="库存" show-overflow-tooltip />
|
||||
<el-table-column prop="attribute" label="口味" show-overflow-tooltip />
|
||||
<el-table-column label="操作" width="150">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
icon="edit-pen"
|
||||
text
|
||||
type="primary"
|
||||
v-auth="'supermarket_shopSku_edit'"
|
||||
@click="formDialogRef.openDialog(scope.row.id)"
|
||||
>
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button icon="delete" text type="primary" v-auth="'supermarket_shopSku_del'" @click="handleDelete([scope.row.id])">
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<pagination @size-change="sizeChangeHandle" @current-change="currentChangeHandle" v-bind="state.pagination" />
|
||||
</div>
|
||||
|
||||
<!-- 编辑、新增 -->
|
||||
<form-dialog ref="formDialogRef" @refresh="getDataList(false)" />
|
||||
|
||||
</div>
|
||||
<!-- 编辑、新增 -->
|
||||
<form-dialog ref="formDialogRef" @refresh="getDataList(false)" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="systemShopSku">
|
||||
import { BasicTableProps, useTable } from "/@/hooks/table";
|
||||
import { fetchList, delObjs } from "/@/api/supermarket/shopSku";
|
||||
import { useMessage, useMessageBox } from "/@/hooks/message";
|
||||
import { useDict } from '/@/hooks/dict';
|
||||
import { BasicTableProps, useTable } from "/@/hooks/table"
|
||||
import { fetchList, delObjs } from "/@/api/supermarket/shopSku"
|
||||
import { useMessage, useMessageBox } from "/@/hooks/message"
|
||||
import { useDict } from "/@/hooks/dict"
|
||||
import { displayPrice } from "/@/utils/formatMoney"
|
||||
|
||||
// 引入组件
|
||||
const FormDialog = defineAsyncComponent(() => import('./form.vue'));
|
||||
// 定义查询字典
|
||||
const { status } = useDict("status")
|
||||
|
||||
const FormDialog = defineAsyncComponent(() => import("./form.vue"))
|
||||
|
||||
// 定义变量内容
|
||||
const formDialogRef = ref()
|
||||
// 搜索变量
|
||||
const queryRef = ref()
|
||||
@@ -69,54 +103,47 @@ const selectObjs = ref([]) as any
|
||||
const multiple = ref(true)
|
||||
|
||||
const state: BasicTableProps = reactive<BasicTableProps>({
|
||||
queryForm: {},
|
||||
pageList: fetchList
|
||||
queryForm: {},
|
||||
pageList: fetchList,
|
||||
})
|
||||
|
||||
// table hook
|
||||
const {
|
||||
getDataList,
|
||||
currentChangeHandle,
|
||||
sizeChangeHandle,
|
||||
sortChangeHandle,
|
||||
downBlobFile,
|
||||
tableStyle
|
||||
} = useTable(state)
|
||||
const { getDataList, currentChangeHandle, sizeChangeHandle, sortChangeHandle, downBlobFile, tableStyle } = useTable(state)
|
||||
|
||||
// 清空搜索条件
|
||||
const resetQuery = () => {
|
||||
// 清空搜索条件
|
||||
queryRef.value?.resetFields()
|
||||
// 清空多选
|
||||
selectObjs.value = []
|
||||
getDataList()
|
||||
// 清空搜索条件
|
||||
queryRef.value?.resetFields()
|
||||
// 清空多选
|
||||
selectObjs.value = []
|
||||
getDataList()
|
||||
}
|
||||
|
||||
// 导出excel
|
||||
const exportExcel = () => {
|
||||
downBlobFile('/supermarket/shopSku/export', Object.assign(state.queryForm, { ids: selectObjs }), 'shopSku.xlsx')
|
||||
downBlobFile("/supermarket/shopSku/export", Object.assign(state.queryForm, { ids: selectObjs }), "shopSku.xlsx")
|
||||
}
|
||||
|
||||
// 多选事件
|
||||
const selectionChangHandle = (objs: { id: string }[]) => {
|
||||
selectObjs.value = objs.map(({ id }) => id);
|
||||
multiple.value = !objs.length;
|
||||
};
|
||||
selectObjs.value = objs.map(({ id }) => id)
|
||||
multiple.value = !objs.length
|
||||
}
|
||||
|
||||
// 删除操作
|
||||
const handleDelete = async (ids: string[]) => {
|
||||
try {
|
||||
await useMessageBox().confirm('此操作将永久删除');
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await useMessageBox().confirm("此操作将永久删除")
|
||||
} catch {
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
await delObjs(ids);
|
||||
getDataList();
|
||||
useMessage().success('删除成功');
|
||||
} catch (err: any) {
|
||||
useMessage().error(err.msg);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
try {
|
||||
await delObjs(ids)
|
||||
getDataList()
|
||||
useMessage().success("删除成功")
|
||||
} catch (err: any) {
|
||||
useMessage().error(err.msg)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -60,7 +60,7 @@
|
||||
<preview-image :src="scope.row.picUrl" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="sort" label="排序字段" show-overflow-tooltip />
|
||||
<el-table-column prop="sort" label="排序" show-overflow-tooltip />
|
||||
<el-table-column prop="status" label="商品状态" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
<dict-tag :options="spu_status" :value="scope.row.status"></dict-tag>
|
||||
|
||||
Reference in new issue
Block a user