houzhongjian
2024-08-08 820397e43a0b64d35c6d31d2a55475061438593b
提交 | 用户 | 时间
820397 1 <template>
H 2   <div class="card-list" ref="tabsRef" @scroll="handleTabsScroll">
3     <div class="card-item" v-for="role in roleList" :key="role.id">
4       <el-card class="card" body-class="card-body">
5         <!-- 更多操作 -->
6         <div class="more-container" v-if="showMore">
7           <el-dropdown @command="handleMoreClick">
8             <span class="el-dropdown-link">
9               <el-button type="text">
10                 <el-icon><More /></el-icon>
11               </el-button>
12             </span>
13             <template #dropdown>
14               <el-dropdown-menu>
15                 <el-dropdown-item :command="['edit', role]">
16                   <Icon icon="ep:edit" color="#787878" />编辑
17                 </el-dropdown-item>
18                 <el-dropdown-item :command="['delete', role]" style="color: red">
19                   <Icon icon="ep:delete" color="red" />删除
20                 </el-dropdown-item>
21               </el-dropdown-menu>
22             </template>
23           </el-dropdown>
24         </div>
25         <!-- 角色信息 -->
26         <div>
27           <img class="avatar" :src="role.avatar" />
28         </div>
29         <div class="right-container">
30           <div class="content-container">
31             <div class="title">{{ role.name }}</div>
32             <div class="description">{{ role.description }}</div>
33           </div>
34           <div class="btn-container">
35             <el-button type="primary" size="small" @click="handleUseClick(role)">使用</el-button>
36           </div>
37         </div>
38       </el-card>
39     </div>
40   </div>
41 </template>
42
43 <script setup lang="ts">
44 import {ChatRoleVO} from '@/api/ai/model/chatRole'
45 import {PropType, ref} from 'vue'
46 import {More} from '@element-plus/icons-vue'
47
48 const tabsRef = ref<any>() // tabs ref
49
50 // 定义属性
51 const props = defineProps({
52   loading: {
53     type: Boolean,
54     required: true
55   },
56   roleList: {
57     type: Array as PropType<ChatRoleVO[]>,
58     required: true
59   },
60   showMore: {
61     type: Boolean,
62     required: false,
63     default: false
64   }
65 })
66
67 // 定义钩子
68 const emits = defineEmits(['onDelete', 'onEdit', 'onUse', 'onPage'])
69
70 /** 操作:编辑、删除 */
71 const handleMoreClick = async (data) => {
72   const type = data[0]
73   const role = data[1]
74   if (type === 'delete') {
75     emits('onDelete', role)
76   } else {
77     emits('onEdit', role)
78   }
79 }
80
81 /** 选中 */
82 const handleUseClick = (role) => {
83   emits('onUse', role)
84 }
85
86 /** 滚动 */
87 const handleTabsScroll = async () => {
88   if (tabsRef.value) {
89     const { scrollTop, scrollHeight, clientHeight } = tabsRef.value
90     if (scrollTop + clientHeight >= scrollHeight - 20 && !props.loading) {
91       await emits('onPage')
92     }
93   }
94 }
95 </script>
96
97 <style lang="scss">
98 // 重写 card 组件 body 样式
99 .card-body {
100   max-width: 240px;
101   width: 240px;
102   padding: 15px 15px 10px 15px;
103
104   display: flex;
105   flex-direction: row;
106   justify-content: flex-start;
107   position: relative;
108 }
109 </style>
110 <style scoped lang="scss">
111 // 卡片列表
112 .card-list {
113   display: flex;
114   flex-direction: row;
115   flex-wrap: wrap;
116   position: relative;
117   height: 100%;
118   overflow: auto;
119   padding: 0px 25px;
120   padding-bottom: 140px;
121   align-items: start;
122   align-content: flex-start;
123   justify-content: start;
124
125   .card {
126     display: inline-block;
127     margin-right: 20px;
128     border-radius: 10px;
129     margin-bottom: 20px;
130     position: relative;
131
132     .more-container {
133       position: absolute;
134       top: 0;
135       right: 12px;
136     }
137
138     .avatar {
139       width: 40px;
140       height: 40px;
141       border-radius: 10px;
142       overflow: hidden;
143     }
144
145     .right-container {
146       margin-left: 10px;
147       width: 100%;
148       //height: 100px;
149
150       .content-container {
151         height: 85px;
152
153         .title {
154           font-size: 18px;
155           font-weight: bold;
156           color: #3e3e3e;
157         }
158
159         .description {
160           margin-top: 10px;
161           font-size: 14px;
162           color: #6a6a6a;
163         }
164       }
165
166       .btn-container {
167         display: flex;
168         flex-direction: row-reverse;
169         margin-top: 2px;
170       }
171     }
172   }
173 }
174 </style>