新增讲师管理页面及crud操作

新增腾讯云cos对象存储
pull/254/head
xjs 3 years ago
parent 87d711fc67
commit 4a7dc5677b

@ -47,6 +47,7 @@
<mybatisplus.version>3.5.1</mybatisplus.version>
<commonsNet.version>3.6</commonsNet.version>
<aliyunoss.version>3.14.0</aliyunoss.version>
<tencentcos.version>5.6.54</tencentcos.version>
<bean-searcher.version>3.5.1</bean-searcher.version>
<oshi.version>5.7.1</oshi.version>
<webmagic.version>0.7.5</webmagic.version>

@ -69,6 +69,13 @@
<version>${aliyunoss.version}</version>
</dependency>
<!--腾讯云cos-->
<dependency>
<groupId>com.qcloud</groupId>
<artifactId>cos_api</artifactId>
<version>${tencentcos.version}</version>
</dependency>
<!-- RuoYi Api System -->
<dependency>
<groupId>com.ruoyi</groupId>
@ -100,4 +107,4 @@
</plugins>
</build>
</project>
</project>

@ -0,0 +1,37 @@
package com.ruoyi.file.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
*
* @author xiejs
* @since 2022-06-29
*/
@Data
@Component
@ConfigurationProperties(prefix = "tencent.cos.file")
public class TencentCosProperties {
/**
*
*/
private String region;
private String secretId;
private String secretKey;
/**
*
*/
private String bucketName;
private String endpoint;
}

@ -6,7 +6,6 @@ import com.ruoyi.common.core.text.UUID;
import com.ruoyi.common.core.utils.file.FileUploadUtils;
import com.ruoyi.file.utils.OssClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.web.multipart.MultipartFile;
@ -24,7 +23,7 @@ import static com.ruoyi.file.utils.OssClient.*;
* @since 2022-01-25
*/
@Service
@Primary
//@Primary
public class AliyunOssFileServiceImpl implements ISysFileService {
@Autowired

@ -0,0 +1,122 @@
package com.ruoyi.file.service;
import cn.hutool.core.date.DateUtil;
import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.BasicCOSCredentials;
import com.qcloud.cos.http.HttpProtocol;
import com.qcloud.cos.model.ObjectMetadata;
import com.qcloud.cos.model.PutObjectRequest;
import com.qcloud.cos.region.Region;
import com.ruoyi.common.core.text.UUID;
import com.ruoyi.common.core.utils.file.FileUploadUtils;
import com.ruoyi.file.config.TencentCosProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import static com.ruoyi.file.utils.OssClient.*;
/**
* cos
*
* @author xiejs
* @since 2022-06-29
*/
@Service
@Primary
public class TencentOssFileServiceImpl implements ISysFileService {
@Autowired
private TencentCosProperties tencentCosProperties;
@Override
public String uploadFile(MultipartFile file) throws Exception {
try {
COSClient cosClient = this.createCOSClient();
String bucketName = tencentCosProperties.getBucketName();
String endpoint = tencentCosProperties.getEndpoint();
//获取流
InputStream is = file.getInputStream();
//获取文件后缀
String extension = FileUploadUtils.getExtension(file);
//获取文件名称
String fileName = this.getDataTime() + DOT + extension;
ObjectMetadata objectMetadata = new ObjectMetadata();
PutObjectRequest putObjectRequest = new PutObjectRequest(
bucketName, fileName, is, objectMetadata
);
cosClient.putObject(putObjectRequest);
cosClient.shutdown();
//拼接文件地址
return HTTPS + bucketName + DOT + endpoint + SLASH + fileName;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
@Override
public void removeFile(String url) {
COSClient cosClient = this.createCOSClient();
String endpoint = tencentCosProperties.getEndpoint();
String bucketName = tencentCosProperties.getBucketName();
String host = HTTPS + bucketName + DOT + endpoint + SLASH;
//如果路径中不包含host
if (!url.contains(host)) {
return;
}
String objectName = url.substring(host.length());
cosClient.deleteObject(bucketName, objectName);
cosClient.shutdown();
}
/**
*
*
* @return
*/
private String getDataTime() {
String today = DateUtil.format(new Date(), "yyyy-MM");
return today + SLASH + UUID.randomUUID();
}
/**
*
*
* @return cosClient
*/
private COSClient createCOSClient() {
//初始化用户身份信息
String secretId = tencentCosProperties.getSecretId();
String secretKey = tencentCosProperties.getSecretKey();
String regionValue = tencentCosProperties.getRegion();
BasicCOSCredentials credentials = new BasicCOSCredentials(secretId, secretKey);
//设置bucket的地域
Region region = new Region(regionValue);
ClientConfig clientConfig = new ClientConfig(region);
clientConfig.setHttpProtocol(HttpProtocol.https);
//生成cos客户端
return new COSClient(credentials, clientConfig);
}
}

@ -0,0 +1,61 @@
import request from '@/utils/request'
const api_name = '/classroom-service-vod/admin/vod/teacher'
export default {
pageList(current, limit, searchObj) {
return request({
url: `${api_name}/findQueryPage/${current}/${limit}`,
method: 'post',
data: searchObj
})
},
//讲师删除
removeTeacherId(id) {
return request({
url: `${api_name}/remove/${id}`,
method: 'delete'
})
},
//讲师添加
saveTeacher(teacher) {
return request({
url: `${api_name}/saveTeacher`,
method: 'post',
data: teacher
})
},
//根据id查询
getTeacherById(id) {
return request({
url: `${api_name}/getTeacher/${id}`,
method: 'get'
})
},
//讲师修改
updateTeacher(teacher) {
return request({
url: `${api_name}/updateTeacher`,
method: 'post',
data: teacher
})
},
//批量删除
batchRemove(idList) {
return request({
url: `${api_name}/removeBatch`,
method: `delete`,
data: idList
})
},
//所有讲师
list() {
return request({
url: `${api_name}/findAll`,
method: `get`
})
}
}

@ -0,0 +1,232 @@
<template>
<div class="app-container">
<!-- 输入表单 -->
<el-form label-width="120px" :model="teacher" :rules="rules" ref="form">
<el-form-item label="讲师名称" prop="name">
<el-input v-model="teacher.name"/>
</el-form-item>
<el-form-item label="入驻时间" prop="joinDate">
<el-date-picker v-model="teacher.joinDate" value-format="yyyy-MM-dd"/>
</el-form-item>
<el-form-item label="讲师排序" prop="sort">
<el-input-number v-model="teacher.sort" :min="0"/>
</el-form-item>
<el-form-item label="讲师头衔" prop="level">
<el-select v-model="teacher.level">
<!--
数据类型一定要和取出的json中的一致否则没法回填
因此这里value使用动态绑定的值保证其数据类型是number
-->
<el-option :value="1" label="高级讲师"/>
<el-option :value="0" label="首席讲师"/>
</el-select>
</el-form-item>
<el-form-item label="讲师简介" prop="intro">
<el-input v-model="teacher.intro"/>
</el-form-item>
<el-form-item label="讲师资历" prop="career">
<el-input v-model="teacher.career" :rows="10" type="textarea"/>
</el-form-item>
<!-- 讲师头像 -->
<!-- 讲师头像 -->
<el-form-item label="讲师头像" prop="avatar">
<el-upload
ref="avatar"
:on-success="handleAvatarSuccess"
:before-upload="beforeAvatarUpload"
:on-error="handleAvatarError"
:http-request="requestUpload"
:file-list="fileList"
action="#"
:before-remove="removeImg"
:limit="1"
name="avatar"
list-type="picture-card" accept="image/*"
>
<i class="el-icon-plus"></i>
</el-upload>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="saveOrUpdate()"></el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
import teacherApi from '@/api/classroom/vod/teacher'
import {removeImg, uploadImg} from "@/api/common";
export default {
name: "TeacherForm",
data() {
return {
teacher: {
sort: 0,
level: 1,
avatar: null
},
fileList: [],
rules: {
name: [{
required: true,
message: '请输入讲师名称',
trigger: 'blur'
}, {min: 1, max: 10, message: '讲师名称长度在 1 到 10 个字符', trigger: 'blur'}],
joinDate: [{
required: true,
message: '请选择入驻时间',
trigger: 'blur'
}],
sort: [{
required: true,
message: '请选择讲师排序',
trigger: 'blur'
}],
level: [{
required: true,
message: '请输入讲师头衔',
trigger: 'blur'
}],
intro: [{min: 1, max: 50, message: '简介长度在 1 到 50 个字符', trigger: 'blur'}],
career: [{min: 1, max: 500, message: '资历长度在 1 到 500 个字符', trigger: 'blur'}],
},
}
},
created() {
//idid
if (this.$route.query.id) {
const id = this.$route.query.id
this.fetchDataById(id)
}
},
beforeDestroy() {
this.fileList = []
},
methods: {
//
handleAvatarSuccess(res, file) {
// console.log(res)
if (res.code === 200) {
// console.log(res)
this.teacher.avatar = res.data
//
this.$forceUpdate()
} else {
this.$message.error('上传失败 非0')
}
},
//
handleAvatarError() {
this.$message.error('上传失败http失败')
},
//
requestUpload() {
},
//
removeImg() {
if (this.teacher.avatar) {
let avatar = {"url": this.teacher.avatar};
removeImg(avatar).then(res => {
})
this.teacher.avatar = null;
}
},
//
beforeAvatarUpload(file) {
const isJPG = file.type === 'image/jpeg' || file.type === 'image/png'
const isLt2M = file.size / 1024 / 1024 < 5
if (!isJPG) {
this.$message.error('上传头像图片只能是 JPG或PNG 格式!')
return false
}
if (!isLt2M) {
this.$message.error('上传头像图片大小不能超过 5 MB!')
return false
}
let formData = new FormData();
formData.append("file", file);
this.$modal.loading("请稍候...");
uploadImg(formData).then(res => {
this.teacher.avatar = res.data.url
this.$modal.closeLoading()
this.$modal.notifySuccess("上传成功");
}).catch(err => {
this.$modal.closeLoading()
})
},
//id
fetchDataById(id) {
teacherApi.getTeacherById(id)
.then(response => {
this.teacher = response.data
this.fileList = []
this.fileList.push({
url: this.teacher.avatar
})
})
},
//
save() {
this.$refs["form"].validate(valid => {
if (valid) {
//
teacherApi.saveTeacher(this.teacher)
.then(response => {
//
this.$message({
type: 'success',
message: '添加成功!'
});
//
this.$router.push({path: '/classroom/classroom-teacher/teacher-list'})
})
}
})
},
//
update() {
this.$refs["form"].validate(valid => {
if (valid) {
teacherApi.updateTeacher(this.teacher)
.then(response => {
//
this.$message({
type: 'success',
message: '修改成功!'
});
//
this.$router.push({path: '/classroom/classroom-teacher/teacher-list'})
})
}
})
},
//
saveOrUpdate() {
if (!this.teacher.id) { //id
this.save()
} else { //id
this.update()
}
}
}
}
</script>

@ -0,0 +1,222 @@
<template>
<div class="app-container">
<!--查询表单-->
<el-card class="operate-container" shadow="never">
<el-form :inline="true" class="demo-form-inline">
<el-form-item label="名称">
<el-input v-model="searchObj.name" placeholder="讲师名"/>
</el-form-item>
<el-form-item label="头衔">
<el-select v-model="searchObj.level" clearable placeholder="头衔" @change="handleQuery">
<el-option value="1" label="高级讲师"/>
<el-option value="0" label="首席讲师"/>
</el-select>
</el-form-item>
<el-form-item label="入驻时间">
<el-date-picker
v-model="searchObj.joinDateBegin"
placeholder="开始时间"
value-format="yyyy-MM-dd"/>
</el-form-item>
<el-form-item label="-">
<el-date-picker
v-model="searchObj.joinDateEnd"
placeholder="结束时间"
value-format="yyyy-MM-dd"/>
</el-form-item>
<el-button type="primary" icon="el-icon-search" @click="fetchData()"></el-button>
<el-button type="default" @click="resetData()"></el-button>
</el-form>
</el-card>
<!-- 工具按钮 -->
<el-card class="operate-container" shadow="never">
<i class="el-icon-tickets" style="margin-top: 5px"></i>
<span style="margin-top: 5px">数据列表</span>
<el-button class="btn-add" @click="add()" style="margin-left: 10px;">添加</el-button>
<el-button class="btn-add" @click="batchRemove()"></el-button>
</el-card>
<!-- 表格 -->
<el-table
:data="list"
border
stripe
@selection-change="handleSelectionChange">
<el-table-column type="selection"/>
<el-table-column
label="#"
width="50">
<template slot-scope="scope">
{{ (page - 1) * limit + scope.$index + 1 }}
</template>
</el-table-column>
<el-table-column prop="name" label="名称" width="80" :show-overflow-tooltip="true"/>
<el-table-column label="头衔" width="90">
<template slot-scope="scope">
<el-tag v-if="scope.row.level === 1" type="success" size="mini"></el-tag>
<el-tag v-if="scope.row.level === 0" size="mini"></el-tag>
</template>
</el-table-column>
<el-table-column prop="intro" label="简介" :show-overflow-tooltip="true" align="center"/>
<el-table-column prop="sort" label="排序" width="60"/>
<el-table-column prop="joinDate" label="入驻时间" width="160"/>
<el-table-column label="操作" width="200" align="center">
<template slot-scope="scope">
<router-link :to="{path:'/classroom/classroom-teacher/teacher-form/',query:{id:scope.row.id}}">
<el-button type="text" size="mini">修改</el-button>
</router-link>
<el-button type="text" size="mini" @click="removeById(scope.row.id)"></el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页组件 -->
<el-pagination
:current-page="page"
:total="total"
:page-size="limit"
:page-sizes="[5, 10, 20, 30, 40, 50, 100]"
style="padding: 30px 0; text-align: center;"
layout="total, sizes, prev, pager, next, jumper"
@size-change="changePageSize"
@current-change="changeCurrentPage"
/>
</div>
</template>
<script>
import teacherApi from "@/api/classroom/vod/teacher";
export default {
name: "TeacherList",
data() {
return {
list: [],
total: 0,
page: 1,
limit: 10,
searchObj: {},
multipleSelection: []//
}
},
created() {
this.fetchData();
},
methods: {
fetchData() {
teacherApi.pageList(this.page, this.limit, this.searchObj).then(res => {
this.list = res.data.records
this.total = res.data.total
})
},
//
add() {
this.$router.push({path: '/classroom/classroom-teacher/teacher-form'})
},
//
changePageSize(size) {
this.limit = size
this.fetchData()
},
//
changeCurrentPage(page) {
this.page = page
this.fetchData()
},
//
resetData() {
this.searchObj = {}
this.fetchData()
},
//
handleSelectionChange(selection) {
this.multipleSelection = selection
},
//
removeById(id) {
this.$confirm('此操作将删除该讲师信息, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
//
teacherApi.removeTeacherId(id)
.then(response => {
//
this.$message({
type: 'success',
message: '删除成功!'
});
//
this.fetchData()
})
})
},
//
batchRemove() {
//
if (this.multipleSelection.length === 0) {
this.$message.warning('请选择要删除的记录!')
return
}
this.$confirm('此操作将删除该讲师信息, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
var idList = []
// [1,2,3]
//
for (var i = 0; i < this.multipleSelection.length; i++) {
var obj = this.multipleSelection[i]
var id = obj.id
//
idList.push(id)
}
//
teacherApi.batchRemove(idList)
.then(response => {
//
this.$message({
type: 'success',
message: '删除成功!'
});
//
this.fetchData()
})
})
},
handleQuery() {
this.page = 1
this.fetchData()
},
},
}
</script>
<style scoped>
</style>

@ -18,6 +18,12 @@
</properties>
<dependencies>
<dependency>
<groupId>com.xjs</groupId>
<artifactId>xjs-business-common</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>

@ -28,6 +28,12 @@
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>com.xjs</groupId>
<artifactId>xjs-business-common</artifactId>
</dependency>
</dependencies>
<build>

@ -30,11 +30,6 @@
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.xjs</groupId>
<artifactId>xjs-business-common</artifactId>
</dependency>
<!--日期时间工具-->
<dependency>
<groupId>joda-time</groupId>

Loading…
Cancel
Save