follow.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513
  1. <!--
  2. * @Author: liuzhenlin 461480418@qq.ocm
  3. * @Date: 2023-01-12 11:57:48
  4. * @LastEditors: liuzhenlin
  5. * @LastEditTime: 2023-05-22 17:37:35
  6. * @Description: file content
  7. * @FilePath: \oms\pages\publicPages\follow.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="content" customStyle="padding:40rpx 0 34rpx">
  24. <view class="form-label flex_l">
  25. <view class="label-tag"></view>
  26. 本次跟进进展
  27. </view>
  28. <u-textarea
  29. v-model="addForm.content"
  30. placeholder="请输入本次跟进进展"
  31. maxlength="800"
  32. height="190rpx"
  33. count
  34. customStyle="border-radius:16rpx"></u-textarea>
  35. </u-form-item>
  36. <u-form-item prop="furtherPlan" customStyle="padding:40rpx 0 34rpx">
  37. <view class="form-label flex_l">
  38. <view class="label-tag"></view>
  39. 下一步跟进计划和目标
  40. </view>
  41. <u-textarea
  42. v-model="addForm.furtherPlan"
  43. placeholder="请输入下一步跟进计划和目标"
  44. maxlength="800"
  45. height="190rpx"
  46. count
  47. customStyle="border-radius:16rpx"></u-textarea>
  48. </u-form-item>
  49. <u-form-item prop="date" borderBottom customStyle="padding:40rpx 0 30rpx" @click="showDate = true">
  50. <view class="form-label flex_l">
  51. <view class="label-tag"></view>
  52. 跟进时间
  53. </view>
  54. <u-input
  55. :readonly="true"
  56. placeholder="请选择跟进时间"
  57. v-model="addForm.date"
  58. border="none"
  59. suffixIcon="arrow-down"
  60. suffixIconStyle="color:#CDCDCD"
  61. clearable
  62. customStyle="padding: 0 30rpx 0 12rpx"></u-input>
  63. </u-form-item>
  64. <u-form-item prop="mode" borderBottom customStyle="padding:40rpx 0 30rpx" @click="showMode = true">
  65. <view class="form-label flex_l">
  66. <view class="label-tag"></view>
  67. 跟进方式
  68. </view>
  69. <u-input
  70. :readonly="true"
  71. placeholder="请选择跟进方式"
  72. v-model="addForm.mode"
  73. border="none"
  74. suffixIcon="arrow-down"
  75. suffixIconStyle="color:#CDCDCD"
  76. clearable
  77. customStyle="padding: 0 30rpx 0 12rpx"></u-input>
  78. </u-form-item>
  79. <u-form-item prop="contactsName" borderBottom customStyle="padding:40rpx 0 30rpx" @click="open">
  80. <view class="form-label flex_l">
  81. <view class="label-tag"></view>
  82. 联系人
  83. </view>
  84. <u-input
  85. :readonly="true"
  86. placeholder="请选择联系人"
  87. v-model="addForm.contactsName"
  88. border="none"
  89. suffixIcon="arrow-down"
  90. suffixIconStyle="color:#CDCDCD"
  91. clearable
  92. customStyle="padding: 0 30rpx 0 12rpx"></u-input>
  93. </u-form-item>
  94. </u-form>
  95. <view class="upload-file-box">
  96. <view class="form-label flex_l">附件</view>
  97. <uni-file-picker file-mediatype="all" v-model="imageValue" mode="grid" @select="select" ref="upload" limit="1">
  98. <view class="upload-btn">
  99. <u-icon name="plus-circle-fill" color="blue" size="28"></u-icon>
  100. </view>
  101. </uni-file-picker>
  102. </view>
  103. <view class="save" @click="handleAdd" :class="!flag ? 'disabledBtn' : ''">保存</view>
  104. <!-- 选择跟进方式 -->
  105. <u-picker
  106. :show="showMode"
  107. :columns="modeColumns"
  108. keyName="label"
  109. @cancel="showMode = false"
  110. @confirm="pickMode"></u-picker>
  111. <!-- 选择下次时间 -->
  112. <u-datetime-picker
  113. v-if="showDate"
  114. :maxDate="maxDate"
  115. :show="showDate"
  116. mode="datetime"
  117. v-model="addForm.date"
  118. @cancel="showDate = false"
  119. @confirm="pickDate"></u-datetime-picker>
  120. </view>
  121. <u-notify ref="uNotify"></u-notify>
  122. <u-toast ref="uToast"></u-toast>
  123. <!-- 客户联系人 -->
  124. <customer-contact ref="concat" @close="closeConcat"></customer-contact>
  125. <!-- 项目联系人 -->
  126. <project-contact ref="projectConcat" @close="closeConcat"></project-contact>
  127. <!-- 经销商代理商联系人 -->
  128. <distr-contact ref="distrConcat" @close="closeConcat" :distrType="targetType"></distr-contact>
  129. </view>
  130. </template>
  131. <script>
  132. // import { mapGetters } from 'vuex'
  133. import to from 'await-to-js'
  134. import followApi from '../../api/follow'
  135. import distrApi from '../../api/base/distr'
  136. import custApi from '../../api/customer'
  137. import prodApi from '../../api/project'
  138. import bidApi from '../../api/bid'
  139. import ProjectContact from '@/components/ProjectContact'
  140. import CustomerContact from '@/components/CustomerContact'
  141. import DistrContact from '@/components/DistrContact'
  142. export default {
  143. name: 'omsIndex',
  144. components: {
  145. CustomerContact,
  146. ProjectContact,
  147. DistrContact,
  148. },
  149. data() {
  150. return {
  151. flag: true,
  152. imageValue: [],
  153. height: '',
  154. paddingTop: '',
  155. showMode: false, //选择行业
  156. showDate: false,
  157. maxDate: new Date() * 1,
  158. modeColumns: [
  159. [
  160. {
  161. label: '电话',
  162. id: '10',
  163. },
  164. {
  165. label: '邮件',
  166. id: '20',
  167. },
  168. {
  169. label: '拜访',
  170. id: '30',
  171. },
  172. ],
  173. ],
  174. addForm: {
  175. files: [],
  176. date: this.parseTime(new Date(), '{y}-{m}-{d}'), //时间
  177. content: '', //客户姓名
  178. furtherPlan: '', //下一步跟进计划
  179. mode: '', //跟进方式
  180. modeId: 0,
  181. fileName: '', //附件
  182. contactsName: '', //联系人
  183. contactsId: 0, //联系人ID
  184. },
  185. targetType: 0, //跟进对象类型(10客户,20项目,30合同,40回款,50经销商,50代理商)
  186. rules: {
  187. furtherPlan: {
  188. type: 'string',
  189. required: true,
  190. message: '请填写下一步跟进计划和目标',
  191. trigger: ['blur'],
  192. },
  193. content: {
  194. type: 'string',
  195. required: true,
  196. message: '请填写跟进内容',
  197. trigger: ['blur'],
  198. },
  199. date: {
  200. type: 'string',
  201. required: true,
  202. message: '请填写跟进时间',
  203. trigger: ['blur'],
  204. },
  205. mode: {
  206. type: 'string',
  207. required: true,
  208. message: '请选择跟进方式',
  209. trigger: ['blur', 'change'],
  210. },
  211. contactsName: {
  212. type: 'string',
  213. required: true,
  214. message: '请选择联系人',
  215. trigger: ['blur', 'change'],
  216. },
  217. },
  218. details: {},
  219. curId: 0,
  220. }
  221. },
  222. computed: {
  223. // ...mapGetters(['details']),
  224. },
  225. onLoad(option) {
  226. this.targetType = option.targetType
  227. this.curId = parseInt(option.id)
  228. },
  229. created() {
  230. const navData = uni.getMenuButtonBoundingClientRect()
  231. this.height = navData.height + 'px'
  232. this.paddingTop = navData.top + 'px'
  233. },
  234. mounted() {
  235. this.initData()
  236. },
  237. methods: {
  238. // 获取客户/项目信息
  239. async initData() {
  240. if (this.targetType == '10') {
  241. //客户
  242. const [err, res] = await to(
  243. custApi.getDetail({
  244. ids: [this.curId],
  245. })
  246. )
  247. if (err) return
  248. if (res && res.code == 200) {
  249. this.details = res.data.list[0]
  250. }
  251. } else if (this.targetType == '20') {
  252. //项目
  253. const [err, res] = await to(
  254. prodApi.getDetail({
  255. id: this.curId,
  256. })
  257. )
  258. if (err) return
  259. if (res && res.code == 200) {
  260. this.details = res.data
  261. }
  262. } else if (this.targetType == '50') {
  263. // 经销商代理商
  264. const [err, res] = await to(distrApi.getEntity({ id: this.curId }))
  265. if (err) return
  266. if (res && res.code == 200) {
  267. this.details = res.data.list
  268. }
  269. } else if (this.targetType == '60') {
  270. // 招标信息
  271. const [err, res] = await to(bidApi.get({ id: this.curId }))
  272. if (err) return
  273. if (res && res.code == 200) {
  274. this.details = res.data
  275. }
  276. }
  277. },
  278. // 打开联系人
  279. open() {
  280. if (this.targetType == '10') {
  281. this.$refs.concat.open(this.details.id)
  282. } else if (this.targetType == '20') {
  283. this.$refs.projectConcat.open(this.details.id, this.details.custId)
  284. } else if (this.targetType == '50') {
  285. this.$refs.distrConcat.open(this.details.id)
  286. } else if (this.targetType == '60') {
  287. this.$refs.concat.open(this.details.custId)
  288. }
  289. },
  290. // 行业选择
  291. pickMode(e) {
  292. this.addForm.modeId = e.value[0].id
  293. this.addForm.mode = e.value[0].label
  294. this.showMode = false
  295. },
  296. async pickDate(e) {
  297. this.showDate = false
  298. const timeFormat = uni.$u.timeFormat
  299. let timeValue = await timeFormat(e.value, 'yyyy-mm-dd hh:MM')
  300. this.addForm.date = timeValue
  301. },
  302. // 关闭选择用户
  303. closeConcat(user) {
  304. if (user) {
  305. if (this.targetType == '50') {
  306. this.addForm.contactsName = user.name
  307. this.addForm.contactsId = user.id
  308. } else {
  309. this.addForm.contactsName = user.label
  310. this.addForm.contactsId = user.id
  311. }
  312. }
  313. },
  314. handleAdd() {
  315. if (!this.flag) return
  316. this.$refs.addForm
  317. .validate()
  318. .then(async () => {
  319. let idParams = {}
  320. if (this.targetType == '10') {
  321. idParams = {
  322. custId: this.details.id,
  323. custName: this.details.custName,
  324. targetId: this.details.id,
  325. targetName: this.details.custName,
  326. }
  327. } else if (this.targetType == '20') {
  328. idParams = {
  329. custId: this.details.custId,
  330. custName: this.details.custName,
  331. targetId: this.details.id,
  332. targetName: this.details.nboName,
  333. }
  334. } else if (this.targetType == '50') {
  335. idParams = {
  336. targetId: this.details.id,
  337. targetName: this.details.distName,
  338. }
  339. } else if (this.targetType == '60') {
  340. idParams = {
  341. targetId: this.details.id,
  342. targetName: this.details.title,
  343. }
  344. }
  345. let params = Object.assign(
  346. {
  347. contactsId: this.addForm.contactsId,
  348. contactsName: this.addForm.contactsName,
  349. followContent: this.addForm.content,
  350. followDate: this.addForm.date,
  351. followType: this.addForm.modeId,
  352. targetType: this.targetType,
  353. furtherPlan: this.addForm.furtherPlan,
  354. files: this.addForm.files,
  355. },
  356. idParams
  357. )
  358. this.flag = false
  359. const [err, res] = await to(followApi.createFollow(params))
  360. this.flag = true
  361. if (err) return
  362. if (res && res.code == 200) {
  363. this.$refs.uToast.show({
  364. type: 'success',
  365. message: '创建成功',
  366. complete: () => {
  367. uni.navigateBack({
  368. //关闭当前页面,返回上一页面或多级页面。
  369. delta: 1,
  370. })
  371. },
  372. })
  373. }
  374. })
  375. .catch((err) => {
  376. this.$refs.uNotify.show({
  377. top: this.height + this.paddingTop + 10,
  378. type: 'warning',
  379. message: err[0].message,
  380. duration: 1000 * 3,
  381. })
  382. })
  383. },
  384. // // 选择上传触发函数
  385. select(e) {
  386. let url = process.uniEnv.VUE_APP_UPLOAD_WEED
  387. uni.request({
  388. url, //仅为示例,并非真实接口地址。
  389. success: (res) => {
  390. this.uploadFiles(e, res.data)
  391. },
  392. })
  393. },
  394. // 上传函数
  395. async uploadFiles(e, res) {
  396. let action = process.uniEnv.VUE_APP_PROTOCOL + res.publicUrl + '/' + res.fid
  397. uni.uploadFile({
  398. url: action,
  399. filePath: e.tempFilePaths[0],
  400. name: 'file',
  401. formData: {
  402. file: e.tempFiles[0].file,
  403. },
  404. success: (res) => {
  405. this.$refs.uToast.show({
  406. type: 'success',
  407. message: '附件上传成功',
  408. })
  409. this.addForm.files = [
  410. {
  411. fileName: e.tempFiles[0].file.name,
  412. fileUrl: action,
  413. },
  414. ]
  415. },
  416. fail: (err) => {},
  417. })
  418. },
  419. goBack() {
  420. uni.navigateBack({
  421. //关闭当前页面,返回上一页面或多级页面。
  422. delta: 1,
  423. })
  424. },
  425. },
  426. }
  427. </script>
  428. <style>
  429. page {
  430. background: #f2f3f5;
  431. }
  432. </style>
  433. <style lang="scss" scoped>
  434. .home {
  435. padding-top: 188rpx;
  436. .nav {
  437. position: absolute;
  438. left: 0;
  439. top: 0;
  440. width: 100%;
  441. height: 284rpx;
  442. background: #3e7ef8;
  443. .title {
  444. position: relative;
  445. text-align: center;
  446. font-size: 32rpx;
  447. font-weight: bold;
  448. color: #ffffff;
  449. .back {
  450. position: absolute;
  451. top: 0;
  452. bottom: 0;
  453. margin: auto;
  454. left: 70rpx;
  455. display: flex;
  456. }
  457. }
  458. }
  459. .main {
  460. position: absolute;
  461. width: 100%;
  462. height: calc(100vh - 188rpx);
  463. background: #ffffff;
  464. box-shadow: 0 6rpx 19rpx 2rpx rgba(0, 45, 132, 0.15);
  465. border-radius: 31rpx 31rpx 0 0;
  466. padding: 0 32rpx;
  467. overflow: auto;
  468. padding-bottom: 64rpx;
  469. .form-label {
  470. font-size: 32rpx;
  471. font-weight: bold;
  472. color: #323232;
  473. padding-bottom: 18rpx;
  474. .label-tag {
  475. width: 15rpx;
  476. height: 15rpx;
  477. background: #ff4d4f;
  478. border-radius: 50%;
  479. margin-right: 10rpx;
  480. }
  481. }
  482. .upload-file-box {
  483. padding: 20rpx 0;
  484. position: relative;
  485. .upload-btn {
  486. position: absolute;
  487. right: 0;
  488. top: 26rpx;
  489. }
  490. }
  491. }
  492. .save {
  493. width: 569rpx;
  494. height: 92rpx;
  495. background: #3e7ef8;
  496. border-radius: 31rpx;
  497. margin: 116rpx auto 0;
  498. font-size: 32rpx;
  499. color: #ffffff;
  500. text-align: center;
  501. line-height: 92rpx;
  502. }
  503. }
  504. </style>