index.vue 1.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. <template>
  2. <ul class="list">
  3. <li class="header" v-if="title">
  4. <h3>{{ title }}</h3>
  5. <div class="action" v-if="$slots.action">
  6. <slot name="action"></slot>
  7. </div>
  8. </li>
  9. <ul class="content" v-if="showContent">
  10. <li
  11. v-for="(item, i) in data"
  12. :key="rawKey ? item.raw[rawKey] : i"
  13. :class="{select: item.select}"
  14. @click.stop="$emit('changeSelect', item)"
  15. >
  16. <div class="atom-content">
  17. <slot name="atom" :item="item"></slot>
  18. </div>
  19. </li>
  20. </ul>
  21. </ul>
  22. </template>
  23. <script lang="ts" setup>
  24. type Item = Record<string, any> & {select?: boolean}
  25. type ListProps = { title?: string, rawKey?: string, data: Array<Item>, showContent?: boolean}
  26. withDefaults(
  27. defineProps<ListProps>(),
  28. { showContent: true }
  29. )
  30. defineEmits<{ (e: 'changeSelect', item: Item): void }>()
  31. </script>
  32. <style lang="scss" scoped>
  33. .header {
  34. border-bottom: 1px solid rgba(255,255,255,0.16);
  35. display: flex;
  36. justify-content: space-between;
  37. padding: 20px;
  38. h3 {
  39. font-size: 16px;
  40. font-weight: bold;
  41. color: #999999;
  42. }
  43. }
  44. .content {
  45. li {
  46. padding: 0 20px;
  47. cursor: pointer;
  48. &.select {
  49. background: rgba(0,200,175,0.1600);
  50. }
  51. .atom-content {
  52. padding: 20px 0;
  53. border-bottom: 1px solid rgba(255,255,255,0.16);
  54. }
  55. }
  56. }
  57. .list li {
  58. list-style: none;
  59. }
  60. </style>