gjy 3 gadi atpakaļ
vecāks
revīzija
106a525a3d
100 mainītis faili ar 9459 papildinājumiem un 0 dzēšanām
  1. 20 0
      .hbuilderx/launch.json
  2. 129 0
      App.vue
  3. 80 0
      PacketCodeC.js
  4. 25 0
      README.md
  5. 171 0
      api/goods.js
  6. 178 0
      api/mock.js
  7. 80 0
      common/appUpdate.js
  8. 86 0
      common/helper.js
  9. 347 0
      components/APPPush/app_push.js
  10. 14 0
      components/APPPush/index.js
  11. 318 0
      components/master-keyboard/master-keyboard.scss
  12. 331 0
      components/master-keyboard/master-keyboard.vue
  13. 205 0
      components/me-tabs/me-tabs.vue
  14. 143 0
      components/ossutil/base64.js
  15. 9 0
      components/ossutil/config.js
  16. 178 0
      components/ossutil/crypto.js
  17. 34 0
      components/ossutil/hmac.js
  18. 79 0
      components/ossutil/sha1.js
  19. 394 0
      components/ossutil/signature.js
  20. 86 0
      components/ossutil/uploadFile.js
  21. 788 0
      components/upload.vue
  22. 10 0
      config/index.js
  23. 103 0
      demo.vue
  24. 20 0
      index.html
  25. BIN
      js_sdk/js-amap/__MACOSX/._amap-wx.130.js
  26. 31 0
      js_sdk/js-amap/amap-wx.130.js
  27. 272 0
      js_sdk/wa-permission/permission.js
  28. 41 0
      main.js
  29. 72 0
      manifest.json
  30. 233 0
      pages.json
  31. 61 0
      pages/goodSource/index.vue
  32. 139 0
      pages/goodSource/mescroll-swiper-item.vue
  33. 119 0
      pages/goodSource/shippingDetails.vue
  34. 35 0
      pages/mine/agency/agency.vue
  35. 213 0
      pages/mine/camera/camera.nvue
  36. 246 0
      pages/mine/camera/idcard/idcard.nvue
  37. 240 0
      pages/mine/camera/idphoto/idphoto.nvue
  38. 214 0
      pages/mine/camera/portrait/portrait.nvue
  39. 228 0
      pages/mine/camera/watermark/watermark.nvue
  40. 61 0
      pages/mine/cargoowner/cargoowner.vue
  41. 248 0
      pages/mine/cargoowner/editpersonalinformation.vue
  42. 531 0
      pages/mine/driverCertification.vue
  43. 329 0
      pages/mine/driverCertificationNext.vue
  44. 40 0
      pages/mine/helpDescription.vue
  45. 182 0
      pages/mine/index.vue
  46. 232 0
      pages/mine/manageBankCards/addBankCard.vue
  47. 20 0
      pages/mine/manageBankCards/editBankCard.vue
  48. 66 0
      pages/mine/manageBankCards/index.vue
  49. 57 0
      pages/mine/manageVehicles/addVehicle.vue
  50. 57 0
      pages/mine/manageVehicles/editVehicle.vue
  51. 95 0
      pages/mine/manageVehicles/index.vue
  52. 258 0
      pages/mine/set.vue
  53. 91 0
      pages/news/index.vue
  54. 164 0
      pages/order/confirmLoading.vue
  55. 164 0
      pages/order/confirmUnloading.vue
  56. 72 0
      pages/order/index.vue
  57. 139 0
      pages/order/mescroll-swiper-item.vue
  58. 135 0
      pages/order/orderDetails.vue
  59. 134 0
      pages/public/login.vue
  60. 208 0
      pages/public/register.vue
  61. 15 0
      public/Pinyin.js
  62. 77 0
      scrolldemo.vue
  63. 92 0
      static/css/common.scss
  64. 20 0
      static/css/font.css
  65. BIN
      static/icon_delete.png
  66. BIN
      static/icon_down.png
  67. BIN
      static/images/login/bg.png
  68. BIN
      static/images/login/bg@2x.png
  69. BIN
      static/images/login/bg@3x.png
  70. BIN
      static/images/login/bg_slices/bg.png
  71. BIN
      static/images/login/bg_slices/bg@2x.png
  72. BIN
      static/images/login/bg_slices/bg@3x.png
  73. BIN
      static/images/login/duihao2.png
  74. BIN
      static/images/login/duihao2@2x.png
  75. BIN
      static/images/login/duihao2@3x.png
  76. BIN
      static/images/login/guanbi@2x.png
  77. BIN
      static/images/login/logo.png
  78. BIN
      static/images/login/logo@2x.png
  79. BIN
      static/images/login/logo@3x.png
  80. BIN
      static/images/login/select.png
  81. BIN
      static/images/login/select@2x.png
  82. BIN
      static/images/login/select@3x.png
  83. BIN
      static/images/login/selected1.png
  84. BIN
      static/images/login/selected2.png
  85. BIN
      static/images/login/selected3.png
  86. BIN
      static/images/mine/saoma.png
  87. BIN
      static/images/myimg/LiangNong.png
  88. BIN
      static/images/myimg/LiangNong@2x.png
  89. BIN
      static/images/myimg/LiangNong@3x.png
  90. BIN
      static/images/myimg/LiangShang@2x.png
  91. BIN
      static/images/myimg/LiangShang@3x.png
  92. BIN
      static/images/myimg/SiJi.png
  93. BIN
      static/images/myimg/SiJi@2x.png
  94. BIN
      static/images/myimg/SiJi@3x.png
  95. BIN
      static/images/myimg/YongHu.png
  96. BIN
      static/images/myimg/YongHu@2x.png
  97. BIN
      static/images/myimg/YongHu@3x.png
  98. BIN
      static/images/myimg/erp.png
  99. BIN
      static/images/myimg/fabu@3x.png
  100. BIN
      static/images/myimg/gengduo1.png

+ 20 - 0
.hbuilderx/launch.json

@@ -0,0 +1,20 @@
+{ // launch.json 配置了启动调试时相关设置,configurations下节点名称可为 app-plus/h5/mp-weixin/mp-baidu/mp-alipay/mp-qq/mp-toutiao/mp-360/
+  // launchtype项可配置值为local或remote, local代表前端连本地云函数,remote代表前端连云端云函数
+    "version": "0.0",
+    "configurations": [{
+     	"app-plus" : 
+     	{
+     		"launchtype" : "local"
+     	},
+     	"default" : 
+     	{
+     		"launchtype" : "local"
+     	},
+     	"h5" : 
+     	{
+     		"launchtype" : "local"
+     	},
+     	"type" : "uniCloud"
+     }
+    ]
+}

+ 129 - 0
App.vue

@@ -0,0 +1,129 @@
+<style lang="scss">
+	/* 注意要写在第一行,同时给style标签加入lang="scss"属性 */
+	@import "@/uni_modules/uview-ui/index.scss";
+	@import 'static/css/common.scss';
+</style>
+<script>
+	import {
+		mapMutations
+	} from 'vuex';
+	import * as config from '@/config'
+	import appUpdate from 'common/appUpdate.js'
+	import app_push from './components/APPPush/app_push.js'
+	export default {
+		methods: {
+			...mapMutations(['login']),
+		},
+		onLaunch: function() {
+			uni.onTabBarMidButtonTap(()=>{
+				uni.navigateTo({
+					url: '/pages/card/card'
+			    });
+			})
+			// #ifdef APP-PLUS
+			let type = uni.getSystemInfoSync().platform
+			console.log(type)
+			if (type == "android") {
+				// appUpdate()
+			}
+			var that = this
+			plus.push.getClientInfoAsync((info) => {
+				var name = 'clientId'
+				var value = info.clientid
+				that.$store.commit('$uStore', {
+					name,
+					value
+				});
+				uni.setStorageSync("clientId", info.clientid)
+				console.log("info.clientid", info.clientid)
+			}, err => {});
+			// 监听在线消息事件  
+			plus.push.addEventListener("receive", function(msg) {
+				var title = msg.content.split(':')[0]
+				var content = msg.content.split(':')[1]
+
+				let params = {
+					inApp: true, // app内横幅提醒
+					voice: true, // 声音提醒
+					vibration: true, // 振动提醒
+					messageType: "",
+					messageTitle: title,
+					messageContent: content,
+					messageImage: 'https://taohaoliang.oss-cn-beijing.aliyuncs.com/app/logo.png'
+				}
+				console.log("msg", msg)
+				new app_push({
+					...params
+				}).show();
+				var userInfo = uni.getStorageSync("userInfo")
+				var that = this
+				that.$request.baseRequest('get', '/notice/query/noticeNumber').then(res => {
+					if (res.data.data) {
+						let name = 'myTip';
+						let value = res.data.data.task;
+						that.$store.commit('$uStore', {
+							name,
+							value
+						});
+						if (value != 0 && value) {
+							uni.setTabBarBadge({
+								index: 4,
+								text: value + ""
+							})
+						}
+						name = 'taskTip';
+						value = res.data.data.task;
+						that.$store.commit('$uStore', {
+							name,
+							value
+						});
+						// name = 'contractTip';
+						// value = res.data.data.contractTip;
+						// that.$store.commit('$uStore', {
+						// 	name,
+						// 	value
+						// });
+					}
+				})
+				//其它逻辑  
+			}, false);
+			//监听系统通知栏消息点击事件  
+			plus.push.addEventListener('click', function(msg) {
+				//处理点击消息的业务逻辑代码  
+				if (msg.content && msg.content.contains("任务")) {
+					uni.navigateTo({
+						url: '/pages/task/my_task'
+					})
+				} else if (msg.content && (msg.content.contains("合同") || msg.content.contains("交易"))) {
+					uni.navigateTo({
+						url: '/pageB/contract/contract'
+					})
+				}
+
+			}, false);
+			// #endif
+			this.$socket.initWebIM(this.$ws, true, true)
+			let userInfo = uni.getStorageSync('userInfo') || '';
+			if (userInfo.id) {
+				//更新登陆状态
+				uni.getStorage({
+					key: 'userInfo',
+					success: (res) => {
+						this.login(res.data);
+					}
+				});
+			}
+
+		},
+		onShow: function() {
+			console.log('App Show')
+		},
+		onHide: function() {
+			console.log('App Hide')
+		},
+	}
+</script>
+
+<style>
+	/*每个页面公共css */
+</style>

+ 80 - 0
PacketCodeC.js

@@ -0,0 +1,80 @@
+const PacketCodeC = {
+  encode (packet) {
+    let bytes = stringToBytes(JSON.stringify(packet))
+    let buffer = new ArrayBuffer(11 + bytes.length)
+    if (buffer.byteLength !== 11 + bytes.length) {
+      return null
+    }
+    let dataView = new DataView(buffer)
+
+    dataView.setInt32(0, 0x12345678)
+    dataView.setInt8(4, packet.version)
+    dataView.setInt8(5, 1) // 写死1表示json序列化
+    dataView.setInt8(6, packet.command)
+    dataView.setInt32(7, bytes.length)
+    for (let i = 11; i < bytes.length + 11; i++) {
+      dataView.setUint8(i, bytes[i - 11])
+    }
+    return dataView.buffer
+  },
+  decode (buffer) {
+    let dataView = new DataView(buffer)
+    let lenght = dataView.getInt32(7)
+    let bytes = []
+    for (let i = 11; i < lenght + 11; i++) {
+      bytes[i - 11] = dataView.getUint8(i)
+    }
+    let json = bytesToString(bytes)
+    return JSON.parse(json)
+  }
+}
+
+var stringToBytes = (str) => {
+  let bytes = []
+  let len, c
+  len = str.length
+  for (let i = 0; i < len; i++) {
+    c = str.charCodeAt(i)
+    if (c >= 0x010000 && c <= 0x10FFFF) {
+      bytes.push(((c >> 18) & 0x07) | 0xF0)
+      bytes.push(((c >> 12) & 0x3F) | 0x80)
+      bytes.push(((c >> 6) & 0x3F) | 0x80)
+      bytes.push((c & 0x3F) | 0x80)
+    } else if (c >= 0x000800 && c <= 0x00FFFF) {
+      bytes.push(((c >> 12) & 0x0F) | 0xE0)
+      bytes.push(((c >> 6) & 0x3F) | 0x80)
+      bytes.push((c & 0x3F) | 0x80)
+    } else if (c >= 0x000080 && c <= 0x0007FF) {
+      bytes.push(((c >> 6) & 0x1F) | 0xC0)
+      bytes.push((c & 0x3F) | 0x80)
+    } else {
+      bytes.push(c & 0xFF)
+    }
+  }
+  return bytes
+}
+
+var bytesToString = (bytes) => {
+  if (typeof bytes === 'string') {
+    return bytes
+  }
+  let str = ''
+  let _arr = bytes
+  for (let i = 0; i < _arr.length; i++) {
+    let one = _arr[i].toString(2)
+    let v = one.match(/^1+?(?=0)/)
+    if (v && one.length === 8) {
+      let bytesLength = v[0].length
+      let store = _arr[i].toString(2).slice(7 - bytesLength)
+      for (let st = 1; st < bytesLength; st++) {
+        store += _arr[st + i].toString(2).slice(2)
+      }
+      str += String.fromCharCode(parseInt(store, 2))
+      i += bytesLength - 1
+    } else {
+      str += String.fromCharCode(_arr[i])
+    }
+  }
+  return str
+}
+export default PacketCodeC

+ 25 - 0
README.md

@@ -0,0 +1,25 @@
+# uniapp开发模板
+
+#### 介绍
+uni-app项目开发模板,集成了u-view 2.0、基于uni-request封装、token验证、websocket、页面权限、按钮权限、mescoll上拉加载、下拉刷新、热更新、推送
+#### 常用u-view组件及方法
+常用view功能在根目录demo页面
+#### 公共样式
+常用css公共变量在 uni.scss和uni_modules\uview-ui目录下的theme.scss, 全局公共样式可以在theme.scss文件配置,也可以在static文件夹common.scss 配置
+全局样式包括但不限于内容布局、文字大小、颜色、公共组件css。
+常用css样式配置在common.scss文件中,常用flex布局、常用对齐方式、常用内边距、外边距
+#### 图片上传和拍照上传
+点击按钮上传文件
+import uploadImage from '@/components/ossutil/uploadFile.js';
+	uni.chooseImage({
+				    count: 1, 
+				    success: function (res) {
+				        console.log(JSON.stringify(res.tempFilePaths));
+						uploadImage(res.tempFilePaths[0], 'appData/',
+							result => {
+								// 上传成功
+								console.log('图片地址', result)
+							}
+						)
+				    }
+				});

+ 171 - 0
api/goods.js

@@ -0,0 +1,171 @@
+const goods = [{
+	"id": "1",
+	"goodImg": "https://www.mescroll.com/demo/res/img/pd1.jpg",
+	"goodName": "【1】  六罐装荷兰美素佳儿金装2段900g",
+	"goodPrice": 1149.00,
+	"goodSold": 648
+}, {
+	"id": "2",
+	"goodImg": "https://www.mescroll.com/demo/res/img/pd2.jpg",
+	"goodName": "【2】  韩国Amore爱茉莉红吕洗发水套装修复受损发质",
+	"goodPrice": 89.00,
+	"goodSold": 128
+}, {
+	"id": "3",
+	"goodImg": "https://www.mescroll.com/demo/res/img/pd3.jpg",
+	"goodName": "【3】  Friso美素佳儿 金装婴儿配方奶粉3段900g",
+	"goodPrice": 195.00,
+	"goodSold": 968
+}, {
+	"id": "4",
+	"goodImg": "https://www.mescroll.com/demo/res/img/pd4.jpg",
+	"goodName": "【4】  Fisher goodPrice费雪 费雪三轮儿童滑行车",
+	"goodPrice": 299.00,
+	"goodSold": 85
+}, {
+	"id": "5",
+	"goodImg": "https://www.mescroll.com/demo/res/img/pd5.jpg",
+	"goodName": "【5】  Babylee巴布力 实木婴儿床 雷卡拉130*70cm",
+	"goodPrice": 1889.00,
+	"goodSold": 18
+}, {
+	"id": "6",
+	"goodImg": "https://www.mescroll.com/demo/res/img/pd6.jpg",
+	"goodName": "【6】  Pigeon贝亲 独立三层奶粉盒 送小罐奶粉1段200g",
+	"goodPrice": 70.00,
+	"goodSold": 658
+}, {
+	"id": "7",
+	"goodImg": "https://www.mescroll.com/demo/res/img/pd7.jpg",
+	"goodName": "【7】 TTBOO兔兔小布 肩纽扣套装",
+	"goodPrice": 268.00,
+	"goodSold": 128
+}, {
+	"id": "8",
+	"goodImg": "https://www.mescroll.com/demo/res/img/pd8.jpg",
+	"goodName": "【8】  Nuna璐拉 婴儿布里奇果精纯嫩肤沐浴露婴儿精纯芦荟胶",
+	"goodPrice": 140.00,
+	"goodSold": 366
+}, {
+	"id": "9",
+	"goodImg": "https://www.mescroll.com/demo/res/img/pd9.jpg",
+	"goodName": "【9】  illuma启赋 奶粉3段900g",
+	"goodPrice": 252.00,
+	"goodSold": 98
+}, {
+	"id": "10",
+	"goodImg": "https://www.mescroll.com/demo/res/img/pd10.jpg",
+	"goodName": "【10】  Abbott雅培乳蛋白部分水解婴儿配方奶粉3段820g",
+	"goodPrice": 89.00,
+	"goodSold": 128
+}, {
+	"id": "11",
+	"goodImg": "https://www.mescroll.com/demo/res/img/pd11.jpg",
+	"goodName": "【11】  韩蜜 酷炫唇蜜(礼盒套装)2.8g*4",
+	"goodPrice": 179.00,
+	"goodSold": 35
+}, {
+	"id": "12",
+	"goodImg": "https://www.mescroll.com/demo/res/img/pd12.jpg",
+	"goodName": "【12】  保税区直发【3包装】日本Merries花王纸尿裤NB90",
+	"goodPrice": 289.00,
+	"goodSold": 1928
+}, {
+	"id": "13",
+	"goodImg": "https://www.mescroll.com/demo/res/img/pd13.jpg",
+	"goodName": "【13】  Comotomo可么多么 硅胶奶瓶(0-3月奶嘴)150ml绿色",
+	"goodPrice": 203.00,
+	"goodSold": 87
+}, {
+	"id": "14",
+	"goodImg": "https://www.mescroll.com/demo/res/img/pd14.jpg",
+	"goodName": "【14】  香港直邮德国瑞德露Rival de Loop芦荟精华安瓶",
+	"goodPrice": 152.00,
+	"goodSold": 61
+}, {
+	"id": "15",
+	"goodImg": "https://www.mescroll.com/demo/res/img/pd15.jpg",
+	"goodName": "【15】  保税区直发药师堂尊马油香草味温和保湿无刺激面霜",
+	"goodPrice": 269.00,
+	"goodSold": 73
+}, {
+	"id": "16",
+	"goodImg": "https://www.mescroll.com/demo/res/img/pd16.jpg",
+	"goodName": "【16】  香港直邮日本Spatreatment眼膜保湿去细纹法令纹",
+	"goodPrice": 219.00,
+	"goodSold": 13
+}, {
+	"id": "17",
+	"goodImg": "https://www.mescroll.com/demo/res/img/pd17.jpg",
+	"goodName": "【17】  韩国MEDIHEALNMF可莱丝针剂睡眠面膜",
+	"goodPrice": 81.00,
+	"goodSold": 128
+}, {
+	"id": "18",
+	"goodImg": "https://www.mescroll.com/demo/res/img/pd18.jpg",
+	"goodName": "【18】  DHC蝶翠诗橄榄蜂蜜滋养洗脸手工皂90g",
+	"goodPrice": 123.00,
+	"goodSold": 77
+}, {
+	"id": "19",
+	"goodImg": "https://www.mescroll.com/demo/res/img/pd19.jpg",
+	"goodName": "【19】  日本资生堂CPB肌肤之钥新版隔离霜 清爽型 30ml",
+	"goodPrice": 429.00,
+	"goodSold": 36
+}, {
+	"id": "20",
+	"goodImg": "https://www.mescroll.com/demo/res/img/pd20.jpg",
+	"goodName": "【20】 Heinz亨氏 婴儿面条优加面条全素套餐组合3口味3盒",
+	"goodPrice": 39.00,
+	"goodSold": 61
+}, {
+	"id": "21",
+	"goodImg": "https://www.mescroll.com/demo/res/img/pd21.jpg",
+	"goodName": "【21】  Heinz亨氏 乐维滋果汁泥组合5口味15袋",
+	"goodPrice": 69.00,
+	"goodSold": 55
+}, {
+	"id": "22",
+	"goodImg": "https://www.mescroll.com/demo/res/img/pd22.jpg",
+	"goodName": "【22】  保税区直发澳大利亚Swisse高浓度蔓越莓胶囊30粒",
+	"goodPrice": 271.00,
+	"goodSold": 19
+}, {
+	"id": "23",
+	"goodImg": "https://www.mescroll.com/demo/res/img/pd23.jpg",
+	"goodName": "【23】  挪威Nordic Naturals小鱼婴幼儿鱼油DHA滴剂",
+	"goodPrice": 102.00,
+	"goodSold": 125
+}, {
+	"id": "24",
+	"goodImg": "https://www.mescroll.com/demo/res/img/pd24.jpg",
+	"goodName": "【24】  澳大利亚Bio island DHA for Pregnancy海藻油DHA",
+	"goodPrice": 289.00,
+	"goodSold": 28
+}, {
+	"id": "25",
+	"goodImg": "https://www.mescroll.com/demo/res/img/pd25.jpg",
+	"goodName": "【25】  澳大利亚Fatblaster Coconut Detox椰子水",
+	"goodPrice": 152.00,
+	"goodSold": 17
+}, {
+	"id": "26",
+	"goodImg": "https://www.mescroll.com/demo/res/img/pd26.jpg",
+	"goodName": "【26】  Suitsky舒比奇 高护极薄舒爽纸尿片尿不湿XL60",
+	"goodPrice": 99.00,
+	"goodSold": 181
+}, {
+	"id": "27",
+	"goodImg": "https://www.mescroll.com/demo/res/img/pd27.jpg",
+	"goodName": "【27】  英国JUST SOAP手工皂 玫瑰天竺葵蛋糕皂",
+	"goodPrice": 72.00,
+	"goodSold": 66
+}, {
+	"id": "28",
+	"goodImg": "https://www.mescroll.com/demo/res/img/pd28.jpg",
+	"goodName": "【28】  德国NUK 多色婴幼儿带盖学饮杯",
+	"goodPrice": 92.00,
+	"goodSold": 138
+}]
+
+export default goods;

+ 178 - 0
api/mock.js

@@ -0,0 +1,178 @@
+/*
+本地模拟接口请求, 仅demo演示用.
+实际项目以您服务器接口返回的数据为准,无需本地处理分页.
+请参考官方写法: https://www.mescroll.com/uni.html?v=20200210#tagUpCallback
+* */
+
+// 模拟数据
+import goods from "./goods.js";
+
+// 获取新闻列表
+export function apiNewList(pageNum, pageSize) {
+	return new Promise((resolute, reject)=>{
+		//延时一秒,模拟联网
+		setTimeout(function() {
+			try {
+				let list = [];
+				if (!pageNum) {
+					//模拟下拉刷新返回的数据
+					let id=new Date().getTime();
+					let newObj = {
+						id:id,
+						title: "【新增新闻" + id + "】 标题",
+						content: "新增新闻的内容"
+					};
+					list.push(newObj);
+				} else {
+					//模拟上拉加载返回的数据
+					for (let i = 0; i < pageSize; i++) {
+						let upIndex = (pageNum - 1) * pageSize + i + 1;
+						let newObj = {
+							id:upIndex,
+							title: "【新闻" + upIndex + "】 标题标题标题标题标题",
+							content: "内容内容内容内容内容内容内容内容内容"
+						};
+						list.push(newObj);
+					}
+					console.log("page.num=" + pageNum + ", page.size=" + pageSize + ", curPageData.length=" + list.length);
+				}
+				//模拟接口请求成功
+				resolute(list);
+			} catch (e) {
+				//模拟接口请求失败
+				reject(e);
+			}
+		}, 1000)
+	})
+}
+
+// 搜索商品
+export function apiGoods(pageNum, pageSize, keyword) {
+	return new Promise((resolute, reject)=>{
+		//延时一秒,模拟联网
+		setTimeout(()=> {
+			try{
+				let data = {
+					list: [], // 数据列表
+					totalCount: 0, // 总数量
+					totalPage: 0, // 总页数
+					hasNext: false // 是否有下一页
+				}
+				
+				// 符合关键词的记录
+				let keywordList = [];
+				if (!keyword || keyword == "推荐"||keyword == "全部") {
+					// 搜索全部商品
+					keywordList = goods;
+				}else{
+					// 关键词搜索
+					if(keyword=="按时间"||keyword=="未发运") keyword="婴"; // 为这个关键词展示多几条数据
+					for (let i = 0; i < goods.length; i++) {
+						let good = goods[i]
+						if (good.goodName.indexOf(keyword) !== -1) {
+							keywordList.push(good)
+						}
+					}
+				}
+				
+				// 分页
+				for (let i = (pageNum - 1) * pageSize; i < pageNum * pageSize; i++) {
+					if (i >= keywordList.length) break
+					data.list.push(keywordList[i])
+				}
+				
+				// 汇总数据
+				data.totalCount = keywordList.length;
+				data.totalPage = Math.ceil(data.totalCount/pageSize);
+				data.hasNext = pageNum < data.totalPage
+				
+				//模拟接口请求成功
+				console.log("pageNum=" + pageNum + ", pageSize=" + pageSize + ", data.list.length=" + data.list.length + ", totalCount=" + data.totalCount + ", totalPage=" + data.totalPage + ", hasNext=" + data.hasNext + (keyword ? ", keyword=" + keyword : ""));
+				resolute(data);
+			} catch (e) {
+				//模拟接口请求失败
+				reject(e);
+			}
+		},1000)
+	})
+}
+
+// 获取微博列表
+export function apiWeiboList(pageNum, pageSize) {
+	return new Promise((resolute, reject)=>{
+		//延时2秒,模拟联网
+		setTimeout(function() {
+			try {
+				let list = [];
+				if(!pageNum){
+					//此处模拟下拉刷新返回的数据
+					let id=new Date().getTime();
+					let newObj={id:id, title:"【新增微博"+id+"】 新增微博", content:"新增微博的内容,新增微博的内容"};
+					list.push(newObj);
+				}else{
+					//此处模拟上拉加载返回的数据
+					for (let i = 0; i < pageSize; i++) {
+						let upIndex=(pageNum-1)*pageSize+i+1;
+						let newObj={id:upIndex, title:"【微博"+upIndex+"】 标题标题标题标题标题标题", content:"内容内容内容内容内容内容内容内容内容内容"};
+						list.push(newObj);
+					}
+					console.log("page.num=" + pageNum + ", page.size=" + pageSize + ", curPageData.length=" + list.length);
+				}
+				//模拟接口请求成功
+				resolute(list);
+			} catch (e) {
+				//模拟接口请求失败
+				reject(e);
+			}
+		}, 2000)
+	})
+}
+
+
+// 获取消息列表(共5页消息)
+export function apiMsgList(pageNum, pageSize) {
+	return new Promise((resolute, reject)=>{
+		//延时一秒,模拟联网
+		setTimeout(function() {
+			try {
+				let list = [];
+				//模拟下拉加载更多记录
+				for (let i = 0; i < pageSize; i++) {
+					let msgId = (pageNum - 1) * pageSize + i + 1;
+					let newObj = {
+						id: msgId,
+						title: "【消息" + msgId + "】",
+						content: "内容: 下拉获取聊天记录"
+					};
+					// 此处模拟只有5页的消息 (第5页只有3条)
+					if(pageNum>=5 && i>=3){}else{
+						list.unshift(newObj);
+					}
+				}
+				console.log("page.num=" + pageNum + ", page.size=" + pageSize + ", curPageData.length=" + list.length);
+				//模拟接口请求成功
+				resolute(list);
+			} catch (e) {
+				//模拟接口请求失败
+				reject(e);
+			}
+		}, 1000)
+	})
+}
+
+// 获取tabs类目
+export function apiGetTabs() {
+	return new Promise((resolute, reject)=>{
+		//延时,模拟联网
+		setTimeout(function() {
+			try {
+				let tabs = ['推荐', '按时间', '按距离', '运费先付', '果汁', '奶瓶', '美素', '花王', '韩蜜', '口红', '毛巾', '玩具', '衣服'];
+				//模拟接口请求成功
+				resolute(tabs);
+			} catch (e) {
+				//模拟接口请求失败
+				reject(e);
+			}
+		}, 10)
+	})
+}

+ 80 - 0
common/appUpdate.js

@@ -0,0 +1,80 @@
+
+//APP更新
+
+import * as config from '../config'
+export default function appUpdate() {
+		
+	let baseUrlNew = config.def().baseUrlNew
+	uni.request({
+	    url: baseUrlNew + '/appVersion/selectInfo',
+	    data: {
+	    	appid: plus.runtime.appid,
+	    	version: plus.runtime.version,
+	    	imei: "1"
+	    },
+	    method: 'GET',
+	    success: (res) => {			
+	    	if (res.statusCode === 200) {
+				console.log("uni.request update success",res)
+				plus.runtime.getProperty(plus.runtime.appid, function(wgtinfo) {
+					let client_version = wgtinfo.version
+					var flag_update = client_version.split(".").splice(0, 2).join(".") != res.data.data.version.split(".").splice(0, 2)
+						.join(".")
+					var flag_hot = (Number(client_version.split(".")[2]) < Number(res.data.data.version.split(".")[2])) & !flag_update
+					console.log("client_version",client_version) 
+					console.log("flag_update",flag_update)
+					console.log("flag_hot",flag_hot)
+				
+					if (flag_update) {
+						console.log("更新弹窗")
+						// 提醒用户更新
+						uni.showModal({
+							title: '更新提示',
+							content: res.data.data.note,
+							success: (showResult) => {
+								if (showResult.confirm) {
+									plus.nativeUI.toast("正在准备环境,请稍后!");
+									console.log(res.data.data.url, )
+									var dtask = plus.downloader.createDownload(res.data.data.url, {
+										method: 'GET',
+										filename: '_doc/update/'
+									}, function(d, status) {
+										if (status == 200) {
+											var path = d.filename; //下载apk
+											plus.runtime.install(path); // 自动安装apk文件
+										} else {
+											plus.nativeUI.alert('版本更新失败:' + status);
+										}
+									});
+									dtask.start();
+								}
+							}
+						})
+					} else if (flag_hot) {
+						console.log("热更新") 
+						uni.downloadFile({
+							url: res.data.data.wgtUrl,
+							success: (downloadResult) => {
+								console.log(downloadResult.tempFilePath)
+								if (downloadResult.statusCode === 200) {
+									plus.nativeUI.toast(`正在热更新!${res.data.data.versionCode}`);
+									plus.runtime.install(downloadResult.tempFilePath, {
+										force: false
+									}, function() {
+										plus.nativeUI.toast("热更新成功");
+										plus.runtime.restart();
+									}, function(e) {
+										console.log(e)
+										plus.nativeUI.toast(`热更新失败:${e.message}`);
+									});
+								}
+							}
+						});
+					}
+				
+				});
+	    	}
+	    }
+	})
+
+}

+ 86 - 0
common/helper.js

@@ -0,0 +1,86 @@
+import * as config from '../config'
+const rolesList = []
+const ossUploadUrl = 'https://taohaoliang.oss-cn-beijing.aliyuncs.com/';
+const chooseImage = {
+	count: '1',
+	sizeType: ['original', 'compressed'],
+	sourceType: ['album'],
+}
+const imgType = '请选择图片来源'
+const imgTypeList = [{
+			name: '相册',
+		},
+		{
+			name: '拍照',
+		}
+	]
+	const getListByUserId = function() {
+		let baseUrlNew = config.def().baseUrlNew
+		var userInfo = uni.getStorageSync("userInfo")
+		console.log("------", userInfo)
+		if (userInfo) {
+			uni.request({
+				url: baseUrlNew + '/roleMenu/query/getListByUserId',
+				data: {
+					userId: userInfo.id ? userInfo.id : userInfo.data.id
+				},
+				method: 'GET',
+				success: (res) => {
+					if (res.statusCode === 200) {
+						uni.setStorageSync("jurisdiction", res.data.data)
+						let list = getUserAllRoles(res.data.data);
+						uni.setStorageSync("rolesList", list)
+
+					}
+				}
+			})
+		}
+	}
+const getUserAllRoles = (item) => {
+	console.log(item)
+
+	for (let i = 0; i < item.length; i++) {
+		rolesList.push(item[i].name)
+		// console.log('用户权限',rolesList)
+		if (item[i].children && item[i].children.length > 0) {
+			getUserAllRoles(item[i].children)
+		}
+	}
+	return rolesList;
+}
+const setAudit = (item) => {
+	let _list = uni.getStorageSync("copyTaskInfo")
+	let _isShowbtn = true
+	if (_list.length == 0) {
+		_isShowbtn = false
+	}
+	for (let i = 0; i < _list.length; i++) {
+		if (_list[i].businessId == item.id) {
+			_list.splice(i, 1)
+			uni.setStorageSync("copyTaskInfo", _list)
+		}
+	}
+	if (_list.length > 0) {
+		uni.navigateTo({
+			url: _list[0].itemUrl + '&isShowbtn=' + _isShowbtn,
+		})
+	}
+	console.log(item)
+}
+const contactCustomerService = (item) => {
+	console.log(item)
+	console.log("联系客服")
+	uni.makePhoneCall({
+		phoneNumber: '114' //仅为示例
+	});
+
+}
+export default {
+	getListByUserId,
+	setAudit,
+	ossUploadUrl,
+	contactCustomerService,
+	chooseImage,
+	imgType,
+	imgTypeList
+}

+ 347 - 0
components/APPPush/app_push.js

@@ -0,0 +1,347 @@
+export class appPush{
+	constructor(option = {}) {
+		console.log("appPush",option)
+		// app内横幅提醒
+		this.inApp = option.inApp;
+		// 声音提醒
+		this.voice = option.voice;
+		// 振动提醒
+		this.vibration = option.vibration;
+		// 消息分类
+		this.messageType = option.messageType || '';
+		// 通知标题
+		this.messageTitle = option.messageTitle || '';
+		// 时间
+		this.messageTime = option.messageTime || '现在';
+		// 通知文案
+		this.messageContent = option.messageContent || '';
+		// 缩略图
+		this.messageImage = option.messageImage || '';	
+		
+		
+	    this.screenWidth = plus.screen.resolutionWidth;
+	    this.screenHeight = plus.screen.resolutionHeight;
+	    // 比例
+	    this.propotation = this.screenWidth / 750
+	    //弹窗容器宽度
+	    this.popupViewWidth = this.propotation * 710;
+	    // 弹窗容器高度
+	    this.popupViewHeight = this.propotation * 152;
+	    // 弹窗容器的Padding
+	    this.viewContentPadding = this.propotation * 30;
+		// 弹框容器的宽度
+		this.viewContentWidth = parseInt(this.popupViewWidth - (this.viewContentPadding * 2))
+		// 弹框到顶部的距离
+		this.system = uni.getSystemInfoSync()
+		// 过度时间
+		this.duration = 200
+		// 关闭时间
+		this.closeTime = 10000
+		
+		console.log(this.inApp, this.voice, this.vibration)
+		
+		this.top = (this.propotation * 20) + this.system.statusBarHeight;
+		this.initTop = -this.system.statusBarHeight
+		
+		this.body = null;
+		this.bodyBg = null;
+		this.timer = null;
+		
+		this.flag = false
+		this.cur = {
+			x: 0,
+			y: 0,
+			pageX: 0,
+			pageY: 0
+		}
+		
+	}
+	
+	// 生成弹框主体
+	createView() {
+		console.log((this.propotation * 20) + this.system.statusBarHeight+ '--------------')
+		let view = new plus.nativeObj.View('popupView', {
+			// tag: 'rect',
+			top: (this.propotation * 20) + this.system.statusBarHeight,
+			left: this.propotation * 20,
+			height: this.popupViewHeight,
+			width: this.popupViewWidth
+		})
+		// 绘制白色背景
+		view.drawRect({
+			color:"#626262",
+			radius:"10px"
+		})
+		let viewContentList = [
+			// {
+			// 	src: '/static/push/message-icon.png',
+			// 	id: 'icon',
+			// 	tag: 'img',
+			// 	position: {
+			// 		top: this.viewContentPadding + "px",
+			// 		left: this.viewContentPadding + "px",
+			// 		width: (this.propotation * 24) + 'px',
+			// 		height: (this.propotation * 24) + 'px',
+			// 	}
+			// },
+			// {
+			// 	tag: 'font',
+			// 	id: 'pop-title',
+			// 	text: this.messageType,
+			// 	textStyles: {
+			// 		size: (this.propotation * 24) + 'px',
+			// 		align: "left",
+			// 		color: "#4F555B"
+			// 	},
+			// 	position: {
+			// 		top: this.viewContentPadding + "px",
+			// 		left: (this.propotation * 64) + 'px',
+			// 		height: (this.propotation * 24) + 'px',
+			// 		width: this.viewContentWidth + "px",
+			// 	}
+			// },
+			// {
+			// 	tag: 'font',
+			// 	id: 'time',
+			// 	text: this.messageTime,
+			// 	textStyles: {
+			// 		size: (this.propotation * 24) + 'px',
+			// 		align: "right",
+			// 		color: "#4F555B"
+			// 	},
+			// 	position: {
+			// 		top: this.viewContentPadding + "px",
+			// 		left: this.viewContentPadding + "px",
+			// 		height: (this.propotation * 24) + 'px',
+			// 		width: this.viewContentWidth + "px",
+			// 	}
+			// },
+			{
+				tag: 'font',
+				id: 'push-title',
+				text: this.messageTitle,
+				textStyles: {
+					size: (this.propotation * 35) + 'px',
+					align: "left",
+					color: "#f7f7f7",
+					overflow: "ellipsis"
+				},
+				position: {
+					top: this.viewContentPadding + 'px',
+					left: (this.propotation * 30) + 'px',
+					height: (this.propotation * 35) + 'px',
+					width: (this.propotation * 505) + 'px',
+				}
+			},
+			{
+				tag: 'font',
+				id: 'push-content',
+				text: this.messageContent,
+				textStyles: {
+					size: (this.propotation * 28) + 'px',
+					align: "left",
+					color: "#f7f7f7",
+					overflow: "ellipsis"
+				},
+				position: {
+					top: (this.propotation * 90) + 'px',
+					left: (this.propotation * 30) + 'px',
+					height: (this.propotation * 28) + 'px',
+					width: (this.propotation * 655) + 'px',
+				}
+			},
+			// {
+			// 	src: this.messageImage,
+			// 	id: 'image',
+			// 	tag: 'img',
+			// 	position: {
+			// 		top: (this.propotation * 68) + 'px',
+			// 		// right: "0px",
+			// 		left: (this.propotation * 586) + 'px',
+			// 		width: (this.propotation * 100) + 'px',
+			// 		height: (this.propotation * 100) + 'px',
+			// 	}
+			// },
+			// {
+			// 	src: '/static/push/img-bg.png',
+			// 	id: 'img-bg',
+			// 	tag: 'img',
+			// 	position: {
+			// 		top: (this.propotation * 68) + 'px',
+			// 		// right: "0px",
+			// 		left: (this.propotation * 586) + 'px',
+			// 		width: (this.propotation * 100) + 'px',
+			// 		height: (this.propotation * 100) + 'px',
+			// 	}
+			// },
+		]
+		view.draw(viewContentList)
+		// view.addEventListener("click",(e)=>{
+		// 	console.log('---------------------')
+		// });
+		view.addEventListener("touchstart", (event) => {
+			// console.log(event)
+			this.flag = true;  
+			var touch;  
+			if (event.touches) {  
+				touch = event.touches[0];  
+			} else {  
+				touch = event;  
+			}  
+			this.cur.x = touch.clientX;  
+			this.cur.y = touch.clientY;
+			this.cur.pageX = touch.pageX;
+			this.cur.pageY = touch.pageY;  
+		})
+		view.addEventListener("touchmove", (event) => {
+			// console.log(e)
+			var touch;  
+			if (event.touches) {  
+				touch = event.touches[0];  
+			} else {  
+				touch = event;
+			}  
+			let moveX = touch.pageX - this.cur.x;   
+			let moveY = touch.pageY - this.cur.y;   
+			let x = moveX;  
+			let y = moveY;
+			// console.log(x, y)
+			// console.log(this.cur, touch)
+			if (x < 0) {  
+				// x = 0;  
+			} else if (x > (this.popupViewWidth - this.popupViewWidth)) {  
+				// x = this.screenWidth - 40;  
+			}  
+			if (y < 0) {  
+				// y = 0;  
+			} else if (y >= ((this.propotation * 20) + this.system.statusBarHeight)) {  
+				y = ((this.propotation * 20) + this.system.statusBarHeight);  
+			}  
+			this.body.setStyle({  
+				top: y + 'px',  
+				left: x + 'px'  
+			});
+		})
+		/**
+		 * 这里有一个bug暂时无法解决,当用户快速往左滑时,滑动区域超出屏幕会监听不到touchend事件😂,很难被发现我就不解决了
+		 */
+		view.addEventListener("touchend", (event) => {
+			// console.log(this.cur, event)
+			var touch;
+			if (event.touches) {  
+				touch = event.touches[0];  
+			} else {  
+				touch = event;  
+			}
+			let differX = Math.abs(this.cur.pageX) - Math.abs(touch.pageX)
+			let differY = Math.abs(this.cur.pageY) - Math.abs(touch.pageY)
+			this.flag = false
+			// console.log(differX, differY)
+			if(Math.abs(differX) > 5 || Math.abs(differY) > 5) {	// 上下移动或左右移动超过5px则关闭弹窗
+				this.hide()
+			} else {	// 否则当作单击事件
+				console.log('-------------------')
+				this.hide()
+			}
+		})
+		this.body = view;
+		
+	// 	let bodyBg = new plus.nativeObj.View('bodyBg',{
+	// 		top: (this.propotation * 20) + this.system.statusBarHeight,
+	// 		left: this.propotation * 20,
+	// 		height: this.popupViewHeight,
+	// 		width: this.popupViewWidth,
+	// 		backgroundColor:'rgba(0, 0, 0, 1)',
+	// 	});
+	// 	bodyBg.draw([
+	// 	  {tag:'font',id:'confirm',text:'关闭关闭',textStyles:{color:'red',size:'16px'}},
+	// 	]);
+	
+	// 	bodyBg.addEventListener("click",(e)=>{
+	// 		console.log('---------------------')
+	// 	});
+	// 	this.bodyBg = bodyBg
+	}
+	// 显示/关闭弹框动画
+	modelAnimationOpenOrClose(type) {
+		var options = {type:type,duration:this.duration};
+		plus.nativeObj.View.startAnimation(options,this.body, () => {
+			// 关闭原生动画
+			plus.nativeObj.View.clearAnimation();
+		});
+	}
+	bgAnimationOpenOrClose(type) {
+		var options = {type:type,duration:this.duration};
+		plus.nativeObj.View.startAnimation(options,this.bodyBg, () => {
+			// 关闭原生动画
+			plus.nativeObj.View.clearAnimation();
+		});
+	}
+	// closeAnimation() {
+	// 	// push弹框距离最顶部的距离
+	// 	let top = (this.propotation * 20) + this.system.statusBarHeight
+	// 	// 完全隐藏时的顶部距离
+	// 	let hideTop = -this.system.statusBarHeight
+	// 	this.timer = setInterval(() => {
+	// 		this.top = this.top - 2
+	// 		if(this.top < hideTop * 2) {
+	// 			clearInterval(this.timer)
+	// 			this.timer = null
+	// 		}
+	// 		this.body.setStyle({
+	// 			top:this.top
+	// 		})
+	// 	}, 1)
+	// }
+	// 显示弹框
+	show() {
+		this.tips()
+		if(this.inApp) {
+			this.createView()
+			// this.modelAnimationOpenOrClose('slide-in-right')
+			this.body.show()
+			// this.bodyBg.show()
+			setTimeout(() => {
+				if(this.body) {
+					this.hide()
+				}
+			}, this.closeTime)
+		}
+	}
+	// 关闭弹框
+	hide() {
+		this.modelAnimationOpenOrClose('slide-out-right')
+		this.body.hide()
+		setTimeout(() => {
+			plus.nativeObj.View.clearAnimation();
+			this.body = null
+		}, this.duration)
+		// this.bgAnimationOpenOrClose('slide-out-right')
+		// this.bodyBg.hide()
+	}
+	// 调用系统提示音和振动
+	tips() {
+		if(this.voice) {
+			let system = uni.getSystemInfoSync().platform
+			if(system == 'ios') {
+				let player = plus.audio.createPlayer( "/static/audio/ios.mp3" );
+				player.play()
+			} else {
+				let main = plus.android.runtimeMainActivity();
+				let RingtoneManager = plus.android.importClass("android.media.RingtoneManager");
+				let uri = RingtoneManager.getActualDefaultRingtoneUri(main, RingtoneManager.TYPE_NOTIFICATION);
+				console.log(uri)
+				let MediaPlayer = plus.android.importClass("android.media.MediaPlayer");  
+				let player = MediaPlayer.create(main, uri);  
+				player.setLooping(false);  
+				player.prepare();  
+				player.start();
+			}
+		}
+		if(this.vibration) {
+			plus.device.vibrate()
+		}
+	}
+}
+
+export default appPush

+ 14 - 0
components/APPPush/index.js

@@ -0,0 +1,14 @@
+import app_push from './app_push.js'
+
+const appPush = {
+	install: function(Vue) {
+		Vue.prototype.$appPush = function(op = {}) {
+			console.log("进入appPush")
+			new app_push({
+				...op
+			}).show();
+		}
+	}
+}
+
+export default appPush

+ 318 - 0
components/master-keyboard/master-keyboard.scss

@@ -0,0 +1,318 @@
+.master_wrap{
+	width: 100%;
+	background-color: #eee;
+	position: fixed;
+	bottom: 0;
+	left: 0;
+	z-index:10000;
+	padding-top: 10rpx;
+	padding-bottom: 20rpx;
+	.down_wrap{
+		width: 100%;
+		height: 50rpx;
+		display: flex;
+		align-items: center;
+		justify-content: center;
+		image{
+			width: 48rpx;
+			height: 48rpx;
+		}
+	}
+	.number_next{
+		width: 100%;
+		height: 80rpx;
+		margin-top: 10rpx;
+		background-color: white;
+		border-radius: 10rpx;
+		text-align: center;
+		line-height: 80rpx;
+		box-sizing: border-box;
+		display: block;
+	}
+	.kerboard_number{
+		width: 100%;
+		display: flex;
+		justify-content: space-evenly;
+		flex-flow: wrap;
+		.number_item{
+			width: 30%;
+			height: 80rpx;
+			margin-top: 10rpx;
+			background-color: white;
+			border-radius: 10rpx;
+			text-align: center;
+			line-height: 80rpx;
+			box-sizing: border-box;
+			display: block;
+		}
+		.number_item_active{
+			width: 30%;
+			height: 80rpx;
+			margin-top: 10rpx;
+			background-color: #888;
+			border-radius: 10rpx;
+			text-align: center;
+			line-height: 80rpx;
+			box-sizing: border-box;
+			display: block;
+			color: white;
+		}
+		.number_empty{
+			background-color: #eeeeee;
+			width: 30%;
+			height: 80rpx;
+			margin-top: 10rpx;
+			border-radius: 10rpx;
+		}
+		.number_empty_active{
+			background-color: #eeeeee;
+		}
+		.number_delete{
+			width: 30%;
+			height: 80rpx;
+			margin-top: 10rpx;
+			background-color: white;
+			display: flex;
+			justify-content: center;
+			align-items: center;
+			.delete_img{
+				width: 65rpx;
+				height: 64rpx;
+			}
+		}
+		.number_delete_active{
+			width: 30%;
+			height: 80rpx;
+			margin-top: 10rpx;
+			background-color: #e64d3a;
+			display: flex;
+			justify-content: center;
+			align-items: center;
+			border-radius: 10rpx;
+			.delete_img{
+				width: 65rpx;
+				height: 64rpx;
+			}
+		}
+	}
+	
+	.keyboard_car{
+		width: 100%;
+		display: flex;
+		flex-direction: column;
+		position: relative;
+		.car_down{
+			position: absolute;
+			top: 10rpx;
+			left: 15rpx;
+			width: 48rpx;
+			height: 48rpx;
+		}
+		.tab_wrap{
+			height: 65rpx;
+			margin: 0 auto;
+			background-color: white;
+			border-radius: 20rpx;
+			display: flex;
+			padding-left: 25rpx;
+			padding-right: 25rpx;
+			image{
+				width: 48rpx;
+				height: 48rpx;
+			}
+			.tab_item{
+				height: 100%;
+				text-align: center;
+				line-height: 65rpx;
+				font-size: 26rpx;
+				margin: 0 20rpx;
+			}
+			.tab_item_active{
+				height: 100%;
+				text-align: center;
+				line-height: 65rpx;
+				font-size: 26rpx;
+				margin: 0 20rpx;
+				text-decoration: underline;
+				color: #e64d3a;
+			}
+		}
+		
+		.car_content{
+			width: 100%;
+			position: relative;
+			.car_province{
+				width: 100%;
+				display: flex;
+				justify-content: space-evenly;
+				flex-flow: wrap;
+				margin: 0;
+				.province_item{
+					width: 9.5%;
+					height: 80rpx;
+					margin-top: 10rpx;
+					background-color: white;
+					border-radius: 10rpx;
+					text-align: center;
+					line-height: 80rpx;
+					box-sizing: border-box;
+					display: block;
+					font-size: 28rpx;
+					font-weight: 450;
+				}
+				.province_item_active{
+					width: 9.5%;
+					height: 80rpx;
+					margin-top: 10rpx;
+					background-color: #888;
+					border-radius: 10rpx;
+					text-align: center;
+					line-height: 80rpx;
+					box-sizing: border-box;
+					display: block;
+					font-size: 28rpx;
+					font-weight: 450;
+					color: white;
+				}
+				.province_item_disable{
+					width: 9.5%;
+					height: 80rpx;
+					margin-top: 10rpx;
+					background-color: #fff;
+					border-radius: 10rpx;
+					text-align: center;
+					line-height: 80rpx;
+					box-sizing: border-box;
+					display: block;
+					font-size: 28rpx;
+					font-weight: 450;
+					opacity: 0.5;
+				}
+			}
+			.car_province_1{
+				width: 100%;
+				display: flex;
+				margin: 0;
+				.province_item1{
+					margin: 0;
+					width: 9.5%;
+					height: 80rpx;
+					margin-top: 10rpx;
+					background-color: white;
+					border-radius: 10rpx;
+					text-align: center;
+					line-height: 80rpx;
+					box-sizing: border-box;
+					display: block;
+					font-size: 28rpx;
+					font-weight: 450;
+				}
+				.province_item_active{
+					width: 9.5%;
+					height: 80rpx;
+					margin-top: 10rpx;
+					background-color: #888;
+					border-radius: 10rpx;
+					text-align: center;
+					line-height: 80rpx;
+					box-sizing: border-box;
+					display: block;
+					font-size: 28rpx;
+					font-weight: 450;
+					color: white;
+				}
+				.province_item_disable{
+					width: 9.5%;
+					height: 80rpx;
+					margin-top: 10rpx;
+					background-color: #fff;
+					border-radius: 10rpx;
+					text-align: center;
+					line-height: 80rpx;
+					box-sizing: border-box;
+					display: block;
+					font-size: 28rpx;
+					font-weight: 450;
+					opacity: 0.5;
+				}
+			}
+			.car_latter{
+				width: 100%;
+				display: flex;
+				justify-content: space-evenly;
+				flex-flow: wrap;
+				.latter_item{
+					width: 9.5%;
+					height: 80rpx;
+					margin-top: 10rpx;
+					background-color: white;
+					border-radius: 10rpx;
+					text-align: center;
+					line-height: 80rpx;
+					box-sizing: border-box;
+					display: block;
+					font-size: 28rpx;
+					font-weight: 450;
+				}
+				.province_item_active{
+					width: 9.5%;
+					height: 80rpx;
+					margin-top: 10rpx;
+					background-color: #888;
+					border-radius: 10rpx;
+					text-align: center;
+					line-height: 80rpx;
+					box-sizing: border-box;
+					display: block;
+					font-size: 28rpx;
+					font-weight: 450;
+					color: white;
+				}
+				.province_item_disable{
+					width: 9.5%;
+					height: 80rpx;
+					margin-top: 10rpx;
+					background-color: #fff;
+					border-radius: 10rpx;
+					text-align: center;
+					line-height: 80rpx;
+					box-sizing: border-box;
+					display: block;
+					font-size: 28rpx;
+					font-weight: 450;
+					opacity: 0.5;
+				}
+			}
+			.car_delete{
+				width: 15%;
+				height: 80rpx;
+				margin-top: 10rpx;
+				background-color: white;
+				border-radius: 10rpx;
+				display: flex;
+				justify-content: center;
+				align-items: center;
+				position: absolute;
+				.delete_img{
+					width: 65rpx;
+					height: 64rpx;
+				}
+			}
+			.car_delete_active{
+				width: 15%;
+				height: 80rpx;
+				margin-top: 10rpx;
+				background-color: #e64d3a;
+				border-radius: 10rpx;
+				display: flex;
+				justify-content: center;
+				align-items: center;
+				position: absolute;
+				.delete_img{
+					width: 65rpx;
+					height: 64rpx;
+				}
+			}
+		}
+	}
+}

+ 331 - 0
components/master-keyboard/master-keyboard.vue

@@ -0,0 +1,331 @@
+<template>
+	<view class="master_wrap" v-show="show" hover-stop-propagation>
+		<block v-if="keyboardtype == 'number' || keyboardtype == 'digit' || keyboardtype == 'idcard'">
+			<view class="down_wrap">
+				<image src="../../static/icon_down.png" @tap.stop="handleCloseKeyboard(false)"></image>
+			</view>
+			<view class="kerboard_number">
+				<view @tap.stop="handleNumberKeyboardClick(item)" :hover-stay-time="100"
+					:class="item== '-1' ? keyboardtype == 'number' ?  'number_empty' :'number_item' : item=='-2' ? 'number_delete' : 'number_item' "
+					:hover-class="item== '-1' ?  keyboardtype == 'number' ?  'number_empty_active' : 'number_item_active' : item=='-2' ? 'number_delete_active' : 'number_item_active'"
+					v-for="(item,index) in  randomNumberArr" :key="index">
+					<block v-if="item == '-1'">
+						<view v-if="keyboardtype == 'digit'">
+							·
+						</view>
+						<view v-else-if=" keyboardtype ==  'idcard'">
+							X
+						</view>
+					</block>
+					<block v-else-if="item == '-2'">
+						<image class="delete_img" src="../../static/icon_delete.png"></image>
+					</block>
+					<block v-else>
+						{{item}}
+					</block>
+				</view>
+			</view>
+			<view class="next-btn">
+				<view class='number_next' @click="nextBtnClick(0)">上一项</view>
+				<view class='number_next' @click="nextBtnClick(1)">下一项</view>
+			</view>
+		</block>
+		<block v-else-if="keyboardtype == 'car'">
+			<view class="keyboard_car">
+				<image @tap.stop="handleCloseKeyboard(false)" class="car_down" src="../../static/icon_down.png"></image>
+				<view class="tab_wrap">
+					<view @tap.stop="handleCarTabItemClick(index)"
+						:class=" carType === index ?'tab_item_active' : 'tab_item'" hover-class="tab_item_active"
+						v-for="(item,index) in carTabArr" :key="index">
+						{{item}}
+					</view>
+				</view>
+				<view class="car_content">
+					<block v-if="carType === 0">
+						<view class="car_province">
+							<view @tap.stop="handleCarKerboardClick(item)"
+								:class="computedDefaultValueLength ===0 ?  'province_item' :'province_item_disable'"
+								:hover-class="computedDefaultValueLength ===0 ? 'province_item_active' : 'none'"
+								:hover-stay-time="100" v-for="(item,index) in sliceProvinceArr" :key="index">
+								{{item}}
+							</view>
+						</view>
+						<view class="car_province_1">
+							<view @tap.stop="handleCarKerboardClick(item)"
+								:class=" (formatCarProvinceFirst(item) === -1 && computedDefaultValueLength ===0 )  ? 'province_item1' :
+								 ((newCar && computedDefaultValueLength ===7 && formatCarProvinceFirst(item) !== -1) || 
+								 (!newCar && computedDefaultValueLength ===6 && formatCarProvinceFirst(item) !== -1) ) ? 'province_item1' :  'province_item_disable'"
+								:hover-class=" (formatCarProvinceFirst(item) === -1 && computedDefaultValueLength ===0) ? 'province_item_active' : 'none'"
+								:hover-stay-time="100" :style="{'margin-left' : computeItemSpace + '%'}"
+								v-for="(item,index) in sliceSecondProvinceArr" :key="index">
+								{{item}}
+							</view>
+						</view>
+					</block>
+					<block v-else="carType === 1">
+						<view class="car_latter">
+							<view @tap.stop="handleCarKerboardClick(item)"
+								:class=" (computedDefaultValueLength ===1 && formatCarProvinceSecond(item) >-1 || computedDefaultValueLength ===0) ? 'province_item_disable' : 'latter_item'"
+								:hover-class=" (computedDefaultValueLength ===1 && formatCarProvinceSecond(item) >-1 || computedDefaultValueLength ===0) ? 'none' : 'province_item_active'"
+								:hover-stay-time="100" v-for="(item,index) in sliceLatterArr" :key="index">
+								<text>{{item}}</text>
+							</view>
+						</view>
+						<view class="car_province_1">
+							<view @tap.stop="handleCarKerboardClick(item)"
+								:class=" (computedDefaultValueLength ===1 && formatCarProvinceSecond(item) >-1 || computedDefaultValueLength ===0)  ? 'province_item_disable' : 'province_item1'"
+								:hover-class=" (computedDefaultValueLength ===1 && formatCarProvinceSecond(item) >-1 || computedDefaultValueLength ===0) ? 'none' : 'province_item_active'"
+								:hover-stay-time="100" :style="{'margin-left' : computeItemSpace + '%'}"
+								v-for="(item,index) in sliceSecondLatterArr" :key="index">
+								{{item}}
+							</view>
+						</view>
+					</block>
+					<view @tap.stop="handleCarKerboardDeleteClick" class="car_delete" hover-class="car_delete_active"
+						:hover-stay-time="100"
+						:style="{'top':computeDeleteTop + 'rpx','right' :computeItemSpace + '%' }">
+						<image class="delete_img" src="../../static/icon_delete.png"></image>
+					</view>
+				</view>
+			</view>
+		</block>
+	</view>
+</template>
+
+<script>
+	export default {
+		name: "master-keyboard",
+		props: {
+		fatherMethod: {
+				type: Function,
+				default: null
+			  },
+			keyboardtype: {
+				type: String,
+				default: 'number' // number=数字键盘 digit=带小数点的数字键盘  idcard=身份证号键盘  car=车牌号键盘
+			},
+			defaultValue: {
+				type: String,
+				default: ''
+			},
+			newCar: {
+				type: Boolean,
+				default: false
+			},
+			randomNumber: {
+				type: Boolean,
+				default: false
+			}
+		},
+		data() {
+			return {
+				numberArr: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'],
+				carProvinceArr: ['京', '津', '渝', '沪', '冀', '晋', '辽', '吉', '黑', '苏', '浙', '皖', '闽', '赣', '鲁', '豫',
+					'鳄', '湘', '粤', '琼', '川', '贵', '云', '陕', '甘', '青', '蒙', '桂', '宁', '新', '藏', '使',
+					'领', '警', '学', '港', '澳'
+				],
+				carLatterArr: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
+					'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R',
+					'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
+				],
+				carTabArr: ['省份', '字母'],
+				carType: 0,
+				show: false,
+			};
+		},
+		computed: {
+			sliceProvinceArr: function() {
+				return this.carProvinceArr.slice(0, 30)
+			},
+			sliceSecondProvinceArr: function() {
+				return this.carProvinceArr.slice(30, this.carProvinceArr.length)
+			},
+			sliceLatterArr: function() {
+				return this.carLatterArr.slice(0, 30)
+			},
+			sliceSecondLatterArr: function() {
+				return this.carLatterArr.slice(30, this.carLatterArr.length)
+			},
+			computeDeleteTop: function() {
+				return 80 * 3 + 10 * 3
+			},
+			computeItemSpace: function() {
+				return (1 - 0.095 * 10) / 11 * 100
+			},
+			computedDefaultValueLength: function() {
+				return this.$props.defaultValue.length
+			},
+			randomNumberArr: function() {
+				if(this.$props.randomNumber){
+					this.numberArr.sort(function() {
+						return 0.5 - Math.random()
+					})
+				}
+				const size = this.numberArr.length
+				this.numberArr.splice(size - 1, 0, "-1")
+				this.numberArr.push("-2")
+				return this.numberArr
+			}
+		},
+		watch: {
+			show: function(value) {
+
+			}
+		},
+		onLoad() {},
+		methods: {
+			nextBtnClick(type){
+				let that = this
+				if (this.fatherMethod) {
+				          this.fatherMethod(type);
+					}
+			},
+			formatCarProvinceFirst(value) {
+				const list = ['使', '领', '警', '学', '港', '澳', ]
+				return list.indexOf(value)
+			},
+			formatCarProvinceSecond(value) {
+				const list = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0']
+				return list.indexOf(value)
+			},
+			handleCloseKeyboard() {
+				this.open(false)
+			},
+			open(value) {
+				this.show = value
+				if(!value&&this.keyboardtype == 'car'){
+					this.carType=0
+				}
+			},
+			//车牌tab点击事件
+			handleCarTabItemClick(index) {
+				this.carType = index
+			},
+			//车牌键盘点击事件
+			handleCarKerboardClick(e) {
+				const keyValue = e
+				let value = this.$props.defaultValue
+				if (/^[\u4e00-\u9fa5]*$/.test(value) && value.length >= 2) {
+					value = ''
+				}
+				var pattern = new RegExp("[\u4E00-\u9FA5]+");
+				var pattern2 = new RegExp("[A-Za-z]+");
+				var pattern3 = new RegExp("[0-9]+");
+
+				if (value.length == 0) {
+					if (!pattern.test(keyValue) || this.formatCarProvinceFirst(keyValue) !== -1) {
+						return
+					}
+					this.carType = 1
+				} else if (value.length == 1) {
+					if (!pattern2.test(keyValue)) {
+						return
+					}
+				} else {
+					if (value.length === (this.$props.newCar ? 7 : 6) && pattern.test(keyValue) && this
+						.formatCarProvinceFirst(keyValue) == -1) {
+						return
+					}
+					if (pattern.test(keyValue) && value.length !== (this.$props.newCar ? 7 : 6)) {
+						return
+					}
+				}
+
+				if (value.length < 7 && !this.$props.newCar) {
+					this.$emit('keyboardClick', {
+						value: value + keyValue
+					})
+				}
+				if (value.length < 8 && this.$props.newCar) {
+					this.$emit('keyboardClick', {
+						value: value + keyValue
+					})
+				}
+			},
+			//车牌键盘删除事件
+			handleCarKerboardDeleteClick() {
+				let deleteValue = this.$props.defaultValue
+				if (deleteValue == '' || (/^[\u4e00-\u9fa5]*$/.test(deleteValue) && deleteValue.length !== 1)) {
+					return
+				}
+				if (deleteValue.length > 0) {
+					let count = deleteValue.length
+					this.$emit('keyboardClick', {
+						value: deleteValue.substr(0, count - 1)
+					})
+				}
+			},
+			//数字键盘点击事件
+			handleNumberKeyboardClick(e) {
+				const keyValue = e
+				if (this.$props.keyboardtype == 'number' || this.$props.keyboardtype == 'digit' || this.$props
+					.keyboardtype == 'idcard') {
+					switch (keyValue) {
+						case '-1':
+							if (this.$props.keyboardtype == 'number' || this.$props.defaultValue == '') {
+								return
+							}
+							let value = this.$props.defaultValue
+							if (/^[\u4e00-\u9fa5]*$/.test(value) || value.indexOf('.') > -1 || value.indexOf('X') > -1) {
+								return
+							}
+							if (this.$props.keyboardtype == 'idcard') {
+								if (value.length === 17) {
+									this.$emit('keyboardClick', {
+										value: value + 'X'
+									})
+								}
+							}
+							if (this.$props.keyboardtype == 'digit') {
+								this.$emit('keyboardClick', {
+									value: value + '.'
+								})
+							}
+							break
+						case '-2':
+							let deleteValue = this.$props.defaultValue
+							if (deleteValue == '' || /^[\u4e00-\u9fa5]*$/.test(deleteValue)) {
+								return
+							}
+							if (deleteValue.length > 0) {
+								let count = deleteValue.length
+								this.$emit('keyboardClick', {
+									value: deleteValue.substr(0, count - 1)
+								})
+							}
+							break
+						default:
+							let initValue = this.$props.defaultValue
+							if (/^[\u4e00-\u9fa5]*$/.test(initValue)) {
+								initValue = ''
+							}
+							if (this.$props.keyboardtype == 'idcard') {
+								if (initValue.length < 18) {
+									this.$emit('keyboardClick', {
+										value: initValue + keyValue
+									})
+								}
+								return
+							}
+							this.$emit('keyboardClick', {
+								value: initValue + keyValue
+							})
+							break
+					}
+				}
+			}
+		}
+	}
+</script>
+
+<style scoped lang="scss">
+	@import './master-keyboard.scss';
+	.next-btn{
+		display: flex;
+		justify-content: space-evenly;
+		.number_next{
+			width: 45%;
+		}
+		
+		}
+</style>

+ 205 - 0
components/me-tabs/me-tabs.vue

@@ -0,0 +1,205 @@
+<!-- tab组件: <me-tabs v-model="tabIndex" :tabs="tabs" @change="tabChange"></me-tabs> -->
+<template>
+	<view class="me-tabs" :class="{'tabs-fixed': fixed}" :style="{height: tabHeightVal, top:topFixed}">
+		<scroll-view v-if="tabs.length" :id="viewId" :scroll-left="scrollLeft" scroll-x scroll-with-animation :scroll-animation-duration="300">
+			<view class="tabs-item" :class="{'tabs-flex':!isScroll, 'tabs-scroll':isScroll}">
+				<!-- tab -->
+				<view class="tab-item" :style="{height: tabHeightVal, 'line-height':tabHeightVal}" v-for="(tab, i) in tabs" :class="{'active': value===i}" :key="i" @click="tabClick(i)">
+					{{getTabName(tab)}}
+				</view>
+				<!-- 下划线 -->
+				<!-- <view class="tabs-line" :style="{left:lineLeft}"></view> -->
+			</view>
+		</scroll-view>
+	</view>
+</template>
+
+<script>
+	export default {
+		props:{
+			tabs: { // 支持格式: ['全部', '待付款'] 或 [{name:'全部'}, {name:'待付款'}]
+				type: Array,
+				default(){
+					return []
+				}
+			},
+			nameKey: { // 取name的字段
+				type: String,
+				default: 'name'
+			},
+			value: { // 当前显示的下标 (使用v-model语法糖: 1.props需为value; 2.需回调input事件)
+				type: [String, Number],
+				default: 0
+			},
+			fixed: Boolean, // 是否悬浮,默认false
+			tabWidth: Number, // 每个tab的宽度,默认不设置值,为flex平均分配; 如果指定宽度,则不使用flex,每个tab居左,超过则水平滑动(单位默认rpx)
+			height: { // 高度,单位rpx
+				type: Number,
+				default: 64
+			},
+			top: { // 顶部偏移的距离,默认单位rpx (当fixed=true时,已加上windowTop)
+				type: Number,
+				default: 0
+			}
+		},
+		data() {
+			return {
+				viewId: 'id_' + Math.random().toString(36).substr(2,16),
+				scrollLeft: 0,
+				windowWidth: 0,
+				windowTop: 0
+			}
+		},
+		computed: {
+			isScroll(){
+				return this.tabWidth && this.tabs.length // 指定了tabWidth的宽度,则支持水平滑动
+			},
+			tabHeightPx(){
+				return uni.upx2px(this.height)
+			},
+			tabHeightVal(){
+				return this.tabHeightPx+'px'
+			},
+			tabWidthPx(){
+				return uni.upx2px(this.tabWidth)
+			},
+			tabWidthVal(){
+				// return this.isScroll ? this.tabWidthPx+'px' : ''
+			},
+			lineLeft() {
+				if (this.isScroll) {
+					return this.tabWidthPx * this.value + this.tabWidthPx/2 + 'px' // 需转为px (用rpx的话iOS真机显示有误差)
+				} else{
+					return 100/this.tabs.length*(this.value + 1) - 100/(this.tabs.length*2) + '%'
+				}
+			},
+			topFixed(){
+				return this.fixed ? this.windowTop + uni.upx2px(this.top) + 'px' : 0
+			},
+			topMargin(){
+				return this.fixed ? 0 : this.top + 'rpx'
+			}
+		},
+		watch: {
+			tabs() {
+				this.warpWidth = null; // 重新计算容器宽度
+				this.scrollCenter(); // 水平滚动到中间
+			},
+			value() {
+				this.scrollCenter(); // 水平滚动到中间
+			}
+		},
+		created() {
+			let sys = uni.getSystemInfoSync();
+			this.windowWidth = sys.windowWidth
+			this.windowTop = sys.windowTop
+		},
+		mounted() {
+			this.scrollCenter() // 滚动到当前下标
+		},
+		methods: {
+			getTabName(tab){
+				return typeof tab === "object" ? tab[this.nameKey] : tab
+			},
+			tabClick(i){
+				if(this.value!=i){
+					this.$emit("input",i);
+					this.$emit("change",i);
+				}
+			},
+			async scrollCenter(){
+				if(!this.isScroll) return;
+				if(!this.warpWidth){ // tabs容器的宽度
+					let rect = await this.initWarpRect()
+					this.warpWidth = rect ? rect.width : this.windowWidth; // 某些情况下取不到宽度,暂时取屏幕宽度
+				}
+				let tabLeft = this.tabWidthPx * this.value + this.tabWidthPx/2; // 当前tab中心点到左边的距离
+				let diff = tabLeft - this.warpWidth/2 // 如果超过tabs容器的一半,则滚动差值
+				this.scrollLeft = diff;
+				// #ifdef MP-TOUTIAO
+				this.scrollTimer && clearTimeout(this.scrollTimer)
+				this.scrollTimer = setTimeout(()=>{ // 字节跳动小程序,需延时再次设置scrollLeft,否则tab切换跨度较大时不生效
+					this.scrollLeft = Math.ceil(diff)
+				},400)
+				// #endif
+			},
+			initWarpRect(){
+				return new Promise(resolve=>{
+					setTimeout(()=>{ // 延时确保dom已渲染, 不使用$nextclick
+						let query = uni.createSelectorQuery();
+						// #ifndef MP-ALIPAY
+						query = query.in(this) // 支付宝小程序不支持in(this),而字节跳动小程序必须写in(this), 否则都取不到值
+						// #endif
+						query.select('#'+this.viewId).boundingClientRect(data => {
+							resolve(data)
+						}).exec();
+					},20)
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+	.me-tabs{
+		position: relative;
+		font-size: 24rpx;
+		background-color: #fff;
+		border-bottom: 1rpx solid #eee;
+		box-sizing: border-box;
+		overflow-y: hidden;
+		background-color: #fff;
+		display: flex;
+		justify-content: space-around;
+		&.tabs-fixed{
+			z-index: 990;
+			position: fixed;
+			left: 0;
+			width: 100%;
+		}
+		
+		.tabs-item{
+			position: relative;
+			white-space: nowrap;
+			padding-bottom: 30rpx; // 撑开高度,再配合me-tabs的overflow-y: hidden,以达到隐藏滚动条的目的
+			box-sizing: border-box;
+			.tab-item{
+				position: relative;
+				text-align: center;
+				box-sizing: border-box;
+				width: 25%;
+				&.active{
+					font-weight: bold;
+					color: red;
+				}
+			}
+		}
+		
+		// 平分的方式显示item
+		.tabs-flex{
+			display: flex;
+			.tab-item{
+				flex: 1;
+			}
+		}
+		// 居左显示item,支持水平滑动
+		.tabs-scroll{
+			.tab-item{
+				display: inline-block;
+			}
+		}
+		
+		// 选中tab的线
+		.tabs-line{
+			z-index: 1;
+			position: absolute;
+			bottom: 30rpx; // 至少与.tabs-item的padding-bottom一致,才能保证在底部边缘
+			width: 50rpx;
+			height: 6rpx;
+			transform: translateX(-50%);
+			border-radius: 4rpx;
+			transition: left .3s;
+			background: red;
+		}
+	}
+</style>

+ 143 - 0
components/ossutil/base64.js

@@ -0,0 +1,143 @@
+
+var base64EncodeChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+var base64DecodeChars = new Array(
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
+    52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
+    -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+    15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
+    -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+    41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1);
+function encode(str) {
+    var out, i, len;
+    var c1, c2, c3;
+    len = str.length;
+    i = 0;
+    out = "";
+    while (i < len) {
+        c1 = str.charCodeAt(i++) & 0xff;
+        if (i == len) {
+            out += base64EncodeChars.charAt(c1 >> 2);
+            out += base64EncodeChars.charAt((c1 & 0x3) << 4);
+            out += "==";
+            break;
+        }
+        c2 = str.charCodeAt(i++);
+        if (i == len) {
+            out += base64EncodeChars.charAt(c1 >> 2);
+            out += base64EncodeChars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4));
+            out += base64EncodeChars.charAt((c2 & 0xF) << 2);
+            out += "=";
+            break;
+        }
+        c3 = str.charCodeAt(i++);
+        out += base64EncodeChars.charAt(c1 >> 2);
+        out += base64EncodeChars.charAt(((c1 & 0x3) << 4) | ((c2 & 0xF0) >> 4));
+        out += base64EncodeChars.charAt(((c2 & 0xF) << 2) | ((c3 & 0xC0) >> 6));
+        out += base64EncodeChars.charAt(c3 & 0x3F);
+    }
+    return out;
+}
+function decode(str) {
+    var c1, c2, c3, c4;
+    var i, len, out;
+    len = str.length;
+    i = 0;
+    out = "";
+    while (i < len) {
+        /* c1 */
+        do {
+            c1 = base64DecodeChars[str.charCodeAt(i++) & 0xff];
+        } while (i < len && c1 == -1);
+        if (c1 == -1)
+            break;
+        /* c2 */
+        do {
+            c2 = base64DecodeChars[str.charCodeAt(i++) & 0xff];
+        } while (i < len && c2 == -1);
+        if (c2 == -1)
+            break;
+        out += String.fromCharCode((c1 << 2) | ((c2 & 0x30) >> 4));
+        /* c3 */
+        do {
+            c3 = str.charCodeAt(i++) & 0xff;
+            if (c3 == 61)
+                return out;
+            c3 = base64DecodeChars[c3];
+        } while (i < len && c3 == -1);
+        if (c3 == -1)
+            break;
+        out += String.fromCharCode(((c2 & 0XF) << 4) | ((c3 & 0x3C) >> 2));
+        /* c4 */
+        do {
+            c4 = str.charCodeAt(i++) & 0xff;
+            if (c4 == 61)
+                return out;
+            c4 = base64DecodeChars[c4];
+        } while (i < len && c4 == -1);
+        if (c4 == -1)
+            break;
+        out += String.fromCharCode(((c3 & 0x03) << 6) | c4);
+    }
+    return out;
+}
+
+
+function utf16to8(str) {
+    var out, i, len, c;
+    out = "";
+    len = str.length;
+    for (i = 0; i < len; i++) {
+        c = str.charCodeAt(i);
+        if ((c >= 0x0001) && (c <= 0x007F)) {
+            out += str.charAt(i);
+        } else if (c > 0x07FF) {
+            out += String.fromCharCode(0xE0 | ((c >> 12) & 0x0F));
+            out += String.fromCharCode(0x80 | ((c >> 6) & 0x3F));
+            out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F));
+        } else {
+            out += String.fromCharCode(0xC0 | ((c >> 6) & 0x1F));
+            out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F));
+        }
+    }
+    return out;
+}
+function utf8to16(str) {
+    var out, i, len, c;
+    var char2, char3;
+    out = "";
+    len = str.length;
+    i = 0;
+    while (i < len) {
+        c = str.charCodeAt(i++);
+        switch (c >> 4) {
+            case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
+                // 0xxxxxxx
+                out += str.charAt(i - 1);
+                break;
+            case 12: case 13:
+                // 110x xxxx 10xx xxxx
+                char2 = str.charCodeAt(i++);
+                out += String.fromCharCode(((c & 0x1F) << 6) | (char2 & 0x3F));
+                break;
+            case 14:
+                // 1110 xxxx 10xx xxxx 10xx xxxx
+                char2 = str.charCodeAt(i++);
+                char3 = str.charCodeAt(i++);
+                out += String.fromCharCode(((c & 0x0F) << 12) |
+                    ((char2 & 0x3F) << 6) |
+                    ((char3 & 0x3F) << 0));
+                break;
+        }
+    }
+    return out;
+}
+
+
+module.exports = {
+    encode: encode,
+    decode: decode,
+    utf16to8: utf16to8,
+    utf8to16: utf8to16
+}

+ 9 - 0
components/ossutil/config.js

@@ -0,0 +1,9 @@
+var fileHost = 'https://taohaoliang.oss-cn-beijing.aliyuncs.com';//你的阿里云地址最后面跟上一个/   在你当前小程序的后台的uploadFile 合法域名也要配上这个域名
+var config = {
+   //aliyun OSS config
+  uploadImageUrl: `${fileHost}`, // 默认存在根目录,可根据需求改
+  AccessKeySecret: 'FpClTp4OVrRRtHEfi3lBOWUoLxKieW',        // AccessKeySecret 去你的阿里云上控制台上找
+  OSSAccessKeyId: 'LTAI4G9c14PgKvM23WZ9zrpc',         // AccessKeyId 去你的阿里云上控制台上找
+   timeout: 87600 //这个是上传文件时Policy的失效时间
+};
+module.exports = config

+ 178 - 0
components/ossutil/crypto.js

@@ -0,0 +1,178 @@
+const Crypto = {};
+
+(function(){
+
+var base64map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+
+// Crypto utilities
+var util = Crypto.util = {
+
+	// Bit-wise rotate left
+	rotl: function (n, b) {
+		return (n << b) | (n >>> (32 - b));
+	},
+
+	// Bit-wise rotate right
+	rotr: function (n, b) {
+		return (n << (32 - b)) | (n >>> b);
+	},
+
+	// Swap big-endian to little-endian and vice versa
+	endian: function (n) {
+
+		// If number given, swap endian
+		if (n.constructor == Number) {
+			return util.rotl(n,  8) & 0x00FF00FF |
+			       util.rotl(n, 24) & 0xFF00FF00;
+		}
+
+		// Else, assume array and swap all items
+		for (var i = 0; i < n.length; i++)
+			n[i] = util.endian(n[i]);
+		return n;
+
+	},
+
+	// Generate an array of any length of random bytes
+	randomBytes: function (n) {
+		for (var bytes = []; n > 0; n--)
+			bytes.push(Math.floor(Math.random() * 256));
+		return bytes;
+	},
+
+	// Convert a string to a byte array
+	stringToBytes: function (str) {
+		var bytes = [];
+		for (var i = 0; i < str.length; i++)
+			bytes.push(str.charCodeAt(i));
+		return bytes;
+	},
+
+	// Convert a byte array to a string
+	bytesToString: function (bytes) {
+		var str = [];
+		for (var i = 0; i < bytes.length; i++)
+			str.push(String.fromCharCode(bytes[i]));
+		return str.join("");
+	},
+
+	// Convert a string to big-endian 32-bit words
+	stringToWords: function (str) {
+		var words = [];
+		for (var c = 0, b = 0; c < str.length; c++, b += 8)
+			words[b >>> 5] |= str.charCodeAt(c) << (24 - b % 32);
+		return words;
+	},
+
+	// Convert a byte array to big-endian 32-bits words
+	bytesToWords: function (bytes) {
+		var words = [];
+		for (var i = 0, b = 0; i < bytes.length; i++, b += 8)
+			words[b >>> 5] |= bytes[i] << (24 - b % 32);
+		return words;
+	},
+
+	// Convert big-endian 32-bit words to a byte array
+	wordsToBytes: function (words) {
+		var bytes = [];
+		for (var b = 0; b < words.length * 32; b += 8)
+			bytes.push((words[b >>> 5] >>> (24 - b % 32)) & 0xFF);
+		return bytes;
+	},
+
+	// Convert a byte array to a hex string
+	bytesToHex: function (bytes) {
+		var hex = [];
+		for (var i = 0; i < bytes.length; i++) {
+			hex.push((bytes[i] >>> 4).toString(16));
+			hex.push((bytes[i] & 0xF).toString(16));
+		}
+		return hex.join("");
+	},
+
+	// Convert a hex string to a byte array
+	hexToBytes: function (hex) {
+		var bytes = [];
+		for (var c = 0; c < hex.length; c += 2)
+			bytes.push(parseInt(hex.substr(c, 2), 16));
+		return bytes;
+	},
+
+	// Convert a byte array to a base-64 string
+	bytesToBase64: function (bytes) {
+
+		// Use browser-native function if it exists
+		// if (typeof btoa == "function") return btoa(util.bytesToString(bytes));
+
+		var base64 = [],
+		    overflow;
+
+		for (var i = 0; i < bytes.length; i++) {
+			switch (i % 3) {
+				case 0:
+					base64.push(base64map.charAt(bytes[i] >>> 2));
+					overflow = (bytes[i] & 0x3) << 4;
+					break;
+				case 1:
+					base64.push(base64map.charAt(overflow | (bytes[i] >>> 4)));
+					overflow = (bytes[i] & 0xF) << 2;
+					break;
+				case 2:
+					base64.push(base64map.charAt(overflow | (bytes[i] >>> 6)));
+					base64.push(base64map.charAt(bytes[i] & 0x3F));
+					overflow = -1;
+			}
+		}
+
+		// Encode overflow bits, if there are any
+		if (overflow != undefined && overflow != -1)
+			base64.push(base64map.charAt(overflow));
+
+		// Add padding
+		while (base64.length % 4 != 0) base64.push("=");
+
+		return base64.join("");
+
+	},
+
+	// Convert a base-64 string to a byte array
+	base64ToBytes: function (base64) {
+
+		// Use browser-native function if it exists
+		if (typeof atob == "function") return util.stringToBytes(atob(base64));
+
+		// Remove non-base-64 characters
+		base64 = base64.replace(/[^A-Z0-9+\/]/ig, "");
+
+		var bytes = [];
+
+		for (var i = 0; i < base64.length; i++) {
+			switch (i % 4) {
+				case 1:
+					bytes.push((base64map.indexOf(base64.charAt(i - 1)) << 2) |
+					           (base64map.indexOf(base64.charAt(i)) >>> 4));
+					break;
+				case 2:
+					bytes.push(((base64map.indexOf(base64.charAt(i - 1)) & 0xF) << 4) |
+					           (base64map.indexOf(base64.charAt(i)) >>> 2));
+					break;
+				case 3:
+					bytes.push(((base64map.indexOf(base64.charAt(i - 1)) & 0x3) << 6) |
+					           (base64map.indexOf(base64.charAt(i))));
+					break;
+			}
+		}
+
+		return bytes;
+
+	}
+
+};
+
+// Crypto mode namespace
+Crypto.mode = {};
+
+})();
+
+module.exports = Crypto;

+ 34 - 0
components/ossutil/hmac.js

@@ -0,0 +1,34 @@
+const Crypto = require('./crypto.js');
+
+(function(){
+
+// Shortcut
+var util = Crypto.util;
+
+Crypto.HMAC = function (hasher, message, key, options) {
+
+	// Allow arbitrary length keys
+	key = key.length > hasher._blocksize * 4 ?
+	      hasher(key, { asBytes: true }) :
+	      util.stringToBytes(key);
+
+	// XOR keys with pad constants
+	var okey = key,
+	    ikey = key.slice(0);
+	for (var i = 0; i < hasher._blocksize * 4; i++) {
+		okey[i] ^= 0x5C;
+		ikey[i] ^= 0x36;
+	}
+
+	var hmacbytes = hasher(util.bytesToString(okey) +
+	                       hasher(util.bytesToString(ikey) + message, { asString: true }),
+	                       { asBytes: true });
+	return options && options.asBytes ? hmacbytes :
+	       options && options.asString ? util.bytesToString(hmacbytes) :
+	       util.bytesToHex(hmacbytes);
+
+};
+
+})();
+
+module.exports = Crypto;

+ 79 - 0
components/ossutil/sha1.js

@@ -0,0 +1,79 @@
+const Crypto = require('./crypto.js');
+
+(function(){
+
+// Shortcut
+var util = Crypto.util;
+
+// Public API
+var SHA1 = Crypto.SHA1 = function (message, options) {
+	var digestbytes = util.wordsToBytes(SHA1._sha1(message));
+	return options && options.asBytes ? digestbytes :
+	       options && options.asString ? util.bytesToString(digestbytes) :
+	       util.bytesToHex(digestbytes);
+};
+
+// The core
+SHA1._sha1 = function (message) {
+
+	var m  = util.stringToWords(message),
+	    l  = message.length * 8,
+	    w  =  [],
+	    H0 =  1732584193,
+	    H1 = -271733879,
+	    H2 = -1732584194,
+	    H3 =  271733878,
+	    H4 = -1009589776;
+
+	// Padding
+	m[l >> 5] |= 0x80 << (24 - l % 32);
+	m[((l + 64 >>> 9) << 4) + 15] = l;
+
+	for (var i = 0; i < m.length; i += 16) {
+
+		var a = H0,
+		    b = H1,
+		    c = H2,
+		    d = H3,
+		    e = H4;
+
+		for (var j = 0; j < 80; j++) {
+
+			if (j < 16) w[j] = m[i + j];
+			else {
+				var n = w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16];
+				w[j] = (n << 1) | (n >>> 31);
+			}
+
+			var t = ((H0 << 5) | (H0 >>> 27)) + H4 + (w[j] >>> 0) + (
+			         j < 20 ? (H1 & H2 | ~H1 & H3) + 1518500249 :
+			         j < 40 ? (H1 ^ H2 ^ H3) + 1859775393 :
+			         j < 60 ? (H1 & H2 | H1 & H3 | H2 & H3) - 1894007588 :
+			                  (H1 ^ H2 ^ H3) - 899497514);
+
+			H4 =  H3;
+			H3 =  H2;
+			H2 = (H1 << 30) | (H1 >>> 2);
+			H1 =  H0;
+			H0 =  t;
+
+		}
+
+		H0 += a;
+		H1 += b;
+		H2 += c;
+		H3 += d;
+		H4 += e;
+
+	}
+
+	return [H0, H1, H2, H3, H4];
+
+};
+
+// Package private blocksize
+SHA1._blocksize = 16;
+
+})();
+
+module.exports = Crypto;

+ 394 - 0
components/ossutil/signature.js

@@ -0,0 +1,394 @@
+class Handwriting {
+  // 内置数据
+  ctx = '';
+  canvasWidth = 300;
+  canvasHeight = 900;
+  linePrack = []; //划线轨迹 ; 生成线条的实际点
+  currentLine = [];
+  transparent = 1; // 透明度
+  pressure = 0.5; // 默认压力
+  smoothness = 100; //顺滑度,用60的距离来计算速度
+  lineSize = 1.5; // 笔记倍数
+  lineMin = 0.5; // 最小笔画半径
+  lineMax = 2; // 最大笔画半径
+  currentPoint = {};
+  firstTouch = true; // 第一次触发
+  radius = 1; //画圆的半径
+  cutArea = {
+    top: 0,
+    right: 0,
+    bottom: 0,
+    left: 0
+  }; //裁剪区域
+  lastPoint = 0;
+  chirography = []; //笔迹
+  startY = 0;
+  deltaY = 0;
+  startValue = 0;
+  constructor(opts) {
+    this.lineColor = opts.lineColor || '#1A1A1A' // 颜色
+    this.slideValue = opts.slideValue || 50
+		this.canvasName = opts.canvasName || 'handWriting'
+    this.init()
+  }
+  init() {
+    this.ctx = uni.createCanvasContext(this.canvasName)
+    var query = uni.createSelectorQuery();
+    query.select('.handCenter').boundingClientRect(rect => {
+      console.log(rect)
+	  if(rect){
+		 this.canvasWidth = rect.width;
+		 this.canvasHeight = rect.height; 
+	  }
+      
+    }).exec();
+    this.selectSlideValue(this.slideValue);
+  }
+
+  // 笔迹开始
+  uploadScaleStart(event) {
+		let e = event.mp
+    if (e.type != 'touchstart') return false;
+    this.ctx.setFillStyle(this.lineColor); // 初始线条设置颜色
+    this.ctx.setGlobalAlpha(this.transparent); // 设置半透明
+    this.currentPoint = {
+      x: e.touches[0].x,
+      y: e.touches[0].y
+    }
+    this.currentLine.unshift({
+      time: new Date().getTime(),
+      dis: 0,
+      x: this.currentPoint.x,
+      y: this.currentPoint.y
+    })
+    if (this.firstTouch) {
+      this.cutArea = {
+        top: this.currentPoint.y,
+        right: this.currentPoint.x,
+        bottom: this.currentPoint.y,
+        left: this.currentPoint.x
+      }
+      this.firstTouch = false
+    }
+    this.pointToLine(this.currentLine);
+  }
+  // 笔迹移动
+  uploadScaleMove(event) {
+		let e = event.mp
+    if (e.type != 'touchmove') return false;
+    if (e.cancelable) {
+      // 判断默认行为是否已经被禁用
+      if (!e.defaultPrevented) {
+        e.preventDefault();
+      }
+    }
+    let point = {
+      x: e.touches[0].x,
+      y: e.touches[0].y
+    }
+    //测试裁剪
+    if (point.y < this.cutArea.top) {
+      this.cutArea.top = point.y;
+    }
+    if (point.y < 0) this.cutArea.top = 0;
+
+    if (point.x > this.cutArea.right) {
+      this.cutArea.right = point.x;
+    }
+    if (this.canvasWidth - point.x <= 0) {
+      this.cutArea.right = this.canvasWidth;
+    }
+    if (point.y > this.cutArea.bottom) {
+      this.cutArea.bottom = point.y;
+    }
+    if (this.canvasHeight - point.y <= 0) {
+      this.cutArea.bottom = this.canvasHeight;
+    }
+    if (point.x < this.cutArea.left) {
+      this.cutArea.left = point.x;
+    }
+    if (point.x < 0) this.cutArea.left = 0;
+
+    this.lastPoint = this.currentPoint;
+    this.currentPoint = point
+    this.currentLine.unshift({
+      time: new Date().getTime(),
+      dis: this.distance(this.currentPoint, this.lastPoint, 'move'),
+      x: point.x,
+      y: point.y
+    })
+    this.pointToLine(this.currentLine);
+  }
+  // 笔迹结束
+  uploadScaleEnd(event) {
+		let e = event.mp
+    if (e.type != 'touchend') return 0;
+    let point = {
+      x: e.changedTouches[0].x,
+      y: e.changedTouches[0].y
+    }
+		
+    this.lastPoint = this.currentPoint;
+    this.currentPoint = point
+    this.currentLine.unshift({
+      time: new Date().getTime(),
+      dis: this.distance(this.currentPoint, this.lastPoint, 'end'),
+      x: point.x,
+      y: point.y
+    })
+    if (this.currentLine.length > 2) {
+      var info = (this.currentLine[0].time - this.currentLine[this.currentLine.length - 1].time) / this.currentLine.length;
+      //$("#info").text(info.toFixed(2));
+    }
+    //一笔结束,保存笔迹的坐标点,清空,当前笔迹
+    //增加判断是否在手写区域;
+    this.pointToLine(this.currentLine);
+    var currentChirography = {
+      lineSize: this.lineSize,
+      lineColor: this.lineColor
+    };
+    this.chirography.unshift(currentChirography);
+    this.linePrack.unshift(this.currentLine);
+    this.currentLine = []
+  }
+  retDraw() {
+    this.ctx.clearRect(0, 0, 700, 730)
+    this.ctx.draw()
+  }
+
+  //画两点之间的线条;参数为:line,会绘制最近的开始的两个点;
+  pointToLine(line) {
+    this.calcBethelLine(line);
+    // this.calcBethelLine1(line);
+    return;
+  }
+  //计算插值的方式;
+  calcBethelLine(line) {
+    if (line.length <= 1) {
+      line[0].r = this.radius;
+      return;
+    }
+    let x0, x1, x2, y0, y1, y2, r0, r1, r2, len, lastRadius, dis = 0,
+      time = 0,
+      curveValue = 0.5;
+    if (line.length <= 2) {
+      x0 = line[1].x
+      y0 = line[1].y
+      x2 = line[1].x + (line[0].x - line[1].x) * curveValue;
+      y2 = line[1].y + (line[0].y - line[1].y) * curveValue;
+      //x2 = line[1].x;
+      //y2 = line[1].y;
+      x1 = x0 + (x2 - x0) * curveValue;
+      y1 = y0 + (y2 - y0) * curveValue;;
+
+    } else {
+      x0 = line[2].x + (line[1].x - line[2].x) * curveValue;
+      y0 = line[2].y + (line[1].y - line[2].y) * curveValue;
+      x1 = line[1].x;
+      y1 = line[1].y;
+      x2 = x1 + (line[0].x - x1) * curveValue;
+      y2 = y1 + (line[0].y - y1) * curveValue;
+    }
+    //从计算公式看,三个点分别是(x0,y0),(x1,y1),(x2,y2) ;(x1,y1)这个是控制点,控制点不会落在曲线上;实际上,这个点还会手写获取的实际点,却落在曲线上
+    len = this.distance({
+      x: x2,
+      y: y2
+    }, {
+      x: x0,
+      y: y0
+    }, 'calc');
+    lastRadius = this.radius;
+    for (let n = 0; n < line.length - 1; n++) {
+      dis += line[n].dis;
+      time += line[n].time - line[n + 1].time;
+      if (dis > this.smoothness) break;
+    }
+    this.radius = Math.min(time / len * this.pressure + this.lineMin, this.lineMax) * this.lineSize
+    line[0].r = this.radius;
+    //计算笔迹半径;
+    if (line.length <= 2) {
+      r0 = (lastRadius + this.radius) / 2;
+      r1 = r0;
+      r2 = r1;
+      //return;
+    } else {
+      r0 = (line[2].r + line[1].r) / 2;
+      r1 = line[1].r;
+      r2 = (line[1].r + line[0].r) / 2;
+    }
+    let n = 5;
+    let point = [];
+    for (let i = 0; i < n; i++) {
+      let t = i / (n - 1);
+      let x = (1 - t) * (1 - t) * x0 + 2 * t * (1 - t) * x1 + t * t * x2;
+      let y = (1 - t) * (1 - t) * y0 + 2 * t * (1 - t) * y1 + t * t * y2;
+      let r = lastRadius + (this.radius - lastRadius) / n * i;
+      point.push({
+        x: x,
+        y: y,
+        r: r
+      });
+      if (point.length == 3) {
+        let a = this.ctaCalc(point[0].x, point[0].y, point[0].r, point[1].x, point[1].y, point[1].r, point[2].x, point[2].y, point[2].r);
+        a[0].color = this.lineColor;
+        this.bethelDraw(a, 1);
+        point = [{
+          x: x,
+          y: y,
+          r: r
+        }];
+      }
+    }
+  }
+  //求两点之间距离
+  distance(a, b, type) {
+    let x = b.x - a.x;
+    let y = b.y - a.y;
+    return Math.sqrt(x * x + y * y) * 5;
+  }
+  ctaCalc(x0, y0, r0, x1, y1, r1, x2, y2, r2) {
+    let a = [],
+      vx01, vy01, norm, n_x0, n_y0, vx21, vy21, n_x2, n_y2;
+    vx01 = x1 - x0;
+    vy01 = y1 - y0;
+    norm = Math.sqrt(vx01 * vx01 + vy01 * vy01 + 0.0001) * 2;
+    vx01 = vx01 / norm * r0;
+    vy01 = vy01 / norm * r0;
+    n_x0 = vy01;
+    n_y0 = -vx01;
+    vx21 = x1 - x2;
+    vy21 = y1 - y2;
+    norm = Math.sqrt(vx21 * vx21 + vy21 * vy21 + 0.0001) * 2;
+    vx21 = vx21 / norm * r2;
+    vy21 = vy21 / norm * r2;
+    n_x2 = -vy21;
+    n_y2 = vx21;
+    a.push({
+      mx: x0 + n_x0,
+      my: y0 + n_y0,
+      color: "#1A1A1A"
+    });
+    a.push({
+      c1x: x1 + n_x0,
+      c1y: y1 + n_y0,
+      c2x: x1 + n_x2,
+      c2y: y1 + n_y2,
+      ex: x2 + n_x2,
+      ey: y2 + n_y2
+    });
+    a.push({
+      c1x: x2 + n_x2 - vx21,
+      c1y: y2 + n_y2 - vy21,
+      c2x: x2 - n_x2 - vx21,
+      c2y: y2 - n_y2 - vy21,
+      ex: x2 - n_x2,
+      ey: y2 - n_y2
+    });
+    a.push({
+      c1x: x1 - n_x2,
+      c1y: y1 - n_y2,
+      c2x: x1 - n_x0,
+      c2y: y1 - n_y0,
+      ex: x0 - n_x0,
+      ey: y0 - n_y0
+    });
+    a.push({
+      c1x: x0 - n_x0 - vx01,
+      c1y: y0 - n_y0 - vy01,
+      c2x: x0 + n_x0 - vx01,
+      c2y: y0 + n_y0 - vy01,
+      ex: x0 + n_x0,
+      ey: y0 + n_y0
+    });
+    a[0].mx = a[0].mx.toFixed(1);
+    a[0].mx = parseFloat(a[0].mx);
+    a[0].my = a[0].my.toFixed(1);
+    a[0].my = parseFloat(a[0].my);
+    for (let i = 1; i < a.length; i++) {
+      a[i].c1x = a[i].c1x.toFixed(1);
+      a[i].c1x = parseFloat(a[i].c1x);
+      a[i].c1y = a[i].c1y.toFixed(1);
+      a[i].c1y = parseFloat(a[i].c1y);
+      a[i].c2x = a[i].c2x.toFixed(1);
+      a[i].c2x = parseFloat(a[i].c2x);
+      a[i].c2y = a[i].c2y.toFixed(1);
+      a[i].c2y = parseFloat(a[i].c2y);
+      a[i].ex = a[i].ex.toFixed(1);
+      a[i].ex = parseFloat(a[i].ex);
+      a[i].ey = a[i].ey.toFixed(1);
+      a[i].ey = parseFloat(a[i].ey);
+    }
+    return a;
+  }
+  bethelDraw(point, is_fill, color) {
+    this.ctx.beginPath();
+    this.ctx.moveTo(point[0].mx, point[0].my);
+    if (undefined != color) {
+      this.ctx.setFillStyle(color);
+      this.ctx.setStrokeStyle(color);
+    } else {
+      this.ctx.setFillStyle(point[0].color);
+      this.ctx.setStrokeStyle(point[0].color);
+    }
+    for (let i = 1; i < point.length; i++) {
+      this.ctx.bezierCurveTo(point[i].c1x, point[i].c1y, point[i].c2x, point[i].c2y, point[i].ex, point[i].ey);
+    }
+    this.ctx.stroke();
+    if (undefined != is_fill) {
+      this.ctx.fill(); //填充图形 ( 后绘制的图形会覆盖前面的图形, 绘制时注意先后顺序 )
+    }
+    this.ctx.draw(true)
+  }
+
+  selectColorEvent(lineColor) {
+    this.lineColor = lineColor;
+  }
+
+  selectSlideValue(slideValue) {
+    switch (slideValue) {
+      case 0:
+        this.lineSize = 0.1;
+        this.lineMin = 0.1;
+        this.lineMax = 0.1;
+        break;
+      case 25:
+        this.lineSize = 1;
+        this.lineMin = 0.5;
+        this.lineMax = 2;
+        break;
+      case 50:
+        this.lineSize = 1.5;
+        this.lineMin = 1;
+        this.lineMax = 3;
+        break;
+      case 75:
+        this.lineSize = 1.5;
+        this.lineMin = 2;
+        this.lineMax = 3.5;
+        break;
+      case 100:
+        this.lineSize = 3;
+        this.lineMin = 2;
+        this.lineMax = 3.5;
+        break;
+    }
+  }
+	
+	saveCanvas(){
+		 return new Promise((resolve,rej) => {
+			uni.canvasToTempFilePath({
+				canvasId: this.canvasName,
+				success: function(res) {
+					console.log(res.tempFilePath)
+					resolve(res.tempFilePath);
+				},
+				 fail:function(err){
+					 console.log('图片生成失败:'+err)
+					 rej(err);
+				 }
+			})
+		})	
+	}	
+}
+
+export default Handwriting;

+ 86 - 0
components/ossutil/uploadFile.js

@@ -0,0 +1,86 @@
+const env = require('./config.js'); //配置文件,在这文件里配置你的OSS keyId和KeySecret,timeout:87600;
+
+const base64 = require('./base64.js');//Base64,hmac,sha1,crypto相关算法
+require('./hmac.js');
+require('./sha1.js');
+const Crypto = require('./crypto.js');
+
+/*
+ *上传文件到阿里云oss
+ *@param - filePath :图片的本地资源路径
+ *@param - dir:表示要传到哪个目录下
+ *@param - successc:成功回调
+ *@param - failc:失败回调
+ */ 
+const uploadFile = function (filePath, dir, successc, failc) {debugger
+  if (!filePath || filePath.length < 9) {
+    uni.showModal({
+      title: '图片错误',
+      content: '请重试',
+      showCancel: false,
+    })
+    return;
+  }
+  
+  //图片名字 可以自行定义,     这里是采用当前的时间戳 + 150内的随机数来给图片命名的
+  const aliyunFileKey = dir + new Date().getTime() + Math.floor(Math.random() * 150) + '.png';
+  
+  const aliyunServerURL = env.uploadImageUrl;//OSS地址,需要https
+  const accessid = env.OSSAccessKeyId;
+  const policyBase64 = getPolicyBase64();
+  const signature = getSignature(policyBase64);//获取签名
+ 
+  uni.uploadFile({
+    url: aliyunServerURL,//开发者服务器 url
+    filePath: filePath,//要上传文件资源的路径
+    name: 'file',//必须填file
+    formData: {
+      'key': aliyunFileKey,
+      'policy': policyBase64,
+      'OSSAccessKeyId': accessid,
+      'signature': signature,
+      'success_action_status': '200',
+    },
+    success: function (res) {
+			console.log(res);
+      if (res.statusCode != 200) {
+        failc(new Error('上传错误:' + JSON.stringify(res)))
+        return;
+      }
+       successc(aliyunServerURL+"/"+aliyunFileKey);
+    },
+    fail: function (err) {
+      err.wxaddinfo = aliyunServerURL;
+      failc(err);
+    },
+  })
+}
+
+const getPolicyBase64 = function () {
+  let date = new Date();
+  date.setHours(date.getHours() + env.timeout);
+  let srcT = date.toISOString();
+  const policyText = {
+    "expiration": srcT, //设置该Policy的失效时间,超过这个失效时间之后,就没有办法通过这个policy上传文件了 
+    "conditions": [
+      ["content-length-range", 0, 5 * 1024 * 1024] // 设置上传文件的大小限制,5mb
+    ]
+  };
+
+  const policyBase64 = base64.encode(JSON.stringify(policyText));
+	console.log(policyBase64);
+  return policyBase64;
+}
+
+const getSignature = function (policyBase64) {
+  const accesskey = env.AccessKeySecret;
+
+  const bytes = Crypto.HMAC(Crypto.SHA1, policyBase64, accesskey, {
+    asBytes: true
+  });
+  const signature = Crypto.util.bytesToBase64(bytes);
+console.log(signature);
+  return signature;
+}
+
+module.exports = uploadFile;

+ 788 - 0
components/upload.vue

@@ -0,0 +1,788 @@
+<template>
+	<view class="u-upload" v-if="!disabled">
+		<view v-if="showUploadList" class="u-list-item u-preview-wrap" :class="{'customPreviewStyle':custom}"
+			v-for="(item, index) in lists" :key="index" :style="{
+				width: width + 'rpx',
+				height: width + 'rpx'
+			}">
+			<view v-if="deletable" class="u-delete-icon" @tap.stop="deleteItem(index)" :style="{
+					background: delBgColor,
+				}">
+				<u-icon class="u-icon" :name="delIcon" :size="delIconSize" :color="delColor"></u-icon>
+			</view>
+			<view v-if="showProgress && item.progress > 0 && !item.error" class="u-check-icon" @tap.stop="deleteItem(index)" :style="{
+					background: checkBgColor,
+				}">
+				<u-icon class="u-icon" :name="checkIcon" :size="checkIconSize" :color="checkColor"></u-icon>
+			</view>
+			<!-- <u-line-progress v-if="showProgress && item.progress > 0 && !item.error" :show-percent="false" height="16"
+				class="u-progress" :percent="item.progress"></u-line-progress> -->
+			<view @tap.stop="retry(index)" v-if="item.error" class="u-error-btn">点击重试</view>
+			<image @tap.stop="doPreviewImage(item.url || item.path, index)" class="u-preview-image" v-if="!item.isImage"
+				:src="item.url || item.path" :mode="imageMode"></image>
+		</view>
+		<slot name="file" :file="lists"></slot>
+		<view style="display: inline-block;" :style="{
+			background:custom?customBack:'transparent',
+			border:custom?customBorder:'1px solid transparent'
+		}" :class="custom?'customStyle':'default'"
+			@tap="selectFile" v-if="maxCount > lists.length">
+			<slot name="addBtn"></slot>
+			<img v-if="custom&&options.bgc!=''" :src="options.bgc" alt="" class="imgstyle">
+			<view class="u-list-item u-add-wrap" hover-class="u-add-wrap__hover" hover-stay-time="150" :style="{
+					width: width + 'rpx',
+					height: width + 'rpx'
+				}">
+				<u-icon v-if="custom&&!customBtn" name="camera-fill" class="" size="100" color="#617E8B"></u-icon>
+				<image v-if="custom&&customBtn" :style="{
+				width: customBtnWidth + 'px',
+				height: customBtnHeight + 'px'
+			}" :src="customBtnImage" mode=""></image>
+				<image v-if="!custom" style='width:23px;height:23px;' src="../static/images/xiangji-2.png" mode=""></image>
+				<view v-if="!custom" class="u-add-tips">{{ uploadText }}</view>
+				<view v-if="custom" :style="{
+				color: customBtnColor,
+				'font-size':customBtnFontSize+'px',
+			}" class="u-add-tips">{{ options.text }}</view>
+			</view>
+		</view>
+		<view @click='imgShow=false' v-if="imgShow" class="shade">
+			<image style='position:absolute;top:0;left:0;right:0;bottom:0;margin:auto;' :src="url" mode=""></image>
+		</view>
+		<!-- <view class="custom-style" v-if="custom"
+					:style="{backgroundImage: 'url(' + options.bgc + ')', backgroundSize:'100% 100%'}">
+
+		</view> -->
+	</view>
+</template>
+
+<script>
+	/**
+	 * upload 图片上传
+	 * @description 该组件用于上传图片场景
+	 * @tutorial https://www.uviewui.com/components/upload.html
+	 * @property {String} action 服务器上传地址
+	 * @property {String Number} max-count 最大选择图片的数量(默认99)
+	 * @property {Boolean} custom-btn 如果需要自定义选择图片的按钮,设置为true(默认false)
+	 * @property {Boolean} show-progress 是否显示进度条(默认true)
+	 * @property {Boolean} disabled 是否启用(显示/移仓)组件(默认false)
+	 * @property {String} image-mode 预览图片等显示模式,可选值为uni的image的mode属性值(默认aspectFill)
+	 * @property {String} del-icon 右上角删除图标名称,只能为uView内置图标
+	 * @property {String} del-bg-color 右上角关闭按钮的背景颜色
+	 * @property {String} del-color 右上角关闭按钮图标的颜色
+	 * @property {Object} header 上传携带的头信息,对象形式
+	 * @property {Object} form-data 上传额外携带的参数
+	 * @property {String} name 上传文件的字段名,供后端获取使用(默认file)
+	 * @property {Array<String>} size-type original 原图,compressed 压缩图,默认二者都有(默认['original', 'compressed'])
+	 * @property {Array<String>} source-type 选择图片的来源,album-从相册选图,camera-使用相机,默认二者都有(默认['album', 'camera'])
+	 * @property {Boolean} preview-full-image	是否可以通过uni.previewImage预览已选择的图片(默认true)
+	 * @property {Boolean} multiple	是否开启图片多选,部分安卓机型不支持(默认true)
+	 * @property {Boolean} deletable 是否显示删除图片的按钮(默认true)
+	 * @property {String Number} max-size 选择单个文件的最大大小,单位B(byte),默认不限制(默认Number.MAX_VALUE)
+	 * @property {Array<Object>} file-list 默认显示的图片列表,数组元素为对象,必须提供url属性
+	 * @property {Boolean} upload-text 选择图片按钮的提示文字(默认“选择图片”)
+	 * @property {Boolean} auto-upload 选择完图片是否自动上传,见上方说明(默认true)
+	 * @property {Boolean} show-tips 特殊情况下是否自动提示toast,见上方说明(默认true)
+	 * @property {Boolean} show-upload-list 是否显示组件内部的图片预览(默认true)
+	 * @event {Function} on-oversize 图片大小超出最大允许大小
+	 * @event {Function} on-preview 全屏预览图片时触发
+	 * @event {Function} on-remove 移除图片时触发
+	 * @event {Function} on-success 图片上传成功时触发
+	 * @event {Function} on-change 图片上传后,无论成功或者失败都会触发
+	 * @event {Function} on-error 图片上传失败时触发
+	 * @event {Function} on-progress 图片上传过程中的进度变化过程触发
+	 * @event {Function} on-uploaded 所有图片上传完毕触发
+	 * @event {Function} on-choose-complete 每次选择图片后触发,只是让外部可以得知每次选择后,内部的文件列表
+	 * @example <u-upload :action="action" :file-list="fileList" ></u-upload>
+	 */
+
+	import uploadImage from '@/components/ossutil/uploadFile.js';
+	export default {
+		name: 'upload',
+		props: {
+			//是否显示组件自带的图片预览功能
+			showUploadList: {
+				type: Boolean,
+				default: true
+			},
+			// 后端地址
+			action: {
+				type: String,
+				default: ''
+			},
+			// 最大上传数量
+			maxCount: {
+				type: [String, Number],
+				default: 52,
+				},
+			// 删除图标大小
+			delIconSize:{
+				type: String,
+				default: '20'
+			},
+			//  是否显示进度条
+			showProgress: {
+				type: Boolean,
+				default: true
+			},
+			// 是否启用
+			disabled: {
+				type: Boolean,
+				default: false
+			},
+			// 预览上传的图片时的裁剪模式,和image组件mode属性一致
+			imageMode: {
+				type: String,
+				default: 'aspectFill'
+			},
+			// 头部信息
+			header: {
+				type: Object,
+				default () {
+					return {};
+				}
+			},
+			// 额外携带的参数
+			formData: {
+				type: Object,
+				default () {
+					return {};
+				}
+			},
+			// 上传的文件字段名
+			name: {
+				type: String,
+				default: 'file'
+			},
+			// 所选的图片的尺寸, 可选值为original compressed
+			sizeType: {
+				type: Array,
+				default () {
+					return ['original', 'compressed'];
+				}
+			},
+			sourceType: {
+				type: Array,
+				default () {
+					return ['album', 'camera'];
+				}
+			},
+			// 成功背景颜色
+			checkBgColor:{
+				type: String,
+				default: '#22C572'
+			},
+			// 成功icon颜色
+			checkColor:{
+				type: String,
+				default: '#fff'
+			},
+			// 成功icon颜色
+			checkIcon:{
+				type: String,
+				default: 'checkbox-mark'
+			},
+			// 成功icon颜色
+			checkIconSize:{
+				type: String,
+				default: '20'
+			},
+			// 是否在点击预览图后展示全屏图片预览
+			previewFullImage: {
+				type: Boolean,
+				default: true
+			},
+			// 是否开启图片多选,部分安卓机型不支持
+			multiple: {
+				type: Boolean,
+				default: true
+			},
+			// 是否展示删除按钮
+			deletable: {
+				type: Boolean,
+				default: true
+			},
+			// 文件大小限制,单位为byte
+			maxSize: {
+				type: [String, Number],
+				default: Number.MAX_VALUE
+			},
+			// 显示已上传的文件列表
+			fileList: {
+				type: Array,
+				default () {
+					return [];
+				}
+			},
+			// 上传区域的提示文字
+			uploadText: {
+				type: String,
+				default: '选择图片'
+			},
+			// 是否自动上传
+			autoUpload: {
+				type: Boolean,
+				default: true
+			},
+			// 是否显示toast消息提示
+			showTips: {
+				type: Boolean,
+				default: true
+			},
+			// 是否通过slot自定义传入选择图标的按钮
+			customBtn: {
+				type: Boolean,
+				default: false
+			},
+			customBtnImage: {
+				type: String,
+				default: ''
+			},
+			customBtnWidth: {
+				type: Number,
+				default: 0
+			},
+			customBtnHeight: {
+				type: Number,
+				default: 0
+			},
+			customBtnColor: {
+				type: String,
+				default: '#617E8B'
+			},
+			customBack:{
+				type: String,
+				default: '#F5F6FA'
+			},
+			customBorder:{
+				type: String,
+				// default: '2px dashed #C6CBCE'
+			},
+			customBtnFontSize:{
+				type: String,
+				default: '18'
+			},
+			// 内部预览图片区域和选择图片按钮的区域宽度,高等于宽
+			width: {
+				type: [String, Number],
+				default: 200
+			},
+			// 右上角关闭按钮的背景颜色
+			delBgColor: {
+				type: String,
+				default: '#fa3534'
+			},
+			// 右上角关闭按钮的叉号图标的颜色
+			delColor: {
+				type: String,
+				default: '#ffffff'
+			},
+			// 右上角删除图标名称,只能为uView内置图标
+			delIcon: {
+				type: String,
+				default: 'close'
+			},
+			// 如果上传后的返回值为json字符串,是否自动转json
+			toJson: {
+				type: Boolean,
+				default: true
+			},
+			// 上传前的钩子,每个文件上传前都会执行
+			beforeUpload: {
+				type: Function,
+				default: null
+			},
+			options: {
+				type: Object,
+				default: null
+			},
+			custom: {
+				type: Boolean,
+				default: false
+			},
+			imgIndex:{
+				type: Number,
+				default: 0
+			}
+		},
+		mounted() {},
+		data() {
+			return {
+				lists: [],
+				isInCount: true,
+				uploading: false,
+				isSelectFile: false,
+				imgShow:false,
+				url:''
+			};
+		},
+		watch: {
+			fileList: {
+				immediate: true,
+				handler(val) {
+					val.map(value => {
+						this.lists.push({
+							url: value.url,
+							error: false,
+							progress: 100
+						});
+					});
+				}
+			}
+		},
+		methods: {
+			// 清除列表
+			clear() {
+				this.lists = [];
+				// 如果是清空形式的话,发出"on-list-change"事件
+				this.$emit('on-list-change', this.lists);
+			},
+			// 重新上传队列中上传失败的所有文件
+			reUpload() {
+				this.uploadFile();
+			},
+			// 选择图片
+			selectFile() {
+				if (this.disabled) return;
+				const {
+					name = '', maxCount, multiple, maxSize, sizeType, lists, camera, compressed, maxDuration, sourceType
+				} = this;
+				let chooseFile = null;
+				const newMaxCount = maxCount - lists.length;
+				// 设置为只选择图片的时候使用 chooseImage 来实现
+				chooseFile = new Promise((resolve, reject) => {
+					uni.chooseImage({
+						count: multiple ? (newMaxCount > 9 ? 9 : newMaxCount) : 1,
+						sourceType: sourceType,
+						sizeType,
+						success: resolve,
+						fail: reject
+					});
+				});
+				chooseFile
+					.then(res => {
+						let file = null;
+						let listOldLength = this.lists.length;
+						res.tempFiles.map((val, index) => {
+							// 如果是非多选,index大于等于1或者超出最大限制数量时,不处理
+							if (!multiple && index >= 1) return;
+							if (val.size > maxSize) {
+								this.$emit('on-oversize', val, this.lists);
+								this.showToast('超出允许的文件大小');
+							} else {
+								if (maxCount <= lists.length) {
+									this.$emit('on-exceed', val, this.lists);
+									this.showToast('超出最大允许的文件个数');
+									return;
+								}
+								let fileName = '';
+								let fileNameLength = '';
+								let fileFormat = '';
+								//#ifdef H5
+								fileName = val.name.lastIndexOf(".");
+								fileNameLength = val.name.length;
+								fileFormat = val.name.substring(fileName + 1, fileNameLength).toLowerCase();
+								//#endif
+								//#ifndef H5
+								fileName = val.path.lastIndexOf(".");
+								fileNameLength = val.path.length;
+								fileFormat = val.path.substring(fileName + 1, fileNameLength).toLowerCase();
+								//#endif
+								lists.push({
+									url: val.path,
+									fileType: fileFormat,
+									progress: 0,
+									error: false
+								});
+								// 列表发生改变,发出事件,第二个参数为当前发生变化的项的索引
+								this.$emit('on-list-change', this.lists);
+							}
+						});
+						// 每次图片选择完,抛出一个事件,并将当前内部选择的图片数组抛出去
+						this.$emit('on-choose-complete', this.lists);
+						if (this.autoUpload) this.uploadFile(listOldLength);
+					})
+					.catch(error => {
+						this.$emit('on-error', error);
+					});
+			},
+			// 提示用户消息
+			showToast(message, force = false) {
+				if (this.showTips || force) {
+					uni.showToast({
+						title: message,
+						icon: 'none'
+					});
+				}
+			},
+			// 该方法供用户通过ref调用,手动上传
+			upload() {
+				this.uploadFile();
+			},
+			// 对失败的图片重新上传
+			retry(index) {
+				this.lists[index].progress = 0;
+				this.lists[index].error = false;
+				this.lists[index].response = null;
+				uni.showLoading({
+					title: '重新上传'
+				});
+				this.uploadFile(index);
+			},
+			// 上传图片
+			async uploadFile(index = 0) {
+				if (this.disabled) return;
+				if (this.uploading) return;
+				// 全部上传完成
+				if (index >= this.lists.length) {
+					this.isSelectFile = true
+					this.$emit('on-uploaded', this.lists);
+					return;
+				}
+				// 检查上传地址
+				if (!this.action) {
+					this.showToast('请配置上传地址', true);
+					return;
+				}
+				// 检查是否是已上传或者正在上传中
+				if (this.lists[index].progress == 100) {
+					if (this.autoUpload == false) this.uploadFile(index + 1);
+					return;
+				}
+				// 执行before-upload钩子
+				if (this.beforeUpload && typeof(this.beforeUpload) === 'function') {
+					// 执行回调,同时传入索引和文件列表当作参数
+					let beforeResponse = this.beforeUpload(index, this.lists);
+					// 判断是否返回了promise
+					if (!!beforeResponse && typeof beforeResponse.then === 'function') {
+						await beforeResponse.then(res => {
+							// promise返回成功,不进行动作,继续上传
+						}).catch(err => {
+							// 进入catch回调的话,继续下一张
+							return this.uploadFile(index + 1);
+						})
+					} else if (beforeResponse === false) {
+						// 如果返回false,继续下一张图片的上传
+						return this.uploadFile(index + 1);
+					}
+				}
+				this.lists[index].error = false;
+				this.uploading = true;
+				uploadImage(this.lists[index].url, 'appData/',
+					result => {
+						console.log
+						// 上传成功
+						this.lists[index].response = result;
+						this.lists[index].progress = 100;
+						this.lists[index].error = false;
+						let data = result
+						this.$emit('on-success', data, index, this.lists,this.imgIndex);
+						uni.hideLoading();
+						this.uploading = false;
+						this.uploadFile(index + 1);
+						this.$emit('on-change', data, index, this.lists,this.imgIndex);
+					}
+				)
+				// 创建上传对象
+				// const task = uni.uploadFile({
+				// 	url: this.action,
+				// 	filePath: this.lists[index].url,
+				// 	name: this.name,
+				// 	formData: this.formData,
+				// 	header: this.header,
+				// 	success: res => {
+				// 		// 判断是否json字符串,将其转为json格式
+				// 		let data = this.toJson && this.checkIsJSON(res.data) ? JSON.parse(res.data) : res
+				// 			.data;
+				// 		if (![200, 201].includes(res.statusCode)) {
+				// 			this.uploadError(index, data);
+				// 		} else {
+				// 			// 上传成功
+				// 			this.lists[index].response = data;
+				// 			this.lists[index].progress = 100;
+				// 			this.lists[index].error = false;
+				// 			// this.$emit('on-success', data, index, this.lists);
+				// 		}
+				// 	},
+				// 	fail: e => {
+				// 		this.uploadError(index, e);
+				// 	},
+				// 	complete: res => {
+				// 		uni.hideLoading();
+				// 		this.uploading = false;
+				// 		this.uploadFile(index + 1);
+				// 		this.$emit('on-change', res, index, this.lists);
+				// 	}
+				// });
+				// task.onProgressUpdate(res => {
+				// 	if (res.progress > 0) {
+				// 		this.lists[index].progress = res.progress;
+				// 		this.$emit('on-progress', res, index, this.lists);
+				// 	}
+				// });
+			},
+			// 上传失败
+			uploadError(index, err) {
+				this.lists[index].progress = 0;
+				this.lists[index].error = true;
+				this.lists[index].response = null;
+				this.$emit('on-error', err, index, this.lists);
+				this.showToast('上传失败,请重试');
+			},
+			// 删除一个图片
+			deleteItem(index) {
+				uni.showModal({
+					title: '提示',
+					content: '您确定要删除此项吗?',
+					success: res => {
+						if (res.confirm) {
+							this.isSelectFile = false
+							if (this.lists[index].process < 100 && this.lists[index].process > 0) {
+								typeof this.lists[index].uploadTask != 'undefined' && this.lists[index]
+									.uploadTask.abort();
+							}
+							this.lists.splice(index, 1);
+							this.$forceUpdate();
+							this.$emit('on-remove', index, this.lists);
+							this.showToast('移除成功');
+							// 列表发生改变,发出事件
+							this.$emit('on-list-change', this.lists);
+						}
+					}
+				});
+			},
+			// 用户通过ref手动的形式,移除一张图片
+			remove(index) {
+				// 判断索引的合法范围
+				if (index >= 0 && index < this.lists.length) {
+					this.lists.splice(index, 1);
+					this.$emit('on-list-change', this.lists);
+				}
+			},
+			// 预览图片
+			doPreviewImage(url, index) {
+				console.log(this.lists,url,index)
+				if (!this.previewFullImage) return;
+				const images = this.lists.map(item => item.url || item.path);
+				this.url=url
+				this.imgShow=true
+				// 图片预览调用onShow清空数据
+				// uni.previewImage({
+				// 	urls: images,
+				// 	current: url,
+				// 	success: () => {
+				// 		this.$emit('on-preview', url, this.lists);
+				// 	},
+				// 	fail: () => {
+				// 		uni.showToast({
+				// 			title: '预览图片失败',
+				// 			icon: 'none'
+				// 		});
+				// 	}
+				// });
+			},
+			// 判断是否json字符串
+			checkIsJSON(str) {
+				if (typeof str == 'string') {
+					try {
+						var obj = JSON.parse(str);
+						if (typeof obj == 'object' && obj) {
+							return true;
+						} else {
+							return false;
+						}
+					} catch (e) {
+						return false;
+					}
+				}
+				return false;
+			}
+		}
+	};
+</script>
+
+<style lang="scss" scoped>
+	// nvue不能用标签命名样式
+	/* #ifndef APP-NVUE */
+	image {
+		display: inline-block;
+		// 解决图片加载时可能会瞬间变形的问题
+		will-change: transform;
+	}
+
+	view,
+	text {
+		box-sizing: border-box;
+		flex-direction: row;
+	}
+
+	/* #endif */
+	.u-upload {
+		display: flex;
+		flex-wrap: wrap;
+		align-items: center;
+	}
+
+	.u-list-item {
+		width: 200rpx;
+		height: 200rpx;
+		overflow: hidden;
+		// margin: 10rpx;
+		background: rgb(244, 245, 246);
+		position: relative;
+		border-radius: 10rpx;
+		display: inline-flex;
+		align-items: center;
+		justify-content: center;
+	}
+
+	.u-preview-wrap {
+		border: 1px solid rgb(235, 236, 238);
+	}
+
+	.u-add-wrap {
+		flex-direction: column;
+		color: $u-content-color;
+		font-size: 28rpx;
+	}
+
+	.u-add-tips {
+		margin-top: 20rpx;
+	}
+
+	.u-add-wrap__hover {
+		background-color: rgb(235, 236, 238);
+	}
+
+	.u-preview-image {
+		display: block;
+		width: 100%;
+		height: 100%;
+		border-radius: 10rpx;
+	}
+
+	.u-delete-icon {
+		position: absolute;
+		top: 0rpx;
+		right: 0rpx;
+		z-index: 10;
+		background-color: $u-error;
+		border-radius:0 0 0 10rpx;
+		width: 44rpx;
+		height: 44rpx;
+		display: flex;
+		align-items: center;
+		justify-content: center;
+	}
+
+	.u-icon {
+		display: flex;
+		align-items: center;
+		justify-content: center;
+	}
+
+	.u-progress {
+		position: absolute;
+		bottom: 10rpx;
+		left: 8rpx;
+		right: 8rpx;
+		z-index: 9;
+		width: auto;
+	}
+
+	.u-error-btn {
+		color: #ffffff;
+		background-color: $u-error;
+		font-size: 20rpx;
+		padding: 4px 0;
+		text-align: center;
+		position: absolute;
+		bottom: 0;
+		left: 0;
+		right: 0;
+		z-index: 9;
+		line-height: 1;
+	}
+	.customStyleBgc {
+		width: 100% !important;
+		height: 440rpx !important;
+		display: flex !important;
+		justify-content: center;
+		align-items: center;
+		position: relative;
+
+		.u-add-wrap {
+			width: 100% !important;
+			height: 100% !important;
+			background: transparent;
+		}
+
+		.u-add-tips {
+			font-size: 18px;
+			font-weight: 600;
+			color: #617E8B;
+		}
+	}
+
+	.customStyle {
+		width: 712rpx !important;
+		height: 440rpx !important;
+		background: #F5F6FA;
+		border-radius: 20rpx;
+		// border: 2px dashed #C6CBCE;
+		display: flex !important;
+		justify-content: center;
+		align-items: center;
+		position: relative;
+
+		.u-add-wrap {
+			width: 100% !important;
+			height: 100% !important;
+			background: transparent;
+		}
+
+		.u-add-tips {
+			font-size: 18px;
+			font-weight: 600;
+			color: #617E8B;
+		}
+	}
+
+	.customPreviewStyle {
+		width: 100% !important;
+		height: 440rpx !important;
+	}
+
+	.imgstyle {
+		width: 100% !important;
+		height: 440rpx !important;
+		position: absolute;
+	}
+	.default{
+		
+		.u-list-item.u-add-wrap{
+			background:#fff;
+			border:1px dashed #AFB3BF;
+		}
+	}
+	.shade{
+		background:#000;
+		position:fixed;
+		top:0;left:0;
+	   width:100%;height:100%;
+	   z-index:10000;
+	}
+	.u-check-icon{
+		position: absolute;
+		bottom: 0rpx;
+		left: 0rpx;
+		z-index: 10;
+		background-color: $u-error;
+		border-radius:0 0 0 10rpx;
+		width: 44rpx;
+		height: 44rpx;
+		display: flex;
+		align-items: center;
+		justify-content: center;
+	}
+</style>

+ 10 - 0
config/index.js

@@ -0,0 +1,10 @@
+const dev = {
+	baseUrlNew: 'http://192.168.1.121:8090',
+	h5Appid: 'wxb66b599f7f61b46f',
+	debug: false
+}
+
+export function def() {
+	return dev
+}
+

+ 103 - 0
demo.vue

@@ -0,0 +1,103 @@
+<template>
+	<view class="content">
+		常用
+		1、延时一定时间进行回调
+		2、获取父组件this
+		3、节流防抖
+		4、对象克隆
+		5、路由跳转
+		6、对象修改为地址栏传参
+		7、常用规则校验
+		8、toast消息提示
+		9、弹框提示
+		10、请求方法
+		11、loading
+	</view>
+</template>
+
+<script>
+	export default {
+		// 此处为页面级,所以name值可选
+		name: 'page',
+		data() {
+			return {
+
+			}
+		},
+		onLoad() {
+
+		},
+		mounted() {
+			// 2、
+			// 将会得到父页面的this实例
+			uni.$u.$parent.call(this, 'page')
+		}
+		methods: {
+			demo() {
+				// 1、
+				// 300ms后触发回调
+				uni.$u.sleep(300).then(() => {
+					console.log('定时结束')
+				})
+				// 3、
+				// <view class="throttle" @tap="$u.throttle(btnAClick, 500)">
+				// uni.$u.throttle(this.toNext, 500)
+				// <view class="debounce" @tap="$u.debounce(btnAClick, 500)">
+				// uni.$u.debounce(this.toNext, 500)
+				// 4、
+				let b = uni.$u.deepClone(a);
+				// 5、
+				// 无参数
+				uni.$u.route('/pages/components/empty/index');
+				// 带参数
+				uni.$u.route('/pages/goodSource/shippingDetails', {
+					id: 1,
+				});
+				// 6、
+				uni.$u.queryParams(this.data)
+				// 7、
+				uni.$u.test.idCard('110101199003070134')
+				// 8、
+				// default/error/success/loading
+				// <u-toast ref="uToast"></u-toast>
+				// let params = {
+				// 		type: 'success',
+				// 		title: '成功主题(带图标)',
+				// 		message: "庄生晓梦迷蝴蝶",
+				// 		iconUrl: 'https://cdn.uviewui.com/uview/demo/toast/success.png'
+				// 	}
+				// this.$refs.uToast.show({
+				// 	...params,
+				// 	complete() {
+				// 		params.url && uni.navigateTo({
+				// 			url: params.url
+				// 		})
+				// 	}
+				// })
+				// uni.$u.toast('倒计时结束后再发送');
+				// 9、
+				// <u-modal :show="isShowAlert" :title="alertTitle" :content='alertContent' :closeOnClickOverlay='true' :showCancelButton='true' confirmColor='#22C572'  @confirm="confirmClick" @close="cancelClick" @cancel="cancelClick"></u-modal>
+				// 10、
+				// that.$request.baseRequest('get', '/commonUser/loginVerifyCode', {
+				// 		phone: that.model1.phone,
+				// 		verifyCode: that.model1.code
+				// 	}).then(res => {
+							
+				
+				// 	})
+				// 	.catch(res => {
+				// 		uni.showToast({
+				// 			title: res.message,
+				// 			icon: 'none',
+				// 			duration: 2000
+				// 		})
+				// 	});
+				// 11、
+				// 	uni.showLoading({
+				// 				title: '登录中',
+				// 				mask: true
+				// 			})
+			}
+		}
+	}
+</script>

+ 20 - 0
index.html

@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="UTF-8" />
+    <script>
+      var coverSupport = 'CSS' in window && typeof CSS.supports === 'function' && (CSS.supports('top: env(a)') ||
+        CSS.supports('top: constant(a)'))
+      document.write(
+        '<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0' +
+        (coverSupport ? ', viewport-fit=cover' : '') + '" />')
+    </script>
+    <title></title>
+    <!--preload-links-->
+    <!--app-context-->
+  </head>
+  <body>
+    <div id="app"><!--app-html--></div>
+    <script type="module" src="/main.js"></script>
+  </body>
+</html>

BIN
js_sdk/js-amap/__MACOSX/._amap-wx.130.js


+ 31 - 0
js_sdk/js-amap/amap-wx.130.js

@@ -0,0 +1,31 @@
+function AMapWX(a){this.key=a.key;this.requestConfig={key:a.key,s:"rsx",platform:"WXJS",appname:a.key,sdkversion:"1.2.0",logversion:"2.0"};this.MeRequestConfig={key:a.key,serviceName:"https://restapi.amap.com/rest/me"}}
+AMapWX.prototype.getWxLocation=function(a,b){wx.getLocation({type:"gcj02",success:function(c){c=c.longitude+","+c.latitude;wx.setStorage({key:"userLocation",data:c});b(c)},fail:function(c){wx.getStorage({key:"userLocation",success:function(d){d.data&&b(d.data)}});a.fail({errCode:"0",errMsg:c.errMsg||""})}})};
+AMapWX.prototype.getMEKeywordsSearch=function(a){if(!a.options)return a.fail({errCode:"0",errMsg:"\u7f3a\u5c11\u5fc5\u8981\u53c2\u6570"});var b=a.options,c=this.MeRequestConfig,d={key:c.key,s:"rsx",platform:"WXJS",appname:a.key,sdkversion:"1.2.0",logversion:"2.0"};b.layerId&&(d.layerId=b.layerId);b.keywords&&(d.keywords=b.keywords);b.city&&(d.city=b.city);b.filter&&(d.filter=b.filter);b.sortrule&&(d.sortrule=b.sortrule);b.pageNum&&(d.pageNum=b.pageNum);b.pageSize&&(d.pageSize=b.pageSize);b.sig&&(d.sig=
+b.sig);wx.request({url:c.serviceName+"/cpoint/datasearch/local",data:d,method:"GET",header:{"content-type":"application/json"},success:function(e){(e=e.data)&&e.status&&"1"===e.status&&0===e.code?a.success(e.data):a.fail({errCode:"0",errMsg:e})},fail:function(e){a.fail({errCode:"0",errMsg:e.errMsg||""})}})};
+AMapWX.prototype.getMEIdSearch=function(a){if(!a.options)return a.fail({errCode:"0",errMsg:"\u7f3a\u5c11\u5fc5\u8981\u53c2\u6570"});var b=a.options,c=this.MeRequestConfig,d={key:c.key,s:"rsx",platform:"WXJS",appname:a.key,sdkversion:"1.2.0",logversion:"2.0"};b.layerId&&(d.layerId=b.layerId);b.id&&(d.id=b.id);b.sig&&(d.sig=b.sig);wx.request({url:c.serviceName+"/cpoint/datasearch/id",data:d,method:"GET",header:{"content-type":"application/json"},success:function(e){(e=e.data)&&e.status&&"1"===e.status&&
+0===e.code?a.success(e.data):a.fail({errCode:"0",errMsg:e})},fail:function(e){a.fail({errCode:"0",errMsg:e.errMsg||""})}})};
+AMapWX.prototype.getMEPolygonSearch=function(a){if(!a.options)return a.fail({errCode:"0",errMsg:"\u7f3a\u5c11\u5fc5\u8981\u53c2\u6570"});var b=a.options,c=this.MeRequestConfig,d={key:c.key,s:"rsx",platform:"WXJS",appname:a.key,sdkversion:"1.2.0",logversion:"2.0"};b.layerId&&(d.layerId=b.layerId);b.keywords&&(d.keywords=b.keywords);b.polygon&&(d.polygon=b.polygon);b.filter&&(d.filter=b.filter);b.sortrule&&(d.sortrule=b.sortrule);b.pageNum&&(d.pageNum=b.pageNum);b.pageSize&&(d.pageSize=b.pageSize);
+b.sig&&(d.sig=b.sig);wx.request({url:c.serviceName+"/cpoint/datasearch/polygon",data:d,method:"GET",header:{"content-type":"application/json"},success:function(e){(e=e.data)&&e.status&&"1"===e.status&&0===e.code?a.success(e.data):a.fail({errCode:"0",errMsg:e})},fail:function(e){a.fail({errCode:"0",errMsg:e.errMsg||""})}})};
+AMapWX.prototype.getMEaroundSearch=function(a){if(!a.options)return a.fail({errCode:"0",errMsg:"\u7f3a\u5c11\u5fc5\u8981\u53c2\u6570"});var b=a.options,c=this.MeRequestConfig,d={key:c.key,s:"rsx",platform:"WXJS",appname:a.key,sdkversion:"1.2.0",logversion:"2.0"};b.layerId&&(d.layerId=b.layerId);b.keywords&&(d.keywords=b.keywords);b.center&&(d.center=b.center);b.radius&&(d.radius=b.radius);b.filter&&(d.filter=b.filter);b.sortrule&&(d.sortrule=b.sortrule);b.pageNum&&(d.pageNum=b.pageNum);b.pageSize&&
+(d.pageSize=b.pageSize);b.sig&&(d.sig=b.sig);wx.request({url:c.serviceName+"/cpoint/datasearch/around",data:d,method:"GET",header:{"content-type":"application/json"},success:function(e){(e=e.data)&&e.status&&"1"===e.status&&0===e.code?a.success(e.data):a.fail({errCode:"0",errMsg:e})},fail:function(e){a.fail({errCode:"0",errMsg:e.errMsg||""})}})};
+AMapWX.prototype.getGeo=function(a){var b=this.requestConfig,c=a.options;b={key:this.key,extensions:"all",s:b.s,platform:b.platform,appname:this.key,sdkversion:b.sdkversion,logversion:b.logversion};c.address&&(b.address=c.address);c.city&&(b.city=c.city);c.batch&&(b.batch=c.batch);c.sig&&(b.sig=c.sig);wx.request({url:"https://restapi.amap.com/v3/geocode/geo",data:b,method:"GET",header:{"content-type":"application/json"},success:function(d){(d=d.data)&&d.status&&"1"===d.status?a.success(d):a.fail({errCode:"0",
+errMsg:d})},fail:function(d){a.fail({errCode:"0",errMsg:d.errMsg||""})}})};
+AMapWX.prototype.getRegeo=function(a){function b(d){var e=c.requestConfig;wx.request({url:"https://restapi.amap.com/v3/geocode/regeo",data:{key:c.key,location:d,extensions:"all",s:e.s,platform:e.platform,appname:c.key,sdkversion:e.sdkversion,logversion:e.logversion},method:"GET",header:{"content-type":"application/json"},success:function(g){if(g.data.status&&"1"==g.data.status){g=g.data.regeocode;var h=g.addressComponent,f=[],k=g.roads[0].name+"\u9644\u8fd1",m=d.split(",")[0],n=d.split(",")[1];if(g.pois&&
+g.pois[0]){k=g.pois[0].name+"\u9644\u8fd1";var l=g.pois[0].location;l&&(m=parseFloat(l.split(",")[0]),n=parseFloat(l.split(",")[1]))}h.provice&&f.push(h.provice);h.city&&f.push(h.city);h.district&&f.push(h.district);h.streetNumber&&h.streetNumber.street&&h.streetNumber.number?(f.push(h.streetNumber.street),f.push(h.streetNumber.number)):f.push(g.roads[0].name);f=f.join("");a.success([{iconPath:a.iconPath,width:a.iconWidth,height:a.iconHeight,name:f,desc:k,longitude:m,latitude:n,id:0,regeocodeData:g}])}else a.fail({errCode:g.data.infocode,
+errMsg:g.data.info})},fail:function(g){a.fail({errCode:"0",errMsg:g.errMsg||""})}})}var c=this;a.location?b(a.location):c.getWxLocation(a,function(d){b(d)})};
+AMapWX.prototype.getWeather=function(a){function b(g){var h="base";a.type&&"forecast"==a.type&&(h="all");wx.request({url:"https://restapi.amap.com/v3/weather/weatherInfo",data:{key:d.key,city:g,extensions:h,s:e.s,platform:e.platform,appname:d.key,sdkversion:e.sdkversion,logversion:e.logversion},method:"GET",header:{"content-type":"application/json"},success:function(f){if(f.data.status&&"1"==f.data.status)if(f.data.lives){if((f=f.data.lives)&&0<f.length){f=f[0];var k={city:{text:"\u57ce\u5e02",data:f.city},
+weather:{text:"\u5929\u6c14",data:f.weather},temperature:{text:"\u6e29\u5ea6",data:f.temperature},winddirection:{text:"\u98ce\u5411",data:f.winddirection+"\u98ce"},windpower:{text:"\u98ce\u529b",data:f.windpower+"\u7ea7"},humidity:{text:"\u6e7f\u5ea6",data:f.humidity+"%"}};k.liveData=f;a.success(k)}}else f.data.forecasts&&f.data.forecasts[0]&&a.success({forecast:f.data.forecasts[0]});else a.fail({errCode:f.data.infocode,errMsg:f.data.info})},fail:function(f){a.fail({errCode:"0",errMsg:f.errMsg||""})}})}
+function c(g){wx.request({url:"https://restapi.amap.com/v3/geocode/regeo",data:{key:d.key,location:g,extensions:"all",s:e.s,platform:e.platform,appname:d.key,sdkversion:e.sdkversion,logversion:e.logversion},method:"GET",header:{"content-type":"application/json"},success:function(h){if(h.data.status&&"1"==h.data.status){h=h.data.regeocode;if(h.addressComponent)var f=h.addressComponent.adcode;else h.aois&&0<h.aois.length&&(f=h.aois[0].adcode);b(f)}else a.fail({errCode:h.data.infocode,errMsg:h.data.info})},
+fail:function(h){a.fail({errCode:"0",errMsg:h.errMsg||""})}})}var d=this,e=d.requestConfig;a.city?b(a.city):d.getWxLocation(a,function(g){c(g)})};
+AMapWX.prototype.getPoiAround=function(a){function b(e){e={key:c.key,location:e,s:d.s,platform:d.platform,appname:c.key,sdkversion:d.sdkversion,logversion:d.logversion};a.querytypes&&(e.types=a.querytypes);a.querykeywords&&(e.keywords=a.querykeywords);wx.request({url:"https://restapi.amap.com/v3/place/around",data:e,method:"GET",header:{"content-type":"application/json"},success:function(g){if(g.data.status&&"1"==g.data.status){if((g=g.data)&&g.pois){for(var h=[],f=0;f<g.pois.length;f++){var k=0==
+f?a.iconPathSelected:a.iconPath;h.push({latitude:parseFloat(g.pois[f].location.split(",")[1]),longitude:parseFloat(g.pois[f].location.split(",")[0]),iconPath:k,width:22,height:32,id:f,name:g.pois[f].name,address:g.pois[f].address})}a.success({markers:h,poisData:g.pois})}}else a.fail({errCode:g.data.infocode,errMsg:g.data.info})},fail:function(g){a.fail({errCode:"0",errMsg:g.errMsg||""})}})}var c=this,d=c.requestConfig;a.location?b(a.location):c.getWxLocation(a,function(e){b(e)})};
+AMapWX.prototype.getStaticmap=function(a){function b(e){c.push("location="+e);a.zoom&&c.push("zoom="+a.zoom);a.size&&c.push("size="+a.size);a.scale&&c.push("scale="+a.scale);a.markers&&c.push("markers="+a.markers);a.labels&&c.push("labels="+a.labels);a.paths&&c.push("paths="+a.paths);a.traffic&&c.push("traffic="+a.traffic);e="https://restapi.amap.com/v3/staticmap?"+c.join("&");a.success({url:e})}var c=[];c.push("key="+this.key);var d=this.requestConfig;c.push("s="+d.s);c.push("platform="+d.platform);
+c.push("appname="+d.appname);c.push("sdkversion="+d.sdkversion);c.push("logversion="+d.logversion);a.location?b(a.location):this.getWxLocation(a,function(e){b(e)})};
+AMapWX.prototype.getInputtips=function(a){var b=Object.assign({},this.requestConfig);a.location&&(b.location=a.location);a.keywords&&(b.keywords=a.keywords);a.type&&(b.type=a.type);a.city&&(b.city=a.city);a.citylimit&&(b.citylimit=a.citylimit);wx.request({url:"https://restapi.amap.com/v3/assistant/inputtips",data:b,method:"GET",header:{"content-type":"application/json"},success:function(c){c&&c.data&&c.data.tips&&a.success({tips:c.data.tips})},fail:function(c){a.fail({errCode:"0",errMsg:c.errMsg||
+""})}})};
+AMapWX.prototype.getDrivingRoute=function(a){var b=Object.assign({},this.requestConfig);a.origin&&(b.origin=a.origin);a.destination&&(b.destination=a.destination);a.strategy&&(b.strategy=a.strategy);a.waypoints&&(b.waypoints=a.waypoints);a.avoidpolygons&&(b.avoidpolygons=a.avoidpolygons);a.avoidroad&&(b.avoidroad=a.avoidroad);wx.request({url:"https://restapi.amap.com/v3/direction/driving",data:b,method:"GET",header:{"content-type":"application/json"},success:function(c){c&&c.data&&c.data.route&&a.success({paths:c.data.route.paths,
+taxi_cost:c.data.route.taxi_cost||""})},fail:function(c){a.fail({errCode:"0",errMsg:c.errMsg||""})}})};
+AMapWX.prototype.getWalkingRoute=function(a){var b=Object.assign({},this.requestConfig);a.origin&&(b.origin=a.origin);a.destination&&(b.destination=a.destination);wx.request({url:"https://restapi.amap.com/v3/direction/walking",data:b,method:"GET",header:{"content-type":"application/json"},success:function(c){c&&c.data&&c.data.route&&a.success({paths:c.data.route.paths})},fail:function(c){a.fail({errCode:"0",errMsg:c.errMsg||""})}})};
+AMapWX.prototype.getTransitRoute=function(a){var b=Object.assign({},this.requestConfig);a.origin&&(b.origin=a.origin);a.destination&&(b.destination=a.destination);a.strategy&&(b.strategy=a.strategy);a.city&&(b.city=a.city);a.cityd&&(b.cityd=a.cityd);wx.request({url:"https://restapi.amap.com/v3/direction/transit/integrated",data:b,method:"GET",header:{"content-type":"application/json"},success:function(c){c&&c.data&&c.data.route&&(c=c.data.route,a.success({distance:c.distance||"",taxi_cost:c.taxi_cost||
+"",transits:c.transits}))},fail:function(c){a.fail({errCode:"0",errMsg:c.errMsg||""})}})};
+AMapWX.prototype.getRidingRoute=function(a){var b=Object.assign({},this.requestConfig);a.origin&&(b.origin=a.origin);a.destination&&(b.destination=a.destination);wx.request({url:"https://restapi.amap.com/v3/direction/riding",data:b,method:"GET",header:{"content-type":"application/json"},success:function(c){c&&c.data&&c.data.route&&a.success({paths:c.data.route.paths})},fail:function(c){a.fail({errCode:"0",errMsg:c.errMsg||""})}})};module.exports.AMapWX=AMapWX;

+ 272 - 0
js_sdk/wa-permission/permission.js

@@ -0,0 +1,272 @@
+/**
+ * 本模块封装了Android、iOS的应用权限判断、打开应用权限设置界面、以及位置系统服务是否开启
+ */
+
+var isIos
+// #ifdef APP-PLUS
+isIos = (plus.os.name == "iOS")
+// #endif
+
+// 判断推送权限是否开启
+function judgeIosPermissionPush() {
+	var result = false;
+	var UIApplication = plus.ios.import("UIApplication");
+	var app = UIApplication.sharedApplication();
+	var enabledTypes = 0;
+	if (app.currentUserNotificationSettings) {
+		var settings = app.currentUserNotificationSettings();
+		enabledTypes = settings.plusGetAttribute("types");
+		console.log("enabledTypes1:" + enabledTypes);
+		if (enabledTypes == 0) {
+			console.log("推送权限没有开启");
+		} else {
+			result = true;
+			console.log("已经开启推送功能!")
+		}
+		plus.ios.deleteObject(settings);
+	} else {
+		enabledTypes = app.enabledRemoteNotificationTypes();
+		if (enabledTypes == 0) {
+			console.log("推送权限没有开启!");
+		} else {
+			result = true;
+			console.log("已经开启推送功能!")
+		}
+		console.log("enabledTypes2:" + enabledTypes);
+	}
+	plus.ios.deleteObject(app);
+	plus.ios.deleteObject(UIApplication);
+	return result;
+}
+
+// 判断定位权限是否开启
+function judgeIosPermissionLocation() {
+	var result = false;
+	var cllocationManger = plus.ios.import("CLLocationManager");
+	var status = cllocationManger.authorizationStatus();
+	result = (status != 2)
+	console.log("定位权限开启:" + result);
+	// 以下代码判断了手机设备的定位是否关闭,推荐另行使用方法 checkSystemEnableLocation
+	/* var enable = cllocationManger.locationServicesEnabled();
+	var status = cllocationManger.authorizationStatus();
+	console.log("enable:" + enable);
+	console.log("status:" + status);
+	if (enable && status != 2) {
+		result = true;
+		console.log("手机定位服务已开启且已授予定位权限");
+	} else {
+		console.log("手机系统的定位没有打开或未给予定位权限");
+	} */
+	plus.ios.deleteObject(cllocationManger);
+	return result;
+}
+
+// 判断麦克风权限是否开启
+function judgeIosPermissionRecord() {
+	var result = false;
+	var avaudiosession = plus.ios.import("AVAudioSession");
+	var avaudio = avaudiosession.sharedInstance();
+	var permissionStatus = avaudio.recordPermission();
+	console.log("permissionStatus:" + permissionStatus);
+	if (permissionStatus == 1684369017 || permissionStatus == 1970168948) {
+		console.log("麦克风权限没有开启");
+	} else {
+		result = true;
+		console.log("麦克风权限已经开启");
+	}
+	plus.ios.deleteObject(avaudiosession);
+	return result;
+}
+
+// 判断相机权限是否开启
+function judgeIosPermissionCamera() {
+	var result = false;
+	var AVCaptureDevice = plus.ios.import("AVCaptureDevice");
+	var authStatus = AVCaptureDevice.authorizationStatusForMediaType('vide');
+	console.log("authStatus:" + authStatus);
+	if (authStatus == 3) {
+		result = true;
+		console.log("相机权限已经开启");
+	} else {
+		console.log("相机权限没有开启");
+	}
+	plus.ios.deleteObject(AVCaptureDevice);
+	return result;
+}
+
+// 判断相册权限是否开启
+function judgeIosPermissionPhotoLibrary() {
+	var result = false;
+	var PHPhotoLibrary = plus.ios.import("PHPhotoLibrary");
+	var authStatus = PHPhotoLibrary.authorizationStatus();
+	console.log("authStatus:" + authStatus);
+	if (authStatus == 3) {
+		result = true;
+		console.log("相册权限已经开启");
+	} else {
+		console.log("相册权限没有开启");
+	}
+	plus.ios.deleteObject(PHPhotoLibrary);
+	return result;
+}
+
+// 判断通讯录权限是否开启
+function judgeIosPermissionContact() {
+	var result = false;
+	var CNContactStore = plus.ios.import("CNContactStore");
+	var cnAuthStatus = CNContactStore.authorizationStatusForEntityType(0);
+	if (cnAuthStatus == 3) {
+		result = true;
+		console.log("通讯录权限已经开启");
+	} else {
+		console.log("通讯录权限没有开启");
+	}
+	plus.ios.deleteObject(CNContactStore);
+	return result;
+}
+
+// 判断日历权限是否开启
+function judgeIosPermissionCalendar() {
+	var result = false;
+	var EKEventStore = plus.ios.import("EKEventStore");
+	var ekAuthStatus = EKEventStore.authorizationStatusForEntityType(0);
+	if (ekAuthStatus == 3) {
+		result = true;
+		console.log("日历权限已经开启");
+	} else {
+		console.log("日历权限没有开启");
+	}
+	plus.ios.deleteObject(EKEventStore);
+	return result;
+}
+
+// 判断备忘录权限是否开启
+function judgeIosPermissionMemo() {
+	var result = false;
+	var EKEventStore = plus.ios.import("EKEventStore");
+	var ekAuthStatus = EKEventStore.authorizationStatusForEntityType(1);
+	if (ekAuthStatus == 3) {
+		result = true;
+		console.log("备忘录权限已经开启");
+	} else {
+		console.log("备忘录权限没有开启");
+	}
+	plus.ios.deleteObject(EKEventStore);
+	return result;
+}
+
+// Android权限查询
+function requestAndroidPermission(permissionID) {
+	return new Promise((resolve, reject) => {
+		plus.android.requestPermissions(
+			[permissionID], // 理论上支持多个权限同时查询,但实际上本函数封装只处理了一个权限的情况。有需要的可自行扩展封装
+			function(resultObj) {
+				var result = 0;
+				for (var i = 0; i < resultObj.granted.length; i++) {
+					var grantedPermission = resultObj.granted[i];
+					console.log('已获取的权限:' + grantedPermission);
+					result = 1
+				}
+				for (var i = 0; i < resultObj.deniedPresent.length; i++) {
+					var deniedPresentPermission = resultObj.deniedPresent[i];
+					console.log('拒绝本次申请的权限:' + deniedPresentPermission);
+					result = 0
+				}
+				for (var i = 0; i < resultObj.deniedAlways.length; i++) {
+					var deniedAlwaysPermission = resultObj.deniedAlways[i];
+					console.log('永久拒绝申请的权限:' + deniedAlwaysPermission);
+					result = -1
+				}
+				resolve(result);
+				// 若所需权限被拒绝,则打开APP设置界面,可以在APP设置界面打开相应权限
+				// if (result != 1) {
+				// gotoAppPermissionSetting()
+				// }
+			},
+			function(error) {
+				console.log('申请权限错误:' + error.code + " = " + error.message);
+				resolve({
+					code: error.code,
+					message: error.message
+				});
+			}
+		);
+	});
+}
+
+// 使用一个方法,根据参数判断权限
+function judgeIosPermission(permissionID) {
+	if (permissionID == "location") {
+		return judgeIosPermissionLocation()
+	} else if (permissionID == "camera") {
+		return judgeIosPermissionCamera()
+	} else if (permissionID == "photoLibrary") {
+		return judgeIosPermissionPhotoLibrary()
+	} else if (permissionID == "record") {
+		return judgeIosPermissionRecord()
+	} else if (permissionID == "push") {
+		return judgeIosPermissionPush()
+	} else if (permissionID == "contact") {
+		return judgeIosPermissionContact()
+	} else if (permissionID == "calendar") {
+		return judgeIosPermissionCalendar()
+	} else if (permissionID == "memo") {
+		return judgeIosPermissionMemo()
+	}
+	return false;
+}
+
+// 跳转到**应用**的权限页面
+function gotoAppPermissionSetting() {
+	if (isIos) {
+		var UIApplication = plus.ios.import("UIApplication");
+		var application2 = UIApplication.sharedApplication();
+		var NSURL2 = plus.ios.import("NSURL");
+		// var setting2 = NSURL2.URLWithString("prefs:root=LOCATION_SERVICES");		
+		var setting2 = NSURL2.URLWithString("app-settings:");
+		application2.openURL(setting2);
+
+		plus.ios.deleteObject(setting2);
+		plus.ios.deleteObject(NSURL2);
+		plus.ios.deleteObject(application2);
+	} else {
+		// console.log(plus.device.vendor);
+		var Intent = plus.android.importClass("android.content.Intent");
+		var Settings = plus.android.importClass("android.provider.Settings");
+		var Uri = plus.android.importClass("android.net.Uri");
+		var mainActivity = plus.android.runtimeMainActivity();
+		var intent = new Intent();
+		intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
+		var uri = Uri.fromParts("package", mainActivity.getPackageName(), null);
+		intent.setData(uri);
+		mainActivity.startActivity(intent);
+	}
+}
+
+// 检查系统的设备服务是否开启
+// var checkSystemEnableLocation = async function () {
+function checkSystemEnableLocation() {
+	if (isIos) {
+		var result = false;
+		var cllocationManger = plus.ios.import("CLLocationManager");
+		var result = cllocationManger.locationServicesEnabled();
+		console.log("系统定位开启:" + result);
+		plus.ios.deleteObject(cllocationManger);
+		return result;
+	} else {
+		var context = plus.android.importClass("android.content.Context");
+		var locationManager = plus.android.importClass("android.location.LocationManager");
+		var main = plus.android.runtimeMainActivity();
+		var mainSvr = main.getSystemService(context.LOCATION_SERVICE);
+		var result = mainSvr.isProviderEnabled(locationManager.GPS_PROVIDER);
+		console.log("系统定位开启:" + result);
+		return result
+	}
+}
+
+module.exports = {
+	judgeIosPermission: judgeIosPermission,
+	requestAndroidPermission: requestAndroidPermission,
+	checkSystemEnableLocation: checkSystemEnableLocation,
+	gotoAppPermissionSetting: gotoAppPermissionSetting
+}

+ 41 - 0
main.js

@@ -0,0 +1,41 @@
+import Vue from 'vue'
+import App from './App'
+
+// vuex
+import store from './store'
+
+// 引入全局uView
+import uView from '@/uni_modules/uview-ui'
+
+import baseApi from '@/util/base.js'
+import request from '@/util/request.js'
+import utils from '@/util/util.js'
+import webim from 'webim.js';
+import helper from'@/common/helper.js'
+Vue.prototype.$api = baseApi
+Vue.prototype.$request = request
+Vue.prototype.$utils = utils
+Vue.prototype.$helper = helper
+Vue.prototype.$socket = webim;
+Vue.prototype.$store = store
+
+
+Vue.config.productionTip = false
+
+App.mpType = 'app'
+Vue.use(uView)
+
+// #ifdef MP
+// 引入uView对小程序分享的mixin封装
+const mpShare = require('@/uni_modules/uview-ui/libs/mixin/mpShare.js')
+Vue.mixin(mpShare)
+// #endif
+const app = new Vue({
+    store,
+    ...App
+})
+
+// // 引入请求封装
+// require('./util/request/index')(app)
+
+app.$mount()

+ 72 - 0
manifest.json

@@ -0,0 +1,72 @@
+{
+    "name" : "uni-app开发模板",
+    "appid" : "__UNI__6485BEA",
+    "description" : "",
+    "versionName" : "1.0.0",
+    "versionCode" : "100",
+    "transformPx" : false,
+    /* 5+App特有相关 */
+    "app-plus" : {
+        "usingComponents" : true,
+        "nvueStyleCompiler" : "uni-app",
+        "compilerVersion" : 3,
+        "splashscreen" : {
+            "alwaysShowBeforeRender" : true,
+            "waiting" : true,
+            "autoclose" : true,
+            "delay" : 0
+        },
+        /* 模块配置 */
+        "modules" : {},
+        /* 应用发布信息 */
+        "distribute" : {
+            /* android打包配置 */
+            "android" : {
+                "permissions" : [
+                    "<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
+                    "<uses-permission android:name=\"android.permission.VIBRATE\"/>",
+                    "<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
+                    "<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
+                    "<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
+                    "<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.CAMERA\"/>",
+                    "<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
+                    "<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
+                    "<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
+                    "<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
+                    "<uses-feature android:name=\"android.hardware.camera\"/>",
+                    "<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
+                ]
+            },
+            /* ios打包配置 */
+            "ios" : {},
+            /* SDK配置 */
+            "sdkConfigs" : {}
+        }
+    },
+    /* 快应用特有相关 */
+    "quickapp" : {},
+    /* 小程序特有相关 */
+    "mp-weixin" : {
+        "appid" : "",
+        "setting" : {
+            "urlCheck" : false
+        },
+        "usingComponents" : true
+    },
+    "mp-alipay" : {
+        "usingComponents" : true
+    },
+    "mp-baidu" : {
+        "usingComponents" : true
+    },
+    "mp-toutiao" : {
+        "usingComponents" : true
+    },
+    "uniStatistics" : {
+        "enable" : false
+    },
+    "vueVersion" : "2"
+}

+ 233 - 0
pages.json

@@ -0,0 +1,233 @@
+{
+	"tabBar": {
+		"custom": false,
+		"color": "#656765",
+		"selectedColor": "#2772FB",
+		"borderStyle": "white",
+		"backgroundColor": "#ffffff",
+		"list": [{
+				"pagePath": "pages/goodSource/index",
+				"iconPath": "static/mine/huoyuan.png",
+				"selectedIconPath": "static/mine/huoyuan_check.png",
+				"text": "订单"
+			},
+			{
+				"pagePath": "pages/order/index",
+				"iconPath": "static/mine/zhaoche.png",
+				"selectedIconPath": "static/mine/zhaoche_check.png",
+				"text": "找车"
+			},
+			// {
+			// 	"pagePath": "pages/grain_pulse/home",
+			// 	"iconPath": "static/mine/fabu.png",
+			// 	"selectedIconPath": "static/mine/fabu.png",
+			// 	"text": "发布"
+			// },
+			{
+				"pagePath": "pages/news/index",
+				"iconPath": "static/mine/tongzhi.png",
+				"selectedIconPath": "static/mine/tongzhi_check.png",
+				"text": "消息"
+			},
+			{
+				"pagePath": "pages/mine/index",
+				"iconPath": "static/mine/wode.png",
+				"selectedIconPath": "static/mine/tongzhi_check.png",
+				"text": "我的"
+			}
+		],
+		"midButton": {
+					"width": "63px",
+					"height": "63px",
+					"iconPath": "static/mine/fabu.png",
+					"iconWidth": "55px"
+					// "backgroundImage":"static/images/tabbar/plus.png"
+				}
+	},
+	"pages": [ //pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
+		{
+			"path": "pages/goodSource/index",
+			"style": {
+				"navigationBarTitleText": "粮运天下"
+			}
+		}, {
+			"path": "pages/order/index",
+			"style": {
+				"navigationBarTitleText": "订单",
+				"enablePullDownRefresh": false
+			}
+
+		}
+
+		, {
+			"path": "pages/news/index",
+			"style": {
+				"navigationBarTitleText": "消息",
+				"enablePullDownRefresh": false
+			}
+
+		},
+		{
+			"path": "pages/mine/index",
+			"style": {
+				"navigationBarTitleText": "我的",
+				"navigationStyle": "custom"
+			}
+
+		},
+		{
+			"path": "pages/public/login",
+			"style": {
+				"navigationBarTitleText": "登录",
+				"enablePullDownRefresh": false
+			}
+
+		},
+		{
+			"path": "pages/public/register",
+			"style": {
+				"navigationBarTitleText": "注册",
+				"enablePullDownRefresh": false
+			}
+		}, {
+			"path": "pages/goodSource/shippingDetails",
+			"style": {
+				"navigationBarTitleText": "发运详情",
+				"enablePullDownRefresh": false
+			}
+
+		}, {
+			"path": "pages/order/orderDetails",
+			"style": {
+				"navigationBarTitleText": "订单详情",
+				"enablePullDownRefresh": false
+			}
+
+		}, {
+			"path": "pages/order/confirmLoading",
+			"style": {
+				"navigationBarTitleText": "确认装车",
+				"enablePullDownRefresh": false
+			}
+
+		}, {
+			"path": "pages/order/confirmUnloading",
+			"style": {
+				"navigationBarTitleText": "确认卸车",
+				"enablePullDownRefresh": false
+			}
+
+		}, {
+			"path": "pages/mine/driverCertification",
+			"style": {
+				"navigationBarTitleText": "司机认证",
+				"enablePullDownRefresh": false
+			}
+
+		}, {
+		 "path": "pages/mine/driverCertificationNext",
+			"style": {
+				"navigationBarTitleText": "司机认证",
+				"enablePullDownRefresh": false
+			}
+
+		}, {
+			"path": "pages/mine/helpDescription",
+			"style": {
+				"navigationBarTitleText": "操作说明",
+				"enablePullDownRefresh": false
+			}
+
+		}, {
+			"path": "pages/mine/manageVehicles/index",
+			"style": {
+				"navigationBarTitleText": "管理车辆",
+				"enablePullDownRefresh": false
+			}
+
+		}, {
+			"path": "pages/mine/manageVehicles/addVehicle",
+			"style": {
+				"navigationBarTitleText": "添加车辆",
+				"enablePullDownRefresh": false
+			}
+
+		}, {
+			"path": "pages/mine/manageVehicles/editVehicle",
+			"style": {
+				"navigationBarTitleText": "修改车辆",
+				"enablePullDownRefresh": false
+			}
+
+		}, {
+			"path": "pages/mine/manageBankCards/index",
+			"style": {
+				"navigationBarTitleText": "银行卡",
+				"enablePullDownRefresh": false
+			}
+
+		}, {
+			"path": "pages/mine/manageBankCards/addBankCard",
+			"style": {
+				"navigationBarTitleText": "添加银行卡",
+				"enablePullDownRefresh": false
+			}
+
+		}, {
+			"path": "pages/mine/manageBankCards/editBankCard",
+			"style": {
+				"navigationBarTitleText": "修改银行卡",
+				"enablePullDownRefresh": false
+			}
+
+		}, {
+			"path": "pages/mine/set",
+			"style": {
+				"navigationBarTitleText": "设置",
+				"enablePullDownRefresh": false
+			}
+
+		},
+		{
+			"path": "pages/mine/camera/idcard/idcard",
+			"style": {
+				"navigationStyle": "custom",
+				"backgroundColor": "#000000"
+			}
+
+		}
+	    ,{
+            "path" : "pages/mine/agency/agency",
+            "style" :                                                                                    
+            {
+                "navigationBarTitleText": "",
+                "enablePullDownRefresh": false
+            }
+            
+        }
+        ,{
+            "path" : "pages/mine/cargoowner/cargoowner",
+            "style" :                                                                                    
+            {
+                "navigationBarTitleText": "货主认证",
+                "enablePullDownRefresh": false
+            }
+            
+        }
+        ,{
+            "path" : "pages/mine/cargoowner/editpersonalinformation",
+            "style" :                                                                                    
+            {
+                "navigationBarTitleText": "",
+                "enablePullDownRefresh": false
+            }
+            
+        }
+    ],
+	"globalStyle": {
+		"navigationBarTextStyle": "black",
+		"navigationBarTitleText": "uni-app",
+		"navigationBarBackgroundColor": "#F8F8F8",
+		"backgroundColor": "#F8F8F8"
+	}
+}

+ 61 - 0
pages/goodSource/index.vue

@@ -0,0 +1,61 @@
+<!-- 货源 -->
+<template>
+	<view class="content">
+		<view class="head flex flex-space-evenly">
+			<view class="flex">
+				<view>装</view>
+				<view @click="changeCity(0)">营口</view>
+				<view>></view>
+			</view>
+			<view>-------></view>
+			<view class="flex">
+				<view>卸</view>
+				<view @click="changeCity(1)">全国</view>
+				<view>></view>
+			</view>
+		</view>
+		<me-tabs v-model="tabIndex" :tabs="tabs" class="m-topr20"></me-tabs>
+		<swiper :style="{height: height}" :current="tabIndex" @change="swiperChange">
+			<swiper-item v-for="(tab,i) in tabs" :key="i">
+				<mescroll-item ref="mescrollItem" :i="i" :index="tabIndex" :tabs="tabs" :height="height">
+				</mescroll-item>
+			</swiper-item>
+		</swiper>
+	</view>
+</template>
+
+<script>
+	import MescrollItem from "./mescroll-swiper-item.vue";
+	export default {
+		components: {
+			MescrollItem
+		},
+		data() {
+			return {
+				src: 'https://cdn.uviewui.com/uview/album/1.jpg',
+				height: "", // 需要固定swiper的高度
+				tabs: [{name:'推荐'}, {name:'按时间'}, {name:'按距离'}, {name:'运费先付'}],
+				tabIndex: 0 // 当前tab的下标
+
+			}
+		},
+		onLoad() {
+			let _isHave = this.$utils.getRoles('aaa')
+			console.log(_isHave)
+			// 需要固定swiper的高度 (需减去悬浮tabs的高度64rpx)
+			this.height = uni.getSystemInfoSync().windowHeight - uni.upx2px(64) + 'px'
+		},
+		methods: {
+			changeCity(type) {
+				console.log(type)
+			},
+			swiperChange(e) {
+				this.tabIndex = e.detail.current
+			}
+		}
+	}
+</script>
+
+<style scoped lang="scss">
+
+</style>

+ 139 - 0
pages/goodSource/mescroll-swiper-item.vue

@@ -0,0 +1,139 @@
+<template>
+	<mescroll-uni :ref="'mescrollRef'+i" @init="mescrollInit" :height="height" :down="downOption" @down="downCallback"
+		:up="upOption" @up="upCallback" @emptyclick="emptyClick">
+		<view :id="'good'+good.id" class="good-list paddingr20" v-for="good in goods" :key="good.id" @click="toDetail(good.id)">
+			<view class="flex flex-space-between row">
+				<view class="left flex">
+					<view>辽</view>
+					<view>营口 鲅鱼圈</view>
+					<view>--------></view>
+					<view class="">
+						京
+					</view>
+					<view>背景 通州</view>
+				</view>
+				<view class="right">
+					21:51
+				</view>
+			</view>
+			<view class="flex flex-space-between row">
+				<view class="left flex">
+					<view>货距~10km</view>
+					<view>运距~35km</view>
+				</view>
+				<view class="right">
+					300元/吨
+				</view>
+			</view>
+			<view class="flex">
+				<view>玉米|</view>
+				<view>3.8-5米|</view>
+				<view>厢式/平板/高栏|</view>
+				<view>10吨</view>
+			</view>
+			<view class="flex">
+				<view>运输过程中其他费用,发货方承担。</view>
+			</view>
+			<view class="flex flex-space-between">
+				<view class="left flex">
+					<u--image :showLoading="true" :src="good.goodImg" width="40px" height="40px"></u--image>
+					<view>张颖</view>
+					<view>发运106次</view>
+					<view>好评率99%</view>
+				</view>
+				<view class="right">
+					<view @click.stop="grabOrders(good.id)">抢单</view>
+				</view>
+			</view>
+		</view>
+	</mescroll-uni>
+</template>
+
+<script>
+	import MescrollMixin from "@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js";
+	import MescrollMoreItemMixin from "@/uni_modules/mescroll-uni/components/mescroll-uni/mixins/mescroll-more-item.js";
+	import {
+		apiGoods
+	} from "@/api/mock.js"
+
+	export default {
+		mixins: [MescrollMixin, MescrollMoreItemMixin], // 注意此处还需使用MescrollMoreItemMixin (必须写在MescrollMixin后面)
+		data() {
+			return {
+				downOption: {
+					auto: false // 不自动加载 (mixin已处理第一个tab触发downCallback)
+				},
+				upOption: {
+					auto: false, // 不自动加载
+					// page: {
+					// 	num: 0, // 当前页码,默认0,回调之前会加1,即callback(page)会从1开始
+					// 	size: 10 // 每页数据的数量
+					// },
+					noMoreSize: 4, //如果列表已无数据,可设置列表的总数量要大于半页才显示无更多数据;避免列表数据过少(比如只有一条数据),显示无更多数据会不好看; 默认5
+					empty: {
+						tip: '~ 空空如也 ~', // 提示
+						btnText: '去看看'
+					}
+				},
+				goods: [] //列表数据
+			}
+		},
+		props: {
+			i: Number, // 每个tab页的专属下标 (除了支付宝小程序必须在这里定义, 其他平台都可不用写, 因为已在MescrollMoreItemMixin定义)
+			index: { // 当前tab的下标 (除了支付宝小程序必须在这里定义, 其他平台都可不用写, 因为已在MescrollMoreItemMixin定义)
+				type: Number,
+				default () {
+					return 0
+				}
+			},
+			tabs: { // 为了请求数据,演示用,可根据自己的项目判断是否要传
+				type: Array,
+				default () {
+					return []
+				}
+			},
+			height: [Number, String] // mescroll的高度
+		},
+		methods: {
+			/*下拉刷新的回调 */
+			downCallback() {
+				// 这里加载你想下拉刷新的数据, 比如刷新轮播数据
+				// loadSwiper();
+				// 下拉刷新的回调,默认重置上拉加载列表为第一页 (自动执行 page.num=1, 再触发upCallback方法 )
+				this.mescroll.resetUpScroll()
+			},
+			/*上拉加载的回调: 其中page.num:当前页 从1开始, page.size:每页数据条数,默认10 */
+			upCallback(page) {
+				//联网加载数据
+				let keyword = this.tabs[this.i].name
+				apiGoods(page.num, page.size, keyword).then(res => {
+					//联网成功的回调,隐藏下拉刷新和上拉加载的状态;
+					this.mescroll.endSuccess(res.list.length);
+					//设置列表数据
+					if (page.num == 1) this.goods = []; //如果是第一页需手动制空列表
+					this.goods = this.goods.concat(res.list); //追加新数据
+				}).catch(() => {
+					//联网失败, 结束加载
+					this.mescroll.endErr();
+				})
+			},
+			//点击空布局按钮的回调
+			emptyClick() {
+				uni.showToast({
+					title: '点击了按钮,具体逻辑自行实现'
+				})
+			},
+			// 跳转详情
+			toDetail(id){
+				console.log('点击详情id:',id)
+				uni.$u.route('/pages/goodSource/shippingDetails', {
+					id:id,
+				});
+			},
+			//抢单
+			grabOrders(id){
+				console.log('抢单id:',id)
+			}
+		}
+	}
+</script>

+ 119 - 0
pages/goodSource/shippingDetails.vue

@@ -0,0 +1,119 @@
+<!-- 发运详情 -->
+<template>
+	<view class="content">
+		<view class="content1">
+			<view class="left">
+				<u--image src="https://cdn.uviewui.com/uview/album/1.jpg" mode="widthFix"></u--image>
+			</view>
+			<view class="right">
+				<view class="flex">
+					<view class="">张三</view>
+					<view class="">联系货主</view>
+					<view>关注</view>
+					<!-- <view>已关注</view> -->
+				</view>
+				<view class="flex">
+					黑龙江中天贸易有限公司
+				</view>
+				<view class="flex">
+					<view class="left">
+						装车
+					</view>
+					<view>辽宁省营口市鲅鱼圈区蝴蝶泉路116号</view>
+				</view>
+				<view class="flex">
+					<view class="left">
+						卸车车
+					</view>
+					<view>黑龙江省齐齐哈尔市梅里斯达斡尔族区杜尔门沁达斡尔乡53农场</view>
+				</view>
+				<view class="flex">
+					<view class="left">
+						货物
+					</view>
+					<view>玉米|20吨</view>
+				</view>
+				<view class="flex">
+					<view class="left">
+						距离
+					</view>
+					<view class="right">
+						<view>运输距离月500公里</view>
+						<view><u--image src="https://cdn.uviewui.com/uview/album/1.jpg" mode="widthFix"></u--image></view>
+					</view>
+				</view>
+				<view class="flex">
+					<view class="left">
+						运费
+					</view>
+					<view class="right">
+						100元/吨
+					</view>
+				</view>
+				<view class="flex">
+					<view class="left">
+						日期
+					</view>
+					<view class="right">
+						<view class="in-row">
+							<view class="text">
+								发车
+							</view>
+							<view class="time">2022-01-27 15:15:15</view>
+						</view>
+						<view class="in-row">
+							<view class="text">
+								装车
+							</view>
+							<view class="time">2022-01-27~2022-01-30</view>
+						</view>
+					</view>
+				</view>
+				<view class="flex">
+					<view class="left">
+						车型
+					</view>
+					<view class="right">
+						10-15米  |  平板/高栏  |  约30吨
+					</view>
+				</view>
+				<view class="flex">
+					<view class="left">
+						描述
+					</view>
+					<view class="right">
+						我是发运任务描述我是发运任务描述我是发运任务描述我是发运任务描述我是发运任务描述我是发运任务描述我是发运任务描述我是发运任务描述我是发运任务描述我是发运任务描述我是发运任务描述
+					</view>
+				</view>
+			</view>
+		</view>
+		<view class="content2">
+			<view class="left">
+				运费¥100元/吨
+			</view>
+			<view class="right">
+				<u-button type="error" text="立即抢单"></u-button>
+			</view>
+			<view class="right">
+				<u-button type="error" text="已抢单" disabled></u-button>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				src: 'https://cdn.uviewui.com/uview/album/1.jpg',
+			};
+		},
+		onLoad(options) {
+			console.log(options)
+		}
+	}
+</script>
+
+<style lang="scss">
+
+</style>

+ 35 - 0
pages/mine/agency/agency.vue

@@ -0,0 +1,35 @@
+<template>
+	<view>
+		<view>
+			<view>张三 1333333333333</view>
+			<view>待审核</view>
+		</view>
+		<view>
+			<view>公司</view>
+			<view></view>
+		</view>
+		<view>
+			<view>授权</view>
+			<view>驳回</view>
+			<view>删除</view>
+			<view>撤销授权</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				
+			}
+		},
+		methods: {
+			
+		}
+	}
+</script>
+
+<style>
+
+</style>

+ 213 - 0
pages/mine/camera/camera.nvue

@@ -0,0 +1,213 @@
+<template>
+	<view class="live-camera" :style="{ width: windowWidth, height: windowHeight }">
+		<live-pusher
+			id="livePusher"
+			ref="livePusher"
+			class="livePusher"
+			mode="FHD"
+			beauty="0"
+			whiteness="0"
+			:aspect="aspect"
+			min-bitrate="1000"
+			audio-quality="16KHz"
+			device-position="back"
+			:auto-focus="true"
+			:muted="true"
+			:enable-camera="true"
+			:enable-mic="false"
+			:zoom="false"
+			@statechange="statechange"
+			:style="{ width: windowWidth, height: windowHeight }"
+		></live-pusher>
+
+		<view class="menu">
+			<!--底部菜单区域背景-->
+			<cover-image class="menu-mask" src="/static/live-camera/bar.png"></cover-image>
+
+			<!--返回键-->
+			<cover-image class="menu-back" @tap="back" src="/static/live-camera/back.png"></cover-image>
+
+			<!--快门键-->
+			<cover-image class="menu-snapshot" @tap="snapshot" src="/static/live-camera/shutter.png"></cover-image>
+
+			<!--反转键-->
+			<cover-image class="menu-flip" @tap="flip" src="/static/live-camera/flip.png"></cover-image>
+		</view>
+	</view>
+</template>
+
+<script>
+let _this = null;
+export default {
+	data() {
+		return {
+			poenCarmeInterval:null,//打开相机的轮询
+			aspect: '2:3', //比例
+			windowWidth: '', //屏幕可用宽度
+			windowHeight: '', //屏幕可用高度
+			camerastate: false, //相机准备好了
+			livePusher: null, //流视频对象
+			snapshotsrc: null //快照
+		};
+	},
+	onLoad(e) {
+		_this = this;
+		this.initCamera();
+	},
+	onReady() {
+		this.livePusher = uni.createLivePusherContext('livePusher', this);
+		this.startPreview(); //开启预览并设置摄像头
+		this.poenCarme();
+	},
+	methods: {
+		
+		//轮询打开
+		poenCarme(){
+			//#ifdef APP-PLUS
+			if (plus.os.name == 'Android') {
+				this.poenCarmeInterval = setInterval(function() {
+					console.log(_this.camerastate);
+					if (!_this.camerastate) _this.startPreview();
+				}, 2500);
+			}
+			//#endif
+		},
+		//初始化相机
+		initCamera() {
+			uni.getSystemInfo({
+				success: function(res) {
+					_this.windowWidth = res.windowWidth;
+					_this.windowHeight = res.windowHeight;
+					let zcs = _this.aliquot(_this.windowWidth,_this.windowHeight);
+					_this.aspect = (_this.windowWidth/zcs)+':'+(_this.windowHeight/zcs);
+					console.log('画面比例:'+_this.aspect);
+				}
+			});
+		},
+		
+		//整除数计算
+		aliquot(x, y) {
+			if (x % y == 0) return y;
+			return this.aliquot(y, x % y);
+		},
+
+		//开始预览
+		startPreview() {
+			this.livePusher.startPreview({
+				success: a => {
+					console.log(a)
+				}
+			});
+		},
+		
+		//停止预览
+		stopPreview() {
+			this.livePusher.stopPreview({
+				success: a => {
+					_this.camerastate = false; //标记相机未启动
+				}
+			});
+		},
+		
+		//状态
+		statechange(e) {
+			//状态改变
+			console.log(e);
+			if (e.detail.code == 1007) {
+				_this.camerastate = true;
+			} else if (e.detail.code == -1301) {
+				_this.camerastate = false;
+			}
+		},
+		
+
+		//返回
+		back() {
+			uni.navigateBack();
+		},
+
+		//抓拍
+		snapshot() {
+			//震动
+			uni.vibrateShort({
+			    success: function () {
+			        console.log('success');
+			    }
+			});
+			//拍照
+			this.livePusher.snapshot({
+				success: e => {
+					_this.snapshotsrc = e.message.tempImagePath;
+					_this.stopPreview();
+					_this.setImage();
+					uni.navigateBack();
+				}
+			});
+		},
+
+		//反转
+		flip() {
+			this.livePusher.switchCamera();
+		},
+
+		//设置
+		setImage() {
+			let pages = getCurrentPages();
+			let prevPage = pages[pages.length - 2]; //上一个页面
+
+			//直接调用上一个页面的setImage()方法,把数据存到上一个页面中去
+			prevPage.$vm.setImage({ path: _this.snapshotsrc });
+		}
+	}
+};
+</script>
+
+<style lang="scss">
+.live-camera {
+	justify-content: center;
+	align-items: center;
+	.menu {
+		position: absolute;
+		left: 0;
+		bottom: 0;
+		width: 750rpx;
+		height: 180rpx;
+		z-index: 98;
+		align-items: center;
+		justify-content: center;
+		.menu-mask {
+			position: absolute;
+			left: 0;
+			bottom: 0;
+			width: 750rpx;
+			height: 180rpx;
+			z-index: 98;
+		}
+		.menu-back {
+			position: absolute;
+			left: 30rpx;
+			bottom: 50rpx;
+			width: 80rpx;
+			height: 80rpx;
+			z-index: 99;
+			align-items: center;
+			justify-content: center;
+		}
+		.menu-snapshot {
+			width: 130rpx;
+			height: 130rpx;
+			z-index: 99;
+		}
+		.menu-flip {
+			position: absolute;
+			right: 30rpx;
+			bottom: 50rpx;
+			width: 80rpx;
+			height: 80rpx;
+			z-index: 99;
+			align-items: center;
+			justify-content: center;
+		}
+	}
+}
+</style>

+ 246 - 0
pages/mine/camera/idcard/idcard.nvue

@@ -0,0 +1,246 @@
+<template>
+	<view class="live-camera" :style="{ width: windowWidth, height: windowHeight }">
+		<view class="preview" :style="{ width: windowWidth, height: windowHeight - 80 }">
+			<live-pusher
+				id="livePusher"
+				ref="livePusher"
+				class="livePusher"
+				mode="FHD"
+				beauty="0"
+				whiteness="0"
+				:aspect="aspect"
+				min-bitrate="1000"
+				audio-quality="16KHz"
+				device-position="back"
+				:auto-focus="true"
+				:muted="true"
+				:enable-camera="true"
+				:enable-mic="false"
+				:zoom="false"
+				@statechange="statechange"
+				:style="{ width: cameraWidth, height: cameraHeight }"
+			></live-pusher>
+
+			<!--提示语-->
+			<cover-view class="remind">
+				<text class="remind-text" style="">{{ message }}</text>
+			</cover-view>
+
+			<!--辅助线-->
+			<cover-view class="outline-box" :style="{ width: windowWidth, height: windowHeight - 80 }">
+				<cover-image
+					class="outline-img"
+					:src="dotype == 'idcardface' ? '/static/live-camera/outline/idcardface.png' : '/static/live-camera/outline/idcardbadge.png'"
+					style=""
+				></cover-image>
+			</cover-view>
+		</view>
+
+		<view class="menu">
+			<!--底部菜单区域背景-->
+			<cover-image class="menu-mask" src="/static/live-camera/bar.png"></cover-image>
+
+			<!--返回键-->
+			<cover-image class="menu-back" @tap="back" src="/static/live-camera/back.png"></cover-image>
+
+			<!--快门键-->
+			<cover-image class="menu-snapshot" @tap="snapshot" src="/static/live-camera/shutter.png"></cover-image>
+
+			<!--反转键-->
+			<cover-image class="menu-flip" @tap="flip" src="/static/live-camera/flip.png"></cover-image>
+		</view>
+	</view>
+</template>
+
+<script>
+let _this = null;
+export default {
+	data() {
+		return {
+			poenCarmeInterval: null, //打开相机的轮询
+			dotype: 'face', //操作类型
+			message: '', //提示
+			aspect: '2:3', //比例
+			cameraWidth: '', //相机画面宽度
+			cameraHeight: '', //相机画面宽度
+			windowWidth: '', //屏幕可用宽度
+			windowHeight: '', //屏幕可用高度
+			camerastate: false, //相机准备好了
+			livePusher: null, //流视频对象
+			snapshotsrc: null //快照
+		};
+	},
+	onLoad(e) {
+		_this = this;
+		this.dotype = e.dotype;
+		this.initCamera();
+	},
+	onReady() {
+		this.livePusher = uni.createLivePusherContext('livePusher', this);
+		this.startPreview(); //开启预览并设置摄像头
+		this.poenCarme();
+	},
+	methods: {
+		//轮询打开
+		poenCarme() {
+			//#ifdef APP-PLUS
+			if (plus.os.name == 'Android') {
+				this.poenCarmeInterval = setInterval(function() {
+					console.log(_this.camerastate);
+					if (!_this.camerastate) _this.startPreview();
+				}, 2500);
+			}
+			//#endif
+		},
+		//初始化相机
+		initCamera() {
+			//处理安卓手机异步授权问题
+			uni.getSystemInfo({
+				success: function(res) {
+					_this.windowWidth = res.windowWidth;
+					_this.windowHeight = res.windowHeight;
+					_this.cameraWidth = res.windowWidth;
+					_this.cameraHeight = res.windowWidth * 1.5;
+				}
+			});
+		},
+
+		//开始预览
+		startPreview() {
+			this.livePusher.startPreview({
+				success: a => {
+					console.log(a);
+				}
+			});
+		},
+
+		//停止预览
+		stopPreview() {
+			this.livePusher.stopPreview({
+				success: a => {
+					_this.camerastate = false; //标记相机未启动
+				}
+			});
+		},
+
+		//状态
+		statechange(e) {
+			//状态改变
+			console.log(e);
+			if (e.detail.code == 1007) {
+				_this.camerastate = true;
+			} else if (e.detail.code == -1301) {
+				_this.camerastate = false;
+			}
+		},
+
+		//返回
+		back() {
+			uni.navigateBack();
+		},
+
+		//抓拍
+		snapshot() {
+			this.livePusher.snapshot({
+				success: e => {
+					_this.snapshotsrc = e.message.tempImagePath;
+					_this.stopPreview();
+					_this.setImage();
+					uni.navigateBack();
+				}
+			});
+		},
+
+		//反转
+		flip() {
+			this.livePusher.switchCamera();
+		},
+
+		//设置
+		setImage() {
+			let pages = getCurrentPages();
+			let prevPage = pages[pages.length - 2]; //上一个页面
+
+			//直接调用上一个页面的setImage()方法,把数据存到上一个页面中去
+			prevPage.$vm.setImage({ path: _this.snapshotsrc, dotype: this.dotype });
+		}
+	}
+};
+</script>
+
+<style lang="scss">
+.live-camera {
+	.preview {
+		justify-content: center;
+		align-items: center;
+		.outline-box {
+			position: absolute;
+			top: 0;
+			left: 0;
+			bottom: 0;
+			z-index: 99;
+			align-items: center;
+			justify-content: center;
+			.outline-img {
+				width: 750rpx;
+				height: 1125rpx;
+			}
+		}
+		.remind {
+			position: absolute;
+			top: 880rpx;
+			width: 750rpx;
+			z-index: 100;
+			align-items: center;
+			justify-content: center;
+			.remind-text {
+				color: #dddddd;
+				font-weight: bold;
+			}
+		}
+	}
+	.menu {
+		position: absolute;
+		left: 0;
+		bottom: 0;
+		width: 750rpx;
+		height: 180rpx;
+		z-index: 98;
+		align-items: center;
+		justify-content: center;
+		.menu-mask {
+			position: absolute;
+			left: 0;
+			bottom: 0;
+			width: 750rpx;
+			height: 180rpx;
+			z-index: 98;
+		}
+		.menu-back {
+			position: absolute;
+			left: 30rpx;
+			bottom: 50rpx;
+			width: 80rpx;
+			height: 80rpx;
+			z-index: 99;
+			align-items: center;
+			justify-content: center;
+		}
+		.menu-snapshot {
+			width: 130rpx;
+			height: 130rpx;
+			z-index: 99;
+		}
+		.menu-flip {
+			position: absolute;
+			right: 30rpx;
+			bottom: 50rpx;
+			width: 80rpx;
+			height: 80rpx;
+			z-index: 99;
+			align-items: center;
+			justify-content: center;
+		}
+	}
+}
+</style>

+ 240 - 0
pages/mine/camera/idphoto/idphoto.nvue

@@ -0,0 +1,240 @@
+<template>
+	<view class="live-camera" :style="{ width: windowWidth, height: windowHeight }">
+		<view class="preview" :style="{ width: windowWidth, height: windowHeight - 80 }">
+			<live-pusher
+				id="livePusher"
+				ref="livePusher"
+				class="livePusher"
+				mode="FHD"
+				beauty="1"
+				whiteness="0"
+				:aspect="aspect"
+				min-bitrate="1000"
+				audio-quality="16KHz"
+				device-position="back"
+				:auto-focus="true"
+				:muted="true"
+				:enable-camera="true"
+				:enable-mic="false"
+				:zoom="false"
+				@statechange="statechange"
+				:style="{ width: cameraWidth, height: cameraHeight }"
+			></live-pusher>
+
+			<!--提示语-->
+			<cover-view class="remind">
+				<text class="remind-text" style="">{{ message }}</text>
+			</cover-view>
+
+			<!--辅助线-->
+			<cover-view class="outline-box" :style="{ width: windowWidth, height: windowHeight - 80 }">
+				<cover-image class="outline-img" src="/static/live-camera/outline/idphotoskin.png" style=""></cover-image>
+			</cover-view>
+		</view>
+
+		<view class="menu">
+			<!--底部菜单区域背景-->
+			<cover-image class="menu-mask" src="/static/live-camera/bar.png"></cover-image>
+
+			<!--返回键-->
+			<cover-image class="menu-back" @tap="back" src="/static/live-camera/back.png"></cover-image>
+
+			<!--快门键-->
+			<cover-image class="menu-snapshot" @tap="snapshot" src="/static/live-camera/shutter.png"></cover-image>
+
+			<!--反转键-->
+			<cover-image class="menu-flip" @tap="flip" src="/static/live-camera/flip.png"></cover-image>
+		</view>
+	</view>
+</template>
+
+<script>
+let _this = null;
+export default {
+	data() {
+		return {
+			dotype: 'idphoto', //操作类型
+			message: '', //提示
+			aspect: '2:3', //比例
+			cameraWidth: '', //相机画面宽度
+			cameraHeight: '', //相机画面宽度
+			windowWidth: '', //屏幕可用宽度
+			windowHeight: '', //屏幕可用高度
+			camerastate: false, //相机准备好了
+			livePusher: null, //流视频对象
+			snapshotsrc: null //快照
+		};
+	},
+	onLoad(e) {
+		_this = this;
+		if (e.dotype != undefined) this.dotype = e.dotype;
+		this.initCamera();
+	},
+	onReady() {
+		this.livePusher = uni.createLivePusherContext('livePusher', this);
+		this.startPreview(); //开启预览并设置摄像头
+		this.poenCarme();
+	},
+	methods: {
+		//轮询打开
+		poenCarme() {
+			//#ifdef APP-PLUS
+			if (plus.os.name == 'Android') {
+				this.poenCarmeInterval = setInterval(function() {
+					console.log(_this.camerastate);
+					if (!_this.camerastate) _this.startPreview();
+				}, 2500);
+			}
+			//#endif
+		},
+
+		//初始化相机
+		initCamera() {
+			uni.getSystemInfo({
+				success: function(res) {
+					_this.windowWidth = res.windowWidth;
+					_this.windowHeight = res.windowHeight;
+					_this.cameraWidth = res.windowWidth;
+					_this.cameraHeight = res.windowWidth * 1.5;
+				}
+			});
+		},
+
+		//开始预览
+		startPreview() {
+			this.livePusher.startPreview({
+				success: a => {
+					console.log(a);
+				}
+			});
+		},
+		//停止预览
+		stopPreview() {
+			this.livePusher.stopPreview({
+				success: a => {
+					_this.camerastate = false; //标记相机未启动
+				}
+			});
+		},
+
+		//状态
+		statechange(e) {
+			//状态改变
+			console.log(e);
+			if (e.detail.code == 1007) {
+				_this.camerastate = true;
+			} else if (e.detail.code == -1301) {
+				_this.camerastate = false;
+			}
+		},
+
+		//返回
+		back() {
+			uni.navigateBack();
+		},
+
+		//抓拍
+		snapshot() {
+			this.livePusher.snapshot({
+				success: e => {
+					_this.snapshotsrc = e.message.tempImagePath;
+					_this.stopPreview();
+					_this.setImage();
+					uni.navigateBack();
+				}
+			});
+		},
+
+		//反转
+		flip() {
+			this.livePusher.switchCamera();
+		},
+
+		//设置
+		setImage() {
+			let pages = getCurrentPages();
+			let prevPage = pages[pages.length - 2]; //上一个页面
+
+			//直接调用上一个页面的setImage()方法,把数据存到上一个页面中去
+			prevPage.$vm.setImage({ path: _this.snapshotsrc, dotype: this.dotype });
+		}
+	}
+};
+</script>
+
+<style lang="scss">
+.live-camera {
+	.preview {
+		justify-content: center;
+		align-items: center;
+		.outline-box {
+			position: absolute;
+			top: 0;
+			left: 0;
+			bottom: 0;
+			z-index: 99;
+			align-items: center;
+			justify-content: center;
+			.outline-img {
+				width: 750rpx;
+				height: 1125rpx;
+			}
+		}
+		.remind {
+			position: absolute;
+			top: 880rpx;
+			width: 750rpx;
+			z-index: 100;
+			align-items: center;
+			justify-content: center;
+			.remind-text {
+				color: #dddddd;
+				font-weight: bold;
+			}
+		}
+	}
+	.menu {
+		position: absolute;
+		left: 0;
+		bottom: 0;
+		width: 750rpx;
+		height: 180rpx;
+		z-index: 98;
+		align-items: center;
+		justify-content: center;
+		.menu-mask {
+			position: absolute;
+			left: 0;
+			bottom: 0;
+			width: 750rpx;
+			height: 180rpx;
+			z-index: 98;
+		}
+		.menu-back {
+			position: absolute;
+			left: 30rpx;
+			bottom: 50rpx;
+			width: 80rpx;
+			height: 80rpx;
+			z-index: 99;
+			align-items: center;
+			justify-content: center;
+		}
+		.menu-snapshot {
+			width: 130rpx;
+			height: 130rpx;
+			z-index: 99;
+		}
+		.menu-flip {
+			position: absolute;
+			right: 30rpx;
+			bottom: 50rpx;
+			width: 80rpx;
+			height: 80rpx;
+			z-index: 99;
+			align-items: center;
+			justify-content: center;
+		}
+	}
+}
+</style>

+ 214 - 0
pages/mine/camera/portrait/portrait.nvue

@@ -0,0 +1,214 @@
+<template>
+	<view class="live-camera" :style="{ width: windowWidth, height: windowHeight }">
+		<live-pusher
+			id="livePusher"
+			ref="livePusher"
+			class="livePusher"
+			mode="FHD"
+			beauty="0"
+			whiteness="0"
+			:aspect="aspect"
+			min-bitrate="1000"
+			audio-quality="16KHz"
+			device-position="back"
+			:auto-focus="true"
+			:muted="true"
+			:enable-camera="true"
+			:enable-mic="false"
+			:zoom="false"
+			:style="{ width: windowWidth, height: windowHeight }"
+		></live-pusher>
+
+		<!--提示语-->
+		<cover-view class="remind">
+			<text class="remind-text" style="">{{ message }}</text>
+		</cover-view>
+
+		<!--辅助线-->
+		<cover-view class="outline">
+			<cover-image class="outline" src="/static/live-camera/outline/portrait.png" style=""></cover-image>
+		</cover-view>
+		
+
+		<view class="menu">
+			<!--底部菜单区域背景-->
+			<cover-image class="menu-mask" src="/static/live-camera/bar.png"></cover-image>
+
+			<!--返回键-->
+			<cover-image class="menu-back" @tap="back" src="/static/live-camera/back.png"></cover-image>
+
+			<!--快门键-->
+			<cover-image class="menu-snapshot" @tap="snapshot" src="/static/live-camera/shutter.png"></cover-image>
+
+			<!--反转键-->
+			<cover-image class="menu-flip" @tap="flip" src="/static/live-camera/flip.png"></cover-image>
+		</view>
+	</view>
+</template>
+
+<script>
+let _this = null;
+export default {
+	data() {
+		return {
+			message:'请拍摄苛学加',//提示
+			aspect: '2:3', //比例
+			windowWidth: '', //屏幕可用宽度
+			windowHeight: '', //屏幕可用高度
+			camerastate: false, //相机准备好了
+			livePusher: null, //流视频对象
+			snapshotsrc: null //快照
+		};
+	},
+	onLoad(e) {
+		_this = this;
+		this.initCamera();
+	},
+	onReady() {
+		this.livePusher = uni.createLivePusherContext('livePusher', this);
+		this.startPreview(); //开启预览并设置摄像头
+	},
+	methods: {
+		//初始化相机
+		initCamera() {
+			uni.getSystemInfo({
+				success: function(res) {
+					_this.windowWidth = res.windowWidth;
+					_this.windowHeight = res.windowHeight;
+					let zcs = _this.aliquot(_this.windowWidth, _this.windowHeight);
+					_this.aspect = _this.windowWidth / zcs + ':' + _this.windowHeight / zcs;
+				}
+			});
+		},
+
+		//整除数计算
+		aliquot(x, y) {
+			if (x % y == 0) return y;
+			return this.aliquot(y, x % y);
+		},
+
+		//开始预览
+		startPreview() {
+			this.livePusher.startPreview({
+				success: a => {
+					if (a.errMsg == 'startPreview:ok' || a.errMsg == 'operateLivePusher:ok') {
+						_this.camerastate = true; //标记相机启动成功
+					}
+				}
+			});
+		},
+		//停止预览
+		stopPreview() {
+			this.livePusher.stopPreview({
+				success: a => {
+					_this.camerastate = false; //标记相机未启动
+				}
+			});
+		},
+
+		//返回
+		back() {
+			uni.navigateBack();
+		},
+
+		//抓拍
+		snapshot() {
+			this.livePusher.snapshot({
+				success: e => {
+					_this.snapshotsrc = e.message.tempImagePath;
+					_this.stopPreview();
+					_this.setImage();
+					uni.navigateBack();
+				}
+			});
+		},
+
+		//反转
+		flip() {
+			this.livePusher.switchCamera();
+		},
+
+		//设置
+		setImage() {
+			let pages = getCurrentPages();
+			let prevPage = pages[pages.length - 2]; //上一个页面
+
+			//直接调用上一个页面的setImage()方法,把数据存到上一个页面中去
+			prevPage.$vm.setImage({ path: _this.snapshotsrc });
+		}
+	}
+};
+</script>
+
+<style lang="scss">
+.live-camera {
+	justify-content: center;
+	align-items: center;
+	.outline {
+		position: absolute;
+		top: 0;
+		left: 0;
+		bottom: 0;
+		width: 750rpx;
+		height: 1125rpx;
+		z-index: 99;
+		align-items: center;
+		justify-content: center;
+	}
+	.remind {
+		position: absolute;
+		top: 880rpx;
+		width: 750rpx;
+		z-index: 100;
+		align-items: center;
+		justify-content: center;
+		.remind-text {
+			color: #dddddd;
+			font-weight: bold;
+		}
+	}
+	.menu {
+		position: absolute;
+		left: 0;
+		bottom: 0;
+		width: 750rpx;
+		height: 180rpx;
+		z-index: 98;
+		align-items: center;
+		justify-content: center;
+		.menu-mask {
+			position: absolute;
+			left: 0;
+			bottom: 0;
+			width: 750rpx;
+			height: 180rpx;
+			z-index: 98;
+		}
+		.menu-back {
+			position: absolute;
+			left: 30rpx;
+			bottom: 50rpx;
+			width: 80rpx;
+			height: 80rpx;
+			z-index: 99;
+			align-items: center;
+			justify-content: center;
+		}
+		.menu-snapshot {
+			width: 130rpx;
+			height: 130rpx;
+			z-index: 99;
+		}
+		.menu-flip {
+			position: absolute;
+			right: 30rpx;
+			bottom: 50rpx;
+			width: 80rpx;
+			height: 80rpx;
+			z-index: 99;
+			align-items: center;
+			justify-content: center;
+		}
+	}
+}
+</style>

+ 228 - 0
pages/mine/camera/watermark/watermark.nvue

@@ -0,0 +1,228 @@
+<template>
+	<view class="live-camera" :style="{ width: windowWidth, height: windowHeight }">
+		<view class="preview" :style="{ width: windowWidth, height: windowHeight}">
+			<live-pusher
+				id="livePusher"
+				ref="livePusher"
+				class="livePusher"
+				mode="FHD"
+				beauty="0"
+				whiteness="0"
+				:aspect="aspect"
+				min-bitrate="1000"
+				audio-quality="16KHz"
+				device-position="back"
+				:auto-focus="true"
+				:muted="true"
+				:enable-camera="true"
+				:enable-mic="false"
+				:zoom="false"
+				@statechange="statechange"
+				:style="{ width: windowWidth, height: windowHeight }"
+			></live-pusher>
+			<!--提示语-->
+			<cover-view class="remind">
+				<text class="remind-text" style="">{{ message }}</text>
+			</cover-view>
+		</view>
+		<view class="menu">
+			<!--底部菜单区域背景-->
+			<cover-image class="menu-mask" src="/static/live-camera/bar.png"></cover-image>
+
+			<!--返回键-->
+			<cover-image class="menu-back" @tap="back" src="/static/live-camera/back.png"></cover-image>
+
+			<!--快门键-->
+			<cover-image class="menu-snapshot" @tap="snapshot" src="/static/live-camera/shutter.png"></cover-image>
+
+			<!--反转键-->
+			<cover-image class="menu-flip" @tap="flip" src="/static/live-camera/flip.png"></cover-image>
+		</view>
+	</view>
+</template>
+
+<script>
+let _this = null;
+export default {
+	data() {
+		return {
+			dotype:'watermark',
+			message:'live-camer',//水印内容
+			poenCarmeInterval: null, //打开相机的轮询
+			aspect: '2:3', //比例
+			windowWidth: '', //屏幕可用宽度
+			windowHeight: '', //屏幕可用高度
+			camerastate: false, //相机准备好了
+			livePusher: null, //流视频对象
+			snapshotsrc: null //快照
+		};
+	},
+	onLoad(e) {
+		_this = this;
+		if (e.dotype != undefined) this.dotype = e.dotype;
+		this.initCamera();
+	},
+	onReady() {
+		this.livePusher = uni.createLivePusherContext('livePusher', this);
+		this.startPreview(); //开启预览并设置摄像头
+		this.poenCarme();
+	},
+	methods: {
+		//轮询打开
+		poenCarme() {
+			//#ifdef APP-PLUS
+			if (plus.os.name == 'Android') {
+				this.poenCarmeInterval = setInterval(function() {
+					console.log(_this.camerastate);
+					if (!_this.camerastate) _this.startPreview();
+				}, 2500);
+			}
+			//#endif
+		},
+		//初始化相机
+		initCamera() {
+			uni.getSystemInfo({
+				success: function(res) {
+					_this.windowWidth = res.windowWidth;
+					_this.windowHeight = res.windowHeight;
+					let zcs = _this.aliquot(_this.windowWidth, _this.windowHeight);
+					_this.aspect = _this.windowWidth / zcs + ':' + _this.windowHeight / zcs;
+					console.log('画面比例:'+_this.aspect);
+				}
+			});
+		},
+
+		//整除数计算
+		aliquot(x, y) {
+			if (x % y == 0) return y;
+			return this.aliquot(y, x % y);
+		},
+
+		//开始预览
+		startPreview() {
+			this.livePusher.startPreview({
+				success: a => {
+					console.log(a);
+				}
+			});
+		},
+
+		//停止预览
+		stopPreview() {
+			this.livePusher.stopPreview({
+				success: a => {
+					_this.camerastate = false; //标记相机未启动
+				}
+			});
+		},
+
+		//状态
+		statechange(e) {
+			//状态改变
+			console.log(e);
+			if (e.detail.code == 1007) {
+				_this.camerastate = true;
+			} else if (e.detail.code == -1301) {
+				_this.camerastate = false;
+			}
+		},
+
+		//返回
+		back() {
+			uni.navigateBack();
+		},
+
+		//抓拍
+		snapshot() {
+			this.livePusher.snapshot({
+				success: e => {
+					_this.snapshotsrc = e.message.tempImagePath;
+					_this.stopPreview();
+					_this.setImage();
+					uni.navigateBack();
+				}
+			});
+		},
+
+		//反转
+		flip() {
+			this.livePusher.switchCamera();
+		},
+
+		//设置
+		setImage() {
+			let pages = getCurrentPages();
+			let prevPage = pages[pages.length - 2]; //上一个页面
+
+			//直接调用上一个页面的setImage()方法,把数据存到上一个页面中去
+			prevPage.$vm.setImage({ path: _this.snapshotsrc , dotype: this.dotype });
+		}
+	}
+};
+</script>
+
+<style lang="scss">
+.live-camera {
+	justify-content: center;
+	align-items: center;
+	.preview {
+		justify-content: center;
+		align-items: center;
+		.remind {
+			position: absolute;
+			top: 60rpx;
+			left: 20rpx;
+			width: 130px;
+			z-index: 100;
+			.remind-text {
+				color: #dddddd;
+				font-size: 40rpx;
+				text-shadow: #fff 1px 0 0, #fff 0 1px 0, #fff -1px 0 0, #fff 0 -1px 0;
+			}
+		}
+	}
+	.menu {
+		position: absolute;
+		left: 0;
+		bottom: 0;
+		width: 750rpx;
+		height: 180rpx;
+		z-index: 98;
+		align-items: center;
+		justify-content: center;
+		.menu-mask {
+			position: absolute;
+			left: 0;
+			bottom: 0;
+			width: 750rpx;
+			height: 180rpx;
+			z-index: 98;
+		}
+		.menu-back {
+			position: absolute;
+			left: 30rpx;
+			bottom: 50rpx;
+			width: 80rpx;
+			height: 80rpx;
+			z-index: 99;
+			align-items: center;
+			justify-content: center;
+		}
+		.menu-snapshot {
+			width: 130rpx;
+			height: 130rpx;
+			z-index: 99;
+		}
+		.menu-flip {
+			position: absolute;
+			right: 30rpx;
+			bottom: 50rpx;
+			width: 80rpx;
+			height: 80rpx;
+			z-index: 99;
+			align-items: center;
+			justify-content: center;
+		}
+	}
+}
+</style>

+ 61 - 0
pages/mine/cargoowner/cargoowner.vue

@@ -0,0 +1,61 @@
+<template>
+	<view class='content'>
+		<view class='identity flex items-center'>
+			<view style='width:100%;' class='flex items-center'>
+				<u--image class='image' :showLoading="true" src="../../../static/mine/huozhurenzheng/shenfen.png" width="32px"
+				height="32px"></u--image>
+				<view style='width:100%;'>
+					<view style='font-size:21px;'>身份信息</view>
+					<view class='flex flex-space-between' style='width:100%;color:#999999;font-size:14px;'>您还未认证身份信息<u-icon name="arrow-right" color="#7E7E7E" size="10"></u-icon></view>
+				</view>
+			</view>
+		</view>
+		<view>
+			<view>所属企业(0)</view>
+			<view>
+				<view>
+					<view>公司</view>
+					<view>状态</view>
+				</view>
+				<view>
+					<view>可垫付运费</view>
+					<view>编辑</view>
+					<view>删除</view>
+				</view>
+				
+			</view>
+			<view>
+				<u--image class='image weibangding' :showLoading="true" src="../../../static/mine/huozhurenzheng/weibangding.png" width="141px"
+				height="141px"></u--image>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				
+			}
+		},
+		methods: {
+			
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.content{
+		height:90vh;
+	}
+	.identity{
+		background: url('~@/static/mine/huozhurenzheng/bg.png') no-repeat;
+		background-size:100%;
+		height:120px;
+		padding:0 30px;
+	}
+	.u-image {
+		 justify-content:center;
+	}
+</style>

+ 248 - 0
pages/mine/cargoowner/editpersonalinformation.vue

@@ -0,0 +1,248 @@
+<template>
+	<view class="content">
+		<view class="content3 flex s-row">
+			<view>个人信息</view>
+			<view class="flex flex-space-between width100">
+				<view>姓名</view>
+				<view class="flex">
+					<u--input placeholder="输入姓名" inputAlign='right' border="none" v-model="dataDetails.name">
+					</u--input>
+				</view>
+			</view>
+			<view class="flex flex-space-between width100">
+				<view>联系电话</view>
+				<view class="flex">
+					<u--input placeholder="输入联系电话" inputAlign='right' border="none" v-model="dataDetails.name">
+					</u--input>
+				</view>
+			</view>
+			<view class="flex flex-space-between width100">
+				上传身份证人像面
+			</view>
+	
+			<u-button type="primary" @click="uploadImg(3)">上传身份证人像面</u-button>
+			<view class="flex flex-space-between width100">
+				上传身份证国徽面
+			</view>
+				
+			<u-button type="primary" @click="uploadImg(3)">上传身份证国徽面</u-button>
+			<view class="flex flex-space-between width100">
+				<view>身份证号</view>
+				<view class="flex">
+					<u--input placeholder="输入身份证号" inputAlign='right' border="none" v-model="dataDetails.name">
+					</u--input>
+				</view>
+			</view>
+			<view class="flex flex-space-between width100">
+				<view>身份证有效期</view>
+				<view class="flex">
+					<u--input placeholder="选择身份证有效期" inputAlign='right' border="none" v-model="dataDetails.name">
+					</u--input>
+					<view>手动输入</view>
+				</view>
+			</view>
+			 <u-checkbox-group
+			            v-model="checkboxValue1"
+			            placement="column"
+			            @change="checkboxChange"
+			        >
+			            <u-checkbox v-model="checked" label="我已阅读并同意全部细则"
+                name="1">明月</u-checkbox>
+			        </u-checkbox-group>
+			<!-- <view class="flex flex-space-between width100">
+				<view>收款人</view>
+				<view class="flex">
+					<u--input placeholder="输入收款人姓名" inputAlign='right' border="none" v-model="dataDetails.name">
+					</u--input>
+				</view>
+			</view> -->
+		</view>
+		<view class="" @click="submit">提交</view>
+		<u-action-sheet :actions="$helper.imgTypeList" :title="$helper.imgType" :show="isShowimgType"
+			@select="imgTypeSelect" :closeOnClickOverlay="true" :closeOnClickAction="true" @close="isShowimgType=false">
+		</u-action-sheet>
+	</view>
+</template>
+
+<script>
+	import upload from '@/components/upload.vue';
+	import uploadImage from '@/components/ossutil/uploadFile.js';
+	var _this;
+	export default {
+		components: {},
+		data() {
+			return {
+				uploadType: '',
+				isShowimgType: false,
+				dataDetails: {
+					name: '阿萨啊',
+					carNumberList: [{
+						kahao: '',
+						addressUrl: ''
+					}],
+					bankList: [{
+						yhk: '',
+						kh: '',
+						khh: '',
+						khzh: '',
+						skr: ''
+					}],
+				},
+				imagesrc: ''
+			};
+		},
+		onLoad() {
+			_this = this;
+		},
+		methods: {
+			//设置图片
+			setImage(e) {
+				debugger
+				console.log(e);
+				//显示在页面
+				//this.imagesrc = e.path;
+				if (e.dotype == 'idphoto') {
+					_this.zjzClipper(e.path);
+				} else if (e.dotype == 'watermark') {
+					_this.watermark(e.path);
+				} else {
+					_this.savePhoto(e.path);
+				}
+			},
+			//保存图片到相册,方便核查
+			savePhoto(path) {
+				debugger
+				this.imagesrc = path;
+				uploadImage(path, 'appData/',
+					result => {
+						// 上传成功
+						console.log('图片地址', result)
+					}
+				)
+				//保存到相册
+				// uni.saveImageToPhotosAlbum({
+				// 	filePath: path,
+				// 	success: () => {
+				// 		uni.showToast({
+				// 			title: '已保存至相册',
+				// 			duration: 2000
+				// 		});
+				// 	}
+				// });
+			},
+			uploadImg(type) {
+	
+				this.uploadType = type
+				this.isShowimgType = true
+			},
+			photograph() {
+				console.log('拍照')
+				let that = this;
+				uni.chooseImage({
+					count: 1,
+					success: function(res) {
+						console.log(JSON.stringify(res.tempFilePaths));
+						uploadImage(res.tempFilePaths[0], 'appData/',
+							result => {
+								// 上传成功
+								console.log('图片地址', result)
+							}
+						)
+					}
+				});
+	
+			},
+			imgTypeSelect(val) {
+				console.log(val)
+				console.log(this.uploadType)
+				if (val.name == '相册') {
+					uni.chooseImage({
+						count: 1,
+						sourceType: this.$helper.chooseImage.sourceType,
+						success: function(res) {
+							console.log(JSON.stringify(res.tempFilePaths));
+							uploadImage(res.tempFilePaths[0], 'appData/',
+								result => {
+									// 上传成功
+									console.log('图片地址', result)
+									switch (this.uploadType) {
+										case 0:
+											console.log('人车合影')
+											break
+										case 1:
+											console.log('身份正面')
+											break
+										case 2:
+											console.log('身份反面')
+											break
+										case 3:
+											console.log('银行卡')
+											break
+										case 4:
+									}
+								}
+							)
+						}
+					});
+	
+				} else {
+					switch (this.uploadType) {
+						case 0:
+							console.log('人车合影')
+							break
+						case 1:
+							uni.$u.route('/pages/mine/camera/idcard/idcard?dotype=face');
+							console.log('身份正面')
+							break
+						case 2:
+							console.log('身份反面')
+							break
+						case 3:
+							console.log('银行卡')
+							break
+						case 4:
+					}
+				}
+	
+			},
+			//身份证正面
+			getImgUrl1(src) {
+				// console.log(src)
+				// console.log('------------res-----------')
+				// let that = this;
+				// that.id[0] = src
+				// that.id1 = src
+				// that.certificates = false
+				// that.personImgs.personImg = that.id[0]
+				// that.$api.doRequest('get', '/driverViewInfo/personShibie', that
+				// 	.personImgs).then(res => {
+				// 	if (res.data.data.recPerson != null) {
+				// 		if (res.data.data.recPerson != "") {
+				// 			that.$set(that.DriverViewInfo, 'driverName', res
+				// 				.data.data.recPerson)
+				// 		}
+				// 	}
+				// 	if (res.data.data.recPersonNo != null) {
+				// 		if (res.data.data.recPersonNo != "") {
+				// 			that.$set(that.DriverViewInfo, 'numberCard', res
+				// 				.data.data.recPersonNo)
+				// 		}
+				// 	}
+				// }).catch(res => {
+				// 	uni.showToast({
+				// 		title: res.data.message,
+				// 		icon: 'none',
+				// 		duration: 2000
+				// 	})
+				// })
+			},
+			submit(){
+				console.log(' tijia')
+			},
+		},
+	};
+</script>
+
+<style>
+
+</style>

+ 531 - 0
pages/mine/driverCertification.vue

@@ -0,0 +1,531 @@
+<template>
+	<view class="content">
+		<view class="content1 content-other">
+			<view class="flex flex-space-between">
+				<view>姓名</view>
+				<u--input placeholder="请输入内容" inputAlign='right' border="none" v-model="dataDetails.driverName">
+				</u--input>
+			</view>
+			<view class="flex flex-space-between">
+				<view>联系电话</view>
+				<u--input placeholder="请输入联系电话" inputAlign='right' border="none" v-model="dataDetails.driverPhone">
+				</u--input>
+			</view>
+			<view class="flex s-row" v-for="(item,index) in dataDetails.driverCarInfoList" :key='index'>
+				<view class="flex flex-space-between width100">
+					<view class="left">
+						车牌号-{{index+1}}
+					</view>
+					<view class="right flex">
+						<input class="car-uumber" v-model='item.carNumber' @click.stop="handleShowKeyboard(index)"
+							:disabled="true" placeholder="输入7位车牌号" name="input"></input>
+						<!-- <u-input v-model="item1.carNo" placeholder="输入7位车牌号" /> -->
+						<view class="flex">
+							<view @click="addCarNumber(dataDetails.driverCarInfoList)" style="margin-right: 20rpx;">
+								<image class='row4-img'
+									src="https://taohaoliang.oss-cn-beijing.aliyuncs.com/app/tmp/jia%402x.png">
+								</image>
+							</view>
+							<view @click="delCarNumber(dataDetails.driverCarInfoList,index)">
+								<image class='row4-img'
+									src="https://taohaoliang.oss-cn-beijing.aliyuncs.com/app/tmp/jian%402x.png">
+								</image>
+							</view>
+						</view>
+					</view>
+				</view>
+				<view class="width100">
+					<view class="">人车合影-{{index+1}}</view>
+					<u-button type="primary" @click="uploadImg(0,item)">上传人车合影</u-button>
+					<image class="preview" :src="item.addressUrl" mode="aspectFit"
+						style="width:710rpx:height:710rpx;margin: 20rpx;">
+						<!-- 		<upload class="upload" ref="upload" :action="action" :max-size="maxSize" :max-count="1"
+						:size-type="['compressed']" @on-success="getImgUrl" @on-error="onError" @on-remove="onRemove"
+						@on-uploaded="isAdd = true" :before-upload="filterFileType" @on-progress="onProgress"></upload> -->
+				</view>
+			</view>
+		</view>
+		<u-divider text="分割线"></u-divider>
+		<view class="content2 content-other">
+			<u-button type="primary" @click="uploadImg(1)">上传身份证人像</u-button>
+			<!-- <upload class="upload" ref="upload" :action="action" :max-size="maxSize" :max-count="1"
+				:size-type="['compressed']" @on-success="getImgUrl1" @on-error="onError" @on-remove="onRemove"
+				@on-uploaded="isAdd = true" :before-upload="filterFileType" :options="uploadOptions1"
+				:custom="uploadCustom1" @on-progress="onProgress"></upload> -->
+			<!-- <navigator class="buttons" url="./camera/idcard/idcard?dotype=face"><button type="primary">打开身份证人像面采集相机</button></navigator> -->
+			<!-- <view>拍摄结果预览图,见下方</view> -->
+			<image class="preview" :src="dataDetails.cardAddressUrl" mode="aspectFit"
+				style="width:710rpx:height:710rpx;margin: 20rpx;">
+			</image>
+			<view class="flex flex-space-between">
+				<view>身份证号</view>
+				<u--input placeholder="请输入身份证号" inputAlign='right' border="none" v-model="dataDetails.numberCard">
+				</u--input>
+			</view>
+			<u-button type="primary" @click="uploadImg(2)">上传身份证国徽页</u-button>
+			<image class="preview" :src="dataDetails.cardBackAddressUrl" mode="aspectFit"
+				style="width:710rpx:height:710rpx;margin: 20rpx;">
+			</image>
+			<view class="flex flex-space-between">
+				<view>身份证截止日期</view>
+				<view class="" @click="selectValidityPeriod">
+					{{dataDetails.cardValidityDate?dataDetails.cardValidityDate:'选择身份证截止日期'}}</view>
+
+			</view>
+			<u-picker :show="isShowcardValidity" ref="uPicker" :columns="validityPeriod"
+				@confirm="confirmValidityPeriod" @change="changeHandler">
+			</u-picker>
+		</view>
+		<u-divider text="分割线"></u-divider>
+		<view class="content3 flex s-row" v-for="(item,index) in dataDetails.bankList" :key='index'>
+			<view class="flex flex-space-between width100">
+				<view class="left">
+					银行卡-{{index+1}}
+				</view>
+				<view class="right flex">
+					<view class="flex">
+						<view @click="addBankNumber(dataDetails.bankList)" style="margin-right: 20rpx;">
+							<image class='row4-img'
+								src="https://taohaoliang.oss-cn-beijing.aliyuncs.com/app/tmp/jia%402x.png">
+							</image>
+						</view>
+						<view @click="delBankNumber(dataDetails.bankList,index)">
+							<image class='row4-img'
+								src="https://taohaoliang.oss-cn-beijing.aliyuncs.com/app/tmp/jian%402x.png">
+							</image>
+						</view>
+					</view>
+				</view>
+			</view>
+			<!-- 	<view class="width100">
+				<view class="">上传银行卡号面</view>
+				<upload class="upload" ref="upload" :action="action" :max-size="maxSize" :max-count="1"
+					:size-type="['compressed']" @on-success="getImgUrl" @on-remove="onRemove" delIconSize='30'
+					delBgColor='rgba(0,0,0,0.4)' delIcon="trash" @on-uploaded="isAdd = true"
+					:before-upload="filterFileType" :options="uploadOptions3" :custom="uploadCustom3"></upload>
+			</view> -->
+			<u-button type="primary" @click="uploadImg(3)">上传银行卡号页</u-button>
+			<view class="flex flex-space-between width100">
+				<view>银行卡卡号</view>
+				<view class="flex">
+					<u--input placeholder="输入银行卡号码" inputAlign='right' border="none" v-model="dataDetails.name">
+					</u--input>
+					<u--image src="../../static/images/xiangji-2.png" width="40px" height="40px" @click='photograph'>
+					</u--image>
+				</view>
+			</view>
+			<view class="flex flex-space-between width100">
+				<view>开户行</view>
+				<view class="flex">
+					<u--input placeholder="输入开户行" inputAlign='right' border="none" v-model="dataDetails.name">
+					</u--input>
+				</view>
+			</view>
+			<view class="flex flex-space-between width100">
+				<view>开户支行</view>
+				<view class="flex">
+					<u--input placeholder="选择开户支行" inputAlign='right' border="none" v-model="dataDetails.name">
+					</u--input>
+					<view>手动输入</view>
+				</view>
+			</view>
+			<view class="flex flex-space-between width100">
+				<view>收款人</view>
+				<view class="flex">
+					<u--input placeholder="输入收款人姓名" inputAlign='right' border="none" v-model="dataDetails.name">
+					</u--input>
+				</view>
+			</view>
+		</view>
+		<view class="content4">
+			<u-button type="primary" @click="next()">
+				下一步
+			</u-button>
+		</view>
+		<master-keyboard ref="keyboard" keyboardtype="car" :show="keyShow" :randomNumber="true" :newCar="false"
+			:defaultValue="carNumber" @keyboardClick="handleClick"></master-keyboard>
+		<u-toast ref="uToast"></u-toast>
+		<u-action-sheet :actions="$helper.imgTypeList" :title="$helper.imgType" :show="isShowimgType"
+			@select="imgTypeSelect" :closeOnClickOverlay="true" :closeOnClickAction="true" @close="isShowimgType=false">
+		</u-action-sheet>
+	</view>
+</template>
+
+<script>
+	import keyboard from "@/components/master-keyboard/master-keyboard.vue";
+	import upload from '@/components/upload.vue';
+	import uploadImage from '@/components/ossutil/uploadFile.js';
+	var _this;
+	export default {
+		components: {
+			keyboard,
+			upload
+		},
+		data() {
+			return {
+				index:'',
+				validityPeriod: [],
+				isShowcardValidity: false,
+				uploadType: '',
+				isShowimgType: false,
+				// uploadOptions1: {
+				// 	"text": "上传身份证头像页",
+				// 	"bgc": "https://taohaoliang.oss-cn-beijing.aliyuncs.com/app/tmp/identityup%282%29.png"
+				// },
+				// uploadOptions2: {
+				// 	"text": "上传身份证国徽页",
+				// 	"bgc": "https://taohaoliang.oss-cn-beijing.aliyuncs.com/app/tmp/identitylow%282%29.png"
+				// },
+				// uploadOptions3: {
+				// 	"text": "上传银行卡正面",
+				// 	"bgc": "https://taohaoliang.oss-cn-beijing.aliyuncs.com/app/tmp/bankup%282%29.png"
+				// },
+				carInfo: '',
+				dataDetails: {
+					commonId: '',
+					driverName: '',
+					driverPhone: '',
+					cardAddressUrl: '',
+					cardBackAddressUrl: '',
+					cardValidityDate: '',
+					driverType: '',
+					driverLicenseHomePage: '',
+					driverLicenseBackPage: '',
+					driverLicenseValidityDate: '',
+					drivingLicenseHomePage: '',
+					drivingLicenseBackPage: '',
+					drivingLicenseValidityDate: '',
+					trailerLicenseHomePage: '',
+					trailerLicenseBackPage: '',
+					trailerLicenseValidityDate: '',
+					qualificationCertificate: '',
+					qualificationCertificateValidityDate: '',
+					operationCertificate: '',
+					operationCertificateValidityDate: '',
+					trailerOperationCertificate: '',
+					trailerOperationCertificateValidityDate: '',
+					numberCard: '',
+					numberCard: '',
+					numberCard: '',
+					numberCard: '',
+					numberCard: '',
+					numberCard: '',
+					numberCard: '',
+					numberCard: '',
+					numberCard: '',
+					numberCard: '',
+					numberCard: '',
+					numberCard: '',
+					numberCard: '',
+					driverCarInfoList: [{
+						carNumber: '',
+						addressUrl: ''
+					}],
+					driverPayeeInfoList: [{
+						payeeAddressUrl: '',
+						bankCard: '',
+						bankDeposit: '',
+						bankDepositBranch: '',
+						payeeName: ''
+					}],
+				},
+				keyShow: false,
+				carNumber: '',
+				action: this.$helper.ossUploadUrl,
+				maxSize: 50 * 1024 * 1024, //限制文件大小 50M
+				isAdd: true,
+				imagesrc: ''
+			};
+		},
+		onLoad() {
+			_this = this;
+			this.makeValidityPeriod()
+		},
+		methods: {
+			changeHandler(e) {
+				const {
+					columnIndex,
+					value,
+					values,
+					index,
+					picker = this.$refs.uPicker
+				} = e
+
+				// if (columnIndex === 0) {
+				// 	debugger
+				// 	if (e.index != 0) {
+				// 		picker.setColumnValues(1, this.validityPeriod[1].shift())
+				// 	}
+
+				// } else if (columnIndex === 1) {
+				// 	if (e.index != 0) {
+				// 		picker.setColumnValues(2, this.validityPeriod[2].shift())
+				// 	}
+				// }
+			},
+			// 回调参数为包含columnIndex、value、values
+			confirmValidityPeriod(e) {
+				debugger
+				console.log('confirm', e)
+				if (e.value[0] == '长期') {
+					this.dataDetails.cardValidityDate = e.value[0]
+				} else {
+					this.dataDetails.cardValidityDate = e.value[0] + '-' + e.value[1] + '-' + e.value[2]
+				}
+
+				this.isShowcardValidity = false
+			},
+			makeValidityPeriod() {
+				//获取当前年
+				let nowDate = new Date();
+				let year = nowDate.getFullYear()
+				let _list1 = ['长期']
+				// let _list2 = ["一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月"]
+				let _list2 = ['长期', "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12"]
+				let _list3 = ['长期', "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12", "13", "14",
+					"15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30",
+					"31"
+				]
+				let _ValidityPeriod = []
+				for (let i = 0; i < 30; i++) {
+					_list1.push(year + i)
+				}
+				this.validityPeriod.push(_list1, _list2, _list3)
+
+			},
+			selectValidityPeriod() {
+				this.isShowcardValidity = true
+			},
+			//设置图片
+			setImage(e) {
+				debugger
+				console.log(e);
+				//显示在页面
+				//this.imagesrc = e.path;
+				if (e.dotype == 'idphoto') {
+					_this.zjzClipper(e.path);
+				} else if (e.dotype == 'watermark') {
+					_this.watermark(e.path);
+				} else {
+					_this.savePhoto(e.path);
+				}
+			},
+			//保存图片到相册,方便核查
+			savePhoto(path) {
+				debugger
+				this.imagesrc = path;
+				uploadImage(path, 'appData/',
+					result => {
+						// 上传成功
+						console.log('图片地址', result)
+					}
+				)
+				//保存到相册
+				// uni.saveImageToPhotosAlbum({
+				// 	filePath: path,
+				// 	success: () => {
+				// 		uni.showToast({
+				// 			title: '已保存至相册',
+				// 			duration: 2000
+				// 		});
+				// 	}
+				// });
+			},
+			uploadImg(type, val) {
+				debugger
+				this.uploadType = type
+				this.isShowimgType = true
+				this.carInfo = val
+			},
+			photograph() {
+				console.log('拍照')
+				let that = this;
+				uni.chooseImage({
+					count: 1,
+					success: function(res) {
+						console.log(JSON.stringify(res.tempFilePaths));
+						uploadImage(res.tempFilePaths[0], 'appData/',
+							result => {
+								// 上传成功
+								console.log('图片地址', result)
+							}
+						)
+					}
+				});
+
+			},
+			imgTypeSelect(val) {
+				debugger
+				console.log(val)
+				console.log(this.uploadType)
+				if (val.name == '相册') {
+					uni.chooseImage({
+						count: 1,
+						sourceType: this.$helper.chooseImage.sourceType,
+						success: function(res) {
+							console.log(JSON.stringify(res.tempFilePaths));
+							uploadImage(res.tempFilePaths[0], 'appData/',
+								result => {
+
+									// 上传成功
+									console.log('图片地址', result)
+									switch (_this.uploadType) {
+										case 0:
+											//赋值上传图片图片路径
+											for (let i = 0; i < _this.dataDetails.driverCarInfoList
+												.length; i++) {
+												let _item = _this.dataDetails.driverCarInfoList[i]
+												if (_item.carNumber == _this.carInfo.carNumber) {
+													_item.addressUrl = result
+													}
+										}
+										
+											console.log('人车合影')
+											break
+										case 1:
+											console.log('身份正面')
+											break
+										case 2:
+											console.log('身份反面')
+											break
+										case 3:
+											console.log('银行卡')
+											break
+										case 4:
+									}
+								}
+							)
+						}
+					});
+
+				} else {
+					switch (this.uploadType) {
+						case 0:
+							console.log('人车合影')
+							break
+						case 1:
+							uni.$u.route('/pages/mine/camera/idcard/idcard?dotype=face');
+							console.log('身份正面')
+							break
+						case 2:
+							console.log('身份反面')
+							break
+						case 3:
+							console.log('银行卡')
+							break
+						case 4:
+					}
+				}
+
+			},
+			//身份证正面
+			getImgUrl1(src) {
+				// console.log(src)
+				// console.log('------------res-----------')
+				// let that = this;
+				// that.id[0] = src
+				// that.id1 = src
+				// that.certificates = false
+				// that.personImgs.personImg = that.id[0]
+				// that.$api.doRequest('get', '/driverViewInfo/personShibie', that
+				// 	.personImgs).then(res => {
+				// 	if (res.data.data.recPerson != null) {
+				// 		if (res.data.data.recPerson != "") {
+				// 			that.$set(that.DriverViewInfo, 'driverName', res
+				// 				.data.data.recPerson)
+				// 		}
+				// 	}
+				// 	if (res.data.data.recPersonNo != null) {
+				// 		if (res.data.data.recPersonNo != "") {
+				// 			that.$set(that.DriverViewInfo, 'numberCard', res
+				// 				.data.data.recPersonNo)
+				// 		}
+				// 	}
+				// }).catch(res => {
+				// 	uni.showToast({
+				// 		title: res.data.message,
+				// 		icon: 'none',
+				// 		duration: 2000
+				// 	})
+				// })
+			},
+			handleClick(e) {debugger
+				this.carNumber = e.value
+				this.dataDetails.driverCarInfoList[this.index].carNumber = e.value //键盘输入值
+			},
+			handleShowKeyboard(index) {
+				debugger
+				if (this.dataDetails.driverCarInfoList[index].carNumber == '') {
+					this.carNumber = ''
+				} else {
+					this.carNumber = this.dataDetails.driverCarInfoList[index].carNumber
+				}
+				if (this.$refs.keyboard.open) {
+					this.$refs.keyboard.open(false) //true 键盘显示 false 键盘隐藏
+				} else {
+					this.$refs.keyboard[0].open(false)
+				}
+				this.index = index
+				if (this.$refs.keyboard.open) {
+					this.$refs.keyboard.open(true) //true 键盘显示 false 键盘隐藏
+				} else {
+					this.$refs.keyboard[0].open(true)
+				}
+			},
+			addCarNumber(val) {
+				val.push({
+					carNo: ''
+				})
+			},
+			delCarNumber(val, index) {
+				if (val.length > 1) {
+					val.splice(index, 1)
+					this.$forceUpdate()
+				} else {
+					let params = {
+						type: 'error',
+						message: "至少保留一个车牌号!",
+						iconUrl: 'https://cdn.uviewui.com/uview/demo/toast/success.png'
+					}
+					this.$refs.uToast.show({
+						...params
+					})
+				}
+			},
+			addBankNumber(val) {
+				val.push({
+					bankNo: ''
+				})
+			},
+			delBankNumber(val, index) {
+				if (val.length > 1) {
+					val.splice(index, 1)
+					this.$forceUpdate()
+				} else {
+					let params = {
+						type: 'error',
+						message: "至少保留一张银行卡!",
+						iconUrl: 'https://cdn.uviewui.com/uview/demo/toast/success.png'
+					}
+					this.$refs.uToast.show({
+						...params
+					})
+				}
+			},
+			next(val) {
+				console.log(111111111111)
+				uni.$u.route('/pages/mine/driverCertificationNext', {
+					id: 1,
+				});
+			}
+
+		},
+	};
+</script>
+
+<style scoped lang="scss">
+	.row4-img {
+		width: 32rpx;
+		height: 32rpx;
+	}
+</style>

+ 329 - 0
pages/mine/driverCertificationNext.vue

@@ -0,0 +1,329 @@
+<template>
+	<view class="content">
+		<u-radio-group v-model="radiovalue1" iconPlacement="row">
+			<u-radio :customStyle="{marginBottom: '8px'}" v-for="(item, index) in radiolist1" :key="index"
+				:label="item.name" :name="item.name" @change="radioChange">
+			</u-radio>
+		</u-radio-group>
+
+		<view class="level1-title">证件信息</view>
+		<view class="content1">
+			<view class="flex flex-space-between">
+				<view class="left">
+					<view>驾驶证主页</view>
+					<u-button type="primary">上传驾驶证主页</u-button>
+				</view>
+				<view class="left">
+					<view>驾驶证副页</view>
+					<u-button type="primary">上传驾驶证副页</u-button>
+				</view>
+			</view>
+			<view class="flex flex-space-between">
+				<view>驾驶证有效期</view>
+				<view>选择驾驶证有效期</view>
+			</view>
+		</view>
+
+		<u-divider text="分割线"></u-divider>
+		<view class="content2">
+			<view class="flex flex-space-between">
+				<view class="left">
+					<view>行驶证主页</view>
+					<u-button type="primary">上传行驶证主页</u-button>
+				</view>
+				<view class="left">
+					<view>行驶证副页</view>
+					<u-button type="primary">上传行驶证副页</u-button>
+				</view>
+			</view>
+			<view class="flex flex-space-between">
+				<view>行驶证有效期</view>
+				<view>选择行驶证有效期</view>
+			</view>
+		</view>
+		<u-divider text="分割线"></u-divider>
+		<view class="content3">
+			<view class="flex flex-space-between">
+				<view class="left">
+					<view>挂车行驶证主页</view>
+					<u-button type="primary">上传挂车行驶证主页</u-button>
+				</view>
+				<view class="left">
+					<view>挂车行驶证副页</view>
+					<u-button type="primary">上传挂车行驶证副页</u-button>
+				</view>
+			</view>
+			<view class="flex flex-space-between">
+				<view>挂车行驶证有效期</view>
+				<view>选择挂车行驶证有效期</view>
+			</view>
+			<u-divider text="分割线"></u-divider>
+		</view>
+		<view class="content4">
+			<view class="flex s-row">
+				<view class="">从业资格证</view>
+				<u-button type="primary">上传从业资格证</u-button>
+			</view>
+			<view class="flex flex-space-between">
+				<view>从业资格证有效期</view>
+				<view>选择从业资格证有效期</view>
+			</view>
+		</view>
+		<u-divider text="分割线"></u-divider>
+		<view class="content5">
+			<view class="flex s-row">
+				<view class="">运营证</view>
+				<u-button type="primary">上传运营证</u-button>
+			</view>
+			<view class="flex flex-space-between">
+				<view>运营证有效期</view>
+				<view>选择运营证有效期</view>
+			</view>
+		</view>
+		<u-divider text="分割线"></u-divider>
+		<view class="content6">
+			<view class="flex s-row">
+				<view class="">挂车运营证</view>
+				<u-button type="primary">上传挂车运营证</u-button>
+			</view>
+			<view class="flex flex-space-between">
+				<view>挂车运营证有效期</view>
+				<view>选择挂车运营证有效期</view>
+			</view>
+		</view>
+		<u-button type="primary" @click="submit">提交</u-button>
+		<u-toast ref="uToast"></u-toast>
+
+	</view>
+</template>
+
+<script>
+	import uploadImage from '@/components/ossutil/uploadFile.js';
+	var _this;
+	export default {
+		components: {},
+		data() {
+			return {
+				radiolist1: [{
+						name: '挂车司机',
+						disabled: false
+					},
+					{
+						name: '非挂车司机',
+						disabled: false
+					}
+				],
+				// u-radio-group的v-model绑定的值如果设置为某个radio的name,就会被默认选中
+				radiovalue1: '挂车司机',
+			};
+		},
+		onLoad(options) {
+			_this = this;
+			console.log(options)
+		},
+		methods: {
+			submit() {
+				// 校验
+				console.log('提交')
+			},
+			radioChange(n) {
+				console.log('radioChange', n);
+			},
+			//设置图片
+			setImage(e) {
+				debugger
+				console.log(e);
+				//显示在页面
+				//this.imagesrc = e.path;
+				if (e.dotype == 'idphoto') {
+					_this.zjzClipper(e.path);
+				} else if (e.dotype == 'watermark') {
+					_this.watermark(e.path);
+				} else {
+					_this.savePhoto(e.path);
+				}
+			},
+			//保存图片到相册,方便核查
+			savePhoto(path) {
+				debugger
+				this.imagesrc = path;
+				uploadImage(path, 'appData/',
+					result => {
+						// 上传成功
+						console.log('图片地址', result)
+					}
+				)
+				//保存到相册
+				// uni.saveImageToPhotosAlbum({
+				// 	filePath: path,
+				// 	success: () => {
+				// 		uni.showToast({
+				// 			title: '已保存至相册',
+				// 			duration: 2000
+				// 		});
+				// 	}
+				// });
+			},
+			uploadImg(type) {
+
+				this.uploadType = type
+				this.isShowimgType = true
+			},
+			photograph() {
+				console.log('拍照')
+				let that = this;
+				uni.chooseImage({
+					count: 1,
+					success: function(res) {
+						console.log(JSON.stringify(res.tempFilePaths));
+						uploadImage(res.tempFilePaths[0], 'appData/',
+							result => {
+								// 上传成功
+								console.log('图片地址', result)
+							}
+						)
+					}
+				});
+
+			},
+			imgTypeSelect(val) {
+				console.log(val)
+				console.log(this.uploadType)
+				if (val.name == '相册') {
+					uni.chooseImage({
+						count: 1,
+						sourceType: this.$helper.chooseImage.sourceType,
+						success: function(res) {
+							console.log(JSON.stringify(res.tempFilePaths));
+							uploadImage(res.tempFilePaths[0], 'appData/',
+								result => {
+									// 上传成功
+									console.log('图片地址', result)
+									switch (this.uploadType) {
+										case 0:
+											console.log('人车合影')
+											break
+										case 1:
+											console.log('身份正面')
+											break
+										case 2:
+											console.log('身份反面')
+											break
+										case 3:
+											console.log('银行卡')
+											break
+										case 4:
+									}
+								}
+							)
+						}
+					});
+
+				} else {
+					debugger
+					switch (this.uploadType) {
+						case 0:
+
+
+							console.log('人车合影')
+
+							break
+						case 1:
+							uni.$u.route('/pages/mine/camera/idcard/idcard?dotype=face');
+							console.log('身份正面')
+							break
+						case 2:
+							console.log('身份反面')
+							break
+						case 3:
+							console.log('银行卡')
+							break
+						case 4:
+					}
+				}
+
+			},
+			// 上传人车合影
+			unloadGroupPhoto() {
+				this.isShowimgType = true
+				// uni.chooseImage({
+				//     count: 1, 
+				//     success: function (res) {
+				//         console.log(JSON.stringify(res.tempFilePaths));
+				// 		uploadImage(res.tempFilePaths[0], 'appData/',
+				// 			result => {
+				// 				// 上传成功
+				// 				console.log('图片地址', result)
+				// 			}
+				// 		)
+				//     }
+				// });
+			},
+			//身份证正面
+			getImgUrl1(src) {
+				// console.log(src)
+				// console.log('------------res-----------')
+				// let that = this;
+				// that.id[0] = src
+				// that.id1 = src
+				// that.certificates = false
+				// that.personImgs.personImg = that.id[0]
+				// that.$api.doRequest('get', '/driverViewInfo/personShibie', that
+				// 	.personImgs).then(res => {
+				// 	if (res.data.data.recPerson != null) {
+				// 		if (res.data.data.recPerson != "") {
+				// 			that.$set(that.DriverViewInfo, 'driverName', res
+				// 				.data.data.recPerson)
+				// 		}
+				// 	}
+				// 	if (res.data.data.recPersonNo != null) {
+				// 		if (res.data.data.recPersonNo != "") {
+				// 			that.$set(that.DriverViewInfo, 'numberCard', res
+				// 				.data.data.recPersonNo)
+				// 		}
+				// 	}
+				// }).catch(res => {
+				// 	uni.showToast({
+				// 		title: res.data.message,
+				// 		icon: 'none',
+				// 		duration: 2000
+				// 	})
+				// })
+			},
+
+			// getImgUrl(res) {
+			// 	// this.detailData.addressUrl = res
+			// 	console.log(res)
+			// 	console.log('------------res-----------')
+			// },
+			// onError(error) {
+			// 	console.log('------------error-----------')
+			// 	console.log(error)
+			// },
+			// onRemove(index) {},
+			// filterFileType(index, lists) {
+			// 	if (lists[index].fileType != 'jpg' && lists[index].fileType != 'png' && lists[index].fileType != 'gif') {
+			// 		lists.splice(index, 1);
+			// 		// 当前文件不支持
+			// 		uni.showModal({
+			// 			title: '暂不支持当前图片类型',
+			// 			showCancel: false
+			// 		});
+			// 	} else {
+			// 		this.isAdd = false;
+			// 	}
+			// },
+			// onProgress(e) {
+			// 	console.log(e)
+			// },
+
+		},
+	};
+</script>
+
+<style scoped lang="scss">
+	.row4-img {
+		width: 32rpx;
+		height: 32rpx;
+	}
+</style>

+ 40 - 0
pages/mine/helpDescription.vue

@@ -0,0 +1,40 @@
+<!-- 帮助说明 -->
+<template>
+	<view class="content flex-center">
+		<view> 手机注册</view>
+		<u-icon name="arrow-downward" size="28"></u-icon>
+		<view>认证身份</view>
+		<u-icon name="arrow-downward" size="28"></u-icon>
+		<view> 发布货运信息</view>
+		<u-icon name="arrow-downward" size="28"></u-icon>
+		<view> 司机抢单</view>
+		<u-icon name="arrow-downward" size="28"></u-icon>
+		<view> 签订运输合同</view>
+		<u-icon name="arrow-downward" size="28"></u-icon>
+		<view> 司机装车反馈,货主确认</view>
+		<u-icon name="arrow-downward" size="28"></u-icon>
+		<view> 平台支付运费预付款</view>
+		<u-icon name="arrow-downward" size="28"></u-icon>
+		<view> 司机卸车反馈,货主确认</view>
+		<u-icon name="arrow-downward" size="28"></u-icon>
+		<view> 平台支付运费尾款</view>
+		<u-icon name="arrow-downward" size="28"></u-icon>
+		<view> 还款</view>
+		<u-icon name="arrow-downward" size="28"></u-icon>
+		<view> 评价司机</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+
+			};
+		}
+	}
+</script>
+
+<style lang="scss">
+
+</style>

+ 182 - 0
pages/mine/index.vue

@@ -0,0 +1,182 @@
+<!-- 我的 -->
+<template>
+	<view class="container">
+		<view class='container_content'>
+			<view class="head">
+				<view style='margin-bottom:14px;' class="row flex flex-end">
+					<u--image class='image' :showLoading="true" src="../../static/mine/saoma.png" width="20px"
+						height="20px"></u--image>
+					<u--image style='margin-right:0;' class='image' :showLoading="true" src="../../static/mine/shezhi.png" width="20px"
+						height="20px"></u--image>
+				</view>
+				<view class="flex">
+					<u--image :showLoading="true" src="https://cdn.uviewui.com/uview/album/1.jpg" width="56px"
+					height="56px"></u--image>
+					<view class='information' v-if='hasLogin'>
+						<view class='flex items-center'>
+							<view class='username'>李振华</view>
+							<view class='currectstatus'>已认证</view>
+						</view>
+						<view class='phone'>18513069273</view>
+					</view>
+					<view class='information' v-else @click="toLogin">立即登录</view>
+				</view>
+				<view class='authentication flex flex-space-between'>
+					<view>
+						<view style='font-size:14px;'>货主身份认证</view>
+						<view style='color:#DDA558;font-size:12px;'>您还没有完成货主认证哦~</view>
+					</view>
+					<view @click="goDetailPage('/pages/mine/cargoowner/cargoowner')" class='promptlyAuthentication'>立即认证</view>
+				</view>
+			</view>
+			<view class='flex operate flex-space-around'>
+				<view class='flex items-center'>
+					<u--image style='margin-right:8px;' :showLoading="true" src="../../static/mine/wodefabu.png" width="42px"
+						height="42px"></u--image>我发布的
+				</view>
+				<view class='flex items-center'>
+					<u--image style='margin-right:8px;' :showLoading="true" src="../../static/mine/pingjia.png" width="42px"
+						height="42px"></u--image>
+					司机评价
+				</view>
+			</view>
+			<view class="content1">
+
+				<view class="flex flex-space-between content1-item" @click="goDetailPage('/pages/mine/manageBankCards/index')">
+					<view class='flex items-center'><u--image style='margin-right:8px;' :showLoading="true" src="../../static/mine/wodegongsi.png" width="20px"
+						height="20px"></u--image>我的公司</view>
+					<view class='flex'> 证件过期 <u-icon name="arrow-right" color="#7E7E7E" size="10"></u-icon></view>
+				</view>
+				<view class="flex flex-space-between content1-item" @click="goDetailPage('/pages/mine/manageVehicles/index')">
+					<view class='flex items-center'><u--image style='margin-right:8px;' :showLoading="true" src="../../static/mine/dailihuozhu.png" width="20px"
+						height="20px"></u--image>代理货主</view>
+					<view> <u-icon name="arrow-right" color="#7E7E7E" size="10"></u-icon> </view>
+				</view>
+				<view class="flex flex-space-between content1-item" @click="$helper.contactCustomerService">
+					<view class='flex items-center'><u--image style='margin-right:8px;' :showLoading="true" src="../../static/mine/kefu.png" width="20px"
+						height="20px"></u--image>联系客服</view>
+					<view> <u-icon name="arrow-right" color="#7E7E7E" size="10"></u-icon> </view>
+				</view>
+				<view class="flex flex-space-between content1-item" @click="goDetailPage('/pages/mine/helpDescription')">
+					<view class='flex items-center'><u--image style='margin-right:8px;' :showLoading="true" src="../../static/mine/bangzhushuoming.png" width="20px"
+						height="20px"></u--image>帮助说明</view>
+					<view> <u-icon name="arrow-right" color="#7E7E7E" size="10"></u-icon> </view>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import {
+		mapState
+	} from 'vuex';
+	export default {
+		data() {
+			return {
+				userName:'',
+			};
+		},
+		onLoad() {
+			// debugger
+			this.userName = this.userInfo.userName
+		},
+		computed: {
+			...mapState(['hasLogin', 'userInfo']),
+			// 手机号中间4位加*
+			// starUserphone() {
+			// 	let reg = /^(\d{3})\d{4}(\d{4})$/;
+			// 	if (this.userphone) {
+			// 		return this.userphone.replace(reg, "$1****$2");
+			// 	}
+			// }
+		},
+		methods: {
+			goDetailPage(src) {
+				uni.$u.route(src);
+			},
+			toLogin() {
+				console.log("userInfo", this.userInfo)
+				if (!this.hasLogin || !this.userInfo || this.userName == "立即登录") {
+					uni.$u.route('/pages/public/login');
+				} else {}
+				// else if(!this.userInfo.nickname){
+				// 	this.inputShow = true
+				// 	this.inputStatus = 'inline'
+				// 	this.feild = "nickname"
+				// 	this.inputContent = ''
+				// }
+			},
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.container{
+		padding-top: 85px;
+		padding-top: 35px;
+		background-color: #F5F6FA;
+		position: relative;
+		width: 100vw;
+		overflow: hidden;
+		background: url('~@/static/mine/bg@3x.png');
+		background-size: 100% 100%;
+		margin: 0 auto;
+		height: calc(100vh - 0px);
+		.container_content{
+			padding:18px;
+		}
+	}
+	.image{
+		margin:0 7px;
+	}
+	.username{
+		font-size:21px;
+	}
+	.information{
+		margin:0 0 36px 17px;
+	}
+	.currectstatus{
+		font-size:10px;
+		color:#D6B798;background:#161111;
+		padding:1px 6px;
+		border-radius:10px;
+		margin:0 6px;
+	}
+	.phone{
+		color:#8F97AB;
+		font-size:13px;
+		margin-top:5px;
+	}
+	.operate{
+		font-size:16px;
+		font-weight: 600;
+		background:#fff;
+		border-radius:10px;
+		padding:10px 15px;
+		margin-bottom:15px;
+	}
+	.content1{
+		background:#fff;
+		padding:10px;
+		border-radius:10px;
+		.content1-item{
+			padding:10px;
+		}
+	}
+	.authentication{
+		border:1px solid #F3EACF;
+		margin:10px 0;
+		height:64px;
+		border-radius:10px;
+		padding:15px;
+		box-sizing: border-box;
+		background: linear-gradient(144deg, #FEFAEE 0%, #FEFDF8 100%);
+	}
+	.promptlyAuthentication{
+		font-size:13px;
+		padding:8px 16px;
+		border-radius:15px;
+		background: linear-gradient(327deg, #EDBB63 0%, #FFDEA5 100%);;
+	}
+</style>

+ 232 - 0
pages/mine/manageBankCards/addBankCard.vue

@@ -0,0 +1,232 @@
+<template>
+	<view class="content">
+		<view class="content3 flex s-row">
+			<view class="flex flex-space-between width100">
+				上传银行卡正面
+			</view>
+
+			<u-button type="primary" @click="uploadImg(3)">上传银行卡号页</u-button>
+			<view class="flex flex-space-between width100">
+				<view>银行卡卡号</view>
+				<view class="flex">
+					<u--input placeholder="输入银行卡号码" inputAlign='right' border="none" v-model="dataDetails.name">
+					</u--input>
+					<u--image src="../../static/images/xiangji-2.png" width="40px" height="40px" @click='photograph'>
+					</u--image>
+				</view>
+			</view>
+			<view class="flex flex-space-between width100">
+				<view>开户行</view>
+				<view class="flex">
+					<u--input placeholder="输入开户行" inputAlign='right' border="none" v-model="dataDetails.name">
+					</u--input>
+				</view>
+			</view>
+			<view class="flex flex-space-between width100">
+				<view>开户支行</view>
+				<view class="flex">
+					<u--input placeholder="选择开户支行" inputAlign='right' border="none" v-model="dataDetails.name">
+					</u--input>
+					<view>手动输入</view>
+				</view>
+			</view>
+			<view class="flex flex-space-between width100">
+				<view>收款人</view>
+				<view class="flex">
+					<u--input placeholder="输入收款人姓名" inputAlign='right' border="none" v-model="dataDetails.name">
+					</u--input>
+				</view>
+			</view>
+		</view>
+		<view class="" @click="submit">提交</view>
+		<u-action-sheet :actions="$helper.imgTypeList" :title="$helper.imgType" :show="isShowimgType"
+			@select="imgTypeSelect" :closeOnClickOverlay="true" :closeOnClickAction="true" @close="isShowimgType=false">
+		</u-action-sheet>
+	</view>
+</template>
+
+<script>
+	import upload from '@/components/upload.vue';
+	import uploadImage from '@/components/ossutil/uploadFile.js';
+	var _this;
+	export default {
+		components: {},
+		data() {
+			return {
+				uploadType: '',
+				isShowimgType: false,
+				dataDetails: {
+					name: '阿萨啊',
+					carNumberList: [{
+						kahao: '',
+						addressUrl: ''
+					}],
+					bankList: [{
+						yhk: '',
+						kh: '',
+						khh: '',
+						khzh: '',
+						skr: ''
+					}],
+				},
+				imagesrc: ''
+			};
+		},
+		onLoad() {
+			_this = this;
+		},
+		methods: {
+			//设置图片
+			setImage(e) {
+				debugger
+				console.log(e);
+				//显示在页面
+				//this.imagesrc = e.path;
+				if (e.dotype == 'idphoto') {
+					_this.zjzClipper(e.path);
+				} else if (e.dotype == 'watermark') {
+					_this.watermark(e.path);
+				} else {
+					_this.savePhoto(e.path);
+				}
+			},
+			//保存图片到相册,方便核查
+			savePhoto(path) {
+				debugger
+				this.imagesrc = path;
+				uploadImage(path, 'appData/',
+					result => {
+						// 上传成功
+						console.log('图片地址', result)
+					}
+				)
+				//保存到相册
+				// uni.saveImageToPhotosAlbum({
+				// 	filePath: path,
+				// 	success: () => {
+				// 		uni.showToast({
+				// 			title: '已保存至相册',
+				// 			duration: 2000
+				// 		});
+				// 	}
+				// });
+			},
+			uploadImg(type) {
+
+				this.uploadType = type
+				this.isShowimgType = true
+			},
+			photograph() {
+				console.log('拍照')
+				let that = this;
+				uni.chooseImage({
+					count: 1,
+					success: function(res) {
+						console.log(JSON.stringify(res.tempFilePaths));
+						uploadImage(res.tempFilePaths[0], 'appData/',
+							result => {
+								// 上传成功
+								console.log('图片地址', result)
+							}
+						)
+					}
+				});
+
+			},
+			imgTypeSelect(val) {
+				console.log(val)
+				console.log(this.uploadType)
+				if (val.name == '相册') {
+					uni.chooseImage({
+						count: 1,
+						sourceType: this.$helper.chooseImage.sourceType,
+						success: function(res) {
+							console.log(JSON.stringify(res.tempFilePaths));
+							uploadImage(res.tempFilePaths[0], 'appData/',
+								result => {
+									// 上传成功
+									console.log('图片地址', result)
+									switch (this.uploadType) {
+										case 0:
+											console.log('人车合影')
+											break
+										case 1:
+											console.log('身份正面')
+											break
+										case 2:
+											console.log('身份反面')
+											break
+										case 3:
+											console.log('银行卡')
+											break
+										case 4:
+									}
+								}
+							)
+						}
+					});
+
+				} else {
+					switch (this.uploadType) {
+						case 0:
+							console.log('人车合影')
+							break
+						case 1:
+							uni.$u.route('/pages/mine/camera/idcard/idcard?dotype=face');
+							console.log('身份正面')
+							break
+						case 2:
+							console.log('身份反面')
+							break
+						case 3:
+							console.log('银行卡')
+							break
+						case 4:
+					}
+				}
+
+			},
+			//身份证正面
+			getImgUrl1(src) {
+				// console.log(src)
+				// console.log('------------res-----------')
+				// let that = this;
+				// that.id[0] = src
+				// that.id1 = src
+				// that.certificates = false
+				// that.personImgs.personImg = that.id[0]
+				// that.$api.doRequest('get', '/driverViewInfo/personShibie', that
+				// 	.personImgs).then(res => {
+				// 	if (res.data.data.recPerson != null) {
+				// 		if (res.data.data.recPerson != "") {
+				// 			that.$set(that.DriverViewInfo, 'driverName', res
+				// 				.data.data.recPerson)
+				// 		}
+				// 	}
+				// 	if (res.data.data.recPersonNo != null) {
+				// 		if (res.data.data.recPersonNo != "") {
+				// 			that.$set(that.DriverViewInfo, 'numberCard', res
+				// 				.data.data.recPersonNo)
+				// 		}
+				// 	}
+				// }).catch(res => {
+				// 	uni.showToast({
+				// 		title: res.data.message,
+				// 		icon: 'none',
+				// 		duration: 2000
+				// 	})
+				// })
+			},
+			submit(){
+				console.log(' tijia')
+			},
+		},
+	};
+</script>
+
+<style scoped lang="scss">
+	.row4-img {
+		width: 32rpx;
+		height: 32rpx;
+	}
+</style>

+ 20 - 0
pages/mine/manageBankCards/editBankCard.vue

@@ -0,0 +1,20 @@
+<!-- 添加银行卡 -->
+<template>
+	<view>
+		修改银行卡
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				
+			};
+		}
+	}
+</script>
+
+<style lang="scss">
+
+</style>

+ 66 - 0
pages/mine/manageBankCards/index.vue

@@ -0,0 +1,66 @@
+<template>
+	<view class="content">
+		<view class="" v-for="(item,index) in 4" :key='index'>
+			<view class="flex">
+				<view class="">中国银行</view>
+				<view>鲅鱼圈支行</view>
+			</view>
+			<view class="flex">收款人:张三</view>
+			<view class="flex flex-end">112 312 312 3123 1231 3123</view>
+			<view>
+				<view>
+					<radio :value="value" />
+					<view>设为默认收款账户</view>
+				</view>
+				<view>
+					<view @click="edit">修改</view>
+					<view>删除</view>
+				</view>
+			</view>
+		</view>
+		<view @click="addBankCard">添加银行卡</view>
+		<u-toast ref="uToast"></u-toast>
+	</view>
+</template>
+
+<script>
+	import {
+		mapState
+	} from 'vuex';
+	export default {
+		data() {
+			return {
+				value: '111'
+			};
+		},
+		computed: {
+			...mapState(['hasLogin', 'userInfo']),
+		},
+		onLoad() {
+			if (!this.hasLogin) {
+				uni.$u.route('/pages/public/login');
+			}
+		},
+		methods: {
+			addBankCard() {
+				uni.$u.route('/pages/mine/manageBankCards/addBankCard');
+			},
+			edit() {
+				uni.$u.route('/pages/mine/manageBankCards/editBankCard');
+				let params = {
+					type: 'success',
+					message: "修改成功",
+					iconUrl: 'https://cdn.uviewui.com/uview/demo/toast/success.png'
+				}
+				this.$refs.uToast.show({
+					...params
+				})
+			},
+		},
+
+	}
+</script>
+
+<style lang="scss">
+
+</style>

+ 57 - 0
pages/mine/manageVehicles/addVehicle.vue

@@ -0,0 +1,57 @@
+<!-- 管理车辆 -->
+<template>
+	<view class="content">
+		<view class="flex flex-space-between">
+			<view>车牌号</view>
+			<u--input placeholder="输入车牌号" inputAlign='right' border="none" v-model="carNumber"></u--input>
+		</view>
+		<view>上传人车合影(车头车牌号可见)</view>
+		<u-button type="primary" @click="unloadGroupPhoto()">上传人车合影</u-button>
+		<u-button type="primary" @click="submit">提交</u-button>
+		<u-toast ref="uToast"></u-toast>
+	</view>
+</template>
+
+<script>
+	import uploadImage from '@/components/ossutil/uploadFile.js';
+	var _this;
+	export default {
+		data() {
+			return {
+				carNumber: '',
+			};
+		},
+		onLoad(options) {
+			_this = this;
+			console.log(options)
+		},
+		methods: {
+			unloadGroupPhoto() {
+				uni.chooseImage({
+					count: 1,
+					success: function(res) {
+						console.log(JSON.stringify(res.tempFilePaths));
+						uploadImage(res.tempFilePaths[0], 'appData/',
+							result => {
+								// 上传成功
+								console.log('图片地址', result)
+							}
+						)
+					}
+				});
+			},
+			submit(){
+				let params = {
+						type: 'success',
+						message: "提交成功",
+						iconUrl: 'https://cdn.uviewui.com/uview/demo/toast/success.png'
+					}
+				this.$refs.uToast.show({...params})
+			},
+		},
+	}
+</script>
+
+<style lang="scss" scoped>
+
+</style>

+ 57 - 0
pages/mine/manageVehicles/editVehicle.vue

@@ -0,0 +1,57 @@
+<!-- 管理车辆 -->
+<template>
+	<view class="content">
+		<view class="flex flex-space-between">
+			<view>车牌号</view>
+			<u--input placeholder="输入车牌号" inputAlign='right' border="none" v-model="carNumber"></u--input>
+		</view>
+		<view>上传人车合影(车头车牌号可见)</view>
+		<u-button type="primary" @click="unloadGroupPhoto()">上传人车合影</u-button>
+		<u-button type="primary" @click="submit">提交</u-button>
+		<u-toast ref="uToast"></u-toast>
+	</view>
+</template>
+
+<script>
+	import uploadImage from '@/components/ossutil/uploadFile.js';
+	var _this;
+	export default {
+		data() {
+			return {
+				carNumber: '',
+			};
+		},
+		onLoad(options) {
+			_this = this;
+			console.log(options)
+		},
+		methods: {
+			unloadGroupPhoto() {
+				uni.chooseImage({
+					count: 1,
+					success: function(res) {
+						console.log(JSON.stringify(res.tempFilePaths));
+						uploadImage(res.tempFilePaths[0], 'appData/',
+							result => {
+								// 上传成功
+								console.log('图片地址', result)
+							}
+						)
+					}
+				});
+			},
+			submit(){
+				let params = {
+						type: 'success',
+						message: "修改成功",
+						iconUrl: 'https://cdn.uviewui.com/uview/demo/toast/success.png'
+					}
+				this.$refs.uToast.show({...params})
+			},
+		},
+	}
+</script>
+
+<style lang="scss" scoped>
+
+</style>

+ 95 - 0
pages/mine/manageVehicles/index.vue

@@ -0,0 +1,95 @@
+<!-- 管理车辆 -->
+<template>
+	<view class="content">
+		<view class="content1">
+			<view class="content1-item inline-block ">
+				<u--image width='100%' height='100%' src="https://cdn.uviewui.com/uview/album/1.jpg" mode="widthFix">
+				</u--image>
+				<view class="flex flex-space-between">
+					<view>辽H11111</view>
+					<view>审核中</view>
+				</view>
+				<view class="flex">
+					<view>删除</view>
+					<view>修改</view>
+				</view>
+			</view>
+			<view class="content1-item inline-block ">
+				<u--image width='100%' height='100%' src="https://cdn.uviewui.com/uview/album/1.jpg" mode="widthFix">
+				</u--image>
+				<view class="flex flex-space-between">
+					<view>辽H11111</view>
+					<view>审核中</view>
+				</view>
+				<view class="flex">
+					<view>删除</view>
+					<view>修改</view>
+				</view>
+			</view>
+			<view class="content1-item inline-block ">
+				<u--image width='100%' height='100%' src="https://cdn.uviewui.com/uview/album/1.jpg" mode="widthFix">
+				</u--image>
+				<view class="flex flex-space-between">
+					<view>辽H11111</view>
+					<view>审核中</view>
+				</view>
+				<view class="flex">
+					<view>删除</view>
+					<view>修改</view>
+				</view>
+			</view>
+			<view class="content1-item inline-block ">
+				<u--image width='100%' height='100%' src="https://cdn.uviewui.com/uview/album/1.jpg" mode="widthFix">
+				</u--image>
+				<view class="flex flex-space-between">
+					<view>辽H11111</view>
+					<view>审核中</view>
+				</view>
+				<view class="flex">
+					<view @click="del">删除</view>
+					<view @click="edit">修改</view>
+				</view>
+			</view>
+		</view>
+		<u-button type="primary" @click="addCar">添加车辆</u-button>
+	</view>
+</template>
+
+<script>
+	import {
+		mapState
+	} from 'vuex';
+	var _this;
+	export default {
+		data() {
+			return {
+
+			};
+		},
+		onLoad(options) {
+			_this = this;
+			console.log(options)
+			if (!this.hasLogin) {
+				uni.$u.route('/pages/public/login');
+			}
+		},
+		methods: {
+			addCar() {
+				uni.$u.route('/pages/mine/manageVehicles/addVehicle');
+			},
+			edit() {
+				uni.$u.route('/pages/mine/manageVehicles/editVehicle');
+			}
+		},
+	}
+</script>
+
+<style lang="scss" scoped>
+	.content1 {
+		width: 100%;
+	}
+
+	.content1-item {
+		width: calc(50% - 0rpx);
+	}
+</style>

+ 258 - 0
pages/mine/set.vue

@@ -0,0 +1,258 @@
+<template>
+	<view class="content">
+		<view class="cu-list menu text-left solid-top indexlow">
+			<view class='flex flex-space-between' @click="switchPicture">
+				<view>
+					<text>头像</text>
+				</view>
+				<view style='align-items: center;' class="flex">
+					<view class="pictures">
+						<image :src="headUrl" class="picture"></image>
+					</view>
+					<image src="../../static/images/myimg/gengduo1@3x.png" class="arrow"></image>
+				</view>
+			</view>
+			<view class='flex flex-space-between' @click="nickname(username)">
+				<view>
+					<text>姓名</text>
+				</view>
+				<view style='align-items: center;' class="flex">
+					<view class="username">
+						{{username}}
+					</view>
+					<image src="../../static/images/myimg/gengduo1@3x.png" class="arrow"></image>
+				</view>
+			</view>
+			<view class='flex flex-space-between' @click='UpdataPassword'>
+				<view>
+					<text>修改账号</text>
+				</view>
+				<image src="../../static/images/myimg/gengduo1@3x.png" class="arrow"></image>
+			</view>
+			<view class='flex flex-space-between' @click='UpdataPassword'>
+				<view>
+					<text>修改密码</text>
+				</view>
+				<image src="../../static/images/myimg/gengduo1@3x.png" class="arrow"></image>
+			</view>
+			<view class='flex flex-space-between' @click='fankui'>
+				<view>
+					<text>意见反馈</text>
+				</view>
+				<image src="../../static/images/myimg/gengduo1@3x.png" class="arrow"></image>
+			</view>
+			<view class='flex flex-space-between' @click='clearStorage'>
+				<view>
+					<text>清除缓存</text>
+				</view>
+				<image src="../../static/images/myimg/gengduo1@3x.png" class="arrow"></image>
+			</view>
+		</view>
+		<view class='exitloginwrap'>
+			<button @click='logout()' class='exitlogin'>退出登录</button>
+		</view>
+		<!-- <u-modal v-model="isShowAlert" :title-style="{fontSize: '18px',fontWeight:'500'}"
+			:content-style="{fontSize: '14px',fontWeight:'400'}" confirm-color='#22C572' confirm-text='确定' title='温馨提示'
+			showCancelButton='false' :content="content" @confirm="goOpenService" @cancel="cancelClick"></u-modal> -->
+	</view>
+</template>
+
+<script>
+	import {
+		mapState
+	} from 'vuex';
+	export default {
+		data() {
+			return {
+				isShowAlert: false,
+				content: '您确定要退出吗?',
+				headUrl: "../../static/images/myimg/YongHu@3x.png",
+				username: "",
+				gridList: [{
+					num: 0,
+					name: '退出登录',
+					// icon:'cuIcon-exit',
+					src: '../../static/images/sign/return@3x.png',
+					tips: 0,
+					url: '',
+					show: true
+				}, ],
+			}
+		},
+		computed: {
+			// ...mapState(['hasLogin', 'userInfo'])
+		},
+		onShow() {
+			this.getList()
+		},
+		onLoad() {},
+		methods: {
+			UpdataPassword() {
+				uni.navigateTo({
+					url: `/pages/public/reset?phone=${this.userInfo.phone}`
+				})
+			},
+			clearStorage() {
+				let that = this
+				uni.clearStorage({
+					success: function(res) {
+						console.log('success');
+						that.goOpenService()
+					}
+				})
+			},
+			cancelClick() {
+				this.isShowAlert = false
+			},
+			goOpenService() {
+				uni.hideTabBarRedDot({
+					index: 3
+				})
+				uni.clearStorageSync();
+				var that = this
+				this.$api.doRequest('post', '/auth/api/logout').then(res => {
+					if (res.data.data) {
+
+					}
+				})
+				this.$store.commit('logout')
+				this.$api.logout()
+				uni.navigateTo({
+					url: `/pages/public/login`
+				})
+			},
+			getList() {
+				this.userInfo = uni.getStorageSync('userInfo')
+				this.headUrl = this.userInfo.avatarUrl
+				if (this.headUrl == null || this.headUrl == "") {
+					this.headUrl = "../../static/images/myimg/YongHu@3x.png"
+				}
+				this.username = this.userInfo.userName
+			},
+			switchPicture() {
+				uni.navigateTo({
+					url: `/pages/user/set_picture`
+				})
+			},
+			nickname(username) {
+				uni.navigateTo({
+					url: `/pages/user/set_nickname?nickname=${username}`
+				})
+			},
+			exitlogin() {
+
+			},
+			fankui() {
+				uni.navigateTo({
+					url: `/pages/user/fankui`
+				})
+			},
+			logout() {
+				// const that = this
+				this.isShowAlert = true
+				// uni.showModal({
+				// 	title: '询问',
+				// 	content: '您确定要退出吗?',
+				// 	cancelText: '取消',
+				// 	confirmText: '确定',
+				// 	success: (e) => {
+				// 		if (e.confirm) {
+				// 			uni.hideTabBarRedDot({
+				// 				index: 3
+				// 			})
+				// 			uni.clearStorageSync();
+				// 			that.$store.commit('logout')
+				// 			that.$api.logout()
+				// 			uni.navigateTo({
+				// 				url: `/pages/public/login`
+				// 			})
+				// 		}
+				// 	}
+				// })
+			},
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	page {
+		background-color: #F5F6FA;
+	}
+
+	.container {
+		padding: 10px 0 0px;
+	}
+
+	.headPortrait {
+		width: 100%;
+		height: 52px;
+		margin-top: 15px;
+		background-color: #FFFFFF;
+		border-radius: 6px;
+		// justify-content: flex-end;
+	}
+
+	.title {
+		font-size: 16px;
+		line-height: 50px;
+		font-weight: 600;
+		margin-left: 10px;
+	}
+
+	.pictures {
+		justify-content: flex-end;
+		width: 35px;
+		height: 35px;
+		background-color: #E0FAF6;
+		border-radius: 18px;
+	}
+
+	.picture {
+		width: 35px;
+		height: 35px;
+	}
+
+	.arrow {
+		margin-left: 15px;
+		width: 8px;
+		height: 12px;
+		// justify-content: flex-end
+
+	}
+
+	.username {
+		line-height: 50px;
+		color: #6D6D72;
+	}
+
+	.sign {
+		width: 18px;
+		height: 18px;
+		top: 4px;
+		margin-right: 6px;
+	}
+
+	.cu-list>.cu-item:after {
+		border: none;
+	}
+
+	.exitloginwrap {
+		position: fixed;
+		bottom: 0;
+		left: 0;
+		width: 100%;
+		padding-bottom: 20px;
+	}
+
+	.exitlogin {
+		width: 90%;
+		background: #fff;
+		border-radius: 30px;
+		color: #FB1E1E;
+		font-size: 17px;
+	}
+
+	.exitlogin:after {
+		border: none;
+	}
+</style>

+ 91 - 0
pages/news/index.vue

@@ -0,0 +1,91 @@
+<template>
+	 <mescroll-body ref="mescrollRef" @init="mescrollInit" @down="downCallback" @up="upCallback">
+		<view class="content">
+			<view class="info-item" v-for="good in goods" :key="good.id">
+				<view class="flex flex-space-between">
+					<view class="left">
+						<view>系统消息</view>
+						 <u-badge :isDot="true" bgColor='red' :absolute='true' :offset='badgeOffset'></u-badge>
+					</view>
+					<view class="">
+						今天 21:51
+					</view>
+				</view>
+				<view class="flex flex-space-between">
+					您的驾驶证即将到期,请尽快到“我的-身份认证”中更新,逾期将影响运费支付。
+				</view>
+				
+			</view>
+		</view>
+	</mescroll-body>
+</template>
+
+<script>
+	import MescrollMixin from "@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js";
+	import {apiGoods} from "@/api/mock.js"
+	
+	export default {
+		mixins: [MescrollMixin], // 使用mixin
+		data() {
+			return {
+				value:100,
+				goods: [] ,// 数据列表
+				badgeOffset:[0,-5]
+			}
+		},
+		methods: {
+			/*上拉加载的回调: 其中page.num:当前页 从1开始, page.size:每页数据条数,默认10 */
+			upCallback(page) {
+				// 此处可以继续请求其他接口
+				// if(page.num == 1){
+				// 	// 请求其他接口...
+				// }
+				
+				// 如果希望先请求其他接口,再触发upCallback,可参考以下写法
+				// if(!this.isInitxx){
+				// 	apiGetxx().then(res=>{
+				// 		this.isInitxx = true
+				// 		this.mescroll.resetUpScroll() // 重新触发upCallback
+				// 	}).catch(()=>{
+				// 		this.mescroll.endErr()
+				// 	})
+				// 	return // 此处return,先获取xx
+				// }
+				
+				//联网加载数据
+				apiGoods(page.num, page.size).then(res=>{
+					//联网成功的回调,隐藏下拉刷新和上拉加载的状态;
+					//mescroll会根据传的参数,自动判断列表如果无任何数据,则提示空;列表无下一页数据,则提示无更多数据;
+
+					//方法一(推荐): 后台接口有返回列表的总页数 totalPage
+					//this.mescroll.endByPage(res.list.length, totalPage); //必传参数(当前页的数据个数, 总页数)
+
+					//方法二(推荐): 后台接口有返回列表的总数据量 totalSize
+					//this.mescroll.endBySize(res.list.length, totalSize); //必传参数(当前页的数据个数, 总数据量)
+
+					//方法三(推荐): 您有其他方式知道是否有下一页 hasNext
+					//this.mescroll.endSuccess(res.list.length, hasNext); //必传参数(当前页的数据个数, 是否有下一页true/false)
+
+					//方法四 (不推荐),会存在一个小问题:比如列表共有20条数据,每页加载10条,共2页.如果只根据当前页的数据个数判断,则需翻到第三页才会知道无更多数据
+					this.mescroll.endSuccess(res.list.length);
+
+					//设置列表数据
+					if(page.num == 1) this.goods = []; //如果是第一页需手动制空列表
+					this.goods=this.goods.concat(res.list); //追加新数据
+				}).catch(()=>{
+					//联网失败, 结束加载
+					this.mescroll.endErr();
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="scss">
+.info-item{
+	.left{
+		position: relative;
+	}
+}
+</style>
+

+ 164 - 0
pages/order/confirmLoading.vue

@@ -0,0 +1,164 @@
+<!-- 确认装车 -->
+<template>
+	<view class="content">
+		<view class="level1-title">
+			任务信息
+		</view>
+		<view class="content1">
+			<view class='row-between'>
+				<view class="">货主</view>
+				<view class="flex">
+					<view>张三</view>
+					<view>del</view>
+				</view>
+				
+			</view>
+			<view class='row-between'>
+				<view class="">货主单位</view>
+				<view>黑龙江中天昊元贸易有限公司</view>
+			</view>
+			<view class='row-between'>
+				<view class="">发货地</view>
+				<view>鲅鱼圈</view>
+			</view>
+			<view class='row-between'>
+				<view class="">卸货地</view>
+				<view>黑龙江省齐齐哈尔市梅里斯达斡尔族区杜尔门沁达斡尔乡53农场</view>
+			</view>
+			<view class='row-between'>
+				<view class="">货名</view>
+				<view>玉米</view>
+			</view>
+			<view class='row-between'>
+				<view class="">运费</view>
+				<view>100元/吨</view>
+			</view>
+		</view>
+		<view class="level1-title">
+			装车信息
+		</view>
+		<view class="content2">
+			<view class='row-between'>
+				<view class="">车牌号</view>
+				<view>辽H12345</view>
+			</view>
+			<view class='row-between'>
+				<view class="">装车时间</view>
+				<view>2022-02-10 16:13:15</view>
+			</view>
+			<view class='row-between'>
+				<view class="">装车净重</view>
+			</view>
+			<view class='s-flex'>
+				<view class="">上传装车照片</view>
+				<upload class="upload" ref="upload" :action="action" :max-size="maxSize" :max-count="3"
+					:size-type="['compressed']" @on-success="getImgUrl" @on-error="onError" @on-remove="onRemove"
+					@on-uploaded="isAdd = true" :before-upload="filterFileType" @on-progress="onProgress"></upload>
+			</view>
+			<view class='s-flex'>
+				<view class="">上传装车磅单</view>
+				<upload class="upload" ref="upload" :action="action" :max-size="maxSize" :max-count="1"
+					:size-type="['compressed']" @on-success="getImgUrl" @on-error="onError" @on-remove="onRemove"
+					@on-uploaded="isAdd = true" :before-upload="filterFileType" @on-progress="onProgress"></upload>
+			</view>
+		</view>
+		<view class="content3 flex">
+			<u-button text="暂存" type="primary" @click="submit(0)"></u-button>
+			<u-button text="提交" type="primary" @click="submit(1)"></u-button>
+		</view>
+		<u-toast ref="uToast"></u-toast>
+		<u-modal :show="isShowAlert" :title="alertTitle" :content='alertContent' :closeOnClickOverlay='true' :showCancelButton='true' confirmColor='#22C572'  @confirm="confirmClick" @close="cancelClick" @cancel="cancelClick"></u-modal>
+	</view>
+</template>
+
+<script>
+	import upload from '@/components/upload.vue';
+	export default {
+		components: {
+			upload
+		},
+		data() {
+			return {
+				detailData: {
+					addressUrl: ''
+				},
+				action: this.$helper.ossUploadUrl,
+				maxSize: 50 * 1024 * 1024, //限制文件大小 50M
+				isAdd: true,
+				isShowAlert: false,
+				alertContent: '',
+				alertTitle: '',
+			}
+		},
+		onLoad(options) {
+			console.log(options)
+		},
+		methods: {
+			alertBtn() {
+				// uni.navigateTo({
+				// 	url: '/pages/public/login'
+				// })
+			},
+			cancelClick() {
+				this.isShowAlert = false
+			},
+			getImgUrl(res) {
+				this.detailData.addressUrl = res
+				console.log(res)
+				console.log('------------res-----------')
+			},
+			onError(error) {
+				alert(error)
+				console.log('------------error-----------')
+				console.log(error)
+			},
+			onRemove(index) {},
+			filterFileType(index, lists) {
+				if (lists[index].fileType != 'jpg' && lists[index].fileType != 'png' && lists[index].fileType != 'gif') {
+					lists.splice(index, 1);
+					// 当前文件不支持
+					uni.showModal({
+						title: '暂不支持当前图片类型',
+						showCancel: false
+					});
+				} else {
+					this.isAdd = false;
+				}
+			},
+			onProgress(e) {
+				console.log(e)
+			},
+			submit(type) {
+				console.log(type)
+				let params = {
+						type: 'success',
+						title: '成功主题(带图标)',
+						message: "庄生晓梦迷蝴蝶",
+						iconUrl: 'https://cdn.uviewui.com/uview/demo/toast/success.png'
+					}
+					if(type==0){
+						
+					}else{
+						this.alertContent='确定提交装车信息?'
+						this.alertTitle='提示'
+						this.isShowAlert = true
+					}
+				// this.$refs.uToast.show({
+				// 	...params,
+				// 	complete() {
+				// 		params.url && uni.navigateTo({
+				// 			url: params.url
+				// 		})
+				// 	}
+				// })
+			},
+			confirmClick(){
+				console.log('提交')
+			}
+		},
+	}
+</script>
+
+<style>
+
+</style>

+ 164 - 0
pages/order/confirmUnloading.vue

@@ -0,0 +1,164 @@
+<!-- 确认装车 -->
+<template>
+	<view class="content">
+		<view class="level1-title">
+			任务信息
+		</view>
+		<view class="content1">
+			<view class='row-between'>
+				<view class="">订单编号</view>
+				<view>CY20220210666666</view>
+			</view>
+			<view class='row-between'>
+				<view class="">货主</view>
+				<view>张三</view>
+			</view>
+			<view class='row-between'>
+				<view class="">货主单位</view>
+				<view>黑龙江中天昊元贸易有限公司</view>
+			</view>
+			<view class='row-between'>
+				<view class="">发货地</view>
+				<view>鲅鱼圈</view>
+			</view>
+			<view class='row-between'>
+				<view class="">卸货地</view>
+				<view>黑龙江省齐齐哈尔市梅里斯达斡尔族区杜尔门沁达斡尔乡53农场</view>
+			</view>
+			<view class='row-between'>
+				<view class="">货名</view>
+				<view>玉米</view>
+			</view>
+			<view class='row-between'>
+				<view class="">运费</view>
+				<view>100元/吨</view>
+			</view>
+		</view>
+		<view class="level1-title">
+			卸车信息
+		</view>
+		<view class="content2">
+			<view class='row-between'>
+				<view class="">车牌号</view>
+				<view>辽H12345</view>
+			</view>
+			<view class='row-between'>
+				<view class="">卸车时间</view>
+				<view>2022-02-10 16:13:15</view>
+			</view>
+			<view class='row-between'>
+				<view class="">卸车净重</view>
+			</view>
+			<view class='s-flex'>
+				<view class="">上传卸车照片</view>
+				<upload class="upload" ref="upload" :action="action" :max-size="maxSize" :max-count="3"
+					:size-type="['compressed']" @on-success="getImgUrl" @on-error="onError" @on-remove="onRemove"
+					@on-uploaded="isAdd = true" :before-upload="filterFileType" @on-progress="onProgress"></upload>
+			</view>
+			<view class='s-flex'>
+				<view class="">上传卸车磅单</view>
+				<upload class="upload" ref="upload" :action="action" :max-size="maxSize" :max-count="1"
+					:size-type="['compressed']" @on-success="getImgUrl" @on-error="onError" @on-remove="onRemove"
+					@on-uploaded="isAdd = true" :before-upload="filterFileType" @on-progress="onProgress"></upload>
+			</view>
+		</view>
+		<view class="content3 flex">
+			<u-button text="暂存" type="primary" @click="submit(0)"></u-button>
+			<u-button text="提交" type="primary" @click="submit(1)"></u-button>
+		</view>
+		<u-toast ref="uToast"></u-toast>
+		<u-modal :show="isShowAlert" :title="alertTitle" :content='alertContent' :closeOnClickOverlay='true' :showCancelButton='true' confirmColor='#22C572'  @confirm="confirmClick" @close="cancelClick" @cancel="cancelClick"></u-modal>
+	</view>
+</template>
+
+<script>
+	import upload from '@/components/upload.vue';
+	export default {
+		components: {
+			upload
+		},
+		data() {
+			return {
+				detailData: {
+					addressUrl: ''
+				},
+				action: this.$helper.ossUploadUrl,
+				maxSize: 50 * 1024 * 1024, //限制文件大小 50M
+				isAdd: true,
+				isShowAlert: false,
+				alertContent: '',
+				alertTitle: '',
+			}
+		},
+		onLoad(options) {
+			console.log(options)
+		},
+		methods: {
+			alertBtn() {
+				// uni.navigateTo({
+				// 	url: '/pages/public/login'
+				// })
+			},
+			cancelClick() {
+				this.isShowAlert = false
+			},
+			getImgUrl(res) {
+				this.detailData.addressUrl = res
+				console.log(res)
+				console.log('------------res-----------')
+			},
+			onError(error) {
+				alert(error)
+				console.log('------------error-----------')
+				console.log(error)
+			},
+			onRemove(index) {},
+			filterFileType(index, lists) {
+				if (lists[index].fileType != 'jpg' && lists[index].fileType != 'png' && lists[index].fileType != 'gif') {
+					lists.splice(index, 1);
+					// 当前文件不支持
+					uni.showModal({
+						title: '暂不支持当前图片类型',
+						showCancel: false
+					});
+				} else {
+					this.isAdd = false;
+				}
+			},
+			onProgress(e) {
+				console.log(e)
+			},
+			submit(type) {
+				console.log(type)
+				let params = {
+						type: 'success',
+						title: '成功主题(带图标)',
+						message: "庄生晓梦迷蝴蝶",
+						iconUrl: 'https://cdn.uviewui.com/uview/demo/toast/success.png'
+					}
+					if(type==0){
+						
+					}else{
+						this.alertContent='确定提交装车信息?'
+						this.alertTitle='提示'
+						this.isShowAlert = true
+					}
+				// this.$refs.uToast.show({
+				// 	...params,
+				// 	complete() {
+				// 		params.url && uni.navigateTo({
+				// 			url: params.url
+				// 		})
+				// 	}
+				// })
+			},
+			confirmClick(){
+				console.log('提交')
+			}
+		},
+	}
+</script>
+
+<style>
+
+</style>

+ 72 - 0
pages/order/index.vue

@@ -0,0 +1,72 @@
+<!-- 货源 -->
+<template>
+	<view class="content">
+		<view class="head flex">
+			<u-search placeholder="日照香炉生紫烟" v-model="keyword"></u-search>
+		</view>
+		<me-tabs v-model="tabIndex" :tabs="tabs" class="m-topr20"></me-tabs>
+		<swiper :style="{height: height}" :current="tabIndex" @change="swiperChange">
+			<swiper-item v-for="(tab,i) in tabs" :key="i">
+				<mescroll-item ref="mescrollItem" :i="i" :index="tabIndex" :tabs="tabs" :height="height">
+				</mescroll-item>
+			</swiper-item>
+		</swiper>
+	</view>
+</template>
+
+<script>
+	import MescrollItem from "./mescroll-swiper-item.vue";
+	export default {
+		components: {
+			MescrollItem
+		},
+		data() {
+			return {
+				keyword:'',
+				src: 'https://cdn.uviewui.com/uview/album/1.jpg',
+				height: "", // 需要固定swiper的高度
+				tabs: [{
+					name: '全部'
+				}, {
+					name: '未发运'
+				}, {
+					name: '运输中'
+				}, {
+					name: '代收货'
+				},
+				{
+					name: '评价'
+				},
+				{
+					name: '待结算'
+				},
+				{
+					name: '已完结'
+				},
+				
+				
+				],
+				tabIndex: 0 // 当前tab的下标
+
+			}
+		},
+		onLoad() {
+			let _isHave = this.$utils.getRoles('aaa')
+			console.log(_isHave)
+			// 需要固定swiper的高度 (需减去悬浮tabs的高度64rpx)
+			this.height = uni.getSystemInfoSync().windowHeight - uni.upx2px(64) + 'px'
+		},
+		methods: {
+			changeCity(type) {
+				console.log(type)
+			},
+			swiperChange(e) {
+				this.tabIndex = e.detail.current
+			}
+		}
+	}
+</script>
+
+<style scoped lang="scss">
+
+</style>

+ 139 - 0
pages/order/mescroll-swiper-item.vue

@@ -0,0 +1,139 @@
+<template>
+	<mescroll-uni :ref="'mescrollRef'+i" @init="mescrollInit" :height="height" :down="downOption" @down="downCallback"
+		:up="upOption" @up="upCallback" @emptyclick="emptyClick">
+		<view :id="'good'+good.id" class="good-list paddingr20" v-for="good in goods" :key="good.id" @click="toDetail(good.id)">
+			<view class="flex flex-space-between">
+				<view>CY20220210666666  玉米</view>
+				<view>待签约</view>
+			</view>
+			<view class="flex flex-space-between row">
+				<view class="left flex">
+					<view>辽</view>
+					<view>营口 鲅鱼圈</view>
+					<view>--------></view>
+					<view class="">
+						京
+					</view>
+					<view>背景 通州</view>
+				</view>
+			</view>
+			<view class="flex flex-space-between">
+				<view class="left flex">
+					<view>货主</view>
+					<view>中天贸易有限公司</view>
+					<view>小王</view>
+				</view>
+				<view class="right">
+					提醒货主确认卸车
+				</view>
+			</view>
+			<view class="flex flex-space-between row">
+				<view class="left flex">
+					运距~35km
+				</view>
+				<view class="right">
+					1000元/车
+				</view>
+			</view>
+		
+			<view class="flex flex-space-between">
+				<view class="left flex tiem">
+					2022-02-10 10:08
+				</view>
+				<view class="right flex">
+					<view @click.stop="grabOrders(good.id)">终止</view>
+					<view @click.stop="grabOrders(good.id)">签约</view>
+				</view>
+			</view>
+		</view>
+	</mescroll-uni>
+</template>
+
+<script>
+	import MescrollMixin from "@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js";
+	import MescrollMoreItemMixin from "@/uni_modules/mescroll-uni/components/mescroll-uni/mixins/mescroll-more-item.js";
+	import {
+		apiGoods
+	} from "@/api/mock.js"
+
+	export default {
+		mixins: [MescrollMixin, MescrollMoreItemMixin], // 注意此处还需使用MescrollMoreItemMixin (必须写在MescrollMixin后面)
+		data() {
+			return {
+				downOption: {
+					auto: false // 不自动加载 (mixin已处理第一个tab触发downCallback)
+				},
+				upOption: {
+					auto: false, // 不自动加载
+					// page: {
+					// 	num: 0, // 当前页码,默认0,回调之前会加1,即callback(page)会从1开始
+					// 	size: 10 // 每页数据的数量
+					// },
+					noMoreSize: 4, //如果列表已无数据,可设置列表的总数量要大于半页才显示无更多数据;避免列表数据过少(比如只有一条数据),显示无更多数据会不好看; 默认5
+					empty: {
+						tip: '~ 空空如也 ~', // 提示
+						btnText: '去看看'
+					}
+				},
+				goods: [] //列表数据
+			}
+		},
+		props: {
+			i: Number, // 每个tab页的专属下标 (除了支付宝小程序必须在这里定义, 其他平台都可不用写, 因为已在MescrollMoreItemMixin定义)
+			index: { // 当前tab的下标 (除了支付宝小程序必须在这里定义, 其他平台都可不用写, 因为已在MescrollMoreItemMixin定义)
+				type: Number,
+				default () {
+					return 0
+				}
+			},
+			tabs: { // 为了请求数据,演示用,可根据自己的项目判断是否要传
+				type: Array,
+				default () {
+					return []
+				}
+			},
+			height: [Number, String] // mescroll的高度
+		},
+		methods: {
+			/*下拉刷新的回调 */
+			downCallback() {
+				// 这里加载你想下拉刷新的数据, 比如刷新轮播数据
+				// loadSwiper();
+				// 下拉刷新的回调,默认重置上拉加载列表为第一页 (自动执行 page.num=1, 再触发upCallback方法 )
+				this.mescroll.resetUpScroll()
+			},
+			/*上拉加载的回调: 其中page.num:当前页 从1开始, page.size:每页数据条数,默认10 */
+			upCallback(page) {
+				//联网加载数据
+				let keyword = this.tabs[this.i].name
+				apiGoods(page.num, page.size, keyword).then(res => {
+					//联网成功的回调,隐藏下拉刷新和上拉加载的状态;
+					this.mescroll.endSuccess(res.list.length);
+					//设置列表数据
+					if (page.num == 1) this.goods = []; //如果是第一页需手动制空列表
+					this.goods = this.goods.concat(res.list); //追加新数据
+				}).catch(() => {
+					//联网失败, 结束加载
+					this.mescroll.endErr();
+				})
+			},
+			//点击空布局按钮的回调
+			emptyClick() {
+				uni.showToast({
+					title: '点击了按钮,具体逻辑自行实现'
+				})
+			},
+			// 跳转详情
+			toDetail(id){
+				console.log('点击详情id:',id)
+				uni.$u.route('/pages/order/orderDetails', {
+					id:id,
+				});
+			},
+			//抢单
+			grabOrders(id){
+				console.log('抢单id:',id)
+			}
+		}
+	}
+</script>

+ 135 - 0
pages/order/orderDetails.vue

@@ -0,0 +1,135 @@
+<!-- 订单详情-->
+<template>
+	<view class="content">
+		<u-divider text="基本信息"></u-divider>
+		<view class="content1">
+			<view class='row-between'>
+				<view class="">货主</view>
+				<view>张三</view>
+			</view>
+			<view class='row-between'>
+				<view class="">货主单位</view>
+				<view>黑龙江中天昊元贸易有限公司</view>
+			</view>
+			<view class='row-between'>
+				<view class="">卸货地</view>
+				<view>黑龙江省齐齐哈尔市梅里斯达斡尔族区杜尔门沁达斡尔乡53农场</view>
+			</view>
+			<view class='row-between'>
+				<view class="">货名</view>
+				<view>玉米</view>
+			</view>
+			<view class='row-between'>
+				<view class="">距离</view>
+				<view>约15公里</view>
+			</view>
+			<view class='row-between'>
+				<view class="">货运费</view>
+				<view>100元/吨</view>
+			</view>
+		</view>
+		<u-divider text="承运信息"></u-divider>
+		<view class="content2">
+			<view class='row-between'>
+				<view class="">合同编号</view>
+				<view>待签订 ></view>
+			</view>
+			<view class='row-between'>
+				<view class="">订单编号</view>
+				<view>CY20220210666666</view>
+			</view>
+			<view class='row-between'>
+				<view class="">装车反馈</view>
+				<view>未装车</view>
+			</view>
+			<view class='row-between'>
+				<view class="">车牌号</view>
+				<view>辽H12345</view>
+			</view>
+			<view class='row-between'>
+				<view class="">装车净重</view>
+				<view>10吨</view>
+			</view>
+			<view class='row-between'>
+				<view class="">装车时间</view>
+				<view>2022-02-10 16:13:15</view>
+			</view>
+			<view class='row-between'>
+				<view class="">装车照片</view>
+				<view class="flex">
+					<u--image :showLoading="true" :src="src" width="40px" height="40px"></u--image>
+					<u--image :showLoading="true" :src="src" width="40px" height="40px"></u--image>
+				</view>
+			</view>
+			<view class='row-between'>
+				<view class="">卸车反馈</view>
+				<view class="flex">
+					<view>已卸车</view>
+					<view>未确认</view>
+				</view>
+			</view>
+			<view class='row-between'>
+				<view class="">卸车净重</view>
+				<view>100吨</view>
+			</view>
+			<view class='row-between'>
+				<view class="">卸车时间</view>
+				<view>2022-02-10 16:13:15</view>
+			</view>
+			<view class='row-between'>
+				<view class="">卸车照片</view>
+				<view class="flex">
+					<u--image :showLoading="true" :src="src" width="40px" height="40px"></u--image>
+					<u--image :showLoading="true" :src="src" width="40px" height="40px"></u--image>
+				</view>
+			</view>
+		</view>
+		<u-divider text="运费信息"></u-divider>
+		<view class="content3">
+			<view class='row-between'>
+				<view class="">预付运费</view>
+				<view>2000</view>
+			</view>
+			<view class='row-between'>
+				<view class="">2022-02-11 15:15:15</view>
+			</view>
+			<view class='row-between'>
+				<view class="">运费尾款</view>
+				<view>2000</view>
+			</view>
+			<view class='row-between'>
+				<view class="">2022-02-11 15:15:15</view>
+			</view>
+			<view class='row-between'>
+				明细:预付2000元,扣款200元,服务费150元,尾款2000元,合计收款4000元。
+			</view>
+		</view>
+		<u-button text="确认装车" type="primary" @click="goConfirmLoading()"></u-button>
+		<u-button text="联系客服" type="primary" @click="$helper.contactCustomerService"></u-button>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				cyinfoStatus: '未装车',
+				src: 'https://cdn.uviewui.com/uview/album/1.jpg',
+				id: 1
+			}
+
+		},
+		methods: {
+			goConfirmLoading(id) {
+				console.log('点击详情id:', id)
+				uni.$u.route('/pages/order/confirmLoading', {
+					id: this.id,
+				});
+			},
+		}
+	}
+</script>
+
+<style lang="scss">
+
+</style>

+ 134 - 0
pages/public/login.vue

@@ -0,0 +1,134 @@
+<template>
+	<view class="u-page">
+		<u--form labelPosition="left" :model="model1" ref="form1">
+			<u-form-item label="电话" prop="phone" borderBottom ref="item1">
+				<u--input v-model="model1.phone" border="none" placeholder="电话"></u--input>
+			</u-form-item>
+
+			<u-form-item label="验证码" prop="code" labelWidth="80" borderBottom>
+				<u--input v-model="model1.code" border="none" placeholder="请填写验证码"></u--input>
+				<u-button slot="right" @tap="getCode" :text="tips" type="success" size="mini" :disabled="disabled1">
+				</u-button>
+			</u-form-item>
+			<u-code ref="uCode" @change="codeChange" seconds="20" @start="disabled1 = true" @end="disabled1 = false">
+			</u-code>
+		</u--form>
+		<u-button type="primary" text="提交" customStyle="margin-top: 50px" @click="submit"></u-button>
+		<u-button  type="primary" @click='goregister'>手机号一键注册</u-button>
+		<u-loading-page :loading="isLoading" bg-color="#e8e8e8"></u-loading-page>
+	</view>
+</template>
+
+<script>
+	import helper from '@/common/helper.js';
+	export default {
+		data() {
+			return {
+				isLoading: false,
+				disabled1: false,
+				tips: '',
+				showCalendar: false,
+				showBirthday: false,
+				model1: {
+					phone: '13333333333',
+					code: '123456'
+				},
+				rules: {
+					code: {
+						type: 'string',
+						required: true,
+						len: 6,
+						message: '请填写4位验证码',
+						trigger: ['blur']
+					},
+				}
+			}
+		},
+		onReady() {
+			// 如果需要兼容微信小程序,并且校验规则中含有方法等,只能通过setRules方法设置规则
+			this.$refs.form1.setRules(this.rules)
+		},
+		methods: {
+
+			codeChange(text) {
+				this.tips = text;
+			},
+			getCode() {
+				if (this.$refs.uCode.canGetCode) {
+					// 模拟向后端请求验证码
+					uni.showLoading({
+						title: '正在获取验证码'
+					})
+					setTimeout(() => {
+						uni.hideLoading();
+						// 这里此提示会被this.start()方法中的提示覆盖
+						uni.$u.toast('验证码已发送');
+						// 通知验证码组件内部开始倒计时
+						this.$refs.uCode.start();
+					}, 2000);
+				} else {
+					uni.$u.toast('倒计时结束后再发送');
+				}
+			},
+
+			submit() {
+				let that = this
+				// 如果有错误,会在catch中返回报错信息数组,校验通过则在then中返回true
+				this.$refs.form1.validate().then(res => {
+					uni.$u.toast('校验通过')
+					this.isLoading = true
+					that.$request.baseRequest('get', '/commonUser/loginVerifyCode', {
+							phone: that.model1.phone,
+							verifyCode: that.model1.code
+						}).then(res => {
+							that.$request.TokenRequest('post', '/commonUser/api/loginQuickly', {
+								mobilePhone: that.model1.phone,
+								veriCode: that.model1.code
+							}).then(res1 => {
+								uni.setStorageSync('pcUserInfo', res1.data)
+								uni.setStorageSync('userInfo', res.data)
+								helper.getListByUserId()
+								that.$store.commit('login', res.data)
+								// that.liangxinLogin()
+								uni.switchTab({
+									url: '/pages/index/index'
+								});
+								this.isLoading = false
+							})
+
+						})
+						.catch(res => {
+							uni.showToast({
+								title: res.message,
+								icon: 'none',
+								duration: 2000
+							})
+						});
+				}).catch(errors => {
+					uni.$u.toast('校验失败')
+				})
+			},
+			reset() {
+				const validateList = ['userInfo.name', 'userInfo.sex', 'radiovalue1', 'checkboxValue1', 'intro',
+					'hotel', 'code', 'userInfo.birthday'
+				]
+				this.$refs.form1.resetFields()
+				this.$refs.form1.clearValidate()
+				setTimeout(() => {
+					this.$refs.form1.clearValidate(validateList)
+					// 或者使用 this.$refs.form1.clearValidate()
+				}, 10)
+			},
+			hideKeyboard() {
+				uni.hideKeyboard()
+			},
+			goregister(){
+					uni.$u.route('/pages/public/register');
+			},
+		},
+	}
+</script>
+
+<style lang="scss">
+
+</style>

+ 208 - 0
pages/public/register.vue

@@ -0,0 +1,208 @@
+<template>
+	<view class="u-page">
+		<u--form labelPosition="left" :model="registerData" ref="registerForm">
+			<u-form-item label="电话" prop="phone" borderBottom>
+				<u--input v-model="registerData.phone" border="none" placeholder="电话"></u--input>
+			</u-form-item>
+
+			<u-form-item label="验证码" prop="code" labelWidth="80" borderBottom>
+				<u--input v-model="registerData.verifyCode" border="none" placeholder="请填写验证码"></u--input>
+				<u-button slot="right" @tap="getCode" :text="tips" type="success" size="mini" :disabled="disabled1">
+				</u-button>
+			</u-form-item>
+			<u-form-item label="密码" prop="password" borderBottom>
+				<u--input v-model="registerData.password" border="none" placeholder="请输入密码,6-16位字符"></u--input>
+			</u-form-item>
+
+			<u-code ref="uCode" @change="codeChange" seconds="20" @start="disabled1 = true" @end="disabled1 = false">
+			</u-code>
+		</u--form>
+		<u-button type="primary" @click='register'>注册</u-button>
+		<view style='color:#6A6A6A;margin-top:10px;text-align:center;' class="flex">
+			<u--image @click='consent' :src="consentStatus==true?'../../static/images/login/select@2x.png':'../../static/images/login/selected2.png'"
+				width="40px" height="40px"></u--image>
+			<!-- <image @click='consent' style='width:14px;height:14px;position:relative;top:2px;margin-right:5px;'
+				:src="consentStatus==true?'../../static/img/login/select@2x.png':'../../static/img/login/selected2.png'"
+				alt=""></image> -->
+			已阅读并同意
+			<navigator url="/pages/sale/webview?can_share=false&url=https://liangxin.zthymaoyi.com/userAgreement.html"
+				class="path" hover-class="navigator-hover">《服务协议》</navigator>和<navigator
+				url="/pages/sale/webview?can_share=false&url=https://liangxin.zthymaoyi.com/screctAgreement.html"
+				class="path" hover-class="navigator-hover">《隐私政策》</navigator>
+		</view>
+	</view>
+</template>
+
+<script>
+	var _this
+	import helper from '@/common/helper.js';
+	export default {
+		data() {
+			return {
+				disabled1: false,
+				tips: '',
+				consentStatus: false,
+				codestatus: false,
+				registerData: {
+					phone: '',
+					password: '',
+					verifyCode: '',
+					userName: ''
+				},
+				rules: {
+					phone: {
+						type: 'string',
+						required: true,
+						len: 11,
+						message: '请填写11位手机号',
+						trigger: ['blur']
+					},
+					verifyCode: {
+						type: 'string',
+						required: true,
+						len: 6,
+						message: '请填写6位验证码',
+						trigger: ['blur']
+					},
+				}
+			}
+		},
+		onReady() {
+			// 如果需要兼容微信小程序,并且校验规则中含有方法等,只能通过setRules方法设置规则
+			this.$refs.registerForm.setRules(this.rules)
+		},
+		onLoad() {
+			_this = this
+		},
+		methods: {
+			codeChange(text) {
+				this.tips = text;
+			},
+			// 获取验证码
+			getCode() {
+				if (/^0?1[3|4|5|6|7|8][0-9]\d{8}$/.test(this.registerData.phone)) {
+					if (this.$refs.uCode.canGetCode) {
+
+						// 模拟向后端请求验证码
+						uni.showLoading({
+							title: '正在获取验证码'
+						})
+						_this.$request.baseRequest('get', '/commonUser/sendVerifyCode', {
+								phone: this.registerData.phone
+							}).then(res => {
+								uni.hideLoading();
+								// 这里此提示会被this.start()方法中的提示覆盖
+								uni.$u.toast('验证码已发送');
+								// 通知验证码组件内部开始倒计时
+								this.$refs.uCode.start();
+
+							})
+							.catch(res => {
+								uni.$u.toast(res.message);
+							});
+
+						// setTimeout(() => {
+
+						// }, 2000);
+					} else {
+						uni.$u.toast('倒计时结束后再发送');
+					}
+				} else {
+					uni.$u.toast('请输入正确手机号');
+				}
+
+			},
+			consent() {
+				this.consentStatus = !this.consentStatus
+				uni.setStorage({
+					key: 'policyStorageKey',
+					data: this.consentStatus
+				});
+			},
+			// 随机数
+			randomAccess(min, max) {
+				return Math.floor(Math.random() * (min - max) + max)
+			},
+			getRandomName(NameLength) {
+				let name = ""
+				for (let i = 0; i < NameLength; i++) {
+					let unicodeNum = ""
+					unicodeNum = this.randomAccess(0x4e00, 0x9fa5).toString(16)
+					name += this.decodeUnicode(unicodeNum)
+				}
+				return name
+			},
+			// 解码
+			decodeUnicode(str) {
+				//Unicode显示方式是\u4e00
+				str = "\\u" + str
+				str = str.replace(/\\/g, "%");
+				//转换中文
+				str = unescape(str);
+				//将其他受影响的转换回原来
+				str = str.replace(/%/g, "\\");
+				return str;
+			},
+			//注册
+			register() {
+				if (!this.consentStatus) {
+					uni.showToast({
+						title: '请勾选协议',
+						icon: 'none',
+						duration: 2000
+					})
+					return
+				}
+				this.$refs.registerForm.validate().then(res => {debugger
+					_this.registerData.userName = _this.getRandomName(3)
+					uni.$u.toast('校验通过')
+					_this.isLoading = true
+					_this.$request.baseRequest('post', '/commonUser/register', _this.registerData).then(res => {
+							if (res.data.code == '11002') {
+								uni.$u.toast('验证码错误或过期,请重新获取')
+
+								return
+							} else if (res.data.code == '11004') {
+								uni.$u.toast('该手机号已注册,可直接登录')
+
+								return
+							} 
+							uni.showLoading({
+								title: '登录中',
+								mask: true
+							})
+							debugger
+							_this.$request.baseRequest('get', '/commonUser/login', {
+								phone: _this.registerData.phone,
+								password: _this.registerData.password,
+								cid: uni.getStorageSync("clientId")
+							}).then(res => {
+								uni.hideLoading()
+								uni.setStorageSync('userInfo', res.data)
+								_this.$store.commit('login', res.data)
+								uni.switchTab({
+									url: '/pages/goodSource/index'
+								});
+									
+								})
+								.catch(res => {
+									uni.$u.toast(res.message)
+								});
+							
+							
+							
+						})
+						.catch(res => {
+							uni.$u.toast(res.message)
+						});
+				}).catch(errors => {
+					uni.$u.toast('校验失败')
+				})
+			},
+		},
+	}
+</script>
+
+<style lang="scss">
+
+</style>

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 15 - 0
public/Pinyin.js


+ 77 - 0
scrolldemo.vue

@@ -0,0 +1,77 @@
+<!-- 订单-->
+<template>
+	 <mescroll-body ref="mescrollRef" @init="mescrollInit" @down="downCallback" @up="upCallback">
+		<view class="notice">mescroll的极简示例,大部分情况就是这么用</view>
+		<good-list :list="goods"></good-list>
+	</mescroll-body>
+</template>
+
+<script>
+	import MescrollMixin from "@/uni_modules/mescroll-uni/components/mescroll-uni/mescroll-mixins.js";
+	import {apiGoods} from "@/api/mock.js"
+	
+	export default {
+		mixins: [MescrollMixin], // 使用mixin
+		data() {
+			return {
+				goods: [] // 数据列表
+			}
+		},
+		methods: {
+			/*上拉加载的回调: 其中page.num:当前页 从1开始, page.size:每页数据条数,默认10 */
+			upCallback(page) {
+				// 此处可以继续请求其他接口
+				// if(page.num == 1){
+				// 	// 请求其他接口...
+				// }
+				
+				// 如果希望先请求其他接口,再触发upCallback,可参考以下写法
+				// if(!this.isInitxx){
+				// 	apiGetxx().then(res=>{
+				// 		this.isInitxx = true
+				// 		this.mescroll.resetUpScroll() // 重新触发upCallback
+				// 	}).catch(()=>{
+				// 		this.mescroll.endErr()
+				// 	})
+				// 	return // 此处return,先获取xx
+				// }
+				
+				//联网加载数据
+				apiGoods(page.num, page.size).then(res=>{
+					//联网成功的回调,隐藏下拉刷新和上拉加载的状态;
+					//mescroll会根据传的参数,自动判断列表如果无任何数据,则提示空;列表无下一页数据,则提示无更多数据;
+
+					//方法一(推荐): 后台接口有返回列表的总页数 totalPage
+					//this.mescroll.endByPage(res.list.length, totalPage); //必传参数(当前页的数据个数, 总页数)
+
+					//方法二(推荐): 后台接口有返回列表的总数据量 totalSize
+					//this.mescroll.endBySize(res.list.length, totalSize); //必传参数(当前页的数据个数, 总数据量)
+
+					//方法三(推荐): 您有其他方式知道是否有下一页 hasNext
+					//this.mescroll.endSuccess(res.list.length, hasNext); //必传参数(当前页的数据个数, 是否有下一页true/false)
+
+					//方法四 (不推荐),会存在一个小问题:比如列表共有20条数据,每页加载10条,共2页.如果只根据当前页的数据个数判断,则需翻到第三页才会知道无更多数据
+					this.mescroll.endSuccess(res.list.length);
+
+					//设置列表数据
+					if(page.num == 1) this.goods = []; //如果是第一页需手动制空列表
+					this.goods=this.goods.concat(res.list); //追加新数据
+				}).catch(()=>{
+					//联网失败, 结束加载
+					this.mescroll.endErr();
+				})
+			}
+		}
+	}
+</script>
+
+<style>
+	/*说明*/
+	.notice{
+		font-size: 26upx;
+		padding: 40upx 0;
+		border-bottom: 1upx solid #eee;
+		text-align: center;
+		color:#555;
+	}
+</style>

+ 92 - 0
static/css/common.scss

@@ -0,0 +1,92 @@
+// 全局公共样式
+.content{
+	background: $ac-bgc;
+	padding:$uni-spacing-row-base;
+	overflow: hidden;
+	
+}
+// 常用公共样式
+// 布局相关 start
+.flex{
+	display: flex;
+}
+.inline-block{
+	display: inline-block;
+}
+.s-row{
+	display: flex;
+	flex-direction: column;
+}
+
+.flex-center{
+	justify-content: center;
+	align-items: center;
+}
+.flex-space-between{
+	justify-content: space-between;
+	align-items: center;
+}
+.flex-space-around{
+	justify-content: space-around;
+	align-items: center;
+}
+.flex-space-evenly{
+	justify-content: space-evenly;
+	align-items: center;
+}
+.flex-end{
+	    justify-content: flex-end;
+}
+.items-center{
+	    align-items: center;
+}
+.flex-start{
+	    justify-content: flex-start;
+}
+.m-topr20{
+	margin-top: 20rpx;
+}
+.paddingr20{
+	padding:20rpx;
+}
+.lr-paddingr20{
+	padding: 0 20rpx;
+}
+.fixed{
+	position: fixed;
+}
+.row-between{
+	display: flex;
+	justify-content: space-between;
+}
+.content-other{
+	background: white;
+	padding:10rpx 20rpx;
+	border-radius: 10rpx;
+}
+.width100{
+	width: 100%;
+}
+// 布局相关 end
+
+// 边线相关start
+.border-bottom{
+	border-bottom: 1px solid $uni-border-color;
+	padding-bottom: 10rpx;
+}
+// 边线相关end
+.red{
+	background: red;
+}
+.yellow{
+	background:yellow;
+}
+
+// 文字相关start
+.level1-title{
+	
+}
+// 文字相关end
+// 边线相关start
+// 边线相关start
+

+ 20 - 0
static/css/font.css

@@ -0,0 +1,20 @@
+@font-face {
+	font-family: "PingFang SC";
+	src: url('https://taohaoliang.oss-accelerate.aliyuncs.com/app/tmp/PingFang-Bold.ttf'),
+/* 		url('https://taohaoliang.oss-cn-beijing.aliyuncs.com/app/tmp/PingFang-ExtraLight.ttf'),
+		url('https://taohaoliang.oss-cn-beijing.aliyuncs.com/app/tmp/PingFang-Heavy.ttf'),
+		url('https://taohaoliang.oss-cn-beijing.aliyuncs.com/app/tmp/PingFang-Light.ttf'), */
+		url('https://taohaoliang.oss-accelerate.aliyuncs.com/app/tmp/PingFang-Medium.ttf'),
+		url('https://taohaoliang.oss-accelerate.aliyuncs.com/app/tmp/PingFang-Regular.ttf');
+		font-weight: normal;
+	font-style: normal;
+}
+@font-face {
+	font-family: "DINPro";
+	src:url('https://taohaoliang.oss-accelerate.aliyuncs.com/app/tmp/DINPro-Bold.ttf'),
+		/* url('https://taohaoliang.oss-cn-beijing.aliyuncs.com/app/tmp/DINPro-Light.ttf'), */
+		url('https://taohaoliang.oss-accelerate.aliyuncs.com/app/tmp/DINPro-Medium.ttf');
+		font-weight: normal;
+	font-style: normal;
+}
+

BIN
static/icon_delete.png


BIN
static/icon_down.png


BIN
static/images/login/bg.png


BIN
static/images/login/bg@2x.png


BIN
static/images/login/bg@3x.png


BIN
static/images/login/bg_slices/bg.png


BIN
static/images/login/bg_slices/bg@2x.png


BIN
static/images/login/bg_slices/bg@3x.png


BIN
static/images/login/duihao2.png


BIN
static/images/login/duihao2@2x.png


BIN
static/images/login/duihao2@3x.png


BIN
static/images/login/guanbi@2x.png


BIN
static/images/login/logo.png


BIN
static/images/login/logo@2x.png


BIN
static/images/login/logo@3x.png


BIN
static/images/login/select.png


BIN
static/images/login/select@2x.png


BIN
static/images/login/select@3x.png


BIN
static/images/login/selected1.png


BIN
static/images/login/selected2.png


BIN
static/images/login/selected3.png


BIN
static/images/mine/saoma.png


BIN
static/images/myimg/LiangNong.png


BIN
static/images/myimg/LiangNong@2x.png


BIN
static/images/myimg/LiangNong@3x.png


BIN
static/images/myimg/LiangShang@2x.png


BIN
static/images/myimg/LiangShang@3x.png


BIN
static/images/myimg/SiJi.png


BIN
static/images/myimg/SiJi@2x.png


BIN
static/images/myimg/SiJi@3x.png


BIN
static/images/myimg/YongHu.png


BIN
static/images/myimg/YongHu@2x.png


BIN
static/images/myimg/YongHu@3x.png


BIN
static/images/myimg/erp.png


BIN
static/images/myimg/fabu@3x.png


BIN
static/images/myimg/gengduo1.png


Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels