chore: sync pending workspace updates
This commit is contained in:
@@ -208,8 +208,8 @@ function handleManualCategoryChange() {
|
|||||||
|
|
||||||
function validateManualForm() {
|
function validateManualForm() {
|
||||||
const form = manualForm.value;
|
const form = manualForm.value;
|
||||||
if (!form.product_info.category_id || !form.product_info.brand_id || !form.product_info.product_name.trim()) {
|
if (!form.product_info.category_id || !form.product_info.brand_id) {
|
||||||
ElMessage.warning("请完整填写品类、品牌和商品名称");
|
ElMessage.warning("请完整填写品类和品牌");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const address = form.return_address;
|
const address = form.return_address;
|
||||||
@@ -827,7 +827,7 @@ onMounted(fetchOrders);
|
|||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="商品名称">
|
<el-form-item label="商品名称">
|
||||||
<el-input v-model="manualForm.product_info.product_name" placeholder="例如:Classic Flap 手袋" />
|
<el-input v-model="manualForm.product_info.product_name" placeholder="可选,例如:Classic Flap 手袋" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="颜色">
|
<el-form-item label="颜色">
|
||||||
<el-input v-model="manualForm.product_info.color" placeholder="可选" />
|
<el-input v-model="manualForm.product_info.color" placeholder="可选" />
|
||||||
|
|||||||
BIN
docs/sop/安心验PC管理后台SOP手册.pdf
Normal file
BIN
docs/sop/安心验PC管理后台SOP手册.pdf
Normal file
Binary file not shown.
BIN
docs/sop/安心验作业端SOP手册-仓管与鉴定师.pdf
Normal file
BIN
docs/sop/安心验作业端SOP手册-仓管与鉴定师.pdf
Normal file
Binary file not shown.
BIN
docs/sop/安心验用户端SOP手册.pdf
Normal file
BIN
docs/sop/安心验用户端SOP手册.pdf
Normal file
Binary file not shown.
@@ -949,8 +949,8 @@ class OrdersController
|
|||||||
if ($serviceProvider === '') {
|
if ($serviceProvider === '') {
|
||||||
return api_error('服务类型不正确', 422);
|
return api_error('服务类型不正确', 422);
|
||||||
}
|
}
|
||||||
if ($categoryId <= 0 || $brandId <= 0 || $productName === '') {
|
if ($categoryId <= 0 || $brandId <= 0) {
|
||||||
return api_error('请完整填写品类、品牌和商品名称', 422);
|
return api_error('请完整填写品类和品牌', 422);
|
||||||
}
|
}
|
||||||
if ($consignee === '' || $mobile === '' || $province === '' || $city === '' || $district === '' || $detailAddress === '') {
|
if ($consignee === '' || $mobile === '' || $province === '' || $city === '' || $district === '' || $detailAddress === '') {
|
||||||
return api_error('请完整填写寄回收件信息', 422);
|
return api_error('请完整填写寄回收件信息', 422);
|
||||||
|
|||||||
@@ -51,6 +51,25 @@ function isPlaceholderApiBase(string $apiBase): bool
|
|||||||
return str_contains($normalized, 'example.com');
|
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;
|
$env = $_ENV;
|
||||||
check(($env['APP_ENV'] ?? '') === 'production', $issues, 'FAIL', 'APP_ENV 非 production', '当前 .env 中 APP_ENV 不是 production。');
|
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 仍然开启。');
|
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';
|
checkClientProductionApiBase($issues, 'admin-web', $projectRoot . '/admin-web/.env.production');
|
||||||
$userProdEnvPath = $projectRoot . '/user-app/.env.production';
|
checkClientProductionApiBase($issues, 'user-app', $projectRoot . '/user-app/.env.production');
|
||||||
$adminProdEnv = @parse_ini_file($adminProdEnvPath);
|
checkClientProductionApiBase($issues, 'work-app', $projectRoot . '/work-app/.env.production');
|
||||||
$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。');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$issues) {
|
if (!$issues) {
|
||||||
echo "RELEASE_AUDIT_OK\n";
|
echo "RELEASE_AUDIT_OK\n";
|
||||||
|
|||||||
@@ -157,8 +157,8 @@ function pickerText(options: Array<{ label?: string; name?: string }>, index: nu
|
|||||||
function validateForm() {
|
function validateForm() {
|
||||||
const product = form.value.product_info;
|
const product = form.value.product_info;
|
||||||
const address = form.value.return_address;
|
const address = form.value.return_address;
|
||||||
if (!product.category_id || !product.brand_id || !product.product_name.trim()) {
|
if (!product.category_id || !product.brand_id) {
|
||||||
showInfoToast("请完整填写品类、品牌和商品名称");
|
showInfoToast("请完整填写品类和品牌");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!address.consignee.trim() || !address.mobile.trim() || !address.province.trim() || !address.city.trim() || !address.district.trim() || !address.detail_address.trim()) {
|
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(() => {
|
|||||||
<picker :range="brandOptions" range-key="name" :value="brandIndex" @change="onBrandChange">
|
<picker :range="brandOptions" range-key="name" :value="brandIndex" @change="onBrandChange">
|
||||||
<view class="field picker-field">{{ pickerText(brandOptions, brandIndex, "选择品牌") }}</view>
|
<view class="field picker-field">{{ pickerText(brandOptions, brandIndex, "选择品牌") }}</view>
|
||||||
</picker>
|
</picker>
|
||||||
<input v-model="form.product_info.product_name" class="field" placeholder="商品名称" />
|
<input v-model="form.product_info.product_name" class="field" placeholder="商品名称,可选" />
|
||||||
<input v-model="form.product_info.color" class="field" placeholder="颜色,可选" />
|
<input v-model="form.product_info.color" class="field" placeholder="颜色,可选" />
|
||||||
<input v-model="form.product_info.size_spec" class="field" placeholder="规格 / 尺寸,可选" />
|
<input v-model="form.product_info.size_spec" class="field" placeholder="规格 / 尺寸,可选" />
|
||||||
<input v-model="form.product_info.serial_no" class="field" placeholder="序列号,可选" />
|
<input v-model="form.product_info.serial_no" class="field" placeholder="序列号,可选" />
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { buildAuthHeaders, clearAdminSession, redirectToLogin } from "./auth";
|
|||||||
import { resolveApiBaseUrl } from "./env";
|
import { resolveApiBaseUrl } from "./env";
|
||||||
|
|
||||||
const BASE_URL = resolveApiBaseUrl().replace(/\/$/, "");
|
const BASE_URL = resolveApiBaseUrl().replace(/\/$/, "");
|
||||||
|
const REQUEST_TIMEOUT_MS = 15000;
|
||||||
|
|
||||||
type RequestMethod = "GET" | "POST" | "PUT" | "DELETE" | "OPTIONS" | "HEAD";
|
type RequestMethod = "GET" | "POST" | "PUT" | "DELETE" | "OPTIONS" | "HEAD";
|
||||||
|
|
||||||
@@ -22,6 +23,25 @@ function buildUrl(url: string, params?: Record<string, string | number | undefin
|
|||||||
return search ? `${BASE_URL}${url}?${search}` : `${BASE_URL}${url}`;
|
return search ? `${BASE_URL}${url}?${search}` : `${BASE_URL}${url}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function buildNetworkError(error: UniApp.GeneralCallbackResult, fallback = "网络请求失败,请稍后重试") {
|
||||||
|
const errMsg = String(error.errMsg || "");
|
||||||
|
const normalized = errMsg.toLowerCase();
|
||||||
|
|
||||||
|
if (normalized.includes("timeout") || errMsg.includes("超时")) {
|
||||||
|
return new Error("连接服务器超时,请检查网络,或联系管理员确认 API 服务是否正常");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (normalized.includes("abort")) {
|
||||||
|
return new Error("请求已取消");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (normalized.includes("fail") || normalized.includes("network") || normalized.includes("request")) {
|
||||||
|
return new Error("无法连接服务器,请检查网络,或联系管理员确认 API 服务是否正常");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Error(errMsg || fallback);
|
||||||
|
}
|
||||||
|
|
||||||
export function request<T>(
|
export function request<T>(
|
||||||
url: string,
|
url: string,
|
||||||
options: {
|
options: {
|
||||||
@@ -42,6 +62,7 @@ export function request<T>(
|
|||||||
method,
|
method,
|
||||||
data: options.data,
|
data: options.data,
|
||||||
header: headers,
|
header: headers,
|
||||||
|
timeout: REQUEST_TIMEOUT_MS,
|
||||||
success: (response: UniApp.RequestSuccessCallbackResult) => {
|
success: (response: UniApp.RequestSuccessCallbackResult) => {
|
||||||
const payload = response.data as ApiResponse<T>;
|
const payload = response.data as ApiResponse<T>;
|
||||||
if (payload?.code === 0) {
|
if (payload?.code === 0) {
|
||||||
@@ -56,7 +77,7 @@ export function request<T>(
|
|||||||
}
|
}
|
||||||
reject(new Error(payload?.message || "请求失败"));
|
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<T>(url: string, filePath: string, formData: Record<st
|
|||||||
reject(error);
|
reject(error);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
fail: (error) => reject(error),
|
fail: (error) => reject(buildNetworkError(error)),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user