This commit is contained in:
dzc committed 2025-09-03 10:03:21 +08:00
commit d94dcdcac6
12 files changed
+1490

No files matched your search

+48
View File
@@ -0,0 +1,48 @@
import request from "/@/utils/request"
export function fetchList(query?: Object) {
return request({
url: '/supermarket/mallCategory/page',
method: 'get',
params: query
})
}
export function addObj(obj?: Object) {
return request({
url: '/supermarket/mallCategory',
method: 'post',
data: obj
})
}
export function getObj(id?: string) {
return request({
url: '/supermarket/mallCategory/' + id,
method: 'get'
})
}
export function delObjs(ids?: Object) {
return request({
url: '/supermarket/mallCategory',
method: 'delete',
data: ids
})
}
export function putObj(obj?: Object) {
return request({
url: '/supermarket/mallCategory',
method: 'put',
data: obj
})
}
export function tree(obj?: Object) {
return request({
url: '/supermarket/mallCategory/tree',
method: 'get',
data: obj
})
}
+41
View File
@@ -0,0 +1,41 @@
import request from "/@/utils/request"
export function fetchList(query?: Object) {
return request({
url: '/supermarket/mallMerchant/page',
method: 'get',
params: query
})
}
export function addObj(obj?: Object) {
return request({
url: '/supermarket/mallMerchant',
method: 'post',
data: obj
})
}
export function getObj(id?: string) {
return request({
url: '/supermarket/mallMerchant/' + id,
method: 'get'
})
}
export function delObjs(ids?: Object) {
return request({
url: '/supermarket/mallMerchant',
method: 'delete',
data: ids
})
}
export function putObj(obj?: Object) {
return request({
url: '/supermarket/mallMerchant',
method: 'put',
data: obj
})
}
+41
View File
@@ -0,0 +1,41 @@
import request from "/@/utils/request"
export function fetchList(query?: Object) {
return request({
url: '/supermarket/mallProduct/page',
method: 'get',
params: query
})
}
export function addObj(obj?: Object) {
return request({
url: '/supermarket/mallProduct',
method: 'post',
data: obj
})
}
export function getObj(id?: string) {
return request({
url: '/supermarket/mallProduct/' + id,
method: 'get'
})
}
export function delObjs(ids?: Object) {
return request({
url: '/supermarket/mallProduct',
method: 'delete',
data: ids
})
}
export function putObj(obj?: Object) {
return request({
url: '/supermarket/mallProduct',
method: 'put',
data: obj
})
}
+41
View File
@@ -0,0 +1,41 @@
import request from "/@/utils/request"
export function fetchList(query?: Object) {
return request({
url: '/supermarket/mallProductSku/page',
method: 'get',
params: query
})
}
export function addObj(obj?: Object) {
return request({
url: '/supermarket/mallProductSku',
method: 'post',
data: obj
})
}
export function getObj(id?: string) {
return request({
url: '/supermarket/mallProductSku/' + id,
method: 'get'
})
}
export function delObjs(ids?: Object) {
return request({
url: '/supermarket/mallProductSku',
method: 'delete',
data: ids
})
}
export function putObj(obj?: Object) {
return request({
url: '/supermarket/mallProductSku',
method: 'put',
data: obj
})
}
+160
View File
@@ -0,0 +1,160 @@
<template>
<el-dialog :title="form.id ? '编辑' : '新增'" v-model="visible"
:close-on-click-modal="false" draggable>
<el-form ref="dataFormRef" :model="form" :rules="dataRules" formDialogRef label-width="90px" v-loading="loading">
<el-row :gutter="24">
<el-col :span="12" class="mb20">
<el-form-item label="父级分类" prop="parentId">
<el-select v-model="form.parentId" clearable placeholder="请选择父级分类">
<el-option
v-for="item in categoryOptions"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item label="分类名称" prop="name">
<el-input v-model="form.name" placeholder="请输入分类名称"/>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item label="排序" prop="sort">
<el-input-number :min="1" :max="1000" v-model="form.sort" placeholder="请输入排序"></el-input-number>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item label="状态(0正常,1下架)" 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>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item label="分类图片" prop="picUrl">
<upload-img v-model="form.picUrl"></upload-img>
</el-form-item>
</el-col>
</el-row>
</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="mallCategoryDialog">
import { useDict } from '/@/hooks/dict';
import { useMessage } from "/@/hooks/message";
import { getObj, addObj, putObj, fetchList } from '/@/api/supermarket/mallCategory'
import { rule } from '/@/utils/validate';
import { ref, reactive, nextTick, onMounted } from 'vue';
const emit = defineEmits(['refresh']);
// 定义变量内容
const dataFormRef = ref();
const visible = ref(false)
const loading = ref(false)
// 定义字典
const { status } = useDict('status')
// 提交表单数据
const form = reactive({
id:'',
parentId: '',
name: '',
sort: 0,
status: '0',
picUrl: '',
});
// 定义校验规则
const dataRules = ref({
name: [{required: true, message: '分类名称不能为空', trigger: 'blur'}],
})
// 分类选项
const categoryOptions = ref<any[]>([]);
// 获取所有分类(排除自身)
const loadCategories = async () => {
const res = await fetchList({ size: 9999 });
if (res && res.data && res.data.records) {
// 排除自己,避免自己作为自己的父级
categoryOptions.value = res.data.records.filter((item: any) => item.id !== form.id);
}
};
onMounted(() => {
loadCategories();
});
// 打开弹窗
const openDialog = (id: string) => {
visible.value = true
form.id = ''
// 重置表单数据
nextTick(() => {
dataFormRef.value?.resetFields();
form.status = '0';
});
// 获取mallCategory信息
if (id) {
form.id = id
getmallCategoryData(id)
} else {
// 新增时直接加载分类
loadCategories();
}
};
// 提交
const onSubmit = async () => {
const valid = await dataFormRef.value.validate().catch(() => {});
if (!valid) return false;
try {
loading.value = true;
form.id ? await putObj(form) : await addObj(form);
useMessage().success(form.id ? '修改成功' : '添加成功');
visible.value = false;
emit('refresh');
} catch (err: any) {
useMessage().error(err.msg);
} finally {
loading.value = false;
}
};
// 初始化表单数据
const getmallCategoryData = (id: string) => {
// 获取数据
loading.value = true
getObj(id).then((res: any) => {
Object.assign(form, res.data)
// 编辑时加载分类并排除自己
loadCategories();
}).finally(() => {
loading.value = false
})
};
// 暴露变量
defineExpose({
openDialog
});
</script>
@@ -0,0 +1,179 @@
<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>
<!-- 编辑、新增 -->
<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';
// 引入组件
const FormDialog = defineAsyncComponent(() => import('./form.vue'));
// 定义查询字典
const { status } = useDict('status')
// 定义变量内容
const formDialogRef = ref()
// 搜索变量
const queryRef = ref()
const showSearch = ref(true)
// 多选变量
const selectObjs = ref([]) as any
const multiple = ref(true)
const state: BasicTableProps = reactive<BasicTableProps>({
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 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;
}
}
onMounted(() => {
getDataList();
})
// table hook
const {
currentChangeHandle,
sizeChangeHandle,
sortChangeHandle,
downBlobFile,
tableStyle
} = useTable(state)
// 清空搜索条件
const resetQuery = () => {
queryRef.value?.resetFields()
selectObjs.value = []
getDataList()
}
// 导出excel
const exportExcel = () => {
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;
};
// 删除操作
const handleDelete = async (ids: string[]) => {
try {
await useMessageBox().confirm('此操作将永久删除');
} catch {
return;
}
try {
await delObjs(ids);
getDataList();
useMessage().success('删除成功');
} catch (err: any) {
useMessage().error(err.msg);
}
};
defineExpose({
treeData
});
</script>
+174
View File
@@ -0,0 +1,174 @@
<template>
<el-dialog :title="form.id ? '编辑' : '新增'" v-model="visible"
:close-on-click-modal="false" draggable>
<el-form ref="dataFormRef" :model="form" :rules="dataRules" formDialogRef label-width="90px" v-loading="loading">
<el-row :gutter="24">
<el-col :span="12" class="mb20">
<el-form-item label="商户名称" prop="name">
<el-input v-model="form.name" placeholder="请输入商户名称"/>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item label="商户简称" prop="shortName">
<el-input v-model="form.shortName" placeholder="请输入商户简称"/>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item label="联系人" prop="contactName">
<el-input v-model="form.contactName" placeholder="请输入联系人"/>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item label="联系电话" prop="contactPhone">
<el-input v-model="form.contactPhone" placeholder="请输入联系电话"/>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item label="邮箱" prop="email">
<el-input v-model="form.email" placeholder="请输入邮箱"/>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item label="状态(1启用 0停用)" prop="status">
<el-radio-group v-model="form.status">
<el-radio :label="item.value" v-for="(item, index) in common_data_status" border :key="index">{{ item.label }}
</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item label="营业执照号" prop="licenseNo">
<el-input v-model="form.licenseNo" placeholder="请输入营业执照号"/>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item label="详细地址" prop="address">
<el-input type="textarea" v-model="form.address" placeholder="请输入详细地址"/>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item label="商户图片URL(逗号分隔)" prop="images">
<upload-img v-model="form.images"></upload-img>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" placeholder="请输入备注"/>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item label="部门ID" prop="deptId">
<el-input v-model="form.deptId" placeholder="请输入部门ID"/>
</el-form-item>
</el-col>
</el-row>
</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="MallMerchantDialog">
import { useDict } from '/@/hooks/dict';
import { useMessage } from "/@/hooks/message";
import { getObj, addObj, putObj } from '/@/api/supermarket/mallMerchant'
import { rule } from '/@/utils/validate';
const emit = defineEmits(['refresh']);
// 定义变量内容
const dataFormRef = ref();
const visible = ref(false)
const loading = ref(false)
// 定义字典
const { common_data_status } = useDict('common_data_status')
// 提交表单数据
const form = reactive({
id:'',
name: '',
shortName: '',
contactName: '',
contactPhone: '',
email: '',
status: '',
licenseNo: '',
address: '',
images: '',
remark: '',
deptId: '',
});
// 定义校验规则
const dataRules = ref({
name: [{required: true, message: '商户名称不能为空', trigger: 'blur'}],
contactName: [{required: true, message: '联系人不能为空', trigger: 'blur'}],
contactPhone: [{required: true, message: '联系电话不能为空', trigger: 'blur'}, { validator: rule.mobilePhone, trigger: 'blur' }],
})
// 打开弹窗
const openDialog = (id: string) => {
visible.value = true
form.id = ''
// 重置表单数据
nextTick(() => {
dataFormRef.value?.resetFields();
});
// 获取mallMerchant信息
if (id) {
form.id = id
getmallMerchantData(id)
}
};
// 提交
const onSubmit = async () => {
const valid = await dataFormRef.value.validate().catch(() => {});
if (!valid) return false;
try {
loading.value = true;
form.id ? await putObj(form) : await addObj(form);
useMessage().success(form.id ? '修改成功' : '添加成功');
visible.value = false;
emit('refresh');
} catch (err: any) {
useMessage().error(err.msg);
} finally {
loading.value = false;
}
};
// 初始化表单数据
const getmallMerchantData = (id: string) => {
// 获取数据
loading.value = true
getObj(id).then((res: any) => {
Object.assign(form, res.data)
}).finally(() => {
loading.value = false
})
};
// 暴露变量
defineExpose({
openDialog
});
</script>
@@ -0,0 +1,147 @@
<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"
@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="email" label="邮箱" show-overflow-tooltip/>
<el-table-column prop="status" label="状态(1启用 0停用)" 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="商户图片URL(逗号分隔)" show-overflow-tooltip/>
<el-table-column prop="remark" label="备注" show-overflow-tooltip/>
<el-table-column prop="deptId" label="部门ID" show-overflow-tooltip/>
<el-table-column label="操作" width="150">
<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="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)" />
</div>
</template>
<script setup lang="ts" name="systemMallMerchant">
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 { common_data_status } = useDict('common_data_status')
// 定义变量内容
const formDialogRef = ref()
// 搜索变量
const queryRef = ref()
const showSearch = ref(true)
// 多选变量
const selectObjs = ref([]) as any
const multiple = ref(true)
const state: BasicTableProps = reactive<BasicTableProps>({
queryForm: {},
pageList: fetchList
})
// table hook
const {
getDataList,
currentChangeHandle,
sizeChangeHandle,
sortChangeHandle,
downBlobFile,
tableStyle
} = useTable(state)
// 清空搜索条件
const resetQuery = () => {
// 清空搜索条件
queryRef.value?.resetFields()
// 清空多选
selectObjs.value = []
getDataList()
}
// 导出excel
const exportExcel = () => {
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;
};
// 删除操作
const handleDelete = async (ids: string[]) => {
try {
await useMessageBox().confirm('此操作将永久删除');
} catch {
return;
}
try {
await delObjs(ids);
getDataList();
useMessage().success('删除成功');
} catch (err: any) {
useMessage().error(err.msg);
}
};
</script>
+219
View File
@@ -0,0 +1,219 @@
<template>
<el-dialog :title="form.id ? '编辑' : '新增'" v-model="visible"
:close-on-click-modal="false" draggable>
<el-form ref="dataFormRef" :model="form" :rules="dataRules" formDialogRef label-width="90px" v-loading="loading">
<el-row :gutter="24">
<el-col :span="12" class="mb20">
<el-form-item label="商户ID" prop="merchantId">
<el-select v-model="form.merchantId" placeholder="请选择商户ID">
<el-option label="请选择">0</el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item label="类目ID" prop="categoryId">
<el-select v-model="form.categoryId" placeholder="请选择类目ID">
<el-option label="请选择">0</el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item label="商品标题" prop="title">
<el-input v-model="form.title" placeholder="请输入商品标题"/>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item label="副标题" prop="subTitle">
<el-input v-model="form.subTitle" placeholder="请输入副标题"/>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item label="品牌" prop="brand">
<el-input v-model="form.brand" placeholder="请输入品牌"/>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item label="主图" prop="coverImage">
<el-input v-model="form.coverImage" placeholder="请输入主图"/>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item label="SPU轮播图URL(逗号分隔,按顺序)" prop="carouselImages">
<el-input v-model="form.carouselImages" placeholder="请输入SPU轮播图URL(逗号分隔,按顺序)"/>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item label="定价方式(1多SKU 2单价SPU)" prop="priceType">
<el-input v-model="form.priceType" placeholder="请输入定价方式(1多SKU 2单价SPU)"/>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item label="SPU售价(当price_type=2有效)" prop="spuPrice">
<el-input v-model="form.spuPrice" placeholder="请输入SPU售价(当price_type=2有效)"/>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item label="划线价" prop="originalPrice">
<el-input v-model="form.originalPrice" placeholder="请输入划线价"/>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item label="总库存(冗余)" prop="totalStock">
<el-input v-model="form.totalStock" 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="状态(1上架 0下架)" prop="status">
<el-input v-model="form.status" placeholder="请输入状态(1上架 0下架)"/>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item label="开售时间" prop="saleStartTime">
<el-input v-model="form.saleStartTime" placeholder="请输入开售时间"/>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item label="停售时间" prop="saleEndTime">
<el-input v-model="form.saleEndTime" placeholder="请输入停售时间"/>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item label="详情描述(HTML/文本)" prop="description">
<editor v-if="visible" v-model:get-html="form.description" placeholder="请输入详情描述(HTML/文本)"></editor>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item label="部门ID" prop="deptId">
<el-input v-model="form.deptId" placeholder="请输入部门ID"/>
</el-form-item>
</el-col>
</el-row>
</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 { rule } from '/@/utils/validate';
const emit = defineEmits(['refresh']);
// 定义变量内容
const dataFormRef = ref();
const visible = ref(false)
const loading = ref(false)
// 定义字典
const { spu_status } = useDict('spu_status')
// 提交表单数据
const form = reactive({
id:'',
merchantId: '',
categoryId: '',
title: '',
subTitle: '',
brand: '',
coverImage: '',
carouselImages: '',
priceType: '',
spuPrice: '',
originalPrice: '',
totalStock: '',
unit: '',
status: '',
saleStartTime: '',
saleEndTime: '',
description: '',
deptId: '',
});
// 定义校验规则
const dataRules = ref({
merchantId: [{required: true, message: '商户ID不能为空', trigger: 'blur'}],
categoryId: [{required: true, message: '类目ID不能为空', trigger: 'blur'}],
title: [{required: true, message: '商品标题不能为空', trigger: 'blur'}],
coverImage: [{required: true, message: '主图不能为空', trigger: 'blur'}],
status: [{required: true, message: '状态(1上架 0下架)不能为空', trigger: 'blur'}],
})
// 打开弹窗
const openDialog = (id: string) => {
visible.value = true
form.id = ''
// 重置表单数据
nextTick(() => {
dataFormRef.value?.resetFields();
});
// 获取mallProduct信息
if (id) {
form.id = id
getmallProductData(id)
}
};
// 提交
const onSubmit = async () => {
const valid = await dataFormRef.value.validate().catch(() => {});
if (!valid) return false;
try {
loading.value = true;
form.id ? await putObj(form) : await addObj(form);
useMessage().success(form.id ? '修改成功' : '添加成功');
visible.value = false;
emit('refresh');
} catch (err: any) {
useMessage().error(err.msg);
} finally {
loading.value = false;
}
};
// 初始化表单数据
const getmallProductData = (id: string) => {
// 获取数据
loading.value = true
getObj(id).then((res: any) => {
Object.assign(form, res.data)
}).finally(() => {
loading.value = false
})
};
// 暴露变量
defineExpose({
openDialog
});
</script>
+150
View File
@@ -0,0 +1,150 @@
<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"
@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="merchantId" label="商户ID" show-overflow-tooltip/>
<el-table-column prop="categoryId" label="类目ID" show-overflow-tooltip/>
<el-table-column prop="title" label="商品标题" show-overflow-tooltip/>
<el-table-column prop="subTitle" label="副标题" show-overflow-tooltip/>
<el-table-column prop="brand" label="品牌" show-overflow-tooltip/>
<el-table-column prop="coverImage" label="主图" show-overflow-tooltip/>
<el-table-column prop="carouselImages" label="SPU轮播图URL(逗号分隔,按顺序)" show-overflow-tooltip/>
<el-table-column prop="priceType" label="定价方式(1多SKU 2单价SPU)" show-overflow-tooltip/>
<el-table-column prop="spuPrice" label="SPU售价(当price_type=2有效)" show-overflow-tooltip/>
<el-table-column prop="originalPrice" label="划线价" show-overflow-tooltip/>
<el-table-column prop="totalStock" label="总库存(冗余)" show-overflow-tooltip/>
<el-table-column prop="unit" label="计量单位" show-overflow-tooltip/>
<el-table-column prop="status" label="状态(1上架 0下架)" show-overflow-tooltip>
<template #default="scope">
<dict-tag :options="spu_status" :value="scope.row.status"></dict-tag>
</template>
</el-table-column>
<el-table-column prop="saleStartTime" label="开售时间" show-overflow-tooltip/>
<el-table-column prop="saleEndTime" label="停售时间" show-overflow-tooltip/>
<el-table-column prop="description" label="详情描述(HTML/文本)" show-overflow-tooltip/>
<el-table-column prop="deptId" label="部门ID" show-overflow-tooltip/>
<el-table-column label="操作" width="150">
<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)" />
</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';
// 引入组件
const FormDialog = defineAsyncComponent(() => import('./form.vue'));
// 定义查询字典
const { spu_status } = useDict('spu_status')
// 定义变量内容
const formDialogRef = ref()
// 搜索变量
const queryRef = ref()
const showSearch = ref(true)
// 多选变量
const selectObjs = ref([]) as any
const multiple = ref(true)
const state: BasicTableProps = reactive<BasicTableProps>({
queryForm: {},
pageList: fetchList
})
// table hook
const {
getDataList,
currentChangeHandle,
sizeChangeHandle,
sortChangeHandle,
downBlobFile,
tableStyle
} = useTable(state)
// 清空搜索条件
const resetQuery = () => {
// 清空搜索条件
queryRef.value?.resetFields()
// 清空多选
selectObjs.value = []
getDataList()
}
// 导出excel
const exportExcel = () => {
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;
};
// 删除操作
const handleDelete = async (ids: string[]) => {
try {
await useMessageBox().confirm('此操作将永久删除');
} catch {
return;
}
try {
await delObjs(ids);
getDataList();
useMessage().success('删除成功');
} catch (err: any) {
useMessage().error(err.msg);
}
};
</script>
@@ -0,0 +1,167 @@
<template>
<el-dialog :title="form.id ? '编辑' : '新增'" v-model="visible"
:close-on-click-modal="false" draggable>
<el-form ref="dataFormRef" :model="form" :rules="dataRules" formDialogRef label-width="90px" v-loading="loading">
<el-row :gutter="24">
<el-col :span="12" class="mb20">
<el-form-item label="SPU ID" prop="productId">
<el-input v-model="form.productId" placeholder="请输入SPU ID"/>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item label="SKU编码" prop="skuCode">
<el-input v-model="form.skuCode" placeholder="请输入SKU编码"/>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item label="SKU名称(规格组合)" prop="skuName">
<el-input v-model="form.skuName" placeholder="请输入SKU名称(规格组合)"/>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item label="售价" prop="price">
<el-input v-model="form.price" placeholder="请输入售价"/>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item label="成本价" prop="costPrice">
<el-input v-model="form.costPrice" placeholder="请输入成本价"/>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item label="库存" prop="stock">
<el-input v-model="form.stock" placeholder="请输入库存"/>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item label="条码" prop="barcode">
<el-input v-model="form.barcode" placeholder="请输入条码"/>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item label="重量(克)" prop="weightG">
<el-input v-model="form.weightG" placeholder="请输入重量(克)"/>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item label="体积(立方厘米)" prop="volumeCm3">
<el-input v-model="form.volumeCm3" placeholder="请输入体积(立方厘米)"/>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item label="状态(1启用 0停用)" prop="status">
<el-input v-model="form.status" placeholder="请输入状态(1启用 0停用)"/>
</el-form-item>
</el-col>
<el-col :span="12" class="mb20">
<el-form-item label="部门ID" prop="deptId">
<el-input v-model="form.deptId" placeholder="请输入部门ID"/>
</el-form-item>
</el-col>
</el-row>
</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="MallProductSkuDialog">
import { useDict } from '/@/hooks/dict';
import { useMessage } from "/@/hooks/message";
import { getObj, addObj, putObj } from '/@/api/supermarket/mallProductSku'
import { rule } from '/@/utils/validate';
const emit = defineEmits(['refresh']);
// 定义变量内容
const dataFormRef = ref();
const visible = ref(false)
const loading = ref(false)
// 定义字典
// 提交表单数据
const form = reactive({
id:'',
productId: '',
skuCode: '',
skuName: '',
price: '',
costPrice: '',
stock: '',
barcode: '',
weightG: '',
volumeCm3: '',
status: '',
deptId: '',
});
// 定义校验规则
const dataRules = ref({
})
// 打开弹窗
const openDialog = (id: string) => {
visible.value = true
form.id = ''
// 重置表单数据
nextTick(() => {
dataFormRef.value?.resetFields();
});
// 获取mallProductSku信息
if (id) {
form.id = id
getmallProductSkuData(id)
}
};
// 提交
const onSubmit = async () => {
const valid = await dataFormRef.value.validate().catch(() => {});
if (!valid) return false;
try {
loading.value = true;
form.id ? await putObj(form) : await addObj(form);
useMessage().success(form.id ? '修改成功' : '添加成功');
visible.value = false;
emit('refresh');
} catch (err: any) {
useMessage().error(err.msg);
} finally {
loading.value = false;
}
};
// 初始化表单数据
const getmallProductSkuData = (id: string) => {
// 获取数据
loading.value = true
getObj(id).then((res: any) => {
Object.assign(form, res.data)
}).finally(() => {
loading.value = false
})
};
// 暴露变量
defineExpose({
openDialog
});
</script>
@@ -0,0 +1,123 @@
<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_mallProductSku_add'">
新 增
</el-button>
<el-button plain :disabled="multiple" icon="Delete" type="primary"
v-auth="'supermarket_mallProductSku_del'" @click="handleDelete(selectObjs)">
删除
</el-button>
<right-toolbar v-model:showSearch="showSearch" :export="'supermarket_mallProductSku_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="productId" label="SPU ID" show-overflow-tooltip/>
<el-table-column prop="skuCode" label="SKU编码" show-overflow-tooltip/>
<el-table-column prop="skuName" label="SKU名称(规格组合)" show-overflow-tooltip/>
<el-table-column prop="price" label="售价" show-overflow-tooltip/>
<el-table-column prop="costPrice" label="成本价" show-overflow-tooltip/>
<el-table-column prop="stock" label="库存" show-overflow-tooltip/>
<el-table-column prop="barcode" label="条码" show-overflow-tooltip/>
<el-table-column prop="weightG" label="重量(克)" show-overflow-tooltip/>
<el-table-column prop="volumeCm3" label="体积(立方厘米)" show-overflow-tooltip/>
<el-table-column prop="status" label="状态(1启用 0停用)" show-overflow-tooltip/>
<el-table-column prop="deptId" label="部门ID" show-overflow-tooltip/>
<el-table-column label="操作" width="150">
<template #default="scope">
<el-button icon="edit-pen" text type="primary" v-auth="'supermarket_mallProductSku_edit'"
@click="formDialogRef.openDialog(scope.row.id)">编辑</el-button>
<el-button icon="delete" text type="primary" v-auth="'supermarket_mallProductSku_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>
</template>
<script setup lang="ts" name="systemMallProductSku">
import { BasicTableProps, useTable } from "/@/hooks/table";
import { fetchList, delObjs } from "/@/api/supermarket/mallProductSku";
import { useMessage, useMessageBox } from "/@/hooks/message";
import { useDict } from '/@/hooks/dict';
// 引入组件
const FormDialog = defineAsyncComponent(() => import('./form.vue'));
// 定义查询字典
// 定义变量内容
const formDialogRef = ref()
// 搜索变量
const queryRef = ref()
const showSearch = ref(true)
// 多选变量
const selectObjs = ref([]) as any
const multiple = ref(true)
const state: BasicTableProps = reactive<BasicTableProps>({
queryForm: {},
pageList: fetchList
})
// table hook
const {
getDataList,
currentChangeHandle,
sizeChangeHandle,
sortChangeHandle,
downBlobFile,
tableStyle
} = useTable(state)
// 清空搜索条件
const resetQuery = () => {
// 清空搜索条件
queryRef.value?.resetFields()
// 清空多选
selectObjs.value = []
getDataList()
}
// 导出excel
const exportExcel = () => {
downBlobFile('/supermarket/mallProductSku/export', Object.assign(state.queryForm, { ids: selectObjs }), 'mallProductSku.xlsx')
}
// 多选事件
const selectionChangHandle = (objs: { id: string }[]) => {
selectObjs.value = objs.map(({ id }) => id);
multiple.value = !objs.length;
};
// 删除操作
const handleDelete = async (ids: string[]) => {
try {
await useMessageBox().confirm('此操作将永久删除');
} catch {
return;
}
try {
await delObjs(ids);
getDataList();
useMessage().success('删除成功');
} catch (err: any) {
useMessage().error(err.msg);
}
};
</script>