diff --git a/admin-web/src/pages/orders/index.vue b/admin-web/src/pages/orders/index.vue
index ccce150..2361144 100644
--- a/admin-web/src/pages/orders/index.vue
+++ b/admin-web/src/pages/orders/index.vue
@@ -208,8 +208,8 @@ function handleManualCategoryChange() {
function validateManualForm() {
const form = manualForm.value;
- if (!form.product_info.category_id || !form.product_info.brand_id || !form.product_info.product_name.trim()) {
- ElMessage.warning("请完整填写品类、品牌和商品名称");
+ if (!form.product_info.category_id || !form.product_info.brand_id) {
+ ElMessage.warning("请完整填写品类和品牌");
return false;
}
const address = form.return_address;
@@ -827,7 +827,7 @@ onMounted(fetchOrders);
-
+
diff --git a/docs/sop/安心验PC管理后台SOP手册.pdf b/docs/sop/安心验PC管理后台SOP手册.pdf
new file mode 100644
index 0000000..d0d833c
Binary files /dev/null and b/docs/sop/安心验PC管理后台SOP手册.pdf differ
diff --git a/docs/sop/安心验作业端SOP手册-仓管与鉴定师.pdf b/docs/sop/安心验作业端SOP手册-仓管与鉴定师.pdf
new file mode 100644
index 0000000..4f30f4c
Binary files /dev/null and b/docs/sop/安心验作业端SOP手册-仓管与鉴定师.pdf differ
diff --git a/docs/sop/安心验用户端SOP手册.pdf b/docs/sop/安心验用户端SOP手册.pdf
new file mode 100644
index 0000000..79d7589
Binary files /dev/null and b/docs/sop/安心验用户端SOP手册.pdf differ
diff --git a/server-api/app/controller/admin/OrdersController.php b/server-api/app/controller/admin/OrdersController.php
index 1d115d7..63bb580 100644
--- a/server-api/app/controller/admin/OrdersController.php
+++ b/server-api/app/controller/admin/OrdersController.php
@@ -949,8 +949,8 @@ class OrdersController
if ($serviceProvider === '') {
return api_error('服务类型不正确', 422);
}
- if ($categoryId <= 0 || $brandId <= 0 || $productName === '') {
- return api_error('请完整填写品类、品牌和商品名称', 422);
+ if ($categoryId <= 0 || $brandId <= 0) {
+ return api_error('请完整填写品类和品牌', 422);
}
if ($consignee === '' || $mobile === '' || $province === '' || $city === '' || $district === '' || $detailAddress === '') {
return api_error('请完整填写寄回收件信息', 422);
diff --git a/server-api/tools/release_audit.php b/server-api/tools/release_audit.php
index e9f135c..2bc5760 100644
--- a/server-api/tools/release_audit.php
+++ b/server-api/tools/release_audit.php
@@ -51,6 +51,25 @@ function isPlaceholderApiBase(string $apiBase): bool
return str_contains($normalized, 'example.com');
}
+function checkClientProductionApiBase(array &$issues, string $label, string $envPath): void
+{
+ $env = @parse_ini_file($envPath);
+ if (!is_array($env)) {
+ add_issue($issues, 'FAIL', "{$label} 缺少生产环境变量", "无法解析 {$envPath}。");
+ return;
+ }
+
+ $apiBase = (string)($env['VITE_API_BASE_URL'] ?? '');
+ if (isPlaceholderApiBase($apiBase)) {
+ add_issue($issues, 'FAIL', "{$label} 生产 API 未配置正式域名", "{$envPath} 的 VITE_API_BASE_URL 仍为本地或占位地址。");
+ return;
+ }
+
+ if (rtrim($apiBase, '/') !== 'https://api.anxinjianyan.com') {
+ add_issue($issues, 'FAIL', "{$label} 生产 API 域名不符合发布规则", "{$envPath} 的 VITE_API_BASE_URL 必须为 https://api.anxinjianyan.com。");
+ }
+}
+
$env = $_ENV;
check(($env['APP_ENV'] ?? '') === 'production', $issues, 'FAIL', 'APP_ENV 非 production', '当前 .env 中 APP_ENV 不是 production。');
check(in_array(strtolower((string)($env['APP_DEBUG'] ?? '')), ['false', '0'], true), $issues, 'FAIL', 'APP_DEBUG 未关闭', '当前 .env 中 APP_DEBUG 仍然开启。');
@@ -161,26 +180,9 @@ if (!is_array($manifest)) {
}
}
-$adminProdEnvPath = $projectRoot . '/admin-web/.env.production';
-$userProdEnvPath = $projectRoot . '/user-app/.env.production';
-$adminProdEnv = @parse_ini_file($adminProdEnvPath);
-$userProdEnv = @parse_ini_file($userProdEnvPath);
-if (is_array($adminProdEnv)) {
- $adminApiBase = (string)($adminProdEnv['VITE_API_BASE_URL'] ?? '');
- if (isPlaceholderApiBase($adminApiBase)) {
- add_issue($issues, 'FAIL', 'admin-web 生产 API 未配置正式域名', 'admin-web/.env.production 的 VITE_API_BASE_URL 仍为本地或占位地址。');
- }
-} else {
- add_issue($issues, 'FAIL', 'admin-web 缺少生产环境变量', '无法解析 admin-web/.env.production。');
-}
-if (is_array($userProdEnv)) {
- $userApiBase = (string)($userProdEnv['VITE_API_BASE_URL'] ?? '');
- if (isPlaceholderApiBase($userApiBase)) {
- add_issue($issues, 'FAIL', 'user-app 生产 API 未配置正式域名', 'user-app/.env.production 的 VITE_API_BASE_URL 仍为本地或占位地址。');
- }
-} else {
- add_issue($issues, 'FAIL', 'user-app 缺少生产环境变量', '无法解析 user-app/.env.production。');
-}
+checkClientProductionApiBase($issues, 'admin-web', $projectRoot . '/admin-web/.env.production');
+checkClientProductionApiBase($issues, 'user-app', $projectRoot . '/user-app/.env.production');
+checkClientProductionApiBase($issues, 'work-app', $projectRoot . '/work-app/.env.production');
if (!$issues) {
echo "RELEASE_AUDIT_OK\n";
diff --git a/work-app/src/pages/order/manual-create.vue b/work-app/src/pages/order/manual-create.vue
index db71777..373252b 100644
--- a/work-app/src/pages/order/manual-create.vue
+++ b/work-app/src/pages/order/manual-create.vue
@@ -157,8 +157,8 @@ function pickerText(options: Array<{ label?: string; name?: string }>, index: nu
function validateForm() {
const product = form.value.product_info;
const address = form.value.return_address;
- if (!product.category_id || !product.brand_id || !product.product_name.trim()) {
- showInfoToast("请完整填写品类、品牌和商品名称");
+ if (!product.category_id || !product.brand_id) {
+ showInfoToast("请完整填写品类和品牌");
return false;
}
if (!address.consignee.trim() || !address.mobile.trim() || !address.province.trim() || !address.city.trim() || !address.district.trim() || !address.detail_address.trim()) {
@@ -251,7 +251,7 @@ onLoad(() => {
{{ pickerText(brandOptions, brandIndex, "选择品牌") }}
-
+
diff --git a/work-app/src/utils/request.ts b/work-app/src/utils/request.ts
index 58de783..bebfc08 100644
--- a/work-app/src/utils/request.ts
+++ b/work-app/src/utils/request.ts
@@ -2,6 +2,7 @@ import { buildAuthHeaders, clearAdminSession, redirectToLogin } from "./auth";
import { resolveApiBaseUrl } from "./env";
const BASE_URL = resolveApiBaseUrl().replace(/\/$/, "");
+const REQUEST_TIMEOUT_MS = 15000;
type RequestMethod = "GET" | "POST" | "PUT" | "DELETE" | "OPTIONS" | "HEAD";
@@ -22,6 +23,25 @@ function buildUrl(url: string, params?: Record(
url: string,
options: {
@@ -42,6 +62,7 @@ export function request(
method,
data: options.data,
header: headers,
+ timeout: REQUEST_TIMEOUT_MS,
success: (response: UniApp.RequestSuccessCallbackResult) => {
const payload = response.data as ApiResponse;
if (payload?.code === 0) {
@@ -56,7 +77,7 @@ export function request(
}
reject(new Error(payload?.message || "请求失败"));
},
- fail: (error: UniApp.GeneralCallbackResult) => reject(error),
+ fail: (error: UniApp.GeneralCallbackResult) => reject(buildNetworkError(error)),
});
});
}
@@ -103,7 +124,7 @@ export function uploadFile(url: string, filePath: string, formData: Record reject(error),
+ fail: (error) => reject(buildNetworkError(error)),
});
});
}