task-card.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448
  1. <template>
  2. <view class="task-card">
  3. <view @click="handleClick">
  4. <view class="task-card__header">
  5. <view class="task-card__title">{{dataSource.task_type}}</view>
  6. <view class="task-card__name">处理人:{{dataSource.operator_user}}</view>
  7. </view>
  8. <view class="task-card__content">
  9. <view class="content__header">
  10. <view class="content__title">{{dataSource.start_time}} → {{dataSource.last_time}}</view>
  11. <view class="content__tag" v-if="dataSource.task_status!=='已完成'"
  12. :class="{warn:dataSource.is_overdue}">
  13. {{dataSource.is_overdue?`已逾期${dataSource.diff_day || 0}天`:`距离结束${dataSource.diff_day||0}天`}}
  14. </view>
  15. <view class="content__tag warn" v-if="dataSource.task_status==='已完成' && dataSource.is_overdue">
  16. {{dataSource.is_overdue&&`已逾期${dataSource.diff_day || 0}天`}}
  17. </view>
  18. </view>
  19. <view class="content__desc">
  20. {{dataSource.tesk_msg}}
  21. </view>
  22. </view>
  23. </view>
  24. <view class="task-card__actions" :class="{'flex-end':dataSource.task_status === '待处理'}" v-if="type==='action'">
  25. <view class="start-btn" v-if="dataSource.task_status === '待处理'">
  26. <u-button text="接收任务" size="mini" type="primary" @click="handleReceiveClick"></u-button>
  27. </view>
  28. <view class="actions__list" :class="{'border-none':dataSource.task_status === '已完成'}"
  29. v-if="dataSource.task_status !== '待处理'">
  30. <view class="actions__item middle">
  31. <view class="actions__icon">
  32. <image src="@/static/image/task/icon/progress.png" mode="aspectFit" class="img"></image>
  33. </view>
  34. <view class="actions__text">{{dataSource.clock_in_count||0}}次</view>
  35. </view>
  36. <view class="actions__item middle">
  37. <view class="actions__icon">
  38. <image src="@/static/image/task/icon/tool.png" mode="aspectFit" class="img"></image>
  39. </view>
  40. <view class="actions__text">
  41. <u-tooltip :zIndex="8" :showCopy="false" :overlay="false" size="12" :color="'#1B76FF'"
  42. :text="meter(dataSource.walk_length) "
  43. :buttons="[meter(dataSource.walk_length) ]"></u-tooltip>
  44. <!-- {{dataSource.walk_length | meter}} -->
  45. </view>
  46. </view>
  47. <view class="actions__item middle">
  48. <view class="actions__icon">
  49. <image src="@/static/image/task/icon/area.png" mode="aspectFit" class="img"></image>
  50. </view>
  51. <view class="actions__text">
  52. <u-tooltip :zIndex="8" :showCopy="false" :overlay="false" size="12" :color="'#1B76FF'"
  53. :text="numberFixed(dataSource.walk_area) + '㎡'"
  54. :buttons="[numberFixed(dataSource.walk_area) + '㎡']"></u-tooltip>
  55. </view>
  56. </view>
  57. </view>
  58. <template v-if="dataSource.task_status === '处理中'">
  59. <view class="actions__btns">
  60. <view class="actions__btn blocked" v-if="dataSource.walk_status === TASK_WALK_TYPE.IS_READY"
  61. @click="handleBtnClick(TASK_ACTION_TYPE.START)">
  62. <view class="actions__btn-icon">
  63. <image src="@/static/image/task/icon/play.svg" mode="aspectFit" class="img"></image>
  64. </view>
  65. <view class="actions__btn-text">开始</view>
  66. </view>
  67. <template v-else>
  68. <view class="actions__btn" @click="handleBtnClick(TASK_ACTION_TYPE.PAUSE)"
  69. v-if="dataSource.walk_status === TASK_WALK_TYPE.IS_RECORDING">
  70. <view class="actions__btn-icon">
  71. <image src="@/static/image/task/icon/pause.svg" mode="aspectFit" class="img">
  72. </image>
  73. </view>
  74. <view class="actions__btn-text">暂停</view>
  75. </view>
  76. <view class="actions__btn" @click="handleBtnClick(TASK_ACTION_TYPE.RESTART)"
  77. v-if="dataSource.walk_status === TASK_WALK_TYPE.IS_PAUSED">
  78. <view class="actions__btn-icon">
  79. <image src="@/static/image/task/icon/play.svg" mode="aspectFit" class="img">
  80. </image>
  81. </view>
  82. <view class="actions__btn-text">重新开始</view>
  83. </view>
  84. <view class="actions__btn" @click="handleBtnClick(TASK_ACTION_TYPE.CLOCK)">
  85. <view class="actions__btn-icon">
  86. <image src="@/static/image/task/icon/clockin.svg" mode="aspectFit" class="img">
  87. </image>
  88. </view>
  89. <view class="actions__btn-text">打卡</view>
  90. </view>
  91. <view class="actions__btn" @click="handleBtnClick(TASK_ACTION_TYPE.FINISHED)">
  92. <view class="actions__btn-icon">
  93. <image src="@/static/image/task/icon/finished.svg" mode="aspectFit" class="img">
  94. </image>
  95. </view>
  96. <view class="actions__btn-text">填报</view>
  97. </view>
  98. </template>
  99. </view>
  100. <view class="actions__tips" v-if="dataSource.walk_status === TASK_WALK_TYPE.IS_RECORDING">
  101. (任务轨迹监测中,如需暂停请点击暂停任务…)</view>
  102. </template>
  103. </view>
  104. <view class="task-card__footer" v-else>
  105. <view class="task-card__decoration-title">
  106. 任务派发人:{{dataSource.owner_user}}
  107. </view>
  108. <view class="task-card__decoration-title">
  109. 任务监督人:{{dataSource.supervisor_user}}
  110. </view>
  111. </view>
  112. </view>
  113. </template>
  114. <script>
  115. import {
  116. TASK_ACTION_TYPE,
  117. TASK_WALK_TYPE
  118. } from '@/util/constants.js';
  119. export default {
  120. props: {
  121. type: {
  122. type: String,
  123. default: 'action'
  124. },
  125. status: {
  126. type: Number,
  127. default: 1
  128. },
  129. dataSource: {
  130. type: Object,
  131. default: () => ({})
  132. }
  133. },
  134. data() {
  135. return {
  136. TASK_ACTION_TYPE,
  137. TASK_WALK_TYPE
  138. }
  139. },
  140. filters: {
  141. numberFixed: function(val) {
  142. if(!val){
  143. return 0
  144. }
  145. return Number(val) ? Number(val).toFixed(2) : (val || 0)
  146. },
  147. meter: function(val) {
  148. if(!val){
  149. return '0m'
  150. }
  151. return val / 1000 > 1 ? (val / 1000).toFixed(2) + 'km' : Number(val).toFixed(2) + 'm'
  152. },
  153. },
  154. mounted() {},
  155. methods: {
  156. numberFixed(val) {
  157. if(!val){
  158. return 0
  159. }
  160. return Number(val) ? Number(val).toFixed(2) : val
  161. },
  162. meter: function(val) {
  163. if(!val){
  164. return '0 m'
  165. }
  166. return val / 1000 > 1 ? (val / 1000).toFixed(2) + 'km' : Number(val).toFixed(2) + 'm'
  167. },
  168. handleClick() {
  169. this.$emit('click', this.dataSource.task_id);
  170. },
  171. handleBtnClick(type) {
  172. this.$emit('btntap', type, this.dataSource.task_id);
  173. },
  174. handleReceiveClick() {
  175. this.$emit('confirm', this.dataSource.task_id);
  176. },
  177. handleResetRecordLocation() {
  178. this.$emit('checkRecordStatus', this.dataSource.task_id)
  179. }
  180. }
  181. }
  182. </script>
  183. <style scoped lang="scss">
  184. .task-card {
  185. background-color: #fff;
  186. border-radius: 16rpx;
  187. padding: 16rpx;
  188. margin-bottom: 24rpx;
  189. &__header {
  190. display: flex;
  191. align-items: center;
  192. justify-content: space-between;
  193. }
  194. &__title {
  195. flex: 1 1 auto;
  196. font-size: 14px;
  197. color: #333;
  198. line-height: 40rpx;
  199. margin-right: 100rpx;
  200. padding-bottom: 10rpx;
  201. @include hairline-bottom(rgba(151, 151, 151, 0.09));
  202. }
  203. &__name {
  204. flex: 0 0 auto;
  205. font-size: 12px;
  206. line-height: 40rpx;
  207. color: #1B76FF;
  208. }
  209. &__content {
  210. padding: 10rpx 16rpx;
  211. }
  212. .content {
  213. &__header {
  214. display: flex;
  215. align-items: center;
  216. }
  217. &__title {
  218. font-size: 12px;
  219. line-height: 36rpx;
  220. color: #1B76FF;
  221. margin-right: 20rpx;
  222. }
  223. &__tag {
  224. padding: 0 12rpx;
  225. color: #1B76FF;
  226. font-size: 12px;
  227. line-height: 28rpx;
  228. border-radius: 8rpx;
  229. border: 1px solid #1B76FF;
  230. &.warn {
  231. color: #F33E43;
  232. border: 1px solid #F33E43;
  233. }
  234. }
  235. &__desc {
  236. height: 56rpx;
  237. padding: 10rpx 0;
  238. color: #656565;
  239. font-size: 12px;
  240. line-height: 36rpx;
  241. margin-bottom: 10rpx;
  242. @include line(2);
  243. }
  244. }
  245. &__actions {
  246. padding: 0 20rpx;
  247. &.flex-end {
  248. text-align: right;
  249. }
  250. .start-btn {
  251. display: inline-block;
  252. // float: right;
  253. }
  254. .actions {
  255. &__list {
  256. display: flex;
  257. align-items: center;
  258. padding: 20rpx 0;
  259. border-bottom: 1px solid rgba(2, 2, 2, 0.3);
  260. &.border-none {
  261. border-bottom-color: transparent;
  262. }
  263. }
  264. &__item {
  265. box-sizing: border-box;
  266. width: 0;
  267. flex: 1 1 auto;
  268. height: 50rpx;
  269. display: flex;
  270. align-items: center;
  271. @include hairline-right(rgba(0, 0, 0, 0.3));
  272. // @include line;
  273. &.middle {
  274. justify-content: center;
  275. padding: 0 30rpx;
  276. .actions__text {
  277. width: 0;
  278. // background-color: #F33E43;
  279. flex: 1 1 auto;
  280. text-align: right;
  281. ::v-deep {
  282. .u-tooltip__wrapper {
  283. width: 100%;
  284. }
  285. .u-tooltip__wrapper__text {
  286. width: 100%;
  287. // font-size: 12px;
  288. // text-align: right;
  289. @include line;
  290. }
  291. }
  292. }
  293. }
  294. &.right {
  295. padding-left: 20rpx;
  296. padding-right: 2rpx;
  297. justify-content: space-between;
  298. .actions__text {
  299. // width: 0;
  300. // flex: 1 1 auto;
  301. // text-align: right;
  302. ::v-deep {
  303. // .u-tooltip__wrapper {
  304. // width: 100%;
  305. // }
  306. .u-tooltip__wrapper__text {
  307. width: 100%;
  308. // font-size: 12px;
  309. // text-align: right;
  310. // @include line;
  311. }
  312. }
  313. }
  314. }
  315. &:last-child {
  316. @include hairline-right(transparent);
  317. }
  318. }
  319. &__icon {
  320. flex: 0 0 auto;
  321. width: 32rpx;
  322. height: 32rpx;
  323. margin-right: 36rpx;
  324. .img {
  325. width: 100%;
  326. height: 100%;
  327. }
  328. }
  329. &__text {
  330. font-size: 14px;
  331. line-height: 36rpx;
  332. color: #1B76FF;
  333. // @include line;
  334. }
  335. &__btns {
  336. display: flex;
  337. align-items: center;
  338. justify-content: space-between;
  339. padding: 24rpx 0;
  340. }
  341. &__btn {
  342. display: flex;
  343. align-items: center;
  344. padding: 10rpx 20rpx;
  345. border-radius: 8rpx;
  346. background-color: #F8F8F8;
  347. &.blocked {
  348. flex: 1;
  349. justify-content: center;
  350. }
  351. &-icon {
  352. width: 40rpx;
  353. height: 40rpx;
  354. overflow: hidden;
  355. .img {
  356. width: 100%;
  357. height: 100%;
  358. }
  359. }
  360. &-text {
  361. min-width: 88rpx;
  362. text-align: center;
  363. font-size: 12px;
  364. line-height: 36rpx;
  365. color: #555555;
  366. }
  367. }
  368. &__tips {
  369. font-size: 12px;
  370. line-height: 28rpx;
  371. color: #1B76FF;
  372. margin-bottom: 8rpx;
  373. }
  374. }
  375. }
  376. &__footer {
  377. display: flex;
  378. justify-content: space-between;
  379. align-items: center;
  380. padding: 20rpx 16rpx;
  381. }
  382. &__decoration-title {
  383. position: relative;
  384. padding-left: 24rpx;
  385. font-size: 12px;
  386. line-height: 36rpx;
  387. height: 36rpx;
  388. color: #656565;
  389. &::before {
  390. content: '';
  391. position: absolute;
  392. left: 0;
  393. top: 50%;
  394. width: 8rpx;
  395. height: 30rpx;
  396. transform: translateY(-50%);
  397. background-color: #1B76FF;
  398. border-radius: 8rpx;
  399. }
  400. }
  401. }
  402. </style>