index.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769
  1. <template>
  2. <view class="deliver-goods">
  3. <header>
  4. <view class="order-num acea-row row-between-wrapper">
  5. <view class="num line1">订单号:{{ order_id }}</view>
  6. <view class="name line1">
  7. <span class="iconfont icon-yonghu2"></span>{{ delivery.nickname }}
  8. </view>
  9. </view>
  10. <view class="address">
  11. <view class="name">
  12. {{ delivery.real_name
  13. }}<span class="phone">{{ delivery.user_phone }}</span>
  14. </view>
  15. <view>{{ delivery.user_address }}</view>
  16. </view>
  17. <view class="line">
  18. <image src="@/static/images/line.jpg" />
  19. </view>
  20. </header>
  21. <view class="wrapper">
  22. <view class="item acea-row row-between-wrapper">
  23. <view>发货方式</view>
  24. <view class="mode acea-row row-middle row-right">
  25. <view class="goods" :class="(active === index || productType==3) ? 'on' : ''" v-for="(item, index) in types"
  26. :key="index" @click="changeType(item, index)">
  27. {{ item.title }}<span class="iconfont icon-xuanzhong2"></span>
  28. </view>
  29. </view>
  30. </view>
  31. <block v-if="logistics.length>0">
  32. <view class="list" v-show="active === 0">
  33. <view class="item acea-row row-between-wrapper" v-if="delivery.config_export_open == 1">
  34. <view>发货类型</view>
  35. <view class="mode acea-row row-middle row-right">
  36. <view class="goods" :class="curExpress === item.key ? 'on' : ''"
  37. v-for="(item, index) in expressType" :key="index" @click="changeExpTpe(item, index)">
  38. {{ item.title }}<span class="iconfont icon-xuanzhong2"></span>
  39. </view>
  40. </view>
  41. </view>
  42. <block v-if="curExpress == 1">
  43. <view class="item acea-row row-between-wrapper">
  44. <view>快递公司</view>
  45. <view class="select-box">
  46. <picker class="pickerBox" @change="bindPickerChange" :value="seIndex" :range="logistics"
  47. range-key="name">
  48. <!-- <view></view> -->
  49. <view class="uni-input"><span class="marr">{{logistics[seIndex].name}}</span> <span class="iconfont icon-xiangyou size"></span></view>
  50. </picker>
  51. </view>
  52. </view>
  53. <view class="item acea-row row-between-wrapper">
  54. <view>快递单号</view>
  55. <input type="text" placeholder="填写快递单号" v-model="delivery_id" class="mode size" />
  56. <!-- #ifdef MP -->
  57. <text class="iconfont icon-xiangji" @click="scanCode"></text>
  58. <!-- #endif -->
  59. <!-- #ifdef H5 -->
  60. <text v-if="isWeixin" class="iconfont icon-xiangji" @click="scanCode"></text>
  61. <!-- #endif -->
  62. </view>
  63. <view class="item">
  64. <p class="trip" v-if="curExpress == 1">顺丰请输入单号 :收件人或寄件人手机号后四位</p>
  65. <p class="trip" v-if="curExpress == 1">例如:0080890707090</p>
  66. </view>
  67. </block>
  68. <block v-if="curExpress == 2">
  69. <view class="item acea-row row-between-wrapper">
  70. <view>快递公司</view>
  71. <view class="select-box">
  72. <picker class="pickerBox" @change="bindPickerChange" :value="seIndex" :range="logistics"
  73. range-key="name">
  74. <!-- <view></view> -->
  75. <view class="uni-input">{{logistics[seIndex].name}}</view>
  76. </picker>
  77. </view>
  78. </view>
  79. <view class="item acea-row row-between-wrapper" v-if="expTemp.length>0">
  80. <view>电子面单</view>
  81. <div class="picker-add">
  82. <picker class="pickerBox" @change="bindTempChange" :value="expIndex" :range="expTemp"
  83. range-key="title">
  84. <view class="uni-input">{{expTemp[expIndex].title}}</view>
  85. </picker>
  86. <div class="look" @click="previewImage">预览</div>
  87. </div>
  88. </view>
  89. <view class="item acea-row row-between-wrapper">
  90. <view>寄件人姓名:</view>
  91. <input type="text" placeholder="填写寄件人姓名" v-model="to_name" class="mode" />
  92. </view>
  93. <view class="item acea-row row-between-wrapper">
  94. <view>寄件人电话:</view>
  95. <input type="text" placeholder="填写寄件人电话" v-model="to_tel" class="mode" />
  96. </view>
  97. <view class="item acea-row row-between-wrapper">
  98. <view>寄件人地址:</view>
  99. <input type="text" placeholder="填写寄件人地址" v-model="to_addr" class="mode" />
  100. </view>
  101. </block>
  102. </view>
  103. </block>
  104. <view class="list" v-show="active === 1">
  105. <view class="item acea-row row-between-wrapper">
  106. <view>送货人</view>
  107. <view class="select-box" v-if="postPeople.length>0">
  108. <picker class="pickerBox" @change="bindPostChange" :value="postIndex" :range="postPeople"
  109. range-key="wx_name">
  110. <!-- <view></view> -->
  111. <view class="uni-input">{{postPeople[postIndex].wx_name}}</view>
  112. </picker>
  113. </view>
  114. </view>
  115. </view>
  116. <textarea v-show="active === 2" v-model="fictitious_content" class="textarea" @blur="bindTextAreaBlur"
  117. placeholder="备注" :maxlength="500" auto-height />
  118. <view class="item acea-row row-between-wrapper" v-if="totalNum>1&&active !== 2">
  119. <view>分单发货</view>
  120. <view class="mode acea-row row-middle row-right">
  121. <view class="goods" :class="curGoods === item.key ? 'on' : ''"
  122. v-for="(item, index) in orderGoods" :key="item.key" @click="changeGoods(item)">
  123. {{ item.title }}<span class="iconfont icon-xuanzhong2"></span>
  124. </view>
  125. </view>
  126. </view>
  127. <splitOrder :splitGoods="splitGoods" @getList="getList" v-if="curGoods"></splitOrder>
  128. </view>
  129. <view class="height-add"></view>
  130. <view class="button">
  131. <view class="box" @click="saveInfo">
  132. 确认提交
  133. </view>
  134. </view>
  135. </view>
  136. </template>
  137. <script>
  138. import {
  139. getOrderDeliveryinfoApi,
  140. getOrderExportApi,
  141. getOrderExportTemp,
  142. setOrderDelivery,
  143. getOrderDelivery,
  144. storeSplitInfo,
  145. storeSplitDelivery
  146. } from "@/api/admin";
  147. import {
  148. checkPhone
  149. } from '@/utils/validate.js'
  150. import splitOrder from '@/components/splitOrder';
  151. export default {
  152. name: "GoodsDeliver",
  153. components: {
  154. splitOrder
  155. },
  156. props: {},
  157. data: function() {
  158. return {
  159. types: [{
  160. type: "express",
  161. title: "发货",
  162. key: 1
  163. },
  164. {
  165. type: "send",
  166. title: "送货",
  167. key: 2
  168. },
  169. {
  170. type: "fictitious",
  171. title: "无需物流",
  172. key: 3
  173. }
  174. ],
  175. expressType: [{
  176. title: '手动填写',
  177. key: 1
  178. },
  179. {
  180. title: '电子面单打印',
  181. key: 2
  182. },
  183. ],
  184. orderGoods: [
  185. {
  186. title:'开启',
  187. key: 1
  188. },
  189. {
  190. title:'关闭',
  191. key: 0
  192. }
  193. ],
  194. curExpress: 1,
  195. active: 0,
  196. order_id: "",
  197. delivery: [],
  198. logistics: [],
  199. delivery_type: "1",
  200. delivery_name: "",
  201. delivery_id: "",
  202. seIndex: 0,
  203. expIndex: 0,
  204. expTemp: [], // 快递模板
  205. to_name: '', // 发货人名称
  206. to_tel: '', // 发货人电话
  207. to_addr: "", // 发货人地址
  208. postPeople: [], //配送人
  209. postIndex: 0,
  210. fictitious_content: '',
  211. listId:0,
  212. curGoods:0,
  213. splitGoods:[],
  214. cartIds:[],
  215. totalNum:0,
  216. productType:0,
  217. // #ifdef H5
  218. isWeixin: this.$wechat.isWeixin()
  219. // #endif
  220. };
  221. },
  222. watch: {
  223. "$route.params.oid": function(newVal) {
  224. let that = this;
  225. if (newVal != undefined) {
  226. that.order_id = newVal;
  227. that.getIndex();
  228. }
  229. }
  230. },
  231. onLoad: function(option) {
  232. this.order_id = option.id;
  233. this.listId = option.listId;
  234. this.totalNum = option.totalNum;
  235. this.comeType = option.comeType;
  236. this.productType = option.productType
  237. if(this.productType==3){
  238. this.types.splice(0,2);
  239. this.delivery_type = 3;
  240. this.active = 2;
  241. }
  242. if(option.orderStatus == 8 || option.orderStatus == 4 || option.orderStatus == 9){
  243. this.curGoods = 1;
  244. this.orderGoods.pop();
  245. this.splitList();
  246. }
  247. this.getIndex();
  248. this.getLogistics();
  249. this.geTorderOrderDelivery()
  250. },
  251. methods: {
  252. getList(val){
  253. let that = this;
  254. that.splitGoods = val;
  255. let cartIds = [];
  256. val.forEach((item)=>{
  257. if(item.checked){
  258. let i = {
  259. cart_id:item.cart_id,
  260. cart_num:item.surplus_num
  261. }
  262. cartIds.push(i)
  263. }
  264. })
  265. this.cartIds = cartIds;
  266. },
  267. splitList(){
  268. storeSplitInfo(this.listId).then(res=>{
  269. let list = res.data;
  270. list.forEach((item)=>{
  271. item.checked = false
  272. item.numShow = item.surplus_num
  273. })
  274. this.splitGoods = list;
  275. }).catch(err=>{
  276. return this.$util.Tips({
  277. title: err
  278. });
  279. })
  280. },
  281. // 点击获取拆单列表
  282. changeGoods(item){
  283. this.curGoods = item.key;
  284. if(item.key){
  285. this.splitList();
  286. }
  287. },
  288. // 扫描快递单号一维码
  289. scanCode() {
  290. // #ifdef MP
  291. let that = this;
  292. uni.scanCode({
  293. scanType: ['barCode'],
  294. success(res) {
  295. that.delivery_id = res.result;
  296. }
  297. })
  298. // #endif
  299. // #ifdef H5
  300. if (this.$wechat.isWeixin()) {
  301. this.$wechat.wechatEvevt('scanQRCode', {
  302. needResult: 1,
  303. scanType: ['barCode']
  304. }).then(res => {
  305. let result = res.resultStr.split(",");
  306. this.delivery_id = result[1];
  307. });
  308. }
  309. // #endif
  310. },
  311. // 预览图片
  312. previewImage() {
  313. uni.previewImage({
  314. urls: [this.expTemp[this.expIndex].pic],
  315. success: function() {
  316. },
  317. fail: function(error) {
  318. }
  319. });
  320. },
  321. // 获取配送员列表
  322. geTorderOrderDelivery() {
  323. getOrderDelivery().then(res => {
  324. this.postPeople = res.data
  325. })
  326. },
  327. // 配送员选择
  328. bindPostChange(e) {
  329. this.postIndex = e.detail.value
  330. },
  331. // 选择发货类型
  332. changeExpTpe(item, index) {
  333. this.curExpress = item.key
  334. this.getLogistics(index || '');
  335. },
  336. changeType: function(item, index) {
  337. this.active = index;
  338. this.delivery_type = item.key;
  339. },
  340. getIndex: function() {
  341. let that = this;
  342. getOrderDeliveryinfoApi(that.order_id).then(
  343. res => {
  344. that.delivery = res.data;
  345. that.to_name = res.data.export.to_name;
  346. that.to_tel = res.data.export.to_tel;
  347. that.to_addr = res.data.export.to_add;
  348. },
  349. error => {
  350. that.$util.Tips({
  351. title: error
  352. })
  353. }
  354. );
  355. },
  356. getLogistics(status) {
  357. let that = this;
  358. getOrderExportApi({
  359. status
  360. }).then(
  361. res => {
  362. that.logistics = res.data;
  363. that.getExpTemp(res.data[0].code)
  364. },
  365. error => {
  366. that.$util.Tips({
  367. title: error
  368. })
  369. }
  370. );
  371. },
  372. async saveInfo() {
  373. let that = this,
  374. delivery_type = that.delivery_type,
  375. delivery_name = that.logistics[that.seIndex].name,
  376. delivery_id = that.delivery_id,
  377. userName = that.delivery_name,
  378. save = {};
  379. save.delivery_type = delivery_type;
  380. save.delivery_code = that.logistics[that.seIndex].code
  381. save.delivery_name = that.logistics[that.seIndex].name
  382. save.type = that.active + 1
  383. if (delivery_type == 1 && this.curExpress == 1) {
  384. if (!delivery_id) {
  385. return this.$util.Tips({
  386. title: '请填写快递单号'
  387. })
  388. }
  389. save.express_record_type = that.curExpress
  390. save.delivery_id = delivery_id
  391. if(that.curGoods){
  392. that.setSplitInfo(save)
  393. }else{
  394. that.setInfo(save);
  395. }
  396. }
  397. if (delivery_type == 1 && this.curExpress == 2) {
  398. if (!that.to_name) {
  399. return this.$util.Tips({
  400. title: '请填写寄件人姓名'
  401. })
  402. }
  403. if (!that.to_tel) {
  404. return this.$util.Tips({
  405. title: '请填写寄件人手机号码'
  406. })
  407. }
  408. if (!(/^1[3456789]\d{9}$/.test(that.to_tel))) {
  409. return this.$util.Tips({
  410. title: '请填写寄件人手机号码'
  411. })
  412. }
  413. if (!that.to_addr) {
  414. return this.$util.Tips({
  415. title: '请填写寄件人地址'
  416. })
  417. }
  418. if (that.expTemp.length == 0) {
  419. return this.$util.Tips({
  420. title: '请选择电子面单'
  421. })
  422. }
  423. save.express_record_type = that.curExpress
  424. save.to_name = that.to_name
  425. save.to_tel = that.to_tel
  426. save.to_addr = that.to_addr
  427. save.express_temp_id = that.expTemp[that.expIndex].temp_id
  428. if(that.curGoods){
  429. that.setSplitInfo(save)
  430. }else{
  431. that.setInfo(save);
  432. }
  433. }
  434. if (delivery_type == 2) {
  435. if(!that.postPeople.length){
  436. return this.$util.Tips({
  437. title: '请在门店后台添加送货人'
  438. })
  439. }
  440. let obj = this.postPeople[this.postIndex]
  441. let params = {}
  442. params.type = that.delivery_type
  443. params.sh_delivery_name = obj.wx_name
  444. params.sh_delivery_id = obj.phone
  445. params.sh_delivery_uid = obj.uid
  446. if(that.curGoods){
  447. that.setSplitInfo(params)
  448. }else{
  449. that.setInfo(params);
  450. }
  451. }
  452. if (delivery_type == 3) {
  453. let params = {}
  454. params.type = that.delivery_type;
  455. params.fictitious_content = that.fictitious_content;
  456. if(that.curGoods){
  457. that.setSplitInfo(params)
  458. }else{
  459. that.setInfo(params);
  460. }
  461. }
  462. },
  463. setInfo: function(item) {
  464. let that = this;
  465. setOrderDelivery(that.delivery.id, item).then(
  466. res => {
  467. that.$util.Tips({
  468. title: res.msg,
  469. icon: 'success',
  470. mask: true
  471. })
  472. setTimeout(res => {
  473. if(this.comeType == 2){
  474. uni.navigateTo({
  475. url:'/pages/admin/store/orderDetail/index?id='+this.listId
  476. })
  477. }else{
  478. uni.navigateTo({
  479. url:'/pages/admin/store/order/index?type=1'
  480. })
  481. }
  482. }, 2000)
  483. },
  484. error => {
  485. that.$util.Tips({
  486. title: error
  487. })
  488. }
  489. );
  490. },
  491. setSplitInfo(item){
  492. if(!this.cartIds.length){
  493. return this.$util.Tips({
  494. title: '请选择发货商品'
  495. })
  496. }
  497. item.cart_ids = this.cartIds
  498. storeSplitDelivery(this.delivery.id, item).then(res=>{
  499. this.$util.Tips({
  500. title: res.msg,
  501. icon: 'success',
  502. mask: true
  503. })
  504. setTimeout(res => {
  505. if(this.comeType == 2){
  506. uni.navigateTo({
  507. url:'/pages/admin/store/orderDetail/index?id='+this.listId
  508. })
  509. }else{
  510. uni.navigateTo({
  511. url:'/pages/admin/store/order/index?type=1'
  512. })
  513. }
  514. }, 2000)
  515. }).catch(err=>{
  516. this.$util.Tips({
  517. title: err
  518. })
  519. })
  520. },
  521. bindPickerChange(e) {
  522. this.seIndex = e.detail.value
  523. this.getExpTemp(this.logistics[e.detail.value].code)
  524. },
  525. bindTempChange(e) {
  526. this.expIndex = e.detail.value
  527. },
  528. getExpTemp(code) {
  529. getOrderExportTemp({
  530. com: code
  531. }).then(res => {
  532. this.expTemp = res.data.data
  533. })
  534. }
  535. }
  536. };
  537. </script>
  538. <style lang="scss" scoped>
  539. .picker-add {
  540. display: flex;
  541. align-items: center;
  542. }
  543. .height-add {
  544. height:1.2rem;
  545. }
  546. /deep/.splitOrder{
  547. margin-bottom: 100rpx;
  548. }
  549. /deep/.splitOrder .items .picTxt{
  550. width: 560rpx;
  551. }
  552. /deep/.splitOrder .items .picTxt .text{
  553. width: 380rpx;
  554. }
  555. /deep/.splitOrder .items .picTxt .name{
  556. width: 292rpx;
  557. }
  558. .marr{display: inline-block;margin-right: 24upx;}
  559. .size{font-size: 28upx;}
  560. .trip {
  561. font-size: 22upx;
  562. color: #ccc;
  563. padding: 6upx 0upx;
  564. }
  565. .button{
  566. position: fixed;
  567. height: 80upx;
  568. bottom: 44upx;
  569. // width: 100%;
  570. .box{
  571. text-align: center;
  572. font-size: 30upx;
  573. color: #FFFFFF;
  574. line-height: 80upx;
  575. width: 690upx;
  576. margin: 0 auto;
  577. height: 80upx;
  578. background: #1890FF;
  579. border-radius: 40upx;
  580. }
  581. }
  582. </style>
  583. <style lang="scss">
  584. /*发货*/
  585. .deliver-goods{
  586. padding: 20upx 30upx;
  587. }
  588. .deliver-goods header {
  589. width: 100%;
  590. background-color: #fff;
  591. margin-top: 10upx;
  592. }
  593. .deliver-goods header .order-num {
  594. padding: 18upx 24upx;
  595. border-bottom: 1px solid #f5f5f5;
  596. height: 67upx;
  597. }
  598. .deliver-goods header .order-num .num {
  599. width: 430upx;
  600. font-size: 26upx;
  601. color: #282828;
  602. position: relative;
  603. }
  604. .deliver-goods header .order-num .num:after {
  605. position: absolute;
  606. content: '';
  607. width: 1px;
  608. height: 30upx;
  609. background-color: #ddd;
  610. top: 50%;
  611. margin-top: -15upx;
  612. right: 0;
  613. }
  614. .deliver-goods header .order-num .name {
  615. font-size: 26upx;
  616. color: #282828;
  617. text-align: center;
  618. width: 200upx;
  619. }
  620. .deliver-goods header .order-num .name .iconfont {
  621. font-size: 35upx;
  622. color: #477ef3;
  623. vertical-align: middle;
  624. margin-right: 10upx;
  625. }
  626. .deliver-goods header .address {
  627. font-size: 26upx;
  628. color: #868686;
  629. background-color: #fff;
  630. padding: 30upx;
  631. }
  632. .deliver-goods header .address .name {
  633. font-size: 34upx;
  634. color: #282828;
  635. margin-bottom: 10upx;
  636. }
  637. .deliver-goods header .address .name .phone {
  638. margin-left: 40upx;
  639. }
  640. .deliver-goods header .line {
  641. width: 100%;
  642. height: 3upx;
  643. }
  644. .deliver-goods header .line image {
  645. width: 100%;
  646. height: 100%;
  647. display: block;
  648. }
  649. .deliver-goods .wrapper {
  650. width: 100%;
  651. background-color: #fff;
  652. margin-top: 20upx;
  653. border-radius: 12upx;
  654. }
  655. .deliver-goods .wrapper .item {
  656. border-bottom: 1px solid #f0f0f0;
  657. padding: 0 30upx;
  658. height: 96upx;
  659. font-size: 28upx;
  660. color: #282828;
  661. position: relative;
  662. }
  663. .deliver-goods .wrapper .item .mode {
  664. width: 460upx;
  665. height: 100%;
  666. text-align: right;
  667. }
  668. .deliver-goods .wrapper .item .mode .iconfont {
  669. font-size: 30upx;
  670. margin-left: 13upx;
  671. }
  672. .deliver-goods .wrapper .item .mode .goods~.goods {
  673. margin-left: 30upx;
  674. }
  675. .deliver-goods .wrapper .item .mode .goods {
  676. color: #bbb;
  677. }
  678. .deliver-goods .wrapper .item .mode .goods.on {
  679. color: #477ef3;
  680. }
  681. .deliver-goods .wrapper .item .icon-up {
  682. position: absolute;
  683. font-size: 35upx;
  684. color: #2c2c2c;
  685. right: 30upx;
  686. }
  687. .deliver-goods .wrapper .item select {
  688. direction: rtl;
  689. padding-right: 60upx;
  690. position: relative;
  691. z-index: 2;
  692. }
  693. .deliver-goods .wrapper .item input::placeholder {
  694. color: #bbb;
  695. }
  696. .deliver-goods .confirm {
  697. font-size: 30upx;
  698. color: #fff;
  699. width: 100%;
  700. height: 80upx;
  701. background-color: #477ef3;
  702. text-align: center;
  703. line-height: 100upx;
  704. position: fixed;
  705. bottom: 0;
  706. }
  707. .select-box {
  708. flex: 1;
  709. height: 100%;
  710. .pickerBox {
  711. display: flex;
  712. align-items: center;
  713. justify-content: flex-end;
  714. width: 100%;
  715. height: 100%;
  716. }
  717. }
  718. .look {
  719. margin-left: 20rpx;
  720. color: #1890FF;
  721. }
  722. .textarea {
  723. display: block;
  724. min-height: 192rpx;
  725. padding: 30rpx;
  726. width: 100%;
  727. border-bottom: 1px solid #f0f0f0;
  728. font-size: 30rpx;
  729. }
  730. .icon-xiangji {
  731. font-size: 35rpx;
  732. color: #477ef3;
  733. }
  734. </style>