| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012 |
- <template>
- <div class="express-order-page">
- <!-- 寄件人和收件人在同一行 -->
- <div class="form-row">
- <!-- 寄件人 -->
- <div class="form-card">
- <div class="card-header send">
- <span class="header-title"><img src="../../../assets/images/icon-send.png"/>寄件人</span>
- <div class="header-actions">
- <el-button
- type="primary"
- link
- @click="openAddressBook('sender')"
- class="action-btn"
- >
- <img src="../../../assets/images/create-order-address.png"/>地址簿
- </el-button>
- </div>
- </div>
- <div class="form-content">
- <!-- 智能识别区域(寄件人) -->
- <div class="recognition-area">
- <div class="recognition-tip">识别后,请检查拆分地址信息是否准确,如有遗漏请及时补充</div>
- <el-input
- type="textarea"
- v-model="senderRecognitionText"
- placeholder="请输入文本,自动识别姓名、电话和地址"
- :rows="3"
- maxlength="250"
- show-word-limit
- class="recognition-textarea"
- />
- <div class="recognition-actions">
- <el-button
- type="primary"
- @click="handleRecognition('sender', 1)"
- v-if="!senderRecognitionText"
- class="recognition-btn"
- >粘贴并识别</el-button>
- <el-button
- type="primary"
- @click="handleRecognition('sender', 2)"
- v-else
- class="recognition-btn"
- >识别</el-button>
- </div>
- </div>
- <el-form
- label-position="left"
- :model="sender"
- :rules="senderRules"
- ref="senderForm"
- label-width="120px"
- class="sender-form"
- >
- <el-form-item label="姓名:" prop="contactName" required>
- <el-input
- v-model="sender.contactName"
- placeholder="请输入真实姓名"
- size="large"
- clearable
- class="fixed-input"
- maxlength="20"
- show-word-limit
- @input="handleSenderChange"
- />
- </el-form-item>
- <el-form-item label="电话:" prop="contactPhone" required>
- <el-input
- v-model="sender.contactPhone"
- placeholder="请输入电话号码"
- size="large"
- clearable
- class="fixed-input"
- maxlength="11"
- @input="handleSenderChange"
- />
- </el-form-item>
- <el-form-item label="省市区:" prop="region" required>
- <RegionCascader
- v-model="sender.region"
- placeholder="请选择省市区"
- size="large"
- :clearable="true"
- class="fixed-input"
- @change="handleSenderRegionChange"
- />
- </el-form-item>
- <el-form-item label="详细地址:" prop="detailedAddress" required>
- <el-input
- v-model="sender.detailedAddress"
- placeholder="请输入详细地址"
- size="large"
- clearable
- class="fixed-input"
- maxlength="100"
- show-word-limit
- @input="handleSenderChange"
- />
- </el-form-item>
- <div class="default-address-footer">
- <!-- 默认地址相关已注释,保留原样 -->
- </div>
- </el-form>
- </div>
- </div>
- <!-- 收件人 -->
- <div class="form-card">
- <div class="card-header receive">
- <span class="header-title"><img src="../../../assets/images/icon-receive.png"/>收件人</span>
- <div class="header-actions">
- <el-button
- type="primary"
- link
- @click="openAddressBook('receiver')"
- class="action-btn"
- >
- <img src="../../../assets/images/create-order-address.png"/>地址簿
- </el-button>
- </div>
- </div>
- <div class="form-content">
- <!-- 智能识别区域(收件人) -->
- <div class="recognition-area">
- <div class="recognition-tip">识别后,请检查拆分地址信息是否准确,如有遗漏请及时补充</div>
- <el-input
- type="textarea"
- v-model="receiverRecognitionText"
- placeholder="请输入文本,自动识别姓名、电话和地址"
- :rows="3"
- maxlength="250"
- show-word-limit
- class="recognition-textarea"
- />
- <div class="recognition-actions">
- <el-button
- type="primary"
- @click="handleRecognition('receiver', 1)"
- v-if="!receiverRecognitionText"
- class="recognition-btn"
- >粘贴并识别</el-button>
- <el-button
- type="primary"
- @click="handleRecognition('receiver', 2)"
- v-else
- class="recognition-btn"
- >识别</el-button>
- </div>
- </div>
- <el-form
- label-position="left"
- :model="receiver"
- :rules="receiverRules"
- ref="receiverForm"
- label-width="120px"
- class="receiver-form"
- >
- <el-form-item label="姓名:" prop="contactName" required>
- <el-input
- v-model="receiver.contactName"
- placeholder="请输入真实姓名"
- size="large"
- clearable
- class="fixed-input"
- maxlength="20"
- show-word-limit
- @input="handleReceiverChange"
- />
- </el-form-item>
- <el-form-item label="电话:" prop="contactPhone" required>
- <el-input
- v-model="receiver.contactPhone"
- placeholder="请输入电话号码"
- size="large"
- clearable
- class="fixed-input"
- maxlength="11"
- @input="handleReceiverChange"
- />
- </el-form-item>
- <el-form-item label="省市区:" prop="region" required>
- <RegionCascader
- v-model="receiver.region"
- placeholder="请选择省市区"
- size="large"
- :clearable="true"
- class="fixed-input"
- @change="handleReceiverRegionChange"
- />
- </el-form-item>
- <el-form-item label="详细地址:" prop="detailedAddress" required>
- <el-input
- v-model="receiver.detailedAddress"
- placeholder="请输入详细地址"
- size="large"
- clearable
- class="fixed-input"
- maxlength="100"
- show-word-limit
- @input="handleReceiverChange"
- />
- </el-form-item>
- </el-form>
- </div>
- </div>
- </div>
- <!-- 寄件方式 -->
- <div class="form-card full-width">
- <div class="card-header with-blue-line">
- <div class="blue-line"></div>
- <span class="header-title">寄件方式</span>
- </div>
- <div class="form-content">
- <div class="delivery-option">
- <div class="option-item">
- <div class="btn-radio">
- <el-radio v-model="deliveryMethod" label="pickup" size="large">
- 上门取件
- </el-radio>
- </div>
- <el-form
- label-position="left"
- :model="deliveryForm"
- :rules="deliveryRules"
- ref="deliveryFormRef"
- label-width="120px"
- class="delivery-form"
- >
- <div class="item-info-grid-3">
- <el-form-item label="上门时间:" prop="pickupTime" required>
- <PickupTimeCascader
- v-model="deliveryForm.pickupTime"
- placeholder="请选择上门时间"
- :clearable="true"
- class="fixed-input pickup-time-select"
- @change="handlePickupTimeChange"
- />
- </el-form-item>
- <el-form-item label="快递类型:" prop="expressType" required class="fixed-input">
- <el-select
- v-model="deliveryForm.expressType"
- placeholder="请选择快递类型"
- size="large"
- class="fixed-input"
- >
- <el-option
- v-if="productType == '1'"
- v-for="dict in jd_logistics_product_code"
- :key="dict.value"
- :label="dict.label"
- :value="dict.value"
- ></el-option>
- <el-option
- v-if="productType == '2'"
- v-for="dict in sf_logistics_product_code"
- :key="dict.value"
- :label="dict.label"
- :value="dict.value"
- ></el-option>
- </el-select>
- </el-form-item>
- </div>
- </el-form>
- </div>
- </div>
- </div>
- </div>
- <!-- 物品信息 -->
- <div class="form-card full-width">
- <div class="card-header with-blue-line">
- <div class="blue-line"></div>
- <span class="header-title">物品信息</span>
- </div>
- <div class="form-content">
- <el-form
- label-position="left"
- :model="itemInfo"
- :rules="itemInfoRules"
- ref="itemInfoForm"
- label-width="120px"
- class="item-info-form"
- >
- <div class="item-info-grid-1">
- <el-form-item label="物品类型:" prop="type" required>
- <el-input
- v-model="itemInfo.type"
- placeholder="请输入物品类型"
- size="large"
- clearable
- class="fixed-input"
- maxlength="50"
- show-word-limit
- />
- </el-form-item>
- </div>
- <div class="item-info-grid-3">
- <el-form-item label="总重量 (kg):" prop="weight" required>
- <el-input-number
- v-model="itemInfo.weight"
- :min="0.1"
- :max="1000"
- :step="0.1"
- size="large"
- controls-position="right"
- class="fixed-input"
- />
- </el-form-item>
- <el-form-item label="总体积 (m³):" prop="volume" required>
- <el-input-number
- v-model="itemInfo.volume"
- :min="0.001"
- :max="100"
- :step="0.001"
- size="large"
- controls-position="right"
- class="fixed-input"
- />
- </el-form-item>
- <el-form-item label="总件数 (件):" prop="quantity" required>
- <el-input-number
- v-model="itemInfo.quantity"
- :min="1"
- :max="999"
- :step="1"
- size="large"
- controls-position="right"
- class="fixed-input"
- />
- </el-form-item>
- </div>
- </el-form>
- </div>
- </div>
- <!-- 增值服务 -->
- <!-- 增值服务:-->
- <!-- 包装:isPack-->
- <!-- 保价:guaranteeMoney-->
- <!-- 超长超重:isOverLongWeight-->
- <!-- 签单返还:isReceiptCollect-->
- <!-- 打木架:isWoodenCrate-->
- <!-- 京东 包装 保价 签单反 保价有的话传值 没有的话传 空 签单反 没筛选了-->
- <div class="form-card full-width">
- <div class="card-header with-blue-line">
- <div class="blue-line"></div>
- <span class="header-title">增值服务</span>
- </div>
- <div class="form-content">
- <div class="value-services-grid">
- <div class="service-item" v-if="productType == '1'">
- <span class="service-label">包装服务</span>
- <el-switch
- v-model="valueServices.packaging"
- size="large"
- active-color="#1890ff"
- />
- </div>
- <div class="service-item" v-if="productType == '1' || productType == '2'">
- <span class="service-label">保价</span>
- <div class="insurance-wrapper">
- <el-switch
- v-model="valueServices.insurance"
- size="large"
- active-color="#1890ff"
- @change="handleInsuranceChange"
- />
- <div class="insurance-input-wrapper" v-if="valueServices.insurance">
- <el-input
- v-model="insuranceAmount"
- placeholder="请输入保价金额"
- size="large"
- class="insurance-input fixed-input"
- @input="validateInsuranceAmount"
- maxlength="10"
- >
- <template #append>元</template>
- </el-input>
- <div v-if="insuranceAmountError" class="error-message">
- {{ insuranceAmountError }}
- </div>
- </div>
- </div>
- </div>
- <!-- <div class="service-item">-->
- <!-- <span class="service-label">超长超重</span>-->
- <!-- <el-switch-->
- <!-- v-model="valueServices.overweight"-->
- <!-- size="large"-->
- <!-- active-color="#1890ff"-->
- <!-- />-->
- <!-- </div>-->
- <div class="service-item" v-if="productType == '1'">
- <span class="service-label">签单返还</span>
- <div class="sign-return-wrapper">
- <el-switch
- v-model="valueServices.signReturn"
- size="large"
- active-color="#1890ff"
- @change="handleSignReturnChange"
- />
- <div class="sign-return-select-wrapper fixed-input" v-if="valueServices.signReturn && productType == '2'">
- <el-select
- v-model="signReturnType"
- placeholder="请选择凭证类型"
- size="large"
- class="fixed-input sign-return-select"
- >
- <el-option
- v-for="option in signReturnOptions"
- :key="option.value"
- :label="option.label"
- :value="option.value"
- />
- </el-select>
- <div v-if="signReturnTypeError" class="error-message">
- {{ signReturnTypeError }}
- </div>
- </div>
- </div>
- </div>
- <!-- <div class="service-item" v-if="productType == '2'">-->
- <!-- <span class="service-label">打木架</span>-->
- <!-- <el-switch-->
- <!-- v-model="valueServices.woodenFrame"-->
- <!-- size="large"-->
- <!-- active-color="#1890ff"-->
- <!-- />-->
- <!-- </div>-->
- </div>
- </div>
- </div>
- <!-- 提交订单 -->
- <div class="form-card full-width">
- <div class="card-header with-blue-line">
- <div class="blue-line"></div>
- <span class="header-title">提交订单</span>
- </div>
- <div class="agreement">
- <div class="price-notice">
- 实际费用以快递员核实为准
- </div>
- <!-- <el-checkbox v-model="agreed" size="large">-->
- <!-- 我已理解并同意遵守《快件服务协议》-->
- <!-- </el-checkbox>-->
- </div>
- <el-button
- type="primary"
- size="large"
- :disabled="!agreed"
- @click="submitOrder"
- class="submit-button"
- >
- 提交订单
- </el-button>
- </div>
- <!-- 地址簿弹窗组件 -->
- <AddressBookDialog
- v-model:visible="addressBookVisible"
- :address-book-type="addressBookType"
- @confirm="applyAddress"
- @cancel="closeAddressBook"
- @close="closeAddressBook"
- />
- </div>
- </template>
- <script setup>
- import { ref, reactive, computed, onMounted, watch } from 'vue'
- import { ElMessage } from 'element-plus'
- import RegionCascader from '@/components/RegionCascader.vue'
- // 导入地址簿弹窗组件
- import AddressBookDialog from './components/AddressBookDialog.vue'
- import PickupTimeCascader from './components/PickupTimeCascader.vue'
- // 导入本地 JSON 数据
- import { areaData,getCodesByNames } from '@/utils/area-data.js'
- import { addBook } from "@/api/logistics/book"
- import { addOrder } from "@/api/logistics/order"
- const { proxy } = getCurrentInstance()
- const { jd_logistics_product_code, sf_logistics_product_code } = proxy.useDict("jd_logistics_product_code", "sf_logistics_product_code")
- import { useRoute } from 'vue-router';
- import {updateBook,getDefaultAddress,getAddressInfo} from "../../../api/logistics/book.js";
- const route = useRoute();
- const productType = ref('1') //1表示京东 2表示顺丰
- // 寄件人信息
- const sender = reactive({
- addressId:'',
- contactName: '',
- contactPhone: '',
- provinceName: '',
- cityName: '',
- countyName: '',
- detailedAddress: '',
- region: [], // 用于绑定RegionCascader组件
- defaultFlag: '0' //是否默认 0非默认 1默认
- })
- // 收件人信息
- const receiver = reactive({
- addressId:'',
- contactName: '',
- contactPhone: '',
- provinceName: '',
- cityName: '',
- countyName: '',
- detailedAddress: '',
- region: [],
- defaultFlag: '0'
- })
- // 寄件方式
- const deliveryMethod = ref('pickup')
- // 寄件方式表单(用于验证)
- const deliveryForm = reactive({
- pickupTime: [],
- expressType: '',
- pickupStartTime: '', // 新增:上门开始时间
- pickupEndTime: '' // 新增:上门结束时间
- })
- // 寄件方式验证规则(针对PickupTimeCascader组件)
- const deliveryRules = {
- pickupTime: [
- {
- required: true,
- validator: (rule, value, callback) => {
- if (!value || value.length === 0) {
- callback(new Error('请选择上门时间'))
- } else {
- // 验证时间格式是否正确(假设PickupTimeCascader返回数组)
- if (Array.isArray(value) && value.length >= 2) {
- callback()
- } else {
- callback(new Error('请选择完整的上门时间'))
- }
- }
- },
- trigger: 'change'
- }
- ],
- expressType: [
- { required: true, message: '请选择快递类型', trigger: 'change' }
- ]
- }
- // 寄件方式表单引用
- const deliveryFormRef = ref(null)
- // 物品信息
- const itemInfo = reactive({
- type: '',
- weight: 1,
- volume: 0.001,
- quantity: 1
- })
- // 增值服务
- const valueServices = reactive({
- packaging: false,
- insurance: false,
- overweight: false,
- signReturn: false,
- woodenFrame: false
- })
- // 保价金额
- const insuranceAmount = ref('')
- const insuranceAmountError = ref('')
- // 签单返还类型
- const signReturnType = ref('')
- const signReturnTypeError = ref('')
- const signReturnOptions = ref([
- { label: '电子凭证', value: 'electronic' },
- { label: '纸质凭证', value: 'paper' }
- ])
- // 协议同意
- const agreed = ref(true)
- // 表单验证规则(已添加长度限制)
- const senderRules = {
- contactName: [
- { required: true, message: '请输入寄件人姓名', trigger: 'blur' },
- { min: 1, max: 20, message: '姓名长度在1-20个字符之间', trigger: 'blur' }
- ],
- contactPhone: [
- { required: true, message: '请输入寄件人电话', trigger: 'blur' },
- { pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号码', trigger: 'blur' }
- ],
- region: [
- {
- required: true,
- validator: (rule, value, callback) => {
- if (!value || value.length === 0) {
- callback(new Error('请选择省市区'))
- } else {
- callback()
- }
- },
- trigger: 'change'
- }
- ],
- detailedAddress: [
- { required: true, message: '请输入详细地址', trigger: 'blur' },
- { min: 3, max: 100, message: '地址长度在3-100个字符之间', trigger: 'blur' }
- ]
- }
- const receiverRules = {
- contactName: [
- { required: true, message: '请输入收件人姓名', trigger: 'blur' },
- { min: 1, max: 20, message: '姓名长度在1-20个字符之间', trigger: 'blur' }
- ],
- contactPhone: [
- { required: true, message: '请输入收件人电话', trigger: 'blur' },
- { pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号码', trigger: 'blur' }
- ],
- region: [
- {
- required: true,
- validator: (rule, value, callback) => {
- if (!value || value.length === 0) {
- callback(new Error('请选择省市区'))
- } else {
- callback()
- }
- },
- trigger: 'change'
- }
- ],
- detailedAddress: [
- { required: true, message: '请输入详细地址', trigger: 'blur' },
- // { min: 3, max: 100, message: '地址长度在3-100个字符之间', trigger: 'blur' }
- ]
- }
- // 物品信息验证规则(已添加长度限制)
- const itemInfoRules = {
- type: [
- { required: true, message: '请输入物品类型', trigger: 'blur' },
- { min: 1, max: 50, message: '物品类型长度在1-50个字符之间', trigger: 'blur' }
- ],
- weight: [
- { required: true, message: '请输入总重量', trigger: 'blur' },
- {
- validator: (rule, value, callback) => {
- if (value <= 0) {
- callback(new Error('重量必须大于0'))
- }
- // else if (value > 1000) {
- // callback(new Error('重量不能超过1000kg'))
- // }
- else {
- callback()
- }
- },
- trigger: 'blur'
- }
- ],
- volume: [
- { required: true, message: '请输入总体积', trigger: 'blur' },
- {
- validator: (rule, value, callback) => {
- if (value <= 0) {
- callback(new Error('体积必须大于0'))
- }
- // else if (value > 100) {
- // callback(new Error('体积不能超过100m³'))
- // }
- else {
- callback()
- }
- },
- trigger: 'blur'
- }
- ],
- quantity: [
- { required: true, message: '请输入总件数', trigger: 'blur' },
- {
- validator: (rule, value, callback) => {
- if (value <= 0) {
- callback(new Error('件数必须大于0'))
- }
- // else if (value > 999) {
- // callback(new Error('件数不能超过999件'))
- // }
- else {
- callback()
- }
- },
- trigger: 'blur'
- }
- ]
- }
- // 表单引用
- const senderForm = ref(null)
- const receiverForm = ref(null)
- const itemInfoForm = ref(null)
- // 地址簿弹窗相关(迁移到组件)
- const addressBookVisible = ref(false)
- const addressBookType = ref('sender')
- // 存储原始地址信息(用于判断是否修改)
- const senderOriginalAddress = ref(null)
- const receiverOriginalAddress = ref(null)
- // 监听快递类型变化
- watch(() => deliveryForm.expressType, (newVal) => {
- // 快递类型变化时清空可能的错误状态
- if (newVal && deliveryFormRef.value) {
- // 清除快递类型的验证错误
- deliveryFormRef.value.clearValidate(['expressType'])
- }
- })
- // 监听上门时间变化
- watch(() => deliveryForm.pickupTime, (newVal) => {
- // 上门时间变化时清空可能的错误状态
- if (newVal && newVal.length > 0 && deliveryFormRef.value) {
- // 清除上门时间的验证错误
- deliveryFormRef.value.clearValidate(['pickupTime'])
- }
- })
- // 监听签单返还开关变化
- watch(() => valueServices.signReturn, (newVal) => {
- if (!newVal) {
- signReturnType.value = ''
- signReturnTypeError.value = ''
- }
- })
- // 监听保价金额变化
- watch(insuranceAmount, () => {
- validateInsuranceAmount()
- })
- // 监听签单返还类型变化
- watch(signReturnType, (newVal) => {
- if (newVal) {
- signReturnTypeError.value = ''
- }
- })
- // ==================== 新增智能识别相关 ====================
- const senderRecognitionText = ref('')
- const receiverRecognitionText = ref('')
- const recognitionLoading = ref(false)
- // 处理识别
- const handleRecognition = async (type, actionType) => {
- let text = ''
- if (actionType === 1) {
- // 粘贴并识别:读取剪贴板
- try {
- const clipboardText = await navigator.clipboard.readText()
- if (!clipboardText) {
- ElMessage.warning('剪贴板内容为空')
- return
- }
- if (type === 'sender') {
- senderRecognitionText.value = clipboardText
- text = clipboardText
- } else {
- receiverRecognitionText.value = clipboardText
- text = clipboardText
- }
- } catch (err) {
- ElMessage.error('读取剪贴板失败,请手动粘贴')
- return
- }
- } else {
- // 直接识别:使用当前文本域内容
- text = type === 'sender' ? senderRecognitionText.value : receiverRecognitionText.value
- }
- if (!text.trim()) {
- ElMessage.warning('请输入要识别的文本')
- return
- }
- recognitionLoading.value = true
- try {
- const params = { param: text }
- const res = await getAddressInfo(params)
- if (res.code === 200 && res.data?.result?.length > 0) {
- const result = res.data.result[0]
- const target = type === 'sender' ? sender : receiver
- // 清空原有 addressId,视为新地址
- target.addressId = ''
- // 姓名
- target.contactName = result.name || ''
- // 电话(取第一个)
- if (result.mobile && result.mobile.length > 0) {
- target.contactPhone = result.mobile[0]
- }
- // 省市区
- if (result.xzq) {
- let province = '', city = '', district = ''
- if (result.xzq.fullName) {
- const parts = result.xzq.fullName.split(',').map(s => s.trim())
- province = parts[0] || ''
- city = parts[1] || ''
- district = parts[2] || ''
- } else {
- province = result.xzq.province || ''
- city = result.xzq.city || ''
- district = result.xzq.district || ''
- }
- target.provinceName = province
- target.cityName = city
- target.countyName = district
- // 获取省市区代码并设置 region(用于 RegionCascader 回显)
- const codes = getCodesByNames(province, city, district)
- target.region = codes
- // 详细地址
- if (result.xzq.subArea) {
- target.detailedAddress = result.xzq.subArea
- } else if (result.address) {
- const fullAddr = result.address
- const prefix = province + city + district
- target.detailedAddress = fullAddr.startsWith(prefix) ? fullAddr.substring(prefix.length) : fullAddr
- }
- }
- // 清空对应识别文本域(可选)
- if (type === 'sender') {
- senderRecognitionText.value = ''
- } else {
- receiverRecognitionText.value = ''
- }
- ElMessage.success('识别成功,请核对信息')
- } else {
- ElMessage.error(res.message || '识别失败')
- }
- } catch (error) {
- console.error('识别错误', error)
- ElMessage.error('识别失败,请重试')
- } finally {
- recognitionLoading.value = false
- }
- }
- // ==================== 新增代码结束 ====================
- // 处理寄件人地区变化
- const handleSenderRegionChange = (regionInfo) => {
- console.log('寄件人地区信息:', regionInfo)
- // 同时更新省份、城市、区县名称
- sender.provinceName = regionInfo.provinceName || ''
- sender.cityName = regionInfo.cityName || ''
- sender.countyName = regionInfo.districtName || ''
- sender.region = [regionInfo.provinceCode,regionInfo.cityCode,regionInfo.districtCode]
- // 如果是从地址簿选择的地址,修改后清空addressId
- if (sender.addressId) {
- sender.addressId = ''
- }
- }
- // 处理收件人地区变化
- const handleReceiverRegionChange = (regionInfo) => {
- console.log('收件人地区信息:', regionInfo)
- receiver.provinceName = regionInfo.provinceName || ''
- receiver.cityName = regionInfo.cityName || ''
- receiver.countyName = regionInfo.districtName || ''
- receiver.region = [regionInfo.provinceCode,regionInfo.cityCode,regionInfo.districtCode]
- // 如果是从地址簿选择的地址,修改后清空addressId
- if (receiver.addressId) {
- receiver.addressId = ''
- }
- }
- // 处理上门时间变化
- const handlePickupTimeChange = (value) => {
- console.log('上门时间选择:', value)
- // 当用户选择上门时间后,清除验证错误
- if (value && deliveryFormRef.value) {
- deliveryFormRef.value.clearValidate(['pickupTime'])
- }
- let formattedPickupStartTime = ''
- let formattedPickupEndTime = ''
- if (Array.isArray(deliveryForm.pickupTime) && deliveryForm.pickupTime.length > 0) {
- // 假设PickupTimeCascader返回的数组结构为 [日期, 时间段]
- const timeArr = deliveryForm.pickupTime[1].split('-')
- console.log('deliveryForm.pickupTime===',deliveryForm.pickupTime)
- console.log('timeArr===',timeArr)
- console.log('deliveryForm.pickupTime[0] + timeArr[0]===',deliveryForm.pickupTime[0] + ' ' + timeArr[0])
- formattedPickupStartTime = deliveryForm.pickupTime[0] + ' ' + timeArr[0] + ":00"
- formattedPickupEndTime = deliveryForm.pickupTime[0] + ' ' + timeArr[1] + ":00"
- console.log('formattedPickupStartTime===',formattedPickupStartTime)
- console.log('formattedPickupEndTime===',formattedPickupEndTime)
- }
- }
- // 处理寄件人表单变化
- const handleSenderChange = () => {
- // 如果是从地址簿选择的地址,修改后清空addressId
- if (sender.addressId) {
- sender.addressId = ''
- }
- }
- // 处理收件人表单变化
- const handleReceiverChange = () => {
- // 如果是从地址簿选择的地址,修改后清空addressId
- if (receiver.addressId) {
- receiver.addressId = ''
- }
- }
- // 方法:打开地址簿
- const openAddressBook = (type) => {
- addressBookType.value = type
- addressBookVisible.value = true
- }
- // 方法:关闭地址簿
- const closeAddressBook = () => {
- addressBookVisible.value = false
- }
- // 方法:应用选择的地址(修改:清空验证错误)
- const applyAddress = (address) => {
- if (address) {
- if (addressBookType.value === 'sender') {
- sender.addressId = address.addressId || ''
- sender.contactName = address.contactName || ''
- sender.contactPhone = address.contactPhone || ''
- sender.provinceName = address.provinceName
- sender.cityName = address.cityName
- sender.countyName = address.countyName
- sender.detailedAddress = address.detailedAddress || ''
- sender.defaultFlag = address.defaultFlag || '0'
- sender.region = getCodesByNames(sender.provinceName,sender.cityName,sender.countyName)
- console.log('region===========', sender.region)
- // 保存原始地址信息(用于判断是否修改)
- senderOriginalAddress.value = {
- contactName: address.contactName || '',
- contactPhone: address.contactPhone || '',
- provinceName: address.provinceName || '',
- cityName: address.cityName || '',
- countyName: address.countyName || '',
- detailedAddress: address.detailedAddress || '',
- defaultFlag: address.defaultFlag || '0'
- }
- // 清空寄件人表单的验证错误
- if (senderForm.value) {
- senderForm.value.clearValidate()
- }
- } else {
- receiver.addressId = address.addressId || ''
- receiver.contactName = address.contactName || ''
- receiver.contactPhone = address.contactPhone || ''
- receiver.provinceName = address.provinceName
- receiver.cityName = address.cityName
- receiver.countyName = address.countyName
- receiver.detailedAddress = address.detailedAddress || ''
- receiver.defaultFlag = address.defaultFlag || '0'
- receiver.region = getCodesByNames(receiver.provinceName,receiver.cityName,receiver.countyName)
- console.log('region===========', receiver.region)
- // 保存原始地址信息(用于判断是否修改)
- receiverOriginalAddress.value = {
- contactName: address.contactName || '',
- contactPhone: address.contactPhone || '',
- provinceName: address.provinceName || '',
- cityName: address.cityName || '',
- countyName: address.countyName || '',
- detailedAddress: address.detailedAddress || '',
- defaultFlag: address.defaultFlag || '0'
- }
- // 清空收件人表单的验证错误
- if (receiverForm.value) {
- receiverForm.value.clearValidate()
- }
- }
- // ElMessage.success('已应用选择的地址')
- } else {
- // ElMessage.warning('请先选择一个地址')
- }
- }
- // 方法:加入地址簿
- const addToAddressBook = async (type) => {
- let formRef = null
- let formData = null
- let regionInfo = null
- if (type === 'sender') {
- formRef = senderForm.value
- formData = sender
- } else {
- formRef = receiverForm.value
- formData = receiver
- }
- if (!formRef) return
- const valid = await formRef.validate().catch(() => false)
- if (!valid) {
- ElMessage.warning('请先填写完整的地址信息')
- return
- }
- if (!formData.region || formData.region.length === 0) {
- ElMessage.warning('请选择省市区')
- return
- }
- const addressData = {
- addressId: formData.addressId || '', // 如果有addressId则传递,为空则新增
- contactName: formData.contactName,
- contactPhone: formData.contactPhone,
- detailedAddress: formData.detailedAddress,
- provinceName: formData.provinceName || '',
- cityName: formData.cityName || '',
- countyName: formData.countyName || '',
- defaultFlag: type === 'sender' ? formData.defaultFlag : '0',
- tag: 'custom',
- }
- try {
- // 如果是新增,更新addressId
- let response = {}
- if (formData.addressId) {
- response = await updateBook(addressData)
- }else {
- response = await addBook(addressData)
- }
- if (response.code === 200) {
- ElMessage.success('地址保存成功')
- } else {
- ElMessage.error(response.msg || '地址保存失败')
- }
- } catch (error) {
- console.error('保存地址失败:', error)
- ElMessage.error('地址保存失败')
- }
- }
- // 方法:处理保价开关变化
- const handleInsuranceChange = (value) => {
- if (!value) {
- insuranceAmount.value = ''
- insuranceAmountError.value = ''
- }
- }
- // 方法:验证保价金额
- const validateInsuranceAmount = () => {
- if (valueServices.insurance && insuranceAmount.value) {
- const amount = parseFloat(insuranceAmount.value)
- // 检查是否为数字
- if (isNaN(amount) || amount <= 0) {
- insuranceAmountError.value = '保价金额必须大于0且为数字'
- return false
- }
- // 检查是否超过最大值
- if (amount > 1000000) {
- insuranceAmountError.value = '保价金额不能超过100万'
- return false
- }
- // 检查小数位数
- const decimalPart = insuranceAmount.value.toString().split('.')[1]
- if (decimalPart && decimalPart.length > 2) {
- insuranceAmountError.value = '保价金额最多保留两位小数'
- return false
- }
- insuranceAmountError.value = ''
- return true
- } else if (valueServices.insurance && !insuranceAmount.value) {
- insuranceAmountError.value = '请填写保价金额'
- return false
- } else {
- insuranceAmountError.value = ''
- return true
- }
- }
- // 方法:处理签单返还开关变化
- const handleSignReturnChange = (value) => {
- if (!value) {
- signReturnType.value = ''
- signReturnTypeError.value = ''
- } else {
- signReturnTypeError.value = ''
- }
- }
- // 方法:验证表单数据
- const validateFormData = () => {
- let isValid = true
- // 验证保价金额
- if (valueServices.insurance) {
- if (!validateInsuranceAmount()) {
- isValid = false
- }
- }
- // 验证签单返还类型
- if (valueServices.signReturn && !signReturnType.value && productType == '2') {
- signReturnTypeError.value = '请选择签单返还凭证类型'
- isValid = false
- }
- return isValid
- }
- function close() {
- const obj = { path: "/waybill/order" }
- proxy.$tab.closeOpenPage(obj)
- }
- // 方法:提交订单
- const isSubmit = ref(false)
- const submitOrder = async () => {
- if (!agreed.value) {
- ElMessage.warning('请先同意服务协议')
- return
- }
- // 验证寄件人表单
- let senderValid = false
- try {
- await senderForm.value.validate()
- senderValid = true
- } catch (error) {
- senderValid = false
- }
- if (!senderValid) {
- ElMessage.warning('请填写完整的寄件人信息')
- return
- }
- // 验证收件人表单
- let receiverValid = false
- try {
- await receiverForm.value.validate()
- receiverValid = true
- } catch (error) {
- receiverValid = false
- }
- if (!receiverValid) {
- ElMessage.warning('请填写完整的收件人信息')
- return
- }
- // 验证寄件方式表单(上门时间和快递类型)
- let deliveryValid = false
- try {
- await deliveryFormRef.value.validate()
- deliveryValid = true
- } catch (error) {
- deliveryValid = false
- }
- if (!deliveryValid) {
- ElMessage.warning('请填写完整的寄件方式信息')
- return
- }
- // 验证物品信息表单
- let itemInfoValid = false
- try {
- await itemInfoForm.value.validate()
- itemInfoValid = true
- } catch (error) {
- itemInfoValid = false
- }
- if (!itemInfoValid) {
- ElMessage.warning('请填写完整的物品信息')
- return
- }
- // 验证其他表单数据(增值服务相关)
- if (!validateFormData()) {
- return
- }
- if(isSubmit.value){
- return
- }
- isSubmit.value = true
- proxy.$modal.loading("正在创建订单,请稍候...")
- let formattedPickupStartTime = ''
- let formattedPickupEndTime = ''
- if (Array.isArray(deliveryForm.pickupTime) && deliveryForm.pickupTime.length > 0) {
- // 假设PickupTimeCascader返回的数组结构为 [日期, 时间段]
- const timeArr = deliveryForm.pickupTime[1].split('-')
- console.log('deliveryForm.pickupTime===',deliveryForm.pickupTime)
- console.log('timeArr===',timeArr)
- console.log('deliveryForm.pickupTime[0] + timeArr[0]===',deliveryForm.pickupTime[0] + ' ' + timeArr[0])
- formattedPickupStartTime = deliveryForm.pickupTime[0] + ' ' + timeArr[0] + ":00"
- formattedPickupEndTime = deliveryForm.pickupTime[0] + ' ' + timeArr[1] + ":00"
- console.log('formattedPickupStartTime===',formattedPickupStartTime)
- console.log('formattedPickupEndTime===',formattedPickupEndTime)
- }
- // <!-- 增值服务:-->
- // <!-- 包装:isPack-->
- // <!-- 保价:guaranteeMoney-->
- // <!-- 超长超重:isOverLongWeight-->
- // <!-- 签单返还:isReceiptCollect-->
- // <!-- 打木架:isWoodenCrate-->
- // <!-- 京东 包装 保价 签单反 保价有的话传值 没有的话传 空 签单反 没筛选了-->
- let services = {
- isPack:valueServices.isPack,
- guaranteeMoney:valueServices.insurance ? insuranceAmount.value : null,
- isReceiptCollect: valueServices.signReturn ? signReturnType.value : null
- }
- if(productType.value == '1'){ //京东
- services = {
- isPack:valueServices.packaging ? true : null,
- guaranteeMoney:valueServices.insurance ? insuranceAmount.value : null,
- isReceiptCollect: valueServices.signReturn ? true : null
- }
- }else {
- services = {
- isPack:valueServices.packaging ? true : null,
- guaranteeMoney:valueServices.insurance ? insuranceAmount.value : null,
- isReceiptCollect: valueServices.signReturn ? true : null
- }
- }
- // 构建完整的订单数据
- const orderData = {
- orderType: productType.value, //1-非时效件(京东),2-时效件(顺丰)
- senderName:sender.contactName,
- senderPhone:sender.contactPhone,
- senderProvince:sender.provinceName,
- senderCity:sender.cityName,
- senderCounty:sender.countyName,
- senderAddress:sender.detailedAddress,
- receiverName:receiver.contactName,
- receiverPhone:receiver.contactPhone,
- receiverProvince:receiver.provinceName,
- receiverCity:receiver.cityName,
- receiverCounty:receiver.countyName,
- receiverAddress:receiver.detailedAddress,
- goodsName:itemInfo.type,
- goodsWeight:itemInfo.weight,
- goodsVolume:itemInfo.volume,
- goodsQty:itemInfo.quantity,
- sendStartTime:formattedPickupStartTime,//上门取件时间
- sendEndTime:formattedPickupEndTime,//上门取件时间
- productCode: deliveryForm.expressType, //快递类型
- addedService: JSON.stringify(services),
- }
- console.log('提交订单数据:', orderData)
- try {
- const response = await addOrder(orderData)
- if(response.code == 200){
- console.log('订单提交成功:', response.data)
- ElMessage.success('订单创建成功!')
- close()
- } else {
- isSubmit.value = false
- // ElMessage.error(response.msg || '订单创建失败!')
- }
- } catch (error) {
- isSubmit.value = false
- console.error('订单提交失败:', error)
- // ElMessage.error(error.value)
- }finally {
- proxy.$modal.closeLoading()
- }
- }
- const getDefaultAddressFun = async () => {
- try {
- const response = await getDefaultAddress()
- if(response.code == 200){
- addressBookType.value = 'sender'
- applyAddress(response.data)
- } else {
- }
- } catch (error) {
- console.error('订单提交失败:', error)
- }
- }
- // 初始化加载
- onMounted(() => {
- console.log('快递下单页面已加载')
- console.log('省市区数据总数:', areaData.length)
- productType.value = route.query.productType || '1';
- console.log("===productType=", productType.value)
- getDefaultAddressFun()
- })
- </script>
- <style scoped>
- .express-order-page {
- width: 100%;
- padding: 20px;
- background-color: #F5F7FA;
- min-height: 100vh;
- box-sizing: border-box;
- }
- .form-row {
- display: flex;
- gap: 20px;
- margin-bottom: 20px;
- }
- .form-card {
- flex: 1;
- background: #ffffff;
- border-radius: 16px;
- overflow: hidden;
- position: relative;
- }
- .form-card.full-width {
- width: 100%;
- margin-bottom: 20px;
- }
- .card-header {
- display: flex;
- align-items: center;
- height: 50px;
- justify-content: space-between;
- padding: 16px 20px;
- background: #fff;
- }
- .card-header.send {
- border-radius: 16px 16px 0px 0px;
- background: linear-gradient(90deg, #EAF1FF 0%, #FFFFFF 100%);
- }
- .card-header.receive {
- border-radius: 16px 16px 0px 0px;
- background: linear-gradient(90deg, #FFF8E9 0%, #FFFFFF 100%);
- }
- .card-header.with-blue-line {
- display: flex;
- align-items: center;
- justify-content: flex-start;
- gap: 8px;
- background: #fff;
- border-radius: 16px 16px 0px 0px;
- }
- .blue-line {
- width: 4px;
- height: 16px;
- background: #2D71FF;
- border-radius: 2px;
- }
- .header-title {
- vertical-align: center;
- line-height: 30px;
- height: 30px;
- font-size: 16px;
- font-weight: 600;
- color: #333333;
- display: flex;
- align-content: center;
- }
- .header-title img {
- width: 30px;
- height: 30px;
- margin-right: 16px;
- }
- .address-book-btn {
- font-size: 14px;
- }
- .address-book-btn img {
- width: 20px;
- height: 20px;
- margin-right: 4px;
- }
- .form-content {
- padding: 20px;
- padding-bottom: 20px;
- }
- :deep(.fixed-input .el-input .el-input-group__append){
- box-shadow:none;
- }
- /* 输入框统一样式 */
- :deep(.fixed-input .el-input__wrapper),
- :deep(.fixed-input .el-cascader .el-input__wrapper),
- :deep(.fixed-input .el-select .el-select__wrapper),
- :deep(.fixed-input .el-input-number .el-input__wrapper) {
- width: 100%;
- box-sizing: border-box;
- background: #F5F7FA;
- border-radius: 4px;
- border: none;
- box-shadow: none !important;
- }
- :deep(.fixed-input .el-input__inner),
- :deep(.fixed-input .el-cascader .el-input__inner),
- :deep(.fixed-input .el-select .el-select__wrapper),
- :deep(.fixed-input .el-input-number .el-input__inner) {
- background: #F5F7FA;
- width: 100%;
- box-sizing: border-box;
- }
- /* 统一筛选框样式 */
- :deep(.fixed-input .el-select),
- :deep(.fixed-input .el-cascader),
- :deep(.fixed-input .el-input-number) {
- width: 100%;
- box-sizing: border-box;
- }
- :deep(.fixed-input .el-select .el-select__wrapper),
- :deep(.fixed-input .el-cascader .el-input__wrapper),
- :deep(.fixed-input .el-input-number .el-input__wrapper) {
- width: 100%;
- box-sizing: border-box;
- background: #F5F7FA;
- border-radius: 4px;
- border: none;
- box-shadow: none !important;
- }
- :deep(.fixed-input .el-select .el-select__wrapper),
- :deep(.fixed-input .el-cascader .el-input__inner),
- :deep(.fixed-input .el-input-number .el-input__inner) {
- background: #F5F7FA;
- width: 100%;
- box-sizing: border-box;
- }
- /* 下拉框选项样式 */
- :deep(.el-select-dropdown) {
- border-radius: 8px;
- box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
- }
- :deep(.el-select-dropdown__item) {
- padding: 8px 20px;
- font-size: 14px;
- color: #333;
- }
- :deep(.el-select-dropdown__item.selected) {
- color: #1890ff;
- background-color: #f0f7ff;
- }
- :deep(.el-select-dropdown__item:hover) {
- background-color: #f5f7fa;
- }
- /* 错误边框样式 */
- .error-border :deep(.el-input__wrapper) {
- box-shadow: 0 0 0 1px #f56c6c !important;
- }
- /* Form 样式调整 */
- :deep(.sender-form .el-form-item),
- :deep(.receiver-form .el-form-item),
- :deep(.item-info-form .el-form-item),
- :deep(.delivery-form .el-form-item) {
- margin-bottom: 20px;
- display: flex;
- align-items: center;
- }
- :deep(.sender-form .el-form-item__label),
- :deep(.receiver-form .el-form-item__label),
- :deep(.item-info-form .el-form-item__label),
- :deep(.delivery-form .el-form-item__label) {
- text-align: left;
- font-size: 14px;
- color: #666666;
- font-weight: 500;
- padding-right: 12px;
- width: 120px;
- flex-shrink: 0;
- white-space: nowrap;
- }
- :deep(.sender-form .el-form-item.is-required .el-form-item__label::before),
- :deep(.receiver-form .el-form-item.is-required .el-form-item__label::before),
- :deep(.item-info-form .el-form-item.is-required .el-form-item__label::before),
- :deep(.delivery-form .el-form-item.is-required .el-form-item__label::before) {
- color: #f56c6c;
- content: '*';
- margin-right: 4px;
- }
- :deep(.sender-form .el-form-item__content),
- :deep(.receiver-form .el-form-item__content),
- :deep(.item-info-form .el-form-item__content),
- :deep(.delivery-form .el-form-item__content) {
- flex: 1;
- min-width: 0;
- }
- :deep(.sender-form .el-input-number),
- :deep(.receiver-form .el-input-number),
- :deep(.item-info-form .el-input-number) {
- width: 100%;
- flex: 1;
- min-width: 0;
- }
- /* 输入框样式修改 */
- :deep(.fixed-input .el-input__wrapper:hover),
- :deep(.fixed-input .el-cascader .el-input__wrapper:hover),
- :deep(.fixed-input .el-select .el-input__wrapper:hover),
- :deep(.fixed-input .el-input-number .el-input__wrapper:hover) {
- background: #F0F2F5;
- }
- :deep(.fixed-input .el-input__wrapper.is-focus),
- :deep(.fixed-input .el-cascader .el-input__wrapper.is-focus),
- :deep(.fixed-input .el-select .el-input__wrapper.is-focus),
- :deep(.fixed-input .el-input-number .el-input__wrapper.is-focus) {
- background: #F5F7FA;
- box-shadow: 0 0 0 1px #409eff;
- }
- /* 调整el-input-number的特殊样式 */
- :deep(.fixed-input .el-input-number) {
- display: flex;
- align-items: center;
- }
- :deep(.fixed-input .el-input-number .el-input-number__decrease),
- :deep(.fixed-input .el-input-number .el-input-number__increase) {
- background-color: #F5F7FA;
- border: none;
- color: #666666;
- }
- :deep(.fixed-input .el-input-number .el-input-number__decrease:hover),
- :deep(.fixed-input .el-input-number .el-input-number__increase:hover) {
- background-color: #E6E8EB;
- }
- :deep(.fixed-input .el-input-number .el-input-number__decrease.is-disabled),
- :deep(.fixed-input .el-input-number .el-input-number__increase.is-disabled) {
- background-color: #F5F7FA;
- color: #C0C4CC;
- }
- :deep(.el-form-item__error) {
- padding-top: 4px;
- font-size: 12px;
- }
- /* 字数限制提示样式 */
- :deep(.el-input__count) {
- color: #999;
- font-size: 12px;
- }
- :deep(.el-input__count .el-input__count-inner) {
- background: transparent;
- }
- /* 默认地址复选框 */
- .default-address-footer {
- display: flex;
- justify-content: space-between;
- align-items: center;
- padding: 10px 0;
- border-top: 1px solid #f0f0f0;
- margin-top: 10px;
- }
- .default-address-wrapper {
- display: flex;
- align-items: center;
- }
- .checkbox-label {
- display: flex;
- align-items: center;
- cursor: pointer;
- user-select: none;
- }
- .checkbox-text {
- font-size: 14px;
- color: #666;
- margin-left: 8px;
- font-weight: normal;
- }
- .default-address-radio :deep(.el-checkbox__label) {
- display: none;
- }
- .default-address-radio :deep(.el-checkbox__inner) {
- border-color: #409eff;
- }
- .add-address-btn {
- padding: 10px 24px;
- border-radius: 4px;
- background-color: #1890ff;
- border-color: #1890ff;
- }
- .add-address-btn:hover {
- background-color: #40a9ff;
- border-color: #40a9ff;
- }
- .form-footer {
- display: flex;
- justify-content: flex-end;
- padding: 10px 0;
- border-top: 1px solid #f0f0f0;
- margin-top: 10px;
- }
- /* 寄件方式样式 */
- .delivery-option {
- display: flex;
- flex-direction: column;
- gap: 20px;
- }
- .option-item {
- display: flex;
- flex-direction: column;
- gap: 15px;
- }
- .btn-radio {
- background: #EAF0FF;
- border-radius: 8px;
- border: 1px solid #2D71FF;
- padding: 10px 16px;
- display: inline-block;
- width: fit-content;
- }
- /* 寄件方式网格布局 */
- .delivery-info-grid {
- display: grid;
- grid-template-columns: 1fr 1fr;
- gap: 30px;
- }
- /* 物品信息网格布局 */
- .item-info-grid-3 {
- display: grid;
- grid-template-columns: 1fr 1fr 1fr;
- gap: 20px;
- }
- /* 物品信息网格布局 */
- .item-info-grid-1 {
- display: grid;
- grid-template-columns: 1fr;
- gap: 20px;
- }
- /* 增值服务样式调整 */
- .value-services-grid {
- display: grid;
- grid-template-columns: repeat(3, 1fr);
- gap: 30px 50px;
- }
- .service-item {
- display: flex;
- align-items: center;
- gap: 15px;
- }
- .service-label {
- line-height: 40px;
- font-size: 14px;
- color: #333333;
- font-weight: 500;
- min-width: 80px;
- white-space: nowrap;
- }
- /* 保价样式 */
- .insurance-wrapper {
- display: flex;
- align-items: center;
- gap: 15px;
- flex-wrap: wrap;
- }
- .insurance-input-wrapper {
- flex: 1;
- min-width: 200px;
- :deep(.el-input-group__append){
- box-shadow: none;
- }
- }
- .insurance-input {
- width: 100%;
- }
- /* 签单返还样式 */
- .sign-return-wrapper {
- display: flex;
- align-items: center;
- gap: 15px;
- flex-wrap: wrap;
- }
- .sign-return-select-wrapper {
- flex: 1;
- min-width: 200px;
- }
- .sign-return-select {
- flex: 1;
- width: 100%;
- position: relative;
- }
- /* 错误信息样式 */
- .error-message {
- color: #f56c6c;
- font-size: 12px;
- margin-top: 4px;
- position: absolute;
- }
- :deep(.el-switch) {
- --el-switch-on-color: #1890ff;
- }
- /* 提交订单区域 */
- .agreement {
- display: flex;
- flex-direction: column;
- margin-left: 16px;
- gap: 12px;
- padding: 20px 0;
- }
- .price-notice {
- font-size: 14px;
- color: #ff7d00;
- font-weight: 500;
- }
- .submit-button {
- width: 120px;
- height: 48px;
- font-size: 16px;
- position: absolute;
- bottom: 27px;
- right: 16px;
- }
- .submit-button:disabled {
- opacity: 0.6;
- cursor: not-allowed;
- }
- /* 响应式调整 */
- @media (max-width: 1200px) {
- .value-services-grid {
- grid-template-columns: repeat(2, 1fr);
- gap: 25px;
- }
- .service-item {
- flex-wrap: wrap;
- }
- .insurance-wrapper,
- .sign-return-wrapper {
- flex-wrap: wrap;
- }
- }
- @media (max-width: 992px) {
- .item-info-grid-3 {
- grid-template-columns: 1fr 1fr;
- }
- .delivery-info-grid {
- grid-template-columns: 1fr;
- gap: 20px;
- }
- .express-type-options {
- width: 100%;
- }
- }
- @media (max-width: 768px) {
- .form-row {
- flex-direction: column;
- }
- .item-info-grid-3 {
- grid-template-columns: 1fr;
- }
- .value-services-grid {
- grid-template-columns: 1fr;
- }
- .express-type-section {
- flex-direction: column;
- align-items: flex-start;
- gap: 10px;
- }
- .express-type-label {
- min-width: auto;
- }
- .insurance-wrapper,
- .sign-return-wrapper {
- flex-direction: column;
- gap: 10px;
- }
- .insurance-input-wrapper,
- .sign-return-select-wrapper {
- min-width: 100%;
- }
- .service-label {
- min-width: auto;
- }
- .service-item {
- flex-direction: column;
- align-items: flex-start;
- gap: 10px;
- }
- .agreement {
- flex-direction: column;
- align-items: flex-start;
- gap: 12px;
- }
- .submit-section {
- flex-direction: column;
- gap: 20px;
- align-items: stretch;
- }
- .submit-button {
- position: static;
- width: 100%;
- margin-top: 20px;
- }
- :deep(.sender-form .el-form-item__label),
- :deep(.receiver-form .el-form-item__label),
- :deep(.item-info-form .el-form-item__label),
- :deep(.delivery-form .el-form-item__label) {
- width: 80px !important;
- }
- .default-address-footer {
- flex-direction: column;
- gap: 15px;
- align-items: flex-start;
- }
- .form-footer {
- justify-content: flex-start;
- }
- }
- /* 添加识别区域样式 */
- .recognition-area {
- background-color: #fff;
- //border-radius: 8px;
- //padding: 16px;
- margin-bottom: 20px;
- //border: 1px solid #e4e7ed;
- }
- .recognition-textarea :deep(.el-textarea__inner) {
- background-color: #F5F7FA;
- border: none;
- border-radius: 4px;
- font-size: 14px;
- }
- .recognition-actions {
- display: flex;
- justify-content: flex-end;
- margin-top: 12px;
- }
- .recognition-btn {
- width: 120px;
- height: 36px;
- background: #1B64F0;
- border-radius: 18px;
- font-size: 14px;
- }
- .recognition-tip {
- font-size: 12px;
- color: #999;
- margin-bottom: 8px;
- line-height: 1.5;
- }
- .header-actions {
- display: flex;
- gap: 12px;
- align-items: center;
- }
- .action-btn {
- display: flex;
- align-items: center;
- gap: 4px;
- }
- </style>
|