app需要接入快递100的页面,好烦啊,还要自己写代码,快递100只提供api,浅浅写一下吧,写一些基础页面,更多的让用户跳转我们自己的小程序页面看好了。
1.uniapp 开发,用到了ui框架List 列表 | 我的资料管理-uv-ui 是全面兼容vue3+2、nvue、app、h5、小程序等多端的uni-app生态框架 (uvui.cn)
2.用到了uniCloud来获取省份区,你也可以不用这个,unicloud-city-select 城市选择组件 | uniCloud (dcloud.net.cn)
3.快递100并没有提供地址簿接口,需要后端写
4.下面的代码仅写了静态页面,语言是vue3+ts css用了sass,一般来说,只要添加了我上面说的哪个ui框架,还有uniapp官方的城市选择组件,就能正常显示,剩下的就是对数据的展示
先看一下页面样式吧,可能有人会觉得有点丑,根据自己的需要修改一下吧,仅作为一个参考
上代码
<style lang="scss">
.special-delivery {
min-height: 100%;
background-color: #f7f8fa;
padding: 20rpx;
box-sizing: border-box;
}
.tabs {
min-height: 100rpx;
display: flex;
justify-content: space-between;
align-items: center;
border-radius: 8px;
background-color: #f2f3f5;
&-list {
height: 100rpx;
flex: 1;
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
background-color: #f2f3f5;
font-size: 30rpx;
}
&-list-checked {
background-color: white;
color: #1876fa;
font-weight: bolder;
border-radius: 8px 8px 0 0;
}
.tabs-list-left {
width: 100%;
border-left: 3rpx solid #999;
text-align: center;
}
.tabs-list-right {
width: 100%;
border-right: 3rpx solid #999;
text-align: center;
}
}
.infor {
min-height: 332rpx;
width: 100%;
background-color: white;
border-radius: 8px;
display: flex;
flex-direction: column;
.input-infor {
flex: 1;
display: flex;
}
&-left {
width: 104rpx;
display: flex;
align-items: center;
justify-content: center;
}
&-right {
width: calc(100% - 104rpx);
border-bottom: 1px solid #f1f1f1;
display: flex;
align-items: center;
justify-content: space-between;
.title {
font-size: 30rpx;
}
.subtitle {
font-size: 24rpx;
color: #999;
margin-top: 20rpx;
}
.address-book {
width: 130rpx;
height: 58rpx;
border-left: 1px solid #f1f1f1;
font-size: 26rpx;
display: flex;
align-items: center;
justify-content: center;
}
}
}
.ji-box {
width: 54rpx;
height: 54rpx;
border-radius: 27rpx;
background-color: #01d20f;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: 30rpx;
position: relative;
}
.ji-box1::after {
content: '';
position: absolute;
bottom: -9rpx;
left: 50%;
transform: translateX(-50%);
width: 0;
height: 0;
border-left: 10rpx solid transparent;
border-right: 10rpx solid transparent;
border-top: 10rpx solid #01d20f;
margin-left: auto;
margin-right: auto;
}
.ji-box2::after {
content: '';
position: absolute;
bottom: -9rpx;
left: 50%;
transform: translateX(-50%);
width: 0;
height: 0;
border-left: 10rpx solid transparent;
border-right: 10rpx solid transparent;
border-top: 10rpx solid #fb660c;
margin-left: auto;
margin-right: auto;
}
.btn-box {
min-height: 206rpx;
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
background-color: white;
margin-top: 22rpx;
flex-direction: column;
.text {
margin: 20rpx;
font-size: 24rpx;
color: #999;
}
}
.btn {
height: 88rpx;
width: 664rpx;
background-color: #ff9533;
border-radius: 8px;
color: white;
font-size: 36rpx;
}
.btn::after {
border: none;
}
.latest-orders {
margin-top: 22rpx;
.title {
font-size: 34rpx;
font-weight: bold;
display: flex;
justify-content: space-between;
align-items: flex-end;
.allordersview {
font-size: 24rpx;
color: #0076f3;
font-weight: normal;
}
}
}
.item-information {
min-height: 98rpx;
display: flex;
justify-content: space-between;
align-items: center;
color: #999;
background-color: white;
border-radius: 8px;
margin-top: 20rpx;
padding: 0 20rpx;
box-sizing: border-box;
.more {
display: flex;
color: #d3d3d3;
}
}
.information {
width: 100%;
padding: 20rpx 60rpx 0 60rpx;
box-sizing: border-box;
.title {
display: flex;
align-items: center;
}
.subtitle {
margin-left: 20rpx;
font-weight: bold;
}
.inputbox {
display: flex;
border-bottom: 1px solid #f1f1f1;
padding: 30rpx 0;
}
.input {
min-width: 150rpx;
display: flex;
align-items: center;
}
}
.addbtn {
height: 60rpx;
width: 444rpx;
background-color: #ff9533;
border-radius: 8px;
color: white;
font-size: 30rpx;
display: flex;
align-items: center;
justify-content: center;
padding: 0;
margin-top: 40rpx;
}
.addbtn::after {
border: none;
}
.ellipsis {
max-width: 400rpx;
/* 隐藏超出容器的文本 */
overflow: hidden;
/* 防止文本换行 */
white-space: nowrap;
/* 使用省略号来指示文本已被截断 */
text-overflow: ellipsis;
}
.address-book-popup {
width: 100%;
min-height: 600rpx;
.addressbooklist{
min-height: 146rpx;
padding: 20rpx;
box-sizing: border-box;
// border-top: 1px solid #f1f1f1;
border-bottom: 1px solid #f1f1f1;
display: flex;
align-items: center;
justify-content: space-between;
}
.footer{
display: flex;
margin-left: 20rpx;
}
.uv-icon{
padding: 0 22rpx;
border-right: 1px solid #a5a5a5;
}
.uv-icon:nth-child(2){
border: none;
}
.name{
font-size: 34rpx;
font-weight: bold;
}
.address{
font-size: 30rpx;
color: #999;
}
}
</style>
<template>
<view class="special-delivery">
<!-- 下单区域 -->
<view class="place-rder">
<view class="tabs">
<view @click="tabcCheck(0)" :class="tabsIndex==0?'tabs-list tabs-list-checked':'tabs-list'">
寄快递
</view>
<view @click="tabcCheck(1)" :class="tabsIndex==1?'tabs-list tabs-list-checked':'tabs-list'">
<view :class="tabsIndex==0?'tabs-list-right':tabsIndex==1?'':'tabs-list-left'">
批量寄件
</view>
</view>
<view @click="tabcCheck(2)" :class="tabsIndex==2?'tabs-list tabs-list-checked':'tabs-list'">
寄大件
</view>
</view>
<view class="infor">
<view class="input-infor">
<view @click.stop="inforFill(1)" class="infor-left">
<view class="ji-box ji-box1">
寄
</view>
</view>
<view class="infor-right">
<view @click.stop="inforFill(1)">
<view class="title ">
<view class="ellipsis" v-if="senderInfor.senderName || senderInfor.senderTel">
{{senderInfor.senderName}} {{senderInfor.senderTel}}
</view>
<text v-if="!senderInfor.senderName && !senderInfor.senderTel">寄件人信息</text>
</view>
<view class="subtitle">
<view class="ellipsis" v-if="senderInfor.senderAddress || senderInfor.senderRegion">
{{senderInfor.senderRegion}}
{{senderInfor.senderAddress}}
</view>
<text
v-if="!senderInfor.senderAddress && !senderInfor.senderRegion">点击填写寄件服务,支持文本导入</text>
</view>
</view>
<view class="address-book" @click.stop="addressBook">
地址簿
</view>
</view>
</view>
<view class="input-infor">
<view @click.stop="inforFill(2)" class="infor-left">
<view class="ji-box ji-box2" style="background-color: #fb660c;">
收
</view>
</view>
<view class="infor-right" style="border: none;">
<view @click.stop="inforFill(2)">
<view class="title">
<view class="ellipsis" v-if="senderInfor.name || senderInfor.tel">{{senderInfor.name}}
{{senderInfor.tel}}
</view>
<text v-if="!senderInfor.name && !senderInfor.tel">收件人信息</text>
</view>
<view class="subtitle">
<view class="ellipsis" v-if="senderInfor.address || senderInfor.regione">
{{senderInfor.regione}}
{{senderInfor.address}}
</view>
<text v-if="!senderInfor.address && !senderInfor.regione">复制收件人信息,系统自动填写</text>
</view>
</view>
<view class="address-book" @click.stop="addressBook">
地址簿
</view>
</view>
</view>
</view>
</view>
<view class="btn-box">
<button @click="Shipping" class="btn">去寄件</button>
<view style="display: flex;height: 30rpx;">
<view class="text">上门取件</view>
<view class="text">先寄后付</view>
<view class="text">售后保障</view>
</view>
</view>
<view class="item-information">
<view>物品信息</view>
<view class="more">请选择物品信息<uv-icon color="#666" name="arrow-right"></uv-icon></view>
</view>
<view class="latest-orders">
<view class="title">
<text>最近订单</text>
<text class="allordersview">查看全部订单</text>
</view>
<uv-empty text="没有你的寄件订单" mode="order" icon="https://cdn.uviewui.com/uview/empty/order.png"></uv-empty>
</view>
</view>
<!-- 寄件人 收件人信息填写 -->
<uv-popup ref="inforPopup" mode="bottom" round="8">
<!-- 寄件人信息填写 -->
<view class="information" v-if="index==1">
<view class="title">
<view class="ji-box ji-box1">
寄
</view>
<view class="subtitle">寄件人</view>
</view>
<view class="inputbox">
<view class="input">姓名</view>
<input v-model="senderInfor.name" type="text" placeholder="请输入姓名" />
</view>
<view class="inputbox">
<view class="input">手机号</view>
<input v-model="senderInfor.tel" class="input" type="text" placeholder="请输入手机号" />
</view>
<view class="inputbox">
<view class="input">地区</view>
<input v-model="senderInfor.region" @click="chooseLocation" class="input" type="text"
placeholder="请选择地区" />
</view>
<view class="inputbox">
<view class="input">地址</view>
<input v-model="senderInfor.address" class="input" type="text" placeholder="请输入地址" />
</view>
<button class="addbtn" @click="addAddress" style="background-color: #01d20f;">点此可以添加到寄件人地址簿</button>
</view>
<!-- 收件人信息填写 -->
<view class="information" v-if="index==2">
<view class="title">
<view class="ji-box ji-box2" style="background-color: #fb660c;">
收
</view>
<view class="subtitle">收件人</view>
</view>
<view class="inputbox">
<view class="input">姓名</view>
<input v-model="senderInfor.name" type="text" placeholder="请输入姓名" />
</view>
<view class="inputbox">
<view class="input">手机号</view>
<input v-model="senderInfor.tel" class="input" type="text" placeholder="请输入手机号" />
</view>
<view class="inputbox">
<view class="input">地区</view>
<input v-model="senderInfor.regione" @click="chooseLocation" class="input" type="text"
placeholder="请选择地区" />
</view>
<view class="inputbox">
<view class="input">地址</view>
<input v-model="senderInfor.address" class="input" type="text" placeholder="请输入地址" />
</view>
<button class="addbtn" @click="addAddress">点此可以添加到收件人地址簿</button>
</view>
</uv-popup>
<!-- 城市选择 -->
<unicloud-city-select ref="citySelect" :hot-city="hotCity" :location="false"
@select="select"></unicloud-city-select>
<!-- 地址簿抽屉 -->
<uv-popup ref="addressBookPopup" mode="bottom" round="8">
<view class="address-book-popup">
<!-- trash-fill edit-pen-fill -->
<view class="addressbooklist">
<view class="header">
<view class="name">
张三 199*****140
</view>
<view class="address ellipsis">
XXXXXXXXXXXXXXxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
</view>
</view>
<view class="footer">
<uv-icon name="trash-fill"></uv-icon>
<uv-icon name="edit-pen-fill"></uv-icon>
</view>
</view>
<view class="addressbooklist">
<view class="header">
<view class="name">
张三 199*****140
</view>
<view class="address ellipsis">
XXXXXXXXXXXXXX
</view>
</view>
<view class="footer">
<uv-icon name="trash-fill"></uv-icon>
<uv-icon name="edit-pen-fill"></uv-icon>
</view>
</view>
</view>
</uv-popup>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { onLoad } from "@dcloudio/uni-app";
let tabsIndex = ref(0)
let addressBookPopup = ref()
let inforPopup = ref()
let citySelect = ref()
let index = ref(1)
// 寄件人表单信息
let senderInfor = ref({
name: null,
tel: null,
region: null,
address: null
})
// 收件人表单信息
let addresseeInfor = ref({
name: null,
tel: null,
region: null,
address: null
})
// 手机号正则
let phoneReg = /^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/
let hotCity = [
{ code: "110100", name: "北京" },
{ code: "310100", name: "上海" },
{ code: "330100", name: "杭州" },
{ code: "440100", name: "广州" },
{ code: "440300", name: "深圳" },
{ code: "320100", name: "南京" },
{ code: "500100", name: "重庆" },
{ code: "510100", name: "成都" }
]
// 下单 订单信息
let orderInfor = ref<orderInfor>()
interface orderInfor {
kuaidicom : string, //快递公司的编码,一律用小写字母,见《快递公司编码》
recManName : string, //收件人姓名
recManMobile : string, //收件人的手机号,手机号和电话号二者其一必填
recManPrintAddr : string, //收件人所在完整地址
sendManName : string, //寄件人姓名
sendManMobile : string, //寄件人的手机号
sendManPrintAddr : string, //寄件人所在的完整地址
callBackUrl : string, //callBackUrl订单信息回调
cargo : string, //物品名称,例:文件
payment : string //支付方式,SHIPPER: 寄方付(默认),CONSIGNEE: 到付(中通不支持)
weight : string,//物品总重量KG,不需带单位,例:1.5
remark : string,//备注
dayType : string,//预约日期,例如:今天/明天/后天
pickupStartTime : string,//预约起始时间,24小时制(HH:mm),例如:09:00
pickupEndTime : string,//预约截止时间,24小时制(HH:mm),例如:10:00
salt : string,//签名用随机字符串
op : string,//是否开启订阅功能 0:不开启(默认) 1:开启 说明开启订阅功能时:pollCallBackUrl必须填入 此功能只针对有快递单号的单
pollCallBackUrl : string,//如果op设置为1时,pollCallBackUrl必须填入,用于跟踪回调。此为免费服务,回调内容通过五、快递信息推送接口 返回(免费服务)
resultv2 : string,//添加此字段表示开通行政区域解析功能 。
thirdOrderId : string,// 平台订单号,最大32位。若此参数与之前的重复,48小时内返回第一次下单内容,否则会重新下单。
}
onLoad(() => {
})
// 切换选项卡
function tabcCheck(index : number) {
tabsIndex.value = index
}
function addressBook() {
addressBookPopup.value.open()
index.value = 1
}
// 寄件信息抽屉弹出
function inforFill(num : number) {
inforPopup.value.open()
index.value = num
}
// 打开地址选择页面
function chooseLocation() {
citySelect.value.open();
}
// 地址选择回调
function select(city : any) {
if (index.value == 1) {
senderInfor.value.region = city.name
console.log("寄件人信息", senderInfor.value)
} else {
addresseeInfor.value.region = city.name
console.log("收件人信息", addresseeInfor.value)
}
}
// 寄件按钮
function Shipping() {
// 验证手机号
if (phoneReg.test(senderInfor.value.tel) && phoneReg.test(addresseeInfor.value.tel)) {
// 都为真 执行下单逻辑
} else {
// 有一个或两个手机号不匹配正则
uni.showToast({
icon: "error",
title: "请检查手机号"
})
}
}
// 添加地址
function addAddress() {
if (index.value == 1) {
console.log("寄件人信息", senderInfor.value)
// 添加寄件人地址
inforDetect(senderInfor.value.name, senderInfor.value.tel, senderInfor.value.address, senderInfor.value.region, () => {
// 此处写添加寄件人地址簿逻辑
})
} else {
console.log("收件人信息", addresseeInfor.value)
// 添加收件人地址
inforDetect(addresseeInfor.value.name, addresseeInfor.value.tel, addresseeInfor.value.address, addresseeInfor.value.region, () => {
// 此处写添加收件人地址簿逻辑
})
}
}
// 添加地址簿参数检测
function inforDetect(name : string, tel : string, address : string, region : string, fn : Function) {
// 信息不为空判断
if (name && tel && address && region) {
// 手机号正则验证
if (phoneReg.test(tel)) {
// 在此处执行添加地址簿逻辑
fn()
// 手机号检查成功
uni.showToast({
icon: "success", title: "添加成功"
})
} else {
// 有一个或两个手机号不匹配正则
uni.showToast({
icon: "error",
title: "请检查手机号"
})
}
} else {
uni.showToast({
icon: "error", title: "请填写完整信息"
})
}
}
</script>