chore: sync release updates

This commit is contained in:
wushumin
2026-05-22 15:47:23 +08:00
parent be64b8e5b7
commit baef2fb64c
23 changed files with 879 additions and 131 deletions

View File

@@ -238,13 +238,30 @@ function updateTemplatePoint(index: number, key: "point_value" | "point_remark",
current[key] = value;
}
function inputEventValue(event: unknown) {
if (typeof event === "string" || typeof event === "number") {
return String(event);
}
const inputEvent = event as {
detail?: { value?: unknown };
target?: { value?: unknown };
};
if (inputEvent?.detail && "value" in inputEvent.detail) {
return String(inputEvent.detail.value ?? "");
}
if (inputEvent?.target && "value" in inputEvent.target) {
return String(inputEvent.target.value ?? "");
}
return "";
}
function updateTemplatePointFromInput(
index: number,
key: "point_value" | "point_remark",
event: Event,
event: unknown,
) {
const target = event.target as HTMLInputElement | HTMLTextAreaElement | null;
updateTemplatePoint(index, key, target?.value || "");
updateTemplatePoint(index, key, inputEventValue(event));
}
function templateKeyPointsPayload() {
@@ -256,6 +273,15 @@ function templateKeyPointsPayload() {
})) || [];
}
function validateRequiredTemplatePoints() {
const missing = detail.value?.appraisal_template?.key_points?.find((item) => item.is_required && !String(item.point_value || "").trim());
if (!missing) {
return true;
}
showInfoToast(`请填写鉴定模板项:${missing.point_name}`);
return false;
}
function returnToWorkOrders(message: string) {
showInfoToast(message);
setTimeout(() => {
@@ -375,11 +401,18 @@ async function chooseEvidenceVideo() {
try {
const result = await uni.chooseVideo({
sourceType: ["album", "camera"],
compressed: true,
maxDuration: 600,
});
const filePath = result.tempFilePath;
if (!filePath) return;
uploading.value = true;
const asset = await adminApi.uploadAppraisalEvidenceFile(filePath, detail.value.task_info.id);
const tempFile = result.tempFile as File | undefined;
const asset = await adminApi.uploadAppraisalEvidenceFile(filePath, detail.value.task_info.id, {
original_name: tempFile?.name,
file_size: Number(result.size || tempFile?.size || 0),
mime_type: tempFile?.type || "video/mp4",
});
evidenceFiles.value.push(asset);
showInfoToast("视频上传成功");
} catch (error) {
@@ -403,7 +436,7 @@ async function chooseZhongjianImage() {
if (!result.tempFilePaths?.length) return;
uploading.value = true;
for (const filePath of result.tempFilePaths) {
const asset = await adminApi.uploadAppraisalEvidenceFile(filePath, detail.value.task_info.id);
const asset = await adminApi.uploadAppraisalEvidenceFile(filePath, detail.value.task_info.id, {}, "zhongjian_report");
zhongjianFiles.value.push(asset);
}
showInfoToast("图片上传成功");
@@ -422,11 +455,23 @@ async function chooseZhongjianVideo() {
try {
const result = await uni.chooseVideo({
sourceType: ["album", "camera"],
compressed: true,
maxDuration: 600,
});
const filePath = result.tempFilePath;
if (!filePath) return;
uploading.value = true;
const asset = await adminApi.uploadAppraisalEvidenceFile(filePath, detail.value.task_info.id);
const tempFile = result.tempFile as File | undefined;
const asset = await adminApi.uploadAppraisalEvidenceFile(
filePath,
detail.value.task_info.id,
{
original_name: tempFile?.name,
file_size: Number(result.size || tempFile?.size || 0),
mime_type: tempFile?.type || "video/mp4",
},
"zhongjian_report",
);
zhongjianFiles.value.push(asset);
showInfoToast("视频上传成功");
} catch (error) {
@@ -452,6 +497,13 @@ async function submitResult(action: "save" | "submit") {
showInfoToast("请先填写鉴定结论");
return;
}
if (action === "submit" && !productName.value.trim() && !categoryName.value.trim() && !brandName.value.trim()) {
showInfoToast("请先完善物品信息");
return;
}
if (action === "submit" && !validateRequiredTemplatePoints()) {
return;
}
const qrInput = action === "submit" ? await confirmAndScanMaterialTag() : "";
if (action === "submit" && !qrInput) {
@@ -487,12 +539,12 @@ async function submitResult(action: "save" | "submit") {
action,
product_info: {
category_id: detail.value!.product_info.category_id,
product_name: detail.value!.product_info.product_name,
category_name: detail.value!.product_info.category_name,
brand_name: detail.value!.product_info.brand_name,
color: detail.value!.product_info.color,
size_spec: detail.value!.product_info.size_spec,
serial_no: detail.value!.product_info.serial_no,
product_name: productName.value.trim(),
category_name: categoryName.value.trim(),
brand_name: brandName.value.trim(),
color: color.value.trim(),
size_spec: sizeSpec.value.trim(),
serial_no: serialNo.value.trim(),
},
result_text: resultText.value.trim(),
result_desc: resultDesc.value.trim(),
@@ -573,6 +625,9 @@ async function submitZhongjianReport() {
showInfoToast("请先完善物品信息");
return;
}
if (!validateRequiredTemplatePoints()) {
return;
}
if (!zhongjianFiles.value.length) {
showInfoToast("请至少上传 1 个中检报告文件");
return;
@@ -691,6 +746,16 @@ onShow(() => {
<view v-if="activeSection === 'result' && !isZhongjian" class="card">
<view class="card-title">鉴定结论</view>
<view class="stack" style="margin-top: 18rpx">
<view class="card-desc">报告展示信息</view>
<input v-model="productName" class="field" :disabled="isTaskReadonly" placeholder="产品名称" />
<input v-model="categoryName" class="field" :disabled="isTaskReadonly" placeholder="品类" />
<input v-model="brandName" class="field" :disabled="isTaskReadonly" placeholder="品牌" />
<view class="meta-grid">
<input v-model="color" class="field" :disabled="isTaskReadonly" placeholder="颜色" />
<input v-model="sizeSpec" class="field" :disabled="isTaskReadonly" placeholder="规格 / 尺寸" />
</view>
<input v-model="serialNo" class="field" :disabled="isTaskReadonly" placeholder="序列号 / 编码" />
<view class="card-desc">鉴定结果</view>
<input v-model="resultText" class="field" :disabled="isTaskReadonly" placeholder="结论,例如:正品 / 存疑" />
<textarea v-model="resultDesc" class="textarea" :disabled="isTaskReadonly" placeholder="结论说明" />
<template v-if="showConditionFields">