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-family: "iconfont"; /* Project id 5086622 */
src: url("iconfont.woff2?t=1765446803106") format("woff2"),
url("iconfont.woff?t=1765446803106") format("woff"),
url("iconfont.ttf?t=1765446803106") format("truetype");
src: url("iconfont.woff2?t=1765507086795") format("woff2"),
url("iconfont.woff?t=1765507086795") format("woff"),
url("iconfont.ttf?t=1765507086795") format("truetype");
}
.iconfont {
@@ -11,11 +11,30 @@
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
color: #b5b5b5;
display: inline-table;
}
.icon-danseshixintubiao- {
color: #b5b5b5;
.icon-delete:before {
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 {
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",
})
.then(() => {
$message.success("删除成功");
if (
courseList.value[courseMetadata.chooseIndex] &&
courseList.value[courseMetadata.chooseIndex].data
@@ -254,8 +255,12 @@ const handleNext = () => {
</div>
<div>
<dragCollapse v-model:courseList="courseList">
<template #title="{ course }">{{ course.title }}</template>
<dragCollapse
v-model:courseList="courseList"
titleKey="title"
:isEdit="true"
>
<!-- <template #title="{ course }">{{ course.title }}</template>-->
<template #desc="{ course }">
若课程只有一个章节将不在学员端显示该章节名称
</template>

View File

@@ -1,14 +1,22 @@
<script setup>
import { ref, watch } from "vue";
import draggable from "vuedraggable";
import { ElIcon } from "element-plus";
import { Delete, ArrowUp, ArrowDown, Operation } from "@element-plus/icons-vue";
import svgIcon from "@/components/SvgIcon.vue";
import { ElInput, ElMessageBox } from "element-plus";
import { $message } from "@/utils/useMessage";
const props = defineProps({
courseList: {
type: Array,
default: () => [],
},
titleKey: {
type: String,
default: "",
},
isEdit: {
type: Boolean,
default: false,
},
});
// 定义 emits 用于更新父组件数据
@@ -48,6 +56,34 @@ const moveStart = (e) => {
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>
<template>
@@ -62,9 +98,28 @@ const moveStart = (e) => {
<template #item="{ element, index }">
<div class="drag-collapse">
<div class="drag-collapse-header">
<div>
<span class="drag-collapse-header-title">
<slot name="title" :course="element">视频可见名称</slot>
<div class="flex align-center">
<span
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 class="drag-collapse-header-desc">
<slot name="desc" :course="element">
@@ -74,25 +129,27 @@ const moveStart = (e) => {
</div>
<div style="display: flex; align-items: center">
<i class="iconfont icon-danseshixintubiao- move-icon"></i>
<svg-icon
icon-class="del"
class="ml10"
style="width: 0.9em; cursor: pointer"
></svg-icon>
<span>
<i class="iconfont icon-danseshixintubiao- move-icon fs16"></i>
</span>
<span>
<i
class="ml10 iconfont icon-delete fs14"
style="cursor: pointer"
@click="deleteCourse(index)"
></i>
</span>
<span @click="toggleCollapse(element)">
<svg-icon
<i
v-if="!element.isCollapsed"
icon-class="up"
class="ml10"
style="width: 0.9em; cursor: pointer"
></svg-icon>
<svg-icon
class="ml10 iconfont icon-up fs10"
style="cursor: pointer; display: inline-table"
></i>
<i
v-else
icon-class="up"
class="ml10"
style="width: 0.9em; cursor: pointer; transform: rotate(180deg)"
></svg-icon>
class="ml10 iconfont icon-up fs10"
style="cursor: pointer; transform: rotate(180deg)"
></i>
</span>
</div>
</div>
@@ -106,9 +163,17 @@ const moveStart = (e) => {
</template>
<style scoped lang="scss">
.icon-danseshixintubiao- {
.icon-danseshixintubiao-,
.icon-up,
.icon-edit {
&:hover {
color: #4284f7;
cursor: pointer;
}
}
.icon-delete {
&:hover {
color: #ff2626;
}
}
.drag-collapse {

View File

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