2025-06-11 16:27:15 +08:00

601 lines
18 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
style="margin-top: 25px"
ref="searchForm"
:inline="true"
:model="formInline"
class="demo-form-inline"
:label-width="'auto'"
>
<el-form-item label="订单编号" prop="goodName">
<el-input
v-model="formInline.orderNo"
placeholder="请输入订单编号"
clearable
/>
</el-form-item>
<el-form-item label="买家名称" prop="goodName">
<el-input
v-model="formInline.receiverName"
placeholder="请输入买家名称"
clearable
/>
</el-form-item>
<el-form-item label="买家电话" prop="goodName">
<el-input
v-model="formInline.receiverPhone"
placeholder="请输入买家电话"
clearable
/>
</el-form-item>
</el-form>
</div>
<div class="search-bar-right">
<el-button
class="el-button-gry"
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
:preserve-expanded-content="preserveExpanded"
: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"
:tree="true"
>
<!-- 自定义-图片 -->
<template #goodUrl="slotProps">
<div class="table-cell-img-box">
<img
:src="slotProps.row.productImage"
class="table-cell-img"
alt=""
/>
</div>
</template>
<!-- 自定义 - 序号 -->
<template #totalAmount="slotProps">
<span v-if="slotProps.row.totalAmount"
>{{ slotProps.row.totalAmount }}</span
>
</template>
<template #payableAmount="slotProps">
<span v-if="slotProps.row.payableAmount"
>{{ slotProps.row.payableAmount }}</span
>
</template>
<template #discountAmount="slotProps">
<span v-if="slotProps.row.discountAmount"
>{{ slotProps.row.discountAmount }}</span
>
</template>
<template #tree="slotProps">
<div class="tree-goods">
<div
:style="{
height: 80 * (slotProps.row.orderItemInfos.length + 1) + 'px',
}"
class="tree-goods-subOrder"
>
<div class="tree-goods-subOrder-list">
<!-- <el-checkbox
style="margin-right: 10px"
size="large"
v-model="checked2"
></el-checkbox>
<div class="tree-goods-subOrder-image">
<img
style="width: 60px; height: 60px"
src="../../assets/images/dark.svg"
alt=""
/>
</div> -->
<div class="tree-goods-subOrder-name">商品照片</div>
<div class="tree-goods-subOrder-name">商品名称</div>
<div class="tree-goods-subOrder-name">商品单价</div>
<div class="tree-goods-subOrder-name">购买数量</div>
<div class="tree-goods-subOrder-name">实付总金额</div>
<div class="tree-goods-subOrder-name">规格</div>
</div>
<div
v-for="item in slotProps.row.orderItemInfos"
:key="item.id"
class="tree-goods-subOrder-list"
style="
margin-top: 20px;
border-bottom: 1px solid #f5f5f5;
padding-bottom: 10px;
"
>
<!-- <el-checkbox
style="margin-right: 10px"
size="large"
v-model="checked2"
></el-checkbox> -->
<div class="tree-goods-subOrder-image">
<img
style="width: 60px; height: 60px"
:src="item.productImage"
alt=""
/>
</div>
<!-- <div class="tree-goods-subOrder-name">
{{ item.productImage }}
</div> -->
<div class="tree-goods-subOrder-name">
{{ item.productName }}
</div>
<div class="tree-goods-subOrder-name">
{{ item.unitPrice }}
</div>
<div class="tree-goods-subOrder-name">
{{ item.quantity }}
</div>
<div class="tree-goods-subOrder-name">
{{ item.subtotalAmount }}
</div>
<div class="tree-goods-subOrder-name">
{{ item.unit }}
</div>
</div>
</div>
<!-- <div class="sendGoods">发货</div> -->
</div>
</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">
<div @click="goSend(slotProps.row)" class="send-button">去发货</div>
<!-- <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 { orderInfo } from "@/api/order/list";
import { id } from "element-plus/es/locales.mjs";
import { ElMessage } from "element-plus";
const route = useRoute();
const router = useRouter();
const preserveExpanded = ref(true);
const formInline = reactive({
orderNo: "",
orderStatus: "8",
current: 1,
size: 10,
receiverName: "",
receiverPhone: "",
});
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: "orderNo", label: "订单编号", width: "150" },
// {
// prop: "productImage",
// label: "商品图片",
// slotName: "goodUrl",
// width: "150",
// },
{ prop: "receiverName", label: "买家名称" },
{ prop: "receiverPhone", label: "买家电话" },
{ prop: "receiverAddress", label: "收货地址" },
{ prop: "totalQuantity", label: "商品数" },
{ prop: "totalAmount", label: "因付金额" },
{ prop: "payableAmount", label: "实付金额" },
{ prop: "discountAmount", label: "折扣金额" },
// {
// prop: "subtotalAmount",
// label: "订单总价",
// width: "150",
// slotName: "subtotalAmount",
// },
// { prop: "stock", label: "子订单数量", width: "150" },
// { prop: "isListed", label: "状态", slotName: "isListed", width: "150" },
// { prop: "action", label: "操作", slotName: "action", width: "150" },
]);
// 生成食物主题昵称
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 orderInfo(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 goSend = (data) => {
router.push({
path: "/order/order/sendGoodsInfo",
query: { data: JSON.stringify(data) },
});
};
// 删除操作
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>
.send-button {
text-align: center;
width: 60px;
height: 25px;
line-height: 25px;
border-radius: 5px;
font-size: 15px;
color: #fff;
background-color: #409eff;
cursor: pointer;
}
.tree-goods {
width: 90%;
display: flex;
justify-content: flex-start;
margin-left: 100px;
align-items: center;
.sendGoods {
margin-left: 15px;
padding: 5px 10px;
background-color: #409eff;
color: #fff;
border-radius: 5px;
cursor: pointer;
}
.tree-goods-subOrder {
// display: flex;
// width: 1510px;
height: 60px;
.tree-goods-subOrder-list {
display: flex;
align-items: center;
justify-content: flex-start;
.tree-goods-subOrder-image {
width: 128px;
height: 60px;
margin-left: 20px;
}
.tree-goods-subOrder-name {
width: 150px;
overflow: hidden;
text-overflow: ellipsis;
height: 60px;
line-height: 60px;
padding: 0 15px;
}
}
}
}
.table-toolbar {
width: 300px;
height: 50px;
position: absolute;
right: 0;
top: 0;
display: flex;
justify-content: end;
padding: 14px 16px 0 0;
}
</style>