2026-07-09 17:59:22 +08:00

969 lines
27 KiB
Vue

<!-- 专项管理 -->
<template>
<div class="trainingData">
<div class="head">
<div class="one">
<p>专项名称:</p>
<el-input v-model="data.classroomModeData.name" placeholder="请输入专项名称" />
</div>
<div class="btn">
<p class="reset" @click="reset(0)">重置</p>
<p class="search" @click="search(0)">查询</p>
<p v-for="(item, index) in handelData" :key="index" :class="item.engName"
@click="handleClick(item.engName)">{{ item.chinName }}</p>
</div>
</div>
<div class="right">
<tableDetail :data="data.classroomModeData" v-if="data.classroomModeData.refreshTable"
@change-page="changePage" @edit="edit" @handle-size-change="handleSizeChange" @to-view="toView">
</tableDetail>
</div>
</div>
<!-- 添加编辑弹窗 -->
<commonDialog :list="data.dialogData" @cancle="cancle(0)">
<template #cont>
<div class="dialogManage">
<el-form ref="formRef" :model="data.dialogData.ruleForm" :rules="data.dialogData.rules"
label-width="120px" class="demo-ruleForm" size="default" status-icon>
<el-form-item label="专项名称:" prop="name">
<el-input v-model="data.dialogData.ruleForm.name" maxlength="32" style="width: 240px;"
placeholder="请输入专项名称" show-word-limit type="text" />
</el-form-item>
<el-form-item label="封面:" prop="photo">
<el-upload class="dl-avatar-uploader-min square" ref="uploadRef" action=""
:show-file-list="false" :before-upload="beforeImageUpload" :on-exceed="handleExceed"
list-type="picture" accept=".jpg,.jpeg,.png">
<el-image v-if="ruleForm.photo" :src="ruleForm.photo" class="avatar" style="width: 100px;height: 100px;"></el-image>
<p v-else style="color:#0486FE">点击封面照片</p>
</el-upload>
</el-form-item>
</el-form>
<!-- <p @click="Add" class="add">+ 添加</p> -->
</div>
</template>
</commonDialog>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import tableDetail from '@/views/specializedTeaching/specialManagement/components/table.vue';
import commonDialog from '@/components/commonDialog/index.vue';
import { useRoute } from 'vue-router';
import { useStore } from 'vuex';
import commonTable from '@/views/motionData/trainingData/components/commonTbale/index.vue';
import eventBus from '@/eventBus.js';
import * as _api from '@/api/TrainingData.js'
import * as _api1 from '@/api/grade';
import { ElMessage } from 'element-plus';
import axios from 'axios';
import { useRouter } from 'vue-router';
const route = useRoute();
let router = useRouter();
const formRef = ref(null) //表单ref
const detailEditDialogDataformRef = ref(null) //表单ref
const currentRoute = route.path; //获取当前页面路由
const store = useStore();
let buttons = store.getters.getPermission(currentRoute).permission;
let idCounter = 1; // 全局计数器
let idCounter1 = 1; // 全局教学视频计数器
let idCounter2 = 1; // 全局体能训练计数器
let currentViewId = ref(null)
let upStudyId = ref(null) //上传课程id
let detailEdit = ref({}) //详情编辑数据
const form = new FormData();//动作讲解
const form1 = new FormData();//动作练习
const form2 = new FormData();//体能训练
const photoForm = new FormData();
const uploadRef = ref(null)
const options = ref([
])
const ruleForm = ref({
id: 0,
name: '',
photo: ''
})
const handleExceed = (files) => {
photoForm.delete("file")
uploadRef.value!.clearFiles()
const file = files[0]
//file.uid = genFileId()
uploadRef.value!.handleStart(file)
}
const beforeImageUpload = (file) => {
console.log(ruleForm.value, 'ruleForm.value')
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function () {
photoForm.append("file", file);
AddPhoto(ruleForm.value)
};
reader.onerror = function (error) {
reject(error);
};
reader.onloadend = function () {
resolve(ruleForm.value.photo);
};
})
}
const projectData = ref([])
let contrast = {
'添加': 'Add',
// '编辑': 'Update'
} //对照表
let handelData = ref<any>([]) //接收处理后的按钮数据
buttons.map((i) => {
handelData.value.push({
engName: i,
chinName: '',
className: i
})
})
//给每个按钮添加中文名
for (let i in contrast) {
handelData.value.map((v) => {
if (v.engName == contrast[i]) {
v.chinName = i
}
})
}
//按钮排序
const customOrder = {
'Add': 1,
};
handelData.value.sort((a, b) => {
const orderA = customOrder[a.engName];
const orderB = customOrder[b.engName];
if (orderA < orderB) {
return -1;
} else if (orderA > orderB) {
return 1;
} else {
return 0;
}
});
console.log(handelData.value, 'handelData')
const data = ref({
classroomModeData: {
refreshTable: false,
name: '',
tableNeed: {
showoperate: true,
showEdit: true,
pageIndex: 1,
pageSize: 10,
total: 0,
height: '76vh',
tdHeight: '50.5px',
tableLabel: [
{
label: "序号",
prop: "ind",
},
{
label: "专项名称",
prop: "specialName",
},
{
label: "章节",
prop: "text",
},
],
tableData: [
],
},
},
dialogData: {
dialogVisible: false,
width: 800,
title: '添加',
ruleForm: {
id: 0,
name: '',
textName: '',
num: null,
startGrade: [],
endGrade: [],
subjects: null
},
rules: {
name: [{
required: true,
message: '请输入专项名称',
trigger: 'blur',
},],
startGrade: [{
type: 'array',
required: true,
message: '请选择',
trigger: 'change',
}],
endGrade: [{
type: 'array',
required: true,
message: '请选择',
trigger: 'change',
}],
subjects: [{
required: true,
message: '请选择',
trigger: 'change',
},],
// textName: [{
// required: true,
// message: '请输入单元章节名称',
// trigger: 'blur',
// },]
},
textDatas: [{
id: 1,
textName: '1单元',
num: null
}]
},
detailDialogData: {
dialogVisible: false,
width: 800,
title: '详情',
textName: '',
tableNeed: {
refresh: false,
showoperate: true,
showEdit: true,
showPagtion: 2,
needUploadTask: true,
pageIndex: 1,
pageSize: 10,
total: 0,
height: '50vh',
tdHeight: '30px',
tableLabel: [
{
label: "序号",
prop: "ind",
},
{
label: "章节",
prop: "text",
},
],
tableData: [
],
},
},
detailEditDialogData: {
dialogVisible: false,
width: 800,
title: '详情编辑',
ruleForm: {
name: '',
},
ruleForm1: {
name: '',
},
actionNames: [{
name: '',
id: 1,
actionName: '动作1名称:',
isPrice: false,
actionUrl: '',
actionUrl1: '',
}],
actionNames1: [{
name: '',
id: 1,
actionName: '训练1名称:',
actionUrl: '',
}],
videoUrl: null,
videoUrl1: null,
videoUrl2: null,
}
})
// 点击添加教学视频
function addVideo(val) {
if (val == 0) {
idCounter1++
data.value.detailEditDialogData.actionNames.push({
name: '',
id: idCounter1,
isPrice: false,
actionName: `动作${idCounter1}名称:`,
actionUrl: '',
actionUrl1: '',
})
console.log(data.value.detailEditDialogData.actionNames, 'data.value.detailEditDialogData.actionNames')
} else {
idCounter2++
data.value.detailEditDialogData.actionNames1.push({
name: '',
id: idCounter2,
actionName: `训练${idCounter2}名称:`,
actionUrl: '',
})
}
}
// 点击删除教学视频
function deleteAction(id, val) {
if (val == 0) {
console.log(data.value.detailEditDialogData.actionNames, ' data.value.detailEditDialogData.actionNames')
data.value.detailEditDialogData.actionNames = data.value.detailEditDialogData.actionNames.filter(item => item.id != id)
} else {
data.value.detailEditDialogData.actionNames1 = data.value.detailEditDialogData.actionNames1.filter(item => item.id != id)
}
}
// 点击添加
function handleClick(val) {
switch (val) {
case 'Add':
data.value.dialogData.dialogVisible = true
break
}
}
// 点击取消
function cancle(val) {
switch (val) {
case 0:
resetForm(formRef.value)
data.value.dialogData.dialogVisible = false
break
case 1:
data.value.detailDialogData.dialogVisible = false
break
case 2:
data.value.detailEditDialogData.dialogVisible = false
data.value.detailEditDialogData.actionNames = [{
name: '',
id: 1,
actionName: '动作1名称:',
isPrice: false,
actionUrl: '',
actionUrl1: '',
}]
data.value.detailEditDialogData.actionNames1 = [{
name: '',
id: 1,
actionName: '训练1名称:',
actionUrl: '',
}]
break
}
}
// 点击确定
// 点击重置
function reset(val) {
if (val == 0) {
data.value.classroomModeData.name = ''
data.value.classroomModeData.refreshTable = false
initList()
} else {
data.value.detailDialogData.textName = ''
data.value.detailDialogData.tableNeed.refresh = false
data.value.detailDialogData.tableNeed.tableData = []
GetSpecialChapterListApi(currentViewId.value)
}
}
// 点击查询
function search(val) {
if (val == 0) {
data.value.classroomModeData.refreshTable = false
initList()
} else {
data.value.detailDialogData.tableNeed.refresh = false
GetSpecialChapterListApi(currentViewId.value)
}
}
// 点击弹窗内的添加
function Add() {
console.log(data.value.dialogData.title, 'data.value.dialogData.title')
if (data.value.dialogData.title == '添加') {
idCounter++
data.value.dialogData.textDatas.push({
id: idCounter,
textName: `${idCounter}单元`,
num: null
})
console.log(data.value.dialogData.textDatas, 'data.value.dialogData.textDatas')
} else if (data.value.dialogData.title == '编辑') {
console.log(data.value.dialogData.textDatas, 'data.value.dialogData.textDatas')
data.value.dialogData.textDatas.push({
id: idCounter,
textName: `${data.value.dialogData.textDatas.length + 1}单元`,
num: null
})
}
}
// 重置表单校验
const resetForm = (formEl) => {
if (!formEl) return
formEl.resetFields()
data.value.dialogData.textDatas = [{
id: 1,
textName: '1单元',
num: null
}]
}
// 切换页码
function changePage(e) {
data.value.classroomModeData.tableNeed.pageIndex = e
}
// 点击编辑
function edit(e) {
console.log(e, 'e')
GetSpecialDetailsApi(e)
data.value.dialogData.dialogVisible = true
data.value.dialogData.title = '编辑'
}
// 点击上传课程
function upStudy(e) {
data.value.detailEditDialogData.title = '上传课程'
data.value.detailEditDialogData.dialogVisible = true
console.log(e, 'eeeeeeeeeeeeee')
upStudyId.value = e.chapterId
}
// 切换每页显示条数
function handleSizeChange(e) {
data.value.classroomModeData.tableNeed.pageSize = e
}
// 查看详情
function toView(e) {
console.log(e, 'toView');
router.push({
path: '/ropeJumping', // 跳转的目标页面路径
query: { id: e.id } // 通过 query 参数传递 e.id
});
}
// 点击详情内的查看详情
function toViewDetail(e) {
console.log(e, 'eeeeeeeeeeee')
eventBus.emit('specialDetails', e);
}
onMounted(() => {
initList()
// GetGradeNames()
// SportsGetGradeNamesApi()
})
// 专项教学列表
async function initList() {
try {
const res = await _api.GetSpecialList(data.value.classroomModeData.name, data.value.classroomModeData.tableNeed.pageIndex, data.value.classroomModeData.tableNeed.pageSize);
if (res.code == 200) {
console.log(res.data, 'initList')
let k = JSON.parse(JSON.stringify(res.data.datas))
k?.map((i, index) => {
i.ind = data.value.classroomModeData.tableNeed.pageSize * (data.value.classroomModeData.tableNeed.pageIndex - 1) + index + 1
})
data.value.classroomModeData.tableNeed.total = res.data.total
data.value.classroomModeData.tableNeed.tableData = k
data.value.classroomModeData.refreshTable = true
}
} catch (error) {
console.error('Error occurred while calling API:', error);
}
}
// 编辑的详情列表
async function GetSpecialDetailsApi(e) {
try {
const res = await _api.GetSpecialDetails(e.id);
if (res.code == 200) {
console.log(res.data, 'GetSpecialDetailsApi')
let k = JSON.parse(JSON.stringify(res.data))
data.value.dialogData.ruleForm.name = res.data.specialName
data.value.dialogData.ruleForm.id = res.data.id
data.value.dialogData.ruleForm.startGrade = [res.data.unitChapterList[0].startGrade, 1]
data.value.dialogData.ruleForm.endGrade = [res.data.unitChapterList[0].endGrade, 1]
data.value.dialogData.ruleForm.subjects = res.data.unitChapterList[0].subjects
// data.value.dialogData.ruleForm.textName = e.text
data.value.dialogData.textDatas = res.data.unitChapterList.map(item => {
return {
id: item.id,
textName: item.unitName,
num: item.chapterNumber,
}
})
}else{
ElMessage.error(res.message)
}
} catch (error) {
console.error('Error occurred while calling API:', error);
}
}
// 编辑专项教学
async function updateList() {
let k = {
"id": 0,
"specialName": "",
"unitChapterList": [
{
"id": 0,
"unitName": "",
"chapterNumber": 0,
"startGrade": 0,
"endGrade": 0,
"subjects": 0
}
]
}
k.id = data.value.dialogData.ruleForm.id
k.specialName = data.value.dialogData.ruleForm.name
k.unitChapterList = data.value.dialogData.textDatas.map(item => {
return {
"id": item.id,
"unitName": item.textName,
"chapterNumber": item.num,
"startGrade": data.value.dialogData.ruleForm.startGrade[0],
"endGrade": data.value.dialogData.ruleForm.endGrade[0],
"subjects": data.value.dialogData.ruleForm.subjects
}
})
// console.log(k, 'k')
// return
try {
const res = await _api.ModifySpecial(k);
console.log(res, 'essss')
if (res.code == 200) {
console.log(res.data, 'initList')
ElMessage.success('编辑成功')
data.value.dialogData.dialogVisible = false
data.value.classroomModeData.refreshTable = false
initList()
resetForm(formRef.value)
} else {
ElMessage.error(res.message)
}
} catch (error) {
console.error('Error occurred while calling API:', error);
}
}
// 列表详情
async function GetSpecialChapterListApi(e) {
try {
const res = await _api.GetSpecialChapterList(e, data.value.detailDialogData.textName, 1, 100000);
if (res.code == 200) {
console.log(res.data, 'GetSpecialDetailsApi')
data.value.detailDialogData.tableNeed.tableData = res.data.datas
data.value.detailDialogData.tableNeed.tableData.map((i, index) => {
i.ind = index + 1
i.text = (`${i.unitName}-${i.chapterName}`)
})
data.value.detailDialogData.tableNeed.refresh = true
}else{
ElMessage.error(res.message)
}
} catch (error) {
console.error('Error occurred while calling API:', error);
}
}
function checkCompleteInfo(k) {
for (const i of k.specialCourseList) {
for (const v of i.specialExplainList) {
if (!v.explainName) {
ElMessage.error('请将信息填写完整');
return false; // 提前退出
}
for (const m of v.specialVideoList) {
if (!m.videoPath) {
ElMessage.error('请将信息填写完整');
return false; // 提前退出
}
}
}
}
return true; // 如果所有信息都完整,则返回 true
}
async function AddPhoto(val) {
console.log(photoForm, 'photoForm')
const options = {
method: 'POST',
url: `/api/Special/UploadImage`,
headers: {
Accept: '',
'content-type': 'multipart/form-data; boundary=---011000010111000001101001'
},
data: photoForm
};
let k = data.value as any
axios.request(options).then(function (response) {
if (response.data.code == 200) {
const newUrl = response.data.data + '?timestamp=' + new Date().getTime();
ruleForm.value.photo = newUrl;
Reflect.set(ruleForm, "coverImage", newUrl);
photoForm.delete("file")
} else {
ElMessage.error(response.data.message)
photoForm.delete("file")
}
}).catch(function (error) {
console.error(error, 'errororor');
});
}
</script>
<style lang="less" scoped>
.trainingData {
width: 100%;
height: auto;
.head {
width: calc(100% - 32px);
height: auto;
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: space-between;
background-color: #fff;
border-radius: 8px;
margin: 12px auto;
.one {
width: 350px;
height: 100%;
display: flex;
align-items: center;
// margin-right: 20px;
margin-left: 20px;
margin-top: 10px;
p {
width: 100px;
text-align: center;
font-family: PingFangSC;
font-weight: 400;
font-size: 14px;
color: rgba(0, 0, 0, 0.85);
}
:deep(.el-cascader) {
width: 280px !important;
height: 40px !important;
.el-input {
width: 100%;
height: 100%;
}
}
:deep(.el-input),
:deep(.el-date-editor) {
width: 280px !important;
height: 40px !important;
}
}
.btn {
// width: 700px;
display: flex;
align-items: center;
justify-content: right;
// margin-right: 20px;
p {
margin: 0 20px 0 0px;
}
.reset {
width: 95px;
height: 40px;
background: #FAFAFA;
border-radius: 8px;
border: 1px solid rgba(0, 0, 0, 0.15);
font-family: PingFangSC;
font-weight: 400;
font-size: 14px;
color: rgba(0, 0, 0, 0.65);
text-align: center;
line-height: 40px;
margin-right: 20px;
cursor: pointer;
user-select: none;
}
.search,
.Add {
width: 95px;
height: 40px;
background: #4188FE;
border-radius: 8px;
border: 1px solid rgba(0, 0, 0, 0.15);
font-family: PingFangSC;
font-weight: 400;
font-size: 14px;
color: #fff;
text-align: center;
line-height: 40px;
cursor: pointer;
user-select: none;
}
}
}
.right {
width: 100%;
height: 100%;
}
}
.dialogManage {
.topIpt {
width: 100%;
height: 40px;
display: flex;
align-items: center;
margin-bottom: 20px;
.left {
width: calc(100% - 200px);
display: flex;
align-items: center;
margin-left: 20px;
p {
margin-right: 5px;
}
}
.right {
width: 200px;
display: flex;
.reset {
width: 75px;
height: 30px;
background: #FAFAFA;
border-radius: 8px;
border: 1px solid rgba(0, 0, 0, 0.15);
font-family: PingFangSC;
font-weight: 400;
font-size: 14px;
color: rgba(0, 0, 0, 0.65);
text-align: center;
line-height: 30px;
margin-right: 20px;
cursor: pointer;
user-select: none;
}
.search {
width: 75px;
height: 30px;
background: #4188FE;
border-radius: 8px;
border: 1px solid rgba(0, 0, 0, 0.15);
font-family: PingFangSC;
font-weight: 400;
font-size: 14px;
color: #fff;
text-align: center;
line-height: 30px;
cursor: pointer;
user-select: none;
}
}
}
.demo-ruleForm {
:deep(.el-form-item) {
display: flex;
// align-items: start;
}
:deep(.el-input) {
// width: 240px;
height: 40px;
}
:deep(.el-input-number) {
margin-left: 20px;
}
:deep(.el-input-number__decrease),
:deep(.el-input-number__increase) {
height: 20px !important;
}
.chapter {
display: flex;
align-items: center;
width: 100%;
height: 40px;
margin-bottom: 10px;
p {
margin-left: 20px;
font-family: PingFangSC;
font-weight: 400;
font-size: 18px;
color: rgba(0, 0, 0, 0.65);
}
}
.headIpt {
width: 100%;
display: flex;
align-items: center;
img {
width: 20px;
height: 20px;
margin-left: 10px;
cursor: pointer;
user-select: none;
}
}
.addVideo {
width: calc(100% - 420px);
height: 40px;
display: flex;
align-items: center;
justify-content: center;
p {
width: 95px;
height: 40px;
background: #4188FE;
border-radius: 8px;
border: 1px solid rgba(0, 0, 0, 0.15);
font-family: PingFangSC;
font-weight: 400;
font-size: 14px;
color: #fff;
text-align: center;
line-height: 40px;
cursor: pointer;
user-select: none;
}
}
}
.top {
margin-bottom: 20px;
.title {
width: 100%;
height: 20px;
font-family: PingFangSC;
font-weight: 400;
font-size: 18px;
color: rgba(0, 0, 0, 0.65);
display: flex;
align-items: center;
margin-left: 40px;
margin-top: 0;
}
.tab {
width: calc(100% - 190px);
display: flex;
align-items: center;
justify-content: space-between;
// margin-left: 40px;
.leftOne,
.rightOne {
width: calc(100% / 2.1);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
// margin-left: 40px;
margin-top: 20px;
img {
width: 50px;
height: 50px;
margin-bottom: 20px;
}
.titles {
width: 100%;
height: 40px;
text-align: center;
line-height: 40px;
background-color: #4188FE;
color: #fff;
font-family: PingFangSC;
font-weight: 400;
font-size: 14px;
// cursor: pointer;
user-select: none;
}
.video {
position: relative;
.dialogClose {
position: absolute;
top: 10px;
right: 10px;
img {
width: 20px;
height: 20px;
cursor: pointer;
user-select: none;
}
}
}
}
}
}
.add {
width: 95px;
height: 40px;
background: #FAFAFA;
border-radius: 8px;
border: 1px solid rgba(0, 0, 0, 0.15);
font-family: PingFangSC;
font-weight: 400;
font-size: 14px;
color: rgba(0, 0, 0, 0.65);
text-align: center;
line-height: 40px;
margin-right: 20px;
cursor: pointer;
user-select: none;
margin-left: 120px;
}
}
</style>