<template>
|
<div class="app-container">
|
<div class="search_form">
|
<el-form :model="searchForm" :inline="true">
|
<el-form-item label="销售订单号:">
|
<el-input v-model="searchForm.salesContractNo" placeholder="请输入" clearable prefix-icon="Search" style="width: 200px"
|
@change="handleQuery" />
|
</el-form-item>
|
<el-form-item label="客户名称:">
|
<el-input v-model="searchForm.customerName" placeholder="请输入" clearable prefix-icon="Search" style="width: 200px"
|
@change="handleQuery" />
|
</el-form-item>
|
<el-form-item>
|
<el-button type="primary" @click="handleQuery"> 搜索 </el-button>
|
</el-form-item>
|
</el-form>
|
</div>
|
<div class="table_list">
|
<div class="actions">
|
<div></div>
|
<div>
|
<el-button @click="handleOut">导出</el-button>
|
<el-button type="danger" plain @click="handleDelete">删除</el-button>
|
</div>
|
</div>
|
<el-table :data="tableData" border v-loading="tableLoading" @selection-change="handleSelectionChange"
|
:row-key="(row) => row.id" style="width: 100%" height="calc(100vh - 21.5em)">
|
<el-table-column align="center" type="selection" width="55" />
|
<el-table-column align="center" label="序号" type="index" width="60" />
|
<el-table-column label="销售订单" prop="salesContractNo" show-overflow-tooltip />
|
<el-table-column label="发货订单号" prop="shippingNo" show-overflow-tooltip />
|
<el-table-column label="客户名称" prop="customerName" show-overflow-tooltip />
|
<el-table-column label="发货进度" align="center" width="150">
|
<template #default="scope">
|
<el-progress
|
:percentage="getShippingProgress(scope.row)"
|
:color="getProgressColor(scope.row)"
|
:stroke-width="8"
|
/>
|
</template>
|
</el-table-column>
|
<el-table-column label="审核状态" prop="status" align="center" width="120">
|
<template #default="scope">
|
<el-tag :type="getApprovalStatusType(scope.row.status)">
|
{{ getApprovalStatusText(scope.row.status) }}
|
</el-tag>
|
</template>
|
</el-table-column>
|
<el-table-column fixed="right" label="操作" width="200" align="center">
|
<template #default="scope">
|
<el-button
|
link
|
type="primary"
|
size="small"
|
:disabled="(scope.row.waitShippingTotal || 0) <= 0"
|
@click="openForm('edit', scope.row)">分批发货</el-button>
|
<el-button
|
link
|
type="primary"
|
size="small"
|
@click="openDetail(scope.row)"
|
>详情</el-button>
|
<el-button
|
link
|
type="danger"
|
size="small"
|
:disabled="isApproving(scope.row.status)"
|
@click="handleDeleteSingle(scope.row)">删除</el-button>
|
</template>
|
</el-table-column>
|
</el-table>
|
<pagination v-show="total > 0" :total="total" layout="total, sizes, prev, pager, next, jumper"
|
:page="page.current" :limit="page.size" @pagination="paginationChange" />
|
</div>
|
|
<!-- 发货详情/分批发货弹窗 -->
|
<el-dialog
|
v-model="dialogFormVisible"
|
:title="dialogMode === 'edit' ? '分批发货管理' : '发货台账详情'"
|
width="90%"
|
@close="closeDia"
|
class="batch-shipping-dialog"
|
>
|
<div v-if="currentShippingOrder" class="shipping-dialog-container">
|
<el-row :gutter="24">
|
<el-col :span="7">
|
<el-card shadow="never" class="order-info-card">
|
<template #header>
|
<div class="card-header">
|
<span>订单信息</span>
|
<el-tag :type="getProgressColor(currentShippingOrder) === '#67C23A' ? 'success' : 'warning'" effect="dark">
|
{{ getShippingProgress(currentShippingOrder) }}%
|
</el-tag>
|
</div>
|
</template>
|
<div class="order-info-content">
|
<div class="info-item">
|
<span class="label">销售订单</span>
|
<span class="value">{{ currentShippingOrder.salesContractNo || '--' }}</span>
|
</div>
|
<div class="info-item">
|
<span class="label">客户名称</span>
|
<span class="value">{{ currentShippingOrder.customerName || '--' }}</span>
|
</div>
|
<div class="info-item">
|
<span class="label">发货订单号</span>
|
<span class="value">{{ currentShippingOrder.shippingNo || '--' }}</span>
|
</div>
|
<el-divider />
|
<div class="quantity-summary">
|
<div class="summary-item">
|
<div class="summary-label">总发货数量</div>
|
<div class="summary-value total">{{ currentShippingOrder.shippingTotal || 0 }}</div>
|
</div>
|
<div class="summary-item">
|
<div class="summary-label">已发货数量</div>
|
<div class="summary-value shipped">{{ currentShippingOrder.shippingSuccessTotal || 0 }}</div>
|
</div>
|
<div class="summary-item">
|
<div class="summary-label">待发货数量</div>
|
<div class="summary-value waiting">{{ currentShippingOrder.waitShippingTotal || 0 }}</div>
|
</div>
|
</div>
|
<div class="progress-wrapper">
|
<el-progress
|
:percentage="getShippingProgress(currentShippingOrder)"
|
:color="getProgressColor(currentShippingOrder)"
|
:stroke-width="12"
|
:show-text="false"
|
/>
|
</div>
|
</div>
|
<div class="action-buttons" v-if="dialogMode === 'edit'">
|
<el-button type="primary" size="large" @click="showAddShippingForm" :disabled="!canAddShipping()" style="width: 100%">
|
<el-icon><Plus /></el-icon> 新增发货
|
</el-button>
|
</div>
|
</el-card>
|
</el-col>
|
|
<el-col :span="17">
|
<el-card shadow="never" class="shipping-records-card">
|
<template #header>
|
<div class="card-header">
|
<span>发货记录</span>
|
<div class="header-actions">
|
<span class="record-count">共 {{ shippingRecords.length }} 条记录</span>
|
</div>
|
</div>
|
</template>
|
|
<div v-if="shippingRecords.length === 0" class="empty-state">
|
<el-empty description="暂无发货记录" />
|
</div>
|
|
<div v-else class="shipping-records-list">
|
<div v-for="(record, index) in shippingRecords" :key="record.id || index" class="shipping-record-item">
|
<div class="record-header">
|
<div class="record-title">
|
<el-tag :type="record.type === '货车' ? 'primary' : 'success'" size="small">
|
{{ record.type }}
|
</el-tag>
|
</div>
|
<div class="record-date">{{ record.shippingDate }}</div>
|
</div>
|
<div class="record-body">
|
<div class="record-info">
|
<div class="info-row">
|
<span class="info-label">发货数量</span>
|
<span class="info-value quantity">{{ record.shippingNum }}</span>
|
</div>
|
<div class="info-row" v-if="record.type === '货车'">
|
<span class="info-label">车牌号</span>
|
<span class="info-value">{{ record.shippingCarNumber || '--' }}</span>
|
</div>
|
<div class="info-row" v-else>
|
<span class="info-label">快递公司</span>
|
<span class="info-value">{{ record.expressCompany || '--' }}</span>
|
</div>
|
<div class="info-row" v-if="record.type === '快递'">
|
<span class="info-label">快递单号</span>
|
<span class="info-value">{{ record.expressNumber || '--' }}</span>
|
</div>
|
<div class="info-row" v-if="record.commonFileList && record.commonFileList.length > 0">
|
<span class="info-label">发货图片</span>
|
<div class="record-images">
|
<el-image
|
v-for="(file, imgIndex) in record.commonFileList"
|
:key="imgIndex"
|
:src="normalizeFileUrl(file?.url)"
|
:preview-src-list="record.commonFileList.map(f => normalizeFileUrl(f?.url))"
|
fit="cover"
|
class="record-image"
|
preview-teleported
|
/>
|
</div>
|
</div>
|
</div>
|
</div>
|
</div>
|
</div>
|
</el-card>
|
</el-col>
|
</el-row>
|
</div>
|
<template #footer>
|
<div class="dialog-footer">
|
<el-button @click="closeDia">关闭</el-button>
|
</div>
|
</template>
|
</el-dialog>
|
|
<!-- 新增发货记录弹窗 -->
|
<el-dialog v-model="showAddForm" title="新增发货记录" width="600px" @close="hideAddShippingForm">
|
<el-alert
|
:title="`可发货数量:${getMaxShippingQuantity()}`"
|
type="info"
|
:closable="false"
|
show-icon
|
style="margin-bottom: 20px"
|
/>
|
<el-form :model="shippingForm" label-width="100px" :rules="shippingRules" ref="shippingFormRef">
|
<el-row :gutter="20">
|
<el-col :span="12">
|
<el-form-item label="发货数量" prop="shippingNum">
|
<el-input-number
|
v-model="shippingForm.shippingNum"
|
:min="1"
|
:max="getMaxShippingQuantity()"
|
:precision="0"
|
placeholder="请输入发货数量"
|
style="width: 100%"
|
/>
|
</el-form-item>
|
</el-col>
|
<el-col :span="12">
|
<el-form-item label="发货类型" prop="type">
|
<el-radio-group v-model="shippingForm.type">
|
<el-radio label="货车">货车</el-radio>
|
<el-radio label="快递">快递</el-radio>
|
</el-radio-group>
|
</el-form-item>
|
</el-col>
|
</el-row>
|
<el-row :gutter="20">
|
<el-col :span="24">
|
<el-form-item label="发货日期" prop="shippingDate">
|
<el-date-picker
|
v-model="shippingForm.shippingDate"
|
value-format="YYYY-MM-DD HH:mm:ss"
|
type="datetime"
|
placeholder="请选择"
|
style="width: 100%"
|
/>
|
</el-form-item>
|
</el-col>
|
</el-row>
|
<el-row :gutter="20">
|
<el-col :span="24" v-if="shippingForm.type === '货车'">
|
<el-form-item label="发货车牌号" prop="shippingCarNumber">
|
<el-input v-model="shippingForm.shippingCarNumber" placeholder="请输入发货车牌号" />
|
</el-form-item>
|
</el-col>
|
<el-col :span="24" v-else>
|
<el-form-item label="快递公司" prop="expressCompany">
|
<el-input v-model="shippingForm.expressCompany" placeholder="请输入快递公司" />
|
</el-form-item>
|
</el-col>
|
<el-col :span="24" v-if="shippingForm.type === '快递'">
|
<el-form-item label="快递单号" prop="expressNumber">
|
<el-input v-model="shippingForm.expressNumber" placeholder="请输入快递单号" />
|
</el-form-item>
|
</el-col>
|
</el-row>
|
<el-row>
|
<el-col :span="24">
|
<el-form-item label="发货图片">
|
<el-upload
|
v-model:file-list="shippingFileList"
|
:action="upload.url"
|
multiple
|
ref="shippingFileUpload"
|
auto-upload
|
:headers="upload.headers"
|
:data="{ type: 9 }"
|
:before-upload="handleDeliveryBeforeUpload"
|
:on-error="handleDeliveryUploadError"
|
:on-success="handleDeliveryUploadSuccess"
|
:on-remove="handleShippingRemove"
|
list-type="picture-card"
|
:limit="9"
|
accept="image/png,image/jpeg,image/jpg"
|
>
|
<el-icon class="avatar-uploader-icon"><Plus /></el-icon>
|
<template #tip>
|
<div class="el-upload__tip">
|
支持 jpg、jpeg、png 格式,最多上传 9 张
|
</div>
|
</template>
|
</el-upload>
|
</el-form-item>
|
</el-col>
|
</el-row>
|
</el-form>
|
<template #footer>
|
<div class="dialog-footer">
|
<el-button type="primary" @click="submitShipping" :loading="shippingRecordsLoading">确认发货</el-button>
|
<el-button @click="hideAddShippingForm">取消</el-button>
|
</div>
|
</template>
|
</el-dialog>
|
</div>
|
</template>
|
|
<script setup>
|
import pagination from "@/components/PIMTable/Pagination.vue";
|
import { onMounted, ref, reactive, toRefs, getCurrentInstance } from "vue";
|
import { ElMessageBox } from "element-plus";
|
import { Plus } from "@element-plus/icons-vue";
|
import { getToken } from "@/utils/auth";
|
import { getCurrentDate } from "@/utils/index.js";
|
import {
|
deliveryLedgerListPage,
|
addOrUpdateDeliveryLedger,
|
delDeliveryLedger, deductStock,
|
shippingInfoDetailListPage,
|
addShippingInfoDetail,
|
updateShippingInfoDetail,
|
delShippingInfoDetail,
|
} from "@/api/salesManagement/deliveryLedger.js";
|
import { delLedgerFile } from "@/api/salesManagement/salesLedger.js";
|
|
|
const { proxy } = getCurrentInstance();
|
const tableData = ref([]);
|
const selectedRows = ref([]);
|
const tableLoading = ref(false);
|
const page = reactive({
|
current: 1,
|
size: 100,
|
});
|
const total = ref(0);
|
const javaApi = proxy.javaApi;
|
|
// 发货详情/分批发货弹框
|
const dialogFormVisible = ref(false);
|
const dialogMode = ref('view');
|
const currentShippingOrder = ref(null);
|
const shippingRecords = ref([]);
|
const shippingRecordsLoading = ref(false);
|
const showAddForm = ref(false);
|
const shippingForm = ref({
|
shippingNum: null,
|
type: "货车",
|
shippingDate: getCurrentDate(),
|
shippingCarNumber: "",
|
expressCompany: "",
|
expressNumber: "",
|
});
|
const shippingRules = {
|
shippingNum: [{ required: true, message: "请输入发货数量", trigger: "blur" }],
|
type: [{ required: true, message: "请选择发货类型", trigger: "change" }],
|
shippingDate: [{ required: true, message: "请选择发货日期", trigger: "change" }],
|
shippingCarNumber: [
|
{ validator: (_, value, callback) => validateShippingCarNumber(value, callback), trigger: "blur" }
|
],
|
expressCompany: [
|
{ validator: (_, value, callback) => validateExpressCompany(value, callback), trigger: "blur" }
|
],
|
};
|
const shippingFileList = ref([]);
|
|
const normalizeFileUrl = (rawUrl = '') => {
|
let fileUrl = rawUrl || '';
|
if (fileUrl && fileUrl.indexOf('\\') > -1) {
|
const uploadsIndex = fileUrl.toLowerCase().indexOf('uploads');
|
if (uploadsIndex > -1) {
|
const relativePath = fileUrl.substring(uploadsIndex).replace(/\\/g, '/');
|
fileUrl = '/' + relativePath;
|
} else {
|
const parts = fileUrl.split('\\');
|
const fileName = parts[parts.length - 1];
|
fileUrl = '/uploads/' + fileName;
|
}
|
}
|
if (fileUrl && !fileUrl.startsWith('http')) {
|
if (!fileUrl.startsWith('/')) fileUrl = '/' + fileUrl;
|
fileUrl = javaApi + fileUrl;
|
}
|
return fileUrl;
|
};
|
|
// 上传配置
|
const upload = reactive({
|
url: import.meta.env.VITE_APP_BASE_API + "/file/upload",
|
headers: { Authorization: "Bearer " + getToken() },
|
});
|
|
// 搜索表单数据
|
const data = reactive({
|
searchForm: {
|
salesContractNo: "",
|
customerName: "",
|
},
|
});
|
const { searchForm } = toRefs(data);
|
|
// 查询列表
|
const handleQuery = () => {
|
page.current = 1;
|
getList();
|
};
|
|
const paginationChange = (obj) => {
|
page.current = obj.page;
|
page.size = obj.limit;
|
getList();
|
};
|
|
const getList = () => {
|
tableLoading.value = true;
|
deliveryLedgerListPage({ ...searchForm.value, ...page })
|
.then((res) => {
|
tableLoading.value = false;
|
tableData.value = res.data.records || [];
|
total.value = res.data.total || 0;
|
})
|
.catch(() => {
|
tableLoading.value = false;
|
});
|
};
|
|
// 表格选择数据
|
const handleSelectionChange = (selection) => {
|
selectedRows.value = selection;
|
};
|
|
// 打开发货弹框
|
const openForm = async (type, row) => {
|
if (type === 'edit' && row && (row.waitShippingTotal || 0) <= 0) {
|
proxy.$modal.msgWarning("没有待发货数量,无法分批发货");
|
return;
|
}
|
|
dialogMode.value = type === 'edit' ? 'edit' : 'view';
|
currentShippingOrder.value = row;
|
showAddForm.value = false;
|
shippingForm.value = {
|
shippingNum: null,
|
type: "货车",
|
shippingDate: getCurrentDate(),
|
shippingCarNumber: "",
|
expressCompany: "",
|
expressNumber: "",
|
};
|
shippingFileList.value = [];
|
|
await loadShippingRecords(row.id);
|
dialogFormVisible.value = true;
|
};
|
|
// 打开详情弹框
|
const openDetail = (row) => {
|
openForm('view', row);
|
};
|
|
// 加载发货记录
|
const loadShippingRecords = async (shippingInfoId) => {
|
shippingRecordsLoading.value = true;
|
try {
|
const res = await shippingInfoDetailListPage({ shippingInfoId, current: 1, size: 100 });
|
shippingRecords.value = res.data.records || [];
|
} catch (error) {
|
shippingRecords.value = [];
|
} finally {
|
shippingRecordsLoading.value = false;
|
}
|
};
|
|
// 显示新增发货表单
|
const showAddShippingForm = () => {
|
showAddForm.value = true;
|
shippingForm.value = {
|
shippingNum: null,
|
type: "货车",
|
shippingDate: getCurrentDate(),
|
shippingCarNumber: "",
|
expressCompany: "",
|
expressNumber: "",
|
};
|
shippingFileList.value = [];
|
};
|
|
// 隐藏新增发货表单
|
const hideAddShippingForm = () => {
|
showAddForm.value = false;
|
shippingForm.value = {
|
shippingNum: null,
|
type: "货车",
|
shippingDate: getCurrentDate(),
|
shippingCarNumber: "",
|
expressCompany: "",
|
expressNumber: "",
|
};
|
shippingFileList.value = [];
|
};
|
|
// 获取最大可发货数量
|
const getMaxShippingQuantity = () => {
|
if (!currentShippingOrder.value) return 0;
|
const waitShipping = currentShippingOrder.value.waitShippingTotal || 0;
|
return Math.max(0, waitShipping);
|
};
|
|
// 是否可以新增发货
|
const canAddShipping = () => {
|
if (!currentShippingOrder.value) return false;
|
const waitShipping = currentShippingOrder.value.waitShippingTotal || 0;
|
return waitShipping > 0;
|
};
|
|
// 提交发货
|
const submitShipping = () => {
|
proxy.$refs["shippingFormRef"].validate((valid) => {
|
if (valid) {
|
let tempFileIds = [];
|
if (shippingFileList.value !== null && shippingFileList.value.length > 0) {
|
tempFileIds = shippingFileList.value.map((item) => item.tempId);
|
}
|
const payload = {
|
shippingInfoId: currentShippingOrder.value.id,
|
salesLedgerId: currentShippingOrder.value.salesLedgerId,
|
salesLedgerProductId: currentShippingOrder.value.salesLedgerProductId,
|
shippingTotal: currentShippingOrder.value.shippingTotal,
|
shippingNum: shippingForm.value.shippingNum,
|
type: shippingForm.value.type,
|
shippingDate: shippingForm.value.shippingDate,
|
shippingCarNumber: shippingForm.value.type === "货车" ? shippingForm.value.shippingCarNumber : "",
|
expressCompany: shippingForm.value.type === "快递" ? shippingForm.value.expressCompany : "",
|
expressNumber: shippingForm.value.type === "快递" ? shippingForm.value.expressNumber : "",
|
tempFileIds: tempFileIds,
|
};
|
addShippingInfoDetail(payload).then((res) => {
|
proxy.$modal.msgSuccess("发货成功");
|
hideAddShippingForm();
|
loadShippingRecords(currentShippingOrder.value.id);
|
getList();
|
});
|
}
|
});
|
};
|
|
// 删除发货记录
|
const deleteShippingRecord = (row) => {
|
if (isApproving(row.status)) {
|
proxy.$modal.msgWarning("审核中的数据不能删除");
|
return;
|
}
|
ElMessageBox.confirm("此操作将删除该发货记录,是否确认?", "删除", {
|
confirmButtonText: "确认",
|
cancelButtonText: "取消",
|
type: "warning",
|
})
|
.then(() => {
|
delShippingInfoDetail([row.id]).then((res) => {
|
proxy.$modal.msgSuccess("删除成功");
|
loadShippingRecords(currentShippingOrder.value.id);
|
getList();
|
});
|
})
|
.catch(() => {
|
proxy.$modal.msg("已取消");
|
});
|
};
|
|
// 关闭弹框
|
const closeDia = () => {
|
dialogFormVisible.value = false;
|
currentShippingOrder.value = null;
|
shippingRecords.value = [];
|
showAddForm.value = false;
|
};
|
|
// 导出
|
const handleOut = () => {
|
ElMessageBox.confirm("选中的内容将被导出,是否确认导出?", "导出", {
|
confirmButtonText: "确认",
|
cancelButtonText: "取消",
|
type: "warning",
|
})
|
.then(() => {
|
proxy.download("/shippingInfo/export", {}, "发货台账.xlsx");
|
})
|
.catch(() => {
|
proxy.$modal.msg("已取消");
|
});
|
};
|
|
// 批量删除
|
const handleDelete = () => {
|
if (selectedRows.value.length === 0) {
|
proxy.$modal.msgWarning("请选择数据");
|
return;
|
}
|
|
const approvingRows = selectedRows.value.filter(row => isApproving(row.status));
|
if (approvingRows.length > 0) {
|
proxy.$modal.msgWarning("审核中的数据不能删除");
|
return;
|
}
|
|
const ids = selectedRows.value.map((item) => item.id);
|
ElMessageBox.confirm("选中的内容将被删除,是否确认删除?", "删除", {
|
confirmButtonText: "确认",
|
cancelButtonText: "取消",
|
type: "warning",
|
})
|
.then(() => {
|
delDeliveryLedger(ids).then((res) => {
|
proxy.$modal.msgSuccess("删除成功");
|
getList();
|
});
|
})
|
.catch(() => {
|
proxy.$modal.msg("已取消");
|
});
|
};
|
|
// 单个删除
|
const handleDeleteSingle = (row) => {
|
if (isApproving(row.status)) {
|
proxy.$modal.msgWarning("审核中的数据不能删除");
|
return;
|
}
|
|
ElMessageBox.confirm("此操作将删除该记录,是否确认?", "删除", {
|
confirmButtonText: "确认",
|
cancelButtonText: "取消",
|
type: "warning",
|
})
|
.then(() => {
|
delDeliveryLedger([row.id]).then((res) => {
|
proxy.$modal.msgSuccess("删除成功");
|
getList();
|
});
|
})
|
.catch(() => {
|
proxy.$modal.msg("已取消");
|
});
|
};
|
|
// 发货类型校验
|
const validateShippingCarNumber = (value, callback) => {
|
if (shippingForm.value.type === "货车") {
|
if (!value) return callback(new Error("请输入发货车牌号"));
|
}
|
callback();
|
};
|
const validateExpressCompany = (value, callback) => {
|
if (shippingForm.value.type === "快递") {
|
if (!value) return callback(new Error("请输入快递公司"));
|
}
|
callback();
|
};
|
|
// 发货图片上传前校检
|
function handleDeliveryBeforeUpload(file) {
|
const isImage = file.type === 'image/png' || file.type === 'image/jpeg' || file.type === 'image/jpg';
|
if (!isImage) {
|
proxy.$modal.msgError("只能上传 jpg、jpeg、png 格式的图片!");
|
return false;
|
}
|
const isLt10M = file.size / 1024 / 1024 < 10;
|
if (!isLt10M) {
|
proxy.$modal.msgError("上传图片大小不能超过 10MB!");
|
return false;
|
}
|
proxy.$modal.loading("正在上传图片,请稍候...");
|
return true;
|
}
|
|
// 发货图片上传失败
|
function handleDeliveryUploadError(err) {
|
proxy.$modal.msgError("上传图片失败");
|
proxy.$modal.closeLoading();
|
}
|
|
// 发货图片上传成功回调
|
function handleDeliveryUploadSuccess(res, file, uploadFiles) {
|
proxy.$modal.closeLoading();
|
if (res.code === 200) {
|
file.tempId = res.data.tempId;
|
proxy.$modal.msgSuccess("上传成功");
|
} else {
|
proxy.$modal.msgError(res.msg);
|
proxy.$refs.shippingFileUpload.handleRemove(file);
|
}
|
}
|
|
// 移除发货图片
|
function handleShippingRemove(file) {
|
if (file.uid) {
|
delLedgerFile([file.uid]).then(() => {
|
proxy.$modal.msgSuccess("删除成功");
|
});
|
}
|
}
|
|
const getShippingProgress = (row) => {
|
const shipped = row.shippingSuccessTotal || 0;
|
const total = shipped + (row.waitShippingTotal || 0);
|
if (total === 0) return 0;
|
return Math.round((shipped / total) * 100);
|
};
|
|
// 获取进度条颜色
|
const getProgressColor = (row) => {
|
const progress = getShippingProgress(row);
|
if (progress === 100) return '#67C23A';
|
if (progress >= 50) return '#E6A23C';
|
return '#409EFF';
|
};
|
|
// 获取审核状态文本
|
const getApprovalStatusText = (status) => {
|
if (status === null || status === undefined || status === '') {
|
return '待审核';
|
}
|
if (typeof status === 'number') {
|
const statusMap = {
|
0: '待审核',
|
1: '审核中',
|
2: '审核拒绝',
|
3: '审核通过'
|
};
|
return statusMap[status] || '待审核';
|
}
|
const statusStr = String(status).trim();
|
const statusTextMap = {
|
'待审核': '待审核',
|
'审核中': '审核中',
|
'审核拒绝': '审核拒绝',
|
'审核通过': '审核通过',
|
'0': '待审核',
|
'1': '审核中',
|
'2': '审核拒绝',
|
'3': '审核通过'
|
};
|
return statusTextMap[statusStr] || statusStr || '待审核';
|
};
|
|
// 获取审核状态标签类型
|
const getApprovalStatusType = (status) => {
|
if (status === null || status === undefined || status === '') {
|
return 'info';
|
}
|
if (typeof status === 'number') {
|
const typeMap = {
|
0: 'info',
|
1: 'warning',
|
2: 'danger',
|
3: 'success'
|
};
|
return typeMap[status] || 'info';
|
}
|
const statusStr = String(status).trim();
|
const typeTextMap = {
|
'待审核': 'info',
|
'审核中': 'warning',
|
'审核拒绝': 'danger',
|
'审核通过': 'success',
|
'0': 'info',
|
'1': 'warning',
|
'2': 'danger',
|
'3': 'success'
|
};
|
return typeTextMap[statusStr] || 'info';
|
};
|
|
// 检查审核状态是否为"审核通过"
|
const isApproved = (status) => {
|
if (status === null || status === undefined || status === '') {
|
return false;
|
}
|
if (typeof status === 'number') {
|
return status === 3;
|
}
|
const statusStr = String(status).trim();
|
return statusStr === '审核通过' || statusStr === '3';
|
};
|
|
// 检查审核状态是否为"审核中"
|
const isApproving = (status) => {
|
if (status === null || status === undefined || status === '') {
|
return false;
|
}
|
if (typeof status === 'number') {
|
return status === 1;
|
}
|
const statusStr = String(status).trim();
|
return statusStr === '审核中' || statusStr === '1';
|
};
|
|
onMounted(() => {
|
getList();
|
});
|
</script>
|
|
<style scoped lang="scss">
|
.table_list {
|
margin-top: unset;
|
}
|
|
.actions {
|
display: flex;
|
justify-content: space-between;
|
margin-bottom: 10px;
|
}
|
|
:deep(.el-upload-list--picture-card .el-upload-list__item-actions) {
|
.el-upload-list__item-preview {
|
display: none;
|
}
|
}
|
|
.batch-shipping-dialog {
|
.shipping-dialog-container {
|
min-height: 500px;
|
}
|
|
.order-info-card {
|
height: 100%;
|
|
.card-header {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
font-weight: bold;
|
}
|
|
.order-info-content {
|
.info-item {
|
display: flex;
|
justify-content: space-between;
|
padding: 8px 0;
|
|
.label {
|
color: #606266;
|
font-size: 14px;
|
}
|
|
.value {
|
color: #303133;
|
font-weight: 500;
|
font-size: 14px;
|
}
|
}
|
|
.quantity-summary {
|
display: flex;
|
justify-content: space-between;
|
margin: 16px 0;
|
|
.summary-item {
|
text-align: center;
|
flex: 1;
|
|
.summary-label {
|
font-size: 12px;
|
color: #909399;
|
margin-bottom: 8px;
|
}
|
|
.summary-value {
|
font-size: 20px;
|
font-weight: bold;
|
|
&.total {
|
color: #409EFF;
|
}
|
|
&.shipped {
|
color: #67C23A;
|
}
|
|
&.waiting {
|
color: #E6A23C;
|
}
|
}
|
}
|
}
|
|
.progress-wrapper {
|
margin-top: 16px;
|
}
|
}
|
|
.action-buttons {
|
margin-top: 20px;
|
}
|
}
|
|
.shipping-records-card {
|
height: 100%;
|
|
.card-header {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
font-weight: bold;
|
|
.header-actions {
|
display: flex;
|
align-items: center;
|
gap: 12px;
|
|
.record-count {
|
font-size: 12px;
|
color: #909399;
|
font-weight: normal;
|
}
|
}
|
|
.record-count {
|
font-size: 12px;
|
color: #909399;
|
font-weight: normal;
|
}
|
}
|
|
.empty-state {
|
padding: 40px 0;
|
}
|
|
.shipping-records-list {
|
.shipping-record-item {
|
border: 1px solid #EBEEF5;
|
border-radius: 4px;
|
padding: 16px;
|
margin-bottom: 12px;
|
transition: all 0.3s;
|
|
&:hover {
|
border-color: #409EFF;
|
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
}
|
|
&:last-child {
|
margin-bottom: 0;
|
}
|
|
.record-header {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
margin-bottom: 12px;
|
padding-bottom: 12px;
|
border-bottom: 1px solid #F5F7FA;
|
|
.record-title {
|
display: flex;
|
align-items: center;
|
gap: 8px;
|
}
|
|
.record-date {
|
font-size: 12px;
|
color: #909399;
|
}
|
}
|
|
.record-body {
|
.record-info {
|
display: flex;
|
flex-wrap: wrap;
|
gap: 24px;
|
|
.info-row {
|
display: flex;
|
align-items: center;
|
gap: 8px;
|
|
.info-label {
|
font-size: 12px;
|
color: #909399;
|
}
|
|
.info-value {
|
font-size: 14px;
|
color: #303133;
|
|
&.quantity {
|
font-weight: bold;
|
color: #409EFF;
|
font-size: 16px;
|
}
|
}
|
}
|
|
.record-images {
|
display: flex;
|
gap: 8px;
|
flex-wrap: wrap;
|
|
.record-image {
|
width: 60px;
|
height: 60px;
|
border-radius: 4px;
|
cursor: pointer;
|
transition: all 0.3s;
|
|
&:hover {
|
transform: scale(1.05);
|
}
|
}
|
}
|
}
|
}
|
}
|
}
|
}
|
}
|
|
.shipping-detail-wrapper {
|
.detail-images {
|
margin-top: 20px;
|
|
.detail-images-title {
|
font-size: 14px;
|
font-weight: bold;
|
margin-bottom: 12px;
|
}
|
|
.detail-image {
|
width: 120px;
|
height: 120px;
|
margin-right: 12px;
|
margin-bottom: 12px;
|
border-radius: 4px;
|
cursor: pointer;
|
}
|
}
|
}
|
</style>
|