mirror of
https://codeup.aliyun.com/67762337eccfc218f6110e0e/vue/fe-manage.git
synced 2025-12-09 10:56:46 +08:00
新增教师节
This commit is contained in:
63
src/api/configPublic.js
Normal file
63
src/api/configPublic.js
Normal file
@@ -0,0 +1,63 @@
|
||||
|
||||
import { message } from "ant-design-vue";
|
||||
import axios from "axios";
|
||||
import router from "@/router";
|
||||
import Cookies from 'vue-cookies'
|
||||
|
||||
axios.defaults.withCredentials = true;
|
||||
const http = axios.create({
|
||||
timeout: 1000 * 15,
|
||||
headers: { "Content-Type": "application/json", },
|
||||
});
|
||||
|
||||
http.interceptors.request.use(
|
||||
(config) => {
|
||||
const token = Cookies.get("token")
|
||||
if (token) {
|
||||
config.headers.token = token; //测试1111
|
||||
} else {
|
||||
message.error('未获取到登录信息,请先登录')
|
||||
}
|
||||
return config;
|
||||
},
|
||||
(err) => {
|
||||
console.log("登陆前拦截", err);
|
||||
return Promise.reject(err);
|
||||
}
|
||||
);
|
||||
|
||||
http.interceptors.response.use(
|
||||
(response) => {
|
||||
// console.log('response', response)
|
||||
const {
|
||||
data: { code },
|
||||
} = response;
|
||||
if (code === 0 || code === 200) {
|
||||
return response.data ? response.data : response;
|
||||
}
|
||||
if (code == 500) {
|
||||
return message.error('请求失败');
|
||||
}
|
||||
if (code == 601) {
|
||||
message.error('token过期请重新登陆');
|
||||
}
|
||||
if (code === 1000) {
|
||||
(process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'alpine') ? router.push({ path: 'login' }) : (window.location.href = process.env.VUE_APP_LOGIN_URL)
|
||||
return Promise.reject(response);
|
||||
}
|
||||
// show && message.error(msg);
|
||||
// console.log("api %o", msg);
|
||||
// return Promise.reject(response);
|
||||
return response
|
||||
},
|
||||
function (error) {
|
||||
if (error.message == "timeout of 1ms exceeded") {
|
||||
message.destroy();
|
||||
message.error("请求超时");
|
||||
}
|
||||
console.log("api error %o", error);
|
||||
return message.error(error.message);
|
||||
}
|
||||
);
|
||||
|
||||
export default http;
|
||||
113
src/api/grateful.js
Normal file
113
src/api/grateful.js
Normal file
@@ -0,0 +1,113 @@
|
||||
import http from './configPublic'
|
||||
const ACTIVITYAPI = '/activityApi'
|
||||
/**
|
||||
* 通知
|
||||
*/
|
||||
//通知列表
|
||||
const noticeList = (data = {}) => http.post(`${ACTIVITYAPI}/xboe/m/boe/notice/list`, data);
|
||||
//通知新增或修改
|
||||
const noticeAddAndUpdate = (data = {}) => http.post(`${ACTIVITYAPI}/xboe/m/boe/notice/save`, data);
|
||||
//通知删除
|
||||
const noticeDelete = (params) => http.delete(`${ACTIVITYAPI}/xboe/m/boe/notice/delete`, { params });
|
||||
//通知根据id查询
|
||||
const noticeDataById = (params) => http.get(`${ACTIVITYAPI}/xboe/m/boe/notice/getDataById`, { params });
|
||||
|
||||
|
||||
/**
|
||||
* 轮播图
|
||||
*/
|
||||
//轮播图列表
|
||||
const carouselList = `${ACTIVITYAPI}/xboe/m/boe/rotation/list`
|
||||
//轮播图新增或修改
|
||||
const carouseAddAndUpdate = (data = {}) => http.post(`${ACTIVITYAPI}/xboe/m/boe/rotation/save`, data);
|
||||
//轮播图删除
|
||||
const carouseDelete = (params) => http.delete(`${ACTIVITYAPI}/xboe/m/boe/rotation/delete`, { params });
|
||||
//轮播图删除
|
||||
const getCarouseById = (params) => http.get(`${ACTIVITYAPI}/xboe/m/boe/rotation/getDataById`, { params });
|
||||
|
||||
|
||||
/**
|
||||
* 教师赋能
|
||||
*/
|
||||
//教师赋能列表
|
||||
const courselList = `${ACTIVITYAPI}/xboe/m/boe/course/list`
|
||||
//添加赋能选择课程接口
|
||||
const addCourselList = (data = {}) => http.post(`${process.env.VUE_APP_SYS_API}/xboe/m/course/fulltext/search`, data, {
|
||||
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
||||
});
|
||||
//取消赋能
|
||||
const courseDelete = (params) => http.delete(`${ACTIVITYAPI}/xboe/m/boe/course/disEnabled`, { params });
|
||||
//获取已有课程id集合
|
||||
const courseIds = (params) => http.get(`${ACTIVITYAPI}/xboe/m/boe/course/ids`, { params });
|
||||
//批量增加课程
|
||||
const saveCourseList = (data = {}) => http.post(`${ACTIVITYAPI}/xboe/m/boe/course/saveList`, data);
|
||||
|
||||
|
||||
/**
|
||||
* 工具
|
||||
*/
|
||||
//工具列表
|
||||
const toolList = (data = {}) => http.post(`${ACTIVITYAPI}/xboe/m/boe/tools/list`, data);
|
||||
//新增工具
|
||||
const saveTool = (data = {}) => http.post(`${ACTIVITYAPI}/xboe/m/boe/tools/save`, data);
|
||||
//工具删除
|
||||
const toolDelete = (params) => http.delete(`${ACTIVITYAPI}/xboe/m/boe/tools/delete`, { params });
|
||||
//工具下载
|
||||
const toolDown = (params) => http.get(`/systemapi/xboe/sys/xuploader/url/download`, { params });
|
||||
|
||||
|
||||
/**
|
||||
* 师资大全
|
||||
*/
|
||||
//师资大全列表
|
||||
const teachersList = `${ACTIVITYAPI}/xboe/m/boe/teachers/list`
|
||||
//师资大全列表添加和编辑接口
|
||||
const teachersAddAndUpdate = (data = {}) => http.post(`${ACTIVITYAPI}/xboe/m/boe/teachers/save`, data);
|
||||
//教师删除
|
||||
const teachersDelete = (params) => http.delete(`${ACTIVITYAPI}/xboe/m/boe/teachers/delete`, { params });
|
||||
|
||||
|
||||
/**
|
||||
* 意见
|
||||
*/
|
||||
//意见列表
|
||||
const opinionList = `${ACTIVITYAPI}/xboe/m/boe/opinion/list`
|
||||
//意见删除
|
||||
const opinionDelete = (params) => http.delete(`${ACTIVITYAPI}/xboe/m/boe/opinion/delete`, { params });
|
||||
|
||||
//查看当前协议
|
||||
//type 查看的类型
|
||||
const query = (type) => http.get('/systemapi/xboe/m/assistance/protocol/query?type=' + type);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
const RECOMMEND_PAGE = "/systemapi/xboe/m/boe/cases/recommend/page";
|
||||
export {
|
||||
RECOMMEND_PAGE,
|
||||
noticeList,
|
||||
noticeDelete,
|
||||
noticeAddAndUpdate,
|
||||
noticeDataById,
|
||||
carouselList,
|
||||
carouseAddAndUpdate,
|
||||
carouseDelete,
|
||||
getCarouseById,
|
||||
courselList,
|
||||
courseIds,
|
||||
saveCourseList,
|
||||
addCourselList,
|
||||
courseDelete,
|
||||
toolList,
|
||||
saveTool,
|
||||
toolDelete,
|
||||
toolDown,
|
||||
teachersList,
|
||||
teachersAddAndUpdate,
|
||||
teachersDelete,
|
||||
opinionList,
|
||||
opinionDelete,
|
||||
query
|
||||
}
|
||||
BIN
src/assets/images/navleft/grateful.png
Normal file
BIN
src/assets/images/navleft/grateful.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 327 B |
File diff suppressed because it is too large
Load Diff
396
src/components/Grateful/AddTeacherInfo.vue
Normal file
396
src/components/Grateful/AddTeacherInfo.vue
Normal file
@@ -0,0 +1,396 @@
|
||||
<template>
|
||||
<a-drawer class="recommend" v-model:visible="visible" width="80%" title="添加教师" @close="closeDrawer"
|
||||
:maskClosable="false">
|
||||
<div class="cstm_items">
|
||||
<div class="signbox">
|
||||
<div class="sign">
|
||||
<img src="@/assets/images/coursewareManage/asterisk.png" alt="" />
|
||||
</div>
|
||||
<span style="margin-right: 3px">姓名</span>
|
||||
</div>
|
||||
<div class="b_input">
|
||||
<a-input v-model:value="formData.teacherName" maxlength="50"
|
||||
style="width: 88%; height: 40px; border-radius: 8px" placeholder="请输入教师姓名" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="cstm_items">
|
||||
<div class="signbox">
|
||||
<span style="margin-right: 3px">工号</span>
|
||||
</div>
|
||||
<div class="b_input">
|
||||
<a-input v-model:value="formData.teacherNo" maxlength="50"
|
||||
style="width: 88%; height: 40px; border-radius: 8px" placeholder="请输入教师工号" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="cstm_items">
|
||||
<div class="signbox">
|
||||
<div class="sign">
|
||||
<img src="@/assets/images/coursewareManage/asterisk.png" alt="" />
|
||||
</div>
|
||||
<span style="margin-right: 3px">课程名称</span>
|
||||
</div>
|
||||
<div class="b_input">
|
||||
<a-input v-model:value="formData.courseName" placeholder="请输入课程名称" show-count
|
||||
style="width: 88%; height: 40px; border-radius: 8px" :maxlength="30" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="cstm_items">
|
||||
<div class="signbox">
|
||||
<div class="sign">
|
||||
<img src="@/assets/images/coursewareManage/asterisk.png" alt="" />
|
||||
</div>
|
||||
<span style="margin-right: 3px">授课时长</span>
|
||||
</div>
|
||||
<div class="b_input">
|
||||
<a-input v-model:value="formData.teacherTime" maxlength="50"
|
||||
style="width: 88%; height: 40px; border-radius: 8px" placeholder="请输入授课时长">
|
||||
<template #suffix>
|
||||
<div class="inp_num">
|
||||
<span style="color: #c7cbd2">/h</span>
|
||||
</div>
|
||||
</template>
|
||||
</a-input>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="cstm_items">
|
||||
<div class="signbox">
|
||||
<span style="margin-right: 3px">教师等级</span>
|
||||
</div>
|
||||
<div class="b_input">
|
||||
<a-input-number style="width: 88%; height: 40px; line-height: 40px; border-radius: 8px" :min="0"
|
||||
:max="999999" placeholder="请输入教师等级" :precision="0" v-model:value="formData.teacherLevel">
|
||||
</a-input-number>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cstm_items">
|
||||
<div class="signbox">
|
||||
<span style="margin-right: 3px">组织全路径</span>
|
||||
</div>
|
||||
<div class="b_input">
|
||||
<a-input v-model:value="formData.orgPath" maxlength="50"
|
||||
style="width: 88%; height: 40px; border-radius: 8px" placeholder="请输入组织全路径" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="cstm_items">
|
||||
<div class="signbox">
|
||||
<div class="sign">
|
||||
<img src="@/assets/images/coursewareManage/asterisk.png" alt="" />
|
||||
</div>
|
||||
<span style="margin-right: 3px">排序</span>
|
||||
</div>
|
||||
<div class="b_input">
|
||||
<a-input-number style="width: 88%; height: 40px; line-height: 40px; border-radius: 8px" :min="0"
|
||||
:max="999999" :precision="0" v-model:value="formData.sort">
|
||||
</a-input-number>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cstm_items" style="align-items: start;">
|
||||
<div class="signbox">
|
||||
<div class="sign">
|
||||
<img src="@/assets/images/coursewareManage/asterisk.png" alt="" />
|
||||
</div>
|
||||
<span style="margin-right: 3px">课程价值</span>
|
||||
</div>
|
||||
<div class="b_input">
|
||||
<a-textarea v-model:value="formData.meaning" showCount :maxlength="30"
|
||||
:auto-size="{ minRows: 5, maxRows: 5 }" style="width: 88%; border-radius: 8px" placeholder="请输入课程价值" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="items_btn">
|
||||
<div class="cstm_btn btn6" @click="closeDrawer">
|
||||
<div class="btnText">取消</div>
|
||||
</div>
|
||||
<a-button class="cstm_btn btn6" @click="submit">
|
||||
确定
|
||||
</a-button>
|
||||
</div>
|
||||
</a-drawer>
|
||||
<a-button type="link" @click="openDrawer">
|
||||
<slot></slot>
|
||||
</a-button>
|
||||
</template>
|
||||
<script setup>
|
||||
import { nextTick, ref, toRaw, watch, reactive } from 'vue';
|
||||
import { Form, message } from "ant-design-vue";
|
||||
import { useResetRef } from "@/utils/useCommon";
|
||||
import { teachersAddAndUpdate } from '@/api/grateful';
|
||||
const formData = useResetRef({
|
||||
courseName: "",
|
||||
enabled: false,
|
||||
id: '',
|
||||
meaning: "",
|
||||
orgPath: "",
|
||||
sort: 1000,
|
||||
teacherLevel: "",
|
||||
teacherName: "",
|
||||
teacherNo: "",
|
||||
teacherTime: ""
|
||||
});
|
||||
const emit = defineEmits(['getList'])
|
||||
const visible = ref(false);
|
||||
const formDataRule = {
|
||||
teacherName: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入姓名",
|
||||
},
|
||||
],
|
||||
courseName: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入课程名称",
|
||||
},
|
||||
],
|
||||
teacherTime: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入授课时长",
|
||||
},
|
||||
],
|
||||
sort: [
|
||||
{
|
||||
required: true,
|
||||
message: "请选择排序",
|
||||
},
|
||||
],
|
||||
meaning: [
|
||||
{
|
||||
required: true,
|
||||
message: "请输入课程价值",
|
||||
},
|
||||
]
|
||||
};
|
||||
const { validate } = Form.useForm(formData, formDataRule);
|
||||
|
||||
// 取消抽屉
|
||||
const closeDrawer = async () => {
|
||||
visible.value = false
|
||||
}
|
||||
const openDrawer = async () => {
|
||||
await formData.reset()
|
||||
console.log('哈哈哈');
|
||||
visible.value = true;
|
||||
};
|
||||
const submit = async () => {
|
||||
await validate().catch(({ errorFields }) => {
|
||||
message.error(errorFields[0].errors.join());
|
||||
throw Error("数据校验不通过");
|
||||
});
|
||||
const result = await teachersAddAndUpdate(formData.value)
|
||||
if (result.code == 200) {
|
||||
visible.value = false;
|
||||
message.success("添加成功!");
|
||||
emit('getList')
|
||||
} else {
|
||||
message.error("添加失败!");
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.items_btn {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: 20px;
|
||||
margin-bottom: 20px;
|
||||
|
||||
.cstm_btn {
|
||||
width: 100px;
|
||||
height: 40px;
|
||||
background: rgba(64, 158, 255, 0);
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 14px;
|
||||
flex-shrink: 0;
|
||||
cursor: pointer;
|
||||
|
||||
.btnText {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
line-height: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
.btn5 {
|
||||
border: 1px solid rgba(64, 158, 255, 1);
|
||||
color: #4ea6ff;
|
||||
}
|
||||
|
||||
.btn6 {
|
||||
background-color: #4ea6ff;
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
|
||||
.recommend {
|
||||
:global(.ant-drawer-header-title) {
|
||||
flex-direction: row-reverse !important;
|
||||
}
|
||||
|
||||
:global(.ant-drawer-close) {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.btnn {
|
||||
height: 72px;
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
background-color: #fff;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: 0px 1px 35px 0px rgba(118, 136, 166, 0.16);
|
||||
|
||||
.btn1 {
|
||||
width: 100px;
|
||||
height: 40px;
|
||||
border: 1px solid #4ea6ff;
|
||||
border-radius: 8px;
|
||||
color: #4ea6ff;
|
||||
background-color: #fff;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.btn2 {
|
||||
cursor: pointer;
|
||||
width: 100px;
|
||||
height: 40px;
|
||||
background: #4ea6ff;
|
||||
border-radius: 8px;
|
||||
border: 0;
|
||||
margin-left: 15px;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
// 头部
|
||||
.filter {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.filterItems {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.select {
|
||||
margin-right: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.btn {
|
||||
padding: 0 26px 0 26px;
|
||||
height: 38px;
|
||||
background: #4ea6ff;
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 14px;
|
||||
flex-shrink: 0;
|
||||
cursor: pointer;
|
||||
|
||||
.search {
|
||||
background-size: 100%;
|
||||
}
|
||||
|
||||
.btnText {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #ffffff;
|
||||
line-height: 36px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.btnn {
|
||||
padding: 0 26px 0 26px;
|
||||
height: 38px;
|
||||
background: #4ea6ff;
|
||||
border-radius: 8px;
|
||||
border: 1px solid rgba(64, 158, 255, 1);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 14px;
|
||||
flex-shrink: 0;
|
||||
cursor: pointer;
|
||||
|
||||
.search {
|
||||
background-size: 100%;
|
||||
}
|
||||
|
||||
.btnText {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #fff;
|
||||
line-height: 36px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.btn1 {
|
||||
.search {
|
||||
width: 15px;
|
||||
height: 17px;
|
||||
background-image: url("../../assets/images/courseManage/search0.png");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.btn1:active {
|
||||
background: #0982ff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.cstm_items {
|
||||
display: flex;
|
||||
width: 80%;
|
||||
margin: auto;
|
||||
align-items: center;
|
||||
margin-bottom: 23px;
|
||||
|
||||
.signbox {
|
||||
display: flex;
|
||||
justify-content: end;
|
||||
width: 100px;
|
||||
margin-right: 6px;
|
||||
|
||||
.sign {
|
||||
margin-top: -5px;
|
||||
margin-right: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.b_input {
|
||||
flex: 1;
|
||||
position: relative;
|
||||
|
||||
.upload_box {
|
||||
display: flex;
|
||||
cursor: pointer;
|
||||
|
||||
.upload_icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.inp_num {
|
||||
position: absolute;
|
||||
top: 9px;
|
||||
right: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
35
src/components/Grateful/Agreement.vue
Normal file
35
src/components/Grateful/Agreement.vue
Normal file
@@ -0,0 +1,35 @@
|
||||
<template>
|
||||
<div class="item-agr">
|
||||
<div style="padding: 0 10px 0 10px;color:#626262;;">
|
||||
<div style="text-align: center;font-size: 26px;padding-bottom:20px ;">京东方大学堂内容发布须知</div>
|
||||
<div class="agr-content" style="min-height: 320px;max-height: 320px;overflow-y: auto;">
|
||||
<div style="">
|
||||
<p style="margin-bottom:10px;line-height: 24px; white-space:pre-line" v-for="(item, index) in context"
|
||||
:key="index">{{ item }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { query } from '@/api/grateful.js';
|
||||
import { ref } from 'vue';
|
||||
const context = ref([])
|
||||
const getInfo = () => {
|
||||
query(1).then(res => {
|
||||
if (res.status == 200) {
|
||||
let list = res.data.result.content.split('\n');
|
||||
context.value = list;
|
||||
}
|
||||
})
|
||||
}
|
||||
getInfo()
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.agr-content {
|
||||
background: #f7f7f7;
|
||||
padding: 20px;
|
||||
color: #626262;
|
||||
}
|
||||
</style>
|
||||
160
src/components/Grateful/CarouselDialog.vue
Normal file
160
src/components/Grateful/CarouselDialog.vue
Normal file
@@ -0,0 +1,160 @@
|
||||
<template>
|
||||
<a-modal v-model:visible="visiable" width="813px" @cancel="cancel" :title="title" :footer="null" :maskClosable="false">
|
||||
<div class="content">
|
||||
<a-form :rules="rules" :label-col="{ span: 4 }">
|
||||
<a-form-item label="展示页面">
|
||||
<a-input style="width: 60%" v-model:value="params.displayPage" />
|
||||
</a-form-item>
|
||||
<a-form-item label="轮播图片" name="picture">
|
||||
<UploadDragger ref="uploadRef" v-model:value="files" @change="change" :accept="accept"
|
||||
:uploadUrl="uploadUrl" :params="folderId" />
|
||||
</a-form-item>
|
||||
<a-form-item v-if="params.picPath" :wrapper-col="{ offset: 4 }">
|
||||
<a-image :src="path" />
|
||||
</a-form-item>
|
||||
<a-form-item :wrapper-col="{ offset: 4 }">
|
||||
<div class="footer">
|
||||
<a-button class="btn" @click="cancel" type="primary">取消</a-button>
|
||||
<a-button class="btn" @click="submit" type="primary" style="margin:0 20px;">提交</a-button>
|
||||
<!-- <a-checkbox v-model:checked="checked">我已阅读并遵守<span
|
||||
style="color: rgb(88, 138, 252);">平台内容发布要求</span></a-checkbox> -->
|
||||
</div>
|
||||
</a-form-item>
|
||||
</a-form>
|
||||
</div>
|
||||
</a-modal>
|
||||
<a-modal :visible="open" width="800px" :closable="false">
|
||||
<Agreement></Agreement>
|
||||
<template #footer>
|
||||
<a-button type="submit" @click="submitOpen">确定</a-button>
|
||||
</template>
|
||||
</a-modal>
|
||||
<a-button @click="showModal" type="link">
|
||||
<slot></slot>
|
||||
</a-button>
|
||||
</template>
|
||||
<script setup>
|
||||
import { computed, defineProps, ref, toRefs, watch, nextTick } from "vue";
|
||||
import UploadDragger from './UploadDragger'
|
||||
import { carouseAddAndUpdate, getCarouseById, } from "@/api/grateful";
|
||||
import { message } from "ant-design-vue";
|
||||
const props = defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
},
|
||||
id: {
|
||||
type: String
|
||||
},
|
||||
handleRest: {
|
||||
type: Function,
|
||||
default: () => { }
|
||||
}
|
||||
});
|
||||
const open = ref(false)
|
||||
const publishInfo = () => {
|
||||
open.value = !open.value
|
||||
}
|
||||
const submitOpen = () => {
|
||||
open.value = !open.value
|
||||
}
|
||||
const uploadRef = ref()
|
||||
//上传文件夹的id
|
||||
const folderId = ref({ folderId: process.env.VUE_APP_PIC_FOLDERID })
|
||||
const files = ref([]);
|
||||
const visiable = ref(false);
|
||||
const params = ref({
|
||||
id: '',
|
||||
pid: '',
|
||||
picFolderId: '',
|
||||
picPath: '',
|
||||
displayPage: '感恩教师节'
|
||||
})
|
||||
const path = computed(() => `https:${process.env.VUE_APP_BOE_API_URL}/upload${params.value.picPath}`)
|
||||
const rules = {
|
||||
picture: [{
|
||||
required: true,
|
||||
message: ''
|
||||
}]
|
||||
}
|
||||
const uploadUrl = ref("/systemapi/api/m/xfile/base/file/upload");
|
||||
const checked = ref(false)
|
||||
const accept = ".png,.jpg,.jpeg,.gif,.svg,.bmp"
|
||||
const showModal = async () => {
|
||||
files.value = []
|
||||
params.value.id = props.id
|
||||
console.log(files.value);
|
||||
if (!props.id) {
|
||||
params.value.displayPage = '感恩教师节'
|
||||
params.value.picFolderId = ''
|
||||
params.value.pid = ''
|
||||
params.value.picPath = ''
|
||||
checked.value = false
|
||||
visiable.value = true;
|
||||
return
|
||||
}
|
||||
getCarouseById({ id: props.id }).then((result) => {
|
||||
console.log(result);
|
||||
params.value.displayPage = result.data.displayPage
|
||||
params.value.picPath = result.data.picPath
|
||||
params.value.pid = result.data.picId
|
||||
params.value.picFolderId = result.data.picFolderId
|
||||
visiable.value = true;
|
||||
checked.value = true
|
||||
}).catch((err) => {
|
||||
message.error(err)
|
||||
visiable.value = true;
|
||||
});
|
||||
|
||||
|
||||
};
|
||||
const change = (newValue) => {
|
||||
if (newValue[0].status == 'done' && newValue[0]?.response?.status == 200) {
|
||||
const { id, folderId, path } = files.value[0].response.result
|
||||
console.log(newValue[0].response.result.path, 9999999999999);
|
||||
params.value.picPath = path
|
||||
params.value.folderId = folderId
|
||||
params.value.pid = id
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const emit = defineEmits(['change'])
|
||||
const submit = () => {
|
||||
console.log('提交', files);
|
||||
if (!params.value.picPath) return message.error('请上传轮播图图片')
|
||||
if (!checked.value) return message.error('请先阅读并遵守平台内容发布要求')
|
||||
carouseAddAndUpdate(params.value).then((result) => {
|
||||
console.log(result);
|
||||
emit('change')
|
||||
message.success('提交成功')
|
||||
props.handleRest()
|
||||
}).catch(() => {
|
||||
message.error('提交失败')
|
||||
})
|
||||
visiable.value = false;
|
||||
uploadRef.value.removeUpload()
|
||||
}
|
||||
|
||||
const cancel = () => {
|
||||
console.log('取消');
|
||||
visiable.value = false;
|
||||
uploadRef.value.removeUpload()
|
||||
}
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.content {
|
||||
padding: 24px;
|
||||
|
||||
.footer {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.btn {
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
313
src/components/Grateful/EmpowerDialog.vue
Normal file
313
src/components/Grateful/EmpowerDialog.vue
Normal file
@@ -0,0 +1,313 @@
|
||||
<template>
|
||||
<a-modal v-model:visible="visiable" width="1000px" @ok="submit" @cancel="getIdList()" :title="title"
|
||||
:maskClosable="false">
|
||||
<div class="content">
|
||||
<div class="topContent">
|
||||
<div class="select">
|
||||
<a-input v-model:value="searchDataInfo.keyword" style="width: 270px; height: 40px; border-radius: 8px"
|
||||
placeholder="请输入标题" />
|
||||
</div>
|
||||
<div style="display: flex; margin-bottom: 20px;margin-left: 20px;">
|
||||
<div class="btn btn1" @click="getTopList(false)">
|
||||
<div class="search"></div>
|
||||
<div class="btnText">搜索</div>
|
||||
</div>
|
||||
<div class="btn btn2" style="width: 105px" @click="handleRest">
|
||||
<div class="search"></div>
|
||||
<div class="btnText">重置</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="table">
|
||||
<a-table style="border: 1px solid #f2f6fe;" :columns="column" :data-source="state.dataSource"
|
||||
:loading="!loading" :row-selection="rowSelection" :pagination="pagination">
|
||||
<template #bodyCell="{ column, record }">
|
||||
<div v-if="column.dataIndex === 'title'" style="display:flex;align-items:center;">
|
||||
<div>
|
||||
<a-image :width="150" :height="75" :src="record.coverImg"></a-image>
|
||||
</div>
|
||||
<div style="height:75px;margin-left: 10px;">
|
||||
<div style="height:25px">{{ record.name }}</div>
|
||||
<div style="height:25px;">
|
||||
<span v-if="record.type == 30"
|
||||
style="background-color: #efbf82;padding: 0 5px;border-radius: 3px;color: white;">
|
||||
面授
|
||||
</span>
|
||||
<span v-if="record.type == 10 || record.type == 20"
|
||||
style="background-color: #4f9bcb;padding: 0 5px;border-radius: 3px;color: white;">
|
||||
录播
|
||||
</span>
|
||||
<span v-if="record.type == 40"
|
||||
style="background-color: #efbf82;padding: 0 5px;border-radius: 3px;color: white;">
|
||||
学习项目
|
||||
</span>
|
||||
</div>
|
||||
<div style="height:25px;display:flex;">
|
||||
<div style="margin-right: 20px;">{{ formatNum(record.studies) }}人已学习</div>
|
||||
<div v-if="record.score">
|
||||
<span class="course-score-value">{{ toScore(record.score) }}分</span>
|
||||
</div>
|
||||
<div v-else class="course-score-no">未评分</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</a-table>
|
||||
</div>
|
||||
</div>
|
||||
</a-modal>
|
||||
<a-button @click="showModal" type="link">
|
||||
<slot></slot>
|
||||
</a-button>
|
||||
</template>
|
||||
<script setup>
|
||||
import { defineProps, ref, computed, reactive, nextTick, watch } from "vue";
|
||||
import { Form, message } from "ant-design-vue";
|
||||
import { addCourselList, courseIds, saveCourseList } from "@/api/grateful";
|
||||
const formatNum = (num) => {
|
||||
let rsNum = 0;
|
||||
if (num < 5) { return num; }
|
||||
if (num >= 5 && num <= 10) { return 10 + "+"; }
|
||||
if (num <= 94) {
|
||||
rsNum = Math.round((num) / 10) * 10;
|
||||
return rsNum + '+';
|
||||
}
|
||||
if (num > 94 && num <= 1000) {
|
||||
rsNum = Math.round((num) / 100) * 100;
|
||||
return rsNum + '+';
|
||||
}
|
||||
if (num > 1000 && num <= 10000) {
|
||||
rsNum = Math.round((num) / 1000) * 1000;
|
||||
return rsNum + '+';
|
||||
}
|
||||
if (num > 10000) {
|
||||
rsNum = Math.round((num) / 10000);
|
||||
return rsNum + 'W+';
|
||||
}
|
||||
return num;
|
||||
}
|
||||
const toScore = (score) => {
|
||||
if (!score) {
|
||||
return '0';
|
||||
}
|
||||
if (('' + score).indexOf('.') > -1) {
|
||||
return score.toFixed(1);
|
||||
} else {
|
||||
return score + '.0';
|
||||
}
|
||||
}
|
||||
const emit = defineEmits(['change'])
|
||||
const props = defineProps({
|
||||
title: {
|
||||
type: String,
|
||||
},
|
||||
pageSizeOptions: {
|
||||
type: Array,
|
||||
default: ['5', '10', '30', '50']
|
||||
}
|
||||
});
|
||||
const column = ref([{
|
||||
title: "选择课程",
|
||||
dataIndex: "title",
|
||||
key: "title",
|
||||
align: "left",
|
||||
width: '75%',
|
||||
ellipsis: true,
|
||||
},
|
||||
{
|
||||
title: "授课讲师",
|
||||
dataIndex: "teacher",
|
||||
key: "teacher",
|
||||
width: '20%',
|
||||
align: "center",
|
||||
ellipsis: true,
|
||||
}]);
|
||||
const state = reactive({
|
||||
selectedRowKeys: [],//案例标题的id
|
||||
selectedRow: [],//选择的每一行数据
|
||||
dataSource: [],//表格的数据
|
||||
})
|
||||
const visiable = ref(false);
|
||||
// 查询数据
|
||||
const searchDataInfo = reactive({
|
||||
pageIndex: 1,
|
||||
pageSize: 5,
|
||||
keyword: '',
|
||||
orderField: 'publishTime'
|
||||
});
|
||||
const { resetFields } = Form.useForm(searchDataInfo, {});
|
||||
|
||||
const loading = ref(false)
|
||||
const total = ref(0)
|
||||
const idList = ref([])
|
||||
// 计算全选
|
||||
const rowSelection = computed(() => {
|
||||
return {
|
||||
selectedRowKeys: state.selectedRowKeys,
|
||||
onChange: onSelectChange,
|
||||
preserveSelectedRowKeys: true,
|
||||
getCheckboxProps: record => ({
|
||||
disabled: idList.value.some((item) => record.id == item)
|
||||
})
|
||||
}
|
||||
});
|
||||
//计算出来已选中状态
|
||||
const onSelectChange = (selectedRowKeys, selectedRow) => {
|
||||
console.log(selectedRowKeys, selectedRow);
|
||||
state.selectedRowKeys = selectedRowKeys
|
||||
state.selectedRow = selectedRow
|
||||
};
|
||||
|
||||
// 分页
|
||||
const pagination = computed(() => ({
|
||||
total: total.value,
|
||||
showQuickJumper: true,
|
||||
showSizeChanger: false,
|
||||
current: searchDataInfo.pageIndex,
|
||||
pageSize: searchDataInfo.pageSize,
|
||||
pageSizeOptions: props.pageSizeOptions,
|
||||
onChange: changePagination,
|
||||
}));
|
||||
const changePagination = (e, pageSize) => {
|
||||
loading.value = false
|
||||
searchDataInfo.pageIndex = e
|
||||
searchDataInfo.pageSize = pageSize
|
||||
nextTick(getTopList);
|
||||
};
|
||||
|
||||
const getIdList = () => {
|
||||
resetFields()
|
||||
courseIds().then((res) => {
|
||||
console.log(res);
|
||||
idList.value = res.data
|
||||
getTopList()
|
||||
})
|
||||
}
|
||||
// 请求列表数据是formdata类型的
|
||||
const getTopList = (type = true) => {
|
||||
if (!type) searchDataInfo.pageIndex = 1
|
||||
addCourselList(searchDataInfo).then((res) => {
|
||||
loading.value = true;
|
||||
console.log(res);
|
||||
res?.data?.result?.list?.forEach(element => {
|
||||
element.key = element.id
|
||||
});
|
||||
state.dataSource = res?.data?.result?.list || []
|
||||
total.value = res?.data?.result?.count
|
||||
}).catch((err) => {
|
||||
message.error(err);
|
||||
loading.value = false;
|
||||
})
|
||||
}
|
||||
getIdList()
|
||||
|
||||
const showModal = () => {
|
||||
visiable.value = true;
|
||||
resetFields()
|
||||
state.selectedRowKeys = []
|
||||
state.selectedRow = []
|
||||
};
|
||||
const paramList = computed(() => state.selectedRow.map((item) => ({
|
||||
id: item.id,
|
||||
name: item.name,
|
||||
publishTime: item.publishTime,
|
||||
score: item.score,
|
||||
studies: item.studies,
|
||||
teacher: item.teacher,
|
||||
type: item.type,
|
||||
coverImg: item.coverImg
|
||||
})))
|
||||
|
||||
const submit = () => {
|
||||
console.log('确定');
|
||||
saveCourseList(paramList.value).then((res) => {
|
||||
console.log(res);
|
||||
visiable.value = false;
|
||||
emit('change')
|
||||
getIdList()
|
||||
})
|
||||
}
|
||||
const handleRest = () => {
|
||||
resetFields()
|
||||
getTopList()
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
getIdList
|
||||
})
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.content {
|
||||
padding: 24px 24px 0 24px;
|
||||
|
||||
.topContent {
|
||||
display: flex;
|
||||
|
||||
.btn {
|
||||
padding: 0 26px 0 26px;
|
||||
height: 38px;
|
||||
background: #4ea6ff;
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 14px;
|
||||
flex-shrink: 0;
|
||||
cursor: pointer;
|
||||
|
||||
.search {
|
||||
background-size: 100%;
|
||||
}
|
||||
|
||||
.btnText {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #ffffff;
|
||||
line-height: 36px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.btn1 {
|
||||
.search {
|
||||
width: 15px;
|
||||
height: 17px;
|
||||
background-image: url("@/assets/images/courseManage/search0.png");
|
||||
}
|
||||
}
|
||||
|
||||
.btn2 {
|
||||
.search {
|
||||
width: 16px;
|
||||
height: 18px;
|
||||
background-image: url("@/assets/images/courseManage/reset0.png");
|
||||
}
|
||||
}
|
||||
|
||||
.btn1:active {
|
||||
background: #0982ff;
|
||||
}
|
||||
|
||||
.btn2:active {
|
||||
background: rgba(64, 158, 255, 0.2);
|
||||
}
|
||||
}
|
||||
|
||||
.table {
|
||||
margin: 20px 38px 30px;
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
|
||||
th.ant-table-cell {
|
||||
background-color: #eff4fc !important;
|
||||
text-align: center;
|
||||
color: #999ba3;
|
||||
}
|
||||
|
||||
td.ant-table-cell {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
443
src/components/Grateful/ImportTeacher.vue
Normal file
443
src/components/Grateful/ImportTeacher.vue
Normal file
@@ -0,0 +1,443 @@
|
||||
<template>
|
||||
<div @click="openDrawer">
|
||||
<slot></slot>
|
||||
</div>
|
||||
<a-drawer :visible="visible" class="drawerStyle impotergroupleader" placement="right" width="800px">
|
||||
<div class="drawerMain">
|
||||
<div class="header">
|
||||
<div class="headerTitle">{{ title }}</div>
|
||||
<img style="width: 29px; height: 29px; cursor: pointer" src="../../assets/images/basicinfo/close.png"
|
||||
@click="closeDrawer" />
|
||||
</div>
|
||||
<div class="main">
|
||||
<div class="minatitl" v-if="templateUrl">
|
||||
<div class="up1">请下载</div>
|
||||
<div class="up2" @click="downLoad" style="cursor: pointer">导入模版</div>
|
||||
<div class="up1">,按要求填写数据并导入</div>
|
||||
</div>
|
||||
<div class="upload">
|
||||
<div class="text">上传:</div>
|
||||
<div class="right">
|
||||
<div style="height: 176px; margin-bottom: 20px">
|
||||
<a-upload-dragger :data="data" :multiple="true" :name="name" :headers="headers" :accept="accept"
|
||||
:action="uploadUrl" @change="handleChange" v-model:file-list="fileList">
|
||||
<p class="ant-upload-drag-icon">
|
||||
</p>
|
||||
<p class="ant-upload-text">点击或将文件拖拽到此处上传</p>
|
||||
<p class="ant-upload-hint">支持扩展名:.xls/.xlsx</p>
|
||||
<template #itemRender="{ file }">
|
||||
<div class="loadstate">
|
||||
<div class="loadborder">
|
||||
<div class="content">
|
||||
<div class="img"></div>
|
||||
<div class="timebox">
|
||||
<div class="timetop">
|
||||
<div class="tit">{{ file.name }}</div>
|
||||
<div class="stateloading">{{
|
||||
{
|
||||
done: "上传成功",
|
||||
uploading: "正在上传",
|
||||
error: "上传失败",
|
||||
removed: "正在上传",
|
||||
}[file.status]
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
<a-progress :percent="file.percent" />
|
||||
</div>
|
||||
<div class="curloading">
|
||||
<div style="color: #387df7; margin-left: 20px; cursor: pointer" @click="removeUpload">删除
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="margin-top: 20px;" v-if="file?.status === 'done'">
|
||||
<div class="tacl">
|
||||
导入{{ file?.response?.data?.total || 0 }}条,成功{{ file?.response?.data?.success || 0 }}条,失败<span
|
||||
style="color: red;">{{ file?.response?.data?.fail || 0 }}</span>条
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</a-upload-dragger>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="btnn">
|
||||
<button class="btn2" @click="closeDrawer">取消</button>
|
||||
<button class="btn2" @click="closeDrawer">确定</button>
|
||||
</div>
|
||||
</div>
|
||||
</a-drawer>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { defineEmits, defineProps, ref } from "vue";
|
||||
import { useTimeout } from "@/utils/useCommon";
|
||||
import { getCookieForName } from "@/api/method";
|
||||
import { message } from "ant-design-vue";
|
||||
|
||||
const props = defineProps({
|
||||
url: String,
|
||||
name: {
|
||||
type: String,
|
||||
defalut: "file"
|
||||
},
|
||||
title: String,
|
||||
accept: String,
|
||||
fileType: Object,
|
||||
data: Object,
|
||||
templateUrl: {
|
||||
type:String,
|
||||
defalut:'/upload/教师导入模版.xlsx'
|
||||
},
|
||||
template: {
|
||||
type: String,
|
||||
defalut: '导入模版'
|
||||
}
|
||||
});
|
||||
const emit = defineEmits({});
|
||||
const visible = ref(false);
|
||||
const fileList = ref([]);
|
||||
const headers = { token: getCookieForName("token") };
|
||||
const uploadUrl = ref(props.url);
|
||||
const downLoad = () => {
|
||||
console.log(props.templateUrl);
|
||||
window.open(props.templateUrl)
|
||||
}
|
||||
const { start } = useTimeout(async ({ file }) => {
|
||||
if (file.status == 'done' && file.response.code == 200) {
|
||||
fileList.value = [...fileList.value];
|
||||
emit("change", "done");
|
||||
message.success("导入成功");
|
||||
throw Error("查询任务结束");
|
||||
} else {
|
||||
console.log(fileList.value);
|
||||
message.error(file.response.message);
|
||||
throw Error("任务结束");
|
||||
}
|
||||
}, 1000);
|
||||
|
||||
const closeDrawer = () => {
|
||||
visible.value = false;
|
||||
fileList.value = [];
|
||||
};
|
||||
|
||||
function openDrawer() {
|
||||
visible.value = true;
|
||||
}
|
||||
|
||||
|
||||
function handleChange({ file }) {
|
||||
console.log(file);
|
||||
|
||||
emit("change", "start");
|
||||
file && file.response && start({ file: file });
|
||||
}
|
||||
|
||||
const removeUpload = () => {
|
||||
fileList.value = [];
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.impotergroupleader>.ant-drawer-content-wrapper {
|
||||
min-width: 800px !important;
|
||||
width: 800px !important;
|
||||
}
|
||||
|
||||
.impotergroupleader {
|
||||
.drawerMain {
|
||||
min-width: 600px;
|
||||
margin: 0px 32px 0px 32px;
|
||||
overflow-x: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.header {
|
||||
height: 73px;
|
||||
border-bottom: 1px solid #e8e8e8;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20px;
|
||||
flex-shrink: 0;
|
||||
|
||||
.headerTitle {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: #333333;
|
||||
line-height: 25px;
|
||||
}
|
||||
}
|
||||
|
||||
.main {
|
||||
|
||||
.minatitl {
|
||||
display: flex;
|
||||
|
||||
.up1 {
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.up2 {
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
color: #4ea6ff;
|
||||
margin-left: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.upload {
|
||||
margin-top: 32px;
|
||||
display: flex;
|
||||
|
||||
.text {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.right {
|
||||
margin-left: 6px;
|
||||
width: 500px;
|
||||
|
||||
.load {
|
||||
width: 500px;
|
||||
height: 176px;
|
||||
background: #f5f9fd;
|
||||
border-radius: 4px;
|
||||
border: 1px dashed #caddfd;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
margin-bottom: 20px;
|
||||
|
||||
.cloud {
|
||||
margin-top: 52px;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
background-image: url(../../assets/images/basicinfo/cloud.png);
|
||||
}
|
||||
|
||||
.tip {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #4ea6ff;
|
||||
margin-top: 15px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.tipz {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #999999;
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.loadstate {
|
||||
width: 500px;
|
||||
margin-bottom: 50px;
|
||||
|
||||
.loadborder {
|
||||
width: 500px;
|
||||
height: 173px;
|
||||
border-radius: 4px;
|
||||
border: 1px dashed #eaeaea;
|
||||
margin-bottom: 30px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
margin-left: 20px;
|
||||
position: relative;
|
||||
|
||||
.defeat {
|
||||
width: 262px;
|
||||
padding: 10px 20px;
|
||||
position: absolute;
|
||||
left: 46px;
|
||||
top: 42px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
height: 32px;
|
||||
border-radius: 2px;
|
||||
border: 1px solid #387df7;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
|
||||
.detext {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #387df7;
|
||||
}
|
||||
}
|
||||
|
||||
.img {
|
||||
width: 30px;
|
||||
height: 34px;
|
||||
background-image: url(../../assets/images/basicinfo/exl.png);
|
||||
}
|
||||
|
||||
.timebox {
|
||||
margin-left: 15px;
|
||||
margin-top: -5px;
|
||||
|
||||
.timetop {
|
||||
display: flex;
|
||||
width: 262px;
|
||||
justify-content: space-between;
|
||||
|
||||
// margin-bottom: 8px;
|
||||
.tit {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.stateloading {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #4ea6ff;
|
||||
}
|
||||
|
||||
.statedefeat {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #ff7474;
|
||||
}
|
||||
|
||||
.statesucce {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #35ae69;
|
||||
}
|
||||
}
|
||||
|
||||
.prog {
|
||||
width: 262px;
|
||||
height: 5px;
|
||||
background: #eaf1fe;
|
||||
border-radius: 4px;
|
||||
|
||||
.inprogloading {
|
||||
width: 55%;
|
||||
height: 5px;
|
||||
border-radius: 4px;
|
||||
|
||||
background: #4ea6ff;
|
||||
}
|
||||
|
||||
//下载失败条
|
||||
.inprogdefeat {
|
||||
width: 55%;
|
||||
height: 5px;
|
||||
border-radius: 4px;
|
||||
|
||||
background: #ff7474;
|
||||
}
|
||||
|
||||
//下载成功条
|
||||
.inprogsucce {
|
||||
width: 100%;
|
||||
height: 5px;
|
||||
border-radius: 4px;
|
||||
|
||||
background: #57c887;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.curloading {
|
||||
margin-left: 15px;
|
||||
margin-top: 15px;
|
||||
display: flex;
|
||||
|
||||
.cur {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.cancel {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #387df7;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.downloadErr {
|
||||
width: 120px;
|
||||
height: 32px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 2px;
|
||||
border: 1px solid #387df7;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #387df7;
|
||||
line-height: 20px;
|
||||
cursor: pointer;
|
||||
margin-left: 66px;
|
||||
margin-top: 16px;
|
||||
position: absolute;
|
||||
bottom: 28px;
|
||||
}
|
||||
|
||||
.tacl {
|
||||
padding-left: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.btnn {
|
||||
height: 72px;
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
background-color: #fff;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: 0px 1px 35px 0px rgba(118, 136, 166, 0.16);
|
||||
|
||||
.btn1 {
|
||||
width: 100px;
|
||||
height: 40px;
|
||||
border: 1px solid #4ea6ff;
|
||||
border-radius: 8px;
|
||||
color: #4ea6ff;
|
||||
background-color: #fff;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.btn2 {
|
||||
cursor: pointer;
|
||||
width: 100px;
|
||||
height: 40px;
|
||||
background: #4ea6ff;
|
||||
border-radius: 8px;
|
||||
border: 0;
|
||||
margin-left: 15px;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
180
src/components/Grateful/PublishNotice.vue
Normal file
180
src/components/Grateful/PublishNotice.vue
Normal file
@@ -0,0 +1,180 @@
|
||||
<template>
|
||||
<a-modal :visible="visiable" width="813px" @cancel="cancel" title="发布通知" :footer="null" :maskClosable="false">
|
||||
<div class="content">
|
||||
<div class="cstm_items">
|
||||
<div class="signbox">
|
||||
<div class="sign">
|
||||
<img src="@/assets/images/coursewareManage/asterisk.png" alt="" />
|
||||
</div>
|
||||
<span style="margin-right: 3px">标题</span>
|
||||
</div>
|
||||
<div class="b_input">
|
||||
<a-input v-model:value="params.name" placeholder="请输入标题" show-count
|
||||
style="width: 88%; height: 40px; border-radius: 8px" :maxlength="20" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="cstm_items">
|
||||
<div class="signbox">
|
||||
<span style="margin-right: 3px">活动时间</span>
|
||||
</div>
|
||||
<div class="select fitems">
|
||||
<a-range-picker style="width: 88%; height: 40px; border-radius: 8px" format="YYYY-MM-DD"
|
||||
valueFormat="YYYY-MM-DD" v-model:value="timeList" separator="至"
|
||||
:placeholder="[' 开始时间', ' 结束时间']" @change="timeChange" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="cstm_items" style="align-items: start;">
|
||||
<div class="signbox">
|
||||
<div class="sign">
|
||||
<img src="@/assets/images/coursewareManage/asterisk.png" alt="" />
|
||||
</div>
|
||||
<span style="margin-right: 3px">正文</span>
|
||||
</div>
|
||||
<div class="b_input">
|
||||
<a-textarea v-model:value="params.content" :auto-size="{ minRows: 5 }"
|
||||
style="width: 88%; border-radius: 8px" placeholder="请输入具体内容......" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="cstm_items" style="align-items: start;">
|
||||
<div class="signbox">
|
||||
</div>
|
||||
<div class="b_input">
|
||||
<div class="footer">
|
||||
<a-button class="btn" @click="cancel()" type="primary">取消</a-button>
|
||||
<a-button class="btn" @click="submit()" type="primary" style="margin:0 20px;">提交</a-button>
|
||||
<!-- <a-checkbox v-model:checked="checked">我已阅读并遵守<span style="color: rgb(88, 138, 252);"
|
||||
@click.stop="publishInfo">平台内容发布要求</span></a-checkbox> -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</a-modal>
|
||||
</template>
|
||||
<script setup>
|
||||
import { ref, watchEffect, defineProps, defineEmits, computed, watch, onMounted } from 'vue'
|
||||
import { message } from "ant-design-vue";
|
||||
import { noticeAddAndUpdate, noticeDataById } from '@/api/grateful'
|
||||
import Agreement from '@/components/Grateful/Agreement'
|
||||
const props = defineProps({
|
||||
visiable: Boolean,
|
||||
id: String
|
||||
})
|
||||
const emit = defineEmits(["update:visiable", 'change']);
|
||||
const checked = ref(false)
|
||||
const timeList = ref([])
|
||||
const params = ref({
|
||||
name: '',
|
||||
content: '',
|
||||
id: '',
|
||||
startTime: '',
|
||||
endTime: ''
|
||||
})
|
||||
const id = computed(() => props.id)
|
||||
params.value.id = id.value
|
||||
onMounted(() => {
|
||||
checked.value = true
|
||||
noticeDataById({ id: id.value }).then((res) => {
|
||||
const { name, startTime, endTime, content } = res.data
|
||||
params.value.name = name;
|
||||
timeList.value = [startTime, endTime];
|
||||
params.value.content = content;
|
||||
})
|
||||
})
|
||||
|
||||
const timeChange = (time, timeStr) => {
|
||||
params.value.startTime = timeStr[0];
|
||||
params.value.endTime = timeStr[1];
|
||||
}
|
||||
|
||||
const submit = async () => {
|
||||
if (!checked.value) {
|
||||
message.error("请勾选平台内容发布要求");
|
||||
return
|
||||
}
|
||||
if (!params.value.name) {
|
||||
message.error("请输入标题内容");
|
||||
return
|
||||
}
|
||||
if (!params.value.content) {
|
||||
message.error("请输入正文具体内容");
|
||||
return
|
||||
}
|
||||
const result = await noticeAddAndUpdate(params.value)
|
||||
if (result.code == 200) {
|
||||
if (props.id) {
|
||||
message.success("编辑成功");
|
||||
} else {
|
||||
message.success("发布成功");
|
||||
}
|
||||
emit('change')
|
||||
cancel()
|
||||
}
|
||||
}
|
||||
|
||||
const cancel = () => {
|
||||
console.log('取消');
|
||||
params.value.timeList = []
|
||||
params.value.name = ''
|
||||
params.value.content = ''
|
||||
checked.value = false
|
||||
emit('update:visiable', false)
|
||||
}
|
||||
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.content {
|
||||
padding: 24px;
|
||||
|
||||
.footer {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.btn {
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.cstm_items {
|
||||
display: flex;
|
||||
width: 80%;
|
||||
margin: auto;
|
||||
align-items: center;
|
||||
margin-bottom: 23px;
|
||||
|
||||
.signbox {
|
||||
display: flex;
|
||||
justify-content: end;
|
||||
width: 100px;
|
||||
margin-right: 6px;
|
||||
|
||||
.sign {
|
||||
margin-top: -5px;
|
||||
margin-right: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.b_input {
|
||||
flex: 1;
|
||||
position: relative;
|
||||
|
||||
.upload_box {
|
||||
display: flex;
|
||||
cursor: pointer;
|
||||
|
||||
.upload_icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.inp_num {
|
||||
position: absolute;
|
||||
top: 9px;
|
||||
right: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
87
src/components/Grateful/ToolUpload.vue
Normal file
87
src/components/Grateful/ToolUpload.vue
Normal file
@@ -0,0 +1,87 @@
|
||||
<template>
|
||||
<a-upload :file-list="files" :action="url" :show-upload-list="showUploadList" :multiple="multiple"
|
||||
:before-upload="beforeUpload" :headers="headers" @change="handleChange" ref="imageRef" :data="{ ...params }">
|
||||
<template v-for="(_, key, index) in $slots" :key="index" v-slot:[key]>
|
||||
<slot :name="key"></slot>
|
||||
</template>
|
||||
</a-upload>
|
||||
</template>
|
||||
<script setup>
|
||||
import { defineProps, defineEmits, defineExpose, ref, watch } from "vue";
|
||||
import { message } from "ant-design-vue";
|
||||
import { getCookieForName } from "@/api/method";
|
||||
const props = defineProps({
|
||||
value: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
showUploadList: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
fileType: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
url: {
|
||||
type: String,
|
||||
default: '/systemapi/api/m/xfile/base/file/upload'
|
||||
},
|
||||
params: {
|
||||
type: Object,
|
||||
default: {
|
||||
folderId: process.env.VUE_APP_TOOL_FOLDERID
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const emit = defineEmits({})
|
||||
|
||||
const files = ref([])
|
||||
const imageRef = ref()
|
||||
const headers = { token: getCookieForName("token") };
|
||||
watch(props, () => {
|
||||
props.value.length !== files.value.length && (files.value = props.value)
|
||||
})
|
||||
|
||||
function handleChange({ file, fileList }) {
|
||||
file.response && file.response.code === 200 && (file.url = file.response.data)
|
||||
files.value = fileList
|
||||
emit('update:value', fileList)
|
||||
}
|
||||
|
||||
function beforeUpload(file) {
|
||||
if (!props.fileType.includes(file.name.split(".").slice(-1).join(''))) {
|
||||
message.error("目前只支持zip格式");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function remove(i) {
|
||||
files.value.splice(i, 1)
|
||||
emit('update:value', files.value)
|
||||
}
|
||||
|
||||
function reUpload(i) {
|
||||
if (files.value[i].status === 'ready' || files.value[i].status === 'uploading') {
|
||||
imageRef.value.abort(files.value[i].raw)
|
||||
files.value[i].status = 'abort';
|
||||
} else if (files.value[i].status === 'fail' || files.value[i].status === 'abort') {
|
||||
imageRef.value.handleStart(files.value[i].raw)
|
||||
imageRef.value.submit()
|
||||
}
|
||||
}
|
||||
|
||||
function abort(i) {
|
||||
imageRef.value.abort(files.value[i].raw)
|
||||
}
|
||||
|
||||
|
||||
defineExpose({ reUpload, remove, abort })
|
||||
|
||||
</script>
|
||||
|
||||
227
src/components/Grateful/UploadDragger.vue
Normal file
227
src/components/Grateful/UploadDragger.vue
Normal file
@@ -0,0 +1,227 @@
|
||||
<template>
|
||||
<a-upload-dragger :data="{ ...params }" :multiple="false" :accept="accept" :action="uploadUrl" :maxCount="maxCount"
|
||||
@change="handleUploadChange" v-model:file-list="fileList" style="width:50%;">
|
||||
<p class="ant-upload-drag-icon">
|
||||
<UploadOutlined />
|
||||
</p>
|
||||
<p class="ant-upload-text">将文件拖到此处,或点击上传</p>
|
||||
<template #itemRender="{ file }">
|
||||
<div class="loadstate">
|
||||
<div class="loadborder">
|
||||
<div class="content">
|
||||
<div class="timebox">
|
||||
<div class="timetop">
|
||||
<div class="tit">{{ file.name }}</div>
|
||||
<div class="stateloading">{{
|
||||
{
|
||||
done: "上传成功",
|
||||
uploading: "正在上传",
|
||||
error: "上传失败",
|
||||
removed: "正在上传",
|
||||
}[file.status]
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
<a-progress :percent="file.percent" />
|
||||
</div>
|
||||
<!-- <div class="curloading">
|
||||
<div class="cur">100%</div>
|
||||
<div class="cancel" style="margin-left: 20px; cursor: pointer" @click="removeUpload">
|
||||
删除
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</a-upload-dragger>
|
||||
</template>
|
||||
<script setup>
|
||||
import { UploadOutlined } from '@ant-design/icons-vue'
|
||||
import { defineProps, ref, defineExpose } from "vue";
|
||||
import { message } from "ant-design-vue";
|
||||
const props = defineProps({
|
||||
uploadUrl: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
params: {
|
||||
type: Object,
|
||||
default: {}
|
||||
},
|
||||
maxCount: {
|
||||
type: Number,
|
||||
default: 1
|
||||
},
|
||||
accept: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
})
|
||||
const emit = defineEmits(['update:value', 'change'])
|
||||
const fileList = ref([]);
|
||||
const handleUploadChange = ({ file, fileList }) => {
|
||||
console.log(file, fileList, 'file');
|
||||
var FileExt = file.name.replace(/.+\./, "");
|
||||
if (props.accept && props.accept.split(',').indexOf('.' + FileExt.toLowerCase()) === -1) {
|
||||
fileList.value = [];
|
||||
return message.error("请上传正确的文件格式");
|
||||
}
|
||||
emit('update:value', fileList)
|
||||
emit('change', fileList)
|
||||
}
|
||||
const removeUpload = () => {
|
||||
fileList.value = [];
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
fileList,
|
||||
removeUpload
|
||||
})
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.loadstate {
|
||||
width: 500px;
|
||||
margin-bottom: 80px;
|
||||
|
||||
.loadborder {
|
||||
width: 500px;
|
||||
height: 70px;
|
||||
border-radius: 4px;
|
||||
border: 1px dashed #eaeaea;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
margin-left: 20px;
|
||||
position: relative;
|
||||
|
||||
.defeat {
|
||||
width: 262px;
|
||||
padding: 10px 20px;
|
||||
position: absolute;
|
||||
left: 46px;
|
||||
top: 42px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
height: 32px;
|
||||
border-radius: 2px;
|
||||
border: 1px solid #387df7;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
|
||||
.detext {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #387df7;
|
||||
}
|
||||
}
|
||||
|
||||
.img {
|
||||
width: 30px;
|
||||
height: 34px;
|
||||
// background-image: url(@/assets/images/basicinfo/exl.png);
|
||||
}
|
||||
|
||||
.timebox {
|
||||
margin-left: 15px;
|
||||
margin-top: -5px;
|
||||
|
||||
.timetop {
|
||||
display: flex;
|
||||
width: 262px;
|
||||
justify-content: space-between;
|
||||
|
||||
.tit {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #333333;
|
||||
width: 200px;
|
||||
height: 21px;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.stateloading {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #4ea6ff;
|
||||
}
|
||||
|
||||
.statedefeat {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #ff7474;
|
||||
}
|
||||
|
||||
.statesucce {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #35ae69;
|
||||
}
|
||||
}
|
||||
|
||||
.prog {
|
||||
width: 262px;
|
||||
height: 5px;
|
||||
background: #eaf1fe;
|
||||
border-radius: 4px;
|
||||
|
||||
.inprogloading {
|
||||
width: 55%;
|
||||
height: 5px;
|
||||
border-radius: 4px;
|
||||
|
||||
background: #4ea6ff;
|
||||
}
|
||||
|
||||
//下载失败条
|
||||
.inprogdefeat {
|
||||
width: 55%;
|
||||
height: 5px;
|
||||
border-radius: 4px;
|
||||
|
||||
background: #ff7474;
|
||||
}
|
||||
|
||||
//下载成功条
|
||||
.inprogsucce {
|
||||
width: 100%;
|
||||
height: 5px;
|
||||
border-radius: 4px;
|
||||
|
||||
background: #57c887;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.curloading {
|
||||
margin-left: 15px;
|
||||
margin-top: 15px;
|
||||
display: flex;
|
||||
|
||||
.cur {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.cancel {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #387df7;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
||||
File diff suppressed because it is too large
Load Diff
50
src/components/Pagination.vue
Normal file
50
src/components/Pagination.vue
Normal file
@@ -0,0 +1,50 @@
|
||||
<template>
|
||||
<a-pagination
|
||||
:showSizeChanger="showSizeChanger"
|
||||
:showQuickJumper="showQuickJumper"
|
||||
:hideOnSinglePage="hideOnSinglePage"
|
||||
:pageSizeOptions="pageSizeOptions"
|
||||
:pageSize="pageSize"
|
||||
:current="page"
|
||||
:total="total"
|
||||
@change="changePagination"
|
||||
/>
|
||||
</template>
|
||||
<script setup>
|
||||
import { defineProps, defineEmits } from "vue";
|
||||
const props = defineProps({
|
||||
total: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
pageSize: {
|
||||
type: Number,
|
||||
default: 10,
|
||||
},
|
||||
page: {
|
||||
type: Number,
|
||||
default: 1,
|
||||
},
|
||||
showSizeChanger: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
showQuickJumper: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
hideOnSinglePage: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
pageSizeOptions:{
|
||||
type:Array,
|
||||
default:["10","20","50","100"]
|
||||
}
|
||||
});
|
||||
const emit = defineEmits(["changePagination"]);
|
||||
const changePagination = (page, pageSize) =>{
|
||||
emit("changePagination", page, pageSize);
|
||||
}
|
||||
</script>
|
||||
<style scoped></style>
|
||||
@@ -1,140 +1,165 @@
|
||||
<template>
|
||||
<a-table
|
||||
:customRow="customRow"
|
||||
class="ant-table-striped"
|
||||
:row-class-name="(_, index) => (index % 2 === 1 ? 'table-striped' : null)"
|
||||
row-key="id"
|
||||
:columns="columns"
|
||||
:data-source="data"
|
||||
:loading="loading"
|
||||
:pagination="pagination"
|
||||
:row-selection="rowSelection"
|
||||
:customRow="customRow"
|
||||
class="ant-table-striped"
|
||||
:row-class-name="(_, index) => (index % 2 === 1 ? 'table-striped' : null)"
|
||||
row-key="id"
|
||||
:columns="columns"
|
||||
:data-source="data"
|
||||
:loading="loading"
|
||||
:pagination="pagination"
|
||||
:row-selection="rowSelection"
|
||||
:scroll="scroll"
|
||||
/>
|
||||
</template>
|
||||
<script setup>
|
||||
import {defineProps, defineExpose, ref, computed, onMounted, defineEmits, nextTick} from "vue";
|
||||
import {usePage, useRequest, useRowsPageNoInit} from "@/api/request";
|
||||
import {useResetRef} from "@/utils/useCommon";
|
||||
import {defineProps, defineExpose, ref, computed, onMounted, defineEmits, nextTick} from "vue";
|
||||
import {usePage, useRequest, useRowsPageNoInit} from "@/api/request";
|
||||
import {useResetRef} from "@/utils/useCommon";
|
||||
|
||||
const props = defineProps({
|
||||
type: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
columns: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
url: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
pageKey: {
|
||||
type: String,
|
||||
default: "pageNo"
|
||||
},
|
||||
params: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
},
|
||||
init: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
request: {
|
||||
type: Function,
|
||||
default: usePage
|
||||
}
|
||||
});
|
||||
const emit = defineEmits(["update:params", "update:selectedRowKeys", "update:selectedRows"]);
|
||||
const rowSelectKeys = ref([]);
|
||||
const selectsData = ref([]);
|
||||
const params = useResetRef({ [props.pageKey]: 1, pageSize: 10 });
|
||||
const postParam = computed(() => ({ ...params.value, ...props.params }));
|
||||
|
||||
const { data, loading, total, fetch: onFetch } = props.request(props.url, postParam);
|
||||
|
||||
const rowSelection = computed(() => (props.type ? {
|
||||
type: props.type,
|
||||
columnWidth: 20,
|
||||
selectedRowKeys: rowSelectKeys.value,
|
||||
onChange: onSelectChange,
|
||||
preserveSelectedRowKeys: true,
|
||||
} : null));
|
||||
|
||||
const customRow = (record) => ({
|
||||
onClick: () => {
|
||||
if (props.type === "checkbox") {
|
||||
if (rowSelectKeys.value.some(t => t === record.id)) {
|
||||
rowSelectKeys.value = rowSelectKeys.value.filter(t => t !== record.id);
|
||||
selectsData.value = selectsData.value.filter(t => t.id !== record.id);
|
||||
} else {
|
||||
rowSelectKeys.value.push(record.id);
|
||||
selectsData.value.push(record);
|
||||
}
|
||||
} else {
|
||||
rowSelectKeys.value = [record.id];
|
||||
selectsData.value = [record];
|
||||
const props = defineProps({
|
||||
type: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
columns: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
url: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
pageKey: {
|
||||
type: String,
|
||||
default: "pageNo"
|
||||
},
|
||||
params: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
},
|
||||
init: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
request: {
|
||||
type: Function,
|
||||
default: usePage
|
||||
},
|
||||
showQuickJumper:{
|
||||
type: Boolean,
|
||||
default:false
|
||||
},
|
||||
scroll:{
|
||||
type:Object,
|
||||
default:{}
|
||||
},
|
||||
pageSize:{
|
||||
type:Number,
|
||||
default:10
|
||||
},
|
||||
getCheckboxProps:{
|
||||
type: Function,
|
||||
default: () => {}
|
||||
},
|
||||
showSizeChanger:{
|
||||
type:Boolean,
|
||||
default:false
|
||||
}
|
||||
emit("update:selectedRowKeys", [...rowSelectKeys.value]);
|
||||
emit("update:selectedRows", [...selectsData.value]);
|
||||
});
|
||||
const emit = defineEmits(["update:params", "update:selectedRowKeys", "update:selectedRows"]);
|
||||
const rowSelectKeys = ref([]);
|
||||
const selectsData = ref([]);
|
||||
const params = useResetRef({ [props.pageKey]: 1, pageSize: props.pageSize });
|
||||
const postParam = computed(() => ({ ...params.value, ...props.params }));
|
||||
|
||||
const { data, loading, total, fetch: onFetch } = props.request(props.url, postParam);
|
||||
|
||||
const rowSelection = computed(() => (props.type ? {
|
||||
type: props.type,
|
||||
columnWidth: 20,
|
||||
selectedRowKeys: rowSelectKeys.value,
|
||||
onChange: onSelectChange,
|
||||
preserveSelectedRowKeys: true,
|
||||
getCheckboxProps: record => props.getCheckboxProps(record)
|
||||
} : null));
|
||||
|
||||
const customRow = (record) => ({
|
||||
onClick: () => {
|
||||
if (props.type === "checkbox") {
|
||||
if(props.getCheckboxProps(record)?.disabled) return
|
||||
if (rowSelectKeys.value.some(t => t === record.id)) {
|
||||
rowSelectKeys.value = rowSelectKeys.value.filter(t => t !== record.id);
|
||||
selectsData.value = selectsData.value.filter(t => t.id !== record.id);
|
||||
} else {
|
||||
rowSelectKeys.value.push(record.id);
|
||||
selectsData.value.push(record);
|
||||
}
|
||||
} else {
|
||||
rowSelectKeys.value = [record.id];
|
||||
selectsData.value = [record];
|
||||
}
|
||||
emit("update:selectedRowKeys", [...rowSelectKeys.value]);
|
||||
emit("update:selectedRows", [...selectsData.value]);
|
||||
}
|
||||
});
|
||||
|
||||
onMounted(() => props.init && nextTick(onFetch));
|
||||
|
||||
function onSelectChange(e, l) {
|
||||
rowSelectKeys.value = e;
|
||||
selectsData.value = l;
|
||||
emit("update:selectedRowKeys", e);
|
||||
emit("update:selectedRows", l);
|
||||
}
|
||||
});
|
||||
|
||||
onMounted(() => props.init && nextTick(onFetch));
|
||||
const pagination = computed(() => ({
|
||||
total: total.value,
|
||||
showSizeChanger: props.showSizeChanger,
|
||||
showQuickJumper:props.showQuickJumper,
|
||||
current: params.value[props.pageKey],
|
||||
pageSize: params.value.pageSize,
|
||||
onChange: changePagination,
|
||||
}));
|
||||
const changePagination = (e,pageSize) => {
|
||||
params.value[props.pageKey] = e;
|
||||
params.value.pageSize = pageSize
|
||||
nextTick(onFetch);
|
||||
};
|
||||
|
||||
function onSelectChange(e, l) {
|
||||
rowSelectKeys.value = e;
|
||||
selectsData.value = l;
|
||||
emit("update:selectedRowKeys", e);
|
||||
emit("update:selectedRows", l);
|
||||
}
|
||||
function reset(v) {
|
||||
params.reset();
|
||||
v && emit("update:params", { ...v });
|
||||
nextTick(onFetch);
|
||||
}
|
||||
|
||||
const pagination = computed(() => ({
|
||||
total: total.value,
|
||||
showSizeChanger: false,
|
||||
current: params.value[props.pageKey],
|
||||
pageSize: params.value.pageSize,
|
||||
onChange: changePagination,
|
||||
}));
|
||||
const changePagination = (e) => {
|
||||
params.value[props.pageKey] = e;
|
||||
nextTick(onFetch);
|
||||
};
|
||||
function resetSelected() {
|
||||
rowSelectKeys.value = [];
|
||||
selectsData.value = [];
|
||||
emit("update:selectedRowKeys", []);
|
||||
emit("update:selectedRows", []);
|
||||
}
|
||||
|
||||
function reset(v) {
|
||||
params.reset();
|
||||
v && emit("update:params", { ...v });
|
||||
nextTick(onFetch);
|
||||
}
|
||||
function clear(v) {
|
||||
rowSelectKeys.value = [];
|
||||
selectsData.value = [];
|
||||
params.reset();
|
||||
v && emit("update:params", { ...v });
|
||||
emit("update:selectedRowKeys", []);
|
||||
emit("update:selectedRows", []);
|
||||
}
|
||||
|
||||
function resetSelected() {
|
||||
rowSelectKeys.value = [];
|
||||
selectsData.value = [];
|
||||
emit("update:selectedRowKeys", []);
|
||||
emit("update:selectedRows", []);
|
||||
}
|
||||
const toLoading = () => loading.value = true;
|
||||
|
||||
function clear(v) {
|
||||
rowSelectKeys.value = [];
|
||||
selectsData.value = [];
|
||||
params.reset();
|
||||
v && emit("update:params", { ...v });
|
||||
emit("update:selectedRowKeys", []);
|
||||
emit("update:selectedRows", []);
|
||||
}
|
||||
function remove(i) {
|
||||
rowSelectKeys.value.splice(i, 1);
|
||||
selectsData.value.splice(i, 1);
|
||||
emit("update:selectedRowKeys", rowSelectKeys.value);
|
||||
emit("update:selectedRows", selectsData.value);
|
||||
}
|
||||
|
||||
const toLoading = () => loading.value = true;
|
||||
const fetch = () => nextTick(onFetch);
|
||||
|
||||
function remove(i) {
|
||||
rowSelectKeys.value.splice(i, 1);
|
||||
selectsData.value.splice(i, 1);
|
||||
emit("update:selectedRowKeys", rowSelectKeys.value);
|
||||
emit("update:selectedRows", selectsData.value);
|
||||
}
|
||||
|
||||
const fetch = () => nextTick(onFetch);
|
||||
|
||||
defineExpose({ fetch, reset, resetSelected, clear, toLoading, remove });
|
||||
defineExpose({ fetch, reset, resetSelected, clear, toLoading, remove , params });
|
||||
|
||||
</script>
|
||||
|
||||
14
src/components/index.js
Normal file
14
src/components/index.js
Normal file
@@ -0,0 +1,14 @@
|
||||
import Pagination from './Pagination.vue'
|
||||
import Table from './common/BaseTable.vue'
|
||||
|
||||
const globalComponents = {
|
||||
Pagination,
|
||||
Table
|
||||
}
|
||||
export default {
|
||||
install(app) {
|
||||
Object.keys(globalComponents).forEach(key => {
|
||||
app.component(key, globalComponents[key])
|
||||
})
|
||||
}
|
||||
}
|
||||
46
src/hooks/useRequest.js
Normal file
46
src/hooks/useRequest.js
Normal file
@@ -0,0 +1,46 @@
|
||||
import { isRef, reactive, ref, toRefs, unref, watch, watchEffect } from "vue";
|
||||
import http from '@/api/configPublic'
|
||||
|
||||
const useTotalPage = (_url, params, config = {}) => {
|
||||
const s = _url.split(" ");
|
||||
const url = s[0];
|
||||
let methods = 'post'
|
||||
if (s[1]) methods = 'get'
|
||||
const state = reactive({
|
||||
data: [],
|
||||
total: 1,
|
||||
current: 1,
|
||||
pages: 1,
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
loading: false
|
||||
});
|
||||
|
||||
if (isRef(_url)) {
|
||||
watchEffect(fetch);
|
||||
}
|
||||
|
||||
function reset() {
|
||||
state.data = [];
|
||||
state.loading = false;
|
||||
}
|
||||
|
||||
function fetch() {
|
||||
state.loading = true;
|
||||
return http[methods](unref(url), !s[1] ? unref(params) : { params: unref(params) }, { ...config }).then(r => {
|
||||
state.data = r.data?.records || 0;
|
||||
state.total = r.data?.total || 0;
|
||||
state.loading = false;
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
...toRefs(state),
|
||||
fetch,
|
||||
reset,
|
||||
};
|
||||
}
|
||||
|
||||
export {
|
||||
useTotalPage
|
||||
}
|
||||
@@ -20,10 +20,13 @@ import {request} from "@/api/request";
|
||||
import {USER_INFO, USER_PERMISSION, VALIDATE_TOKEN} from "@/api/apis";
|
||||
import * as api1 from "@/api/index1";
|
||||
import {getCookieForName} from "@/api/method";
|
||||
import components from './components'
|
||||
// import axios from 'axios'
|
||||
// axios.defaults.withCredentials = true;
|
||||
// import zhCN from 'ant-design-vue/es/locale/zh_CN';
|
||||
const app = createApp(App)
|
||||
//全局注册
|
||||
app.use(components)
|
||||
// 清理控制台warn信息
|
||||
app.config.warnHandler = () => null;
|
||||
// app.use(ElementPlus, {
|
||||
|
||||
340
src/views/gratefulteacher/GratefulCarousel.vue
Normal file
340
src/views/gratefulteacher/GratefulCarousel.vue
Normal file
@@ -0,0 +1,340 @@
|
||||
<!-- 感恩教师通知 -->
|
||||
<template>
|
||||
<div class="researchmanage">
|
||||
<!-- 搜索框及按钮 -->
|
||||
<div class="filter">
|
||||
<div class="filterItems">
|
||||
<div class="select">
|
||||
<div class="select addTimeBox">
|
||||
<div class="addTime">创建时间:</div>
|
||||
<a-date-picker style="width: 300px" v-model:value="params.createTime" valueFormat="YYYY-MM-DD" />
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: flex; margin-bottom: 20px">
|
||||
<div class="btn btn1" @click="searchInfo">
|
||||
<div class="search"></div>
|
||||
<div class="btnText">搜索</div>
|
||||
</div>
|
||||
<div class="btn btn2" style="width: 105px" @click="handleRest">
|
||||
<div class="search"></div>
|
||||
<div class="btnText">重置</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<CarouselDialog title="新建轮播图" @change="handleRest">
|
||||
<div class="btns">
|
||||
<div class="btn btn3">
|
||||
<div class="search"></div>
|
||||
<div class="btnText">新建</div>
|
||||
</div>
|
||||
</div>
|
||||
</CarouselDialog>
|
||||
</div>
|
||||
<!-- 搜索框及按钮 -->
|
||||
<!-- 表格 -->
|
||||
<div class="table">
|
||||
<Table ref="carouselTableRef" :columns="column" :url="carouselList" page-key="pageNo" v-model:params="params"
|
||||
:request="useTotalPage" :showQuickJumper="true" :scroll="{ x: 1000 }" :showSizeChanger="true">
|
||||
</Table>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { ref, onMounted, reactive, computed, watchEffect } from "vue";
|
||||
import dialog from "@/utils/dialog";
|
||||
import { carouselList, carouseDelete } from "@/api/grateful";
|
||||
import { useTotalPage } from "@/hooks/useRequest";
|
||||
import CarouselDialog from "@/components/Grateful/CarouselDialog.vue";
|
||||
import { message } from "ant-design-vue";
|
||||
|
||||
const column = ref([
|
||||
{
|
||||
title: "序号",
|
||||
key: "index",
|
||||
width: 10,
|
||||
align: "center",
|
||||
ellipsis: true,
|
||||
customRender: ({ index }) => {
|
||||
return index + 1;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "图片",
|
||||
dataIndex: "picPath",
|
||||
key: "picPath",
|
||||
width: 35,
|
||||
align: "center",
|
||||
className: "h",
|
||||
customRender: ({ text }) => {
|
||||
return (
|
||||
<div style="height:100px;">
|
||||
<img style="width:80%;height:100%;object-fit:contain;" src={`https:${process.env.VUE_APP_BOE_API_URL}/upload${text}`} />
|
||||
</div>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "展示页面",
|
||||
dataIndex: "displayPage",
|
||||
key: "displayPage",
|
||||
width: 15,
|
||||
align: "center",
|
||||
className: "h",
|
||||
customRender: ({ text }) => (<span>{text ? text : '-'}</span>)
|
||||
},
|
||||
{
|
||||
title: "创建时间",
|
||||
dataIndex: "createTime",
|
||||
key: "createTime",
|
||||
width: 20,
|
||||
align: "center",
|
||||
className: "h",
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
width: 10,
|
||||
className: "h",
|
||||
dataIndex: "operation",
|
||||
key: "id",
|
||||
fixed: "right",
|
||||
align: "center",
|
||||
customRender: ({ record }) => {
|
||||
return (
|
||||
<div class="opa">
|
||||
<CarouselDialog id={record.id} handleRest={handleRest} title="编辑轮播图">
|
||||
<a style="margin-right:10px;">
|
||||
编辑
|
||||
</a>
|
||||
</CarouselDialog>
|
||||
<a onClick={() => handleOper(record, "del")}>删除</a>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
const params = ref({
|
||||
createTime: ''
|
||||
});
|
||||
|
||||
const carouselTableRef = ref();
|
||||
const searchInfo = () => {
|
||||
console.log("搜索");
|
||||
carouselTableRef.value.params.pageNo = 1;
|
||||
carouselTableRef.value.fetch();
|
||||
};
|
||||
|
||||
const handleRest = () => {
|
||||
console.log("重置");
|
||||
params.value.createTime = '';
|
||||
carouselTableRef.value.reset();
|
||||
};
|
||||
|
||||
const handle = ({ id }) => ({
|
||||
del: async () => {
|
||||
console.log("删除接口", id);
|
||||
carouseDelete({ id }).then((result) => {
|
||||
message.success('删除成功')
|
||||
carouselTableRef.value.fetch();
|
||||
}).catch((err) => {
|
||||
message.error('删除失败')
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
const handleMsg = {
|
||||
del: "你确定要删除这条意见吗?",
|
||||
};
|
||||
|
||||
function handleOper(record, type, status = "") {
|
||||
dialog({
|
||||
content: handleMsg[status ? type + status : type],
|
||||
ok: handle(record)[type],
|
||||
});
|
||||
}
|
||||
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.addTimeBox {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.addTime {
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
margin-left: 10px;
|
||||
color: rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
.ant-picker {
|
||||
padding-left: 85px;
|
||||
}
|
||||
|
||||
.ant-picker-range .ant-picker-active-bar {
|
||||
margin-left: 85px;
|
||||
}
|
||||
}
|
||||
|
||||
.researchmanage {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
|
||||
.filter {
|
||||
margin-left: 38px;
|
||||
margin-right: 38px;
|
||||
margin-top: 30px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.filterItems {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.select {
|
||||
margin-right: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.btn {
|
||||
padding: 0 26px 0 26px;
|
||||
height: 38px;
|
||||
background: #4ea6ff;
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 14px;
|
||||
flex-shrink: 0;
|
||||
cursor: pointer;
|
||||
|
||||
.search {
|
||||
background-size: 100%;
|
||||
}
|
||||
|
||||
.btnText {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #ffffff;
|
||||
line-height: 36px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.btnn {
|
||||
padding: 0 26px 0 26px;
|
||||
height: 38px;
|
||||
background: #4ea6ff;
|
||||
border-radius: 8px;
|
||||
border: 1px solid rgba(64, 158, 255, 1);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 14px;
|
||||
flex-shrink: 0;
|
||||
cursor: pointer;
|
||||
|
||||
.search {
|
||||
background-size: 100%;
|
||||
}
|
||||
|
||||
.btnText {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #fff;
|
||||
line-height: 36px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.btn1 {
|
||||
.search {
|
||||
width: 15px;
|
||||
height: 17px;
|
||||
background-image: url("@/assets/images/courseManage/search0.png");
|
||||
}
|
||||
}
|
||||
|
||||
.btn2 {
|
||||
.search {
|
||||
width: 16px;
|
||||
height: 18px;
|
||||
background-image: url("@/assets/images/courseManage/reset0.png");
|
||||
}
|
||||
}
|
||||
|
||||
.btn1:active {
|
||||
background: #0982ff;
|
||||
}
|
||||
|
||||
.btn2:active {
|
||||
background: rgba(64, 158, 255, 0.2);
|
||||
}
|
||||
}
|
||||
|
||||
.btns {
|
||||
display: flex;
|
||||
|
||||
.btn {
|
||||
padding: 0 26px;
|
||||
height: 38px;
|
||||
background: #4ea6ff;
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 14px;
|
||||
flex-shrink: 0;
|
||||
cursor: pointer;
|
||||
|
||||
.search {
|
||||
background-size: 100%;
|
||||
}
|
||||
|
||||
.btnText {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #ffffff;
|
||||
line-height: 36px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.btn3 {
|
||||
margin-right: 0;
|
||||
|
||||
.search {
|
||||
width: 17px;
|
||||
height: 18px;
|
||||
background-image: url("@/assets/images/courseManage/add0.png");
|
||||
}
|
||||
}
|
||||
|
||||
.btn3:active {
|
||||
background: #0982ff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.table {
|
||||
margin: 20px 38px 30px;
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
|
||||
th.ant-table-cell {
|
||||
background-color: #eff4fc !important;
|
||||
text-align: center;
|
||||
color: #999ba3;
|
||||
}
|
||||
|
||||
td.ant-table-cell {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
371
src/views/gratefulteacher/GratefulNotice.vue
Normal file
371
src/views/gratefulteacher/GratefulNotice.vue
Normal file
@@ -0,0 +1,371 @@
|
||||
<!-- 感恩教师通知 -->
|
||||
<template>
|
||||
<div class="researchmanage">
|
||||
<!-- 搜索框及按钮 -->
|
||||
<div class="filter">
|
||||
<div class="filterItems">
|
||||
<div class="select">
|
||||
<a-input v-model:value="searchData.name" style="width: 270px; height: 40px; border-radius: 8px"
|
||||
placeholder="请输入标题" />
|
||||
</div>
|
||||
<div class="select">
|
||||
<a-select v-model:value="searchData.isTop" style="width: 270px" placeholder="全部" :options="state.pinnedList"
|
||||
@change="selectPinned" allowClear></a-select>
|
||||
</div>
|
||||
|
||||
<div style="display: flex; margin-bottom: 20px">
|
||||
<div class="btn btn1" @click="getList(false)">
|
||||
<div class="search"></div>
|
||||
<div class="btnText">搜索</div>
|
||||
</div>
|
||||
<div class="btn btn2" style="width: 105px" @click="handleRest">
|
||||
<div class="search"></div>
|
||||
<div class="btnText">重置</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="btns" @click="publish('')">
|
||||
<div class="btn btn3">
|
||||
<div class="search"></div>
|
||||
<div class="btnText">发布</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 搜索框及按钮 -->
|
||||
<!-- 表格 -->
|
||||
<div class="table">
|
||||
<a-table style="border: 1px solid #f2f6fe" :columns="column" :data-source="state.data" :loading="!loading"
|
||||
:pagination="pagination">
|
||||
<template #bodyCell="{ column, record }">
|
||||
<a-space v-if="column.dataIndex === 'operation'" style="padding-right: 10px">
|
||||
<a-button type="link" @click="publish(record.id)">编辑 </a-button>
|
||||
<a-button v-if="record.isTop === '1'" type="link" @click="handleOper(record, 'pinned', '0')">
|
||||
置顶
|
||||
</a-button>
|
||||
<a-button v-else type="link" @click="handleOper(record, 'pinned', '1')">
|
||||
取消置顶
|
||||
</a-button>
|
||||
<a-button type="link" @click="handleOper(record, 'del')">删除
|
||||
</a-button>
|
||||
</a-space>
|
||||
</template>
|
||||
</a-table>
|
||||
</div>
|
||||
</div>
|
||||
<PublishNotice v-if="visiable" v-model:visiable="visiable" :id="state.id" @change="handleRest"></PublishNotice>
|
||||
</template>
|
||||
<script setup lang="jsx">
|
||||
import { ref, onMounted, reactive, computed } from "vue";
|
||||
import { message, Form } from "ant-design-vue";
|
||||
import dialog from "@/utils/dialog";
|
||||
import PublishNotice from "@/components/Grateful/PublishNotice.vue";
|
||||
import { noticeList, noticeAddAndUpdate, noticeDelete } from '@/api/grateful'
|
||||
const column = [
|
||||
{
|
||||
title: "标题",
|
||||
dataIndex: "name",
|
||||
key: "name",
|
||||
width: "15%",
|
||||
align: "center",
|
||||
ellipsis: true,
|
||||
className: "h",
|
||||
customRender: ({ text }) => {
|
||||
return text ? text : "-";
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "创建人",
|
||||
dataIndex: "createName",
|
||||
key: "createName",
|
||||
width: "5%",
|
||||
align: "center",
|
||||
className: "h",
|
||||
customRender: ({ text }) => {
|
||||
return text ? text : "-";
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "开始时间",
|
||||
dataIndex: "startTime",
|
||||
key: "startTime",
|
||||
width: "10%",
|
||||
align: "center",
|
||||
className: "h",
|
||||
customRender: ({ text }) => {
|
||||
return text ? text : "-";
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "结束时间",
|
||||
dataIndex: "endTime",
|
||||
key: "endTime",
|
||||
width: "10%",
|
||||
align: "center",
|
||||
className: "h",
|
||||
customRender: ({ text }) => {
|
||||
return text ? text : "-";
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
width: "15%",
|
||||
className: "h",
|
||||
dataIndex: "operation",
|
||||
key: "id",
|
||||
fixed: "right",
|
||||
align: "center",
|
||||
// slots: { customRender: "operation" },
|
||||
},
|
||||
];
|
||||
const visiable = ref(false)
|
||||
const publish = (id) => {
|
||||
state.id = id
|
||||
visiable.value = !visiable.value
|
||||
}
|
||||
const loading = ref(false);
|
||||
const state = reactive({
|
||||
data: [],
|
||||
total: 0,
|
||||
id: '',
|
||||
pinnedList: [
|
||||
{
|
||||
id: 1,
|
||||
value: '0',
|
||||
label: "已置顶",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
value: '1',
|
||||
label: "未置顶",
|
||||
},
|
||||
],
|
||||
});
|
||||
const pagination = computed(() => ({
|
||||
total: state.total,
|
||||
showQuickJumper: true,
|
||||
showSizeChanger: true,
|
||||
current: searchData.value.pageNo,
|
||||
pageSize: searchData.value.pageSize,
|
||||
onChange: changePagination,
|
||||
}));
|
||||
|
||||
// 查询数据
|
||||
const searchData = ref({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
name: "",
|
||||
isTop: undefined
|
||||
});
|
||||
const { resetFields } = Form.useForm(searchData, {});
|
||||
|
||||
const changePagination = (e, pageSize) => {
|
||||
searchData.value.pageNo = e;
|
||||
searchData.value.pageSize = pageSize;
|
||||
getList()
|
||||
};
|
||||
|
||||
const selectPinned = (value) => {
|
||||
searchData.isTop = value;
|
||||
};
|
||||
|
||||
const handleRest = () => {
|
||||
resetFields();
|
||||
getList();
|
||||
};
|
||||
|
||||
const getList = async (type = true) => {
|
||||
loading.value = false;
|
||||
if (!type) searchData.value.pageNo = 1;
|
||||
const result = await noticeList(searchData.value)
|
||||
if (result.code === 200) {
|
||||
loading.value = true;
|
||||
state.data = result?.data?.records ?? [];
|
||||
state.total = result?.data?.total ?? 0;
|
||||
} else {
|
||||
loading.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
// 获取列表数据
|
||||
getList();
|
||||
|
||||
|
||||
const handle = (record, status) => ({
|
||||
pinned: async () => {
|
||||
try {
|
||||
console.log(record.id, status);
|
||||
noticeAddAndUpdate({
|
||||
id: record.id,
|
||||
isTop: status
|
||||
}).then(() => {
|
||||
getList();
|
||||
})
|
||||
} catch (error) {
|
||||
message.error("置顶失败!");
|
||||
}
|
||||
},
|
||||
del: async () => {
|
||||
noticeDelete({ id: record.id }).then(() => {
|
||||
message.success("删除成功!");
|
||||
getList();
|
||||
}).catch(() => {
|
||||
message.error("删除失败!");
|
||||
})
|
||||
},
|
||||
});
|
||||
|
||||
const handleMsg = {
|
||||
del: "你确定要删除这条通知吗?",
|
||||
pinned0: "您确定要置顶此通知吗?",
|
||||
pinned1: "您确定要取消置顶此通知吗?",
|
||||
};
|
||||
|
||||
function handleOper(record, type, status = "") {
|
||||
console.log(record);
|
||||
dialog({
|
||||
content: handleMsg[status ? type + status : type],
|
||||
ok: handle(record, status)[type],
|
||||
});
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
handleRest
|
||||
})
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.researchmanage {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
|
||||
.filter {
|
||||
margin-left: 38px;
|
||||
margin-right: 38px;
|
||||
margin-top: 30px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.filterItems {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.select {
|
||||
margin-right: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.btn {
|
||||
padding: 0 26px 0 26px;
|
||||
height: 38px;
|
||||
background: #4ea6ff;
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 14px;
|
||||
flex-shrink: 0;
|
||||
cursor: pointer;
|
||||
|
||||
.search {
|
||||
background-size: 100%;
|
||||
}
|
||||
|
||||
.btnText {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #ffffff;
|
||||
line-height: 36px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.btn1 {
|
||||
.search {
|
||||
width: 15px;
|
||||
height: 17px;
|
||||
background-image: url("@/assets/images/courseManage/search0.png");
|
||||
}
|
||||
}
|
||||
|
||||
.btn2 {
|
||||
.search {
|
||||
width: 16px;
|
||||
height: 18px;
|
||||
background-image: url("@/assets/images/courseManage/reset0.png");
|
||||
}
|
||||
}
|
||||
|
||||
.btn1:active {
|
||||
background: #0982ff;
|
||||
}
|
||||
|
||||
.btn2:active {
|
||||
background: rgba(64, 158, 255, 0.2);
|
||||
}
|
||||
}
|
||||
|
||||
.btns {
|
||||
display: flex;
|
||||
|
||||
.btn {
|
||||
padding: 0 26px;
|
||||
height: 38px;
|
||||
background: #4ea6ff;
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 14px;
|
||||
flex-shrink: 0;
|
||||
cursor: pointer;
|
||||
|
||||
.search {
|
||||
background-size: 100%;
|
||||
}
|
||||
|
||||
.btnText {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #ffffff;
|
||||
line-height: 36px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.btn3 {
|
||||
margin-right: 0;
|
||||
|
||||
.search {
|
||||
width: 17px;
|
||||
height: 18px;
|
||||
background-image: url("@/assets/images/courseManage/add0.png");
|
||||
}
|
||||
}
|
||||
|
||||
.btn3:active {
|
||||
background: #0982ff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.table {
|
||||
margin: 20px 38px 30px;
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
|
||||
th.ant-table-cell {
|
||||
background-color: #eff4fc !important;
|
||||
text-align: center;
|
||||
color: #999ba3;
|
||||
}
|
||||
|
||||
td.ant-table-cell {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
361
src/views/gratefulteacher/TeacherEmpowerment.vue
Normal file
361
src/views/gratefulteacher/TeacherEmpowerment.vue
Normal file
@@ -0,0 +1,361 @@
|
||||
<!-- 感恩教师通知 -->
|
||||
<template>
|
||||
<div class="researchmanage">
|
||||
<!-- 搜索框及按钮 -->
|
||||
<div class="filter">
|
||||
<div class="filterItems">
|
||||
<div class="select">
|
||||
<a-input v-model:value="params.createName" style="width: 270px; height: 40px; border-radius: 8px"
|
||||
placeholder="请输入创建人" />
|
||||
</div>
|
||||
<div class="select">
|
||||
<a-input v-model:value="params.name" style="width: 270px; height: 40px; border-radius: 8px"
|
||||
placeholder="请输入名称" />
|
||||
</div>
|
||||
<div style="display: flex; margin-bottom: 20px">
|
||||
<div class="btn btn1" @click="searchInfo">
|
||||
<div class="search"></div>
|
||||
<div class="btnText">搜索</div>
|
||||
</div>
|
||||
<div class="btn btn2" style="width: 105px" @click="handleRest">
|
||||
<div class="search"></div>
|
||||
<div class="btnText">重置</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<EmpowerDialog ref="EmpowerDialogRef" title="选择课程" @change="handleRest">
|
||||
<div class="btns">
|
||||
<div class="btn btn3">
|
||||
<div class="search"></div>
|
||||
<div class="btnText">添加赋能</div>
|
||||
</div>
|
||||
</div>
|
||||
</EmpowerDialog>
|
||||
</div>
|
||||
<!-- 搜索框及按钮 -->
|
||||
<!-- 表格 -->
|
||||
<div class="table">
|
||||
<Table ref="carouselTableRef" :columns="column" :url="courselList" page-key="pageNo" v-model:params="params"
|
||||
:request="useTotalPage" :showQuickJumper="true" :scroll="{ x: 1000 }" :showSizeChanger="true">
|
||||
</Table>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { ref, onMounted, reactive, computed } from "vue";
|
||||
import dialog from "@/utils/dialog";
|
||||
import { courselList, courseDelete } from "@/api/grateful";
|
||||
import { useTotalPage } from "@/hooks/useRequest";
|
||||
import EmpowerDialog from '@/components/Grateful/EmpowerDialog'
|
||||
import { Form, message } from "ant-design-vue";
|
||||
|
||||
const column = ref([
|
||||
{
|
||||
title: "序号",
|
||||
key: "index",
|
||||
width: 10,
|
||||
align: "center",
|
||||
ellipsis: true,
|
||||
customRender: ({ index }) => {
|
||||
return index + 1;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "课程名称",
|
||||
dataIndex: "name",
|
||||
key: "name",
|
||||
width: 20,
|
||||
align: "center",
|
||||
className: "h",
|
||||
ellipsis: true,
|
||||
},
|
||||
{
|
||||
title: "课程形式",
|
||||
dataIndex: "type",
|
||||
key: "type",
|
||||
width: 15,
|
||||
align: "center",
|
||||
className: "h",
|
||||
customRender: ({ text }) => {
|
||||
return (
|
||||
<div class="racona">
|
||||
<span>{text == 10 || text == 20 ? '录播课' : text == 30 ? '面授课' : '学习项目'}</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
title: "学习人数",
|
||||
dataIndex: "studies",
|
||||
key: "studies",
|
||||
width: 15,
|
||||
align: "center",
|
||||
className: "h",
|
||||
customRender: ({ text }) => (<span> {text ? text : 0}</span>)
|
||||
},
|
||||
{
|
||||
title: "评分",
|
||||
dataIndex: "score",
|
||||
key: "score",
|
||||
width: 10,
|
||||
align: "center",
|
||||
className: "h",
|
||||
customRender: ({ text }) => (<span> {text ? text : 0}</span>)
|
||||
},
|
||||
{
|
||||
title: "授课讲师",
|
||||
dataIndex: "teacher",
|
||||
key: "teacher",
|
||||
width: 15,
|
||||
align: "center",
|
||||
className: "h",
|
||||
},
|
||||
{
|
||||
title: "设置赋能时间",
|
||||
dataIndex: "createTime",
|
||||
key: "createTime",
|
||||
width: 20,
|
||||
align: "center",
|
||||
className: "h",
|
||||
customRender: ({ text }) => (<span> {text ? text.replace('T', ' ') : 0}</span>)
|
||||
},
|
||||
{
|
||||
title: "发布时间",
|
||||
dataIndex: "publishTime",
|
||||
key: "publishTime",
|
||||
width: 20,
|
||||
align: "center",
|
||||
className: "h",
|
||||
customRender: ({ text }) => (<span> {text ? text : '-'}</span>)
|
||||
},
|
||||
{
|
||||
title: "创建人",
|
||||
dataIndex: "createName",
|
||||
key: "createName",
|
||||
width: 15,
|
||||
align: "center",
|
||||
className: "h",
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
width: 20,
|
||||
className: "h",
|
||||
dataIndex: "operation",
|
||||
key: "id",
|
||||
fixed: "right",
|
||||
align: "center",
|
||||
customRender: ({ record }) => {
|
||||
return (
|
||||
<div class="opa">
|
||||
<a onClick={() => handleOper(record, 'empower')}>取消赋能</a>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
const params = ref({
|
||||
createName: '',
|
||||
name: '',
|
||||
});
|
||||
|
||||
const carouselTableRef = ref();
|
||||
const searchInfo = () => {
|
||||
console.log("搜索");
|
||||
console.log(carouselTableRef.value.params);
|
||||
carouselTableRef.value.params.pageNo = 1
|
||||
carouselTableRef.value.fetch();
|
||||
};
|
||||
|
||||
const handleRest = () => {
|
||||
console.log("重置");
|
||||
params.value.createName = ''
|
||||
params.value.name = ''
|
||||
carouselTableRef.value.reset();
|
||||
};
|
||||
const EmpowerDialogRef = ref()
|
||||
const handle = ({ id }) => ({
|
||||
empower: async () => {
|
||||
console.log("删除接口", id);
|
||||
courseDelete({ id }).then(() => {
|
||||
console.log(EmpowerDialogRef.value);
|
||||
EmpowerDialogRef.value.getIdList()
|
||||
message.success('取消成功')
|
||||
carouselTableRef.value.fetch();
|
||||
}).catch(() => {
|
||||
message.error(); ('取消失败')
|
||||
})
|
||||
},
|
||||
});
|
||||
|
||||
const handleMsg = {
|
||||
empower: "你确定取消该课程为赋能课程?",
|
||||
};
|
||||
|
||||
function handleOper(record, type, status = "") {
|
||||
dialog({
|
||||
content: handleMsg[status ? type + status : type],
|
||||
ok: handle(record)[type],
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.addTimeBox {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.addTime {
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
margin-left: 10px;
|
||||
color: rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
.ant-picker {
|
||||
padding-left: 85px;
|
||||
}
|
||||
|
||||
.ant-picker-range .ant-picker-active-bar {
|
||||
margin-left: 85px;
|
||||
}
|
||||
}
|
||||
|
||||
.researchmanage {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
|
||||
.filter {
|
||||
margin-left: 38px;
|
||||
margin-right: 38px;
|
||||
margin-top: 30px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.filterItems {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.select {
|
||||
margin-right: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.btn {
|
||||
padding: 0 26px 0 26px;
|
||||
height: 38px;
|
||||
background: #4ea6ff;
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 14px;
|
||||
flex-shrink: 0;
|
||||
cursor: pointer;
|
||||
|
||||
.search {
|
||||
background-size: 100%;
|
||||
}
|
||||
|
||||
.btnText {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #ffffff;
|
||||
line-height: 36px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.btn1 {
|
||||
.search {
|
||||
width: 15px;
|
||||
height: 17px;
|
||||
background-image: url("@/assets/images/courseManage/search0.png");
|
||||
}
|
||||
}
|
||||
|
||||
.btn2 {
|
||||
.search {
|
||||
width: 16px;
|
||||
height: 18px;
|
||||
background-image: url("@/assets/images/courseManage/reset0.png");
|
||||
}
|
||||
}
|
||||
|
||||
.btn1:active {
|
||||
background: #0982ff;
|
||||
}
|
||||
|
||||
.btn2:active {
|
||||
background: rgba(64, 158, 255, 0.2);
|
||||
}
|
||||
}
|
||||
|
||||
.btns {
|
||||
display: flex;
|
||||
|
||||
.btn {
|
||||
padding: 0 26px;
|
||||
height: 38px;
|
||||
background: #4ea6ff;
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 14px;
|
||||
flex-shrink: 0;
|
||||
cursor: pointer;
|
||||
|
||||
.search {
|
||||
background-size: 100%;
|
||||
}
|
||||
|
||||
.btnText {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #ffffff;
|
||||
line-height: 36px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.btn3 {
|
||||
margin-right: 0;
|
||||
|
||||
.search {
|
||||
width: 17px;
|
||||
height: 18px;
|
||||
background-image: url("@/assets/images/courseManage/add0.png");
|
||||
}
|
||||
}
|
||||
|
||||
.btn3:active {
|
||||
background: #0982ff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.table {
|
||||
margin: 20px 38px 30px;
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
|
||||
th.ant-table-cell {
|
||||
background-color: #eff4fc !important;
|
||||
text-align: center;
|
||||
color: #999ba3;
|
||||
}
|
||||
|
||||
td.ant-table-cell {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
236
src/views/gratefulteacher/TeacherOpinion.vue
Normal file
236
src/views/gratefulteacher/TeacherOpinion.vue
Normal file
@@ -0,0 +1,236 @@
|
||||
<!-- 感恩教师通知 -->
|
||||
<template>
|
||||
<div class="researchmanage">
|
||||
<!-- 搜索框及按钮 -->
|
||||
<div class="filter">
|
||||
<div class="filterItems">
|
||||
<div class="select">
|
||||
<div class="select addTimeBox">
|
||||
<a-date-picker style="width: 300px" v-model:value="params.createTime" valueFormat="YYYY-MM-DD" />
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: flex; margin-bottom: 20px">
|
||||
<div class="btn btn1" @click="searchInfo()">
|
||||
<div class="search"></div>
|
||||
<div class="btnText">搜索</div>
|
||||
</div>
|
||||
<div class="btn btn2" style="width: 105px" @click="handleRest">
|
||||
<div class="search"></div>
|
||||
<div class="btnText">重置</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 搜索框及按钮 -->
|
||||
<!-- 表格 -->
|
||||
<div class="table">
|
||||
<Table ref="opinionTableRef" :columns="column" :url="opinionList" page-key="pageNo" v-model:params="params"
|
||||
:request="useTotalPage" :showQuickJumper="true" :scroll="{ x: 1000 }" :showSizeChanger="true">
|
||||
</Table>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { ref } from "vue";
|
||||
import dialog from "@/utils/dialog";
|
||||
import { opinionList, opinionDelete } from "@/api/grateful";
|
||||
import { useTotalPage } from "@/hooks/useRequest";
|
||||
import { message } from "ant-design-vue";
|
||||
|
||||
const column = ref([
|
||||
{
|
||||
title: "序号",
|
||||
key: "index",
|
||||
width: 10,
|
||||
align: "center",
|
||||
ellipsis: true,
|
||||
customRender: ({ index }) => {
|
||||
return index + 1;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "意见内容",
|
||||
dataIndex: "content",
|
||||
key: "content",
|
||||
width: 40,
|
||||
align: "center",
|
||||
className: "h",
|
||||
ellipsis: true,
|
||||
customRender: ({ text }) => {
|
||||
return text ? text : "-";
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "用户",
|
||||
dataIndex: "createName",
|
||||
key: "createName",
|
||||
width: 10,
|
||||
align: "center",
|
||||
className: "h",
|
||||
},
|
||||
{
|
||||
title: "提交时间",
|
||||
dataIndex: "createTime",
|
||||
key: "createTime",
|
||||
width: 20,
|
||||
align: "center",
|
||||
className: "h",
|
||||
customRender: ({ text }) => {
|
||||
return (
|
||||
<span>{text.replace('T', ' ')}</span>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
width: 10,
|
||||
className: "h",
|
||||
dataIndex: "operation",
|
||||
key: "id",
|
||||
fixed: "right",
|
||||
align: "center",
|
||||
customRender: ({ record }) => {
|
||||
return (
|
||||
<div class="opa">
|
||||
<a onClick={() => handleOper(record, "del")}>删除</a>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
const params = ref({
|
||||
createTime: ''
|
||||
});
|
||||
|
||||
const opinionTableRef = ref();
|
||||
const searchInfo = () => {
|
||||
console.log("搜索");
|
||||
opinionTableRef.value.params.pageNo = 1
|
||||
opinionTableRef.value.fetch();
|
||||
};
|
||||
|
||||
const handleRest = () => {
|
||||
console.log("重置");
|
||||
params.value.createTime = '';
|
||||
opinionTableRef.value.reset();
|
||||
};
|
||||
|
||||
const handle = ({ id }) => ({
|
||||
del: async () => {
|
||||
opinionDelete({ id }).then(() => {
|
||||
message.success('删除成功')
|
||||
opinionTableRef.value.fetch();
|
||||
}).catch(() => {
|
||||
message.error('删除失败')
|
||||
})
|
||||
},
|
||||
});
|
||||
|
||||
const handleMsg = {
|
||||
del: "你确定要删除这条意见吗?",
|
||||
};
|
||||
|
||||
function handleOper(record, type, status = "") {
|
||||
dialog({
|
||||
content: handleMsg[status ? type + status : type],
|
||||
ok: handle(record)[type],
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.researchmanage {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
|
||||
.filter {
|
||||
margin-left: 38px;
|
||||
margin-right: 38px;
|
||||
margin-top: 30px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.filterItems {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.select {
|
||||
margin-right: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.btn {
|
||||
padding: 0 26px 0 26px;
|
||||
height: 38px;
|
||||
background: #4ea6ff;
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 14px;
|
||||
flex-shrink: 0;
|
||||
cursor: pointer;
|
||||
|
||||
.search {
|
||||
background-size: 100%;
|
||||
}
|
||||
|
||||
.btnText {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #ffffff;
|
||||
line-height: 36px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.btn1 {
|
||||
.search {
|
||||
width: 15px;
|
||||
height: 17px;
|
||||
background-image: url("@/assets/images/courseManage/search0.png");
|
||||
}
|
||||
}
|
||||
|
||||
.btn2 {
|
||||
.search {
|
||||
width: 16px;
|
||||
height: 18px;
|
||||
background-image: url("@/assets/images/courseManage/reset0.png");
|
||||
}
|
||||
}
|
||||
|
||||
.btn1:active {
|
||||
background: hsl(210, 100%, 52%);
|
||||
}
|
||||
|
||||
.btn2:active {
|
||||
background: rgba(64, 158, 255, 0.2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.table {
|
||||
margin: 20px 38px 30px;
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
|
||||
th.ant-table-cell {
|
||||
background-color: #eff4fc !important;
|
||||
text-align: center;
|
||||
color: #999ba3;
|
||||
}
|
||||
|
||||
td.ant-table-cell {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
||||
383
src/views/gratefulteacher/TeacherTopic.vue
Normal file
383
src/views/gratefulteacher/TeacherTopic.vue
Normal file
@@ -0,0 +1,383 @@
|
||||
<!-- 感恩教师师资大全 -->
|
||||
<template>
|
||||
<div class="researchmanage">
|
||||
<!-- 搜索框及按钮 -->
|
||||
<div class="filter">
|
||||
<div class="filterItems">
|
||||
<div class="select">
|
||||
<a-input v-model:value="params.teacherName" style="width: 270px; height: 40px; border-radius: 8px"
|
||||
placeholder="请输入教师姓名" />
|
||||
</div>
|
||||
<div class="select">
|
||||
<a-select v-model:value="params.teacherLevel" style="width: 270px" placeholder="全部"
|
||||
:options="teacherLevelList" allowClear></a-select>
|
||||
</div>
|
||||
<div style="display: flex; margin-bottom: 20px">
|
||||
<div class="btn btn1" @click="searchInfo">
|
||||
<div class="search"></div>
|
||||
<div class="btnText">搜索</div>
|
||||
</div>
|
||||
<div class="btn btn2" style="width: 105px" @click="handleRest">
|
||||
<div class="search"></div>
|
||||
<div class="btnText">重置</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="display: flex;">
|
||||
<AddTeacherInfo @getList="searchInfo">
|
||||
<div class="btns" style="margin-right: 10px;">
|
||||
<div class="btn btn3">
|
||||
<div class="search"></div>
|
||||
<div class="btnText">添加教师</div>
|
||||
</div>
|
||||
</div>
|
||||
</AddTeacherInfo>
|
||||
<ImportTeacher @change="change" title="导入教师" :template-url="teacherTemplateUrl" :data="{ type: 3 }"
|
||||
:url="`/activityApi/xboe/m/boe/teachers/import`" name="file">
|
||||
<div class="btns">
|
||||
<div class="btn btn3">
|
||||
<div class="search"></div>
|
||||
<div class="btnText">导入教师</div>
|
||||
</div>
|
||||
</div>
|
||||
</ImportTeacher>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<!-- 搜索框及按钮 -->
|
||||
<!-- 表格 -->
|
||||
<div class="table">
|
||||
<Table ref="carouselTableRef" :columns="column" :url="teachersList" page-key="pageNo" v-model:params="params"
|
||||
:request="useTotalPage" :showQuickJumper="true" :scroll="{ x: 1000 }" :showSizeChanger="true">
|
||||
</Table>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { ref, onMounted, reactive, computed } from "vue";
|
||||
import dialog from "@/utils/dialog";
|
||||
import { message } from "ant-design-vue";
|
||||
import { teachersList, teachersDelete } from "@/api/grateful";
|
||||
import { useTotalPage } from "@/hooks/useRequest";
|
||||
import AddTeacherInfo from '@/components/Grateful/AddTeacherInfo.vue'
|
||||
import ImportTeacher from '@/components/Grateful/ImportTeacher'
|
||||
//下载模版
|
||||
const teacherTemplateUrl = ref(process.env.VUE_APP_FILE_PATH + '教师导入模版.xlsx');
|
||||
const column = ref([
|
||||
{
|
||||
title: "课程名称",
|
||||
dataIndex: "courseName",
|
||||
key: "courseName",
|
||||
width: 30,
|
||||
align: "center",
|
||||
ellipsis: true,
|
||||
},
|
||||
{
|
||||
title: "教师姓名",
|
||||
dataIndex: "teacherName",
|
||||
key: "teacherName",
|
||||
width: 15,
|
||||
align: "center"
|
||||
},
|
||||
{
|
||||
title: "排序",
|
||||
dataIndex: "sort",
|
||||
key: "sort",
|
||||
width: 15,
|
||||
align: "center"
|
||||
},
|
||||
{
|
||||
title: "教师工号",
|
||||
dataIndex: "teacherNo",
|
||||
key: "teacherNo",
|
||||
width: 15,
|
||||
align: "center",
|
||||
customRender: ({ record }) => {
|
||||
return (
|
||||
<span>{record.teacherNo ? record.teacherNo : '-'}</span>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "授课时长(H)",
|
||||
dataIndex: "teacherTime",
|
||||
key: "teacherTime",
|
||||
width: 20,
|
||||
align: "center",
|
||||
customRender: ({ record }) => {
|
||||
return (
|
||||
<span>{record.teacherTime ? record.teacherTime : '-'}</span>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "教师等级",
|
||||
dataIndex: "teacherLevel",
|
||||
key: "teacherLevel",
|
||||
width: 15,
|
||||
align: "center",
|
||||
customRender: ({ record }) => {
|
||||
return (
|
||||
<span>{record.teacherLevel ? record.teacherLevel + '级' : '-'}</span>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "组织全路径",
|
||||
dataIndex: "orgPath",
|
||||
key: "orgPath",
|
||||
width: 40,
|
||||
align: "center",
|
||||
ellipsis: true,
|
||||
customRender: ({ record }) => {
|
||||
return (
|
||||
<span>{record.orgPath ? record.orgPath : '-'}</span>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
width: 10,
|
||||
dataIndex: "operation",
|
||||
key: "id",
|
||||
fixed: "right",
|
||||
align: "center",
|
||||
customRender: ({ record }) => {
|
||||
return (
|
||||
<div class="opa">
|
||||
<a onClick={() => handleOper(record, 'del')}>删除</a>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
const params = ref({
|
||||
teacherName: '',
|
||||
teacherLevel: undefined,
|
||||
enabled: ''
|
||||
});
|
||||
const teacherLevelList = ref([{
|
||||
id: 1,
|
||||
value: '1',
|
||||
label: "1级",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
value: '2',
|
||||
label: "2级",
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
value: '3',
|
||||
label: "3级",
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
value: '4',
|
||||
label: "4级",
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
value: '5',
|
||||
label: "5级",
|
||||
},
|
||||
])
|
||||
|
||||
const carouselTableRef = ref();
|
||||
const searchInfo = () => {
|
||||
|
||||
console.log("搜索");
|
||||
carouselTableRef.value.params.pageNo = 1
|
||||
carouselTableRef.value.fetch();
|
||||
};
|
||||
|
||||
const handleRest = () => {
|
||||
console.log("重置");
|
||||
params.value.teacherName = ''
|
||||
params.value.enabled = ''
|
||||
params.value.teacherLevel = undefined
|
||||
carouselTableRef.value.reset();
|
||||
};
|
||||
const handle = ({ id }) => ({
|
||||
del: async () => {
|
||||
console.log("删除接口", id);
|
||||
teachersDelete({ id }).then(() => {
|
||||
message.success("删除成功");
|
||||
carouselTableRef.value.fetch();
|
||||
}).catch((err) => {
|
||||
message.error("删除失败");
|
||||
})
|
||||
},
|
||||
});
|
||||
|
||||
const handleMsg = {
|
||||
del: "你确定删除该教师信息吗?",
|
||||
};
|
||||
|
||||
function handleOper(record, type, status = "") {
|
||||
dialog({
|
||||
content: handleMsg[status ? type + status : type],
|
||||
ok: handle(record)[type],
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.addTimeBox {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.addTime {
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
margin-left: 10px;
|
||||
color: rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
.ant-picker {
|
||||
padding-left: 85px;
|
||||
}
|
||||
|
||||
.ant-picker-range .ant-picker-active-bar {
|
||||
margin-left: 85px;
|
||||
}
|
||||
}
|
||||
|
||||
.researchmanage {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: relative;
|
||||
|
||||
.filter {
|
||||
margin-left: 38px;
|
||||
margin-right: 38px;
|
||||
margin-top: 30px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.filterItems {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.select {
|
||||
margin-right: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.btn {
|
||||
padding: 0 26px 0 26px;
|
||||
height: 38px;
|
||||
background: #4ea6ff;
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 14px;
|
||||
flex-shrink: 0;
|
||||
cursor: pointer;
|
||||
|
||||
.search {
|
||||
background-size: 100%;
|
||||
}
|
||||
|
||||
.btnText {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #ffffff;
|
||||
line-height: 36px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.btn1 {
|
||||
.search {
|
||||
width: 15px;
|
||||
height: 17px;
|
||||
background-image: url("@/assets/images/courseManage/search0.png");
|
||||
}
|
||||
}
|
||||
|
||||
.btn2 {
|
||||
.search {
|
||||
width: 16px;
|
||||
height: 18px;
|
||||
background-image: url("@/assets/images/courseManage/reset0.png");
|
||||
}
|
||||
}
|
||||
|
||||
.btn1:active {
|
||||
background: #0982ff;
|
||||
}
|
||||
|
||||
.btn2:active {
|
||||
background: rgba(64, 158, 255, 0.2);
|
||||
}
|
||||
}
|
||||
|
||||
.btns {
|
||||
display: flex;
|
||||
|
||||
.btn {
|
||||
padding: 0 26px;
|
||||
height: 38px;
|
||||
background: #4ea6ff;
|
||||
border-radius: 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 14px;
|
||||
flex-shrink: 0;
|
||||
cursor: pointer;
|
||||
|
||||
.search {
|
||||
background-size: 100%;
|
||||
}
|
||||
|
||||
.btnText {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #ffffff;
|
||||
line-height: 36px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.btn3 {
|
||||
margin-right: 0;
|
||||
|
||||
.search {
|
||||
width: 17px;
|
||||
height: 18px;
|
||||
background-image: url("@/assets/images/courseManage/add0.png");
|
||||
}
|
||||
}
|
||||
|
||||
.btn3:active {
|
||||
background: #0982ff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.table {
|
||||
margin: 20px 38px 30px;
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
|
||||
th.ant-table-cell {
|
||||
background-color: #eff4fc !important;
|
||||
text-align: center;
|
||||
color: #999ba3;
|
||||
}
|
||||
|
||||
td.ant-table-cell {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
403
src/views/gratefulteacher/ToolDown.vue
Normal file
403
src/views/gratefulteacher/ToolDown.vue
Normal file
@@ -0,0 +1,403 @@
|
||||
<template>
|
||||
<div class="DownLoad">
|
||||
<div class="downTop">
|
||||
<div class="tab1">
|
||||
<div class="nameinp">
|
||||
<a-input v-model:value="params.name" style="width: 330px; height: 40px; border-radius: 8px"
|
||||
placeholder="关键词搜索" />
|
||||
</div>
|
||||
<div class="btns">
|
||||
<div class="btn1" @click="searchDownloadList">
|
||||
<div class="img1">
|
||||
<img src="@/assets/images/courseManage/search0.png" />
|
||||
</div>
|
||||
<div class="wz">搜索</div>
|
||||
</div>
|
||||
<div class="btn2" @click="reseatDownloadList">
|
||||
<div class="img2">
|
||||
<img src="@/assets/images/courseManage/reset0.png" />
|
||||
</div>
|
||||
<div class="wz">重置</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ToolUpload v-model:value="files" ref="uploadRef" :file-type="fileType">
|
||||
<a-button type="primary" style=" border-radius: 8px;width: 100px;height: 40px;background: #4ea6ff"
|
||||
:loading="!againUpload">上传</a-button>
|
||||
</ToolUpload>
|
||||
</div>
|
||||
<div style="display: flex; flex-wrap: wrap">
|
||||
<div v-if="teacherToolList.length == 0" class="downContent">
|
||||
<img src="@/assets/images/courseManage/downloadnodata.png" />
|
||||
</div>
|
||||
<div v-else v-for="(toolInfo, index) in teacherToolList" class="zipcontainer" :key="index">
|
||||
<div v-if="toolInfo" class="item">
|
||||
<div class="itemup">
|
||||
<div class="lefttop"></div>
|
||||
<div class="cent">
|
||||
<div class="zip"></div>
|
||||
<div class="ziprit">
|
||||
<div class="textop">{{ toolInfo.name }}</div>
|
||||
<div class="texdown">
|
||||
<div class="timemanag" style="margin-top: 12px">
|
||||
{{ toolInfo.createTime ? toolInfo.createTime.replace('T', ' ') : "-" }}
|
||||
{{ toolInfo.createName ? toolInfo.createName : "-" }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="itemdown">
|
||||
<div class="download" @click="downLoadFile(toolInfo)">下载</div>
|
||||
<div class="delete" @click="handleOper(toolInfo, 'del')">删除</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="margin-top: 90px;display: flex;align-items: center;justify-content: flex-end;">
|
||||
<Pagination :total="params.total" :pageSize="params.pageSize" :page="params.pageNo"
|
||||
@changePagination="changePagination" :pageSizeOptions="['12', '24', '36', '48']">
|
||||
</Pagination>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { reactive, watch, ref } from "vue";
|
||||
import ToolUpload from "@/components/Grateful/ToolUpload";
|
||||
import dialog from "@/utils/dialog";
|
||||
import { toolDelete, toolList, saveTool, toolDown } from "@/api/grateful";
|
||||
import { message } from "ant-design-vue";
|
||||
const params = reactive({
|
||||
name: "",
|
||||
pageSize: 12,
|
||||
pageNo: 1,
|
||||
total: 0
|
||||
});
|
||||
const teacherToolList = ref([])
|
||||
const uploadRef = ref();
|
||||
const fileType = ref(["zip"]);
|
||||
const files = ref([]);
|
||||
const againUpload = ref(true);
|
||||
watch(files, () => {
|
||||
console.log("lalalalala", files, files.value.length, files.value);
|
||||
if (files.value.length !== 0) {
|
||||
const file = files.value[files.value.length - 1]
|
||||
if (file.status) {
|
||||
if (file.status == "done") {
|
||||
againUpload.value = true;
|
||||
const { id, folderId, name, path } = file.response.result
|
||||
saveTool({ fileId: id, fileFolderId: folderId, name, filePath: path }).then((result) => {
|
||||
message.success("上传成功");
|
||||
reseatDownloadList()
|
||||
}).catch((err) => {
|
||||
message.error("上传失败");
|
||||
});
|
||||
} else {
|
||||
againUpload.value = false;
|
||||
}
|
||||
} else {
|
||||
againUpload.value = true;
|
||||
}
|
||||
} else {
|
||||
againUpload.value = true;
|
||||
}
|
||||
});
|
||||
|
||||
const changePagination = (page, pageSize) => {
|
||||
params.pageNo = page;
|
||||
params.pageSize = pageSize;
|
||||
getList()
|
||||
};
|
||||
const getList = async () => {
|
||||
const result = await toolList(params)
|
||||
if (result.code == 200) {
|
||||
const { total, records } = result.data
|
||||
teacherToolList.value = records
|
||||
params.total = total
|
||||
}
|
||||
}
|
||||
getList()
|
||||
const searchDownloadList = () => {
|
||||
params.pageNo = 1
|
||||
getList()
|
||||
};
|
||||
const reseatDownloadList = () => {
|
||||
params.pageNo = 1;
|
||||
params.pageSize = 12;
|
||||
params.name = '';
|
||||
getList()
|
||||
};
|
||||
const downLoadFile = (toolInfo) => {
|
||||
if (!toolInfo.filePath) return;
|
||||
console.log(toolInfo);
|
||||
toolDown({
|
||||
urlStr: `https:${process.env.VUE_APP_BOE_API_URL}/upload${toolInfo.filePath}`,
|
||||
fileName: toolInfo.name
|
||||
}).then((result) => {
|
||||
if (!result.data) {
|
||||
return
|
||||
}
|
||||
const link = document.createElement('a');// 创建a标签
|
||||
let blob = new Blob([result.data], { type: '' }); // 设置文件类型
|
||||
link.style.display = "none";
|
||||
link.href = URL.createObjectURL(blob); // 创建URL
|
||||
link.setAttribute("download", `${toolInfo.name}`);
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
URL.revokeObjectURL(link.href);
|
||||
document.body.removeChild(link);
|
||||
})
|
||||
};
|
||||
|
||||
const handle = ({ id }) => ({
|
||||
del: async () => {
|
||||
console.log("删除接口");
|
||||
toolDelete({ id }).then(() => {
|
||||
message.success("删除成功");
|
||||
getList()
|
||||
}).catch(() => {
|
||||
message.error("删除失败");
|
||||
})
|
||||
},
|
||||
});
|
||||
|
||||
const handleMsg = {
|
||||
del: "你确定要删除这条工具吗?",
|
||||
};
|
||||
|
||||
function handleOper(record, type, status = "") {
|
||||
dialog({
|
||||
content: handleMsg[status ? type + status : type],
|
||||
ok: handle(record)[type],
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.DownLoad {
|
||||
width: 100%;
|
||||
margin: 30px 38px;
|
||||
|
||||
.downTop {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
|
||||
.tab1 {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
.t1 {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.nameinp {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-right: 10px;
|
||||
|
||||
.namee {
|
||||
color: rgba(0, 0, 0, 0.85);
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.btns {
|
||||
display: flex;
|
||||
|
||||
.btn1 {
|
||||
width: 100px;
|
||||
height: 40px;
|
||||
margin-right: 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #ffffff;
|
||||
font-size: 14px;
|
||||
background: #4ea6ff;
|
||||
border-radius: 8px;
|
||||
border: 1px solid #4ea6ff;
|
||||
cursor: pointer;
|
||||
|
||||
.wz {
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.btn1:active {
|
||||
background: #0982ff;
|
||||
}
|
||||
|
||||
.btn2:active {
|
||||
background: rgba(64, 158, 255, 0.2);
|
||||
}
|
||||
|
||||
.btn2 {
|
||||
width: 100px;
|
||||
height: 40px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
background: #4ea6ff;
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
|
||||
.wz {
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.btnImport {
|
||||
width: 100px;
|
||||
height: 40px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
background: #4ea6ff;
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.downContent {
|
||||
width: 100%;
|
||||
height: 500px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border: 1px solid #d9d9d9;
|
||||
border-radius: 8px;
|
||||
margin-top: 60px;
|
||||
}
|
||||
|
||||
.zipcontainer {
|
||||
display: flex;
|
||||
width: 352px;
|
||||
height: 160px;
|
||||
flex-wrap: wrap;
|
||||
margin-right: 56px;
|
||||
margin-top: 90px;
|
||||
|
||||
.item {
|
||||
margin-right: 50px;
|
||||
margin-bottom: 50px;
|
||||
|
||||
.itemup {
|
||||
width: 352px;
|
||||
height: 160px;
|
||||
background: #ffffff;
|
||||
border-radius: 2px 2px 0px 0px;
|
||||
border: 1px solid #4ea6ff;
|
||||
position: relative;
|
||||
|
||||
.lefttop {
|
||||
width: 8px;
|
||||
height: 21px;
|
||||
background: #4ea6ff;
|
||||
border-radius: 0px 4px 4px 0px;
|
||||
top: 18px;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.cent {
|
||||
display: flex;
|
||||
margin-top: 40px;
|
||||
margin-left: 40px;
|
||||
|
||||
.zip {
|
||||
width: 62px;
|
||||
height: 72px;
|
||||
background-image: url(@/assets/images/leveladd/zip.png);
|
||||
background-size: 100%;
|
||||
}
|
||||
|
||||
.ziprit {
|
||||
margin-left: 20px;
|
||||
margin-top: -5px;
|
||||
|
||||
.textop {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: #4ea6ff;
|
||||
}
|
||||
|
||||
.texdown {
|
||||
.timemanag {
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
color: #878b92;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.itemdown {
|
||||
width: 352px;
|
||||
height: 48px;
|
||||
border-radius: 0px 0px 2px 2px;
|
||||
border: 1px solid #4ea6ff;
|
||||
border-top: 0;
|
||||
display: flex;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
line-height: 22px;
|
||||
|
||||
.download {
|
||||
width: 176px;
|
||||
height: 48px;
|
||||
color: #ffffff;
|
||||
cursor: pointer;
|
||||
background: #409eff;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.download:hover {
|
||||
background-color: rgba(64, 158, 255, 0.76);
|
||||
}
|
||||
|
||||
.download:active {
|
||||
background-color: #0982ff;
|
||||
}
|
||||
|
||||
.delete {
|
||||
width: 176px;
|
||||
height: 48px;
|
||||
color: #4ea6ff;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.delete:hover {
|
||||
background-color: rgba(64, 158, 255, 0.1);
|
||||
}
|
||||
|
||||
.delete:active {
|
||||
background-color: rgba(64, 158, 255, 0.2);
|
||||
}
|
||||
|
||||
.outime {
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
color: #878b92;
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user