create.vue 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634
  1. <!--
  2. * @Author: liuzhenlin 461480418@qq.ocm
  3. * @Date: 2023-01-12 11:57:48
  4. * @LastEditors: liuzhenlin
  5. * @LastEditTime: 2023-03-27 16:19:53
  6. * @Description: file content
  7. * @FilePath: \oms\pages\project\create.vue
  8. -->
  9. <template>
  10. <view class="home">
  11. <view class="nav">
  12. <view :style="{ paddingTop }">
  13. <view class="title" :style="[{ height }, { lineHeight: height }]">
  14. <view class="back" @click="goBack()">
  15. <u-icon name="arrow-left" color="#ffffff" size="22"></u-icon>
  16. </view>
  17. <text>项目创建</text>
  18. </view>
  19. </view>
  20. </view>
  21. <view class="main">
  22. <u-form :model="addForm" :rules="rules" ref="addForm" label-width="0">
  23. <u-form-item prop="custName" borderBottom customStyle="padding:40rpx 0 30rpx">
  24. <view class="form-label flex_l">
  25. <view class="label-tag"></view>
  26. 关联客户
  27. </view>
  28. <u-input
  29. v-model="addForm.custName"
  30. disabled
  31. disabledColor="#ffffff"
  32. placeholder="请选择关联客户"
  33. border="none"></u-input>
  34. </u-form-item>
  35. <u-form-item prop="productLineVal" borderBottom customStyle="padding:40rpx 0 30rpx" @click="showLine = true">
  36. <view class="form-label flex_l">
  37. <view class="label-tag"></view>
  38. 产品线
  39. </view>
  40. <u-input
  41. :readonly="true"
  42. placeholder="请选择产品线"
  43. v-model="addForm.productLineVal"
  44. border="none"
  45. suffixIcon="arrow-down"
  46. suffixIconStyle="color:#CDCDCD"
  47. clearable
  48. customStyle="padding: 0 30rpx 0 12rpx"></u-input>
  49. </u-form-item>
  50. <u-form-item prop="nboName" borderBottom customStyle="padding:40rpx 0 30rpx">
  51. <view class="form-label flex_l">
  52. <view class="label-tag"></view>
  53. 项目名称
  54. </view>
  55. <u-input
  56. placeholder="输入项目名称"
  57. v-model="addForm.nboName"
  58. border="none"
  59. suffixIconStyle="color:#CDCDCD"
  60. clearable
  61. customStyle="padding: 0 30rpx 0 12rpx"></u-input>
  62. </u-form-item>
  63. <u-form-item prop="nboSourceVal" borderBottom customStyle="padding:40rpx 0 30rpx" @click="showNboSource = true">
  64. <view class="form-label flex_l">
  65. <view class="label-tag"></view>
  66. 项目来源
  67. </view>
  68. <u-input
  69. :readonly="true"
  70. placeholder="请选择项目来源"
  71. v-model="addForm.nboSourceVal"
  72. border="none"
  73. suffixIcon="arrow-down"
  74. suffixIconStyle="color:#CDCDCD"
  75. clearable
  76. customStyle="padding: 0 30rpx 0 12rpx"></u-input>
  77. </u-form-item>
  78. <u-form-item
  79. prop="bidInfo"
  80. borderBottom
  81. customStyle="padding:40rpx 0 30rpx"
  82. v-if="addForm.nboSource == 80"
  83. @click="$refs.bidRef.open()">
  84. <view class="form-label flex_l">
  85. <view class="label-tag"></view>
  86. 招标信息
  87. </view>
  88. <u-input
  89. v-model="addForm.bidInfo"
  90. disabled
  91. disabledColor="#ffffff"
  92. placeholder="招标信息"
  93. border="none"></u-input>
  94. <u-icon slot="right" name="arrow-right"></u-icon>
  95. </u-form-item>
  96. <u-form-item prop="saleName" borderBottom customStyle="padding:40rpx 0 30rpx" @click="$refs.user.open()">
  97. <view class="form-label flex_l">
  98. <view class="label-tag"></view>
  99. 销售工程师
  100. </view>
  101. <u-input
  102. :readonly="true"
  103. placeholder="请选择销售工程师"
  104. v-model="addForm.saleName"
  105. border="none"
  106. suffixIcon="arrow-down"
  107. suffixIconStyle="color:#CDCDCD"
  108. clearable
  109. customStyle="padding: 0 30rpx 0 12rpx"></u-input>
  110. </u-form-item>
  111. <u-form-item prop="salesVal" borderBottom customStyle="padding:40rpx 0 30rpx" @click="showModel = true">
  112. <view class="form-label flex_l">
  113. <view class="label-tag"></view>
  114. 销售模式
  115. </view>
  116. <u-input
  117. :readonly="true"
  118. placeholder="请选择销售模式"
  119. v-model="addForm.salesVal"
  120. border="none"
  121. suffixIcon="arrow-down"
  122. suffixIconStyle="color:#CDCDCD"
  123. clearable
  124. customStyle="padding: 0 30rpx 0 12rpx"></u-input>
  125. </u-form-item>
  126. <u-form-item
  127. borderBottom
  128. customStyle="padding:40rpx 0 30rpx"
  129. @click="$refs.dealer.open()"
  130. v-if="addForm.salesModel > 10">
  131. <view class="form-label flex_l">
  132. <view class="label-tag"></view>
  133. 经销商
  134. </view>
  135. <u-input
  136. :readonly="true"
  137. placeholder="请选择经销商"
  138. v-model="addForm.distributorName"
  139. border="none"
  140. suffixIcon="arrow-down"
  141. suffixIconStyle="color:#CDCDCD"
  142. clearable
  143. customStyle="padding: 0 30rpx 0 12rpx"></u-input>
  144. </u-form-item>
  145. <u-form-item prop="isBigVal" borderBottom customStyle="padding:40rpx 0 30rpx" @click="showLarge = true">
  146. <view class="form-label flex_l">
  147. <view class="label-tag"></view>
  148. 是否大项目
  149. </view>
  150. <u-input
  151. :readonly="true"
  152. placeholder="请选择是否大项目"
  153. v-model="addForm.isBigVal"
  154. border="none"
  155. suffixIcon="arrow-down"
  156. suffixIconStyle="color:#CDCDCD"
  157. clearable
  158. customStyle="padding: 0 30rpx 0 12rpx"></u-input>
  159. </u-form-item>
  160. <u-form-item prop="nboTypeVal" borderBottom customStyle="padding:40rpx 0 30rpx" @click="showNboType = true">
  161. <view class="form-label flex_l">
  162. <view class="label-tag"></view>
  163. 项目类别
  164. </view>
  165. <u-input
  166. :readonly="true"
  167. placeholder="请选择项目类别"
  168. v-model="addForm.nboTypeVal"
  169. border="none"
  170. suffixIcon="arrow-down"
  171. suffixIconStyle="color:#CDCDCD"
  172. clearable
  173. customStyle="padding: 0 30rpx 0 12rpx"></u-input>
  174. </u-form-item>
  175. <u-form-item borderBottom customStyle="padding:40rpx 0 30rpx">
  176. <view class="form-label flex_l">备注</view>
  177. <u-input
  178. placeholder="输入备注"
  179. v-model="addForm.remark"
  180. border="none"
  181. clearable
  182. customStyle="padding: 0 30rpx 0 12rpx"></u-input>
  183. </u-form-item>
  184. </u-form>
  185. <view class="center">
  186. <view class="handle-btn" @click="handleAdd">保存</view>
  187. </view>
  188. </view>
  189. <!-- 选择销售 -->
  190. <select-user
  191. ref="user"
  192. :query-params="{ roles: ['SalesEngineer', 'ProductLineManager'] }"
  193. @close="closeUser($event)"></select-user>
  194. <!-- 选择经销商 -->
  195. <select-dealer ref="dealer" @close="closeDealer($event)"></select-dealer>
  196. <!-- 选择招标信息 -->
  197. <select-bid ref="bidRef" :query-params="{ custId: addForm.custId }" @close="closeBid($event)"></select-bid>
  198. <!-- 项目来源 -->
  199. <u-picker
  200. :show="showNboSource"
  201. :columns="nboSourceColumns"
  202. keyName="value"
  203. @cancel="showNboSource = false"
  204. @confirm="pickSource"></u-picker>
  205. <!-- 产品线 -->
  206. <u-picker
  207. :show="showLine"
  208. :columns="productLineColumns"
  209. keyName="value"
  210. @cancel="showLine = false"
  211. @confirm="pickLine"></u-picker>
  212. <!-- 销售模式 -->
  213. <u-picker
  214. :show="showModel"
  215. :columns="salesModelColumns"
  216. keyName="value"
  217. @cancel="showModel = false"
  218. @confirm="pickModel"></u-picker>
  219. <!-- 大项目 -->
  220. <u-picker
  221. :show="showLarge"
  222. :columns="yesOrNoColumns"
  223. keyName="value"
  224. @cancel="showLarge = false"
  225. @confirm="pickLarge"></u-picker>
  226. <!-- 项目类别 -->
  227. <u-picker
  228. :show="showNboType"
  229. :columns="nboTypeColumns"
  230. keyName="value"
  231. @cancel="showNboType = false"
  232. @confirm="pickNboType"></u-picker>
  233. <u-notify ref="uNotify"></u-notify>
  234. <u-toast ref="uToast"></u-toast>
  235. </view>
  236. </template>
  237. <script>
  238. import { mapGetters } from 'vuex'
  239. import projectApi from 'api/project'
  240. import customerApi from '../../api/customer'
  241. import to from 'await-to-js'
  242. import SelectUser from 'components/SelectUser'
  243. import SelectDealer from 'components/SelectDealer'
  244. import SelectBid from 'components/SelectBid'
  245. export default {
  246. name: 'omsIndex',
  247. components: { SelectUser, SelectDealer, SelectBid },
  248. data() {
  249. return {
  250. flag: true,
  251. step: 1,
  252. height: '',
  253. paddingTop: '',
  254. showNboSource: false, //项目来源选择
  255. showModel: false, //销售模式选择
  256. showLine: false, //产品线选择
  257. showLarge: false, //是否是大项目选择
  258. showNboType: false, //项目类别
  259. nboSourceColumns: [], //项目来源
  260. salesModelColumns: [], //销售模式
  261. productLineColumns: [], //产品线
  262. yesOrNoColumns: [], //是否是大项目
  263. nboTypeColumns: [
  264. [
  265. { key: '30', value: 'C类' },
  266. { key: '50', value: '储备' },
  267. ],
  268. ],
  269. addForm: {
  270. nboName: '', //项目名称
  271. custId: '', //关联客户id
  272. custName: '', //关联客户
  273. nboSource: '', //项目来源
  274. nboSourceVal: '', //项目来源文字
  275. saleName: '', //销售工程师
  276. saleId: '', //销售工程师id
  277. salesModel: '', //销售模式(10直销20经销30代理)
  278. salesVal: '', //销售模式文字
  279. distributorId: null, //经销商/代理商ID
  280. distributorName: '', //经销商/代理商名称
  281. productLine: '', //产品线来源
  282. productLineVal: '', //产品线文字
  283. isBig: '', //是否是大项目
  284. isBigVal: '', //是否是大项目文字
  285. remark: '', //备注
  286. nboTypeVal: '', //项目类别
  287. nboType: '', //项目类别
  288. bidInfo: '', //招标标题
  289. bidId: null,
  290. },
  291. rules: {
  292. nboName: [{ required: true, trigger: ['blur', 'change'], message: '请输入项目名称' }],
  293. custName: [{ required: true, trigger: ['blur', 'change'], message: '请选择关联客户' }],
  294. nboSourceVal: [{ required: true, trigger: ['blur', 'change'], message: '请选择项目来源' }],
  295. saleName: [{ required: true, trigger: ['blur', 'change'], message: '请选择销售工程师' }],
  296. salesModelVal: [{ required: true, trigger: ['blur', 'change'], message: '请选择销售模式' }],
  297. distributorName: [{ required: true, trigger: ['blur', 'change'], message: '请选择经销商/代理商' }],
  298. isBigVal: [{ required: true, trigger: ['blur', 'change'], message: '请选择是否大项目' }],
  299. productLineVal: [{ required: true, trigger: ['blur', 'change'], message: '请选择产品线' }],
  300. nboTypeVal: [{ required: true, trigger: ['blur', 'change'], message: '请选择项目类别' }],
  301. // 跟进
  302. // followTime: [{ required: true, trigger: ['blur', 'change'], message: '请输入跟进时间' }],
  303. // followContent: [{ required: true, trigger: ['blur', 'change'], message: '请输入跟进内容' }],
  304. },
  305. productList: [],
  306. }
  307. },
  308. computed: {
  309. ...mapGetters(['userId', 'nickName']),
  310. },
  311. onLoad(option) {
  312. this.addForm.custId = parseInt(option.id)
  313. },
  314. created() {
  315. const navData = uni.getMenuButtonBoundingClientRect()
  316. this.height = navData.height + 'px'
  317. this.paddingTop = navData.top + 'px'
  318. },
  319. onShow() {
  320. if (this.addForm.custId) {
  321. this.getCustomerDetail()
  322. }
  323. this.getOptions()
  324. },
  325. methods: {
  326. getOptions() {
  327. Promise.all([
  328. this.getDicts('proj_nbo_source'),
  329. this.getDicts('proj_sales_model'),
  330. this.getDicts('sys_product_line'),
  331. this.getDicts('sys_yes_no'),
  332. ]).then(([nboSource, salesModel, productLine, yesOrNo]) => {
  333. this.nboSourceColumns = [nboSource.data.values] || []
  334. this.salesModelColumns = [salesModel.data.values] || []
  335. this.productLineColumns = [productLine.data.values] || []
  336. this.yesOrNoColumns = [yesOrNo.data.values] || []
  337. })
  338. },
  339. async getCustomerDetail() {
  340. const [err, res] = await to(customerApi.getDetail({ ids: [this.addForm.custId] }))
  341. if (err) return
  342. if (res && res.code == 200) {
  343. this.addForm.custName = res.data.list[0].custName
  344. }
  345. },
  346. // 打开主要联系人
  347. openContactUser() {
  348. if (!this.addForm.custId) {
  349. this.$refs.uNotify.show({
  350. top: this.height + this.paddingTop + 10,
  351. type: 'warning',
  352. message: '请先选择客户',
  353. duration: 1000 * 3,
  354. })
  355. } else {
  356. this.$refs.contact.open(this.addForm.custId)
  357. }
  358. },
  359. // 关闭选择客户
  360. closeCust(user) {
  361. if (user) {
  362. this.addForm.custId = user.id
  363. this.addForm.custName = user.name
  364. this.addForm.nboName = user.name + this.addForm.productLineVal
  365. }
  366. },
  367. // 经销商
  368. closeDealer(dealer) {
  369. if (dealer) {
  370. this.addForm.distributorId = dealer.id
  371. this.addForm.distributorName = dealer.name
  372. }
  373. },
  374. // 关闭选择销售
  375. closeUser(user) {
  376. if (user) {
  377. this.addForm.saleId = user.id
  378. this.addForm.saleName = user.label
  379. }
  380. },
  381. // 全部用户
  382. closeAllUser(user) {
  383. if (user) {
  384. this.addForm.followUserId = user.id
  385. this.addForm.followUserName = user.label
  386. }
  387. },
  388. closeProduct(product) {
  389. this.productList = [...product]
  390. },
  391. // 关闭选择招标信息的回调
  392. closeBid(bid) {
  393. console.log('bid', bid)
  394. this.addForm.bidInfo = bid.title
  395. this.addForm.bidId = bid.id
  396. },
  397. removeProductItem(idx) {
  398. this.productList.splice(idx, 1)
  399. },
  400. // 选择来源
  401. pickSource(e) {
  402. this.addForm.nboSource = e.value[0].key
  403. this.addForm.nboSourceVal = e.value[0].value
  404. this.showNboSource = false
  405. },
  406. // 选择产品线
  407. pickLine(e) {
  408. this.addForm.productLine = e.value[0].key
  409. this.addForm.productLineVal = e.value[0].value
  410. this.addForm.nboName = this.addForm.custName + this.addForm.productLineVal
  411. this.showLine = false
  412. },
  413. // 选择销售类型
  414. pickModel(e) {
  415. this.addForm.salesModel = e.value[0].key
  416. this.addForm.salesVal = e.value[0].value
  417. if (e.value[0].key == '10') {
  418. this.distributorId = null
  419. this.distributorName = ''
  420. }
  421. this.showModel = false
  422. },
  423. // 是否大项目
  424. pickLarge(e) {
  425. this.addForm.isBig = e.value[0].key
  426. this.addForm.isBigVal = e.value[0].value
  427. this.showLarge = false
  428. },
  429. // 项目类别
  430. pickNboType(e) {
  431. this.addForm.nboType = e.value[0].key
  432. this.addForm.nboTypeVal = e.value[0].value
  433. this.showNboType = false
  434. },
  435. nextStep() {
  436. if (this.step == 1) {
  437. this.$refs.addForm
  438. .validate()
  439. .then(async () => {
  440. this.step++
  441. })
  442. .catch((err) => {
  443. this.$refs.uNotify.show({
  444. top: this.height + this.paddingTop + 10,
  445. type: 'warning',
  446. message: err[0].message,
  447. duration: 1000 * 3,
  448. })
  449. })
  450. } else if (this.step == 2) {
  451. if (this.productList.length == 0) {
  452. this.$refs.uNotify.show({
  453. top: this.height + this.paddingTop + 10,
  454. type: 'warning',
  455. message: '请选择产品',
  456. duration: 1000 * 3,
  457. })
  458. return
  459. }
  460. this.step++
  461. }
  462. },
  463. previousStep() {
  464. if (this.step > 1) {
  465. this.step--
  466. }
  467. },
  468. handleAdd() {
  469. this.$refs.addForm
  470. .validate()
  471. .then(async () => {
  472. if (!this.flag) return
  473. this.$refs.addForm
  474. .validate()
  475. .then(async () => {
  476. this.flag = false
  477. let params = this.addForm
  478. const [err, res] = await to(projectApi.create(params))
  479. this.flag = true
  480. if (err) return
  481. if (res && res.code == 200) {
  482. this.$refs.uToast.show({
  483. type: 'success',
  484. message: '创建成功',
  485. complete: () => {
  486. this.goBack()
  487. },
  488. })
  489. }
  490. })
  491. .catch((err) => {
  492. this.$refs.uNotify.show({
  493. top: this.height + this.paddingTop + 10,
  494. type: 'warning',
  495. message: err[0].message,
  496. duration: 1000 * 3,
  497. })
  498. })
  499. })
  500. .catch((err) => {
  501. this.$refs.uNotify.show({
  502. top: this.height + this.paddingTop + 10,
  503. type: 'warning',
  504. message: err[0].message,
  505. duration: 1000 * 3,
  506. })
  507. })
  508. },
  509. goBack() {
  510. uni.navigateBack({
  511. //关闭当前页面,返回上一页面或多级页面。
  512. delta: 1,
  513. })
  514. },
  515. },
  516. }
  517. </script>
  518. <style>
  519. page {
  520. background: #f2f3f5;
  521. }
  522. </style>
  523. <style lang="scss" scoped>
  524. .home {
  525. padding-top: 188rpx;
  526. .nav {
  527. position: absolute;
  528. left: 0;
  529. top: 0;
  530. width: 100%;
  531. height: 284rpx;
  532. background: #3c9cff;
  533. .title {
  534. position: relative;
  535. text-align: center;
  536. font-size: 32rpx;
  537. font-weight: bold;
  538. color: #ffffff;
  539. .back {
  540. position: absolute;
  541. top: 0;
  542. bottom: 0;
  543. margin: auto;
  544. left: 70rpx;
  545. display: flex;
  546. }
  547. }
  548. }
  549. .main {
  550. position: absolute;
  551. width: 100%;
  552. height: calc(100vh - 188rpx);
  553. background: #ffffff;
  554. box-shadow: 0 6rpx 19rpx 2rpx rgba(0, 45, 132, 0.15);
  555. border-radius: 31rpx 31rpx 0 0;
  556. padding: 0 32rpx;
  557. overflow: auto;
  558. padding-bottom: 64rpx;
  559. .step-tit {
  560. text-align: center;
  561. line-height: 60rpx;
  562. font-size: 26rpx;
  563. color: #000;
  564. }
  565. .form-label {
  566. font-size: 32rpx;
  567. font-weight: bold;
  568. color: #323232;
  569. padding-bottom: 18rpx;
  570. .label-tag {
  571. width: 15rpx;
  572. height: 15rpx;
  573. background: #ff4d4f;
  574. border-radius: 50%;
  575. margin-right: 10rpx;
  576. }
  577. }
  578. .handle-btn {
  579. width: 234rpx;
  580. height: 92rpx;
  581. background: #3c9cff;
  582. border-radius: 31rpx;
  583. margin: 30rpx auto 0;
  584. font-size: 32rpx;
  585. color: #ffffff;
  586. text-align: center;
  587. line-height: 92rpx;
  588. }
  589. }
  590. .step1 {
  591. width: 100%;
  592. height: calc(100% - 124rpx);
  593. overflow: auto;
  594. }
  595. .step2 {
  596. width: 100%;
  597. height: calc(100% - 124rpx);
  598. .product-wrap {
  599. width: 100%;
  600. margin-top: 30rpx;
  601. height: calc(100% - 150rpx);
  602. overflow: auto;
  603. padding: 0 10rpx;
  604. .product-item {
  605. margin: 30rpx 0;
  606. padding: 20rpx;
  607. border-radius: 10px;
  608. box-shadow: 0 6rpx 19rpx 2rpx rgba(0, 45, 132, 0.15);
  609. .product-label {
  610. padding: 20rpx 0 20rpx 20rpx;
  611. }
  612. }
  613. }
  614. .margin20 {
  615. font-weight: bold;
  616. margin: 10px 20px;
  617. }
  618. .add-btn {
  619. color: #fff;
  620. width: 120rpx;
  621. height: 60rpx;
  622. padding: 0rpx 8rpx;
  623. font-size: 12rpx;
  624. background: #3c9cff;
  625. border-radius: 3px;
  626. text-align: center;
  627. line-height: 58rpx;
  628. font-size: 44rpx;
  629. }
  630. }
  631. }
  632. </style>