fix:修复在线商城分类图片商品图片显示
This commit is contained in:
1 parent
089008ad0e
commit
875aac6771
4 files changed
+815
-791
No files matched your search
@@ -1,160 +1,153 @@
|
||||
<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-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="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="排序" 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-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:imageUrl="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>
|
||||
</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="ShopCategoryDialog">
|
||||
import { useDict } from '/@/hooks/dict';
|
||||
import { useMessage } from "/@/hooks/message";
|
||||
import { getObj, addObj, putObj, fetchList } from '/@/api/supermarket/shopCategory'
|
||||
import { rule } from '/@/utils/validate';
|
||||
import { ref, reactive, nextTick, onMounted } from 'vue';
|
||||
const emit = defineEmits(['refresh']);
|
||||
import { useDict } from "/@/hooks/dict"
|
||||
import { useMessage } from "/@/hooks/message"
|
||||
import { getObj, addObj, putObj, fetchList } from "/@/api/supermarket/shopCategory"
|
||||
import { rule } from "/@/utils/validate"
|
||||
import { ref, reactive, nextTick, onMounted } from "vue"
|
||||
const emit = defineEmits(["refresh"])
|
||||
|
||||
// 定义变量内容
|
||||
const dataFormRef = ref();
|
||||
const dataFormRef = ref()
|
||||
const visible = ref(false)
|
||||
const loading = ref(false)
|
||||
// 定义字典
|
||||
const { status } = useDict('status')
|
||||
const { status } = useDict("status")
|
||||
|
||||
// 提交表单数据
|
||||
const form = reactive({
|
||||
id:'',
|
||||
parentId: '',
|
||||
name: '',
|
||||
sort: 0,
|
||||
status: '0',
|
||||
picUrl: '',
|
||||
});
|
||||
id: "",
|
||||
parentId: "",
|
||||
name: "",
|
||||
sort: 0,
|
||||
status: "0",
|
||||
picUrl: "",
|
||||
})
|
||||
|
||||
// 定义校验规则
|
||||
const dataRules = ref({
|
||||
name: [{required: true, message: '分类名称不能为空', trigger: 'blur'}],
|
||||
name: [{ required: true, message: "分类名称不能为空", trigger: "blur" }],
|
||||
})
|
||||
|
||||
// 分类选项
|
||||
const categoryOptions = ref<any[]>([]);
|
||||
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);
|
||||
}
|
||||
};
|
||||
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();
|
||||
});
|
||||
loadCategories()
|
||||
})
|
||||
|
||||
// 打开弹窗
|
||||
const openDialog = (id: string) => {
|
||||
visible.value = true
|
||||
form.id = ''
|
||||
visible.value = true
|
||||
form.id = ""
|
||||
|
||||
// 重置表单数据
|
||||
nextTick(() => {
|
||||
dataFormRef.value?.resetFields();
|
||||
form.status = '0';
|
||||
});
|
||||
// 重置表单数据
|
||||
nextTick(() => {
|
||||
dataFormRef.value?.resetFields()
|
||||
form.status = "0"
|
||||
})
|
||||
|
||||
// 获取shopCategory信息
|
||||
if (id) {
|
||||
form.id = id
|
||||
getshopCategoryData(id)
|
||||
} else {
|
||||
// 新增时直接加载分类
|
||||
loadCategories();
|
||||
}
|
||||
};
|
||||
// 获取shopCategory信息
|
||||
if (id) {
|
||||
form.id = id
|
||||
getshopCategoryData(id)
|
||||
} else {
|
||||
// 新增时直接加载分类
|
||||
loadCategories()
|
||||
}
|
||||
}
|
||||
|
||||
// 提交
|
||||
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
|
||||
|
||||
try {
|
||||
loading.value = true;
|
||||
form.id ? await putObj(form) : await addObj(form);
|
||||
useMessage().success(form.id ? '修改成功' : '添加成功');
|
||||
visible.value = false;
|
||||
emit('refresh');
|
||||
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);
|
||||
useMessage().error(err.msg)
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化表单数据
|
||||
const getshopCategoryData = (id: string) => {
|
||||
// 获取数据
|
||||
loading.value = true
|
||||
getObj(id).then((res: any) => {
|
||||
Object.assign(form, res.data)
|
||||
// 编辑时加载分类并排除自己
|
||||
loadCategories();
|
||||
}).finally(() => {
|
||||
loading.value = false
|
||||
})
|
||||
};
|
||||
// 获取数据
|
||||
loading.value = true
|
||||
getObj(id)
|
||||
.then((res: any) => {
|
||||
Object.assign(form, res.data)
|
||||
// 编辑时加载分类并排除自己
|
||||
loadCategories()
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
// 暴露变量
|
||||
defineExpose({
|
||||
openDialog
|
||||
});
|
||||
</script>
|
||||
openDialog,
|
||||
})
|
||||
</script>
|
||||
@@ -1,84 +1,110 @@
|
||||
<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_shopCategory_add'">
|
||||
新 增
|
||||
</el-button>
|
||||
<el-button plain :disabled="multiple" icon="Delete" type="primary"
|
||||
v-auth="'supermarket_shopCategory_del'" @click="handleDelete(selectObjs)">
|
||||
删除
|
||||
</el-button>
|
||||
<right-toolbar v-model:showSearch="showSearch" :export="'supermarket_shopCategory_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_shopCategory_edit'"
|
||||
@click="formDialogRef.openDialog(scope.row.id)">编辑</el-button>
|
||||
<el-button icon="delete" text type="primary" v-auth="'supermarket_shopCategory_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_shopCategory_add'"
|
||||
>
|
||||
新 增
|
||||
</el-button>
|
||||
<el-button
|
||||
plain
|
||||
:disabled="multiple"
|
||||
icon="Delete"
|
||||
type="primary"
|
||||
v-auth="'supermarket_shopCategory_del'"
|
||||
@click="handleDelete(selectObjs)"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
<right-toolbar
|
||||
v-model:showSearch="showSearch"
|
||||
:export="'supermarket_shopCategory_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="状态" 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_shopCategory_edit'"
|
||||
@click="formDialogRef.openDialog(scope.row.id)"
|
||||
>
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button icon="delete" text type="primary" v-auth="'supermarket_shopCategory_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="systemShopCategory">
|
||||
import { BasicTableProps, useTable } from "/@/hooks/table";
|
||||
import { fetchList, delObjs, tree as fetchTree, putObj } from "/@/api/supermarket/shopCategory";
|
||||
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/shopCategory"
|
||||
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 +115,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/shopCategory/export', Object.assign(state.queryForm, { ids: selectObjs }), 'shopCategory.xlsx')
|
||||
downBlobFile("/supermarket/shopCategory/export", Object.assign(state.queryForm, { ids: selectObjs }), "shopCategory.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
|
||||
});
|
||||
</script>
|
||||
treeData,
|
||||
})
|
||||
</script>
|
||||
@@ -1,505 +1,499 @@
|
||||
<template>
|
||||
<el-dialog :title="form.id ? '编辑' : '新增'" v-model="visible"
|
||||
:close-on-click-modal="false" draggable
|
||||
width="1100px">
|
||||
<el-tabs v-model="activeTab" type="card" style="margin-bottom: 24px;" :before-leave="handleTabLeave">
|
||||
<el-tab-pane label="基本信息" name="base">
|
||||
<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="productCode" required>
|
||||
<el-input v-model="form.productCode" placeholder="请输入货号"/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12" class="mb20">
|
||||
<el-form-item label="商品名称" prop="productName" required>
|
||||
<el-input v-model="form.productName" 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 }"
|
||||
clearable
|
||||
placeholder="请选择商品分类"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8" class="mb20">
|
||||
<el-form-item label="商品性质" prop="productNature">
|
||||
<el-select v-model="form.productNature" placeholder="请选择商品性质">
|
||||
<el-option :value="item.value" :label="item.label" v-for="(item, index) in supermarket_nature" :key="index" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24" class="mb20">
|
||||
<el-form-item label="商品封面图" prop="picUrl" required>
|
||||
<upload-img v-model:imageUrl="form.picUrl"></upload-img>
|
||||
</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="请输入商品详情"></editor>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12" class="mb20">
|
||||
<el-form-item label="库存" prop="stock">
|
||||
<el-input-number :min="0" :max="1000" v-model="form.stock" placeholder="请输入库存"></el-input-number>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12" class="mb20">
|
||||
<el-form-item label="单人限购数" prop="limitNum">
|
||||
<el-input-number :min="1" :max="1000" v-model="form.limitNum" placeholder="请输入单人限购数量"></el-input-number>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="SKU信息" name="sku">
|
||||
<el-divider>SKU 列表</el-divider>
|
||||
<el-table :data="form.skuList" style="width: 100%; min-width: 1000px; margin-bottom: 16px;" :header-cell-style="tableHeaderStyle">
|
||||
<el-table-column prop="barCode" width="120">
|
||||
<template #header>
|
||||
<span class="required">*</span> 条码
|
||||
</template>
|
||||
<template #default="scope">
|
||||
<el-form-item
|
||||
:prop="`skuList.${scope.$index}.barCode`"
|
||||
:rules="[{ required: true, message: '条码不能为空', trigger: 'blur' }]"
|
||||
>
|
||||
<el-input v-model="scope.row.barCode" placeholder="请输入条码" clearable />
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="spec" width="100">
|
||||
<template #header>规格</template>
|
||||
<template #default="scope">
|
||||
<el-input v-model="scope.row.spec" placeholder="请输入规格" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="unit" width="120">
|
||||
<template #header>
|
||||
<span class="required">*</span> 单位
|
||||
</template>
|
||||
<template #default="scope">
|
||||
<el-form-item
|
||||
:prop="`skuList.${scope.$index}.unit`"
|
||||
:rules="[{ required: true, message: '单位不能为空', trigger: 'blur' }]"
|
||||
>
|
||||
<el-input v-model="scope.row.unit" placeholder="请输入单位" clearable />
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="status" width="100">
|
||||
<template #header>状态</template>
|
||||
<template #default="scope">
|
||||
<el-select v-model="scope.row.status" placeholder="请选择">
|
||||
<el-option label="正常" :value="0" />
|
||||
<el-option label="停销" :value="1" />
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="retailPrice" width="140">
|
||||
<template #header>
|
||||
<span class="required">*</span> 零售价
|
||||
</template>
|
||||
<template #default="scope">
|
||||
<el-form-item
|
||||
:prop="`skuList.${scope.$index}.retailPrice`"
|
||||
:rules="[{ required: true, message: '零售价不能为空', trigger: 'blur' }]"
|
||||
>
|
||||
<el-input v-model="scope.row.retailPrice" placeholder="零售价/单位分" clearable style="width: 80px;" />
|
||||
<span style="margin-left: 4px; color: #888;">元</span>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="promotionPrice" width="140">
|
||||
<template #header>促销价</template>
|
||||
<template #default="scope">
|
||||
<el-input v-model="scope.row.promotionPrice" placeholder="促销价" clearable style="width: 80px;" />
|
||||
<span style="margin-left: 4px; color: #888;">元</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="stock" width="120">
|
||||
<template #header>
|
||||
<span class="required">*</span> 库存
|
||||
</template>
|
||||
<template #default="scope">
|
||||
<el-form-item
|
||||
:prop="`skuList.${scope.$index}.stock`"
|
||||
:rules="[{ required: true, message: '库存不能为空', trigger: 'blur' }]"
|
||||
>
|
||||
<el-input v-model="scope.row.stock" placeholder="库存" clearable />
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="attribute" width="120">
|
||||
<template #header>口味</template>
|
||||
<template #default="scope">
|
||||
<el-input v-model="scope.row.attribute" placeholder="口味" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="80">
|
||||
<template #header>操作</template>
|
||||
<template #default="scope">
|
||||
<el-button type="danger" size="small" @click="removeSku(scope.$index)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-button type="primary" @click="addSku">新增SKU</el-button>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="在销商户" name="merchant">
|
||||
<el-button type="primary" @click="showMerchantDialog = true">选择在销商户</el-button>
|
||||
<el-table :data="selectedMerchants" style="margin-top: 16px;">
|
||||
<el-table-column prop="name" label="商户名称" />
|
||||
<el-table-column prop="deptName" label="部门" />
|
||||
<el-table-column label="操作" width="80">
|
||||
<template #default="scope">
|
||||
<el-button type="danger" size="small" @click="removeMerchant(scope.$index)">移除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-dialog v-model="showMerchantDialog" title="选择在销商户" width="700px">
|
||||
<el-input v-model="merchantSearch" placeholder="搜索商户名称" style="margin-bottom: 12px;" @input="fetchMerchantList" />
|
||||
<el-table :data="merchantList" @selection-change="handleMerchantSelect" :row-key="(row: Record<string, any>) => row.id" height="400">
|
||||
<el-table-column type="selection" width="40" />
|
||||
<el-table-column prop="name" label="商户名称" />
|
||||
<el-table-column prop="deptName" label="部门" />
|
||||
</el-table>
|
||||
<template #footer>
|
||||
<el-button @click="showMerchantDialog = false">取消</el-button>
|
||||
<el-button type="primary" @click="confirmMerchantSelect">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
<template #footer>
|
||||
<el-button v-if="activeTab === 'sku'" @click="activeTab = 'base'">上一步</el-button>
|
||||
<el-button v-if="activeTab === 'merchant'" @click="activeTab = 'sku'">上一步</el-button>
|
||||
<el-button v-if="activeTab === 'base'" type="primary" @click="handleNextTab">下一步</el-button>
|
||||
<el-button v-else-if="activeTab === 'sku'" type="primary" @click="handleNextTab">下一步</el-button>
|
||||
<el-button v-else-if="activeTab === 'merchant'" type="primary" @click="onSubmit" :disabled="loading">完成</el-button>
|
||||
<el-button @click="visible = false">取消</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
<el-dialog :title="form.id ? '编辑' : '新增'" v-model="visible" :close-on-click-modal="false" draggable width="1100px">
|
||||
<el-tabs v-model="activeTab" type="card" style="margin-bottom: 24px" :before-leave="handleTabLeave">
|
||||
<el-tab-pane label="基本信息" name="base">
|
||||
<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="productCode" required>
|
||||
<el-input v-model="form.productCode" placeholder="请输入货号" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12" class="mb20">
|
||||
<el-form-item label="商品名称" prop="productName" required>
|
||||
<el-input v-model="form.productName" 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 }"
|
||||
clearable
|
||||
placeholder="请选择商品分类"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8" class="mb20">
|
||||
<el-form-item label="商品性质" prop="productNature">
|
||||
<el-select v-model="form.productNature" placeholder="请选择商品性质">
|
||||
<el-option :value="item.value" :label="item.label" v-for="(item, index) in supermarket_nature" :key="index" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="24" class="mb20">
|
||||
<el-form-item label="商品封面图" prop="picUrl" required>
|
||||
<upload-img v-model:imageUrl="form.picUrl"></upload-img>
|
||||
</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="请输入商品详情"></editor>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12" class="mb20">
|
||||
<el-form-item label="库存" prop="stock">
|
||||
<el-input-number :min="0" :max="1000" v-model="form.stock" placeholder="请输入库存"></el-input-number>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12" class="mb20">
|
||||
<el-form-item label="单人限购数" prop="limitNum">
|
||||
<el-input-number :min="1" :max="1000" v-model="form.limitNum" placeholder="请输入单人限购数量"></el-input-number>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-form>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="SKU信息" name="sku">
|
||||
<el-divider>SKU 列表</el-divider>
|
||||
<el-table :data="form.skuList" style="width: 100%; min-width: 1000px; margin-bottom: 16px" :header-cell-style="tableHeaderStyle">
|
||||
<el-table-column prop="barCode" width="120">
|
||||
<template #header> <span class="required">*</span> 条码 </template>
|
||||
<template #default="scope">
|
||||
<el-form-item
|
||||
:prop="`skuList.${scope.$index}.barCode`"
|
||||
:rules="[{ required: true, message: '条码不能为空', trigger: 'blur' }]"
|
||||
>
|
||||
<el-input v-model="scope.row.barCode" placeholder="请输入条码" clearable />
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="spec" width="100">
|
||||
<template #header>规格</template>
|
||||
<template #default="scope">
|
||||
<el-input v-model="scope.row.spec" placeholder="请输入规格" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="unit" width="120">
|
||||
<template #header> <span class="required">*</span> 单位 </template>
|
||||
<template #default="scope">
|
||||
<el-form-item :prop="`skuList.${scope.$index}.unit`" :rules="[{ required: true, message: '单位不能为空', trigger: 'blur' }]">
|
||||
<el-input v-model="scope.row.unit" placeholder="请输入单位" clearable />
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="status" width="100">
|
||||
<template #header>状态</template>
|
||||
<template #default="scope">
|
||||
<el-select v-model="scope.row.status" placeholder="请选择">
|
||||
<el-option label="正常" :value="0" />
|
||||
<el-option label="停销" :value="1" />
|
||||
</el-select>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="retailPrice" width="140">
|
||||
<template #header> <span class="required">*</span> 零售价 </template>
|
||||
<template #default="scope">
|
||||
<el-form-item
|
||||
:prop="`skuList.${scope.$index}.retailPrice`"
|
||||
:rules="[{ required: true, message: '零售价不能为空', trigger: 'blur' }]"
|
||||
>
|
||||
<el-input v-model="scope.row.retailPrice" placeholder="零售价/单位分" clearable style="width: 80px" />
|
||||
<span style="margin-left: 4px; color: #888">元</span>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="promotionPrice" width="140">
|
||||
<template #header>促销价</template>
|
||||
<template #default="scope">
|
||||
<el-input v-model="scope.row.promotionPrice" placeholder="促销价" clearable style="width: 80px" />
|
||||
<span style="margin-left: 4px; color: #888">元</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="stock" width="120">
|
||||
<template #header> <span class="required">*</span> 库存 </template>
|
||||
<template #default="scope">
|
||||
<el-form-item :prop="`skuList.${scope.$index}.stock`" :rules="[{ required: true, message: '库存不能为空', trigger: 'blur' }]">
|
||||
<el-input v-model="scope.row.stock" placeholder="库存" clearable />
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="attribute" width="120">
|
||||
<template #header>口味</template>
|
||||
<template #default="scope">
|
||||
<el-input v-model="scope.row.attribute" placeholder="口味" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="80">
|
||||
<template #header>操作</template>
|
||||
<template #default="scope">
|
||||
<el-button type="danger" size="small" @click="removeSku(scope.$index)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-button type="primary" @click="addSku">新增SKU</el-button>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="在销商户" name="merchant">
|
||||
<el-button type="primary" @click="showMerchantDialog = true">选择在销商户</el-button>
|
||||
<el-table :data="selectedMerchants" style="margin-top: 16px">
|
||||
<el-table-column prop="name" label="商户名称" />
|
||||
<el-table-column prop="deptName" label="部门" />
|
||||
<el-table-column label="操作" width="80">
|
||||
<template #default="scope">
|
||||
<el-button type="danger" size="small" @click="removeMerchant(scope.$index)">移除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-dialog v-model="showMerchantDialog" title="选择在销商户" width="700px">
|
||||
<el-input v-model="merchantSearch" placeholder="搜索商户名称" style="margin-bottom: 12px" @input="fetchMerchantList" />
|
||||
<el-table
|
||||
:data="merchantList"
|
||||
@selection-change="handleMerchantSelect"
|
||||
:row-key="(row: Record<string, any>) => row.id"
|
||||
height="400"
|
||||
>
|
||||
<el-table-column type="selection" width="40" />
|
||||
<el-table-column prop="name" label="商户名称" />
|
||||
<el-table-column prop="deptName" label="部门" />
|
||||
</el-table>
|
||||
<template #footer>
|
||||
<el-button @click="showMerchantDialog = false">取消</el-button>
|
||||
<el-button type="primary" @click="confirmMerchantSelect">确定</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
<template #footer>
|
||||
<el-button v-if="activeTab === 'sku'" @click="activeTab = 'base'">上一步</el-button>
|
||||
<el-button v-if="activeTab === 'merchant'" @click="activeTab = 'sku'">上一步</el-button>
|
||||
<el-button v-if="activeTab === 'base'" type="primary" @click="handleNextTab">下一步</el-button>
|
||||
<el-button v-else-if="activeTab === 'sku'" type="primary" @click="handleNextTab">下一步</el-button>
|
||||
<el-button v-else-if="activeTab === 'merchant'" type="primary" @click="onSubmit" :disabled="loading">完成</el-button>
|
||||
<el-button @click="visible = false">取消</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="ShopSpuDialog">
|
||||
import { useDict } from '/@/hooks/dict';
|
||||
import { useMessage } from "/@/hooks/message";
|
||||
import { getObj, addObj, putObj } from '/@/api/supermarket/shopSpu';
|
||||
import { rule } from '/@/utils/validate';
|
||||
import { tree as fetchCategoryTree } from '/@/api/supermarket/shopCategory';
|
||||
import { select as fetchMerchantSelect } from '/@/api/wallet/mch-manage';
|
||||
import { useDict } from "/@/hooks/dict"
|
||||
import { useMessage } from "/@/hooks/message"
|
||||
import { getObj, addObj, putObj } from "/@/api/supermarket/shopSpu"
|
||||
import { rule } from "/@/utils/validate"
|
||||
import { tree as fetchCategoryTree } from "/@/api/supermarket/shopCategory"
|
||||
import { select as fetchMerchantSelect } from "/@/api/wallet/mch-manage"
|
||||
import { displayPrice } from "/@/utils/formatMoney"
|
||||
|
||||
const emit = defineEmits(['refresh']);
|
||||
const emit = defineEmits(["refresh"])
|
||||
|
||||
// 定义变量内容
|
||||
const dataFormRef = ref();
|
||||
const dataFormRef = ref()
|
||||
const visible = ref(false)
|
||||
const loading = ref(false)
|
||||
// 定义字典
|
||||
const { supermarket_nature,spu_status} = useDict("supermarket_nature",'spu_status')
|
||||
const { supermarket_nature, spu_status } = useDict("supermarket_nature", "spu_status")
|
||||
// 提交表单数据
|
||||
const form = reactive({
|
||||
id: '',
|
||||
productCode: '',
|
||||
productName: '',
|
||||
productNature: "",
|
||||
description: '',
|
||||
categoryId: '',
|
||||
picUrl: '',
|
||||
sliderPicUrls: '',
|
||||
sort: 0,
|
||||
status: '',
|
||||
stock: 0,
|
||||
giveIntegral: '',
|
||||
merchantRelationId: '',
|
||||
deptId: '',
|
||||
shopSkuId: '',
|
||||
salesCount: '',
|
||||
limitNum: 0,
|
||||
skuList: [] as any[],
|
||||
});
|
||||
id: "",
|
||||
productCode: "",
|
||||
productName: "",
|
||||
productNature: "",
|
||||
description: "",
|
||||
categoryId: "",
|
||||
picUrl: "",
|
||||
sliderPicUrls: "",
|
||||
sort: 0,
|
||||
status: "",
|
||||
stock: 0,
|
||||
giveIntegral: "",
|
||||
merchantRelationId: "",
|
||||
deptId: "",
|
||||
shopSkuId: "",
|
||||
salesCount: "",
|
||||
limitNum: 0,
|
||||
skuList: [] as any[],
|
||||
})
|
||||
|
||||
// 定义校验规则
|
||||
const dataRules = ref({
|
||||
productNature: [{ required: true, message: "请选择商品性质", trigger: "blur" }],
|
||||
productCode: [{ required: true, message: '货号不能为空', trigger: 'blur' }],
|
||||
productName: [{ required: true, message: '商品名称不能为空', trigger: 'blur' }],
|
||||
categoryId: [{ required: true, message: '商品分类不能为空', trigger: 'change' }],
|
||||
picUrl: [{ required: true, message: '商品封面图不能为空', trigger: 'change' }],
|
||||
sort: [{validator: rule.number, trigger: 'blur'}],
|
||||
stock: [{validator: rule.number, trigger: 'blur'}],
|
||||
limitNum: [{validator: rule.number, trigger: 'blur'}],
|
||||
productNature: [{ required: true, message: "请选择商品性质", trigger: "blur" }],
|
||||
productCode: [{ required: true, message: "货号不能为空", trigger: "blur" }],
|
||||
productName: [{ required: true, message: "商品名称不能为空", trigger: "blur" }],
|
||||
categoryId: [{ required: true, message: "商品分类不能为空", trigger: "change" }],
|
||||
picUrl: [{ required: true, message: "商品封面图不能为空", trigger: "change" }],
|
||||
sort: [{ validator: rule.number, trigger: "blur" }],
|
||||
stock: [{ validator: rule.number, trigger: "blur" }],
|
||||
limitNum: [{ validator: rule.number, trigger: "blur" }],
|
||||
})
|
||||
|
||||
const categoryOptions = ref<any[]>([]);
|
||||
const categoryOptions = ref<any[]>([])
|
||||
|
||||
const loadCategoryTree = async () => {
|
||||
const res = await fetchCategoryTree();
|
||||
categoryOptions.value = res.data || [];
|
||||
};
|
||||
const res = await fetchCategoryTree()
|
||||
categoryOptions.value = res.data || []
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
loadCategoryTree();
|
||||
});
|
||||
loadCategoryTree()
|
||||
})
|
||||
|
||||
const activeTab = ref('base');
|
||||
const activeTab = ref("base")
|
||||
|
||||
// 打开弹窗
|
||||
const openDialog = (id: string) => {
|
||||
visible.value = true
|
||||
activeTab.value = 'base';
|
||||
if (!id) {
|
||||
// 新增时彻底重置所有表单数据
|
||||
Object.assign(form, {
|
||||
id: '',
|
||||
productCode: '',
|
||||
productName: '',
|
||||
description: '',
|
||||
categoryId: '',
|
||||
picUrl: '',
|
||||
sliderPicUrls: '',
|
||||
sort: 0,
|
||||
status: '',
|
||||
stock: 0,
|
||||
giveIntegral: '',
|
||||
merchantRelationId: '',
|
||||
deptId: '',
|
||||
shopSkuId: '',
|
||||
salesCount: '',
|
||||
limitNum: 0,
|
||||
skuList: []
|
||||
});
|
||||
selectedMerchants.value = [];
|
||||
selectedMerchantIds.value = [];
|
||||
// skuList至少有一条
|
||||
addSku();
|
||||
nextTick(() => {
|
||||
dataFormRef.value?.resetFields();
|
||||
});
|
||||
} else {
|
||||
form.id = id;
|
||||
nextTick(() => {
|
||||
dataFormRef.value?.resetFields();
|
||||
});
|
||||
getshopSpuData(id);
|
||||
}
|
||||
// 重新加载分类树
|
||||
loadCategoryTree();
|
||||
};
|
||||
visible.value = true
|
||||
activeTab.value = "base"
|
||||
if (!id) {
|
||||
// 新增时彻底重置所有表单数据
|
||||
Object.assign(form, {
|
||||
id: "",
|
||||
productCode: "",
|
||||
productName: "",
|
||||
description: "",
|
||||
categoryId: "",
|
||||
picUrl: "",
|
||||
sliderPicUrls: "",
|
||||
sort: 0,
|
||||
status: "",
|
||||
stock: 0,
|
||||
giveIntegral: "",
|
||||
merchantRelationId: "",
|
||||
deptId: "",
|
||||
shopSkuId: "",
|
||||
salesCount: "",
|
||||
limitNum: 0,
|
||||
skuList: [],
|
||||
})
|
||||
selectedMerchants.value = []
|
||||
selectedMerchantIds.value = []
|
||||
// skuList至少有一条
|
||||
addSku()
|
||||
nextTick(() => {
|
||||
dataFormRef.value?.resetFields()
|
||||
})
|
||||
} else {
|
||||
form.id = id
|
||||
nextTick(() => {
|
||||
dataFormRef.value?.resetFields()
|
||||
})
|
||||
getshopSpuData(id)
|
||||
}
|
||||
// 重新加载分类树
|
||||
loadCategoryTree()
|
||||
}
|
||||
|
||||
// 提交
|
||||
const onSubmit = async () => {
|
||||
const valid = await dataFormRef.value.validate().catch(() => {});
|
||||
if (!valid) return false;
|
||||
if (!selectedMerchants.value.length) {
|
||||
useMessage().error('请至少选择一个在销商户');
|
||||
activeTab.value = 'merchant';
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
loading.value = true;
|
||||
// merchantIds 逗号分隔字符串
|
||||
const merchantIds = selectedMerchants.value.map(m => m.id).join(',');
|
||||
const submitForm = {
|
||||
...form,
|
||||
categoryId: Array.isArray(form.categoryId) ? form.categoryId.slice(-1)[0] : form.categoryId,
|
||||
merchantIds
|
||||
};
|
||||
form.id ? await putObj(submitForm) : await addObj(submitForm);
|
||||
useMessage().success(form.id ? '修改成功' : '添加成功');
|
||||
visible.value = false;
|
||||
emit('refresh');
|
||||
} catch (err: any) {
|
||||
useMessage().error(err.msg);
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
const valid = await dataFormRef.value.validate().catch(() => {})
|
||||
if (!valid) return false
|
||||
if (!selectedMerchants.value.length) {
|
||||
useMessage().error("请至少选择一个在销商户")
|
||||
activeTab.value = "merchant"
|
||||
return false
|
||||
}
|
||||
try {
|
||||
loading.value = true
|
||||
// merchantIds 逗号分隔字符串
|
||||
const merchantIds = selectedMerchants.value.map((m) => m.id).join(",")
|
||||
const submitForm = {
|
||||
...form,
|
||||
categoryId: Array.isArray(form.categoryId) ? form.categoryId.slice(-1)[0] : form.categoryId,
|
||||
merchantIds,
|
||||
}
|
||||
form.id ? await putObj(submitForm) : await addObj(submitForm)
|
||||
useMessage().success(form.id ? "修改成功" : "添加成功")
|
||||
visible.value = false
|
||||
emit("refresh")
|
||||
} catch (err: any) {
|
||||
useMessage().error(err.msg)
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 初始化表单数据
|
||||
const getshopSpuData = (id: string) => {
|
||||
// 获取数据
|
||||
loading.value = true
|
||||
getObj(id).then((res: any) => {
|
||||
Object.assign(form, res.data)
|
||||
form.skuList = res.data.skuList || []
|
||||
// skuList至少有一条
|
||||
if (!form.skuList || form.skuList.length === 0) {
|
||||
addSku();
|
||||
}
|
||||
// 处理 categoryId 回显为数组
|
||||
if (res.data.categoryId && categoryOptions.value.length) {
|
||||
form.categoryId = findCategoryPath(categoryOptions.value, res.data.categoryId);
|
||||
}
|
||||
// 处理 merchantIds 回显
|
||||
if (res.data.merchantIds) {
|
||||
const idsArr = typeof res.data.merchantIds === 'string' ? res.data.merchantIds.split(',').filter(Boolean) : [];
|
||||
selectedMerchantIds.value = idsArr;
|
||||
if (merchantList.value.length) {
|
||||
selectedMerchants.value = merchantList.value.filter(m => idsArr.includes(String(m.id)));
|
||||
} else {
|
||||
fetchMerchantList().then(() => {
|
||||
selectedMerchants.value = merchantList.value.filter(m => idsArr.includes(String(m.id)));
|
||||
});
|
||||
}
|
||||
} else {
|
||||
selectedMerchants.value = [];
|
||||
selectedMerchantIds.value = [];
|
||||
}
|
||||
}).finally(() => {
|
||||
loading.value = false
|
||||
})
|
||||
};
|
||||
// 获取数据
|
||||
loading.value = true
|
||||
getObj(id)
|
||||
.then((res: any) => {
|
||||
Object.assign(form, res.data)
|
||||
form.skuList =
|
||||
res.data.skuList.map((item: any) => {
|
||||
return { ...item, promotionPrice: displayPrice(item.promotionPrice, ""), retailPrice: displayPrice(item.retailPrice, "") }
|
||||
}) || []
|
||||
// skuList至少有一条
|
||||
if (!form.skuList || form.skuList.length === 0) {
|
||||
addSku()
|
||||
}
|
||||
// 处理 categoryId 回显为数组
|
||||
if (res.data.categoryId && categoryOptions.value.length) {
|
||||
form.categoryId = findCategoryPath(categoryOptions.value, res.data.categoryId)
|
||||
}
|
||||
// 处理 merchantIds 回显
|
||||
if (res.data.merchantIds) {
|
||||
const idsArr = typeof res.data.merchantIds === "string" ? res.data.merchantIds.split(",").filter(Boolean) : []
|
||||
selectedMerchantIds.value = idsArr
|
||||
if (merchantList.value.length) {
|
||||
selectedMerchants.value = merchantList.value.filter((m) => idsArr.includes(String(m.id)))
|
||||
} else {
|
||||
fetchMerchantList().then(() => {
|
||||
selectedMerchants.value = merchantList.value.filter((m) => idsArr.includes(String(m.id)))
|
||||
})
|
||||
}
|
||||
} else {
|
||||
selectedMerchants.value = []
|
||||
selectedMerchantIds.value = []
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
loading.value = false
|
||||
})
|
||||
}
|
||||
|
||||
function addSku() {
|
||||
form.skuList.push({
|
||||
barCode: '',
|
||||
spec: '',
|
||||
unit: '',
|
||||
status: 0,
|
||||
promotionPrice: 0,
|
||||
stock: '',
|
||||
attribute: ''
|
||||
});
|
||||
form.skuList.push({
|
||||
barCode: "",
|
||||
spec: "",
|
||||
unit: "",
|
||||
status: 0,
|
||||
promotionPrice: 0,
|
||||
stock: "",
|
||||
attribute: "",
|
||||
})
|
||||
}
|
||||
|
||||
function removeSku(index: number) {
|
||||
form.skuList.splice(index, 1);
|
||||
form.skuList.splice(index, 1)
|
||||
}
|
||||
|
||||
// 分步校验tab切换
|
||||
const handleTabLeave = async (newTab: string, oldTab: string) => {
|
||||
// 基本信息tab校验
|
||||
if (oldTab === 'base' && newTab !== 'base') {
|
||||
// 校验基本信息必填
|
||||
const valid = await dataFormRef.value.validateField([
|
||||
'productCode', 'productName', 'categoryId', 'picUrl'
|
||||
]).catch(() => false);
|
||||
return !!valid;
|
||||
}
|
||||
// SKU信息tab校验
|
||||
if (oldTab === 'sku' && newTab === 'merchant') {
|
||||
// 校验SKU表格必填
|
||||
let valid = true;
|
||||
for (let i = 0; i < form.skuList.length; i++) {
|
||||
const sku = form.skuList[i];
|
||||
if (!sku.barCode || !sku.unit || !sku.retailPrice || !sku.stock) {
|
||||
useMessage().error(`第${i + 1}行SKU必填项未填写`);
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
// 基本信息tab校验
|
||||
if (oldTab === "base" && newTab !== "base") {
|
||||
// 校验基本信息必填
|
||||
const valid = await dataFormRef.value.validateField(["productCode", "productName", "categoryId", "picUrl"]).catch(() => false)
|
||||
return !!valid
|
||||
}
|
||||
// SKU信息tab校验
|
||||
if (oldTab === "sku" && newTab === "merchant") {
|
||||
// 校验SKU表格必填
|
||||
let valid = true
|
||||
for (let i = 0; i < form.skuList.length; i++) {
|
||||
const sku = form.skuList[i]
|
||||
if (!sku.barCode || !sku.unit || !sku.retailPrice || !sku.stock) {
|
||||
useMessage().error(`第${i + 1}行SKU必填项未填写`)
|
||||
valid = false
|
||||
break
|
||||
}
|
||||
}
|
||||
return valid
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
const tabOrder = ['base', 'sku', 'merchant'];
|
||||
const tabOrder = ["base", "sku", "merchant"]
|
||||
function handleNextTab() {
|
||||
if (activeTab.value === 'base') {
|
||||
dataFormRef.value.validateField(['productCode', 'productName', 'categoryId', 'picUrl']).then(() => {
|
||||
activeTab.value = 'sku';
|
||||
});
|
||||
} else if (activeTab.value === 'sku') {
|
||||
// 校验SKU表格必填
|
||||
let valid = true;
|
||||
for (let i = 0; i < form.skuList.length; i++) {
|
||||
const sku = form.skuList[i];
|
||||
if (!sku.barCode || !sku.unit || !sku.retailPrice || !sku.stock) {
|
||||
useMessage().error(`第${i + 1}行SKU必填项未填写`);
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (valid) {
|
||||
activeTab.value = 'merchant';
|
||||
}
|
||||
}
|
||||
if (activeTab.value === "base") {
|
||||
dataFormRef.value.validateField(["productCode", "productName", "categoryId", "picUrl"]).then(() => {
|
||||
activeTab.value = "sku"
|
||||
})
|
||||
} else if (activeTab.value === "sku") {
|
||||
// 校验SKU表格必填
|
||||
let valid = true
|
||||
for (let i = 0; i < form.skuList.length; i++) {
|
||||
const sku = form.skuList[i]
|
||||
if (!sku.barCode || !sku.unit || !sku.retailPrice || !sku.stock) {
|
||||
useMessage().error(`第${i + 1}行SKU必填项未填写`)
|
||||
valid = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if (valid) {
|
||||
activeTab.value = "merchant"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function requiredLabel(label: string) {
|
||||
return `<span class='required'>*</span> ${label}`;
|
||||
return `<span class='required'>*</span> ${label}`
|
||||
}
|
||||
const tableHeaderStyle = () => ({ 'font-weight': 'bold' });
|
||||
const tableHeaderStyle = () => ({ "font-weight": "bold" })
|
||||
|
||||
// 暴露变量
|
||||
defineExpose({
|
||||
openDialog
|
||||
});
|
||||
openDialog,
|
||||
})
|
||||
|
||||
const showMerchantDialog = ref(false);
|
||||
const merchantList = ref<any[]>([]);
|
||||
const merchantSearch = ref('');
|
||||
const selectedMerchants = ref<any[]>([]);
|
||||
const selectedMerchantIds = ref<any[]>([]);
|
||||
const showMerchantDialog = ref(false)
|
||||
const merchantList = ref<any[]>([])
|
||||
const merchantSearch = ref("")
|
||||
const selectedMerchants = ref<any[]>([])
|
||||
const selectedMerchantIds = ref<any[]>([])
|
||||
|
||||
const fetchMerchantList = async () => {
|
||||
const res = await fetchMerchantSelect({
|
||||
name: merchantSearch.value,
|
||||
current: 1,
|
||||
size: 9999,
|
||||
types: 3
|
||||
});
|
||||
merchantList.value = res.data?.records || [];
|
||||
};
|
||||
const res = await fetchMerchantSelect({
|
||||
name: merchantSearch.value,
|
||||
current: 1,
|
||||
size: 9999,
|
||||
types: 3,
|
||||
})
|
||||
merchantList.value = res.data?.records || []
|
||||
}
|
||||
|
||||
const handleMerchantSelect = (rows: any[]) => {
|
||||
selectedMerchantIds.value = rows.map((row: any) => (row as any).id);
|
||||
};
|
||||
selectedMerchantIds.value = rows.map((row: any) => (row as any).id)
|
||||
}
|
||||
|
||||
const confirmMerchantSelect = () => {
|
||||
selectedMerchants.value = merchantList.value.filter(m => selectedMerchantIds.value.includes(m.id));
|
||||
showMerchantDialog.value = false;
|
||||
};
|
||||
selectedMerchants.value = merchantList.value.filter((m) => selectedMerchantIds.value.includes(m.id))
|
||||
showMerchantDialog.value = false
|
||||
}
|
||||
|
||||
const removeMerchant = (idx: number) => {
|
||||
selectedMerchants.value.splice(idx, 1);
|
||||
selectedMerchantIds.value = selectedMerchants.value.map(m => m.id);
|
||||
};
|
||||
selectedMerchants.value.splice(idx, 1)
|
||||
selectedMerchantIds.value = selectedMerchants.value.map((m) => m.id)
|
||||
}
|
||||
|
||||
// 打开弹窗时自动加载商户
|
||||
watch(showMerchantDialog, (val) => { if (val) fetchMerchantList(); });
|
||||
watch(showMerchantDialog, (val) => {
|
||||
if (val) fetchMerchantList()
|
||||
})
|
||||
|
||||
// 工具函数:根据分类id查找路径
|
||||
function findCategoryPath(options, targetId, path = []) {
|
||||
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 []
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.required {
|
||||
color: #f56c6c;
|
||||
margin-right: 2px;
|
||||
color: #f56c6c;
|
||||
margin-right: 2px;
|
||||
}
|
||||
.el-table .el-form-item {
|
||||
margin-bottom: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.el-table .el-form-item__error {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
font-size: 12px;
|
||||
color: #f56c6c;
|
||||
line-height: 1.2;
|
||||
white-space: nowrap;
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
left: 0;
|
||||
font-size: 12px;
|
||||
color: #f56c6c;
|
||||
line-height: 1.2;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.el-table .el-table__cell {
|
||||
vertical-align: top;
|
||||
position: relative;
|
||||
vertical-align: top;
|
||||
position: relative;
|
||||
}
|
||||
</style>
|
||||
@@ -1,87 +1,111 @@
|
||||
<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="productName" >
|
||||
<el-input placeholder="请输入商品名称" v-model="state.queryForm.productName" />
|
||||
</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_shopSpu_add'">
|
||||
新 增
|
||||
</el-button>
|
||||
<el-button plain :disabled="multiple" icon="Delete" type="primary"
|
||||
v-auth="'supermarket_shopSpu_del'" @click="handleDelete(selectObjs)">
|
||||
删除
|
||||
</el-button>
|
||||
<right-toolbar v-model:showSearch="showSearch" :export="'supermarket_shopSpu_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="productName">
|
||||
<el-input placeholder="请输入商品名称" v-model="state.queryForm.productName" />
|
||||
</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_shopSpu_add'">
|
||||
新 增
|
||||
</el-button>
|
||||
<el-button
|
||||
plain
|
||||
:disabled="multiple"
|
||||
icon="Delete"
|
||||
type="primary"
|
||||
v-auth="'supermarket_shopSpu_del'"
|
||||
@click="handleDelete(selectObjs)"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
<right-toolbar
|
||||
v-model:showSearch="showSearch"
|
||||
:export="'supermarket_shopSpu_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="productCode" label="货号" show-overflow-tooltip/>
|
||||
<el-table-column prop="productName" label="商品名称" show-overflow-tooltip/>
|
||||
<el-table-column prop="categoryId" label="商品分类" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
{{ findCategoryPath(categoryOptions, scope.row.categoryId).join(' / ') }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="picUrl" 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>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="stock" label="库存" show-overflow-tooltip/>
|
||||
<el-table-column prop="salesCount" label="销量" show-overflow-tooltip/>
|
||||
<el-table-column prop="limitNum" label="单人限购数" show-overflow-tooltip/>
|
||||
<el-table-column label="操作" width="150">
|
||||
<template #default="scope">
|
||||
<el-button icon="edit-pen" text type="primary" v-auth="'supermarket_shopSpu_edit'"
|
||||
@click="formDialogRef.openDialog(scope.row.id)">编辑</el-button>
|
||||
<el-button icon="delete" text type="primary" v-auth="'supermarket_shopSpu_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="productCode" label="货号" show-overflow-tooltip />
|
||||
<el-table-column prop="productName" label="商品名称" show-overflow-tooltip />
|
||||
<el-table-column prop="categoryId" label="商品分类" show-overflow-tooltip>
|
||||
<template #default="scope">
|
||||
{{ findCategoryPath(categoryOptions, scope.row.categoryId).join(" / ") }}
|
||||
</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 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>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="stock" label="库存" show-overflow-tooltip />
|
||||
<el-table-column prop="salesCount" label="销量" show-overflow-tooltip />
|
||||
<el-table-column prop="limitNum" label="单人限购数" show-overflow-tooltip />
|
||||
<el-table-column label="操作" width="150">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
icon="edit-pen"
|
||||
text
|
||||
type="primary"
|
||||
v-auth="'supermarket_shopSpu_edit'"
|
||||
@click="formDialogRef.openDialog(scope.row.id)"
|
||||
>编辑</el-button
|
||||
>
|
||||
<el-button icon="delete" text type="primary" v-auth="'supermarket_shopSpu_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="systemShopSpu">
|
||||
import { BasicTableProps, useTable } from "/src/hooks/table";
|
||||
import { fetchList, delObjs, putObj } from "/src/api/supermarket/shopSpu";
|
||||
import { useMessage, useMessageBox } from "/src/hooks/message";
|
||||
import { useDict } from '/src/hooks/dict';
|
||||
import { tree as fetchCategoryTree } from '/src/api/supermarket/shopCategory';
|
||||
import { onMounted, ref } from 'vue';
|
||||
import { BasicTableProps, useTable } from "/src/hooks/table"
|
||||
import { fetchList, delObjs, putObj } from "/src/api/supermarket/shopSpu"
|
||||
import { useMessage, useMessageBox } from "/src/hooks/message"
|
||||
import { useDict } from "/src/hooks/dict"
|
||||
import { tree as fetchCategoryTree } from "/src/api/supermarket/shopCategory"
|
||||
import { onMounted, ref } from "vue"
|
||||
|
||||
// 引入组件
|
||||
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 formDialogRef = ref()
|
||||
// 搜索变量
|
||||
@@ -92,74 +116,67 @@ 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 categoryOptions = ref<any[]>([]);
|
||||
const categoryOptions = ref<any[]>([])
|
||||
onMounted(async () => {
|
||||
const res = await fetchCategoryTree();
|
||||
categoryOptions.value = res.data || [];
|
||||
});
|
||||
const res = await fetchCategoryTree()
|
||||
categoryOptions.value = res.data || []
|
||||
})
|
||||
|
||||
// 递归查找分类路径
|
||||
function findCategoryPath(options: any[], id: string | number, path: string[] = []): string[] {
|
||||
for (const item of options) {
|
||||
const newPath = [...path, item.name];
|
||||
if (item.id == id) return newPath;
|
||||
if (item.children) {
|
||||
const result = findCategoryPath(item.children, id, newPath);
|
||||
if (result.length) return result;
|
||||
}
|
||||
}
|
||||
return [];
|
||||
for (const item of options) {
|
||||
const newPath = [...path, item.name]
|
||||
if (item.id == id) return newPath
|
||||
if (item.children) {
|
||||
const result = findCategoryPath(item.children, id, newPath)
|
||||
if (result.length) return result
|
||||
}
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
// 清空搜索条件
|
||||
const resetQuery = () => {
|
||||
// 清空搜索条件
|
||||
queryRef.value?.resetFields()
|
||||
// 清空多选
|
||||
selectObjs.value = []
|
||||
getDataList()
|
||||
// 清空搜索条件
|
||||
queryRef.value?.resetFields()
|
||||
// 清空多选
|
||||
selectObjs.value = []
|
||||
getDataList()
|
||||
}
|
||||
|
||||
// 导出excel
|
||||
const exportExcel = () => {
|
||||
downBlobFile('/supermarket/shopSpu/export', Object.assign(state.queryForm, { ids: selectObjs }), 'shopSpu.xlsx')
|
||||
downBlobFile("/supermarket/shopSpu/export", Object.assign(state.queryForm, { ids: selectObjs }), "shopSpu.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)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
Reference in new issue
Block a user