detail.vue 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800
  1. <template>
  2. <view class="container">
  3. <!-- 车牌号区域 -->
  4. <view class="box">
  5. <view class="left">车牌号</view>
  6. <view class="right2">
  7. <view class="item">
  8. <view :class="['select', form.selectValue != 0 ? 'selected' : '']" @tap="handleMultiple(form.selectIndex)">
  9. {{ form.selectValue != 0 ? form.selectValue : '请选择' }}
  10. </view>
  11. </view>
  12. <view class="right-img"><img src="../../static/bottom.png" /></view>
  13. </view>
  14. <!-- 车牌号选项弹窗区域 -->
  15. <transition>
  16. <multiple-picker
  17. title="请选择"
  18. :show="selectMultiple.show"
  19. :columns="selectMultiple.columns"
  20. :defaultIndex="selectMultiple.index"
  21. @confirm="confirmMultiple"
  22. @cancel="selectMultiple.show = false"
  23. @change="changeMultiple"
  24. ></multiple-picker>
  25. </transition>
  26. </view>
  27. <!-- 人数区域 -->
  28. <view class="box">
  29. <view class="left">容量</view>
  30. <view class="right">{{ info.contain }}</view>
  31. </view>
  32. <!-- 发车日期区域 -->
  33. <view class="box">
  34. <view class="left">发车日期</view>
  35. <view class="right">{{ info.yy_date }}</view>
  36. </view>
  37. <!-- 发车时间区域 -->
  38. <view class="box">
  39. <view class="left">发车时间</view>
  40. <picker style="width: 40%;" @change="bindPickerChange($event, 1)" mode="time" :value="info.ci_time" :start="getCurrentTime()">
  41. <view :class="['right', info.ci_time != 0 ? '' : 'unSelect']">
  42. {{ info.ci_time != 0 ? info.ci_time : '请选择' }}
  43. <view class="right-img"><img src="../../static/bottom.png" /></view>
  44. </view>
  45. </picker>
  46. </view>
  47. <!-- 扫码开始时间区域 -->
  48. <view class="box">
  49. <view class="left">扫码开始时间</view>
  50. <picker style="width: 40%;" @change="bindPickerChange($event, 4)" mode="time" :value="info.sm_start">
  51. <view :class="['right', info.sm_start != 0 ? '' : 'unSelect']">
  52. {{ info.sm_start != 0 ? info.sm_start : '请选择' }}
  53. <view class="right-img"><img src="../../static/bottom.png" /></view>
  54. </view>
  55. </picker>
  56. </view>
  57. <!-- 扫码结束时间区域 -->
  58. <view class="box">
  59. <view class="left">扫码结束时间</view>
  60. <picker style="width: 40%;" @change="bindPickerChange($event, 5)" mode="time" :value="info.sm_end">
  61. <view :class="['right', info.sm_end != 0 ? '' : 'unSelect']">
  62. {{ info.sm_end != 0 ? info.sm_end : '请选择' }}
  63. <view class="right-img"><img src="../../static/bottom.png" /></view>
  64. </view>
  65. </picker>
  66. </view>
  67. <!-- 预约截止时间区域 -->
  68. <view class="box">
  69. <view class="left">预约截止时间</view>
  70. <picker style="width: 40%;" @change="bindPickerChange($event, 7)" mode="time" :value="info.yy_end">
  71. <view :class="['right', info.yy_end != 0 ? '' : 'unSelect']">
  72. {{ info.yy_end != 0 ? info.yy_end : '请选择' }}
  73. <view class="right-img"><img src="../../static/bottom.png" /></view>
  74. </view>
  75. </picker>
  76. </view>
  77. <!-- 路线区域 -->
  78. <view class="box">
  79. <view class="left">路线</view>
  80. <picker style="width: 60%;" @change="bindPickerChange($event, 2)" :range="pathList" range-key="route">
  81. <view :class="['right', info.route ? '' : 'unSelect']">
  82. {{ info.route ? info.route : '请选择' }}
  83. <view class="right-img"><img src="../../static/bottom.png" /></view>
  84. </view>
  85. </picker>
  86. </view>
  87. <!-- 站点区域 -->
  88. <view class="box">
  89. <view class="left">站点</view>
  90. <picker style="width: 80%;" @change="bindPickerChange($event, 3)" :range="endList" range-key="route_end">
  91. <view :class="['right', info.route_end ? '' : 'unSelect']">
  92. {{ info.route_end ? info.route_end : '请选择' }}
  93. <view class="right-img"><img src="../../static/bottom.png" /></view>
  94. </view>
  95. </picker>
  96. </view>
  97. <!-- 状态区域 -->
  98. <view class="box">
  99. <view class="left">状态</view>
  100. <view class="right">{{ info.state_str }}</view>
  101. </view>
  102. <!-- 提前一天预约区域 -->
  103. <view class="box">
  104. <view class="left">可否提前一天预约</view>
  105. <view class="right">{{ info.before_state == 0 ? '不可以' : '可以' }}</view>
  106. </view>
  107. <!-- 保存按钮区域 -->
  108. <view class="saveBtn" @click="handleSave">保存</view>
  109. <!-- 人员名单区域 -->
  110. <view class="list">
  111. <!-- 标题区域 -->
  112. <view class="list-title" v-if="info.user_num != 0">人员名单({{ listData.length }}人)</view>
  113. <!-- 筛选区域 -->
  114. <view class="list-search" v-if="info.user_num !== '0'">
  115. <!-- 身份筛选区域 -->
  116. <picker style="width: 50%;" :range="statusList" range-key="text" @change="bindPickerChange($event, 6)">
  117. <view class="list-search-item">
  118. {{ statusList[result_status].text }}
  119. <view class="right-img"><img src="../../static/bottom.png" /></view>
  120. </view>
  121. </picker>
  122. <!-- 上车状态筛选区域 -->
  123. <picker style="width: 50%;" :range="typeList" range-key="text" @change="bindPickerChange($event, 8)">
  124. <view class="list-search-item2">
  125. {{ typeList[result_state].text }}
  126. <view class="right-img"><img src="../../static/bottom.png" /></view>
  127. </view>
  128. </picker>
  129. </view>
  130. <view class="list-item" v-for="(item, index) in listData" :key="index">
  131. <view class="item-img"><img src="../../static/man.png" /></view>
  132. <view class="item-info">
  133. <view class="info-name">
  134. <view>{{ item.user_name }}</view>
  135. </view>
  136. <view class="info-mes">
  137. {{ item.user_zz }}
  138. <span>{{ item.yy_time }}</span>
  139. </view>
  140. </view>
  141. <view v-if="item.yy_state === '1'" class="item-type"><img src="../../static/subscribe.png" /></view>
  142. <view v-else class="item-type"><img src="../../static/pass2.png" /></view>
  143. </view>
  144. <!-- 无数据时展示的区域 -->
  145. <view class="list-nodata" v-if="listData.length == 0">
  146. <img src="../../static/no-bus.png" />
  147. <view>暂无数据</view>
  148. </view>
  149. </view>
  150. </view>
  151. </template>
  152. <script setup>
  153. import { ref } from 'vue'
  154. import { onLoad } from '@dcloudio/uni-app'
  155. import { myRequest } from '@/util/api.js'
  156. import { isWeixin } from '@/util/isWeixin.js'
  157. import { filterIdentity } from '@/util/filterIdentity.js'
  158. import { time_to_sec, time_change } from '@/util/formatTime.js'
  159. onLoad(options => {
  160. if (isWeixin()) {
  161. filterIdentity()
  162. info.value = JSON.parse(options.info)
  163. // console.log(info.value)
  164. idRef.value = info.value.id
  165. // 获取人员列表
  166. getData()
  167. // 获取路线数组
  168. getPathList()
  169. // 获取终点站列表
  170. getEndList()
  171. // 获取车牌号列表
  172. getBusList()
  173. // 获取发车时间提前推迟多少分钟可以扫码数据
  174. getTimeConfig()
  175. // 处理车牌号数据
  176. form.value.selectValue = info.value.car_number
  177. setTimeout(() => {
  178. let temList = []
  179. selectMultiple.value.columns.forEach(item => {
  180. if (item.label == form.value.selectValue) {
  181. temList.push(item.value)
  182. }
  183. })
  184. form.value.selectIndex = temList
  185. }, 500)
  186. // let userInfo = JSON.parse(uni.getStorageSync('bus-userInfo'))
  187. // // console.log(userInfo)
  188. // if (userInfo.user_zz !== '车队长') {
  189. // uni.redirectTo({
  190. // url: '/pages/404/404?message=暂无权限'
  191. // })
  192. // } else {
  193. // info.value = JSON.parse(options.info)
  194. // // console.log(info.value)
  195. // idRef.value = info.value.id
  196. // // 获取人员列表
  197. // getData()
  198. // // 获取路线数组
  199. // getPathList()
  200. // // 获取终点站列表
  201. // getEndList()
  202. // // 获取车牌号列表
  203. // getBusList()
  204. // // 获取发车时间提前推迟多少分钟可以扫码数据
  205. // getTimeConfig()
  206. // // 处理车牌号数据
  207. // form.value.selectValue = info.value.car_number
  208. // setTimeout(() => {
  209. // let temList = []
  210. // selectMultiple.value.columns.forEach(item => {
  211. // if (item.label == form.value.selectValue) {
  212. // temList.push(item.value)
  213. // }
  214. // })
  215. // form.value.selectIndex = temList
  216. // }, 500)
  217. // }
  218. } else {
  219. uni.redirectTo({
  220. url: '/pages/404/404?message=请在微信客户端打开链接'
  221. })
  222. }
  223. })
  224. // 带过来的预约详情数据
  225. const info = ref({})
  226. // 参数id
  227. const idRef = ref(null)
  228. // 车牌号绑定数据
  229. const form = ref({
  230. selectValue: '',
  231. selectIndex: []
  232. })
  233. // 车牌号数组相关数据
  234. const selectMultiple = ref({
  235. show: false,
  236. index: [],
  237. columns: []
  238. })
  239. // 路线数组
  240. const pathList = ref([])
  241. // 终点站数组
  242. const endList = ref([])
  243. // 人员列表数组
  244. const listData = ref([])
  245. // 发车时间提前多少分钟可以扫码
  246. const time_early = ref(null)
  247. // 发车时间推迟多少分钟可以扫码
  248. const time_late = ref(null)
  249. // 发车前多少分钟截止预约
  250. const time_yy_end = ref(null)
  251. // 人员名单上车状态
  252. const result_state = ref(0)
  253. const typeList = ref([
  254. {
  255. text: '全部',
  256. value: 0
  257. },
  258. {
  259. text: '已预约未上车',
  260. value: 1
  261. },
  262. {
  263. text: '已上车',
  264. value: 2
  265. }
  266. ])
  267. // 人员名单身份类型
  268. const result_status = ref(0)
  269. const statusList = ref([
  270. {
  271. text: '全部',
  272. value: 0
  273. },
  274. {
  275. text: '教师',
  276. value: 1
  277. },
  278. {
  279. text: '临时人员',
  280. value: 2
  281. }
  282. ])
  283. // 获取路线数组请求
  284. const getPathList = async () => {
  285. const res = await myRequest({
  286. url: '/appqueryRoute.action'
  287. })
  288. // console.log(res);
  289. pathList.value = res.data
  290. }
  291. // 获取终点站数组请求
  292. const getEndList = async () => {
  293. const res = await myRequest({
  294. url: '/appqueryEndRoutes.action',
  295. data: {
  296. route: info.value.route
  297. }
  298. })
  299. // console.log(res);
  300. endList.value = res.data
  301. }
  302. // 获取车牌号数组请求
  303. const getBusList = async () => {
  304. const res = await myRequest({
  305. url: '/appqueryCarInfos.action'
  306. })
  307. // console.log(res);
  308. if (res.data.length) {
  309. let temList = []
  310. res.data.forEach((item, index) => {
  311. temList.push({
  312. label: item.car_number,
  313. value: index.toString()
  314. })
  315. })
  316. selectMultiple.value.columns = temList
  317. }
  318. }
  319. // 获取人员名单请求
  320. const getData = async () => {
  321. const res = await myRequest({
  322. url: '/appqueryAppointeds.action',
  323. data: {
  324. id: idRef.value,
  325. result_state: result_state.value,
  326. userzz_state: result_status.value
  327. }
  328. })
  329. // console.log(res)
  330. listData.value = res.data
  331. }
  332. // 保存按钮回调
  333. const handleSave = () => {
  334. if (info.value.car_number == 0) {
  335. uni.showToast({
  336. title: '请选择车牌号',
  337. icon: 'none'
  338. })
  339. return
  340. }
  341. if (info.value.ci_time == 0) {
  342. uni.showToast({
  343. title: '请选择发车时间',
  344. icon: 'none'
  345. })
  346. return
  347. }
  348. if (!info.value.sm_start) {
  349. uni.showToast({
  350. title: '请选择扫码开始时间',
  351. icon: 'none'
  352. })
  353. return
  354. }
  355. if (!info.value.sm_end) {
  356. uni.showToast({
  357. title: '请选择扫码结束时间',
  358. icon: 'none'
  359. })
  360. return
  361. }
  362. if (time_to_sec(info.value.sm_start) >= time_to_sec(info.value.ci_time)) {
  363. uni.showToast({
  364. title: '扫码开始时间不能晚于发车时间',
  365. icon: 'none',
  366. duration: 2000
  367. })
  368. return
  369. }
  370. if (time_to_sec(info.value.sm_end) < time_to_sec(info.value.ci_time)) {
  371. uni.showToast({
  372. title: '扫码结束时间不能早于发车时间',
  373. icon: 'none',
  374. duration: 2000
  375. })
  376. return
  377. }
  378. if (!info.value.yy_end) {
  379. uni.showToast({
  380. title: '请选择预约截止时间',
  381. icon: 'none'
  382. })
  383. return
  384. }
  385. if (!info.value.route) {
  386. uni.showToast({
  387. title: '请选择路线',
  388. icon: 'none'
  389. })
  390. return
  391. }
  392. if (!info.value.route_end) {
  393. uni.showToast({
  394. title: '请选择终点站',
  395. icon: 'none'
  396. })
  397. return
  398. }
  399. uni.showModal({
  400. title: '提示',
  401. content: '确定保存吗?',
  402. success: res => {
  403. if (res.confirm) {
  404. handleSaveRequest()
  405. } else if (res.cancel) {
  406. }
  407. }
  408. })
  409. }
  410. // 保存请求
  411. const handleSaveRequest = () => {
  412. // console.log(info.value)
  413. const { id, car_number, ci_time, route, route_end, contain, sm_start, sm_end, yy_end } = info.value
  414. const { user_name } = JSON.parse(uni.getStorageSync('bus-userInfo'))
  415. uni.request({
  416. url: '/carstop/carbook/scheupdate.action',
  417. method: 'post',
  418. header: {
  419. admin_name: user_name
  420. },
  421. data: {
  422. id,
  423. car_number,
  424. ci_time,
  425. route,
  426. route_end,
  427. contain,
  428. sm_start,
  429. sm_end,
  430. yy_end
  431. },
  432. success: res => {
  433. if (res.data.code == 200) {
  434. uni.showToast({
  435. title: res.data.message
  436. })
  437. setTimeout(() => {
  438. uni.redirectTo({
  439. url: '/pages/record/record'
  440. })
  441. }, 1500)
  442. } else {
  443. uni.showToast({
  444. title: res.data.message,
  445. icon: 'error'
  446. })
  447. }
  448. }
  449. })
  450. }
  451. // 点击车牌号下拉框回调
  452. const handleMultiple = val => {
  453. // console.log(val);
  454. selectMultiple.value.index = val || []
  455. selectMultiple.value.show = true
  456. }
  457. // 车牌号下拉框确定按钮回调
  458. const confirmMultiple = e => {
  459. // console.log(e);
  460. // console.log(e.value);
  461. if (selectMultiple.value.index != e.value) {
  462. let temp = []
  463. e.selected.forEach(item => {
  464. temp.push(item.label)
  465. })
  466. form.value.selectValue = temp.toString()
  467. info.value.car_number = temp.toString()
  468. }
  469. form.value.selectIndex = e.value
  470. selectMultiple.value.show = false
  471. // 获取汽车容量
  472. getBusContain()
  473. }
  474. // 获取汽车容量请求
  475. const getBusContain = async () => {
  476. const res = await myRequest({
  477. url: '/appqueryCarContain.action',
  478. data: {
  479. car_number: form.value.selectValue
  480. }
  481. })
  482. // console.log(res);
  483. info.value.contain = res.data
  484. }
  485. // 获取发车时间提前推迟多少分钟可以扫码数据
  486. const getTimeConfig = async () => {
  487. const res = await myRequest({
  488. url: '/cnqueryHb.action'
  489. })
  490. // console.log(res)
  491. time_early.value = res.sm_end
  492. time_late.value = res.sm_start
  493. time_yy_end.value = res.yy_end
  494. }
  495. // 下拉框选择时的回调
  496. const changeMultiple = e => {
  497. // console.log(e);
  498. }
  499. // 原生下拉框的选择回调事件
  500. const bindPickerChange = (e, type) => {
  501. if (type === 1) {
  502. info.value.ci_time = e.detail.value
  503. info.value.sm_start = time_change(info.value.ci_time, time_early.value * -1)
  504. info.value.sm_end = time_change(info.value.ci_time, time_late.value)
  505. info.value.yy_end = time_change(info.value.ci_time, time_yy_end.value * -1)
  506. } else if (type === 2) {
  507. info.value.route = pathList.value[e.detail.value].route
  508. getEndList()
  509. info.value.route_end = ''
  510. } else if (type === 3) {
  511. info.value.route_end = endList.value[e.detail.value].route_end
  512. } else if (type === 4) {
  513. info.value.sm_start = e.detail.value
  514. } else if (type === 5) {
  515. info.value.sm_end = e.detail.value
  516. } else if (type === 6) {
  517. result_status.value = e.detail.value
  518. getData()
  519. } else if (type === 7) {
  520. info.value.yy_end = e.detail.value
  521. } else if (type === 8) {
  522. result_state.value = e.detail.value
  523. getData()
  524. }
  525. }
  526. // 获取当前时间 hh:mm
  527. const getCurrentTime = () => {
  528. const date = new Date()
  529. let H = (date.getHours() + '').padStart(2, '0')
  530. let M = (date.getMinutes() + '').padStart(2, '0')
  531. return `${H}:${M}`
  532. }
  533. </script>
  534. <style lang="scss" scoped>
  535. .container {
  536. background-color: #fff;
  537. .box {
  538. display: flex;
  539. justify-content: space-between;
  540. align-items: center;
  541. padding: 0 30rpx;
  542. height: 98rpx;
  543. font-size: 28rpx;
  544. border-bottom: 1rpx solid #e6e6e6;
  545. .left {
  546. flex: 1;
  547. color: #999999;
  548. }
  549. .right {
  550. flex: 1;
  551. display: flex;
  552. justify-content: flex-end;
  553. .right-img {
  554. margin-left: 27rpx;
  555. margin-top: -5rpx;
  556. width: 17rpx;
  557. height: 12rpx;
  558. img {
  559. width: 100%;
  560. height: 100%;
  561. }
  562. }
  563. }
  564. .right2 {
  565. flex: 2;
  566. display: flex;
  567. justify-content: flex-end;
  568. align-items: center;
  569. .item {
  570. flex: 1;
  571. padding: 20rpx 0;
  572. .select {
  573. width: 100%;
  574. padding-top: 6px;
  575. padding-bottom: 6px;
  576. padding-left: 9px;
  577. border-radius: 4px;
  578. font-size: 15px;
  579. text-align: end;
  580. box-sizing: border-box;
  581. color: #cccccc;
  582. line-height: 26px;
  583. &.selected {
  584. color: black;
  585. }
  586. }
  587. }
  588. .right-img {
  589. margin-left: 27rpx;
  590. margin-top: -30rpx;
  591. width: 17rpx;
  592. height: 12rpx;
  593. img {
  594. width: 100%;
  595. height: 100%;
  596. }
  597. }
  598. }
  599. .unSelect {
  600. color: #ccc;
  601. }
  602. }
  603. .saveBtn {
  604. margin: 20rpx 30rpx;
  605. line-height: 100rpx;
  606. text-align: center;
  607. color: #fff;
  608. font-size: 34rpx;
  609. border-radius: 15rpx;
  610. background: linear-gradient(180deg, #8684ff 0%, #3c50e8 100%);
  611. }
  612. .list {
  613. padding: 13rpx 30rpx;
  614. .list-title {
  615. display: flex;
  616. margin-top: 20rpx;
  617. height: 41rpx;
  618. color: #999999;
  619. font-size: 28rpx;
  620. }
  621. .list-search {
  622. display: flex;
  623. padding: 20rpx 0;
  624. .list-search-item,
  625. .list-search-item2 {
  626. flex: 1;
  627. display: flex;
  628. justify-content: flex-start;
  629. .right-img {
  630. margin-left: 27rpx;
  631. margin-top: -5rpx;
  632. width: 17rpx;
  633. height: 12rpx;
  634. img {
  635. width: 100%;
  636. height: 100%;
  637. }
  638. }
  639. }
  640. .list-search-item2 {
  641. justify-content: flex-end;
  642. }
  643. }
  644. .list-item {
  645. display: flex;
  646. align-items: center;
  647. box-sizing: border-box;
  648. padding: 29rpx 0 26rpx 0;
  649. height: 155rpx;
  650. border-bottom: 1rpx solid #e6e6e6;
  651. .item-img {
  652. width: 100rpx;
  653. height: 100rpx;
  654. border-radius: 50%;
  655. img {
  656. width: 100%;
  657. height: 100%;
  658. }
  659. }
  660. .item-info {
  661. flex: 1;
  662. display: flex;
  663. flex-direction: column;
  664. justify-content: space-evenly;
  665. margin-left: 6rpx;
  666. height: 100rpx;
  667. .info-name {
  668. display: flex;
  669. align-items: center;
  670. font-size: 32rpx;
  671. .info-name-img {
  672. margin-left: 26rpx;
  673. width: 30rpx;
  674. height: 35rpx;
  675. img {
  676. width: 100%;
  677. height: 100%;
  678. }
  679. }
  680. }
  681. .info-mes {
  682. font-size: 24rpx;
  683. color: #999999;
  684. span {
  685. margin-left: 26rpx;
  686. color: #a6a6a6;
  687. }
  688. }
  689. }
  690. .item-type {
  691. width: 104rpx;
  692. height: 41rpx;
  693. img {
  694. width: 100%;
  695. height: 100%;
  696. }
  697. }
  698. }
  699. .list-nodata {
  700. padding: 50rpx 0;
  701. background-color: #fff;
  702. text-align: center;
  703. color: #999999;
  704. img {
  705. width: 500rpx;
  706. }
  707. }
  708. }
  709. }
  710. .v-enter-active,
  711. .v-leave-active {
  712. transition: opacity 0.5s ease;
  713. }
  714. .v-enter-from,
  715. .v-leave-to {
  716. opacity: 0;
  717. }
  718. </style>