form.vue 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507
  1. <template>
  2. <zj-page-layout :hasFooter="true">
  3. <view class="form-container">
  4. <view class="clipboard">
  5. <view class="box">
  6. <u--textarea v-model="clipboard" border="none" :confirmType="'done'" placeholder="试试粘贴“收件人姓名,手机号,详细地址”,可快速识别您的用户及地址信息"></u--textarea>
  7. <view class="btns">
  8. <u-button text="清空" size="small" @click="clipboard = ''"></u-button>
  9. <u-button type="primary" text="识别" size="small" @click="shibie"></u-button>
  10. </view>
  11. </view>
  12. </view>
  13. <view class="row">
  14. <view class="title">联系人</view>
  15. <view class="right input"><input type="text" placeholder="请输入联系人" v-model="formData.name"></view>
  16. </view>
  17. <view class="row">
  18. <view class="title">手机号码</view>
  19. <view class="right input"><input type="number" placeholder="请输入手机号码" v-model="formData.phone"></view>
  20. </view>
  21. <view class="row">
  22. <view class="title">所在地区</view>
  23. <view class="right">
  24. <picker @change="onRegionChange" v-model="regionValue" mode="region">
  25. <view class="picker">
  26. <view v-if="regionValue.length">{{regionValue[0] + '/' +regionValue[1] + '/' +regionValue[2]}}</view>
  27. <view v-else style="color: #666666;">请选择省/市/区</view>
  28. <text class="iconfont icon-jinru"></text>
  29. </view>
  30. </picker>
  31. </view>
  32. </view>
  33. <view class="row">
  34. <view class="title">所在街道</view>
  35. <view class="right">
  36. <picker @change="onStreetChange" :value="streetValue" :range="streetList" range-key="name" mode="selector" :disabled="!regionValue[2]">
  37. <view class="picker">
  38. <view v-if="streetValue !== ''">{{streetList[streetValue].name}}</view>
  39. <view v-else style="color: #666666;">请选择街道</view>
  40. <text class="iconfont icon-jinru"></text>
  41. </view>
  42. </picker>
  43. </view>
  44. </view>
  45. <view class="row">
  46. <view class="title">详细地址</view>
  47. <view class="right textarea">
  48. <textarea placeholder="请输入详细地址" auto-height v-model="formData.address"></textarea>
  49. <view class="r" @tap="getLocation"><text class="iconfont icon-dingwei1"></text>定位</view>
  50. </view>
  51. </view>
  52. <!-- <view class="row">
  53. <view class="title">门牌号</view>
  54. <view class="right input"><input type="text" placeholder="请输入门牌号" maxlength="15" v-model="formData.houseNo"></view>
  55. </view> -->
  56. <view class="row mt20">
  57. <view class="title">设为默认</view>
  58. <view class="right default"><switch @change="switchChange" color="#01C30B" v-model="formData.defaultAddr" :checked="formData.defaultAddr" style="transform:scale(0.7)" /></view>
  59. </view>
  60. </view>
  61. <template slot="footer">
  62. <view class="footer-btn-group">
  63. <u-button text="删除" @click="handleDelete" v-if="editId"></u-button>
  64. <u-button text="保存" type="primary" @click="submitForm"></u-button>
  65. </view>
  66. </template>
  67. </zj-page-layout>
  68. </template>
  69. <script>
  70. import {getArea} from '@/common/utils/util.js';
  71. export default {
  72. data() {
  73. return {
  74. editId: null, // 编辑的id
  75. regionValue: [], // 省市区值
  76. streetList: [],
  77. streetValue: '',
  78. formData: { // 表单数据
  79. name: '',
  80. phone: '',
  81. province: '',
  82. city: '',
  83. area: '',
  84. street: '',
  85. address: '',
  86. // houseNo: '',
  87. defaultAddr: false,
  88. },
  89. canClickSave: true, // 能否点击提交
  90. clipboard: '',
  91. }
  92. },
  93. onLoad({id, addressData}) {
  94. this.editId = id;
  95. if(id) {
  96. uni.setNavigationBarTitle({
  97.   title: '编辑地址'
  98. })
  99. this.getAddressData();
  100. }
  101. if(addressData) {
  102. addressData = JSON.parse(addressData);
  103. this.formData = {
  104. name: addressData.name,
  105. phone: addressData.phone,
  106. province: addressData.province,
  107. city: addressData.city,
  108. area: addressData.area,
  109. address: addressData.address,
  110. // houseNo: addressData.houseNo,
  111. defaultAddr: addressData.defaultAddr,
  112. }
  113. this.regionValue = [addressData.province, addressData.city, addressData.area];
  114. this.getStreetList();
  115. }
  116. },
  117. methods: {
  118. async getRegion(address) {
  119. const result = new Promise((resolve, reject) => {
  120. this.$api.post('/lbs/amap/region/query2', {
  121. address
  122. }).then(res => {
  123. resolve(res.data);
  124. })
  125. })
  126. return result;
  127. },
  128. async shibie() {
  129. // 莫阿宝,13686123158,广东省广州市天河区棠下街道天河软件园
  130. // console.log(this.smart(this.clipboard));
  131. const data = this.smart(this.clipboard);
  132. this.formData.name = data.name || '';
  133. this.formData.phone = data.phone || '';
  134. if(data.address) {
  135. let addressData = await this.getRegion(data.address);
  136. this.formData.province = addressData.provinceName || '';
  137. this.formData.city = addressData.cityName || '';
  138. this.formData.area = addressData.areaName || '';
  139. this.formData.address = data.address.replace(`${addressData.provinceName || ''}${addressData.cityName || ''}${addressData.areaName || ''}${addressData.name || ''}`, '') || '';
  140. this.regionValue = [addressData.provinceName || '', addressData.cityName || '', addressData.areaName || ''];
  141. addressData.name && this.getStreetList(addressData.name);
  142. }
  143. },
  144. smart(data) {
  145. data = this.stripscript(data); //过滤特殊字符
  146. let obj = {};
  147. let copyData = JSON.parse(JSON.stringify(data)).split(" ");
  148. copyData.forEach((item, index) => {
  149. if (item) {
  150. let addressObj = this.smartData(item);
  151. console.log(addressObj)
  152. obj = Object.assign(obj, addressObj);
  153. }
  154. });
  155. return obj;
  156. },
  157. smartData(data) {
  158. let smartObj = {};
  159. //address= data.replace(/\s/g, ''); //去除空格
  160. // 手机号匹配(提取出手机号)
  161. let phone = data.match(/(86-[1][0-9]{10}) | (86[1][0-9]{10})|([1][0-9]{10})/g);
  162. // 如果存在手机号
  163. if (phone) {
  164. smartObj.phone = phone[0];
  165. if(data != phone[0]) {
  166. // 如果手机号是开头或结尾
  167. if(data.startsWith(phone[0]) || data.endsWith(phone[0])) {
  168. let remainData = data.replace(phone[0], ''); // 除了手机号,剩下的内容
  169. // 如果还有剩下的内容
  170. if(remainData) {
  171. if (new RegExp(/省|市|区/).test(remainData)) {
  172. smartObj.address = remainData;
  173. } else {
  174. smartObj.name = remainData;
  175. }
  176. }
  177. }
  178. // 如果手机号在中间
  179. else {
  180. let remainDatas = data.replace(phone[0], '&&').split('&&'); // 除了手机号,剩下的内容
  181. for(let i = 0; i < remainDatas.length; i++) {
  182. if(new RegExp(/省|市|区/).test(remainDatas[i])) {
  183. smartObj.address = remainDatas[i];
  184. }else {
  185. smartObj.name = remainDatas[i];
  186. }
  187. }
  188. }
  189. }
  190. }
  191. // 如果不存在手机号
  192. else {
  193. if (new RegExp(/省|市|区/).test(data)) {
  194. smartObj.address = data;
  195. }
  196. else {
  197. smartObj.name = data;
  198. }
  199. }
  200. return smartObj;
  201. },
  202. // 过滤特殊字符
  203. stripscript(s) {
  204. s = s.replace(/(\d{3})-(\d{4})-(\d{4})/g, "$1$2$3");
  205. s = s.replace(/(\d{3}) (\d{4}) (\d{4})/g, "$1$2$3");
  206. var pattern = new RegExp(
  207. "[`~!@#$^&*()=|{}':;',\\[\\].<>/?~!@#¥……&*()——|{}【】‘;:”“’。,、?-]"
  208. );
  209. var rs = "";
  210. for (var i = 0; i < s.length; i++) {
  211. rs = rs + s.substr(i, 1).replace(pattern, " ");
  212. }
  213. rs = rs.replace(/[\r\n]/g, "");
  214. return rs;
  215. },
  216. // 获取地址信息
  217. getAddressData() {
  218. this.$api.get('/user/address/detail', {
  219. userAddressId: this.editId
  220. }).then(res => {
  221. this.formData = {
  222. name: res.data.name,
  223. phone: res.data.phone,
  224. province: res.data.province,
  225. city: res.data.city,
  226. area: res.data.area,
  227. address: res.data.address,
  228. // houseNo: res.data.houseNo,
  229. defaultAddr: res.data.defaultAddr,
  230. }
  231. this.regionValue = [res.data.province, res.data.city, res.data.area];
  232. this.getStreetList(res.data.street);
  233. })
  234. },
  235. // 地图选点
  236. getLocation() {
  237. let that = this;
  238. uni.chooseLocation({
  239. success: function (res) {
  240. console.log(res);
  241. let SSQ_value = getArea(res.address);
  242. if(!SSQ_value.Province) {
  243. SSQ_value.Province = SSQ_value.City;
  244. }
  245. that.formData.province = SSQ_value.Province;
  246. that.formData.city = SSQ_value.City;
  247. that.formData.area = SSQ_value.Country;
  248. let regionValue = [];
  249. regionValue.push(SSQ_value.Province);
  250. regionValue.push(SSQ_value.City);
  251. regionValue.push(SSQ_value.Country);
  252. that.regionValue = regionValue;
  253. that.formData.address = res.address.slice(res.address.indexOf(SSQ_value.Country) + SSQ_value.Country.length) + res.name;
  254. that.getStreetList();
  255. that.streetValue = '';
  256. that.formData.street = '';
  257. },
  258. fail: function(res) {
  259. uni.getSetting({
  260. success: function(res) {
  261. if (!res.authSetting['scope.userLocation']) {
  262. uni.showModal({
  263. title: '是否授权当前位置',
  264. content: '需要获取您的地理位置,请确认授权,否则地图功能将无法使用',
  265. success(tip) {
  266. if (tip.confirm) {
  267. uni.openSetting({
  268. success: function(data) {
  269. if (data.authSetting["scope.userLocation"] === true) {
  270. that.$successToast('授权成功');
  271. setTimeout(() => {
  272. that.getLocation();
  273. }, 1000)
  274. }
  275. }
  276. })
  277. }
  278. }
  279. })
  280. }
  281. }
  282. })
  283. }
  284. });
  285. },
  286. // 切换省市区
  287. onRegionChange(e) {
  288. console.log(e.detail);
  289. this.regionValue = e.detail.value;
  290. this.formData.province = this.regionValue[0];
  291. this.formData.city = this.regionValue[1];
  292. this.formData.area = this.regionValue[2];
  293. this.getStreetList();
  294. this.streetValue = '';
  295. },
  296. // 获取街道列表
  297. getStreetList(street) {
  298. this.$api.get('/user/address/street', {
  299. province: this.regionValue[0],
  300. city: this.regionValue[1],
  301. area: this.regionValue[2],
  302. }).then(res => {
  303. this.streetList = res.data;
  304. if(street) {
  305. let index = this.findElem(this.streetList, 'name', street);
  306. this.streetValue = index;
  307. this.formData.street = street;
  308. }
  309. })
  310. },
  311. // 切换街道
  312. onStreetChange(e) {
  313. console.log(e.detail.value);
  314. this.streetValue = e.detail.value;
  315. this.formData.street = this.streetList[this.streetValue].name;
  316. },
  317. findElem(array, attr, val) {
  318. for (var i = 0; i < array.length; i++) {
  319. if (array[i][attr] == val) {
  320. return i; //返回当前索引值
  321. }
  322. }
  323. return -1;
  324. },
  325. switchChange(e) {
  326. console.log(e.detail.value);
  327. this.formData.defaultAddr = e.detail.value;
  328. },
  329. // 验证数据
  330. vailateData() {
  331. if(!this.formData.name) {
  332. this.$toast('请填写姓名');
  333. return false;
  334. }
  335. if(!this.formData.phone) {
  336. this.$toast('请填写手机号码');
  337. return false;
  338. }
  339. if(!(/^1[3456789]\d{9}$/.test(this.formData.phone))) {
  340. this.$toast('请填写正确的手机号码');
  341. return false;
  342. }
  343. if(!this.formData.province) {
  344. this.$toast('请选择所在地区');
  345. return false;
  346. }
  347. if(!this.formData.street) {
  348. this.$toast('请选择所在街道');
  349. return false;
  350. }
  351. if(!this.formData.address) {
  352. this.$toast('请填写详细地址');
  353. return false;
  354. }
  355. return true;
  356. },
  357. // 提交表单
  358. submitForm() {
  359. if (!this.canClickSave) return false;
  360. this.canClickSave = false;
  361. setTimeout(() => { this.canClickSave = true }, 3000)
  362. if(!this.vailateData())return;
  363. let params = this.formData;
  364. params.userId = this.$store.state.user.userId;
  365. let url = '';
  366. if(this.editId) {
  367. params.userAddressId = this.editId;
  368. url = '/user/address/update';
  369. }else {
  370. url = '/user/address/save';
  371. }
  372. this.$api.post(url, params).then(res => {
  373. this.$successToast(this.editId? '编辑成功':'添加成功');
  374. this.$backPage(1, 1000);
  375. })
  376. },
  377. // 删除
  378. handleDelete() {
  379. this.$modal({
  380. content: '确定要删除该地址吗?',
  381. }).then(() => {
  382. this.$api.post('/user/address/del', {
  383. userAddressId: this.editId
  384. }).then(res => {
  385. this.$successToast('删除成功');
  386. this.$backPage(1, 1000);
  387. })
  388. }).catch(() => {})
  389. }
  390. }
  391. }
  392. </script>
  393. <style lang="scss">
  394. .form-container {
  395. .clipboard {
  396. padding: 20rpx;
  397. background: #FFFFFF;
  398. .box {
  399. background: #f5f5f5;
  400. ::v-deep .u-textarea {
  401. background: none !important;
  402. }
  403. .btns {
  404. padding: 20rpx;
  405. display: flex;
  406. justify-content: flex-end;
  407. ::v-deep .u-button {
  408. width: 100rpx;
  409. margin-left: 30rpx;
  410. margin-right: 0;
  411. }
  412. }
  413. }
  414. }
  415. .row {
  416. background: #FFFFFF;
  417. min-height: 88rpx;
  418. padding: 0 20rpx;
  419. display: flex;
  420. justify-content: space-between;
  421. align-items: center;
  422. border-bottom: 1px solid #f5f5f5;
  423. .title {
  424. flex-shrink: 0;
  425. width: 160rpx;
  426. font-size: 28rpx;
  427. color: #333333;
  428. }
  429. .right {
  430. flex: 1;
  431. width: 0;
  432. input {
  433. font-size: 28rpx;
  434. }
  435. .picker {
  436. display: flex;
  437. align-items: center;
  438. justify-content: space-between;
  439. image {
  440. width: 16rpx;
  441. height: 28rpx;
  442. }
  443. }
  444. }
  445. .textarea {
  446. display: flex;
  447. justify-content: space-between;
  448. align-items: center;
  449. textarea {
  450. padding: 10rpx 0;
  451. }
  452. .r {
  453. display: flex;
  454. align-items: center;
  455. flex-shrink: 0;
  456. font-size: 24rpx;
  457. color: #666666;
  458. margin-left: 15rpx;
  459. .iconfont {
  460. font-size: 36rpx;
  461. color: #999999;
  462. margin-right: 4rpx;
  463. }
  464. }
  465. }
  466. .default {
  467. display: flex;
  468. justify-content: flex-end;
  469. switch {
  470. margin-right: -20rpx;
  471. }
  472. }
  473. }
  474. }
  475. </style>