index.vue 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. <template>
  2. <view class="question-card" :class="{'question-card--answered': question.answeredAt}">
  3. <view class="question-card__header">
  4. <view class="question-card__user">
  5. <image :src="question.playerAvatar" mode="aspectFill" class="question-card__avatar" />
  6. <text class="question-card__name">{{ question.playerName }}</text>
  7. </view>
  8. <view class="question-card__time">{{ formatTime(question.createdAt) }}</view>
  9. </view>
  10. <view class="question-card__content">
  11. {{ question.content }}
  12. </view>
  13. <view v-if="question.answeredAt" class="question-card__answer">
  14. <view class="question-card__answer-label">回答</view>
  15. <view class="question-card__answer-content">{{ question.answer }}</view>
  16. </view>
  17. <view v-else-if="isHost" class="question-card__actions">
  18. <nut-button size="small" type="primary" @click="onAnswer('是')">是</nut-button>
  19. <nut-button size="small" type="primary" @click="onAnswer('否')">否</nut-button>
  20. <nut-button size="small" @click="onAnswer('不相关')">不相关</nut-button>
  21. </view>
  22. </view>
  23. </template>
  24. <script setup lang="ts">
  25. import { defineProps, defineEmits } from 'vue';
  26. import type { Question } from '@/types/game';
  27. import { formatDistanceToNow } from 'date-fns';
  28. import { zhCN } from 'date-fns/locale';
  29. interface QuestionWithAvatar extends Question {
  30. playerAvatar: string;
  31. }
  32. const props = defineProps({
  33. question: {
  34. type: Object as () => QuestionWithAvatar,
  35. required: true
  36. },
  37. isHost: {
  38. type: Boolean,
  39. default: false
  40. }
  41. });
  42. const emit = defineEmits(['answer']);
  43. const formatTime = (date: Date) => {
  44. return formatDistanceToNow(new Date(date), {
  45. addSuffix: true,
  46. locale: zhCN
  47. });
  48. };
  49. const onAnswer = (answer: string) => {
  50. emit('answer', {
  51. questionId: props.question.id,
  52. answer
  53. });
  54. };
  55. </script>
  56. <style lang="scss">
  57. .question-card {
  58. background-color: $background-color-light;
  59. border-radius: $border-radius-small;
  60. padding: $spacing-base;
  61. margin-bottom: $spacing-base;
  62. box-shadow: $shadow-light;
  63. &--answered {
  64. background-color: $background-color-gray;
  65. }
  66. &__header {
  67. display: flex;
  68. justify-content: space-between;
  69. align-items: center;
  70. margin-bottom: $spacing-small;
  71. }
  72. &__user {
  73. display: flex;
  74. align-items: center;
  75. }
  76. &__avatar {
  77. width: 24px;
  78. height: 24px;
  79. border-radius: $border-radius-circle;
  80. margin-right: $spacing-mini;
  81. }
  82. &__name {
  83. font-size: $font-size-small;
  84. color: $text-color-primary;
  85. font-weight: $font-weight-medium;
  86. }
  87. &__time {
  88. font-size: $font-size-small;
  89. color: $text-color-secondary;
  90. }
  91. &__content {
  92. font-size: $font-size-base;
  93. color: $text-color-primary;
  94. margin-bottom: $spacing-base;
  95. line-height: $line-height-base;
  96. }
  97. &__answer {
  98. background-color: rgba($primary-color, 0.05);
  99. padding: $spacing-small;
  100. border-radius: $border-radius-small;
  101. display: flex;
  102. }
  103. &__answer-label {
  104. font-size: $font-size-small;
  105. color: $primary-color;
  106. font-weight: $font-weight-medium;
  107. margin-right: $spacing-small;
  108. }
  109. &__answer-content {
  110. font-size: $font-size-small;
  111. color: $text-color-primary;
  112. }
  113. &__actions {
  114. display: flex;
  115. gap: $spacing-small;
  116. }
  117. }
  118. </style>