chore: release updated anxinyan version
This commit is contained in:
@@ -3,13 +3,15 @@ import { computed, ref } from "vue";
|
||||
import { onLoad } from "@dcloudio/uni-app";
|
||||
import { adminApi, type AdminManualOrderCreatePayload, type AdminManualOrderMeta } from "../../api/admin";
|
||||
import { showErrorToast, showInfoToast, withLoading } from "../../utils/feedback";
|
||||
import { buildRegionPickerState, updateRegionPickerIndexes } from "../../utils/regions";
|
||||
import { recognizeReturnAddress } from "../../utils/address-recognition";
|
||||
import { buildRegionPickerState, findRegionIndexes, updateRegionPickerIndexes } from "../../utils/regions";
|
||||
|
||||
const loading = ref(false);
|
||||
const submitting = ref(false);
|
||||
const meta = ref<AdminManualOrderMeta>({ categories: [], brands: [] });
|
||||
const form = ref<AdminManualOrderCreatePayload>(createForm());
|
||||
const regionPickerIndexes = ref<[number, number, number]>([0, 0, 0]);
|
||||
const addressRecognitionText = ref("");
|
||||
|
||||
const providerOptions = [
|
||||
{ label: "实物鉴定", value: "anxinyan" },
|
||||
@@ -110,6 +112,21 @@ function pickerText(options: Array<{ label?: string; name?: string }>, index: nu
|
||||
return item?.label || item?.name || fallback;
|
||||
}
|
||||
|
||||
function applyRecognizedReturnAddress() {
|
||||
const result = recognizeReturnAddress(addressRecognitionText.value);
|
||||
if (!result.ok || !result.address) {
|
||||
showInfoToast(result.message || "寄回地址识别失败");
|
||||
return;
|
||||
}
|
||||
|
||||
form.value.return_address = {
|
||||
...form.value.return_address,
|
||||
...result.address,
|
||||
};
|
||||
regionPickerIndexes.value = findRegionIndexes(result.address);
|
||||
showInfoToast("寄回地址已识别并填入");
|
||||
}
|
||||
|
||||
function validateForm() {
|
||||
const product = form.value.product_info;
|
||||
const address = form.value.return_address;
|
||||
@@ -173,6 +190,14 @@ onLoad(() => {
|
||||
|
||||
<view class="card stack">
|
||||
<view class="card-title">寄回信息</view>
|
||||
<view class="address-recognition">
|
||||
<textarea
|
||||
v-model="addressRecognitionText"
|
||||
class="textarea address-recognition__textarea"
|
||||
placeholder="粘贴收货人、收货电话、收货地址,自动识别后填入下方字段"
|
||||
/>
|
||||
<button class="btn btn--ghost address-recognition__button" @click="applyRecognizedReturnAddress">识别并填入</button>
|
||||
</view>
|
||||
<input v-model="form.return_address.consignee" class="field" placeholder="收件人" />
|
||||
<input v-model="form.return_address.mobile" class="field" type="number" placeholder="手机号,用于匹配用户" />
|
||||
<picker
|
||||
@@ -216,6 +241,19 @@ onLoad(() => {
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.address-recognition {
|
||||
display: grid;
|
||||
gap: 12rpx;
|
||||
}
|
||||
|
||||
.address-recognition__textarea {
|
||||
min-height: 188rpx;
|
||||
}
|
||||
|
||||
.address-recognition__button {
|
||||
justify-self: stretch;
|
||||
}
|
||||
|
||||
.region-field {
|
||||
justify-content: space-between;
|
||||
gap: 16rpx;
|
||||
|
||||
@@ -48,7 +48,7 @@ const resultMetaItems = computed(() => {
|
||||
for (const point of normalizedKeyPoints(result.key_points)) {
|
||||
items.push({
|
||||
label: point.point_name,
|
||||
value: [point.point_value, point.point_remark].filter(Boolean).join(";") || "-",
|
||||
value: point.point_value || "-",
|
||||
});
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@ function normalizedKeyPoints(value: unknown) {
|
||||
point_remark: textValue(point.point_remark),
|
||||
};
|
||||
})
|
||||
.filter((item) => item.point_value || item.point_remark);
|
||||
.filter((item) => item.point_value);
|
||||
}
|
||||
|
||||
function isImageAsset(item: AdminFileAsset) {
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, ref } from "vue";
|
||||
import { onLoad } from "@dcloudio/uni-app";
|
||||
import { adminApi, type AdminFileAsset, type AdminWarehouseWorkbenchContext } from "../../api/admin";
|
||||
import { adminApi, type AdminExpressCompanyItem, type AdminFileAsset, type AdminWarehouseWorkbenchContext } from "../../api/admin";
|
||||
import { showErrorToast, showInfoToast, withLoading } from "../../utils/feedback";
|
||||
|
||||
const internalTagNo = ref("");
|
||||
const expressCompany = ref("");
|
||||
const trackingNo = ref("");
|
||||
const expressCompanyOptions = ref<AdminExpressCompanyItem[]>([]);
|
||||
const expressCompanyLoading = ref(false);
|
||||
const defaultExpressCompany = ref("");
|
||||
const context = ref<AdminWarehouseWorkbenchContext | null>(null);
|
||||
const loading = ref(false);
|
||||
const submitting = ref(false);
|
||||
@@ -16,6 +19,14 @@ const activeVideo = ref<AdminFileAsset | null>(null);
|
||||
const RETURN_SHIPPED_STORAGE_KEY = "warehouse_return_shipped_context";
|
||||
|
||||
const returnConfirmed = computed(() => Boolean(context.value?.transfer_flow?.return_confirmed_at));
|
||||
const expressCompanyNames = computed(() => {
|
||||
const names = expressCompanyOptions.value.map((item) => item.company_name);
|
||||
if (expressCompany.value && !names.includes(expressCompany.value)) {
|
||||
return [expressCompany.value, ...names];
|
||||
}
|
||||
return names;
|
||||
});
|
||||
const expressCompanyIndex = computed(() => Math.max(0, expressCompanyNames.value.findIndex((item) => item === expressCompany.value)));
|
||||
const canSubmit = computed(() =>
|
||||
returnConfirmed.value &&
|
||||
Boolean(expressCompany.value.trim()) &&
|
||||
@@ -53,6 +64,27 @@ async function fetchContext() {
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchExpressCompanies() {
|
||||
expressCompanyLoading.value = true;
|
||||
try {
|
||||
const response = await adminApi.getExpressCompanies({ enabled_only: 1 });
|
||||
expressCompanyOptions.value = response.list;
|
||||
defaultExpressCompany.value = response.default_company;
|
||||
if (!expressCompany.value) {
|
||||
expressCompany.value = response.default_company || response.list[0]?.company_name || "";
|
||||
}
|
||||
} catch (error) {
|
||||
showErrorToast(error, "快递公司列表加载失败");
|
||||
} finally {
|
||||
expressCompanyLoading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
function onExpressCompanyChange(event: any) {
|
||||
const index = Number(event.detail?.value || 0);
|
||||
expressCompany.value = expressCompanyNames.value[index] || "";
|
||||
}
|
||||
|
||||
function scanTrackingNo() {
|
||||
uni.scanCode({
|
||||
scanType: ["barCode", "qrCode"],
|
||||
@@ -189,6 +221,7 @@ async function submitReturnShipping() {
|
||||
|
||||
onLoad((options) => {
|
||||
internalTagNo.value = readQueryString(options?.internal_tag_no);
|
||||
void fetchExpressCompanies();
|
||||
void fetchContext();
|
||||
});
|
||||
</script>
|
||||
@@ -241,7 +274,13 @@ onLoad((options) => {
|
||||
<view class="card">
|
||||
<view class="card-title">快递单号</view>
|
||||
<view class="card-desc">报告确认后登记回寄物流信息。</view>
|
||||
<input v-model="expressCompany" class="field form-field" placeholder="回寄快递公司,例如:顺丰速运" />
|
||||
<picker :range="expressCompanyNames" :value="expressCompanyIndex" @change="onExpressCompanyChange">
|
||||
<view class="field picker-field form-field">
|
||||
<text v-if="expressCompany" class="picker-field__value">{{ expressCompany }}</text>
|
||||
<text v-else class="picker-field__placeholder">{{ expressCompanyLoading ? "正在加载快递公司" : "请选择回寄快递公司" }}</text>
|
||||
<text class="picker-field__arrow"></text>
|
||||
</view>
|
||||
</picker>
|
||||
<view class="scan-control">
|
||||
<input v-model="trackingNo" class="field scan-input" placeholder="扫描或输入回寄运单号" />
|
||||
<button class="btn scan-button" @click="scanTrackingNo">扫码</button>
|
||||
@@ -305,6 +344,38 @@ onLoad((options) => {
|
||||
margin-top: 18rpx;
|
||||
}
|
||||
|
||||
.picker-field {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 16rpx;
|
||||
}
|
||||
|
||||
.picker-field__value,
|
||||
.picker-field__placeholder {
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.picker-field__value {
|
||||
color: var(--work-text);
|
||||
}
|
||||
|
||||
.picker-field__placeholder {
|
||||
color: var(--work-text-muted);
|
||||
}
|
||||
|
||||
.picker-field__arrow {
|
||||
width: 14rpx;
|
||||
height: 14rpx;
|
||||
flex: 0 0 14rpx;
|
||||
border-right: 3rpx solid var(--work-text-soft);
|
||||
border-bottom: 3rpx solid var(--work-text-soft);
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
.scan-control {
|
||||
display: flex;
|
||||
gap: 14rpx;
|
||||
|
||||
@@ -269,7 +269,7 @@ function templateKeyPointsPayload() {
|
||||
point_code: item.point_code,
|
||||
point_name: item.point_name,
|
||||
point_value: item.point_value || "",
|
||||
point_remark: item.point_remark || "",
|
||||
point_remark: "",
|
||||
})) || [];
|
||||
}
|
||||
|
||||
@@ -787,13 +787,6 @@ onShow(() => {
|
||||
:placeholder="`${item.point_name} 值`"
|
||||
@input="updateTemplatePointFromInput(index, 'point_value', $event)"
|
||||
/>
|
||||
<textarea
|
||||
:value="item.point_remark"
|
||||
class="textarea"
|
||||
:disabled="isTaskReadonly"
|
||||
:placeholder="`${item.point_name} 说明`"
|
||||
@input="updateTemplatePointFromInput(index, 'point_remark', $event)"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -888,13 +881,6 @@ onShow(() => {
|
||||
:placeholder="`${item.point_name} 值`"
|
||||
@input="updateTemplatePointFromInput(index, 'point_value', $event)"
|
||||
/>
|
||||
<textarea
|
||||
:value="item.point_remark"
|
||||
class="textarea"
|
||||
:disabled="isTaskReadonly"
|
||||
:placeholder="`${item.point_name} 说明`"
|
||||
@input="updateTemplatePointFromInput(index, 'point_remark', $event)"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user