Explorar el Código

提取视图卡片公共组件

lm hace 1 mes
padre
commit
1ccdac39cb

+ 241 - 0
src/components/questionnaireCard/QuestionnaireCard.vue

@@ -0,0 +1,241 @@
+<template>
+     <ul class="questionnaire_list">
+        <li v-for="quesitonnaire in questionnaireList" :key="quesitonnaire.id" class="card_item">
+            <!-- 顶部区域:图标 + 标题 -->
+            <div class="card_header">
+                <!-- 模拟图片中的文档图标 -->
+                <img src="" alt="" class="card-icon" />
+                <span class="card_title two_line_ellipsis">{{ quesitonnaire.assessmentTitle }}</span>
+                <el-switch
+                    v-if="cardType == 'reviewManage'"
+                    :model-valule="quesitonnaire.cardOnOff"
+                    @change="(val)=>HandleOnOffChange(val,quesitonnaire)"
+                    style="--el-switch-on-color: #2e64fa; --el-switch-off-color: #bbbbbb"
+                />
+            </div>
+
+            <!-- 中间区域:元数据 (分数、创建人、状态、时间) -->
+            <div class="card_meta">
+                <div class="meta_row">
+                    <!-- 问卷总分 -->
+                    <span  v-if="cardType == 'questionnareManage'" class="score_text">{{ quesitonnaire.assessmentScore }}分</span>
+                    <span class="creator_text">管理员</span>
+                    <!-- 评价类型 -->
+                    <span v-if="cardType == 'reviewManage'">线上匿名___</span>
+                    <!-- 状态文本:根据 cardStatus 动态变色 -->
+                    <span :class="['status_text', statusNumToName(quesitonnaire.cardStatus)?.themeClass ]">
+                        {{ statusNumToName(quesitonnaire.cardStatus)?.title  }}
+                    </span>
+                </div>
+                <div class="time_row">
+                    <span>{{ quesitonnaire.createdAt }}</span>
+                </div>
+            </div>
+
+            <div class="page_solid_line"></div>
+
+            <!-- 底部区域:操作按钮 -->
+            <div class="card_footer">
+                <slot name="default" :row="quesitonnaire"></slot>
+            </div>
+        </li>
+    </ul>
+
+
+
+</template>
+
+
+<script setup lang="ts">
+
+interface QuestionnaireItm {
+    id:Number,
+    assessmentTitle:String,  //标题
+    assessmentScore:Number|String,  //总分
+    teacherName:String,  //创建人
+    createdAt:String,   //创建时间
+    cardStatus:Number,   //1 已使用   0 未使用
+    cardOnOff?:Boolean
+
+}
+
+interface StatusItm {
+  statusFlag:Number | String,
+  title:String,
+  themeClass:'used' | 'unused' | 'ongoing' | 'end' | String
+}
+
+ // questionnareManage (问卷管理) | reviewManage (评价管理) |  
+type CardType = 'questionnareManage' | 'reviewManage'
+
+
+const props = defineProps({
+    questionnaireList:{   //卡片数据
+        type:Array<QuestionnaireItm>,
+        required:true,
+    },
+    cardStatusMsg:{  //卡片状态信息
+        required:true,
+        type:Array<StatusItm>
+    },
+    cardTypeMsg:{
+        type:Array,
+    },
+    showSwitch:{   //展示卡片开关
+        type:Boolean,
+        default:false
+    },
+    cardType:{
+        type:String as ()=>CardType,  
+        required:true
+    }
+})
+
+const emit = defineEmits('switchOnOff')
+// 处理卡片的开关状态
+const HandleOnOffChange = (val,row)=>{
+    console.log('当前值',val)
+    emit('switchOnOff',{id:row.id,onOffVal:val })
+}
+const statusNumToName=(status:String|Number|null)=>{
+  let result =  props?.cardStatusMsg?.find(item=>item.statusFlag === status)
+  if(result){
+    return result
+  }else{
+    return {
+      title:'',
+      themeClass:''
+    }
+  }
+}
+</script>
+
+
+<style lang="scss" scoped>
+
+/* 列表容器:横向排列,允许换行 */
+.questionnaire_list {
+        
+    display: flex;
+    flex-wrap: wrap;
+    gap: 20px;
+    list-style: none;
+    padding: 0;
+
+    
+    /* 单个卡片样式 */
+    .card_item {
+        width: 325px; /* 固定宽度以匹配图片比例 */
+        background: #F8FAFE;
+        border: 1px solid #EBEEF5;
+        border-radius: 10px;
+        padding: 16px 0;
+        display: flex;
+        flex-direction: column;
+        justify-content: space-between;
+        gap:12px;
+      
+        /* 头部:图标和标题 */
+        .card_header {
+            display: flex;
+            align-items: center;
+            gap:8px;
+            padding:0 16px;
+
+            .card-icon {
+                width: 40px;
+                height: 40px;
+                background-color: #e6f7ff; /* 浅蓝背景 */
+                border-radius: 4px;
+                padding: 4px;
+            }
+            .card_title {
+                font-size: 14px;
+                font-weight: 600;
+                color: #333;
+                line-height: 1;
+                // max-width: 240px;
+            }
+        }
+
+
+        /* 中部:元数据信息 */
+        .card_meta {
+            font-size: 12px;
+            line-height: 16px;
+            color: #666;
+            display: flex;
+            flex-direction: column;
+            gap:12px;
+            padding:0 16px;
+
+            .meta_row {
+                display: flex;
+                align-items: center;
+                gap: 12px;
+
+                .score_text {
+                    color: #333;
+                }
+                    
+                /* 状态颜色控制 */
+                .status_text {
+                    display: flex;
+                    align-items: center;
+
+                    &::before {
+                        content: "";
+                        display: inline-block;
+                        width: 6px;
+                        height: 6px;
+                        border-radius: 50%;
+                        margin-right: 6px;
+                    }
+
+                    /* 已使用 (蓝色) */
+                    &.used {
+                        color: #1890ff;
+                        &::before {
+                            background-color: #1890ff;
+                        }
+                    }
+                    /* 未使用 (灰色) */
+                    &.unused {
+                        color: #999;
+                        &::before {
+                            background-color: #ccc;
+                        }
+                    }
+
+                    &.ongoing {
+
+                    }
+
+                    &.end{
+
+                    }
+                }
+            }
+            .time_row {
+                color: #999;
+            }
+        }
+
+        /* 底部:按钮组 */
+        .card_footer {
+            display: flex;
+            justify-content: flex-start;
+            gap: 12px;
+            padding:0 16px;
+            // margin-top: auto; /* 将按钮推到底部 */
+            :deep(.el-button){
+                height: 32px;
+                padding: 6px 12px;
+                font-size: 14px;
+                margin-left: 0px;
+            }
+        }
+    }
+}
+
+</style>

+ 43 - 159
src/views/surveyManagement/SurveyManagement.vue

@@ -20,47 +20,26 @@
             <div class="page_jg_20"></div>
 
             <!-- 视图展示数据 -->
-            <ul v-if="defaultViewMode == 'view'" class="questionnaire_list">
-                <li v-for="quesitonnaire in questionnaireList" :key="quesitonnaire.id" class="card_item">
-                    <!-- 顶部区域:图标 + 标题 -->
-                    <div class="card_header">
-                        <!-- 模拟图片中的文档图标 -->
-                        <img src="" alt="" class="card-icon" />
-                        <span class="card_title two_line_ellipsis">{{ quesitonnaire.assessmentTitle }}</span>
-                    </div>
-
-                    <!-- 中间区域:元数据 (分数、创建人、状态、时间) -->
-                    <div class="card_meta">
-                        <div class="meta_row">
-                            <span class="score_text">{{ quesitonnaire.assessmentScore }}分</span>
-                            <span class="creator_text">管理员</span>
-                            <!-- 状态文本:根据 useStatus 动态变色 -->
-                            <span :class="['status_text', quesitonnaire.useStatus === 1 ? 'used' : 'unused']">
-                                {{ quesitonnaire.useStatus === 1 ? '已使用' : '未使用' }}
-                            </span>
-                        </div>
-                        <div class="time_row">
-                            <span>{{ quesitonnaire.createdAt }}</span>
-                        </div>
-                    </div>
+            <QuestionnaireCard 
+                v-if="defaultViewMode == 'view'" 
+                :questionnaireList="questionnaireList"
+                :cardStatusMsg="cardStatusMsg"
+                cardType="questionnareManage"
+            >
+                <template #default="{row}">
+                    <el-button 
+                        :class="[Number(row.useStatus) === 1 ? 'is-disabled' : 'button_background']"
+                        @click="Number(row.useStatus) === 1 ?  '' : GoToCreateQuestionnaire(row)"    
+                    >编辑</el-button>
+                    <el-button class="button_border" @click="GoToPreviewQuestionnaire(row)">预览</el-button>
+                    <el-button class="button_refresh" @click="CopyQuestionnaire(row)">复制</el-button>
+                    <el-button 
+                        :class="[Number(row.useStatus) === 1 ? 'is-disabled' : 'delete_button_border']"
+                        @click="Number(row.useStatus) === 1 ?  '' : OpenDeleteDialog(row)"
+                    >删除</el-button>
+                </template>
+            </QuestionnaireCard>
 
-                    <div class="page_solid_line"></div>
-
-                    <!-- 底部区域:操作按钮 -->
-                    <div class="card_footer">
-                        <el-button 
-                            :class="[Number(quesitonnaire.useStatus) === 1 ? 'is-disabled' : 'button_background']"
-                            @click="Number(quesitonnaire.useStatus) === 1 ?  '' : GoToCreateQuestionnaire(quesitonnaire)"    
-                        >编辑</el-button>
-                        <el-button class="button_border" @click="GoToPreviewQuestionnaire(quesitonnaire)">预览</el-button>
-                        <el-button class="button_refresh" @click="CopyQuestionnaire(quesitonnaire)">复制</el-button>
-                        <el-button 
-                            :class="[Number(quesitonnaire.useStatus) === 1 ? 'is-disabled' : 'delete_button_border']"
-                            @click="Number(quesitonnaire.useStatus) === 1 ?  '' : OpenDeleteDialog(quesitonnaire)"
-                        >删除</el-button>
-                    </div>
-                </li>
-            </ul>
 
             <!-- 列表展示数据 -->
             <Table v-else
@@ -115,6 +94,8 @@ import Table from '@/baseComponents/Table.vue';
 import TabSearch from '@/baseComponents/TabSearch.vue';
 import TableRowStatus from '@/baseComponents/TableRowStatus.vue';
 
+import QuestionnaireCard from '@/components/questionnaireCard/QuestionnaireCard.vue';
+
 import { getQuestionnaireListApi , copyQuestionnaireApi,deleteQuestionnaireApi} from '@/api/surveyManagement'
 
 
@@ -130,6 +111,7 @@ interface QuestionnaireItm {
     teacherName:String,  //创建人
     createdAt:String,   //创建时间
     useStatus:Number,   //1 已使用   0 未使用
+    cardStatus:Number,
 }
 const router = useRouter()
 
@@ -147,6 +129,20 @@ const totalNum = ref(0)
 const pageSize = ref(20)
 const questionnaireList = ref<QuestionnaireItm[]>([]);
 
+// 问卷状态展示
+const cardStatusMsg = ref([
+    {
+        statusFlag:0,
+        title:'未使用',
+        themeClass:'unused'
+    },
+    {
+        statusFlag:1,
+        title:'已使用',
+        themeClass:'used'
+    },
+])
+
 const GetQuestionnaireList = async ()=>{
     let params = {
         pageNum:currentPage.value,
@@ -155,7 +151,12 @@ const GetQuestionnaireList = async ()=>{
     let res = await getQuestionnaireListApi(params)
 
     if(res.code == 200){
-        questionnaireList.value = res.data.records
+        questionnaireList.value = res.data.records.map(itm=>{
+            return {
+                ...itm,
+                cardStatus:itm.useStatus
+            }
+        })
     }
 }
 
@@ -171,7 +172,7 @@ const GoToCreateQuestionnaire = (row?:any)=>{
 
 // 预览问卷
 const GoToPreviewQuestionnaire = (row)=>{
-     router.push(`/main/previewQuestionnaire?id=${row.id}`)
+    router.push(`/main/previewQuestionnaire?id=${row.id}`)
 }
 
 // 复制问卷
@@ -237,123 +238,6 @@ onMounted(async()=>{
         }
    } 
 }
-/* 列表容器:横向排列,允许换行 */
-.questionnaire_list {
-        
-    display: flex;
-    flex-wrap: wrap;
-    gap: 20px;
-    list-style: none;
-    padding: 0;
-
-    
-    /* 单个卡片样式 */
-    .card_item {
-        width: 325px; /* 固定宽度以匹配图片比例 */
-        background: #F8FAFE;
-        border: 1px solid #EBEEF5;
-        border-radius: 10px;
-        padding: 16px 0;
-        display: flex;
-        flex-direction: column;
-        justify-content: space-between;
-        gap:12px;
-      
-        /* 头部:图标和标题 */
-        .card_header {
-            display: flex;
-            align-items: center;
-            gap:8px;
-            padding:0 16px;
-
-            .card-icon {
-                width: 40px;
-                height: 40px;
-                background-color: #e6f7ff; /* 浅蓝背景 */
-                border-radius: 4px;
-                padding: 4px;
-            }
-            .card_title {
-                font-size: 14px;
-                font-weight: 600;
-                color: #333;
-                line-height: 1;
-                // max-width: 240px;
-            }
-        }
-
-
-        /* 中部:元数据信息 */
-        .card_meta {
-            font-size: 12px;
-            line-height: 16px;
-            color: #666;
-            display: flex;
-            flex-direction: column;
-            gap:12px;
-            padding:0 16px;
-
-            .meta_row {
-                display: flex;
-                align-items: center;
-                gap: 12px;
-
-                .score_text {
-                    color: #333;
-                }
-                    
-                /* 状态颜色控制 */
-                .status_text {
-                    display: flex;
-                    align-items: center;
-
-                    &::before {
-                        content: "";
-                        display: inline-block;
-                        width: 6px;
-                        height: 6px;
-                        border-radius: 50%;
-                        margin-right: 6px;
-                    }
-                    /* 已使用 (蓝色) */
-                    &.used {
-                        color: #1890ff;
-                        &::before {
-                            background-color: #1890ff;
-                        }
-                    }
-                    /* 未使用 (灰色) */
-                    &.unused {
-                        color: #999;
-                        &::before {
-                            background-color: #ccc;
-                        }
-                    }
-                }
-            }
-            .time_row {
-                color: #999;
-            }
-        }
-
-        /* 底部:按钮组 */
-        .card_footer {
-            display: flex;
-            justify-content: flex-start;
-            gap: 12px;
-            padding:0 16px;
-            // margin-top: auto; /* 将按钮推到底部 */
-            .el-button{
-                height: 32px;
-                padding: 6px 12px;
-                font-size: 14px;
-                margin-left: 0px;
-            }
-        }
-    }
-}
-
-
 .dialog_alert{
     color:#666;
     display: flex;