index.vue 1.5 KB

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