task-card.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  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. return Number(val) ? Number(val).toFixed(2) : val
  143. },
  144. meter: function(val) {
  145. return val / 1000 > 1 ? (val / 1000).toFixed(2) + 'km' : Number(val).toFixed(2) + 'm'
  146. },
  147. },
  148. mounted() {},
  149. methods: {
  150. numberFixed(val) {
  151. return Number(val) ? Number(val).toFixed(2) : val
  152. },
  153. meter: function(val) {
  154. return val / 1000 > 1 ? (val / 1000).toFixed(2) + 'km' : Number(val).toFixed(2) + 'm'
  155. },
  156. handleClick() {
  157. this.$emit('click', this.dataSource.task_id);
  158. },
  159. handleBtnClick(type) {
  160. this.$emit('btntap', type, this.dataSource.task_id);
  161. },
  162. handleReceiveClick() {
  163. this.$emit('confirm', this.dataSource.task_id);
  164. },
  165. handleResetRecordLocation() {
  166. this.$emit('checkRecordStatus', this.dataSource.task_id)
  167. }
  168. }
  169. }
  170. </script>
  171. <style scoped lang="scss">
  172. .task-card {
  173. background-color: #fff;
  174. border-radius: 16rpx;
  175. padding: 16rpx;
  176. margin-bottom: 24rpx;
  177. &__header {
  178. display: flex;
  179. align-items: center;
  180. justify-content: space-between;
  181. }
  182. &__title {
  183. flex: 1 1 auto;
  184. font-size: 14px;
  185. color: #333;
  186. line-height: 40rpx;
  187. margin-right: 100rpx;
  188. padding-bottom: 10rpx;
  189. @include hairline-bottom(rgba(151, 151, 151, 0.09));
  190. }
  191. &__name {
  192. flex: 0 0 auto;
  193. font-size: 12px;
  194. line-height: 40rpx;
  195. color: #1B76FF;
  196. }
  197. &__content {
  198. padding: 10rpx 16rpx;
  199. }
  200. .content {
  201. &__header {
  202. display: flex;
  203. align-items: center;
  204. }
  205. &__title {
  206. font-size: 12px;
  207. line-height: 36rpx;
  208. color: #1B76FF;
  209. margin-right: 20rpx;
  210. }
  211. &__tag {
  212. padding: 0 12rpx;
  213. color: #1B76FF;
  214. font-size: 12px;
  215. line-height: 28rpx;
  216. border-radius: 8rpx;
  217. border: 1px solid #1B76FF;
  218. &.warn {
  219. color: #F33E43;
  220. border: 1px solid #F33E43;
  221. }
  222. }
  223. &__desc {
  224. height: 56rpx;
  225. padding: 10rpx 0;
  226. color: #656565;
  227. font-size: 12px;
  228. line-height: 36rpx;
  229. margin-bottom: 10rpx;
  230. @include line(2);
  231. }
  232. }
  233. &__actions {
  234. padding: 0 20rpx;
  235. &.flex-end {
  236. text-align: right;
  237. }
  238. .start-btn {
  239. display: inline-block;
  240. // float: right;
  241. }
  242. .actions {
  243. &__list {
  244. display: flex;
  245. align-items: center;
  246. padding: 20rpx 0;
  247. border-bottom: 1px solid rgba(2, 2, 2, 0.3);
  248. &.border-none {
  249. border-bottom-color: transparent;
  250. }
  251. }
  252. &__item {
  253. box-sizing: border-box;
  254. width: 0;
  255. flex: 1 1 auto;
  256. height: 50rpx;
  257. display: flex;
  258. align-items: center;
  259. @include hairline-right(rgba(0, 0, 0, 0.3));
  260. // @include line;
  261. &.middle {
  262. justify-content: center;
  263. padding: 0 30rpx;
  264. .actions__text {
  265. width: 0;
  266. // background-color: #F33E43;
  267. flex: 1 1 auto;
  268. text-align: right;
  269. ::v-deep {
  270. .u-tooltip__wrapper {
  271. width: 100%;
  272. }
  273. .u-tooltip__wrapper__text {
  274. width: 100%;
  275. // font-size: 12px;
  276. // text-align: right;
  277. @include line;
  278. }
  279. }
  280. }
  281. }
  282. &.right {
  283. padding-left: 20rpx;
  284. padding-right: 2rpx;
  285. justify-content: space-between;
  286. .actions__text {
  287. // width: 0;
  288. // flex: 1 1 auto;
  289. // text-align: right;
  290. ::v-deep {
  291. // .u-tooltip__wrapper {
  292. // width: 100%;
  293. // }
  294. .u-tooltip__wrapper__text {
  295. width: 100%;
  296. // font-size: 12px;
  297. // text-align: right;
  298. // @include line;
  299. }
  300. }
  301. }
  302. }
  303. &:last-child {
  304. @include hairline-right(transparent);
  305. }
  306. }
  307. &__icon {
  308. flex: 0 0 auto;
  309. width: 32rpx;
  310. height: 32rpx;
  311. margin-right: 36rpx;
  312. .img {
  313. width: 100%;
  314. height: 100%;
  315. }
  316. }
  317. &__text {
  318. font-size: 14px;
  319. line-height: 36rpx;
  320. color: #1B76FF;
  321. // @include line;
  322. }
  323. &__btns {
  324. display: flex;
  325. align-items: center;
  326. justify-content: space-between;
  327. padding: 24rpx 0;
  328. }
  329. &__btn {
  330. display: flex;
  331. align-items: center;
  332. padding: 10rpx 20rpx;
  333. border-radius: 8rpx;
  334. background-color: #F8F8F8;
  335. &.blocked {
  336. flex: 1;
  337. justify-content: center;
  338. }
  339. &-icon {
  340. width: 40rpx;
  341. height: 40rpx;
  342. overflow: hidden;
  343. .img {
  344. width: 100%;
  345. height: 100%;
  346. }
  347. }
  348. &-text {
  349. min-width: 88rpx;
  350. text-align: center;
  351. font-size: 12px;
  352. line-height: 36rpx;
  353. color: #555555;
  354. }
  355. }
  356. &__tips {
  357. font-size: 12px;
  358. line-height: 28rpx;
  359. color: #1B76FF;
  360. margin-bottom: 8rpx;
  361. }
  362. }
  363. }
  364. &__footer {
  365. display: flex;
  366. justify-content: space-between;
  367. align-items: center;
  368. padding: 20rpx 16rpx;
  369. }
  370. &__decoration-title {
  371. position: relative;
  372. padding-left: 24rpx;
  373. font-size: 12px;
  374. line-height: 36rpx;
  375. height: 36rpx;
  376. color: #656565;
  377. &::before {
  378. content: '';
  379. position: absolute;
  380. left: 0;
  381. top: 50%;
  382. width: 8rpx;
  383. height: 30rpx;
  384. transform: translateY(-50%);
  385. background-color: #1B76FF;
  386. border-radius: 8rpx;
  387. }
  388. }
  389. }
  390. </style>