mirror of
https://codeup.aliyun.com/67762337eccfc218f6110e0e/vue/fe-manage.git
synced 2025-12-20 08:16:46 +08:00
feat(courselibrary): 增强课程章节编辑功能
- 添加章节标题编辑功能,支持输入框修改 - 实现章节删除确认弹窗及成功提示 - 更新拖拽组件属性配置,移除旧插槽用法 - 替换 SVG 图标为 iconfont 字体图标 - 引入新的图标样式和 hover 效果 - 优化 collapse 组件交互逻辑与样式表现 - 升级 iconfont 字体文件,新增多个图标定义
This commit is contained in:
@@ -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.
@@ -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>
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user