feat(courselibrary): 增强课程章节编辑功能

- 添加章节标题编辑功能,支持输入框修改
- 实现章节删除确认弹窗及成功提示
- 更新拖拽组件属性配置,移除旧插槽用法
- 替换 SVG 图标为 iconfont 字体图标
- 引入新的图标样式和 hover 效果
- 优化 collapse 组件交互逻辑与样式表现
- 升级 iconfont 字体文件,新增多个图标定义
This commit is contained in:
陈昱达
2025-12-12 11:29:10 +08:00
parent b1bd6d7d61
commit 70fcfc6cd3
7 changed files with 134 additions and 34 deletions

View File

@@ -1,8 +1,8 @@
@font-face { @font-face {
font-family: "iconfont"; /* Project id 5086622 */ font-family: "iconfont"; /* Project id 5086622 */
src: url("iconfont.woff2?t=1765446803106") format("woff2"), src: url("iconfont.woff2?t=1765507086795") format("woff2"),
url("iconfont.woff?t=1765446803106") format("woff"), url("iconfont.woff?t=1765507086795") format("woff"),
url("iconfont.ttf?t=1765446803106") format("truetype"); url("iconfont.ttf?t=1765507086795") format("truetype");
} }
.iconfont { .iconfont {
@@ -11,11 +11,30 @@
font-style: normal; font-style: normal;
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
color: #b5b5b5;
display: inline-table;
} }
.icon-danseshixintubiao- { .icon-delete:before {
color: #b5b5b5; content: "\e6a6";
} }
.icon-view:before {
content: "\e68d";
}
.icon-up:before {
content: "\e616";
}
.icon-setting:before {
content: "\e623";
}
.icon-edit:before {
content: "\e659";
}
.icon-danseshixintubiao-:before { .icon-danseshixintubiao-:before {
content: "\e632"; content: "\e632";
} }

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -194,6 +194,7 @@ const deleteRow = (data) => {
type: "error", type: "error",
}) })
.then(() => { .then(() => {
$message.success("删除成功");
if ( if (
courseList.value[courseMetadata.chooseIndex] && courseList.value[courseMetadata.chooseIndex] &&
courseList.value[courseMetadata.chooseIndex].data courseList.value[courseMetadata.chooseIndex].data
@@ -254,8 +255,12 @@ const handleNext = () => {
</div> </div>
<div> <div>
<dragCollapse v-model:courseList="courseList"> <dragCollapse
<template #title="{ course }">{{ course.title }}</template> v-model:courseList="courseList"
titleKey="title"
:isEdit="true"
>
<!-- <template #title="{ course }">{{ course.title }}</template>-->
<template #desc="{ course }"> <template #desc="{ course }">
若课程只有一个章节将不在学员端显示该章节名称 若课程只有一个章节将不在学员端显示该章节名称
</template> </template>

View File

@@ -1,14 +1,22 @@
<script setup> <script setup>
import { ref, watch } from "vue"; import { ref, watch } from "vue";
import draggable from "vuedraggable"; import draggable from "vuedraggable";
import { ElIcon } from "element-plus"; import { ElInput, ElMessageBox } from "element-plus";
import { Delete, ArrowUp, ArrowDown, Operation } from "@element-plus/icons-vue"; import { $message } from "@/utils/useMessage";
import svgIcon from "@/components/SvgIcon.vue";
const props = defineProps({ const props = defineProps({
courseList: { courseList: {
type: Array, type: Array,
default: () => [], default: () => [],
}, },
titleKey: {
type: String,
default: "",
},
isEdit: {
type: Boolean,
default: false,
},
}); });
// 定义 emits 用于更新父组件数据 // 定义 emits 用于更新父组件数据
@@ -48,6 +56,34 @@ const moveStart = (e) => {
item.isCollapsed = true; item.isCollapsed = true;
}); });
}; };
const showInput = ref(false);
const editTitle = (element) => {
console.log("编辑");
element.showInput = true;
element.copyTitle = element[props.titleKey];
};
const saveTitle = (element) => {
element.showInput = false;
element[props.titleKey] = element.copyTitle;
delete element.copyTitle;
delete element.showInput;
delete element.isCollapsed;
emit("update:courseList", dragList.value);
};
const deleteCourse = (index) => {
ElMessageBox.confirm("确定删除所选章节吗", "删除确认", {
title: "删除确认",
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "error",
}).then(() => {
$message.success("删除成功");
dragList.value.splice(index, 1);
emit("update:courseList", dragList.value);
});
};
</script> </script>
<template> <template>
@@ -62,9 +98,28 @@ const moveStart = (e) => {
<template #item="{ element, index }"> <template #item="{ element, index }">
<div class="drag-collapse"> <div class="drag-collapse">
<div class="drag-collapse-header"> <div class="drag-collapse-header">
<div> <div class="flex align-center">
<span class="drag-collapse-header-title"> <span
<slot name="title" :course="element">视频可见名称</slot> class="drag-collapse-header-title flex align-item-c"
style="align-items: center"
>
<span v-if="element.showInput">
<el-input v-model="element.copyTitle" clearable></el-input>
</span>
<span v-else>{{ element[titleKey] }}</span>
<i
class="iconfont icon-edit fs14 ml20"
v-if="isEdit && !element.showInput"
@click="editTitle(element)"
></i>
<i
class="fs16 ml20"
v-if="isEdit && element.showInput"
style="cursor: pointer; color: #4284f7"
@click="saveTitle(element)"
></i
>
</span> </span>
<span class="drag-collapse-header-desc"> <span class="drag-collapse-header-desc">
<slot name="desc" :course="element"> <slot name="desc" :course="element">
@@ -74,25 +129,27 @@ const moveStart = (e) => {
</div> </div>
<div style="display: flex; align-items: center"> <div style="display: flex; align-items: center">
<i class="iconfont icon-danseshixintubiao- move-icon"></i> <span>
<svg-icon <i class="iconfont icon-danseshixintubiao- move-icon fs16"></i>
icon-class="del" </span>
class="ml10" <span>
style="width: 0.9em; cursor: pointer" <i
></svg-icon> class="ml10 iconfont icon-delete fs14"
style="cursor: pointer"
@click="deleteCourse(index)"
></i>
</span>
<span @click="toggleCollapse(element)"> <span @click="toggleCollapse(element)">
<svg-icon <i
v-if="!element.isCollapsed" v-if="!element.isCollapsed"
icon-class="up" class="ml10 iconfont icon-up fs10"
class="ml10" style="cursor: pointer; display: inline-table"
style="width: 0.9em; cursor: pointer" ></i>
></svg-icon> <i
<svg-icon
v-else v-else
icon-class="up" class="ml10 iconfont icon-up fs10"
class="ml10" style="cursor: pointer; transform: rotate(180deg)"
style="width: 0.9em; cursor: pointer; transform: rotate(180deg)" ></i>
></svg-icon>
</span> </span>
</div> </div>
</div> </div>
@@ -106,9 +163,17 @@ const moveStart = (e) => {
</template> </template>
<style scoped lang="scss"> <style scoped lang="scss">
.icon-danseshixintubiao- { .icon-danseshixintubiao-,
.icon-up,
.icon-edit {
&:hover { &:hover {
color: #4284f7; color: #4284f7;
cursor: pointer;
}
}
.icon-delete {
&:hover {
color: #ff2626;
} }
} }
.drag-collapse { .drag-collapse {

View File

@@ -197,14 +197,20 @@ const renderNameColumn = () => {
startEdit(record); startEdit(record);
}, },
}, },
createVNode(svgIcon, { h("i", {
iconClass: "tableEdit", class: "iconfont icon-edit",
style: { style: {
fontSize: "12px", fontSize: "12px",
width: "1em",
height: "1em",
}, },
}) })
// createVNode(svgIcon, {
// iconClass: "tableEdit",
// style: {
// fontSize: "12px",
// width: "1em",
// height: "1em",
// },
// })
), ),
] ]
); );
@@ -435,6 +441,11 @@ const components = {
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
:deep(.icon-edit) {
&:hover {
color: #4284f7;
}
}
.drag-table-container { .drag-table-container {
padding: 20px; padding: 20px;
margin: 0 auto; margin: 0 auto;