2025-06-06 19:00:59 +08:00

362 lines
12 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="app-container customer-control">
<div class="container-custom">
<!-- 搜索栏 -->
<div ref="searchBarRef" class="search-box">
<div class="search-bar">
<div class="search-bar-left">
<div class="order-tab" style="margin-top: -10px">
<el-tabs v-model="activeCurrent" @tab-click="tabChange">
<el-tab-pane v-for="t in bottomList" :key="t.id" :label="t.title + '(' + t.value + ')'" :name="t.id">
</el-tab-pane>
</el-tabs>
</div>
<el-form ref="searchForm" :inline="true" :model="formInline" class="demo-form-inline" :label-width="'auto'">
<el-form-item label="商品名称" prop="goodName">
<el-input v-model="formInline.goodName" placeholder="请输入商品名称" clearable />
</el-form-item>
<el-form-item label="商品分类" prop="goodCategoryId">
<el-select v-model="formInline.goodCategoryId" placeholder="请选择" clearable>
<el-option v-for="item in goodsCategoryList" :key="item.id" :value="item.id" :label="item.name" />
</el-select>
</el-form-item>
<el-form-item label="商品品牌" prop="storeId">
<el-select v-model="formInline.storeId" placeholder="请选择" clearable>
<el-option v-for="item in goodsBrandList" :key="item.id" :value="item.id" :label="item.name" />
</el-select>
</el-form-item>
</el-form>
</div>
<div class="search-bar-right">
<el-button type="primary" icon="Search" @click="onSubmit">查询</el-button>
<el-button icon="Refresh" style="margin: 16px 0 0 0" @click="resetForm">重置</el-button>
</div>
</div>
</div>
<!-- 表格 -->
<div class="table-cont" :style="{ height: tableViewportHeight + 'px' }">
<div class="table-toolbar">
<el-button icon="delete" @click="batchDelete" :disabled="btnStatus"
style="margin-right: 10px">批量删除</el-button>
<router-link to="/goods/goodsManage/addGoods">
<el-button type="primary" icon="plus" @click="onSubmit">新增商品</el-button>
</router-link>
</div>
<tableComponent :table-data="tableData" :columns="columns" :show-border="false" :show-selection="true"
:header-cell-class-name="getHeaderClass" @page-change="handlePaginationChange" :loading="tableLoading"
@selection-change="handleSelectionChange" :total="tableTotal" :current-page="formInline.current"
:page-size="formInline.size" :showSort="true">
<!-- 自定义-图片 -->
<template #goodUrl="slotProps">
<div class="table-cell-img-box">
<img :src="slotProps.row.goodUrl" class="table-cell-img" alt="" />
</div>
</template>
<!-- 自定义 - 序号 -->
<template #sort="slotProps">
<span v-if="slotProps.row.goodPrice">{{ slotProps.row.goodPrice }}</span>
</template>
<!-- 自定义-状态 -->
<template #isListed="slotProps">
<span v-if="slotProps.row.isListed == 0" class="color-blue">待上架</span>
<span v-else-if="slotProps.row.isListed == 1" class="color-black">已上架</span>
<span v-else-if="slotProps.row.isListed == 2" class="color-green">上架</span>
<span v-else-if="slotProps.row.isListed == 3" class="color-red">下架</span>
<span v-else-if="slotProps.row.isListed == 4" class="color-orange">审核中</span>
</template>
<!-- 自定义-操作 -->
<template #action="slotProps">
<el-tooltip effect="dark" placement="bottom-end">
<template #content>
<div class="custom-tooltip-content">
<el-icon class="el-icon-custom" @click="seeDetails(slotProps.row)">
<View />
</el-icon>
<el-icon class="el-icon-custom" @click="toUpload(slotProps.row)">
<Upload />
</el-icon>
<el-icon class="el-icon-custom" @click="toDownload(slotProps.row)">
<Download />
</el-icon>
<el-icon class="el-icon-custom" @click="handleEdit(slotProps.row)">
<Edit />
</el-icon>
<el-icon class="el-icon-custom" @click="handleDelete(slotProps.row)">
<Delete />
</el-icon>
</div>
</template>
<span class="el-dropdown-link">
<el-icon>
<More />
</el-icon>
</span>
</el-tooltip>
</template>
</tableComponent>
</div>
</div>
</div>
</template>
<script setup>
import { ref, reactive, computed, onMounted, onBeforeUnmount } from "vue";
import tableComponent from "@/components/tableComponent.vue";
import Mock from "mockjs";
import { getGoodManageInfo, getGoodType, goodDelete } from "@/api/goods/info";
import { id } from "element-plus/es/locales.mjs";
import { ElMessage } from 'element-plus'
const route = useRoute()
const router = useRouter()
const formInline = reactive({
goodName: "",
goodCategoryId: "",
storeId: "",
type: "1",
current: 1,
size: 10,
});
const goodsCategoryList = ref([
{ name: "蔬菜", id: 1 },
{ name: "肥料", id: 2 },
{ name: "农药", id: 3 },
]);
const goodsBrandList = ref([
{ name: "品牌1", id: 1 },
{ name: "品牌2", id: 2 },
{ name: "品牌3", id: 3 },
]);
const searchForm = ref(null);
const onSubmit = () => {
console.log("submit!");
formInline.current = 1;
console.log(formInline);
loadData();
};
const resetForm = () => {
searchForm.value.resetFields();
};
let activeCurrent = ref("1");
let bottomList = reactive([
{ title: "全部", id: "1", value: 134 },
{ title: "已上架", id: "2", value: 97 },
{ title: "已下架", id: "3", value: 37 },
]);
const tabChange = (Event) => {
console.log(Event.index);
if (Event.index == "0") {
// 请求全部
formInline.type = "1";
} else if (Event.index == "1") {
// 请求已上架
formInline.type = "2";
} else if (Event.index == "2") {
// 请求已下架
formInline.type = "3";
}
loadData();
};
// 表格数据
const tableData = ref([]);
const selectedIds = ref([]);
const btnStatus = computed(() => {
return selectedIds.value.length <= 0;
});
const tableLoading = ref(false);
const tableTotal = ref(0);
let nowClickRow = ref({});
// 列配置
const columns = ref([]);
const columns1 = ref([
{ prop: "goodId", label: "ID", width: "150" },
{ prop: "goodUrl", label: "商品图片", slotName: "goodUrl" },
{ prop: "goodName", label: "商品名称", width: "120" },
{ prop: "categoryName", label: "分类名称" },
{ prop: "goodPrice", label: "商品售价" },
{ prop: "salesVolume", label: "销量" },
{ prop: "pageView", label: "浏览量" },
{ prop: "stock", label: "库存" },
{ prop: "isListed", label: "状态", slotName: "isListed" },
{ prop: "action", label: "操作", slotName: "action" },
]);
// 生成食物主题昵称
const generateFoodNickname = () => {
// 食物名词(仅限食物)
const foods = [
"辣椒",
"西瓜",
"土豆",
"番茄",
"黄瓜",
"苹果",
"蛋糕",
"面包",
"披萨",
"冰淇淋",
"奶茶",
"咖啡",
"啤酒",
"炸鸡",
];
// 随机组合:形容词 + 食物
return Mock.mock(`@pick(${foods})`);
};
// 生成模拟数据
const generateMockData = () => {
return Mock.mock({
"list|10": [
{
"id|+1": 10000,
"goodId|+1": 10000,
"sort|+1": 1,
goodUrl: " @image", //商品图片
goodName: () => generateFoodNickname(), //商品名称
categoryName: '@pick(["蔬菜", "肥料", "农药"])', //分类名称
goodPrice: "@float(10, 200, 2, 2)", //商品售价
salesVolume: "@integer(1000, 20000)", //销量
pageView: Mock.mock("@id").toString().slice(0, 6), //浏览量
stock: "@integer(5000, 90000)", //库存
isListed: '@pick([0, 1, 2, 3, 4])', //状态
ordersNums: "@integer(10, 200)",
},
],
}).list;
};
// 加载数据
const loadData = async () => {
tableLoading.value = true;
// 测试
// tableData.value = generateMockData();
// tableTotal.value = tableData.value.length;
// console.log(tableData.value);
try {
let response = await getGoodManageInfo(formInline);
console.log(response);
if (response.code == 200) {
tableData.value = response.data.records;
tableTotal.value = response.data.total;
}
} catch (error) {
console.log(error);
}
tableLoading.value = false;
};
// 自定义表头类名,也可以在columns指定列中添加headerClassName: 'custom-header'
const getHeaderClass = ({ column }) => {
return "custom-header";
};
// 分页变化
const handlePaginationChange = ({ page, pageSize }) => {
console.log("分页变化:", page, pageSize);
formInline.current = page;
formInline.size = pageSize;
// 这里可以调用API获取新数据
loadData();
};
// 多选框变化
const handleSelectionChange = (selection, ids) => {
console.log("选中项:", selection, ids);
selectedIds.value = ids;
};
// 查看详情
const seeDetails = (row) => {
nowClickRow.value = row;
console.log("要查看详情的行:", row);
};
const toUpload = () => {
console.log("上架:");
};
const toDownload = () => {
console.log("下架:");
};
// 编辑操作
const handleEdit = (row) => {
nowClickRow.value = row;
console.log("要编辑的行:", row);
// 跳转路由并携带参数行数据和query的值edit
router.push({
path: "/goods/goodsManage/editGoods",
query: { goodId: row.goodId }
})
};
// 删除操作
const handleDelete = (row) => {
nowClickRow.value = row;
console.log("要删除的行:", row);
};
// 批量删除
const batchDelete = async() => {
console.log("要删除的行:", selectedIds.value.join(","));
ElMessage.success("删除成功");
// let res = await goodDelete({id: selectedIds.value});
// if (res.code == 200) {
// ElMessage.success("删除成功");
// loadData();
// } else {
// ElMessage.error("删除失败");
// }
};
const titleRef = ref(null);
const searchBarRef = ref(null);
const tableViewportHeight = ref(0);
// 精确计算可用高度
const calculateTableHeight = () => {
// 获取窗口总高度
const windowHeight = window.innerHeight;
// 获取各组件高度
const headerHeight = titleRef.value?.$el?.offsetHeight || 0;
const searchBarHeight = searchBarRef.value?.offsetHeight || 0;
// 计算容器内边距补偿(根据实际样式调整)
const paddingCompensation = 130;
// 最终计算
tableViewportHeight.value =
windowHeight - headerHeight - searchBarHeight - paddingCompensation;
// console.log(tableViewportHeight.value);
};
// 组件挂载时加载数据
onMounted(() => {
columns.value = columns1.value;
loadData();
calculateTableHeight();
// 添加响应式监听
window.addEventListener("resize", calculateTableHeight);
// 监听DOM变化适用于动态变化的header/searchbar
const observer = new ResizeObserver(calculateTableHeight);
if (titleRef.value?.$el) observer.observe(titleRef.value.$el);
if (searchBarRef.value) observer.observe(searchBarRef.value);
});
onBeforeUnmount(() => {
window.removeEventListener("resize", calculateTableHeight);
});
</script>
<style lang="scss" scoped>
.table-toolbar {
width: 300px;
height: 50px;
position: absolute;
right: 0;
top: 0;
display: flex;
justify-content: end;
padding: 14px 16px 0 0;
}
</style>