Merge branches 'release/test' and 'release/test' of http://8.163.30.128:10082/html/client-web into release/test
This commit is contained in:
@@ -42,14 +42,24 @@ const emit = defineEmits<{
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.first-leg-editor-page { min-width: 0; border: 1px solid #edf0f5; background: #fff; box-shadow: 0 5px 18px rgba(15, 31, 58, .04); }
|
||||
.first-leg-editor-page { min-width: 0; padding-bottom: 72px; border: 1px solid #edf0f5; background: #fff; box-shadow: 0 5px 18px rgba(15, 31, 58, .04); }
|
||||
.editor-page-nav { display: flex; min-height: 52px; align-items: center; justify-content: space-between; gap: 16px; padding: 8px 24px; border-bottom: 1px solid #edf0f5; }
|
||||
.editor-page-nav span { color: var(--muted); font-size: 12px; }
|
||||
.editor-page-body { padding: 26px 32px 34px; }
|
||||
.editor-page-footer { position: sticky; z-index: 3; bottom: 0; display: flex; justify-content: center; padding: 12px 24px; border-top: 1px solid #edf0f5; background: rgba(255, 255, 255, 0.96); box-shadow: 0 -6px 18px rgba(15, 31, 58, .06); backdrop-filter: blur(10px); }
|
||||
.editor-page-footer { position: fixed; z-index: 18; right: 0; bottom: 0; left: 224px; display: flex; min-height: 68px; align-items: center; justify-content: center; padding: 10px 24px; border-top: 1px solid #dfe6ee; background: rgba(255, 255, 255, 0.97); box-shadow: 0 -6px 18px rgba(15, 31, 58, .08); backdrop-filter: blur(10px); }
|
||||
.editor-page-footer :deep(.editor-actions) { width: min(100%, 900px); justify-content: center; }
|
||||
.editor-page-footer :deep(.editor-actions > .el-button) { min-width: 132px; min-height: 42px; }
|
||||
.editor-page-footer :deep(.editor-actions > .el-button:last-child) { min-width: 172px; }
|
||||
.editor-page-footer :deep(.submit-order-button) { position: relative; isolation: isolate; overflow: hidden; border-color: rgba(255, 255, 255, .24); background: linear-gradient(105deg, #08a9bd 0%, #167da2 28%, #2563eb 62%, #4338ca 100%); background-size: 220% 100%; box-shadow: 0 10px 24px rgba(23, 107, 135, .3), 0 0 0 1px rgba(34, 211, 238, .13), 0 0 26px rgba(37, 99, 235, .12); animation: submit-gradient 5s ease-in-out infinite, submit-pulse 2.8s ease-in-out infinite; }
|
||||
.editor-page-footer :deep(.submit-order-button::before) { position: absolute; z-index: -1; top: -80%; bottom: -80%; left: -48%; width: 34%; transform: rotate(18deg); background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .68), transparent); content: ''; animation: submit-shine 3.2s ease-in-out infinite; }
|
||||
.editor-page-footer :deep(.submit-order-button::after) { position: absolute; z-index: -1; inset: 1px; border-radius: 5px; background: linear-gradient(180deg, rgba(255, 255, 255, .13), transparent 48%); content: ''; pointer-events: none; }
|
||||
.editor-page-footer :deep(.submit-order-button:hover) { transform: translateY(-2px) scale(1.025); border-color: rgba(255, 255, 255, .3); background: linear-gradient(105deg, #08b8cb 0%, #167da2 28%, #2563eb 62%, #4338ca 100%); background-size: 220% 100%; box-shadow: 0 15px 30px rgba(23, 107, 135, .35), 0 0 0 1px rgba(34, 211, 238, .25), 0 0 34px rgba(37, 99, 235, .2); }
|
||||
.editor-page-footer :deep(.submit-order-button svg) { position: relative; z-index: 1; filter: drop-shadow(0 2px 4px rgba(0, 0, 0, .18)); animation: submit-plane 2.6s ease-in-out infinite; }
|
||||
@keyframes submit-gradient { 0%, 100% { background-position: 0% 50%; } 50% { background-position: 100% 50%; } }
|
||||
@keyframes submit-pulse { 0%, 100% { filter: saturate(1); } 50% { filter: saturate(1.12) brightness(1.04); } }
|
||||
@keyframes submit-shine { 0%, 52% { left: -48%; opacity: 0; } 62% { opacity: 1; } 86%, 100% { left: 122%; opacity: 0; } }
|
||||
@keyframes submit-plane { 0%, 100% { transform: translate3d(0, 1px, 0) rotate(-3deg); } 50% { transform: translate3d(3px, -2px, 0) rotate(2deg); } }
|
||||
@media (prefers-reduced-motion: reduce) { .editor-page-footer :deep(.submit-order-button), .editor-page-footer :deep(.submit-order-button::before), .editor-page-footer :deep(.submit-order-button svg) { animation: none; } }
|
||||
:global(.first-leg-editor-dialog.el-dialog) { display: flex; max-width: 1500px; height: 94vh; margin-bottom: 0; flex-direction: column; overflow: hidden; border-radius: 6px; }
|
||||
:global(.first-leg-editor-dialog .el-dialog__header) { flex: 0 0 auto; margin-right: 0; padding: 17px 22px; border-bottom: 1px solid var(--border); }
|
||||
:global(.first-leg-editor-dialog .el-dialog__title) { color: var(--navy); font-size: 16px; font-weight: 700; }
|
||||
@@ -58,10 +68,11 @@ const emit = defineEmits<{
|
||||
:global(.first-leg-editor-dialog .el-dialog__footer) { flex: 0 0 auto; padding: 12px 22px; border-top: 1px solid var(--border); background: #fff; }
|
||||
|
||||
@media (max-width: 720px) {
|
||||
.first-leg-editor-page { padding-bottom: 0; }
|
||||
.editor-page-nav { align-items: flex-start; flex-direction: column; gap: 2px; padding: 10px 16px; }
|
||||
.editor-page-nav span { padding-left: 1px; line-height: 1.5; }
|
||||
.editor-page-body { padding: 18px 16px 24px; }
|
||||
.editor-page-footer { padding: 10px 16px; }
|
||||
.editor-page-footer { position: sticky; bottom: 0; left: auto; padding: 10px 16px; }
|
||||
:global(.first-leg-editor-dialog.el-dialog) { width: calc(100vw - 24px) !important; height: 96vh; margin-top: 2vh; }
|
||||
}
|
||||
|
||||
|
||||
@@ -37,5 +37,5 @@ function selectMode(mode: 'standard' | 'quick') {
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.first-leg-create-hub{display:grid;min-width:0;gap:12px}.create-hub-heading{display:grid;gap:5px}.create-hub-heading h1{margin:0;color:var(--navy);font-size:24px;line-height:1.25}.create-hub-heading p{margin:0;color:var(--muted);font-size:13px}.order-mode-switch{display:inline-flex;width:max-content;padding:5px;border:1px solid #dbe4f1;border-radius:12px;background:#fff;box-shadow:0 8px 20px rgba(26,43,75,.06)}.order-mode-switch button{display:inline-flex;height:38px;align-items:center;gap:8px;padding:0 20px;border:0;border-radius:8px;background:transparent;color:#607087;font:inherit;font-size:13px;font-weight:650;cursor:pointer}.order-mode-switch button.active{background:linear-gradient(135deg,#4f73ee,#8a56dc);color:#fff;box-shadow:0 6px 14px rgba(79,115,238,.22)}.order-mode-switch button:focus-visible{outline:2px solid var(--primary);outline-offset:2px}
|
||||
.first-leg-create-hub{display:grid;min-width:0;gap:14px}.create-hub-heading{display:grid;gap:5px}.create-hub-heading h1{margin:0;color:var(--navy);font-size:24px;line-height:1.25}.create-hub-heading p{margin:0;color:var(--muted);font-size:13px}.order-mode-switch{display:inline-flex;width:max-content;padding:4px;border:1px solid #d9e2ec;border-radius:8px;background:#f4f7fa}.order-mode-switch button{display:inline-flex;height:38px;align-items:center;gap:8px;padding:0 20px;border:0;border-radius:6px;background:transparent;color:#607087;font:inherit;font-size:13px;font-weight:650;cursor:pointer}.order-mode-switch button.active{background:var(--primary);color:#fff;box-shadow:0 2px 6px rgba(23,107,135,.2)}.order-mode-switch button:focus-visible{outline:2px solid var(--primary);outline-offset:2px}
|
||||
</style>
|
||||
|
||||
@@ -358,7 +358,8 @@ test('shows a loading state before the list can create an order', () => {
|
||||
test('auto-fills trusted warehouse and company data instead of asking customers to repeat it', () => {
|
||||
assert.match(source, /async function selectDestinationWarehouse\(id: string\)/)
|
||||
assert.match(source, /await store\.loadWarehouseDetail\(warehouse\.id\)/)
|
||||
assert.match(source, /availableWarehouses\.value\.length === 1/)
|
||||
assert.match(source, /warehouse\.code\.toUpperCase\(\)\.includes\('YIWU'\)/)
|
||||
assert.match(source, /warehouse\.name\.includes\('义乌'\)/)
|
||||
assert.match(source, /availableDestinationWarehouses\.value\.length === 1/)
|
||||
assert.match(source, /function createPickupPartySnapshot\(\)/)
|
||||
assert.match(source, /contactName: tenantStore\.company\.contactName/)
|
||||
@@ -422,6 +423,24 @@ test('distills order creation into the confirmed prototype sections with server
|
||||
assert.doesNotMatch(source, /v-model="form\.(?:businessType|origin|destination|priority|tradeTerm)"/)
|
||||
})
|
||||
|
||||
test('matches the prototype two-column create layout and reset action', () => {
|
||||
assert.match(source, /class="order-form-section prototype-section order-basic-section"/)
|
||||
assert.match(source, /<h3>客户下单<\/h3><p>创建新订单<\/p>/)
|
||||
assert.match(source, /\.is-create-route \.prototype-order-form \{[^}]*grid-template-columns: repeat\(2, minmax\(0, 1fr\)\)/)
|
||||
assert.match(source, /\.is-create-route \.cargo-section, \.is-create-route \.cost-estimate-section \{ grid-column: 1 \/ -1; \}/)
|
||||
assert.match(source, /\.is-create-route \.prototype-form-row :deep\(\.el-form-item__label\) \{[^}]*height: 40px[^}]*align-items: center[^}]*justify-content: flex-end/)
|
||||
assert.match(source, /\.is-create-route \.compact-transport-grid > :deep\(\.el-form-item__label\) \{[^}]*align-items: center[^}]*text-align: right/)
|
||||
assert.match(source, /async function resetCreateForm\(\)/)
|
||||
assert.match(source, /确认清空当前填写的订单内容并恢复默认值/)
|
||||
assert.match(source, /v-if="isCreatePage"[^>]*@click="resetCreateForm"[^>]*><RotateCcw[^>]*\/>重置/)
|
||||
assert.match(source, /class="submit-order-button"/)
|
||||
assert.match(editorShellSource, /\.first-leg-editor-page \{[^}]*padding-bottom: 72px/)
|
||||
assert.match(editorShellSource, /\.editor-page-footer \{[^}]*position: fixed[^}]*bottom: 0[^}]*left: 224px/)
|
||||
assert.match(editorShellSource, /submit-gradient 5s ease-in-out infinite/)
|
||||
assert.match(editorShellSource, /submit-shine 3\.2s ease-in-out infinite/)
|
||||
assert.match(editorShellSource, /@media \(prefers-reduced-motion: reduce\)/)
|
||||
})
|
||||
|
||||
test('shows an optional LX inbound order number for one-click dropship orders', () => {
|
||||
assert.match(source, /v-if="form\.fulfillmentType === 'ONE_CLICK_DROPSHIP'" label="LX入库单号" prop="lxCode"/)
|
||||
assert.match(source, /v-model="form\.lxCode"[^>]*placeholder="请输入LX入库单号"/)
|
||||
|
||||
@@ -1262,8 +1262,12 @@ async function loadSelectedWarehouse(id: string | number | boolean | undefined)
|
||||
|
||||
async function autofillWarehouseSelections() {
|
||||
if (!isCreatePage.value || editingId.value) return
|
||||
if (!form.receivingWarehouseId && availableWarehouses.value.length === 1) {
|
||||
form.receivingWarehouseId = availableWarehouses.value[0].id
|
||||
if (!form.receivingWarehouseId) {
|
||||
const yiwuWarehouse = availableWarehouses.value.find((warehouse) => warehouse.code.toUpperCase().includes('YIWU'))
|
||||
?? availableWarehouses.value.find((warehouse) => warehouse.name.includes('义乌'))
|
||||
if (yiwuWarehouse) form.receivingWarehouseId = yiwuWarehouse.id
|
||||
}
|
||||
if (form.receivingWarehouseId) {
|
||||
await loadSelectedWarehouse(form.receivingWarehouseId)
|
||||
}
|
||||
if (form.destinationType !== 'PRIVATE' && !form.destinationWarehouseId && availableDestinationWarehouses.value.length === 1) {
|
||||
@@ -1485,6 +1489,27 @@ function closeEditor() {
|
||||
})
|
||||
}
|
||||
|
||||
async function resetCreateForm() {
|
||||
if (saving.value) return
|
||||
if (editorDirty.value) {
|
||||
try {
|
||||
await ElMessageBox.confirm('确认清空当前填写的订单内容并恢复默认值?', '重置订单', {
|
||||
type: 'warning',
|
||||
confirmButtonText: '确认重置',
|
||||
cancelButtonText: '继续填写',
|
||||
})
|
||||
} catch (error) {
|
||||
if (error === 'cancel' || error === 'close') return
|
||||
throw error
|
||||
}
|
||||
}
|
||||
editingId.value = undefined
|
||||
replaceForm(emptyDraft())
|
||||
await autofillWarehouseSelections()
|
||||
resetEditorValidation()
|
||||
await router.replace({ name: 'first-leg-order-create' })
|
||||
}
|
||||
|
||||
function addCargoItem() {
|
||||
form.items.push(createEmptyCargoItem(`new-cargo-${++cargoSequence}`))
|
||||
resetEditorValidation()
|
||||
@@ -2134,8 +2159,8 @@ async function searchOrders(model: QueryModel) {
|
||||
|
||||
<FirstLegOrderEditorShell v-model="editorOpen" :page="isCreatePage" :title="editingId ? '编辑订单草稿' : (routeCopySourceId ? '复制订单' : '创建订单')" :before-close="requestCloseEditor" @back="closeEditor">
|
||||
<el-form ref="orderFormRef" v-loading="isCreatePage && supportingDataLoading" :model="form" :rules="orderFormRules" label-position="top" class="order-form prototype-order-form" :class="{ 'is-dialog-order-form': !isCreatePage }" scroll-to-error>
|
||||
<section class="order-form-section prototype-section">
|
||||
<div class="order-section-heading"><div><h3>客户下单</h3><p>先选择货物如何送到国内收货仓,并填写本次运输安排。</p></div></div>
|
||||
<section class="order-form-section prototype-section order-basic-section">
|
||||
<div class="order-section-heading"><div><h3>客户下单</h3><p>创建新订单</p></div></div>
|
||||
<div class="prototype-form-flow shipping-form-flow">
|
||||
<el-form-item label="履约类型" prop="fulfillmentType" required class="prototype-form-row prototype-form-row--tabs"><el-radio-group v-model="form.fulfillmentType" class="segmented-options" @change="changeFulfillmentType"><el-radio-button value="STANDARD">普通头程</el-radio-button><el-radio-button value="ONE_CLICK_DROPSHIP">一件代发</el-radio-button></el-radio-group><small v-if="form.fulfillmentType === 'ONE_CLICK_DROPSHIP'" class="field-guidance">测量完成后不办理国内库存入库,将直接推送 PDA 合托。</small></el-form-item>
|
||||
<el-form-item v-if="form.fulfillmentType === 'ONE_CLICK_DROPSHIP'" label="LX入库单号" prop="lxCode" class="prototype-form-row prototype-form-row--wide"><el-input v-model="form.lxCode" maxlength="128" placeholder="请输入LX入库单号" /><small class="field-guidance">用于绑定领星入库单,提交后可在尾程订单、入库单和出库单中查询。</small></el-form-item>
|
||||
@@ -2271,7 +2296,7 @@ async function searchOrders(model: QueryModel) {
|
||||
</div>
|
||||
</section>
|
||||
</el-form>
|
||||
<template #footer><div class="editor-actions"><el-button :disabled="saving" @click="closeEditor">返回</el-button><el-button v-if="editingId ? canEditOrder : canCreateOrder" :loading="saving" @click="saveDraft">保存草稿</el-button><el-button v-if="auth.hasPermission('order:first-leg:submit')" type="primary" :loading="saving" @click="submitOrder"><Send :size="16" />{{ companySubmissionBlocked ? '提交前需完成资料审核' : '提交订单' }}</el-button></div></template>
|
||||
<template #footer><div class="editor-actions"><el-button v-if="isCreatePage" :disabled="saving" @click="resetCreateForm"><RotateCcw :size="16" />重置</el-button><el-button v-else :disabled="saving" @click="closeEditor">返回</el-button><el-button v-if="editingId ? canEditOrder : canCreateOrder" :loading="saving" @click="saveDraft">保存草稿</el-button><el-button v-if="auth.hasPermission('order:first-leg:submit')" class="submit-order-button" type="primary" :loading="saving" @click="submitOrder"><Send :size="17" />{{ companySubmissionBlocked ? '提交前需完成资料审核' : '提交订单' }}</el-button></div></template>
|
||||
</FirstLegOrderEditorShell>
|
||||
|
||||
<el-dialog v-model="batchImportOpen" title="Excel 批量创建订单草稿" width="680px" destroy-on-close append-to-body>
|
||||
@@ -2528,8 +2553,23 @@ async function searchOrders(model: QueryModel) {
|
||||
.is-create-route { gap: 0; }
|
||||
.is-create-route .first-leg-editor-page { width: 100%; }
|
||||
.is-create-route .supporting-data-error, .is-create-route > .el-alert { margin-bottom: 14px; }
|
||||
.is-create-route .prototype-order-form { width: 100%; margin: 0; padding: 0 0 16px; }
|
||||
.is-create-route .prototype-section:not(.cargo-section):not(.cost-estimate-section):not(.destination-section) { width: min(100%, 900px); }
|
||||
.is-create-route .prototype-order-form { display: grid; width: 100%; grid-template-columns: repeat(2, minmax(0, 1fr)); align-items: stretch; gap: 16px; margin: 0; padding: 0 0 16px; }
|
||||
.is-create-route .prototype-section { min-width: 0; margin: 0; padding: 0 24px 24px; border: 1px solid #dfe6ee; border-radius: 8px; background: #fff; }
|
||||
.is-create-route .prototype-section + .prototype-section { margin-top: 0; }
|
||||
.is-create-route .order-basic-section, .is-create-route .destination-section { height: 100%; }
|
||||
.is-create-route .cargo-section, .is-create-route .cost-estimate-section { grid-column: 1 / -1; }
|
||||
.is-create-route .order-section-heading { min-height: 66px; align-items: center; margin: 0 -24px 22px; padding: 15px 24px; border-bottom: 1px solid #e7ecf2; }
|
||||
.is-create-route .order-section-heading h3, .is-create-route .prototype-section:first-child > .order-section-heading h3 { margin: 0; color: var(--navy); font-size: 17px; font-weight: 700; }
|
||||
.is-create-route .order-section-heading p { margin-top: 4px; color: #8a98a8; }
|
||||
.is-create-route .prototype-form-flow, .is-create-route .destination-form-flow { width: 100%; max-width: none; }
|
||||
.is-create-route .prototype-form-row, .is-create-route .prototype-form-row--wide, .is-create-route .prototype-form-row--compact, .is-create-route .prototype-form-row--short, .is-create-route .prototype-form-row--tabs { grid-template-columns: 120px minmax(0, 1fr); }
|
||||
.is-create-route .prototype-form-row :deep(.el-form-item__label) { display: flex; height: 40px; min-height: 40px; align-items: center; justify-content: flex-end; padding: 0 18px 0 0; font-size: 13px; line-height: 1.35; text-align: right; }
|
||||
.is-create-route .segmented-options, .is-create-route .destination-type-options { width: 100%; max-width: 560px; background: #f3f6f9; }
|
||||
.is-create-route .compact-transport-grid { width: 100%; margin-top: 4px; }
|
||||
.is-create-route .compact-transport-grid > :deep(.el-form-item), .is-create-route .compact-transport-grid > :deep(.el-form-item:nth-child(1)), .is-create-route .compact-transport-grid > :deep(.el-form-item:nth-child(6)), .is-create-route .compact-transport-grid > :deep(.el-form-item:nth-child(7)) { grid-template-columns: 120px minmax(0, 1fr); }
|
||||
.is-create-route .compact-transport-grid > :deep(.el-form-item__label) { display: flex; height: 40px; min-height: 40px; align-items: center; justify-content: flex-end; padding: 0 18px 0 0; line-height: 1.35; text-align: right; }
|
||||
.is-create-route .selected-destination { width: auto; margin-left: 138px; }
|
||||
.is-create-route .cargo-table-heading, .is-create-route .cost-estimate-section .order-section-heading { margin-bottom: 16px; }
|
||||
.order-form { width: min(100%, 1000px); margin: 0; padding: 0 0 12px; }
|
||||
.order-form.is-dialog-order-form { width: 100%; max-width: none; }
|
||||
.is-dialog-order-form > .cargo-section, .is-dialog-order-form > .cost-estimate-section { width: 100%; max-width: none; }
|
||||
@@ -2604,6 +2644,7 @@ async function searchOrders(model: QueryModel) {
|
||||
.compact-transport-grid :deep(.el-form-item__label) { color: #4d5a6c; font-size: 13px; }
|
||||
.shipping-form-flow { max-width: 900px; }
|
||||
.prototype-order-form > .prototype-section:first-child { width: 100%; }
|
||||
.is-create-route .prototype-order-form > .prototype-section:first-child > .order-section-heading { margin-top: 0; }
|
||||
.shipping-form-flow .prototype-form-row { margin-bottom: 10px; }
|
||||
.shipping-form-flow .prototype-form-row--tabs { margin-bottom: 12px; }
|
||||
.compact-transport-grid { display: grid; width: 100%; grid-template-columns: 1fr; gap: 0; margin: 6px 0 0; }
|
||||
|
||||
Reference in New Issue
Block a user