OaTaskCard.vue 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. <template>
  2. <view class="oa-task-card" :class="'tone-' + normalizedTone">
  3. <view class="oa-task-card__body" @click="$emit('open')">
  4. <view class="oa-task-card__top">
  5. <view class="oa-task-card__title-row">
  6. <view v-if="unread" class="oa-task-card__unread" aria-hidden="true" />
  7. <text class="oa-task-card__title">{{ title }}</text>
  8. </view>
  9. <text
  10. v-if="statusText"
  11. class="oa-task-card__status"
  12. :class="'is-' + normalizedTone"
  13. >
  14. {{ statusText }}
  15. </text>
  16. </view>
  17. <view v-if="metaLines && metaLines.length" class="oa-task-card__meta">
  18. <view
  19. v-for="(line, idx) in metaLines"
  20. :key="idx"
  21. class="oa-task-card__meta-line"
  22. >
  23. <text class="oa-task-card__meta-label">{{ line.label }}</text>
  24. <text class="oa-task-card__meta-value">{{ line.value }}</text>
  25. </view>
  26. </view>
  27. </view>
  28. <view v-if="actions && actions.length" class="oa-task-card__footer">
  29. <view
  30. v-for="act in actions"
  31. :key="act.key"
  32. class="oa-task-card__btn"
  33. :class="{
  34. 'is-primary': !!act.primary,
  35. 'is-danger': !!act.danger && !act.primary,
  36. 'is-disabled': !!act.disabled
  37. }"
  38. @click.stop="onActionClick(act)"
  39. >
  40. {{ act.label }}
  41. </view>
  42. </view>
  43. </view>
  44. </template>
  45. <script>
  46. const TONES = ['warn', 'success', 'danger', 'info']
  47. export default {
  48. name: 'OaTaskCard',
  49. props: {
  50. title: { type: String, default: '' },
  51. statusText: { type: String, default: '' },
  52. statusTone: { type: String, default: 'info' },
  53. metaLines: { type: Array, default: () => [] },
  54. unread: { type: Boolean, default: false },
  55. actions: { type: Array, default: () => [] }
  56. },
  57. emits: ['open', 'action'],
  58. computed: {
  59. normalizedTone() {
  60. const t = String(this.statusTone || 'info').toLowerCase()
  61. return TONES.includes(t) ? t : 'info'
  62. }
  63. },
  64. methods: {
  65. onActionClick(act) {
  66. if (!act || act.disabled) return
  67. this.$emit('action', act)
  68. }
  69. }
  70. }
  71. </script>