addVisit.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  1. <template>
  2. <div class="addVisit">
  3. <m-header v-if="statusList.headerStatus" :name="name" />
  4. <van-cell-group>
  5. <van-field label="回访老师" v-model="teacherName" readonly input-align="right" placeholder="请选择" />
  6. </van-cell-group>
  7. <van-cell-group>
  8. <van-field label="学员姓名" @click="onCheckStudent" v-model="studentName" readonly input-align="right" :is-link="id ? false : true" placeholder="请选择" />
  9. <van-field label="回访类型" @click="onChange('type')" v-model="form.type" readonly input-align="right" :is-link="id ? false : true" placeholder="请选择" />
  10. <van-field label="回访目的" @click="onChange('purpose')" v-model="form.purpose" readonly input-align="right" :is-link="id ? false : true" placeholder="请选择" />
  11. </van-cell-group>
  12. <van-cell-group>
  13. <van-field label="当前学生情况" class="textarea" :readonly="id ? true : false" v-model="form.overview" rows="2" autosize type="textarea" maxlength="50" placeholder="请输入留言" :show-word-limit="id ? false : true" />
  14. </van-cell-group>
  15. <van-cell-group>
  16. <van-field label="沟通后家长反馈" class="textarea" :readonly="id ? true : false" v-model="form.feedback" rows="2" autosize type="textarea" maxlength="50" placeholder="请输入留言" :show-word-limit="id ? false : true" />
  17. </van-cell-group>
  18. <van-cell-group>
  19. <van-field label="回访时间" v-model="form.visitTime" readonly @click="onEnListShow" input-align="right" :is-link="id ? false : true" placeholder="请选择" />
  20. </van-cell-group>
  21. <div class="button-group" v-if="!id">
  22. <van-button type="primary" @click="onSubmit" round size="large">确认</van-button>
  23. </div>
  24. <van-action-sheet v-model="visit.status" :actions="visit.data" cancel-text="取消" @cancel="visit.status = false" @select="onModeSelect" />
  25. <van-popup v-model="dataForm.status" position="bottom">
  26. <van-datetime-picker v-model="dataForm.currentDate" type="date" :min-date="dataForm.minDate" :max-date="dataForm.maxDate" :formatter="formatter" @cancel="dataForm.status = false" @confirm="onCurrentConfirm" />
  27. </van-popup>
  28. <!-- 选择上课学生 -->
  29. <van-popup v-model="statusList.studentStatus" :lock-scroll="true" position="bottom" :style="{ height: '180%' }">
  30. <van-sticky>
  31. <van-search show-action shape="round" @search="onSearch" v-model="params.search" placeholder="请输入学生名或手机号">
  32. <template #action>
  33. <div @click="onSearch">搜索</div>
  34. </template>
  35. </van-search>
  36. </van-sticky>
  37. <div class="paddingB80">
  38. <van-list v-model="loading" class="studentContainer" v-if="dataShow" key="data" :finished="finished" finished-text="" @load="getStudent">
  39. <van-radio-group v-model="radioSelect">
  40. <van-cell-group>
  41. <van-cell v-for="(item, index) in dataList" :key="index" @click="onCheckboxSelect(item)" class="input-cell" :center="true">
  42. <template slot="icon">
  43. <img class="logo" v-if="item.avatar" :src="item.avatar" alt="">
  44. <img class="logo" v-else src="@/assets/images/icon_student.png" alt="">
  45. </template>
  46. <template slot="title">
  47. {{ item.userName }}
  48. </template>
  49. <template slot="label">
  50. <span>{{ desensitPhone(item.phone) }}</span>
  51. </template>
  52. <template slot="default">
  53. <van-radio :name="item.userId"></van-radio>
  54. </template>
  55. </van-cell>
  56. </van-cell-group>
  57. </van-radio-group>
  58. </van-list>
  59. <m-empty class="empty" v-else key="data" />
  60. </div>
  61. <div class="button-group-popup">
  62. <span class="btn" @click="onPopupCancel">取消</span>
  63. <span class="btn primary" @click="onPopupSubmit">确定</span>
  64. </div>
  65. </van-popup>
  66. </div>
  67. </template>
  68. <script>
  69. import MHeader from '@/components/MHeader'
  70. import { browser } from '@/common/common'
  71. import MEmpty from '@/components/MEmpty'
  72. import dayjs from 'dayjs'
  73. import { queryStudentsWithTeacher, visitAdd, visitGetInfo } from '@/api/teacher'
  74. import { queryUserInfo } from '@/api/app'
  75. import setLoading from '@/utils/loading'
  76. export default {
  77. name: 'addVisit',
  78. components: {
  79. MHeader,
  80. MEmpty
  81. },
  82. data() {
  83. const query = this.$route.query
  84. return {
  85. id: query.id,
  86. name: query.name,
  87. dataForm: { // 时间下拉框
  88. status: false,
  89. minDate: new Date(2000, 0, 1),
  90. maxDate: new Date(),
  91. currentDate: new Date()
  92. },
  93. statusList: { // 散状态集合
  94. headerStatus: true, // 头部是否展示
  95. studentStatus: false, // 上课学生状态
  96. },
  97. typeList: [{name: "课程推荐"}, {name: "常规回访"}, {name: "其它"}],
  98. visit: {
  99. status: false,
  100. type: null,
  101. data: []
  102. },
  103. studentName: null,
  104. teacherName: null,
  105. form: {
  106. teacherId: null,
  107. studentId: null,
  108. type: null,
  109. purpose: null,
  110. overview: null,
  111. feedback: null,
  112. visitTime: null,
  113. visiterType: 'TEACHER'
  114. },
  115. loading: false,
  116. finished: false,
  117. params: {
  118. search: null,
  119. page: 1,
  120. rows: 20
  121. },
  122. dataShow: true, // 是否有数据
  123. radioSelect: null,
  124. radioSelectName: null,
  125. clickStatus: false,
  126. dataList: []
  127. }
  128. },
  129. mounted() {
  130. let params = this.$route.query
  131. if (params.Authorization) {
  132. localStorage.setItem('Authorization', decodeURI(params.Authorization))
  133. localStorage.setItem('userInfo', decodeURI(params.Authorization))
  134. }
  135. if (browser().android || browser().iPhone) {
  136. this.statusList.headerStatus = false
  137. }
  138. document.title = this.name
  139. this.__init()
  140. },
  141. methods: {
  142. async __init() {
  143. let res = await queryUserInfo()
  144. let result = res.data
  145. if(res.status == 200) {
  146. this.teacherName = result.realName
  147. this.form.teacherId = result.id
  148. } else {
  149. this.$toast(res.msg)
  150. }
  151. if(this.id) {
  152. setLoading(true)
  153. let queryInfo = await visitGetInfo({ id: this.id })
  154. const queryResult = queryInfo.data
  155. let form = this.form
  156. setLoading(false)
  157. if(queryResult.code == 200) {
  158. let tempData = queryResult.data
  159. this.studentName = tempData.studentName
  160. form.studentId = tempData.studentId
  161. form.type = tempData.type
  162. form.purpose = tempData.purpose
  163. form.overview = tempData.overview
  164. form.feedback = tempData.feedback
  165. form.visitTime = dayjs(tempData.visitTime).format('YYYY-MM-DD')
  166. form.visiterType = tempData.visiterType
  167. } else {
  168. this.$toast(res.msg)
  169. }
  170. }
  171. },
  172. async onSubmit() {
  173. const form = this.form
  174. if(!form.studentId) {
  175. this.$toast('请选择学员')
  176. return
  177. } else if(!form.type) {
  178. this.$toast('请选择回访类型')
  179. return
  180. } else if(!form.purpose) {
  181. this.$toast('请选择回访目的')
  182. return
  183. } else if(!form.overview) {
  184. this.$toast('请输入当前学生情况')
  185. return
  186. } else if(!form.feedback) {
  187. this.$toast('请输入沟通后家长反馈')
  188. return
  189. } else if(!form.visitTime) {
  190. this.$toast('请选择回访时间')
  191. return
  192. }
  193. this.clickStatus = true
  194. setLoading(true)
  195. let res = await visitAdd(form)
  196. let result = res.data
  197. setLoading(false)
  198. if(result.code == 200) {
  199. this.$toast('添加成功')
  200. this.$router.push('visitList')
  201. } else {
  202. this.$toast(result.msg)
  203. this.clickStatus = false
  204. return
  205. }
  206. },
  207. onCheckStudent() {
  208. if(this.id) {
  209. return
  210. }
  211. this.statusList.studentStatus = true
  212. },
  213. onChange(type) {
  214. if(this.id) {
  215. return
  216. }
  217. let visit = this.visit
  218. let form = this.form
  219. if(type == 'type') {
  220. visit.data = this.typeList
  221. } else if(type == 'purpose') {
  222. if(form.type == '其它') {
  223. visit.data = [{name: '其它'}]
  224. } else if(form.type == '课程推荐') {
  225. visit.data = [{name: '新课推荐'}, {name: '续费提醒'}]
  226. } else if(form.type == '常规回访') {
  227. visit.data = [{name: '课后及作业回访'}, {name: '练习及乐团表现'}]
  228. } else {
  229. this.$toast('请选择回访类型')
  230. return
  231. }
  232. }
  233. visit.status = true
  234. visit.type = type
  235. },
  236. onSearch() {
  237. this.params.page = 1
  238. this.dataList = []
  239. this.dataShow = true
  240. this.loading = true
  241. this.finished = false
  242. this.getStudent()
  243. },
  244. onCheckboxSelect(item) {
  245. this.radioSelect = item.userId
  246. this.radioSelectName = item.userName
  247. },
  248. onPopupCancel () {
  249. this.statusList.studentStatus = false
  250. },
  251. onPopupSubmit() {
  252. this.form.studentId = this.radioSelect
  253. this.studentName = this.radioSelectName
  254. this.statusList.studentStatus = false
  255. },
  256. onCurrentConfirm(value) {
  257. if(value) {
  258. this.form.visitTime = dayjs(value).format('YYYY-MM-DD')
  259. }
  260. this.dataForm.status = false
  261. },
  262. onEnListShow() {
  263. if(this.id) {
  264. return
  265. }
  266. this.dataForm.status = true
  267. },
  268. getStudent() {
  269. let params = this.params
  270. queryStudentsWithTeacher(params).then(res => {
  271. let result = res.data
  272. this.loading = false
  273. if (result.code == 200) {
  274. params.page = result.data.pageNo
  275. this.dataList = this.dataList.concat(result.data.rows)
  276. if (params.page >= result.data.totalPage) {
  277. this.finished = true
  278. }
  279. this.params.page++
  280. } else {
  281. this.finished = true
  282. }
  283. // 判断是否有数据
  284. if (this.dataList.length <= 0) {
  285. this.dataShow = false
  286. }
  287. })
  288. },
  289. onModeSelect(value) {
  290. let visit = this.visit
  291. let form = this.form
  292. if(visit.type == 'type') {
  293. form.type = value.name
  294. form.purpose = null
  295. } else if(visit.type == 'purpose') {
  296. form.purpose = value.name
  297. }
  298. visit.status = false
  299. },
  300. formatter(type, value) {
  301. if (type === 'year') {
  302. return `${value}年`;
  303. } else if (type === 'month') {
  304. return `${value}月`
  305. } else if (type === 'day') {
  306. return `${value}日`
  307. }
  308. return value;
  309. },
  310. desensitPhone(phone) { // 手机号脱敏
  311. let first = phone.substr(0, 3)
  312. let last = phone.substr(-4)
  313. return first + '****' + last
  314. }
  315. }
  316. }
  317. </script>
  318. <style lang='less' scoped>
  319. @import url("../../assets/commonLess/variable.less");
  320. .addVisit {
  321. min-height: 100vh;
  322. }
  323. .vip-title {
  324. padding: .06rem 0 .04rem;
  325. font-size: .12rem;
  326. color: @mFontColor;
  327. text-align: center;
  328. }
  329. /deep/.van-cell-group {
  330. margin-bottom: .1rem;
  331. }
  332. /deep/.van-cell {
  333. display: flex;
  334. align-items: center;
  335. font-size: .16rem;
  336. line-height: .26rem;
  337. }
  338. /deep/.van-field__label,
  339. /deep/.van-cell__value {
  340. flex: 1 auto;
  341. }
  342. /deep/.van-field__word-limit {
  343. margin-top: 0px;
  344. position: absolute;
  345. top: -0.2rem;
  346. right: 5px;
  347. font-size: .14rem;
  348. }
  349. /deep/.van-field__control:disabled {
  350. color: #6a6969;
  351. }
  352. .textarea {
  353. display: flex;
  354. flex-direction: column;
  355. align-items: inherit;
  356. /deep/.van-field__label {
  357. width: 100%;
  358. }
  359. // /deep/.van-field__value {
  360. // border: 1px solid #ccc;
  361. // }
  362. }
  363. .button-group {
  364. margin: .3rem .26rem .2rem;
  365. .van-button--primary {
  366. background: @mColor;
  367. font-size: .18rem;
  368. }
  369. }
  370. .studentContainer {
  371. /deep/.van-cell__title {
  372. font-size: .14rem;
  373. color: @mFontColor;
  374. flex: 1 auto;
  375. }
  376. .logo {
  377. width: .35rem;
  378. height: .35rem;
  379. margin-right: .12rem;
  380. border-radius: 100%;
  381. }
  382. .input-cell {
  383. padding: .12rem .16rem .2rem;
  384. .van-radio {
  385. justify-content: flex-end;
  386. }
  387. }
  388. /deep/.van-cell__value {
  389. height: .2rem;
  390. }
  391. /deep/.van-radio__icon .van-icon {
  392. border-color: @sFontColor;
  393. }
  394. /deep/.van-radio__icon--checked {
  395. .van-icon {
  396. border-color: @orangeColor;
  397. background: @orangeColor;
  398. }
  399. }
  400. .van-tag {
  401. margin-left: .08rem;
  402. }
  403. }
  404. .paddingB80 {
  405. padding-bottom: .8rem
  406. }
  407. .button-group-popup {
  408. position: fixed;
  409. bottom: 0;
  410. padding: 0.2rem 0;
  411. width: 100%;
  412. text-align: center;
  413. background-color: #FFFFFF;
  414. .btn {
  415. padding: 0 0.45rem;
  416. line-height: 0.4rem;
  417. display: inline-block;
  418. border: 1px solid @mColor;
  419. border-radius: 1rem;
  420. color: @mColor;
  421. background: #fff;
  422. font-size: 0.18rem;
  423. &.primary {
  424. color: #fff;
  425. background: @mColor;
  426. }
  427. }
  428. .btn+.btn {
  429. margin-left: 0.1rem;
  430. }
  431. }
  432. .studentColor {
  433. color: #14928A;
  434. }
  435. </style>