课程详情

develoop
lijiaqi 3 months ago
parent 53c5e56c7e
commit 3e36c4e65f
  1. 12
      src/api/user/object.js
  2. 4
      src/views/course/components/chapters-details.vue
  3. 12
      src/views/course/components/course-chapters.vue
  4. 138
      src/views/course/components/course-object.vue
  5. 25
      src/views/course/components/courseEdit.vue
  6. 40
      vite.config.ts.timestamp-1723381540521-cd7b5d4b77f62.mjs

@ -12,3 +12,15 @@ export const getObjectList = (params) => {
params,
})
}
// 删除课程目标
export const delObjectContents = (id) => {
return request.delete(`/api/objective_contents/${id}`)
}
// 添加课程目标
export const addObjectContents = (params) => {
return request.post(`/api/objective_contents/addcontent`, params)
}
// 查询目标内容
export const getObjectContent = (id) => {
return request.get(`/api/objective_contents/${id}`)
}

@ -28,7 +28,9 @@
padding: 20px;
p {
margin: 10px;
margin-bottom: 5px;
line-height: 1.5;
letter-spacing: 1px;
}
}
}

@ -140,8 +140,16 @@ const dataSource = ref<Tree[]>([
<span class="custom-tree-node">
<span @click="getDetails(data.id)">{{ data.name }}</span>
<span>
<el-button @click="append(data)">添加</el-button>
<el-button @click="remove(node, data)">删除</el-button>
<el-button @click="append(data)" circle size="small" type="primary" plain>
<el-icon :size="15">
<Plus />
</el-icon>
</el-button>
<el-button @click="remove(node, data)" circle size="small" type="danger" plain>
<el-icon :size="15">
<Delete />
</el-icon>
</el-button>
<!-- <a @click="append(data)"></a> -->
<!-- <a style="margin-left: 8px" @click="remove(node, data)">删除</a> -->
</span>

@ -2,8 +2,15 @@
import { ref, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Edit, Delete } from '@element-plus/icons-vue'
import { getObjectType, updateContents, getObjectList } from '@/api/user/object'
import {
updateContents,
getObjectList,
delObjectContents,
addObjectContents,
getObjectContent,
} from '@/api/user/object'
import { useRoute } from 'vue-router'
import { ITEM_RENDER_EVT } from 'element-plus/es/components/virtual-list/src/defaults.mjs'
const route = useRoute()
// const router = useRouter()
const courseId = ref(0)
@ -15,7 +22,7 @@ const params = ref({
id: '',
objectiveId: '',
})
//
//
const getObject = async () => {
const res = await getObjectList({ id: courseId.value })
console.log(res, 'objectres')
@ -26,21 +33,21 @@ const getObject = async () => {
console.log(data.value, 'data.value')
// content.value = res.data[0].contents[0].content
}
//
const type = ref({
id: '',
typeName: '',
})
const getType = async () => {
const res = await getObjectType()
type.value = res.data.slice(1, 5)
console.log(type.value, 'typeres')
}
// const type = ref({
// id: '',
// typeName: '',
// })
// const getType = async () => {
// const res = await getObjectType()
// type.value = res.data.slice(1, 5)
// console.log(type.value, 'typeres')
// }
onMounted(() => {
courseId.value = route.query.id
console.log(courseId.value, 'courseid.vlue')
getObject()
getType()
})
//
const isEditing = ref(false)
@ -84,6 +91,81 @@ const saveContent = async () => {
const cancelEdit = () => {
isEditing.value = false
}
//
const delObject = async (id: any) => {
await ElMessageBox.confirm('你确认要删除该课程目标吗', '温馨提示', {
type: 'warning',
confirmButtonText: '确认',
cancelButtonText: '取消',
})
await delObjectContents(id).then(() => {
ElMessage.success('删除成功')
getObject()
})
}
//
//
const formData = ref({
description: '',
})
//
const dialogVisible = ref(false)
//
const handleClose = () => {
dialogVisible.value = false
}
const close = () => {
formData.value = {
description: '',
}
dialogVisible.value = false
}
//
const flog = ref()
const objectiveIds = ref(0)
const addObject = (item: any) => {
// console.log(id, 'id')
dialogVisible.value = true
flog.value = false
formData.value.description = ''
// updateDisabledStatus()
objectiveIds.value = item.id
}
const editdata = ref({ id: '', objectiveId: '' })
const updateObjectContent = async (id: any) => {
dialogVisible.value = true
flog.value = true
const res = await getObjectContent(id)
formData.value.description = res.data.content
console.log(res, '回显res')
editdata.value.id = res.data.id
editdata.value.objectiveId = res.data.objectiveId
}
//
const submit = async () => {
if (formData.value.description === '') {
//
await ElMessage.error('内容不能为空')
return
}
if (flog.value) {
await updateContents({
...editdata.value,
content: formData.value.description,
})
ElMessage.success('编辑成功')
} else {
console.log(objectiveIds, 'objectiveIds')
await addObjectContents({
objectiveId: objectiveIds.value,
content: formData.value.description,
})
ElMessage.success('添加成功')
}
getObject()
dialogVisible.value = false
formData.value.description = ''
}
</script>
<template>
<div class="grid-content course-object" style="height: 450px">
@ -98,15 +180,13 @@ const cancelEdit = () => {
<el-card style="max-width: 480px">
<template #header>
<div class="card-header">
<span>课程总目标</span>
<span>整体目标</span>
<el-button type="primary" :icon="Edit" circle plain @click="updateContent"></el-button>
</div>
</template>
<div class="el-card__body" style="">
<div v-if="isEditing" class="editCon">
<textarea class="textarea" @change="textChange" v-model="content">
{{ params.content }}
</textarea>
<textarea class="textarea" v-model="content"></textarea>
<el-button type="primary" @click="saveContent">保存</el-button>
<el-button type="default" @click="cancelEdit">取消</el-button>
</div>
@ -124,7 +204,7 @@ const cancelEdit = () => {
<div class="left">
<div class="type">{{ item.name }}</div>
<div class="icon">
<el-icon>
<el-icon @click="addObject(item)">
<Plus />
</el-icon>
</div>
@ -134,8 +214,8 @@ const cancelEdit = () => {
<li v-for="(obj, i) in item.contents" :key="obj.id">
<span>目标{{ i + 1 }}{{ obj.content }}</span>
<div class="icon">
<el-button type="primary" :icon="Edit" circle size="small" plain />
<el-button type="danger" :icon="Delete" circle size="small" plain />
<el-button type="primary" :icon="Edit" circle size="small" plain @click="updateObjectContent(obj.id)" />
<el-button type="danger" :icon="Delete" circle size="small" plain @click="delObject(obj.id)" />
</div>
</li>
</el-scrollbar>
@ -144,6 +224,20 @@ const cancelEdit = () => {
<el-divider style="margin: 0; width: 100%" />
</li>
</ul>
<el-dialog v-if="dialogVisible" v-model="dialogVisible" :title="flog ? '编辑' : '新增'" width="500"
:before-close="handleClose">
<el-form :model="formData" label-width="auto" style="max-width: 600px">
<el-form-item label="内容" prop="description">
<el-input v-model="formData.description" placeholder="请输入内容"></el-input>
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button @click="close">取消</el-button>
<el-button type="primary" @click="submit">确定</el-button>
</div>
</template>
</el-dialog>
</div>
</div>
</div>
@ -204,8 +298,8 @@ const cancelEdit = () => {
}
.text {
font-size: 14px;
color: #8a8b99;
font-size: 16px;
color: #606169;
text-align: left;
line-height: 1.5;
letter-spacing: 1px;
@ -270,6 +364,7 @@ const cancelEdit = () => {
border-right: 1px solid #dcdfe6;
flex-wrap: wrap;
align-content: center;
letter-spacing: 1px;
.icon {
margin-left: 10px;
@ -295,6 +390,7 @@ const cancelEdit = () => {
align-items: center;
line-height: 1;
margin-top: 2px;
letter-spacing: 1px;
}
}
}

@ -128,32 +128,7 @@ const rules = {
},
],
}
//
// const validateUniqueCode = async (rule, value, callback) => {
// if (!value) {
// return callback() //
// }
// try {
// const response = await request(`/api/checkCourseCode?code=${value}`) //
// const data = await response.json()
// if (data.exists) {
// callback(new Error('使')) //
// } else {
// callback() //
// }
// } catch (error) {
// console.error(':', error)
// callback(new Error(''))
// }
// }
//
// const onSelectFile = (uploadFile) => {
// // console.log(uploadFile)
// imgUrl.value = URL.createObjectURL(uploadFile.raw)
// formModel.value.img = uploadFile.raw
// }
//
const nameDisabled = ref(false)
const codeDisabled = ref(false)

@ -0,0 +1,40 @@
// vite.config.ts
import vue from "file:///E:/jiaoxue/Teaching_integration_platform_admin_template/node_modules/.pnpm/@vitejs+plugin-vue@5.0.4_vite@5.1.4_vue@3.4.29/node_modules/@vitejs/plugin-vue/dist/index.mjs";
import path from "path";
import { viteMockServe } from "file:///E:/jiaoxue/Teaching_integration_platform_admin_template/node_modules/.pnpm/vite-plugin-mock@3.0.1_esbuild@0.19.12_mockjs@1.1.0_vite@5.1.4/node_modules/vite-plugin-mock/dist/index.mjs";
import { createSvgIconsPlugin } from "file:///E:/jiaoxue/Teaching_integration_platform_admin_template/node_modules/.pnpm/vite-plugin-svg-icons@2.0.1_vite@5.1.4/node_modules/vite-plugin-svg-icons/dist/index.mjs";
var vite_config_default = ({ command }) => {
return {
plugins: [
vue(),
viteMockServe({
enable: command === "serve"
}),
createSvgIconsPlugin({
// Specify the icon folder to be cached
iconDirs: [path.resolve(process.cwd(), "src/assets/icons")],
// Specify symbolId format
symbolId: "icon-[dir]-[name]"
})
],
resolve: {
alias: {
"@": path.resolve("./src")
// 相对路径别名配置,使用 @ 代替 src
}
},
// 配置scss
css: {
preprocessorOptions: {
scss: {
javascriptEnabled: true,
additionalData: '@import "./src/styles/variable.scss";'
}
}
}
};
};
export {
vite_config_default as default
};
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsidml0ZS5jb25maWcudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImNvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9kaXJuYW1lID0gXCJFOlxcXFxqaWFveHVlXFxcXFRlYWNoaW5nX2ludGVncmF0aW9uX3BsYXRmb3JtX2FkbWluX3RlbXBsYXRlXCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ZpbGVuYW1lID0gXCJFOlxcXFxqaWFveHVlXFxcXFRlYWNoaW5nX2ludGVncmF0aW9uX3BsYXRmb3JtX2FkbWluX3RlbXBsYXRlXFxcXHZpdGUuY29uZmlnLnRzXCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ltcG9ydF9tZXRhX3VybCA9IFwiZmlsZTovLy9FOi9qaWFveHVlL1RlYWNoaW5nX2ludGVncmF0aW9uX3BsYXRmb3JtX2FkbWluX3RlbXBsYXRlL3ZpdGUuY29uZmlnLnRzXCI7aW1wb3J0IHsgZGVmaW5lQ29uZmlnIH0gZnJvbSAndml0ZSdcclxuaW1wb3J0IHZ1ZSBmcm9tICdAdml0ZWpzL3BsdWdpbi12dWUnXHJcbmltcG9ydCBwYXRoIGZyb20gJ3BhdGgnXHJcbi8vIFx1NUJGQ1x1NTE2NW1vY2tcdTYzRDJcdTRFRjZcclxuaW1wb3J0IHsgdml0ZU1vY2tTZXJ2ZSB9IGZyb20gJ3ZpdGUtcGx1Z2luLW1vY2snXHJcbi8vIFx1NUJGQ1x1NTE2NXN2Z1x1OTE0RFx1N0Y2RVx1NjNEMlx1NEVGNlxyXG5pbXBvcnQgeyBjcmVhdGVTdmdJY29uc1BsdWdpbiB9IGZyb20gJ3ZpdGUtcGx1Z2luLXN2Zy1pY29ucydcclxuLy8gaHR0cHM6Ly92aXRlanMuZGV2L2NvbmZpZy9cclxuZXhwb3J0IGRlZmF1bHQgKHsgY29tbWFuZCB9OiBhbnkpID0+IHtcclxuICByZXR1cm4ge1xyXG4gICAgcGx1Z2luczogW1xyXG4gICAgICB2dWUoKSxcclxuICAgICAgdml0ZU1vY2tTZXJ2ZSh7XHJcbiAgICAgICAgZW5hYmxlOiBjb21tYW5kID09PSAnc2VydmUnLFxyXG4gICAgICB9KSxcclxuICAgICAgY3JlYXRlU3ZnSWNvbnNQbHVnaW4oe1xyXG4gICAgICAgIC8vIFNwZWNpZnkgdGhlIGljb24gZm9sZGVyIHRvIGJlIGNhY2hlZFxyXG4gICAgICAgIGljb25EaXJzOiBbcGF0aC5yZXNvbHZlKHByb2Nlc3MuY3dkKCksICdzcmMvYXNzZXRzL2ljb25zJyldLFxyXG4gICAgICAgIC8vIFNwZWNpZnkgc3ltYm9sSWQgZm9ybWF0XHJcbiAgICAgICAgc3ltYm9sSWQ6ICdpY29uLVtkaXJdLVtuYW1lXScsXHJcbiAgICAgIH0pLFxyXG4gICAgXSxcclxuICAgIHJlc29sdmU6IHtcclxuICAgICAgYWxpYXM6IHtcclxuICAgICAgICAnQCc6IHBhdGgucmVzb2x2ZSgnLi9zcmMnKSwgLy8gXHU3NkY4XHU1QkY5XHU4REVGXHU1Rjg0XHU1MjJCXHU1NDBEXHU5MTREXHU3RjZFXHVGRjBDXHU0RjdGXHU3NTI4IEAgXHU0RUUzXHU2NkZGIHNyY1xyXG4gICAgICB9LFxyXG4gICAgfSxcclxuICAgIC8vIFx1OTE0RFx1N0Y2RXNjc3NcclxuICAgIGNzczoge1xyXG4gICAgICBwcmVwcm9jZXNzb3JPcHRpb25zOiB7XHJcbiAgICAgICAgc2Nzczoge1xyXG4gICAgICAgICAgamF2YXNjcmlwdEVuYWJsZWQ6IHRydWUsXHJcbiAgICAgICAgICBhZGRpdGlvbmFsRGF0YTogJ0BpbXBvcnQgXCIuL3NyYy9zdHlsZXMvdmFyaWFibGUuc2Nzc1wiOycsXHJcbiAgICAgICAgfSxcclxuICAgICAgfSxcclxuICAgIH0sXHJcbiAgfVxyXG59XHJcbiJdLAogICJtYXBwaW5ncyI6ICI7QUFDQSxPQUFPLFNBQVM7QUFDaEIsT0FBTyxVQUFVO0FBRWpCLFNBQVMscUJBQXFCO0FBRTlCLFNBQVMsNEJBQTRCO0FBRXJDLElBQU8sc0JBQVEsQ0FBQyxFQUFFLFFBQVEsTUFBVztBQUNuQyxTQUFPO0FBQUEsSUFDTCxTQUFTO0FBQUEsTUFDUCxJQUFJO0FBQUEsTUFDSixjQUFjO0FBQUEsUUFDWixRQUFRLFlBQVk7QUFBQSxNQUN0QixDQUFDO0FBQUEsTUFDRCxxQkFBcUI7QUFBQTtBQUFBLFFBRW5CLFVBQVUsQ0FBQyxLQUFLLFFBQVEsUUFBUSxJQUFJLEdBQUcsa0JBQWtCLENBQUM7QUFBQTtBQUFBLFFBRTFELFVBQVU7QUFBQSxNQUNaLENBQUM7QUFBQSxJQUNIO0FBQUEsSUFDQSxTQUFTO0FBQUEsTUFDUCxPQUFPO0FBQUEsUUFDTCxLQUFLLEtBQUssUUFBUSxPQUFPO0FBQUE7QUFBQSxNQUMzQjtBQUFBLElBQ0Y7QUFBQTtBQUFBLElBRUEsS0FBSztBQUFBLE1BQ0gscUJBQXFCO0FBQUEsUUFDbkIsTUFBTTtBQUFBLFVBQ0osbUJBQW1CO0FBQUEsVUFDbkIsZ0JBQWdCO0FBQUEsUUFDbEI7QUFBQSxNQUNGO0FBQUEsSUFDRjtBQUFBLEVBQ0Y7QUFDRjsiLAogICJuYW1lcyI6IFtdCn0K
Loading…
Cancel
Save