create.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668
  1. <template>
  2. <view class="page">
  3. <view class="form">
  4. <u-form :model="form" ref="uForm">
  5. <u-form-item label-width="150" label="成交楼盘" prop="deal_item" required>
  6. <u-input placeholder="请输入成交楼盘" v-model="form.deal_item" type="text"></u-input>
  7. </u-form-item>
  8. <u-form-item label-width="150" label="成交房号" prop="house_no" required>
  9. <u-input placeholder="请输入成交房号" v-model="form.house_no" type="text"></u-input>
  10. </u-form-item>
  11. <u-form-item label-width="150" label="房屋类型" prop="house_type" required>
  12. <u-radio-group v-model="form.house_type" active-color="#2979ff">
  13. <u-radio :name="HT.val" v-for="HT in houseTypeList" :key="HT.val">{{HT.key}}</u-radio>
  14. </u-radio-group>
  15. </u-form-item>
  16. <u-form-item label-width="150" label="成交店员" prop="deal_clerk" required>
  17. <u-input placeholder="请输入成交店员" v-model="form.deal_clerk" type="text"></u-input>
  18. </u-form-item>
  19. <u-form-item label-width="150" label="成交类型" prop="deal_type" required>
  20. <u-radio-group v-model="form.deal_type" active-color="#2979ff">
  21. <u-radio :name="DT.val" v-for="DT in dealTypeList" :key="DT.val">{{DT.key}}</u-radio>
  22. </u-radio-group>
  23. </u-form-item>
  24. <u-form-item label-width="150" label="所属门店" prop="store_type" required>
  25. <u-radio-group v-model="form.store_type" active-color="#2979ff">
  26. <u-radio :name="DT.val" v-for="DT in storeTypeList" :key="DT.val">{{DT.key}}</u-radio>
  27. </u-radio-group>
  28. </u-form-item>
  29. <u-form-item label-width="150" label="成交日期" prop="deal_at" @click.native="openDealAtPopoup" required>
  30. <view class="scoped-input-floor" @click.native="openDealAtPopoup"></view>
  31. <u-input placeholder="请选择成交日期" v-model="form.deal_at" disabled type="text"></u-input>
  32. </u-form-item>
  33. <u-form-item label-width="150" label="客户姓名" prop="customer_name" required>
  34. <u-input placeholder="请输入客户姓名" v-model="form.customer_name" type="text"></u-input>
  35. <view class="scoped-input-label-tips" @click="openCustPopup">选择客户</view>
  36. </u-form-item>
  37. <u-form-item label-width="150" label="手机号" prop="customer_phone" required>
  38. <u-input placeholder="请输入手机号" v-model="form.customer_phone" type="number"></u-input>
  39. </u-form-item>
  40. <u-form-item label-width="150" label="面积" prop="area" required>
  41. <u-input placeholder="请输入面积" v-model="form.area" type="text"></u-input>
  42. <template v-slot:right>
  43. </template>
  44. </u-form-item>
  45. <u-form-item label-width="150" label="总价" prop="price" required>
  46. <u-input placeholder="请输入总价" v-model="form.price" type="text"></u-input>
  47. <template v-slot:right>
  48. </template>
  49. </u-form-item>
  50. <u-form-item label-width="150" label="报备渠道" prop="report_dept" required>
  51. <u-input placeholder="请输入报备渠道" v-model="form.report_dept" type="text"></u-input>
  52. </u-form-item>
  53. <u-form-item label-width="150" label="折扣体系" prop="discount">
  54. <u-input placeholder="请输入折扣体系" v-model="form.discount" type="text"></u-input>
  55. </u-form-item>
  56. <u-form-item label-width="150" label="佣金" prop="brokerage">
  57. <u-input placeholder="请输入佣金" v-model="form.brokerage" type="text"></u-input>
  58. </u-form-item>
  59. <u-form-item label-position="top" label-width="150" label="佣金凭证" prop="brokerage_img">
  60. <view class="id_card" @click="uploadbrokerageImgImage">
  61. <u-icon v-if="form.brokerage_img == null" name="plus" size="32" color="#606266"></u-icon>
  62. <text v-if="form.brokerage_img == null">请先上传佣金凭证照片</text>
  63. <image v-if="form.brokerage_img != null" :src="brokerage_img" mode="aspectFill"></image>
  64. </view>
  65. </u-form-item>
  66. <u-form-item label-width="150" label="返佣" prop="rebate">
  67. <u-input placeholder="请输入返佣" v-model="form.rebate" type="text"></u-input>
  68. </u-form-item>
  69. <u-form-item label-width="150" label="客户生日" prop="birthday" @click.native="openbirthdayPopoup">
  70. <view class="scoped-input-floor" @click.native="openbirthdayPopoup"></view>
  71. <u-input placeholder="请选择客户生日" v-model="form.birthday" disabled type="text"></u-input>
  72. </u-form-item>
  73. <u-form-item label-width="150" label="备注信息" prop="remark" label-position="top">
  74. <u-input placeholder="备注信息" v-model="form.remark" type="textarea"></u-input>
  75. </u-form-item>
  76. </u-form>
  77. <u-gap height="60"></u-gap>
  78. <u-button type="primary" :diabled="submitButtonDisabled" @click="submitHandle">提交</u-button>
  79. </view>
  80. <!-- 列表选择 -->
  81. <u-select mode="single-column" :list="propertySelectList" v-model="propertySelectShow" @confirm="propertySelectConfirm"></u-select>
  82. <u-select mode="single-column" :list="salerSelectList" v-model="salerSelectShow" @confirm="salerSelectConfirm"></u-select>
  83. <!-- modal -->
  84. <u-modal v-model="submitModalShow" content="请务必仔细确认各项信息是否正确" :show-cancel-button="true" @confirm="submit()"></u-modal>
  85. <u-modal v-model="modalShow" :content="modalContent" :show-cancel-button="true" @cancel="modalCancel()" @confirm="modalConfirm()"></u-modal>
  86. <u-calendar v-model="dealAtShow" :mode="calendarMode" @change="dealAtChange"></u-calendar>
  87. <u-calendar v-model="birthdayShow" :mode="calendarMode" @change="birthdayChange"></u-calendar>
  88. <!-- utoast -->
  89. <u-toast ref="uToast" />
  90. <u-popup v-model="curPopupShow" mode="center" width="90%" height="100%">
  91. <view class="bwin-popup scoped-cur-popup">
  92. <view class="scp-header-input">
  93. <u-input class="input" v-model="curPopupKeyword" placeholder="点这输入客户手机号段模糊搜索"></u-input>
  94. <view class="b" @click="getCurDataList">搜索</view>
  95. </view>
  96. <scroll-view :scroll-y="true" class="popup-body">
  97. <view class="scoped-cust-list">
  98. <view v-for="(item, index) in popupDataList" :key="index" :class="form.customer_phone == item.phone ? 'scl-item cur' : 'scl-item'" @click="listItemHandle(item)">
  99. <view class="p1">{{item.name}}
  100. <u-icon
  101. class="u-m-l-5"
  102. :name="item.sex == 'male' ? 'man' : 'woman'"
  103. size="22"
  104. :color="item.sex == 'male' ? '#2080f0' : '#f85f69'"
  105. ></u-icon>
  106. </view>
  107. <view class="p2">{{item.phone}}
  108. <view class="s" v-if="item.realname">
  109. [{{ item.realname }}]
  110. </view>
  111. </view>
  112. <view class="p3">{{item.create_at}}</view>
  113. </view>
  114. </view>
  115. </scroll-view>
  116. <view class="popup-footer" style="position: fixed;bottom: 12rpx;">
  117. <u-button size="medium" @click="curPopupShow = false">关闭</u-button>
  118. <u-button size="medium" type="primary" @click="curPopupShow = false">确定</u-button>
  119. </view>
  120. </view>
  121. </u-popup>
  122. </view>
  123. </template>
  124. <script>
  125. export default {
  126. data() {
  127. const userInfo = uni.getStorageSync('MD_userInfo2')
  128. return {
  129. curPopupShow: false,
  130. curPopupKeyword: '',
  131. popupDataList: [],
  132. brokerage_img: '',
  133. dealAtShow: false,
  134. birthdayShow: false,
  135. calendarMode: 'date',
  136. isEdit: false,
  137. form: {
  138. deal_item: '',
  139. house_no: '',
  140. house_type: '1',
  141. deal_clerk: userInfo.nickname,
  142. deal_type: '1',
  143. store_type: '其它',
  144. deal_at: '',
  145. customer_name: '',
  146. customer_phone: '',
  147. area: '',
  148. price: '',
  149. report_dept: '',
  150. discount: '',
  151. brokerage: '',
  152. rebate: '',
  153. brokerage_img: null,
  154. remark: null
  155. },
  156. submitButtonDisabled: true,
  157. rules: {
  158. deal_item: [
  159. {
  160. required: true,
  161. message: '成交楼盘不得为空',
  162. trigger: ['change', 'blur']
  163. },
  164. ],
  165. house_no: [
  166. {
  167. required: true,
  168. message: '成交房号不得为空',
  169. trigger: ['change', 'blur']
  170. },
  171. ],
  172. house_type: [
  173. {
  174. required: true,
  175. message: '房屋类型不得为空',
  176. trigger: ['change', 'blur']
  177. },
  178. ],
  179. deal_clerk: [
  180. {
  181. required: true,
  182. message: '成交店员不得为空',
  183. trigger: ['change', 'blur']
  184. },
  185. ],
  186. deal_type: [
  187. {
  188. required: true,
  189. message: '成交类型不得为空',
  190. trigger: ['change', 'blur']
  191. },
  192. ],
  193. store_type: [
  194. {
  195. required: true,
  196. message: '所属门店不得为空',
  197. trigger: ['change', 'blur']
  198. },
  199. ],
  200. deal_at: [
  201. {
  202. required: true,
  203. message: '成交日期不得为空',
  204. trigger: ['change', 'blur']
  205. },
  206. ],
  207. customer_name: [
  208. {
  209. required: true,
  210. message: '客户姓名不得为空',
  211. trigger: ['change', 'blur']
  212. },
  213. ],
  214. customer_phone: [
  215. {
  216. required: true,
  217. message: '客户手机号不得为空',
  218. trigger: ['change', 'blur']
  219. },
  220. // 11个字符判断
  221. {
  222. len: 11,
  223. message: '手机号格式不正确',
  224. trigger: ['change', 'blur']
  225. },
  226. ],
  227. area: [
  228. {
  229. required: true,
  230. message: '面积不得为空',
  231. trigger: ['change', 'blur']
  232. },
  233. ],
  234. price: [
  235. {
  236. required: true,
  237. message: '总价不得为空',
  238. trigger: ['change', 'blur']
  239. },
  240. ],
  241. report_dept: [
  242. {
  243. required: true,
  244. message: '报备渠道不得为空',
  245. trigger: ['change', 'blur']
  246. },
  247. ],
  248. },
  249. recordLevelList: [],
  250. propertySelectShow: false,
  251. propertySelectList: [],
  252. salerSelectShow: false,
  253. salerSelectList: [],
  254. submitModalShow: false,
  255. modalShow: false,
  256. modalContent: '',
  257. houseTypeList: [],
  258. dealTypeList: [],
  259. storeTypeList: [],
  260. };
  261. },
  262. onLoad(data) {
  263. const that = this
  264. const eventChannel = that.getOpenerEventChannel(); // that 需指向 this
  265. // 监听data事件,获取上一页面通过eventChannel.emit传送到当前页面的数据
  266. if (eventChannel.on) {
  267. eventChannel.on('data', data => {
  268. if (data) {
  269. that.form.deal_item = data.info.deal_item;
  270. that.form.house_no = data.info.house_no;
  271. that.form.house_type = data.info.house_type;
  272. that.form.deal_clerk = data.info.deal_clerk;
  273. that.form.deal_type = data.info.deal_type;
  274. that.form.store_type = data.info.store_type;
  275. that.form.deal_at = data.info.deal_at;
  276. that.form.customer_name = data.info.customer_name;
  277. that.form.customer_phone = data.info.customer_phone;
  278. that.form.area = String(data.info.area);
  279. that.form.price = String(data.info.price);
  280. that.form.report_dept = data.info.report_dept;
  281. that.form.discount = data.info.discount;
  282. that.form.brokerage = data.info.brokerage;
  283. that.form.rebate = data.info.rebate;
  284. that.brokerage_img = that.form.brokerage_img = data.info.brokerage_img;
  285. that.form.remark = data.info.remark;
  286. that.form.id = data.info.id;
  287. that.isEdit = true
  288. wx.setNavigationBarTitle({
  289. title: `编辑成交单-${data.info.deal_item}(${data.info.house_no})`
  290. })
  291. }
  292. })
  293. }
  294. },
  295. created () {
  296. const dictObj = uni.getStorageSync('MD_dict')
  297. this.houseTypeList = dictObj.trade_house_type || []
  298. this.dealTypeList = dictObj.trade_deal_type || []
  299. this.storeTypeList = dictObj.store_type || []
  300. },
  301. // 必须要在onReady生命周期,因为onLoad生命周期组件可能尚未创建完毕
  302. onReady() {
  303. this.$refs.uForm.setRules(this.rules);
  304. },
  305. methods: {
  306. listItemHandle (item) {
  307. let form = this.form
  308. form.customer_name = `${item.name}${item.sex === 'male' ? '女士' : '先生'}`
  309. form.customer_phone = item.phone
  310. this.form = {...form}
  311. },
  312. getCurDataList () {
  313. uni.api.cust.apicustomerlist({page_size: 100, phone: this.curPopupKeyword}).then(res => {
  314. let list = res.list || []
  315. this.popupDataList = [...list]
  316. })
  317. },
  318. openCustPopup () {
  319. this.curPopupShow = true
  320. this.getCurDataList()
  321. },
  322. uploadImgHandle (bc) {
  323. uni.chooseImage({
  324. count: 1,
  325. sizeType: ['compressed'],
  326. success: function(res) {
  327. const filePath = res.tempFilePaths[0];
  328. let token = uni.getStorageSync('MD_token') || ''
  329. uni.uploadFile({
  330. url: uni.baseUrl + 'api/upload/cloud',
  331. filePath,
  332. name: 'upload',
  333. formData: {
  334. 'token': token
  335. },
  336. success: (f) => {
  337. const cData = JSON.parse(f.data)
  338. if (cData.errno === 0) {
  339. if (bc && typeof(bc) === 'function') bc(cData.data)
  340. } else {
  341. uni.$msg(cData.errmsg || `未知错误-${cData.errno}`)
  342. }
  343. }
  344. })
  345. }
  346. })
  347. },
  348. // 选择、验证、上传正面照片
  349. uploadbrokerageImgImage() {
  350. this.uploadImgHandle((d) => {
  351. this.form.brokerage_img = d.url
  352. // this.brokerage_img = d.pub_url
  353. this.brokerage_img = d.url
  354. })
  355. },
  356. openDealAtPopoup () {
  357. console.log('成交日期成交日期')
  358. this.dealAtShow = true
  359. },
  360. dealAtChange (e) {
  361. this.form.deal_at = e.result || ''
  362. },
  363. openbirthdayPopoup () {
  364. this.birthdayShow = true
  365. },
  366. birthdayChange (e) {
  367. this.form.birthday = e.result || ''
  368. },
  369. // 选择所属项目回调
  370. propertySelectConfirm(e) {
  371. e.map((val, index) => {
  372. this.form.estate_id = val.value;
  373. this.form.estate_name = val.label;
  374. });
  375. },
  376. submitHandle() {
  377. const that = this
  378. this.$refs.uForm.validate(valid => {
  379. if (valid) {
  380. // 验证成功
  381. let apiStr = 'apitradeadd'
  382. let params = {
  383. deal_item: that.form.deal_item,
  384. house_no: that.form.house_no,
  385. house_type: that.form.house_type,
  386. deal_clerk: that.form.deal_clerk,
  387. deal_type: that.form.deal_type,
  388. store_type: that.form.store_type,
  389. deal_at: that.form.deal_at,
  390. customer_name: that.form.customer_name,
  391. customer_phone: that.form.customer_phone,
  392. price: that.form.price,
  393. area: that.form.area,
  394. report_dept: that.form.report_dept,
  395. discount: that.form.discount,
  396. brokerage: that.form.brokerage,
  397. rebate: that.form.rebate,
  398. brokerage_img: that.form.brokerage_img,
  399. birthday: that.form.birthday,
  400. remark: that.form.remark
  401. }
  402. if(that.isEdit) {
  403. apiStr = 'apitradeedit'
  404. params.id = that.form.id
  405. }
  406. uni.api.cust[apiStr](params).then(res => {
  407. if (that.isEdit) {
  408. uni.$msgConfirm('编辑成功', () => {
  409. uni.reLaunch({
  410. url: '/pages/trade/list'
  411. })
  412. }, () => {
  413. uni.reLaunch({
  414. url: '/pages/trade/list'
  415. })
  416. })
  417. } else {
  418. uni.$msgConfirm('添加成功,是否前往成交单列表?', () => {
  419. uni.reLaunch({
  420. url: '/pages/trade/list'
  421. })
  422. }, () => {
  423. const userInfo = uni.getStorageSync('MD_userInfo2')
  424. this.form = {
  425. deal_item: '',
  426. house_no: '',
  427. house_type: '1',
  428. deal_clerk: userInfo.nickname,
  429. deal_type: '1',
  430. store_type: '其它',
  431. deal_at: '',
  432. birthday: '',
  433. customer_name: '',
  434. customer_phone: '',
  435. area: '',
  436. price: '',
  437. report_dept: '',
  438. discount: '',
  439. brokerage: '',
  440. rebate: '',
  441. brokerage_img: null,
  442. remark: null
  443. }
  444. })
  445. }
  446. })
  447. } else {
  448. console.log('验证失败');
  449. }
  450. });
  451. },
  452. // 获取手机号
  453. getPhoneNumber: function(e) {
  454. // 点击获取手机号码按钮
  455. let _that = this;
  456. if (e.detail.errMsg == 'getPhoneNumber:fail user deny') {
  457. _that.$refs.uToast.show({
  458. title: '您可以在个人设置中再次绑定',
  459. type: 'warning'
  460. });
  461. setTimeout(() => {
  462. _that.reLunchUser();
  463. }, 1500);
  464. return; // 即用户拒绝授权
  465. }
  466. console.log(e.detail.errMsg);
  467. console.log(e.detail.iv);
  468. console.log(e.detail.encryptedData);
  469. let iv = e.detail.iv;
  470. let encryptedData = e.detail.encryptedData;
  471. // 不是登陆完第一时间授权
  472. wx.login({
  473. success(res) {
  474. if (res.code) {
  475. // 设置用户手机号
  476. _that.setUserPhoneNumber(encryptedData, iv, res.code);
  477. } else {
  478. this.$refs.uToast.show({
  479. title: res.errMsg,
  480. type: 'warning'
  481. });
  482. console.log('登录失败!' + res.errMsg);
  483. }
  484. }
  485. });
  486. },
  487. // 以下是工具函数
  488. // 关闭键盘
  489. hideKeyboard() {
  490. uni.hideKeyboard();
  491. },
  492. // 格式化日期的月份或天数的显示(小于10,在前面增加0)
  493. getFormatDate(value) {
  494. if (value == undefined || value == '') {
  495. return '';
  496. }
  497. var str = value;
  498. if (parseInt(value) < 10) {
  499. str = '0' + value;
  500. }
  501. return str;
  502. }
  503. }
  504. };
  505. </script>
  506. <style lang="scss">
  507. .page {
  508. padding: 20rpx;
  509. background-color: #ffffff;
  510. }
  511. .form {
  512. border-radius: 10rpx;
  513. padding: 0 40rpx;
  514. }
  515. .popup-body {
  516. box-sizing: border-box;
  517. .tips-title {
  518. font-size: $u-p;
  519. margin-bottom: 20rpx;
  520. }
  521. .tips-content {
  522. font-size: $u-p2;
  523. color: $u-tips-color;
  524. margin-bottom: 60rpx;
  525. }
  526. }
  527. .id_card {
  528. color: #606266;
  529. width: 100%;
  530. height: 350rpx;
  531. display: flex;
  532. flex-direction: column;
  533. align-items: center;
  534. justify-content: center;
  535. background-color: #f4f5f6;
  536. font-size: $u-p2;
  537. }
  538. .footer {
  539. position: absolute;
  540. text-align: center;
  541. bottom: 40rpx;
  542. font-size: $u-p2;
  543. .agreement {
  544. color: $u-type-error;
  545. }
  546. }
  547. .slot-content {
  548. font-size: 28rpx;
  549. color: $u-content-color;
  550. padding: 20rpx;
  551. }
  552. .scoped-input-floor {
  553. position: absolute;
  554. left: 0;
  555. top: 0;
  556. width: 100%;
  557. height: 100%;
  558. background: transparent;
  559. z-index: 9;
  560. }
  561. .scoped-input-label-tips {
  562. position: absolute;
  563. left: 0;
  564. bottom: -20rpx;
  565. color: #f00;
  566. }
  567. .scoped-cur-popup {
  568. position: relative;
  569. height: 100%;
  570. padding-bottom: 100rpx;
  571. .popup-body {
  572. box-sizing: border-box;
  573. border-bottom: 1PX solid #dcdcdc;
  574. }
  575. .scp-header-input {
  576. position: fixed;
  577. width: 90%;
  578. display: flex;
  579. border-bottom: 1PX solid #dcdcdc;
  580. .input {
  581. flex: 1;
  582. padding-left: 20rpx;
  583. height: 80rpx;
  584. .u-input__input {
  585. height: 80rpx;
  586. }
  587. }
  588. .b {
  589. width: 200rpx;
  590. height: 80rpx;
  591. line-height: 80rpx;
  592. background: #2d8cf0;
  593. color: #fff;
  594. text-align: center;
  595. margin-left: 20rpx;
  596. }
  597. }
  598. }
  599. .scoped-cust-list {
  600. .scl-item {
  601. border-bottom: 1PX solid #f2f2f2;
  602. padding: 20rpx 0;
  603. &.cur {
  604. background: #369af7;
  605. border-radius: 10rpx;
  606. .p1, .p2, .p3 {
  607. color: #fff;
  608. }
  609. }
  610. .p1 {
  611. font-size: 28rpx;
  612. color: #333;
  613. }
  614. .p2 {
  615. font-size: 28rpx;
  616. color: #666;
  617. .s {
  618. display: inline-block;
  619. }
  620. }
  621. .p3 {
  622. color: #999;
  623. font-size: 24rpx;
  624. }
  625. }
  626. }
  627. </style>