chore: release updated anxinyan version
This commit is contained in:
@@ -745,7 +745,7 @@ function normalizedKeyPoints() {
|
||||
point_code: item.point_code,
|
||||
point_name: item.point_name,
|
||||
point_value: item.point_value.trim(),
|
||||
point_remark: item.point_remark.trim(),
|
||||
point_remark: "",
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -1577,7 +1577,7 @@ onMounted(async () => {
|
||||
<div class="task-form-block">
|
||||
<div class="task-form-block__title">鉴定模板填写</div>
|
||||
<div class="task-panel__desc">
|
||||
选择品类后自动加载对应模板,按关键项逐项填写检查结论和备注。
|
||||
选择品类后自动加载对应模板,按关键项逐项填写检查结果。
|
||||
</div>
|
||||
<div v-loading="appraisalTemplateLoading">
|
||||
<div v-if="resultKeyPoints.length" class="task-key-point-list">
|
||||
@@ -1619,10 +1619,6 @@ onMounted(async () => {
|
||||
/>
|
||||
<el-input v-else v-model="item.point_value" :disabled="isTaskReadonly" placeholder="请输入检查结果" />
|
||||
</div>
|
||||
<div class="task-form-field task-form-field--full">
|
||||
<div class="task-form-field__label">备注</div>
|
||||
<el-input v-model="item.point_remark" :disabled="isTaskReadonly" type="textarea" :rows="2" placeholder="可补充细节、依据或风险点" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
193
admin-web/src/pages/express-companies/index.vue
Normal file
193
admin-web/src/pages/express-companies/index.vue
Normal file
@@ -0,0 +1,193 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, reactive, ref } from "vue";
|
||||
import { ElMessage } from "element-plus";
|
||||
import {
|
||||
adminApi,
|
||||
type AdminExpressCompanyItem,
|
||||
type AdminExpressCompanyPayload,
|
||||
} from "../../api/admin";
|
||||
import OrderStatusTag from "../../components/OrderStatusTag.vue";
|
||||
|
||||
const loading = ref(false);
|
||||
const submitting = ref(false);
|
||||
const dialogVisible = ref(false);
|
||||
const companies = ref<AdminExpressCompanyItem[]>([]);
|
||||
const defaultCompany = ref("");
|
||||
|
||||
const enabledCount = computed(() => companies.value.filter((item) => item.status === "enabled").length);
|
||||
|
||||
const form = reactive<AdminExpressCompanyPayload>({
|
||||
company_name: "",
|
||||
company_code: "",
|
||||
status: "enabled",
|
||||
is_default: false,
|
||||
sort_order: 0,
|
||||
remark: "",
|
||||
});
|
||||
|
||||
async function fetchCompanies() {
|
||||
loading.value = true;
|
||||
try {
|
||||
const response = await adminApi.getExpressCompanies();
|
||||
companies.value = response.data.list;
|
||||
defaultCompany.value = response.data.default_company;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
ElMessage.error("快递公司加载失败");
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
function openDialog(row?: AdminExpressCompanyItem) {
|
||||
if (row) {
|
||||
form.id = row.id;
|
||||
form.company_name = row.company_name;
|
||||
form.company_code = row.company_code;
|
||||
form.status = row.status;
|
||||
form.is_default = row.is_default;
|
||||
form.sort_order = row.sort_order;
|
||||
form.remark = row.remark;
|
||||
} else {
|
||||
form.id = undefined;
|
||||
form.company_name = "";
|
||||
form.company_code = "";
|
||||
form.status = "enabled";
|
||||
form.is_default = companies.value.length === 0;
|
||||
form.sort_order = companies.value.length + 1;
|
||||
form.remark = "";
|
||||
}
|
||||
dialogVisible.value = true;
|
||||
}
|
||||
|
||||
async function submit() {
|
||||
if (!form.company_name.trim()) {
|
||||
ElMessage.warning("请填写快递公司名称");
|
||||
return;
|
||||
}
|
||||
if (form.is_default && form.status !== "enabled") {
|
||||
ElMessage.warning("默认快递公司必须保持启用");
|
||||
return;
|
||||
}
|
||||
|
||||
submitting.value = true;
|
||||
try {
|
||||
await adminApi.saveExpressCompany({
|
||||
...form,
|
||||
company_name: form.company_name.trim(),
|
||||
company_code: form.company_code.trim(),
|
||||
remark: form.remark.trim(),
|
||||
});
|
||||
ElMessage.success(form.id ? "快递公司已更新" : "快递公司已创建");
|
||||
dialogVisible.value = false;
|
||||
await fetchCompanies();
|
||||
} catch (error: any) {
|
||||
console.error(error);
|
||||
ElMessage.error(error?.message || "快递公司保存失败");
|
||||
} finally {
|
||||
submitting.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
function statusTagText(row: AdminExpressCompanyItem) {
|
||||
return row.is_default ? `${row.status_text} / 默认` : row.status_text;
|
||||
}
|
||||
|
||||
onMounted(fetchCompanies);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-loading="loading">
|
||||
<div class="metric-grid" style="margin-bottom: 18px">
|
||||
<div class="metric-card">
|
||||
<div class="metric-card__label">快递公司总数</div>
|
||||
<div class="metric-card__value">{{ companies.length }}</div>
|
||||
<div class="metric-card__desc">当前已维护的可选快递公司</div>
|
||||
</div>
|
||||
<div class="metric-card">
|
||||
<div class="metric-card__label">启用中</div>
|
||||
<div class="metric-card__value">{{ enabledCount }}</div>
|
||||
<div class="metric-card__desc">仓管寄回下拉列表中可选择</div>
|
||||
</div>
|
||||
<div class="metric-card">
|
||||
<div class="metric-card__label">默认快递公司</div>
|
||||
<div class="metric-card__value metric-card__value--text">{{ defaultCompany || "-" }}</div>
|
||||
<div class="metric-card__desc">新登记寄回运单时默认选中</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-card class="panel-card" shadow="never">
|
||||
<div class="filters-row" style="justify-content: space-between;">
|
||||
<div style="color: var(--admin-text-subtle);">
|
||||
维护仓管寄回时可选的快递公司。停用后不会出现在寄回下拉列表中。
|
||||
</div>
|
||||
<el-button type="primary" @click="openDialog()">新增快递公司</el-button>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<el-card class="panel-card orders-table" shadow="never">
|
||||
<el-table :data="companies" stripe>
|
||||
<el-table-column prop="company_name" label="快递公司" min-width="180" />
|
||||
<el-table-column prop="company_code" label="编码" min-width="160" />
|
||||
<el-table-column label="状态" min-width="140">
|
||||
<template #default="{ row }">
|
||||
<OrderStatusTag :status="statusTagText(row)" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="sort_order" label="排序" min-width="90" />
|
||||
<el-table-column prop="remark" label="备注" min-width="240" />
|
||||
<el-table-column prop="updated_at" label="更新时间" min-width="170" />
|
||||
<el-table-column label="操作" fixed="right" width="100">
|
||||
<template #default="{ row }">
|
||||
<el-button link type="primary" @click="openDialog(row)">编辑</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-card>
|
||||
|
||||
<el-dialog v-model="dialogVisible" :title="form.id ? '编辑快递公司' : '新增快递公司'" width="560px">
|
||||
<el-form label-position="top">
|
||||
<el-form-item label="快递公司名称">
|
||||
<el-input v-model="form.company_name" maxlength="64" placeholder="例如:顺丰速运" />
|
||||
</el-form-item>
|
||||
<el-form-item label="编码">
|
||||
<el-input v-model="form.company_code" maxlength="64" placeholder="可留空,系统自动生成" />
|
||||
</el-form-item>
|
||||
<el-row :gutter="16">
|
||||
<el-col :span="12">
|
||||
<el-form-item label="状态">
|
||||
<el-select v-model="form.status" style="width: 100%">
|
||||
<el-option label="启用" value="enabled" />
|
||||
<el-option label="停用" value="disabled" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="排序值">
|
||||
<el-input v-model.number="form.sort_order" type="number" placeholder="越小越靠前" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-form-item label="默认设置">
|
||||
<el-checkbox v-model="form.is_default">设为默认快递公司</el-checkbox>
|
||||
</el-form-item>
|
||||
<el-form-item label="备注">
|
||||
<el-input v-model="form.remark" type="textarea" :rows="3" maxlength="255" placeholder="内部备注,可不填" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="dialogVisible = false">取消</el-button>
|
||||
<el-button type="primary" :loading="submitting" @click="submit">保存</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.metric-card__value--text {
|
||||
overflow: hidden;
|
||||
font-size: 24px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
</style>
|
||||
@@ -1,8 +1,9 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, ref } from "vue";
|
||||
import { ElMessage, ElMessageBox } from "element-plus";
|
||||
import { adminApi, type AdminManualOrderCreatePayload, type AdminManualOrderMeta, type AdminOrderDetail, type AdminOrderListItem, type AdminOrderWarehouseOption } from "../../api/admin";
|
||||
import { adminApi, type AdminExpressCompanyItem, type AdminManualOrderCreatePayload, type AdminManualOrderMeta, type AdminOrderDetail, type AdminOrderListItem, type AdminOrderWarehouseOption } from "../../api/admin";
|
||||
import OrderStatusTag from "../../components/OrderStatusTag.vue";
|
||||
import { recognizeReturnAddress } from "../../utils/address-recognition";
|
||||
|
||||
const loading = ref(false);
|
||||
const detailLoading = ref(false);
|
||||
@@ -18,11 +19,15 @@ const returnDialogVisible = ref(false);
|
||||
const returnSubmitting = ref(false);
|
||||
const returnExpressCompany = ref("");
|
||||
const returnTrackingNo = ref("");
|
||||
const expressCompanyLoading = ref(false);
|
||||
const expressCompanyOptions = ref<AdminExpressCompanyItem[]>([]);
|
||||
const defaultExpressCompany = ref("");
|
||||
const manualDialogVisible = ref(false);
|
||||
const manualSubmitting = ref(false);
|
||||
const manualMetaLoading = ref(false);
|
||||
const manualMeta = ref<AdminManualOrderMeta>({ categories: [], brands: [] });
|
||||
const manualForm = ref<AdminManualOrderCreatePayload>(createManualOrderForm());
|
||||
const manualAddressRecognitionText = ref("");
|
||||
|
||||
const keyword = ref("");
|
||||
const serviceProvider = ref("");
|
||||
@@ -113,6 +118,27 @@ const logisticsActionText = computed(() => {
|
||||
const canSubmitReturnLogistics = computed(() => Boolean(detail.value?.order_info.can_submit_return_logistics));
|
||||
const returnLogisticsBlockReason = computed(() => detail.value?.order_info.return_logistics_block_reason || "");
|
||||
const canMarkReturnReceived = computed(() => Boolean(detail.value?.order_info.can_mark_return_received));
|
||||
const expressCompanySelectOptions = computed(() => {
|
||||
if (!returnExpressCompany.value || expressCompanyOptions.value.some((item) => item.company_name === returnExpressCompany.value)) {
|
||||
return expressCompanyOptions.value;
|
||||
}
|
||||
|
||||
return [
|
||||
{
|
||||
id: 0,
|
||||
company_name: returnExpressCompany.value,
|
||||
company_code: returnExpressCompany.value,
|
||||
status: "enabled",
|
||||
status_text: "启用中",
|
||||
is_default: false,
|
||||
sort_order: 0,
|
||||
remark: "",
|
||||
created_at: "",
|
||||
updated_at: "",
|
||||
},
|
||||
...expressCompanyOptions.value,
|
||||
];
|
||||
});
|
||||
function createManualOrderForm(): AdminManualOrderCreatePayload {
|
||||
return {
|
||||
service_provider: "anxinyan",
|
||||
@@ -185,10 +211,40 @@ async function ensureManualMeta() {
|
||||
|
||||
async function openManualDialog() {
|
||||
manualForm.value = createManualOrderForm();
|
||||
manualAddressRecognitionText.value = "";
|
||||
manualDialogVisible.value = true;
|
||||
await ensureManualMeta();
|
||||
}
|
||||
|
||||
async function ensureExpressCompanyOptions() {
|
||||
if (expressCompanyOptions.value.length) return;
|
||||
expressCompanyLoading.value = true;
|
||||
try {
|
||||
const response = await adminApi.getExpressCompanies({ enabled_only: 1 });
|
||||
expressCompanyOptions.value = response.data.list;
|
||||
defaultExpressCompany.value = response.data.default_company;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
ElMessage.error("快递公司列表加载失败");
|
||||
} finally {
|
||||
expressCompanyLoading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
function applyRecognizedManualAddress() {
|
||||
const result = recognizeReturnAddress(manualAddressRecognitionText.value);
|
||||
if (!result.ok || !result.address) {
|
||||
ElMessage.warning(result.message || "寄回地址识别失败");
|
||||
return;
|
||||
}
|
||||
|
||||
manualForm.value.return_address = {
|
||||
...manualForm.value.return_address,
|
||||
...result.address,
|
||||
};
|
||||
ElMessage.success("寄回地址已识别并填入");
|
||||
}
|
||||
|
||||
function validateManualForm() {
|
||||
const form = manualForm.value;
|
||||
if (!form.product_info.category_id) {
|
||||
@@ -312,13 +368,14 @@ async function submitWarehouseReassign() {
|
||||
}
|
||||
}
|
||||
|
||||
function openReturnDialog() {
|
||||
async function openReturnDialog() {
|
||||
if (!detail.value) return;
|
||||
if (!canSubmitReturnLogistics.value) {
|
||||
ElMessage.warning(returnLogisticsBlockReason.value || "当前订单暂不支持登记回寄运单");
|
||||
return;
|
||||
}
|
||||
returnExpressCompany.value = detail.value.return_logistics?.express_company || "";
|
||||
await ensureExpressCompanyOptions();
|
||||
returnExpressCompany.value = detail.value.return_logistics?.express_company || defaultExpressCompany.value || expressCompanyOptions.value[0]?.company_name || "";
|
||||
returnTrackingNo.value = detail.value.return_logistics?.tracking_no || "";
|
||||
returnDialogVisible.value = true;
|
||||
}
|
||||
@@ -735,7 +792,20 @@ onMounted(fetchOrders);
|
||||
<el-dialog v-model="returnDialogVisible" title="登记回寄运单" width="520px">
|
||||
<el-form label-position="top">
|
||||
<el-form-item label="回寄快递公司">
|
||||
<el-input v-model="returnExpressCompany" placeholder="例如:顺丰速运" />
|
||||
<el-select
|
||||
v-model="returnExpressCompany"
|
||||
:loading="expressCompanyLoading"
|
||||
filterable
|
||||
placeholder="请选择回寄快递公司"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in expressCompanySelectOptions"
|
||||
:key="`${item.id}-${item.company_name}`"
|
||||
:label="item.company_name"
|
||||
:value="item.company_name"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="回寄运单号">
|
||||
<el-input v-model="returnTrackingNo" placeholder="请输入回寄运单号" />
|
||||
@@ -810,6 +880,18 @@ onMounted(fetchOrders);
|
||||
<div class="manual-section">
|
||||
<div class="manual-section__title">寄回信息</div>
|
||||
<el-form label-position="top">
|
||||
<el-form-item label="自动识别寄回地址">
|
||||
<div class="manual-address-recognition">
|
||||
<el-input
|
||||
v-model="manualAddressRecognitionText"
|
||||
type="textarea"
|
||||
:rows="5"
|
||||
resize="none"
|
||||
placeholder="粘贴收货人、收货电话、收货地址,自动识别后填入下方字段"
|
||||
/>
|
||||
<el-button @click="applyRecognizedManualAddress">识别并填入</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<div class="manual-grid">
|
||||
<el-form-item label="收件人">
|
||||
<el-input v-model="manualForm.return_address.consignee" placeholder="用于匹配或创建用户" />
|
||||
@@ -985,6 +1067,15 @@ onMounted(fetchOrders);
|
||||
gap: 0 18px;
|
||||
}
|
||||
|
||||
.manual-address-recognition {
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.manual-address-recognition .el-button {
|
||||
justify-self: flex-start;
|
||||
}
|
||||
|
||||
.manual-upload-head {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
@@ -56,6 +56,7 @@ const drawerVisible = ref(false);
|
||||
const inspectionDrawerVisible = ref(false);
|
||||
const inspectionSubmitting = ref(false);
|
||||
const publishingId = ref<number | null>(null);
|
||||
const traceVisibilitySavingId = ref<number | null>(null);
|
||||
const detailQrDataUrl = ref("");
|
||||
|
||||
const keyword = ref("");
|
||||
@@ -279,6 +280,7 @@ type PublishReportTarget = Pick<AdminReportListItem, "id" | "report_status" | "r
|
||||
report_type: string;
|
||||
material_tag_bound: boolean;
|
||||
};
|
||||
type ReportTraceVisibilityTarget = Pick<AdminReportListItem, "id" | "trace_info_visible">;
|
||||
|
||||
async function promptReportMaterialTagInput() {
|
||||
try {
|
||||
@@ -344,6 +346,46 @@ async function publishReport(row: PublishReportTarget) {
|
||||
}
|
||||
}
|
||||
|
||||
function switchValueToBoolean(value: unknown) {
|
||||
if (typeof value === "boolean") return value;
|
||||
if (typeof value === "number") return value === 1;
|
||||
return ["1", "true", "yes", "on"].includes(String(value).trim().toLowerCase());
|
||||
}
|
||||
|
||||
async function updateReportTraceVisibility(row: ReportTraceVisibilityTarget, value: unknown) {
|
||||
const visible = switchValueToBoolean(value);
|
||||
traceVisibilitySavingId.value = row.id;
|
||||
try {
|
||||
const response = await adminApi.updateReportTraceVisibility(row.id, visible);
|
||||
if (response.code !== 0) {
|
||||
ElMessage.error(response.message || "追溯信息开关保存失败");
|
||||
return;
|
||||
}
|
||||
|
||||
const appliedVisible = Boolean(response.data.trace_info_visible);
|
||||
row.trace_info_visible = appliedVisible;
|
||||
|
||||
const listItem = reports.value.find((item) => item.id === row.id);
|
||||
if (listItem) {
|
||||
listItem.trace_info_visible = appliedVisible;
|
||||
}
|
||||
if (detail.value?.report_header.id === row.id) {
|
||||
detail.value.report_header.trace_info_visible = appliedVisible;
|
||||
}
|
||||
|
||||
ElMessage.success(response.message || (appliedVisible ? "追溯信息已设为显示" : "追溯信息已隐藏"));
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
ElMessage.error("追溯信息开关保存失败");
|
||||
} finally {
|
||||
traceVisibilitySavingId.value = null;
|
||||
}
|
||||
}
|
||||
|
||||
function handleTraceVisibilityChange(row: ReportTraceVisibilityTarget, value: unknown) {
|
||||
void updateReportTraceVisibility(row, value);
|
||||
}
|
||||
|
||||
function validateInspectionForm() {
|
||||
const { report_header, product_info, result_info } = inspectionForm.value;
|
||||
if (!report_header.report_title.trim()) {
|
||||
@@ -466,6 +508,18 @@ watch(
|
||||
<span v-else class="detail-label">不适用</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="追溯信息" min-width="130">
|
||||
<template #default="{ row }">
|
||||
<el-switch
|
||||
:model-value="row.trace_info_visible"
|
||||
:loading="traceVisibilitySavingId === row.id"
|
||||
inline-prompt
|
||||
active-text="显示"
|
||||
inactive-text="隐藏"
|
||||
@change="handleTraceVisibilityChange(row, $event)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="institution_name" label="出具机构" min-width="160" />
|
||||
<el-table-column prop="publish_time" label="发布时间" min-width="170" />
|
||||
<el-table-column label="操作" fixed="right" width="220">
|
||||
@@ -538,6 +592,20 @@ watch(
|
||||
<div class="detail-label">出具机构</div>
|
||||
<div class="detail-value">{{ detail.report_header.institution_name }}</div>
|
||||
</div>
|
||||
<div class="detail-card__desc">
|
||||
<div class="detail-label">追溯信息</div>
|
||||
<div class="detail-value report-visibility-control">
|
||||
<el-switch
|
||||
:model-value="detail.report_header.trace_info_visible"
|
||||
:loading="traceVisibilitySavingId === detail.report_header.id"
|
||||
inline-prompt
|
||||
active-text="显示"
|
||||
inactive-text="隐藏"
|
||||
@change="handleTraceVisibilityChange(detail.report_header, $event)"
|
||||
/>
|
||||
<span>{{ detail.report_header.trace_info_visible ? "用户端显示追溯信息 tab" : "用户端隐藏追溯信息 tab" }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="detail-card">
|
||||
@@ -599,7 +667,7 @@ watch(
|
||||
<template v-if="detail.result_info.key_points?.length">
|
||||
<div v-for="(item, index) in detail.result_info.key_points" :key="`${item.point_code || item.point_name}-${index}`" class="detail-card__desc">
|
||||
<div class="detail-label">{{ item.point_name || "鉴定项" }}</div>
|
||||
<div class="detail-value">{{ [item.point_value, item.point_remark].filter(Boolean).join(";") || "-" }}</div>
|
||||
<div class="detail-value">{{ item.point_value || "-" }}</div>
|
||||
</div>
|
||||
</template>
|
||||
<div v-if="detail.result_info.external_remark" class="detail-card__desc">
|
||||
@@ -987,4 +1055,17 @@ watch(
|
||||
.report-evidence-card__body {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.report-visibility-control {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.report-visibility-control span {
|
||||
color: var(--admin-text-subtle);
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, defineComponent, h, nextTick, ref, type PropType } from "vue";
|
||||
import { computed, defineComponent, h, nextTick, onMounted, ref, type PropType } from "vue";
|
||||
import { ElMessage, type InputInstance } from "element-plus";
|
||||
import {
|
||||
adminApi,
|
||||
type AdminExpressCompanyItem,
|
||||
type AdminFileAsset,
|
||||
type AdminReportDetail,
|
||||
type AdminWarehouseWorkbenchContext,
|
||||
@@ -20,6 +21,9 @@ const returnTagNo = ref("");
|
||||
const returnMaterialQr = ref("");
|
||||
const returnExpressCompany = ref("");
|
||||
const returnTrackingNo = ref("");
|
||||
const expressCompanyLoading = ref(false);
|
||||
const expressCompanyOptions = ref<AdminExpressCompanyItem[]>([]);
|
||||
const defaultExpressCompany = ref("");
|
||||
const inboundAttachments = ref<AdminFileAsset[]>([]);
|
||||
const returnPackingAttachments = ref<AdminFileAsset[]>([]);
|
||||
|
||||
@@ -47,6 +51,27 @@ const returnReportActionText = computed(() => {
|
||||
if (currentReturnIsZhongjian.value || returnMaterialMatched.value) return "核对报告";
|
||||
return "匹配吊牌并核对报告";
|
||||
});
|
||||
const expressCompanySelectOptions = computed(() => {
|
||||
if (!returnExpressCompany.value || expressCompanyOptions.value.some((item) => item.company_name === returnExpressCompany.value)) {
|
||||
return expressCompanyOptions.value;
|
||||
}
|
||||
|
||||
return [
|
||||
{
|
||||
id: 0,
|
||||
company_name: returnExpressCompany.value,
|
||||
company_code: returnExpressCompany.value,
|
||||
status: "enabled",
|
||||
status_text: "启用中",
|
||||
is_default: false,
|
||||
sort_order: 0,
|
||||
remark: "",
|
||||
created_at: "",
|
||||
updated_at: "",
|
||||
},
|
||||
...expressCompanyOptions.value,
|
||||
];
|
||||
});
|
||||
|
||||
const OrderContextCard = defineComponent({
|
||||
name: "OrderContextCard",
|
||||
@@ -225,6 +250,21 @@ function removeInboundAttachment(fileUrl: string) {
|
||||
inboundAttachments.value = inboundAttachments.value.filter((item) => item.file_url !== fileUrl);
|
||||
}
|
||||
|
||||
async function ensureExpressCompanyOptions() {
|
||||
if (expressCompanyOptions.value.length) return;
|
||||
expressCompanyLoading.value = true;
|
||||
try {
|
||||
const response = await adminApi.getExpressCompanies({ enabled_only: 1 });
|
||||
expressCompanyOptions.value = response.data.list;
|
||||
defaultExpressCompany.value = response.data.default_company;
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
ElMessage.error("快递公司列表加载失败");
|
||||
} finally {
|
||||
expressCompanyLoading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
async function lookupZhongjian() {
|
||||
if (!zhongjianTagNo.value.trim()) {
|
||||
ElMessage.warning("请扫描内部流转码");
|
||||
@@ -274,8 +314,9 @@ async function lookupReturn() {
|
||||
}
|
||||
loading.value = true;
|
||||
try {
|
||||
await ensureExpressCompanyOptions();
|
||||
returnMaterialQr.value = "";
|
||||
returnExpressCompany.value = "";
|
||||
returnExpressCompany.value = defaultExpressCompany.value || expressCompanyOptions.value[0]?.company_name || "";
|
||||
returnTrackingNo.value = "";
|
||||
returnPackingAttachments.value = [];
|
||||
returnReviewReport.value = null;
|
||||
@@ -449,6 +490,10 @@ function openFile(url: string) {
|
||||
if (!url) return;
|
||||
window.open(url, "_blank", "noopener,noreferrer");
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
void ensureExpressCompanyOptions();
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -570,7 +615,21 @@ function openFile(url: string) {
|
||||
</el-button>
|
||||
</div>
|
||||
<div v-if="returnContext && returnConfirmed" class="return-form">
|
||||
<el-input v-model="returnExpressCompany" size="large" placeholder="回寄快递公司,例如:顺丰速运" />
|
||||
<el-select
|
||||
v-model="returnExpressCompany"
|
||||
:loading="expressCompanyLoading"
|
||||
filterable
|
||||
size="large"
|
||||
placeholder="请选择回寄快递公司"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in expressCompanySelectOptions"
|
||||
:key="`${item.id}-${item.company_name}`"
|
||||
:label="item.company_name"
|
||||
:value="item.company_name"
|
||||
/>
|
||||
</el-select>
|
||||
<el-input ref="returnTrackingInputRef" v-model="returnTrackingNo" size="large" placeholder="扫描或输入回寄运单号" @keyup.enter="shipReturn" />
|
||||
<div class="packing-upload">
|
||||
<div class="packing-upload-head">
|
||||
|
||||
Reference in New Issue
Block a user