初始化

This commit is contained in:
hezhidong
2024-01-30 09:30:56 +08:00
parent a38cfb023d
commit ff582f261b
213 changed files with 37514 additions and 4 deletions
+79
View File
@@ -0,0 +1,79 @@
<template>
<div id="app">
<router-view />
<Setings ref="setingsRef" />
</div>
</template>
<script>
import setIntroduction from "@/utils/setIconfont.js";
import { Local } from "@/utils/storage.js";
import Setings from "@/layout/navBars/breadcrumb/setings.vue";
import Upgrade from "@/layout/upgrade/index.vue";
export default {
name: "App",
components: { Setings, Upgrade },
mounted() {
this.initSetIconfont();
this.openSetingsDrawer();
this.getLayoutThemeConfig();
},
methods: {
// 设置初始化,防止刷新时恢复默认
initSetIconfont() {
// 设置批量第三方 icon 图标
setIntroduction.cssCdn();
// 设置批量第三方 js
setIntroduction.jsCdn();
},
// 布局配置弹窗打开
openSetingsDrawer() {
this.bus.$on("openSetingsDrawer", () => {
this.$refs.setingsRef.openDrawer();
});
},
// 获取缓存中的布局配置
getLayoutThemeConfig() {
if (Local.get("themeConfigPrev")) {
this.$store.dispatch("themeConfig/setThemeConfig", Local.get("themeConfigPrev"));
document.documentElement.style.cssText = Local.get("themeConfigStyle");
} else {
Local.set("themeConfigPrev", this.$store.state.themeConfig.themeConfig);
}
},
},
watch: {
// 监听路由的变化
$route: {
handler(to) {
this.$nextTick(() => {
let webTitle = "";
let { globalTitle } = this.$store.state.themeConfig.themeConfig;
to.path === "/login"
? (webTitle = to.meta.title)
: (webTitle = this.$t(to.meta.title));
document.title = `${webTitle} - ${globalTitle}` || globalTitle;
});
},
deep: true,
immediate: true,
},
},
destroyed() {
this.bus.$off("openSetingsDrawer");
},
};
</script>
<style>
textarea {
resize: none;
}
.el-textarea .el-textarea__inner {
resize: none;
}
.box-card {
margin-top: 10px;
}
</style>
+65
View File
@@ -0,0 +1,65 @@
import request from '@/utils/request';
import logoRequest from '@/utils/logoRequest';
/**
* 登录api接口集合
* @method signIn 用户登录
* @method signOut 用户退出登录
*/
// export function useLoginApi() {
// return {
// signIn: (params) => {
// return request({
// url: '/user/signIn',
// method: 'post',
// data: params,
// });
// },
// signOut: (params) => {
// return request({
// url: '/user/signOut',
// method: 'post',
// data: params,
// });
// },
// };
// }
export function useLoginApi() {
return {
signIn: (params) => {
return request({
url: '/auth/login',
method: 'post',
data: params,
});
},
signOut: () => {
return request({
url: '/auth/logout',
method: 'DELETE',
});
},
// 获取验证码
getCode: () => {
return request({
url: '/code',
method: 'get',
});
},
// 获取用户信息
requestToObtainUserInformation: () => {
return request({
url: '/user-dept/user/info',
method: 'get',
});
},
// 登录获取thken
loginToObtain: (authCode) => {
return logoRequest({
url: "/oauth2/token?client_id=test-client&client_secret=123456&login_type=qrcode&grant_type=dingtalk&authCode="+authCode,
method: 'post',
});
},
};
}
+54
View File
@@ -0,0 +1,54 @@
import request from '@/utils/request';
/**
* webpack 的代理只是本地开发生效,打包后需要在部署环境 搭建 nginx 代理
* 所以:
* 开发环境,请求跨越的接口。为了配置跨越示例
* 线上环境,请求目录下的 `json` 数据
* 一般后端接口都会处理跨越问题,可根据具体情况进行修改
* json 格式地址:https://gitee.com/lyt-top/vue-next-admin-images/tree/master/vue2
* 本地菜单地址:public/xxx.json
*/
/**
* 后端控制菜单模拟json,路径在 https://gitee.com/lyt-top/vue-next-admin-images/tree/master/menu
* 后端控制路由,isRequestRoutes 为 true,则开启后端控制路由
* @method getMenuAdmin 获取后端动态路由菜单(admin)
* @method getMenuTest 获取后端动态路由菜单(test)
*/
export function useMenuApi() {
return {
getMenuAdmin: (params) => {
// 本地数据,路径:`/public/xxx.json`
// return request({
// url: './admin.json',
// method: 'get',
// params,
// });
// 模拟跨域
// return request({
// url: '/gitee/lyt-top/vue-next-admin-images/raw/master/vue2/admin.json',
// method: 'get',
// });
// 获取袁永军路由表
return request({
url: '/system/menu/getRouters',
method: 'get',
params,
});
},
getMenuTest: (params) => {
// 本地数据,路径:`/public/xxx.json`
return request({
url: './test.json',
method: 'get',
params,
});
// 模拟跨域
// return request({
// url: '/gitee/lyt-top/vue-next-admin-images/raw/master/vue2/test.json',
// method: 'get',
// });
},
};
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

+6
View File
@@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 50" width="64" height="50">
<style>
tspan { white-space:pre }
</style>
<path id="p " fill="#409eff" d="M32.37 1.82L32.37 1.82Q33.13 1.88 33.13 2.05L33.77 1.94Q44.03 1.94 49.24 11.55Q50.12 13.71 50.12 15.94Q50.12 20.75 45.61 24.03Q41.86 26.31 37.93 26.31L37.82 26.31Q34.24 26.31 30.02 25.14Q28.32 30.71 25.86 40.61L26.04 40.84Q25.39 43.36 24.46 48.4Q24.34 48.4 24.05 48.52Q19.13 46.23 19.13 42.84Q20.18 36.45 20.71 34.75Q20.71 31.82 16.31 25.67Q14.73 22.21 14.73 20.1L14.85 19.87Q14.85 19.75 14.73 19.75Q15.67 14.54 16.31 14.54Q17.07 11.96 22.64 6.63Q25.45 4.46 28.85 2.99Q30.67 2.52 32.37 1.82ZM35.77 4.69L35.77 4.69L35.77 4.81Q35.77 7.09 31.72 19.05Q31.72 19.4 30.67 22.56L30.55 23.21L30.55 23.62Q30.9 24.14 34.18 24.14Q38.23 24.14 42.09 21.57Q45.43 19.11 46.37 15.71L46.25 15.41Q46.66 14.54 46.66 14.01L46.66 12.31Q46.66 10.02 43.91 6.74Q40.8 4.69 36.53 4.69L35.77 4.69ZM18.48 16.88L18.48 16.88Q21.88 20.22 24.05 21.27Q24.81 19.52 26.04 15.18L27.45 10.79L28.73 7.27Q29.03 7.27 29.03 6.51L28.85 6.51Q22.64 8.97 18.77 16.12Q18.77 16.18 18.48 16.88ZM18.13 17.41L18.13 17.41Q17.6 19.05 17.31 21.57Q17.31 25.9 21.59 31L23.93 22.33Q23.93 22.04 21.06 20.1Q18.48 17.76 18.48 17.41L18.13 17.41Z" />
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

+17
View File
@@ -0,0 +1,17 @@
// timeStr表示时间 separator表示分隔符 type == yaer表示只返回年月日
export function formatDate (timeStr = (new Date()), separator = '-', type){
const date = new Date(timeStr)
let yaer = date.getFullYear()
let month = date.getMonth() + 1
let day = date.getDate()
let hour = date.getHours()
let minute = date.getMinutes()
let second = date.getSeconds()
if(type == 'year'){
return yaer + separator + (month >= 10 ? month : ('0' + month)) + separator + (day >= 10 ? day : ('0' + day))
}else {
return yaer + separator + (month >= 10 ? month : ('0' + month)) + separator + (day >= 10 ? day : ('0' + day)) + ' ' + (hour >= 10 ? hour : ('0' + hour)) + ':' + (minute >= 10 ? minute : ('0' + minute)) + ':' + (second >= 10 ? second : ('0' + second))
}
}
+47
View File
@@ -0,0 +1,47 @@
<template>
<div>
<el-button @click="newlyClick" type="primary" size="mini" icon="el-icon-plus"
>新增</el-button
>
<el-button @click="resetClick" type="info" size="mini" icon="iconfont icon-biaodan"
>重置</el-button
>
<el-button @click="searchClick" type="warning" size="mini" icon="el-icon-search"
>搜索</el-button
>
<el-input
v-if="false"
v-model="searchData"
size="mini"
style="width: 20%"
placeholder="请输入搜索的关键字"
>
</el-input>
</div>
</template>
<script>
export default {
name: "CommonHead",
data() {
return {
searchData: "",
};
},
methods: {
newlyClick() {
// 在此处调用父组件传入的方法叫父组件做事情
this.$emit("newly-data");
},
resetClick() {
this.$emit("reset-data");
},
searchClick() {
this.$emit("search-data", this.searchData);
},
},
};
</script>
<style lang="scss" scoped></style>
+108
View File
@@ -0,0 +1,108 @@
<template>
<el-table
border
:header-cell-style="{
background: '#f5f7fa',
}"
:data="tableData"
style="width: 100%; margin-top: 20px"
height="650"
size="mini"
>
<el-table-column
v-if="column.label !== 'id'"
align="left"
v-for="(column, index) in tableColumns"
:key="index"
:prop="column.prop"
:label="column.label"
width="auto"
></el-table-column>
<el-table-column align="left" prop="zip" label="操作" width="160">
<template slot-scope="scope">
<el-button
@click="handleEdit(scope.row)"
class="el-icon-edit"
type="text"
size="small"
>编辑</el-button
>
<el-popconfirm @confirm="handleDelete(scope.row)" :title="'确定要删除吗?'">
<el-button
slot="reference"
style="margin-left: 10px; color: red"
class="el-icon-delete"
type="text"
size="small"
>删除</el-button
>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
</template>
<script>
export default {
props: {
columns: {
type: Array,
required: true,
},
data: {
type: Array,
required: true,
},
deleteFunc: {
type: Function,
default: () => {},
},
editFunc: {
type: Function,
default: () => {},
},
},
name: "CommonTables",
data() {
return {};
},
methods: {
// 删除事件
handleDelete(row) {
this.deleteFunc(row);
},
// 编辑事件
handleEdit(row) {
console.log(row);
this.editFunc(row);
},
},
computed: {
tableColumns() {
// 处理传进来的列配置,返回符合 Element UI 表格要求的配置
return this.columns.map((column) => {
return {
label: column.label,
prop: column.prop,
};
});
},
tableData() {
// 处理传进来的数据,返回符合 Element UI 表格要求的数据
return this.data.map((rowData) => {
let row = {};
for (let column of this.columns) {
row[column.prop] = rowData[column.prop];
}
return row;
});
},
},
};
</script>
<style lang="scss" scoped>
.s {
color: red;
}
</style>
+127
View File
@@ -0,0 +1,127 @@
<template>
<el-table
border
:header-cell-style="{
background: '#f5f7fa',
}"
:data="tableData"
style="width: 100%; margin-top: 20px"
height="650"
size="mini"
>
<el-table-column
v-if="column.label !== 'id'"
align="left"
v-for="(column, index) in tableColumns"
:key="index"
:prop="column.prop"
:label="column.label"
width="auto"
>
<template slot-scope="scope">
<span v-if="column.type === 'text'"> {{ scope.row[column.prop] }}</span>
<div v-else-if="column.type === 'signUp'">
<el-tag size="small" v-if="scope.row[column.prop] == 0">已到</el-tag>
<el-tag size="small" type="success" v-else-if="scope.row[column.prop] == 1"
>迟到</el-tag
>
<el-tag size="small" type="danger" v-else-if="scope.row[column.prop] == 2"
>旷课</el-tag
>
<el-tag size="small" type="warning" v-else-if="scope.row[column.prop] == 3"
>请假</el-tag
>
<el-tag size="small" type="warning" v-else-if="scope.row[column.prop] == 4"
>早退</el-tag
>
</div>
<div v-else-if="column.type === 'image'">
<img style="width: 200px; height: 100px" :src="scope.row[column.prop]" />
</div>
</template>
</el-table-column>
<el-table-column align="left" label="操作" width="160">
<template slot-scope="scope">
<el-button
@click="handleEdit(scope.row)"
class="el-icon-edit"
type="text"
size="small"
>编辑</el-button
>
<el-popconfirm @confirm="handleDelete(scope.row)" :title="'确定要删除吗?'">
<el-button
slot="reference"
style="margin-left: 10px; color: red"
class="el-icon-delete"
type="text"
size="small"
>删除</el-button
>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
</template>
<script>
export default {
name: "CommonTablesImg",
props: {
columns: {
type: Array,
required: true,
},
data: {
type: Array,
required: true,
},
deleteFunc: {
type: Function,
default: () => {},
},
editFunc: {
type: Function,
default: () => {},
},
},
data() {
return {};
},
methods: {
// 删除事件
handleDelete(row) {
this.deleteFunc(row);
},
// 编辑事件
handleEdit(row) {
console.log(row);
this.editFunc(row);
},
},
computed: {
tableColumns() {
// 处理传进来的列配置,返回符合 Element UI 表格要求的配置
return this.columns.map((column) => {
return {
label: column.label,
prop: column.prop,
type: column.type,
};
});
},
tableData() {
// 处理传进来的数据,返回符合 Element UI 表格要求的数据
return this.data.map((rowData) => {
let row = {};
for (let column of this.columns) {
row[column.prop] = rowData[column.prop];
}
return row;
});
},
},
};
</script>
<style lang="scss" scoped></style>
+140
View File
@@ -0,0 +1,140 @@
<template>
<el-dialog title="图片剪裁" width="630px" :visible.sync="dialogVisible" append-to-body>
<div class="cropper-content">
<div class="cropper" style="text-align: center">
<!-- 这个组件vueCropper就是我们刚才引入在main.js里面的那个 直接拿来用 就好 -->
<vueCropper
ref="cropper"
:img="option.img"
:output-size="option.size"
:output-type="option.outputType"
:info="true"
:full="option.full"
:can-move="option.canMove"
:can-move-box="option.canMoveBox"
:original="option.original"
:auto-crop="option.autoCrop"
:fixed="option.fixed"
:fixed-number="option.fixedNumber"
:center-box="option.centerBox"
:info-true="option.infoTrue"
:fixed-box="option.fixedBox"
/>
</div>
</div>
<div slot="footer" class="dialog-footer">
<el-button>
<el-upload
class="avatar-uploader"
list-type="picture"
action=""
:auto-upload="false"
:show-file-list="false"
:on-change="changeUpload"
>
<i class="el-icon-refresh" style="margin-right: 5px" />换图片
</el-upload>
</el-button>
<el-button @click="dialogVisible = false">取 消</el-button>
<el-button type="primary" @click="finish">确认</el-button>
</div>
</el-dialog>
</template>
<script>
import axios from "axios"; //你们有封装接口了的 就直接用你们封装的方法来写 我这里是为了做样式 就直接用了axios请求
// 发送到服务器的请求
import { rqUploadImages } from "../../views/growthAlbumSection/pictureSetConfiguration/api";
export default {
data() {
return {
dialogVisible: false,
// 这都是需要用到的参数看个人需求 用不到的可以删除 可以去官网参考一下
option: {
name: "",
img: "",
info: true,
outputSize: 1,
outputType: "png",
canScale: false,
autoCrop: true,
fixedBox: false,
fixed: false,
fixedNumber: [150, 240],
full: true,
canMoveBox: true,
original: false,
centerBox: false,
infoTrue: true,
},
// 上传线上地址的数据
form: {
files: [],
type: "",
},
};
},
mounted() {},
methods: {
changeUpload(file) {
let testmsg = file.name.substring(file.name.lastIndexOf(".") + 1);
const isJPG = testmsg === "jpg";
const isJPEG = testmsg === "jpeg";
const isPNG = testmsg === "png";
if (!isJPG && !isPNG && !isJPEG) {
this.$message.error("上传图片只能是 JPG/JPEG 或 PNG 格式!");
return;
}
this.$nextTick(() => {
this.option.img = file.url;
this.option.name = file.name;
this.dialogVisible = true;
});
},
// 上传
async Upload() {
let json = "";
let newJson = JSON.stringify(this.form);
json = newJson;
try {
let result = await rqUploadImages(json);
if (result.code == 200) {
this.$message.success("新增成功");
} else {
this.$message.error("服务器错误");
}
} catch (error) {
this.$message.error("网络错误");
}
},
finish() {
this.$refs.cropper.getCropBlob(async (data) => {
let file = new FormData(); //转formData格式 因为我们获取的是blob类型 我后端只支持文件类型所以转了 如果你们后端什么格式都接受 这里就不用走了
var abc = new File([data], this.option.name, { type: "image/jpg" });
file.append("img", abc);
axios
.post(this.$store.state.imgUrl, file, {
// headers: {
// "Content-Type": "application/x-www-form-urlencoded",
// token: "这里是token 后端需要的话就带 不需要这个可以删掉",
// },
headers: this.$store.state.uploadHeader,
})
.then((res) => {
console.log(this.form);
console.log(res.data.data); //后端返回来的图片地址
this.form.files.push(res.data.data);
this.Upload();
this.dialogVisible = false;
});
});
},
},
};
</script>
<style scoped>
.cropper {
width: 100%;
height: 400px;
}
</style>
+58
View File
@@ -0,0 +1,58 @@
<!-- page-size 每页数据 -->
<template>
<div class="pagination-box">
<el-pagination
background
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="pageNum"
:page-sizes="[10,20,50,100]"
:page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total">
</el-pagination>
</div>
</template>
<script>
export default {
props:{
total: {
required: true,
type: Number
},
pageNum: {
type: Number
},
pageSize: {
type: Number,
default: 10,
}
},
methods: {
handleSizeChange(val) {
this.$emit('clickSize',val)
},
handleCurrentChange(val) {
this.$emit('clickCurrent',val)
}
},
data() {
return {
};
},
created(){
console.log('分液器')
// 阿莎积分拉萨见附件当了
},
mounted(){
console.log('mounted')
}
}
</script>
<style lang="scss" scoped>
.pagination-box{
padding-top: 20px;
}
</style>
+60
View File
@@ -0,0 +1,60 @@
import Vue from 'vue';
import VueI18n from 'vue-i18n';
import zhcnLocale from 'element-ui/lib/locale/lang/zh-CN';
import enLocale from 'element-ui/lib/locale/lang/en';
import zhtwLocale from 'element-ui/lib/locale/lang/zh-TW';
import store from '@/store/index.js';
import nextZhcn from '@/i18n/lang/zh-cn.js';
import nextEn from '@/i18n/lang/en.js';
import nextZhtw from '@/i18n/lang/zh-tw.js';
import pagesHomeZhcn from '@/i18n/pages/home/zh-cn.js';
import pagesHomeEn from '@/i18n/pages/home/en.js';
import pagesHomeZhtw from '@/i18n/pages/home/zh-tw.js';
import pagesLoginZhcn from '@/i18n/pages/login/zh-cn.js';
import pagesLoginEn from '@/i18n/pages/login/en.js';
import pagesLoginZhtw from '@/i18n/pages/login/zh-tw.js';
// 使用插件
Vue.use(VueI18n);
// 定义语言国际化内容
/**
* 说明:
* /src/i18n/lang 下的 js 为框架的国际化内容
* /src/i18n/pages 下的 js 为各界面的国际化内容
*/
const messages = {
'zh-cn': {
...zhcnLocale,
message: {
...nextZhcn,
...pagesHomeZhcn,
...pagesLoginZhcn,
},
},
en: {
...enLocale,
message: {
...nextEn,
...pagesHomeEn,
...pagesLoginEn,
},
},
'zh-tw': {
...zhtwLocale,
message: {
...nextZhtw,
...pagesHomeZhtw,
...pagesLoginZhtw,
},
},
};
// 导出语言国际化
export const i18n = new VueI18n({
locale: store.state.themeConfig.themeConfig.globalI18n,
fallbackLocale: 'zh-cn',
messages,
});
+169
View File
@@ -0,0 +1,169 @@
// 定义内容
export default {
router: {
home: 'home',
system: 'system',
systemMenu: 'systemMenu',
systemUser: 'systemUser',
limits: 'limits',
limitsFrontEnd: 'FrontEnd',
limitsFrontEndPage: 'FrontEndPage',
limitsFrontEndBtn: 'FrontEndBtn',
limitsBackEnd: 'BackEnd',
ParentList:'ParentList',
limitsBackEndEndPage: 'BackEndEndPage',
MeetingRoomReservation:'MeetingRoomReservation',
CreateMeetingRoom:'CreateMeetingRoom',
CreateFunctionRoom:'CreateFunctionRoom',
TeacherTable:'TeacherTable',
CampusCalendar:'CampusCalendar',
StudentTable:'StudentTable',
PrincipalsMailbox:"PrincipalsMailbox",
roleManagement:'roleManagement',
abnormalStudentManagement:'abnormalStudentManagement',
morningAndAfternoonInspectionManagement:'morningAndAfternoonInspectionManagement',
deviceManagement:'deviceManagement',
schoolAlbumManagement:'schoolAlbumManagement',
Statistics:'Statistics',
LetterList:"LetterList",
ccInformation:"ccInformation",
moralEducationManagement:'moralEducationManagement',
personnelManagement:'personnelManagement',
ResponsiblePersonManagement:'ResponsiblePersonManagement',
AttendanceForm:'AttendanceForm',
StudentSafetyAttendance:'StudentSafetyAttendance',
SetAttendanceRules:'SetAttendanceRules',
Inspect:'Inspect',
MoralEducationEvaluation:'MoralEducationEvaluation',
InterestClass:'InterestClass',
InterestClassEntry:'InterestClassEntry',
InterestCourseManagement:'InterestCourseManagement',
PaymentSystem:'PaymentSystem',
CreatePayment:'CreatePayment',
PaymentDetails:'PaymentDetails',
SmartVisitors:'SmartVisitors',
HomeSchoolAddressBook:'HomeSchoolAddressBook',
VisitorsRecord:'VisitorsRecord',
basicInFormation:'basicInFormation',
businessDataInformation:"businessDataInformation",
dataItemAnalysis:'dataItemAnalysis',
dataItemConfiguration:'dataItemConfiguration',
pictureSetConfiguration:'pictureSetConfiguration',
growthAlbumSection:'growthAlbumSection',
rolePermissions:"rolePermissions",
setScoreRules:'setScoreRules',
facultyInformation:'facultyInformation',
attendanceMachineEquipmentManagement:'attendanceMachineEquipmentManagement'
},
staticRoutes: {
signIn: 'signIn',
notFound: 'notFound',
noPower: 'noPower',
},
user: {
title0: 'Component size',
title1: 'Language switching',
title2: 'Menu search',
title3: 'Layout configuration',
title4: 'news',
title5: 'Full screen on',
title6: 'Full screen off',
dropdownDefault: 'default',
dropdownMedium: 'medium',
dropdownSmall: 'small',
dropdownMini: 'mini',
dropdown1: 'home page',
dropdown2: 'Personal Center',
dropdown3: '404',
dropdown4: '401',
dropdown5: 'Log out',
dropdown6: 'Code warehouse',
searchPlaceholder: 'Menu search: support Chinese, routing path',
newTitle: 'notice',
newBtn: 'All read',
newGo: 'Go to the notification center',
newDesc: 'No notice',
logOutTitle: 'Tips',
logOutMessage: 'This operation will log out. Do you want to continue?',
logOutConfirm: 'determine',
logOutCancel: 'cancel',
logOutExit: 'Exiting',
logOutSuccess: 'Exit successfully!',
},
tagsView: {
refresh: 'refresh',
close: 'close',
closeOther: 'closeOther',
closeAll: 'closeAll',
fullscreen: 'fullscreen',
},
notFound: {
foundTitle: 'Wrong address input, please re-enter the address~',
foundMsg: 'You can check the web address first, and then re-enter or give us feedback.',
foundBtn: 'Back to home page',
},
noAccess: {
accessTitle: 'You are not authorized to operate~',
accessMsg: 'Contact information: add QQ group discussion 665452019',
accessBtn: 'Reauthorization',
},
layout: {
configTitle: 'Layout configuration',
oneTitle: 'Global Themes',
twoTitle: 'Menu / top bar',
twoTopBar: 'Top bar background',
twoMenuBar: 'Menu background',
twoColumnsMenuBar: 'Column menu background',
twoTopBarColor: 'Top bar default font color',
twoMenuBarColor: 'Menu default font color',
twoColumnsMenuBarColor: 'Default font color bar menu',
twoIsTopBarColorGradual: 'Top bar gradient',
twoIsMenuBarColorGradual: 'Menu gradient',
twoIsMenuBarColorHighlight: 'Menu font highlight',
threeTitle: 'Interface settings',
threeIsCollapse: 'Menu horizontal collapse',
threeIsUniqueOpened: 'Menu accordion',
threeIsFixedHeader: 'Fixed header',
threeIsClassicSplitMenu: 'Classic layout split menu',
threeIsLockScreen: 'Open the lock screen',
threeLockScreenTime: 'screen locking(s/s)',
fourTitle: 'Interface display',
fourIsShowLogo: 'Sidebar logo',
fourIsBreadcrumb: 'Open breadcrumb',
fourIsBreadcrumbIcon: 'Open breadcrumb icon',
fourIsTagsview: 'Open tagsview',
fourIsTagsviewIcon: 'Open tagsview Icon',
fourIsCacheTagsView: 'Enable tagsview cache',
fourIsSortableTagsView: 'Enable tagsview drag',
fourIsFooter: 'Open footer',
fourIsGrayscale: 'Grey model',
fourIsInvert: 'Color weak mode',
fourIsDark: 'Dark Mode',
fourIsWartermark: 'Turn on watermark',
fourWartermarkText: 'Watermark copy',
fiveTitle: 'Other settings',
fiveTagsStyle: 'Tagsview style',
fiveAnimation: 'page animation',
fiveColumnsAsideStyle: 'Column style',
fiveColumnsAsideLayout: 'Column layout',
sixTitle: 'Layout switch',
sixDefaults: 'One',
sixClassic: 'Two',
sixTransverse: 'Three',
sixColumns: 'Four',
tipText: 'Click the button below to copy the layout configuration to `/src/store/modules/themeConfig.js` It has been modified in.',
copyText: 'replication configuration',
resetText: 'restore default',
copyTextSuccess: 'Copy succeeded!',
copyTextError: 'Copy failed!',
},
upgrade: {
title: 'New version',
msg: 'The new version is available, please update it now! Dont worry, the update is fast!',
desc: 'Prompt: Update will restore the default configuration',
btnOne: 'Cruel refusal',
btnTwo: 'Update now',
btnTwoLoading: 'Updating',
},
};
+170
View File
@@ -0,0 +1,170 @@
// 定义内容
export default {
router: {
home: '首页',
system: '系统设置',
systemMenu: '菜单管理',
systemUser: '用户管理',
limits: '权限管理',
limitsFrontEnd: '前端控制',
limitsFrontEndPage: '页面权限',
limitsFrontEndBtn: '按钮权限',
limitsBackEnd: '后端控制',
personnelManagement:'人员管理',
limitsBackEndEndPage: '页面权限',
MeetingRoomReservation:'会议室与功能室',
CreateMeetingRoom:'创建会议室',
CreateFunctionRoom:'创建功能室',
CampusCalendar:'校园行事历',
ParentList:'家长列表',
StudentTable:'学生列表',
PrincipalsMailbox:"校长信箱",
LetterList:'信件列表',
TeacherTable:'教师列表',
abnormalStudentManagement:'异常学生管理',
morningAndAfternoonInspectionManagement:"晨午检管理",
deviceManagement:'人脸设备管理',
ResponsiblePersonManagement:'负责人管理',
moralEducationManagement:'德育管理',
Statistics:'统计',
ccInformation:'配置',
AttendanceForm:'考勤表单',
StudentSafetyAttendance:'学生安全考勤',
SetAttendanceRules:'设置考勤规则',
Inspect:'晨午检查',
roleManagement:'角色分配',
MoralEducationEvaluation:'德育评价',
InterestClass:'兴趣班',
InterestClassEntry:'兴趣班录入',
InterestCourseManagement:'兴趣课程管理',
PaymentSystem:'缴费系统',
CreatePayment:'创建缴费',
PaymentDetails:'缴费明细',
SmartVisitors:'智能访客',
HomeSchoolAddressBook:'家校通信录',
VisitorsRecord:'访客记录',
basicInFormation:'信息管理',
businessDataInformation:'业务数据管理',
dataItemAnalysis:'数据项分析',
dataItemConfiguration:'数据项配置',
pictureSetConfiguration:'图片集配置',
growthAlbumSection:'成长画册',
rolePermissions:'角色权限',
setScoreRules:'设置规则',
schoolAlbumManagement:'学校画册管理',
facultyInformation:'教职工信息',
attendanceMachineEquipmentManagement:'考勤机设备管理',
},
staticRoutes: {
signIn: '登录',
notFound: '找不到此页面',
noPower: '没有权限',
},
user: {
title0: '组件大小',
title1: '语言切换',
title2: '菜单搜索',
title3: '布局配置',
title4: '消息',
title5: '开全屏',
title6: '关全屏',
dropdownDefault: '默认',
dropdownMedium: '中等',
dropdownSmall: '小型',
dropdownMini: '超小',
dropdown1: '首页',
dropdown2: '个人中心',
dropdown3: '404',
dropdown4: '401',
dropdown5: '退出登录',
dropdown6: '代码仓库',
searchPlaceholder: '菜单搜索:支持中文、路由路径',
newTitle: '通知',
newBtn: '全部已读',
newGo: '前往通知中心',
newDesc: '暂无通知',
logOutTitle: '提示',
logOutMessage: '此操作将退出登录, 是否继续?',
logOutConfirm: '确定',
logOutCancel: '取消',
logOutExit: '退出中',
logOutSuccess: '安全退出成功!',
},
tagsView: {
refresh: '刷新',
close: '关闭',
closeOther: '关闭其它',
closeAll: '全部关闭',
fullscreen: '当前页全屏',
},
notFound: {
foundTitle: '地址输入错误,请重新输入地址~',
foundMsg: '您可以先检查网址,然后重新输入或给我们反馈问题。',
foundBtn: '返回首页',
},
noAccess: {
accessTitle: '您未被授权,没有操作权限~',
accessMsg: '联系方式:加QQ群探讨 665452019',
accessBtn: '重新授权',
},
layout: {
configTitle: '布局配置',
oneTitle: '全局主题',
twoTitle: '菜单 / 顶栏',
twoTopBar: '顶栏背景',
twoMenuBar: '菜单背景',
twoColumnsMenuBar: '分栏菜单背景',
twoTopBarColor: '顶栏默认字体颜色',
twoMenuBarColor: '菜单默认字体颜色',
twoColumnsMenuBarColor: '分栏菜单默认字体颜色',
twoIsTopBarColorGradual: '顶栏背景渐变',
twoIsMenuBarColorGradual: '菜单背景渐变',
twoIsMenuBarColorHighlight: '菜单字体背景高亮',
threeTitle: '界面设置',
threeIsCollapse: '菜单水平折叠',
threeIsUniqueOpened: '菜单手风琴',
threeIsFixedHeader: '固定 Header',
threeIsClassicSplitMenu: '经典布局分割菜单',
threeIsLockScreen: '开启锁屏',
threeLockScreenTime: '自动锁屏(s/秒)',
fourTitle: '界面显示',
fourIsShowLogo: '侧边栏 Logo',
fourIsBreadcrumb: '开启 Breadcrumb',
fourIsBreadcrumbIcon: '开启 Breadcrumb 图标',
fourIsTagsview: '开启 Tagsview',
fourIsTagsviewIcon: '开启 Tagsview 图标',
fourIsCacheTagsView: '开启 TagsView 缓存',
fourIsSortableTagsView: '开启 TagsView 拖拽',
fourIsFooter: '开启 Footer',
fourIsGrayscale: '灰色模式',
fourIsInvert: '色弱模式',
fourIsDark: '深色模式',
fourIsWartermark: '开启水印',
fourWartermarkText: '水印文案',
fiveTitle: '其它设置',
fiveTagsStyle: 'Tagsview 风格',
fiveAnimation: '主页面切换动画',
fiveColumnsAsideStyle: '分栏高亮风格',
fiveColumnsAsideLayout: '分栏布局风格',
sixTitle: '布局切换',
sixDefaults: '默认',
sixClassic: '经典',
sixTransverse: '横向',
sixColumns: '分栏',
tipText: '点击下方按钮,复制布局配置去 `src/store/modules/themeConfig.js` 中修改。',
copyText: '一键复制配置',
resetText: '一键恢复默认',
copyTextSuccess: '复制成功!',
copyTextError: '复制失败!',
},
upgrade: {
title: '新版本升级',
msg: '新版本来啦,马上更新尝鲜吧!不用担心,更新很快的哦!',
desc: '提示:更新会还原默认配置',
btnOne: '残忍拒绝',
btnTwo: '马上更新',
btnTwoLoading: '更新中',
},
};
+168
View File
@@ -0,0 +1,168 @@
// 定义内容
export default {
router: {
home: '首頁',
system: '系統設置',
systemMenu: '選單管理',
systemUser: '用戶管理',
limits: '許可權管理',
limitsFrontEnd: '前端控制',
limitsFrontEndPage: '頁面許可權',
limitsFrontEndBtn: '按鈕許可權',
limitsBackEnd: '後端控制',
personnelManagement:'人員管理',
ParentList:'家長列表',
limitsBackEndEndPage: '頁面許可權',
MeetingRoomReservation:'會議室與功能室',
CreateMeetingRoom:'創建會議室',
CreateFunctionRoom:'創建功能室',
CampusCalendar:'校園行事歷',
PrincipalsMailbox:"校長信箱",
TeacherTable:'教師列表',
abnormalStudentManagement:'异常学生管理',
roleManagement:'角色分配',
StudentTable:'學生列表',
LetterList:"信件列表",
Statistics:'统计',
ccInformation:'配置',
moralEducationManagement:'德育管理',
ResponsiblePersonManagement:'負責人管理',
morningAndAfternoonInspectionManagement:"晨午检管理",
AttendanceForm:'考勤表單',
StudentSafetyAttendance:'學生安全考勤',
SetAttendanceRules:'設置考勤規則',
Inspect:'晨午檢查',
MoralEducationEvaluation:'德育評價',
InterestClass:'興趣班',
InterestClassEntry:'興趣班錄入',
InterestCourseManagement:'興趣課程管理',
PaymentSystem:'繳費系統',
CreatePayment:'創建繳費',
PaymentDetails:'繳費明細',
SmartVisitors:'智能訪客',
HomeSchoolAddressBook:'家校通信錄',
VisitorsRecord:'訪客記錄',
basicInFormation:'信息管理',
businessDataInformation:'業務數據管理',
dataItemAnalysis:'數據項分析',
dataItemConfiguration:'數據項配置',
pictureSetConfiguration:'圖片集配置',
growthAlbumSection:'成長畫冊',
rolePermissions:'角色权限',
setScoreRules:'设置规则',
schoolAlbumManagement:'學校畫冊管理',
facultyInformation:'教職工信息',
deviceManagement:'人脸设备管理',
attendanceMachineEquipmentManagement:'考勤機設備管理',
},
staticRoutes: {
signIn: '登入',
notFound: '找不到此頁面',
noPower: '沒有許可權',
},
user: {
title0: '組件大小',
title1: '語言切換',
title2: '選單蒐索',
title3: '佈局配寘',
title4: '消息',
title5: '開全屏',
title6: '關全屏',
dropdownDefault: '默認',
dropdownMedium: '中等',
dropdownSmall: '小型',
dropdownMini: '超小',
dropdown1: '首頁',
dropdown2: '個人中心',
dropdown3: '404',
dropdown4: '401',
dropdown5: '登出',
dropdown6: '程式碼倉庫',
searchPlaceholder: '選單蒐索:支援中文、路由路徑',
newTitle: '通知',
newBtn: '全部已讀',
newGo: '前往通知中心',
newDesc: '暫無通知',
logOutTitle: '提示',
logOutMessage: '此操作將登出,是否繼續?',
logOutConfirm: '確定',
logOutCancel: '取消',
logOutExit: '退出中',
logOutSuccess: '安全退出成功!',
},
tagsView: {
refresh: '重繪',
close: '關閉',
closeOther: '關閉其它',
closeAll: '全部關閉',
fullscreen: '當前頁全屏',
},
notFound: {
foundTitle: '地址輸入錯誤,請重新輸入地址~',
foundMsg: '您可以先檢查網址,然後重新輸入或給我們迴響問題。',
foundBtn: '返回首頁',
},
noAccess: {
accessTitle: '您未被授權,沒有操作許可權~',
accessMsg: '聯繫方式:加QQ群探討665452019',
accessBtn: '重新授權',
},
layout: {
configTitle: '佈局配寘',
oneTitle: '全域主題',
twoTitle: '選單 / 頂欄',
twoTopBar: '頂欄背景',
twoMenuBar: '選單背景',
twoColumnsMenuBar: '分欄選單背景',
twoTopBarColor: '頂欄默認字體顏色',
twoMenuBarColor: '選單默認字體顏色',
twoColumnsMenuBarColor: '分欄選單默認字體顏色',
twoIsTopBarColorGradual: '頂欄背景漸變',
twoIsMenuBarColorGradual: '選單背景漸變',
twoIsMenuBarColorHighlight: '選單字體背景高亮',
threeTitle: '介面設定',
threeIsCollapse: '選單水准折疊',
threeIsUniqueOpened: '選單手風琴',
threeIsFixedHeader: '固定 Header',
threeIsClassicSplitMenu: '經典佈局分割選單',
threeIsLockScreen: '開啟鎖屏',
threeLockScreenTime: '自動鎖屏(s/秒)',
fourTitle: '介面顯示',
fourIsShowLogo: '側邊欄 Logo',
fourIsBreadcrumb: '開啟 Breadcrumb',
fourIsBreadcrumbIcon: '開啟 Breadcrumb 圖標',
fourIsTagsview: '開啟 Tagsview',
fourIsTagsviewIcon: '開啟 Tagsview 圖標',
fourIsCacheTagsView: '開啟 TagsView 緩存',
fourIsSortableTagsView: '開啟 TagsView 拖拽',
fourIsFooter: '開啟 Footer',
fourIsGrayscale: '灰色模式',
fourIsInvert: '色弱模式',
fourIsDark: '深色模式',
fourIsWartermark: '開啟浮水印',
fourWartermarkText: '浮水印文案',
fiveTitle: '其它設定',
fiveTagsStyle: 'Tagsview 風格',
fiveAnimation: '主頁面切換動畫',
fiveColumnsAsideStyle: '分欄高亮風格',
fiveColumnsAsideLayout: '分欄佈局風格',
sixTitle: '佈局切換',
sixDefaults: '默認',
sixClassic: '經典',
sixTransverse: '橫向',
sixColumns: '分欄',
tipText: '點擊下方按鈕,複製佈局配寘去`src/store/modules/themeConfig.js`中修改。',
copyText: '一鍵複製配寘',
resetText: '一鍵恢復默認',
copyTextSuccess: '複製成功!',
copyTextError: '複製失敗!',
},
upgrade: {
title: '新版本陞級',
msg: '新版本來啦,馬上更新嘗鮮吧! 不用擔心,更新很快的哦!',
desc: '提示:更新會還原默認配寘',
btnOne: '殘忍拒絕',
btnTwo: '馬上更新',
btnTwoLoading: '更新中',
},
};
+14
View File
@@ -0,0 +1,14 @@
// 定义内容
export default {
card: {
title1: 'My desk',
title2: 'Message notification',
title3: 'more',
title4: 'Marketing recommendation',
title5: 'more',
title6: 'Inventory operations',
title7: 'Performance',
title8: 'Out of stock monitoring',
title9: 'Performance overtime warning',
},
};
+14
View File
@@ -0,0 +1,14 @@
// 定义内容
export default {
card: {
title1: '我的工作台',
title2: '消息通知',
title3: '更多',
title4: '营销推荐',
title5: '更多',
title6: '库存作业',
title7: '履约情况',
title8: '缺货监控',
title9: '履约超时预警',
},
};
+14
View File
@@ -0,0 +1,14 @@
// 定义内容
export default {
card: {
title1: '我的工作臺',
title2: '消息通知',
title3: '更多',
title4: '行銷推薦',
title5: '更多',
title6: '庫存工作',
title7: '履約情况',
title8: '缺貨監控',
title9: '履約超時預警',
},
};
+18
View File
@@ -0,0 +1,18 @@
// 定义内容
export default {
login: {
placeholder1: 'The user name admin or not is test',
placeholder2: 'Password: 123456',
placeholder3: 'Please enter the verification code',
btnText: 'Sign in',
link: {
one1: 'Third party login',
one2: 'Links',
},
signInText: 'welcome back!',
copyright: {
one5: 'Copyright: Shenzhen XXX Software Technology Co., Ltd',
two6: 'Copyright: Shenzhen XXX software technology Guangdong ICP preparation no.05010000',
},
},
};
+18
View File
@@ -0,0 +1,18 @@
// 定义内容
export default {
login: {
placeholder1: '用户名 admin 或不输均为 test',
placeholder2: '密码:123456',
placeholder3: '请输入验证码',
btnText: '登 录',
link: {
one1: '第三方登录',
one2: '友情链接',
},
signInText: '欢迎回来!',
copyright: {
one5: '版权所有:深圳市xxx软件科技有限公司',
two6: 'Copyright: Shenzhen XXX Software Technology 粤ICP备05010000号',
},
},
};
+18
View File
@@ -0,0 +1,18 @@
// 定义内容
export default {
login: {
placeholder1: '用戶名admin或不輸均為test',
placeholder2: '密碼:123456',
placeholder3: '請輸入驗證碼',
btnText: '登 录',
link: {
one1: '協力廠商登入',
one2: '友情連結',
},
signInText: '歡迎回來!',
copyright: {
one5: '版權所有:深圳市xxx軟件科技有限公司',
two6: 'Copyright: Shenzhen XXX Software Technology 粵ICP備05010000號',
},
},
};
+106
View File
@@ -0,0 +1,106 @@
<template>
<el-aside class="layout-aside" :class="setCollapseWidth" v-if="clientWidth > 1000">
<Logo v-if="setShowLogo" />
<el-scrollbar class="flex-auto" ref="layoutAsideRef">
<Vertical :menuList="menuList" :class="setCollapseWidth" />
</el-scrollbar>
</el-aside>
<el-drawer :visible.sync="getThemeConfig.isCollapse" :with-header="false" direction="ltr" size="220px" v-else>
<el-aside class="layout-aside w100 h100">
<Logo v-if="setShowLogo" />
<el-scrollbar class="flex-auto" ref="layoutAsideRef">
<Vertical :menuList="menuList" />
</el-scrollbar>
</el-aside>
</el-drawer>
</template>
<script>
import Vertical from '@/layout/navMenu/vertical.vue';
import Logo from '@/layout/logo/index.vue';
export default {
name: 'layoutAside',
components: { Vertical, Logo },
data() {
return {
menuList: [],
clientWidth: '',
};
},
computed: {
// 设置左侧菜单的具体宽度
setCollapseWidth() {
let { layout, isCollapse } = this.$store.state.themeConfig.themeConfig;
let asideBrColor = '';
layout === 'classic' || layout === 'columns' ? (asideBrColor = 'layout-el-aside-br-color') : '';
if (layout === 'columns') {
// 分栏布局,菜单收起时宽度给 1px
if (isCollapse) {
return ['layout-aside-width1', asideBrColor];
} else {
return ['layout-aside-width-default', asideBrColor];
}
} else {
// 其它布局给 64px
if (isCollapse) {
return ['layout-aside-width64', asideBrColor];
} else {
return ['layout-aside-width-default', asideBrColor];
}
}
},
// 设置 logo 是否显示
setShowLogo() {
let { layout, isShowLogo } = this.$store.state.themeConfig.themeConfig;
return (isShowLogo && layout === 'defaults') || (isShowLogo && layout === 'columns');
},
// 获取布局配置信息
getThemeConfig() {
return this.$store.state.themeConfig.themeConfig;
},
},
created() {
this.initMenuFixed(document.body.clientWidth);
this.setFilterRoutes();
this.bus.$on('setSendColumnsChildren', (res) => {
this.menuList = res.children;
});
this.bus.$on('layoutMobileResize', (res) => {
this.initMenuFixed(res.clientWidth);
});
// 菜单滚动条监听
this.bus.$on('updateElScrollBar', () => {
setTimeout(() => {
this.$refs.layoutAsideRef.update();
}, 300);
});
},
methods: {
// 设置/过滤路由(非静态路由/是否显示在菜单中)
setFilterRoutes() {
if (this.$store.state.themeConfig.themeConfig.layout === 'columns') return false;
this.menuList = this.filterRoutesFun(this.$store.state.routesList.routesList);
},
// 设置/过滤路由 递归函数
filterRoutesFun(arr) {
return arr
.filter((item) => !item.meta.isHide)
.map((item) => {
item = Object.assign({}, item);
if (item.children) item.children = this.filterRoutesFun(item.children);
return item;
});
},
// 设置菜单导航是否固定(移动端)
initMenuFixed(clientWidth) {
this.clientWidth = clientWidth;
},
},
// 页面销毁时
destroyed() {
// 取消菜单滚动条监听
this.bus.$off('updateElScrollBar', () => {});
},
};
</script>
+233
View File
@@ -0,0 +1,233 @@
<template>
<div class="layout-columns-aside">
<el-scrollbar>
<ul>
<li
v-for="(v, k) in columnsAsideList"
:key="k"
@click="onColumnsAsideMenuClick(v)"
ref="columnsAsideOffsetTopRefs"
:class="{ 'layout-columns-active': liIndex === k }"
:title="$t(v.meta.title)"
>
<div :class="setColumnsAsidelayout" v-if="!v.meta.isLink || (v.meta.isLink && v.meta.isIframe)">
<i :class="v.meta.icon"></i>
<div class="font12">
{{
$t(v.meta.title) && $t(v.meta.title).length >= 4
? $t(v.meta.title).substr(0, setColumnsAsidelayout === 'columns-vertical' ? 4 : 3)
: $t(v.meta.title)
}}
</div>
</div>
<div :class="setColumnsAsidelayout" v-else>
<a :href="v.meta.isLink" target="_blank">
<i :class="v.meta.icon"></i>
<div class="font12">
{{
$t(v.meta.title) && $t(v.meta.title).length >= 4
? $t(v.meta.title).substr(0, setColumnsAsidelayout === 'columns-vertical' ? 4 : 3)
: $t(v.meta.title)
}}
</div>
</a>
</div>
</li>
<div ref="columnsAsideActiveRef" :class="setColumnsAsideStyle"></div>
</ul>
</el-scrollbar>
</div>
</template>
<script>
export default {
name: 'layoutColumnsAside',
data() {
return {
columnsAsideList: [],
liIndex: 0,
difference: 0,
routeSplit: [],
};
},
computed: {
// 设置分栏高亮风格
setColumnsAsideStyle() {
return this.$store.state.themeConfig.themeConfig.columnsAsideStyle;
},
// 设置分栏布局风格
setColumnsAsidelayout() {
return this.$store.state.themeConfig.themeConfig.columnsAsideLayout;
},
},
mounted() {
this.setFilterRoutes();
},
methods: {
// 设置菜单高亮位置移动
setColumnsAsideMove(k) {
if (k === undefined) return false;
const els = this.$refs.columnsAsideOffsetTopRefs;
this.liIndex = k;
this.$refs.columnsAsideActiveRef.style.top = `${els[k].offsetTop + this.difference}px`;
},
// 菜单高亮点击事件
onColumnsAsideMenuClick(v) {
let { path, redirect } = v;
if (redirect) this.$router.push(redirect);
else this.$router.push(path);
// 一个路由设置自动收起菜单
// https://gitee.com/lyt-top/vue-next-admin/issues/I6HW7H
if (!v.children || v.children.length <= 1) this.$store.state.themeConfig.themeConfig.isCollapse = true;
else if (v.children.length > 1) this.$store.state.themeConfig.themeConfig.isCollapse = false;
},
// 设置高亮动态位置
onColumnsAsideDown(k) {
this.$nextTick(() => {
this.setColumnsAsideMove(k);
});
},
// 设置/过滤路由(非静态路由/是否显示在菜单中)
setFilterRoutes() {
if (this.$store.state.routesList.routesList.length <= 0) return false;
this.columnsAsideList = this.filterRoutesFun(this.$store.state.routesList.routesList);
const resData = this.setSendChildren(this.$route.path);
if (Object.keys(resData).length <= 0) return false;
this.onColumnsAsideDown(resData.item[0].k);
// 刷新时,初始化一个路由设置自动收起菜单
// https://gitee.com/lyt-top/vue-next-admin/issues/I6HW7H
resData.children.length <= 1
? (this.$store.state.themeConfig.themeConfig.isCollapse = true)
: (this.$store.state.themeConfig.themeConfig.isCollapse = false);
this.bus.$emit('setSendColumnsChildren', resData);
},
// 传送当前子级数据到菜单中
setSendChildren(path) {
const currentPathSplit = path.split('/');
let currentData = {};
this.columnsAsideList.map((v, k) => {
if (v.path === `/${currentPathSplit[1]}`) {
v['k'] = k;
currentData['item'] = [{ ...v }];
currentData['children'] = [{ ...v }];
if (v.children) currentData['children'] = v.children;
}
});
return currentData;
},
// 路由过滤递归函数
filterRoutesFun(arr) {
return arr
.filter((item) => !item.meta.isHide)
.map((item) => {
item = Object.assign({}, item);
if (item.children) item.children = this.filterRoutesFun(item.children);
return item;
});
},
// tagsView 点击时,根据路由查找下标 columnsAsideList,实现左侧菜单高亮
setColumnsMenuHighlight(path) {
this.routeSplit = path.split('/');
this.routeSplit.shift();
const routeFirst = `/${this.routeSplit[0]}`;
const currentSplitRoute = this.columnsAsideList.find((v) => v.path === routeFirst);
if (!currentSplitRoute) return false;
// 延迟拿值,防止取不到
setTimeout(() => {
this.onColumnsAsideDown(currentSplitRoute.k);
}, 0);
},
},
watch: {
// 监听 vuex 数据变化
'$store.state': {
handler(val) {
val.themeConfig.themeConfig.columnsAsideStyle === 'columnsRound' ? (this.difference = 3) : (this.difference = 0);
if (val.routesList.routesList.length === this.columnsAsideList.length) return false;
this.setFilterRoutes();
},
deep: true,
},
// 监听路由的变化
$route: {
handler(to) {
this.setColumnsMenuHighlight(to.path);
this.bus.$emit('setSendColumnsChildren', this.setSendChildren(to.path));
},
deep: true,
},
},
};
</script>
<style scoped lang="scss">
.layout-columns-aside {
width: 70px;
height: 100%;
background: var(--prev-bg-columnsMenuBar);
ul {
position: relative;
li {
color: var(--prev-bg-columnsMenuBarColor);
width: 100%;
height: 50px;
text-align: center;
display: flex;
cursor: pointer;
position: relative;
z-index: 1;
.columns-vertical {
margin: auto;
.columns-vertical-title {
padding-top: 1px;
}
}
.columns-horizontal {
display: flex;
height: 50px;
width: 100%;
align-items: center;
padding: 0 5px;
i {
margin-right: 3px;
}
a {
display: flex;
.columns-horizontal-title {
padding-top: 1px;
}
}
}
a {
text-decoration: none;
color: var(--prev-bg-columnsMenuBarColor);
}
}
.layout-columns-active,
.layout-columns-active a {
color: var(--prev-color-text-white);
transition: 0.3s ease-in-out;
}
.columns-round {
background: var(--prev-color-primary);
color: var(--prev-color-text-white);
position: absolute;
left: 50%;
top: 2px;
height: 50px;
width: 65px;
transform: translateX(-50%);
z-index: 0;
transition: 0.3s ease-in-out;
border-radius: 5px;
}
.columns-card {
@extend .columns-round;
top: 0;
height: 50px;
width: 100%;
border-radius: 0;
}
}
}
</style>
+24
View File
@@ -0,0 +1,24 @@
<template>
<el-header class="layout-header" :height="setHeaderHeight">
<NavBarsIndex />
</el-header>
</template>
<script>
import NavBarsIndex from '@/layout/navBars/index.vue';
export default {
name: 'layoutHeader',
components: { NavBarsIndex },
data() {
return {};
},
computed: {
// 设置顶部 header 的具体高度
setHeaderHeight() {
let { isTagsview, layout } = this.$store.state.themeConfig.themeConfig;
if (isTagsview && layout !== 'classic') return '84px';
else return '50px';
},
},
};
</script>
+93
View File
@@ -0,0 +1,93 @@
<template>
<el-main class="layout-main">
<el-scrollbar
class="layout-scrollbar"
ref="layoutScrollbarRef"
v-show="!currentRouteMeta.isLink && !currentRouteMeta.isIframe"
:style="{ minHeight: `calc(100vh - ${headerHeight}` }"
>
<LayoutParentView />
<Footers v-if="getThemeConfig.isFooter" />
</el-scrollbar>
<Links
:style="{ height: `calc(100vh - ${headerHeight}` }"
:meta="currentRouteMeta"
v-if="currentRouteMeta.isLink && !currentRouteMeta.isIframe"
/>
<Iframes
:style="{ height: `calc(100vh - ${headerHeight}` }"
:meta="currentRouteMeta"
v-if="currentRouteMeta.isLink && currentRouteMeta.isIframe && isShowLink"
@getCurrentRouteMeta="onGetCurrentRouteMeta"
/>
</el-main>
</template>
<script>
import LayoutParentView from '@/layout/routerView/parent.vue';
import Footers from '@/layout/footer/index.vue';
import Links from '@/layout/routerView/link.vue';
import Iframes from '@/layout/routerView/iframes.vue';
export default {
name: 'layoutMain',
components: { LayoutParentView, Footers, Links, Iframes },
data() {
return {
headerHeight: '',
currentRouteMeta: {},
isShowLink: false,
};
},
computed: {
// 获取布局配置信息
getThemeConfig() {
return this.$store.state.themeConfig.themeConfig;
},
},
mounted() {
this.initHeaderHeight();
this.initCurrentRouteMeta(this.$route.meta);
},
methods: {
// 初始化当前路由 meta 信息
initCurrentRouteMeta(meta) {
this.isShowLink = false;
this.currentRouteMeta = meta;
setTimeout(() => {
this.isShowLink = true;
}, 100);
},
// 设置 main 的高度
initHeaderHeight() {
let { isTagsview } = this.$store.state.themeConfig.themeConfig;
if (isTagsview) return (this.headerHeight = `84px`);
else return (this.headerHeight = `50px`);
},
// 子组件触发更新
onGetCurrentRouteMeta() {
this.initCurrentRouteMeta(this.$route.meta);
},
},
watch: {
// 监听 vuex 数据变化
'$store.state.themeConfig.themeConfig': {
handler(val) {
this.headerHeight = val.isTagsview ? '84px' : '50px';
if (val.isFixedHeaderChange !== val.isFixedHeader) {
if (!this.$refs.layoutScrollbarRef) return false;
this.$refs.layoutScrollbarRef.update();
}
},
deep: true,
},
// 监听路由的变化
$route: {
handler(to) {
this.initCurrentRouteMeta(to.meta);
this.$refs.layoutScrollbarRef.wrap.scrollTop = 0;
},
deep: true,
},
},
};
</script>
+29
View File
@@ -0,0 +1,29 @@
<template>
<div class="layout-footer mt15">
<div class="layout-footer-warp">
<div>智慧校园❤️</div>
<div class="mt5">版权所有:数字校园教育管理平台</div>
</div>
</div>
</template>
<script>
export default {
name: "layoutFooter",
data() {
return {};
},
};
</script>
<style scoped lang="scss">
.layout-footer {
width: 100%;
display: flex;
&-warp {
margin: auto;
color: var(--prev-color-text-secondary);
text-align: center;
}
}
</style>
+51
View File
@@ -0,0 +1,51 @@
<template>
<Defaults v-if="getThemeConfig.layout === 'defaults'" />
<Classic v-else-if="getThemeConfig.layout === 'classic'" />
<Transverse v-else-if="getThemeConfig.layout === 'transverse'" />
<Columns v-else-if="getThemeConfig.layout === 'columns'" />
</template>
<script>
import { Local } from '@/utils/storage.js';
export default {
name: 'layout',
components: {
Defaults: () => import('@/layout/main/defaults.vue'),
Classic: () => import('@/layout/main/classic.vue'),
Transverse: () => import('@/layout/main/transverse.vue'),
Columns: () => import('@/layout/main/columns.vue'),
},
computed: {
// 获取布局配置信息
getThemeConfig() {
return this.$store.state.themeConfig.themeConfig;
},
},
created() {
this.onLayoutResize();
window.addEventListener('resize', this.onLayoutResize);
},
methods: {
// 窗口大小改变时(适配移动端)
onLayoutResize() {
if (!Local.get('oldLayout')) Local.set('oldLayout', this.$store.state.themeConfig.themeConfig.layout);
const clientWidth = document.body.clientWidth;
if (clientWidth < 1000) {
this.$store.state.themeConfig.themeConfig.isCollapse = false;
this.bus.$emit('layoutMobileResize', {
layout: 'defaults',
clientWidth,
});
} else {
this.bus.$emit('layoutMobileResize', {
layout: Local.get('oldLayout') ? Local.get('oldLayout') : this.$store.state.themeConfig.themeConfig.layout,
clientWidth,
});
}
},
},
distroyed() {
window.removeEventListener('resize', this.onLayoutResize);
},
};
</script>
+78
View File
@@ -0,0 +1,78 @@
<template>
<div class="layout-logo" v-if="setShowLogo" @click="onThemeConfigChange">
<!-- <img :src="logo" class="layout-logo-medium-img" /> -->
<!-- <span>{{ getThemeConfig.globalTitle }}</span> -->
<span>数字校园教育管理平台</span>
</div>
<div class="layout-logo-size" v-else @click="onThemeConfigChange">
<img :src="logo" class="layout-logo-size-img" />
</div>
</template>
<script>
export default {
name: "layoutLogo",
data() {
return {
logo: require("@/assets/logo.png"),
};
},
computed: {
// 获取布局配置信息
getThemeConfig() {
console.log(this.$store.state.themeConfig);
return this.$store.state.themeConfig.themeConfig;
},
// 设置 logo 是否显示
setShowLogo() {
let { isCollapse, layout } = this.$store.state.themeConfig.themeConfig;
return !isCollapse || layout === "classic" || document.body.clientWidth < 1000;
},
},
methods: {
// logo 点击实现菜单展开/收起
onThemeConfigChange() {
if (this.$store.state.themeConfig.themeConfig.layout === "transverse") return false;
this.$store.state.themeConfig.themeConfig.isCollapse = !this.$store.state
.themeConfig.themeConfig.isCollapse;
},
},
};
</script>
<style scoped lang="scss">
.layout-logo {
width: 220px;
height: 50px;
display: flex;
align-items: center;
justify-content: center;
box-shadow: rgb(0 21 41 / 2%) 0px 1px 4px;
color: var(--prev-color-primary);
font-size: 16px;
cursor: pointer;
animation: logoAnimation 0.3s ease-in-out;
&:hover {
span {
opacity: 0.9;
}
}
&-medium-img {
width: 20px;
margin-right: 5px;
position: relative;
top: 2px;
}
}
.layout-logo-size {
width: 100%;
height: 50px;
display: flex;
cursor: pointer;
&-img {
width: 20px;
margin: auto;
animation: logoAnimation 0.3s ease-in-out;
}
}
</style>
+30
View File
@@ -0,0 +1,30 @@
<template>
<el-container class="layout-container flex-center">
<Headers />
<el-container class="layout-mian-height-50">
<Asides />
<div class="flex-center layout-backtop">
<TagsView v-if="getThemeConfig.isTagsview" />
<Mains />
</div>
</el-container>
<el-backtop target=".layout-backtop .el-main .el-scrollbar__wrap"></el-backtop>
</el-container>
</template>
<script>
import Asides from '@/layout/component/aside.vue';
import Headers from '@/layout/component/header.vue';
import Mains from '@/layout/component/main.vue';
import TagsView from '@/layout/navBars/tagsView/tagsView.vue';
export default {
name: 'layoutClassic',
components: { Asides, Headers, Mains, TagsView },
computed: {
// 获取布局配置信息
getThemeConfig() {
return this.$store.state.themeConfig.themeConfig;
},
},
};
</script>
+33
View File
@@ -0,0 +1,33 @@
<template>
<el-container class="layout-container">
<ColumnsAside />
<div class="layout-columns-warp">
<Asides />
<el-container class="flex-center layout-backtop">
<Headers v-if="isFixedHeader" />
<el-scrollbar>
<Headers v-if="!isFixedHeader" />
<Mains />
</el-scrollbar>
</el-container>
</div>
<el-backtop target=".layout-backtop .el-scrollbar__wrap"></el-backtop>
</el-container>
</template>
<script>
import Asides from '@/layout/component/aside.vue';
import Headers from '@/layout/component/header.vue';
import Mains from '@/layout/component/main.vue';
import ColumnsAside from '@/layout/component/columnsAside.vue';
export default {
name: 'layoutColumns',
components: { Asides, Headers, Mains, ColumnsAside },
computed: {
// 是否开启固定 header
isFixedHeader() {
return this.$store.state.themeConfig.themeConfig.isFixedHeader;
},
},
};
</script>
+41
View File
@@ -0,0 +1,41 @@
<template>
<el-container class="layout-container">
<Asides />
<el-container class="flex-center layout-backtop">
<Headers v-if="isFixedHeader" />
<el-scrollbar ref="layoutDefaultsScrollbarRef">
<Headers v-if="!isFixedHeader" />
<Mains />
</el-scrollbar>
</el-container>
<el-backtop target=".layout-backtop .el-scrollbar__wrap"></el-backtop>
</el-container>
</template>
<script>
import Asides from '@/layout/component/aside.vue';
import Headers from '@/layout/component/header.vue';
import Mains from '@/layout/component/main.vue';
export default {
name: 'layoutDefaults',
components: { Asides, Headers, Mains },
data() {
return {};
},
computed: {
// 是否开启固定 header
isFixedHeader() {
return this.$store.state.themeConfig.themeConfig.isFixedHeader;
},
},
watch: {
// 监听路由的变化
$route: {
handler() {
this.$refs.layoutDefaultsScrollbarRef.wrap.scrollTop = 0;
},
deep: true,
},
},
};
</script>
+16
View File
@@ -0,0 +1,16 @@
<template>
<el-container class="layout-container flex-center layout-backtop">
<Headers />
<Mains />
<el-backtop target=".layout-backtop .el-main .el-scrollbar__wrap"></el-backtop>
</el-container>
</template>
<script>
import Headers from '@/layout/component/header.vue';
import Mains from '@/layout/component/main.vue';
export default {
name: 'layoutTransverse',
components: { Headers, Mains },
};
</script>
@@ -0,0 +1,139 @@
<template>
<div class="layout-navbars-breadcrumb" :style="{ display: isShowBreadcrumb }">
<i
class="layout-navbars-breadcrumb-icon"
:class="getThemeConfig.isCollapse ? 'el-icon-s-unfold' : 'el-icon-s-fold'"
@click="onThemeConfigChange"
></i>
<el-breadcrumb class="layout-navbars-breadcrumb-hide">
<transition-group name="breadcrumb" mode="out-in">
<el-breadcrumb-item v-for="(v, k) in breadcrumbList" :key="v.path">
<span v-if="k === breadcrumbList.length - 1" class="layout-navbars-breadcrumb-span">
<i :class="v.meta.icon" class="layout-navbars-breadcrumb-iconfont" v-if="getThemeConfig.isBreadcrumbIcon"></i>{{ $t(v.meta.title) }}
</span>
<a v-else @click.prevent="onBreadcrumbClick(v)">
<i :class="v.meta.icon" class="layout-navbars-breadcrumb-iconfont" v-if="getThemeConfig.isBreadcrumbIcon"></i>{{ $t(v.meta.title) }}
</a>
</el-breadcrumb-item>
</transition-group>
</el-breadcrumb>
</div>
</template>
<script>
import { Local } from '@/utils/storage.js';
export default {
name: 'layoutBreadcrumb',
data() {
return {
breadcrumbList: [],
routeSplit: [],
routeSplitFirst: '',
routeSplitIndex: 1,
};
},
computed: {
// 获取布局配置信息
getThemeConfig() {
return this.$store.state.themeConfig.themeConfig;
},
// 动态设置经典、横向布局不显示
isShowBreadcrumb() {
const { layout, isBreadcrumb } = this.$store.state.themeConfig.themeConfig;
if (layout === 'classic' || layout === 'transverse') {
return 'none';
} else {
return isBreadcrumb ? '' : 'none';
}
},
},
mounted() {
this.initRouteSplit(this.$route.path);
},
methods: {
// breadcrumb 当前项点击时
onBreadcrumbClick(v) {
const { redirect, path } = v;
if (redirect) this.$router.push(redirect);
else this.$router.push(path);
},
// breadcrumb icon 点击菜单展开与收起
onThemeConfigChange() {
this.$store.state.themeConfig.themeConfig.isCollapse = !this.$store.state.themeConfig.themeConfig.isCollapse;
this.setLocalThemeConfig();
},
// 存储布局配置
setLocalThemeConfig() {
Local.remove('themeConfigPrev');
Local.set('themeConfigPrev', this.$store.state.themeConfig.themeConfig);
},
// 递归设置 breadcrumb
getBreadcrumbList(arr) {
arr.map((item) => {
this.routeSplit.map((v, k, arrs) => {
if (this.routeSplitFirst === item.path) {
this.routeSplitFirst += `/${arrs[this.routeSplitIndex]}`;
this.breadcrumbList.push(item);
this.routeSplitIndex++;
if (item.children) this.getBreadcrumbList(item.children);
}
});
});
},
// 当前路由分割处理
initRouteSplit(path) {
this.breadcrumbList = [
{
path: '/',
meta: {
title: this.$store.state.routesList.routesList[0].meta.title,
icon: this.$store.state.routesList.routesList[0].meta.icon,
},
},
];
this.routeSplit = path.split('/');
this.routeSplit.shift();
this.routeSplitFirst = `/${this.routeSplit[0]}`;
this.routeSplitIndex = 1;
this.getBreadcrumbList(this.$store.state.routesList.routesList);
},
},
// 监听路由的变化
watch: {
$route: {
handler(newVal) {
this.initRouteSplit(newVal.path);
},
deep: true,
},
},
};
</script>
<style scoped lang="scss">
.layout-navbars-breadcrumb {
flex: 1;
height: inherit;
display: flex;
align-items: center;
padding-left: 15px;
.layout-navbars-breadcrumb-icon {
cursor: pointer;
font-size: 18px;
margin-right: 15px;
color: var(--prev-bg-topBarColor);
opacity: 0.8;
&:hover {
opacity: 1;
}
}
.layout-navbars-breadcrumb-span {
opacity: 0.7;
color: var(--prev-bg-topBarColor);
}
.layout-navbars-breadcrumb-iconfont {
font-size: 14px;
margin-right: 5px;
}
}
</style>
+77
View File
@@ -0,0 +1,77 @@
<template>
<div class="layout-navbars-breadcrumb-index">
<Logo v-if="setIsShowLogo" />
<Breadcrumb />
<Horizontal :menuList="menuList" v-if="isLayoutTransverse" />
<User />
</div>
</template>
<script>
import Breadcrumb from '@/layout/navBars/breadcrumb/breadcrumb.vue';
import User from '@/layout/navBars/breadcrumb/user.vue';
import Logo from '@/layout/logo/index.vue';
import Horizontal from '@/layout/navMenu/horizontal.vue';
export default {
name: 'layoutNavBars',
components: { Breadcrumb, User, Logo, Horizontal },
data() {
return {
menuList: [],
};
},
computed: {
// 设置 logo 是否显示
setIsShowLogo() {
let { isShowLogo, layout } = this.$store.state.themeConfig.themeConfig;
return (isShowLogo && layout === 'classic') || (isShowLogo && layout === 'transverse');
},
// 设置是否显示横向菜单
isLayoutTransverse() {
let { layout, isClassicSplitMenu } = this.$store.state.themeConfig.themeConfig;
return layout === 'transverse' || (isClassicSplitMenu && layout === 'classic');
},
},
mounted() {
this.setFilterRoutes();
},
methods: {
// 设置路由的过滤
setFilterRoutes() {
this.menuList = this.filterRoutesFun(this.$store.state.routesList.routesList);
},
// 设置路由的过滤递归函数
filterRoutesFun(arr) {
return arr
.filter((item) => !item.meta.isHide)
.map((item) => {
item = Object.assign({}, item);
if (item.children) item.children = this.filterRoutesFun(item.children);
return item;
});
},
},
watch: {
// 监听 vuex 数据变化
'$store.state': {
handler(val) {
if (val.routesList.routesList.length === this.menuList.length) return false;
this.setFilterRoutes();
},
deep: true,
},
},
};
</script>
<style scoped lang="scss">
.layout-navbars-breadcrumb-index {
height: 50px;
display: flex;
align-items: center;
padding-right: 15px;
overflow: hidden;
background: var(--prev-bg-topBar);
border-bottom: 1px solid var(--prev-border-color-lighter);
}
</style>
+100
View File
@@ -0,0 +1,100 @@
<template>
<div class="layout-search-dialog">
<el-dialog :visible.sync="isShowSearch" width="300px" destroy-on-close :modal="false" fullscreen :show-close="false">
<el-autocomplete
v-model="menuQuery"
:fetch-suggestions="menuSearch"
:placeholder="$t('message.user.searchPlaceholder')"
prefix-icon="el-icon-search"
ref="layoutMenuAutocompleteRef"
@select="onHandleSelect"
@blur="onSearchBlur"
>
<template slot-scope="{ item }">
<div><i :class="item.meta.icon" class="mr10"></i>{{ $t(item.meta.title) }}</div>
</template>
</el-autocomplete>
</el-dialog>
</div>
</template>
<script>
export default {
name: 'layoutBreadcrumbSearch',
data() {
return {
isShowSearch: false,
menuQuery: '',
tagsViewList: [],
};
},
methods: {
// 搜索弹窗打开
openSearch() {
this.menuQuery = '';
this.isShowSearch = true;
this.initTageView();
this.$nextTick(() => {
this.$refs.layoutMenuAutocompleteRef.focus();
});
},
// 搜索弹窗关闭
closeSearch() {
setTimeout(() => {
this.isShowSearch = false;
}, 150);
},
// 菜单搜索数据过滤
menuSearch(queryString, cb) {
let results = queryString ? this.tagsViewList.filter(this.createFilter(queryString)) : this.tagsViewList;
cb(results);
},
// 菜单搜索过滤
createFilter(queryString) {
return (restaurant) => {
return (
restaurant.path.toLowerCase().indexOf(queryString.toLowerCase()) > -1 ||
restaurant.meta.title.toLowerCase().indexOf(queryString.toLowerCase()) > -1 ||
this.$t(restaurant.meta.title).toLowerCase().indexOf(queryString.toLowerCase()) > -1
);
};
},
// 初始化菜单数据
initTageView() {
if (this.tagsViewList.length > 0) return false;
this.$store.state.tagsViewRoutes.tagsViewRoutes.map((v) => {
if (!v.meta.isHide) this.tagsViewList.push({ ...v });
});
},
// 当前菜单选中时
onHandleSelect(item) {
let { path, redirect } = item;
if (item.meta.isLink && !item.meta.isIframe) window.open(item.meta.isLink);
else if (redirect) this.$router.push(redirect);
else this.$router.push(path);
this.closeSearch();
},
// input 失去焦点时
onSearchBlur() {
this.closeSearch();
},
},
};
</script>
<style scoped lang="scss">
.layout-search-dialog {
::v-deep .el-dialog {
box-shadow: unset !important;
border-radius: 0 !important;
background: rgba(0, 0, 0, 0.5);
}
::v-deep .el-autocomplete {
width: 560px;
position: absolute;
top: 100px;
left: 50%;
transform: translateX(-50%);
}
}
</style>
+538
View File
@@ -0,0 +1,538 @@
<template>
<div class="layout-breadcrumb-seting">
<el-drawer
:title="$t('message.layout.configTitle')"
:visible.sync="getThemeConfig.isDrawer"
direction="rtl"
destroy-on-close
size="240px"
@close="onDrawerClose"
>
<el-scrollbar class="layout-breadcrumb-seting-bar">
<!-- 全局主题 -->
<el-divider content-position="left">{{ $t('message.layout.oneTitle') }}</el-divider>
<div class="layout-breadcrumb-seting-bar-flex">
<div class="layout-breadcrumb-seting-bar-flex-label">primary</div>
<div class="layout-breadcrumb-seting-bar-flex-value">
<el-color-picker v-model="getThemeConfig.primary" size="small" @change="onColorPickerChange"> </el-color-picker>
</div>
</div>
<div class="layout-breadcrumb-seting-bar-flex mt15">
<div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourIsDark') }}</div>
<div class="layout-breadcrumb-seting-bar-flex-value">
<el-switch v-model="getThemeConfig.isIsDark" :width="35" @change="onAddDarkChange"></el-switch>
</div>
</div>
<!-- 界面设置 -->
<el-divider content-position="left">{{ $t('message.layout.threeTitle') }}</el-divider>
<div class="layout-breadcrumb-seting-bar-flex">
<div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.threeIsCollapse') }}</div>
<div class="layout-breadcrumb-seting-bar-flex-value">
<el-switch v-model="getThemeConfig.isCollapse" :width="35" @change="setLocalThemeConfig"></el-switch>
</div>
</div>
<div class="layout-breadcrumb-seting-bar-flex mt15">
<div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.threeIsUniqueOpened') }}</div>
<div class="layout-breadcrumb-seting-bar-flex-value">
<el-switch v-model="getThemeConfig.isUniqueOpened" :width="35" @change="setLocalThemeConfig"></el-switch>
</div>
</div>
<div class="layout-breadcrumb-seting-bar-flex mt15">
<div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.threeIsFixedHeader') }}</div>
<div class="layout-breadcrumb-seting-bar-flex-value">
<el-switch v-model="getThemeConfig.isFixedHeader" :width="35" @change="setLocalThemeConfig"></el-switch>
</div>
</div>
<!-- 界面显示 -->
<el-divider content-position="left">{{ $t('message.layout.fourTitle') }}</el-divider>
<div class="layout-breadcrumb-seting-bar-flex">
<div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourIsShowLogo') }}</div>
<div class="layout-breadcrumb-seting-bar-flex-value">
<el-switch v-model="getThemeConfig.isShowLogo" :width="35" @change="setLocalThemeConfig"></el-switch>
</div>
</div>
<div
class="layout-breadcrumb-seting-bar-flex mt15"
:style="{ opacity: getThemeConfig.layout === 'classic' || getThemeConfig.layout === 'transverse' ? 0.5 : 1 }"
>
<div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourIsBreadcrumb') }}</div>
<div class="layout-breadcrumb-seting-bar-flex-value">
<el-switch
v-model="getThemeConfig.isBreadcrumb"
:disabled="getThemeConfig.layout === 'classic' || getThemeConfig.layout === 'transverse'"
:width="35"
@change="setLocalThemeConfig"
></el-switch>
</div>
</div>
<div class="layout-breadcrumb-seting-bar-flex mt15">
<div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourIsBreadcrumbIcon') }}</div>
<div class="layout-breadcrumb-seting-bar-flex-value">
<el-switch v-model="getThemeConfig.isBreadcrumbIcon" :width="35" @change="setLocalThemeConfig"></el-switch>
</div>
</div>
<div class="layout-breadcrumb-seting-bar-flex mt15">
<div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourIsTagsview') }}</div>
<div class="layout-breadcrumb-seting-bar-flex-value">
<el-switch v-model="getThemeConfig.isTagsview" :width="35" @change="setLocalThemeConfig"></el-switch>
</div>
</div>
<div class="layout-breadcrumb-seting-bar-flex mt15">
<div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourIsTagsviewIcon') }}</div>
<div class="layout-breadcrumb-seting-bar-flex-value">
<el-switch v-model="getThemeConfig.isTagsviewIcon" :width="35" @change="setLocalThemeConfig"></el-switch>
</div>
</div>
<div class="layout-breadcrumb-seting-bar-flex mt15">
<div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourIsCacheTagsView') }}</div>
<div class="layout-breadcrumb-seting-bar-flex-value">
<el-switch v-model="getThemeConfig.isCacheTagsView" :width="35" @change="setLocalThemeConfig"></el-switch>
</div>
</div>
<div class="layout-breadcrumb-seting-bar-flex mt15">
<div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourIsFooter') }}</div>
<div class="layout-breadcrumb-seting-bar-flex-value">
<el-switch v-model="getThemeConfig.isFooter" :width="35" @change="setLocalThemeConfig"></el-switch>
</div>
</div>
<div class="layout-breadcrumb-seting-bar-flex mt15">
<div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourIsGrayscale') }}</div>
<div class="layout-breadcrumb-seting-bar-flex-value">
<el-switch v-model="getThemeConfig.isGrayscale" :width="35" @change="onAddFilterChange('grayscale')"></el-switch>
</div>
</div>
<div class="layout-breadcrumb-seting-bar-flex mt15">
<div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fourIsInvert') }}</div>
<div class="layout-breadcrumb-seting-bar-flex-value">
<el-switch v-model="getThemeConfig.isInvert" :width="35" @change="onAddFilterChange('invert')"></el-switch>
</div>
</div>
<!-- 其它设置 -->
<el-divider content-position="left">{{ $t('message.layout.fiveTitle') }}</el-divider>
<div class="layout-breadcrumb-seting-bar-flex mt15">
<div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fiveTagsStyle') }}</div>
<div class="layout-breadcrumb-seting-bar-flex-value">
<el-select v-model="getThemeConfig.tagsStyle" placeholder="请选择" size="mini" style="width: 90px" @change="setLocalThemeConfig">
<el-option label="风格1" value="tags-style-one"></el-option>
</el-select>
</div>
</div>
<div class="layout-breadcrumb-seting-bar-flex mt15">
<div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fiveAnimation') }}</div>
<div class="layout-breadcrumb-seting-bar-flex-value">
<el-select v-model="getThemeConfig.animation" placeholder="请选择" size="mini" style="width: 90px" @change="setLocalThemeConfig">
<el-option label="slide-right" value="slide-right"></el-option>
<el-option label="slide-left" value="slide-left"></el-option>
<el-option label="opacitys" value="opacitys"></el-option>
</el-select>
</div>
</div>
<div class="layout-breadcrumb-seting-bar-flex mt15">
<div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fiveColumnsAsideStyle') }}</div>
<div class="layout-breadcrumb-seting-bar-flex-value">
<el-select v-model="getThemeConfig.columnsAsideStyle" placeholder="请选择" size="mini" style="width: 90px" @change="setLocalThemeConfig">
<el-option label="圆角" value="columns-round"></el-option>
<el-option label="卡片" value="columns-card"></el-option>
</el-select>
</div>
</div>
<div class="layout-breadcrumb-seting-bar-flex mt15 mb28">
<div class="layout-breadcrumb-seting-bar-flex-label">{{ $t('message.layout.fiveColumnsAsideLayout') }}</div>
<div class="layout-breadcrumb-seting-bar-flex-value">
<el-select v-model="getThemeConfig.columnsAsideLayout" placeholder="请选择" size="mini" style="width: 90px" @change="setLocalThemeConfig">
<el-option label="水平" value="columns-horizontal"></el-option>
<el-option label="垂直" value="columns-vertical"></el-option>
</el-select>
</div>
</div>
<!-- 布局切换 -->
<el-divider content-position="left">{{ $t('message.layout.sixTitle') }}</el-divider>
<div class="layout-drawer-content-flex">
<!-- defaults 布局 -->
<div class="layout-drawer-content-item" @click="onSetLayout('defaults')">
<section class="el-container el-circular" :class="{ 'drawer-layout-active': getThemeConfig.layout === 'defaults' }">
<aside class="el-aside" style="width: 20px"></aside>
<section class="el-container is-vertical">
<header class="el-header" style="height: 10px"></header>
<main class="el-main"></main>
</section>
</section>
<div class="layout-tips-warp" :class="{ 'layout-tips-warp-active': getThemeConfig.layout === 'defaults' }">
<div class="layout-tips-box">
<p class="layout-tips-txt">{{ $t('message.layout.sixDefaults') }}</p>
</div>
</div>
</div>
<!-- classic 布局 -->
<div class="layout-drawer-content-item" @click="onSetLayout('classic')">
<section class="el-container is-vertical el-circular" :class="{ 'drawer-layout-active': getThemeConfig.layout === 'classic' }">
<header class="el-header" style="height: 10px"></header>
<section class="el-container">
<aside class="el-aside" style="width: 20px"></aside>
<section class="el-container is-vertical">
<main class="el-main"></main>
</section>
</section>
</section>
<div class="layout-tips-warp" :class="{ 'layout-tips-warp-active': getThemeConfig.layout === 'classic' }">
<div class="layout-tips-box">
<p class="layout-tips-txt">{{ $t('message.layout.sixClassic') }}</p>
</div>
</div>
</div>
<!-- transverse 布局 -->
<div class="layout-drawer-content-item" @click="onSetLayout('transverse')">
<section class="el-container is-vertical el-circular" :class="{ 'drawer-layout-active': getThemeConfig.layout === 'transverse' }">
<header class="el-header" style="height: 10px"></header>
<section class="el-container">
<section class="el-container is-vertical">
<main class="el-main"></main>
</section>
</section>
</section>
<div class="layout-tips-warp" :class="{ 'layout-tips-warp-active': getThemeConfig.layout === 'transverse' }">
<div class="layout-tips-box">
<p class="layout-tips-txt">{{ $t('message.layout.sixTransverse') }}</p>
</div>
</div>
</div>
<!-- columns 布局 -->
<div class="layout-drawer-content-item" @click="onSetLayout('columns')">
<section class="el-container el-circular" :class="{ 'drawer-layout-active': getThemeConfig.layout === 'columns' }">
<aside class="el-aside-dark" style="width: 10px"></aside>
<aside class="el-aside" style="width: 20px"></aside>
<section class="el-container is-vertical">
<header class="el-header" style="height: 10px"></header>
<main class="el-main"></main>
</section>
</section>
<div class="layout-tips-warp" :class="{ 'layout-tips-warp-active': getThemeConfig.layout === 'columns' }">
<div class="layout-tips-box">
<p class="layout-tips-txt">{{ $t('message.layout.sixColumns') }}</p>
</div>
</div>
</div>
</div>
<div class="copy-config">
<el-alert :title="$t('message.layout.tipText')" type="warning" :closable="false"> </el-alert>
<el-button
size="small"
class="copy-config-btn"
icon="el-icon-document-copy"
type="primary"
ref="copyConfigBtnRef"
@click="onCopyConfigClick"
>{{ $t('message.layout.copyText') }}
</el-button>
<el-button size="small" class="copy-config-btn-reset" type="info" icon="el-icon-refresh-right" @click="onResetConfigClick">
{{ $t('message.layout.resetText') }}
</el-button>
</div>
</el-scrollbar>
</el-drawer>
</div>
</template>
<script>
import ClipboardJS from 'clipboard';
import { Local } from '@/utils/storage.js';
import { useChangeColor } from '@/utils/theme.js';
import config from '/package.json';
export default {
name: 'layoutBreadcrumbSeting',
computed: {
// 获取布局配置信息
getThemeConfig() {
return this.$store.state.themeConfig.themeConfig;
},
},
created() {
// 判断当前布局是否不相同,不相同则初始化当前布局的样式,防止监听窗口大小改变时,布局配置logo、菜单背景等部分布局失效问题
if (!Local.get('frequency')) this.initSetLayoutChange();
Local.set('frequency', 1);
// 监听窗口大小改变,非默认布局,设置成默认布局(适配移动端)
this.bus.$on('layoutMobileResize', (res) => {
if (this.$store.state.themeConfig.themeConfig.layout === res.layout) return false;
this.$store.state.themeConfig.themeConfig.layout = res.layout;
this.$store.state.themeConfig.themeConfig.isDrawer = false;
this.$store.state.themeConfig.themeConfig.isCollapse = false;
this.initSetLayoutChange();
});
},
mounted() {
this.initLayoutConfig();
},
methods: {
// 全局主题
onColorPickerChange() {
if (!this.getThemeConfig.primary) return;
// 颜色加深
document.documentElement.style.setProperty('--prev-color-primary', this.getThemeConfig.primary);
// 颜色变浅
for (let i = 1; i <= 9; i++) {
document.documentElement.style.setProperty(
`--prev-color-primary-light-${i}`,
`${useChangeColor().getLightColor(this.getThemeConfig.primary, i / 10)}`
);
}
this.setLocalThemeConfig();
},
// 深色模式
onAddDarkChange() {
const body = document.documentElement;
if (this.getThemeConfig.isIsDark) body.setAttribute('data-theme', 'dark');
else body.setAttribute('data-theme', '');
this.setLocalThemeConfig();
},
// 初始化:刷新页面时,设置了值,直接取缓存中的值进行初始化
initLayoutConfig() {
window.addEventListener('load', () => {
// 默认样式
this.onColorPickerChange();
// 灰色模式
if (this.$store.state.themeConfig.themeConfig.isGrayscale) this.onAddFilterChange('grayscale');
// 色弱模式
if (this.$store.state.themeConfig.themeConfig.isInvert) this.onAddFilterChange('invert');
// 深色模式
if (this.$store.state.themeConfig.themeConfig.isIsDark) this.onAddDarkChange();
// 语言国际化
if (Local.get('themeConfigPrev')) this.$i18n.locale = Local.get('themeConfigPrev').globalI18n;
});
},
// 存储布局配置
setLocalThemeConfig() {
Local.remove('themeConfigPrev');
Local.set('themeConfigPrev', this.$store.state.themeConfig.themeConfig);
this.setLocalThemeConfigStyle();
},
// 存储布局配置全局主题样式(html根标签)
setLocalThemeConfigStyle() {
Local.set('themeConfigStyle', document.documentElement.style.cssText);
},
// 布局配置弹窗打开
openDrawer() {
this.$store.state.themeConfig.themeConfig.isDrawer = true;
},
// 关闭弹窗时,初始化变量
onDrawerClose() {
this.$store.state.themeConfig.themeConfig.isDrawer = false;
this.setLocalThemeConfig();
},
// 灰色模式/色弱模式
onAddFilterChange(attr) {
if (attr === 'grayscale') {
if (this.$store.state.themeConfig.themeConfig.isGrayscale) this.$store.state.themeConfig.themeConfig.isInvert = false;
} else {
if (this.$store.state.themeConfig.themeConfig.isInvert) this.$store.state.themeConfig.themeConfig.isGrayscale = false;
}
const cssAttr =
attr === 'grayscale'
? `grayscale(${this.$store.state.themeConfig.themeConfig.isGrayscale ? 1 : 0})`
: `invert(${this.$store.state.themeConfig.themeConfig.isInvert ? '80%' : '0%'})`;
const appEle = document.body;
appEle.setAttribute('style', `filter: ${cssAttr};`);
this.setLocalThemeConfig();
},
// 布局切换
onSetLayout(layout) {
Local.set('oldLayout', layout);
if (this.$store.state.themeConfig.themeConfig.layout === layout) return false;
this.$store.state.themeConfig.themeConfig.layout = layout;
this.$store.state.themeConfig.themeConfig.isDrawer = false;
this.initSetLayoutChange();
},
// 设置布局切换,重置主题样式
initSetLayoutChange() {
if (this.$store.state.themeConfig.themeConfig.layout === 'classic') {
this.onBgColorPickerChange('menuBar', '#ffffff');
this.onBgColorPickerChange('menuBarColor', '#606266');
this.onBgColorPickerChange('topBar', '#ffffff');
this.onBgColorPickerChange('topBarColor', '#606266');
} else if (this.$store.state.themeConfig.themeConfig.layout === 'transverse') {
this.onBgColorPickerChange('menuBarColor', '#ffffff');
this.onBgColorPickerChange('topBar', '#545c64');
this.onBgColorPickerChange('topBarColor', '#ffffff');
} else if (this.$store.state.themeConfig.themeConfig.layout === 'columns') {
this.onBgColorPickerChange('menuBar', '#ffffff');
this.onBgColorPickerChange('menuBarColor', '#606266');
this.onBgColorPickerChange('topBar', '#ffffff');
this.onBgColorPickerChange('topBarColor', '#606266');
} else {
this.onBgColorPickerChange('menuBar', '#545c64');
this.onBgColorPickerChange('menuBarColor', '#eaeaea');
this.onBgColorPickerChange('topBar', '#ffffff');
this.onBgColorPickerChange('topBarColor', '#606266');
}
},
// 菜单 / 顶栏背景等
onBgColorPickerChange(bg, rgb) {
document.documentElement.style.setProperty(`--prev-bg-${bg}`, rgb);
this.setLocalThemeConfigStyle();
},
// 一键复制配置
onCopyConfigClick() {
this.$store.state.themeConfig.themeConfig.isDrawer = false;
let clipboardJS = new ClipboardJS('.copy-config-btn', {
text: () => JSON.stringify(this.$store.state.themeConfig.themeConfig),
});
clipboardJS.on('success', () => {
this.$message.success('配置复制成功');
this.isDrawer = false;
clipboardJS.destroy();
});
clipboardJS.on('error', () => {
this.$message.error('配置复制失败');
});
},
// 一键恢复默认
onResetConfigClick() {
Local.clear();
window.location.reload();
Local.set('version', config.version);
},
},
};
</script>
<style scoped lang="scss">
.layout-breadcrumb-seting-bar {
height: calc(100vh - 50px);
padding: 0 15px;
::v-deep .el-scrollbar__view {
overflow-x: hidden !important;
}
.layout-breadcrumb-seting-bar-flex {
display: flex;
align-items: center;
&-label {
flex: 1;
color: var(--prev-color-text-primary);
}
}
.layout-drawer-content-flex {
overflow: hidden;
display: flex;
flex-wrap: wrap;
align-content: flex-start;
margin: 0 -5px;
.layout-drawer-content-item {
width: 50%;
height: 70px;
cursor: pointer;
border: 1px solid transparent;
position: relative;
padding: 5px;
.el-container {
height: 100%;
.el-aside-dark {
background-color: var(--prev-color-seting-header);
}
.el-aside {
background-color: var(--prev-color-seting-aside);
}
.el-header {
background-color: var(--prev-color-seting-header);
}
.el-main {
background-color: var(--prev-color-seting-main);
}
}
.el-circular {
border-radius: 2px;
overflow: hidden;
border: 1px solid transparent;
transition: all 0.3s ease-in-out;
}
.drawer-layout-active {
border: 1px solid;
border-color: var(--prev-color-primary);
}
.layout-tips-warp,
.layout-tips-warp-active {
transition: all 0.3s ease-in-out;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
border: 1px solid;
border-color: var(--prev-color-primary-light-5);
border-radius: 100%;
padding: 4px;
.layout-tips-box {
transition: inherit;
width: 30px;
height: 30px;
z-index: 9;
border: 1px solid;
border-color: var(--prev-color-primary-light-5);
border-radius: 100%;
.layout-tips-txt {
transition: inherit;
position: relative;
top: 5px;
font-size: 12px;
line-height: 1;
letter-spacing: 2px;
white-space: nowrap;
color: var(--prev-color-primary-light-5);
text-align: center;
transform: rotate(30deg);
left: -1px;
background-color: var(--prev-color-seting-main);
width: 32px;
height: 17px;
line-height: 17px;
}
}
}
.layout-tips-warp-active {
border: 1px solid;
border-color: var(--prev-color-primary);
.layout-tips-box {
border: 1px solid;
border-color: var(--prev-color-primary);
.layout-tips-txt {
color: var(--prev-color-primary) !important;
background-color: var(--prev-color-seting-main) !important;
}
}
}
&:hover {
.el-circular {
transition: all 0.3s ease-in-out;
border: 1px solid;
border-color: var(--prev-color-primary);
}
.layout-tips-warp {
transition: all 0.3s ease-in-out;
border-color: var(--prev-color-primary);
.layout-tips-box {
transition: inherit;
border-color: var(--prev-color-primary);
.layout-tips-txt {
transition: inherit;
color: var(--prev-color-primary) !important;
background-color: var(--prev-color-seting-main) !important;
}
}
}
}
}
}
.copy-config {
margin: 10px 0;
.copy-config-btn {
width: 100%;
margin-top: 15px;
}
.copy-config-btn-reset {
width: 100%;
margin: 10px 0 0;
}
}
}
</style>
+331
View File
@@ -0,0 +1,331 @@
<template>
<div class="layout-navbars-breadcrumb-user" :style="{ flex: layoutUserFlexNum }">
<el-dropdown
:show-timeout="70"
:hide-timeout="50"
trigger="click"
@command="onComponentSizeChange"
>
<div class="layout-navbars-breadcrumb-user-icon">
<i class="iconfont icon-ziti" :title="$t('message.user.title0')"></i>
</div>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item command="" :disabled="disabledSize === ''">{{
$t("message.user.dropdownDefault")
}}</el-dropdown-item>
<el-dropdown-item command="medium" :disabled="disabledSize === 'medium'">{{
$t("message.user.dropdownMedium")
}}</el-dropdown-item>
<el-dropdown-item command="small" :disabled="disabledSize === 'small'">{{
$t("message.user.dropdownSmall")
}}</el-dropdown-item>
<el-dropdown-item command="mini" :disabled="disabledSize === 'mini'">{{
$t("message.user.dropdownMini")
}}</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
<el-dropdown
:show-timeout="70"
:hide-timeout="50"
trigger="click"
@command="onLanguageChange"
>
<div class="layout-navbars-breadcrumb-user-icon">
<i
class="iconfont"
:class="disabledI18n === 'en' ? 'icon-fuhao-yingwen' : 'icon-fuhao-zhongwen'"
:title="$t('message.user.title1')"
></i>
</div>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="zh-cn" :disabled="disabledI18n === 'zh-cn'"
>简体中文</el-dropdown-item
>
<el-dropdown-item command="en" :disabled="disabledI18n === 'en'"
>English</el-dropdown-item
>
<el-dropdown-item command="zh-tw" :disabled="disabledI18n === 'zh-tw'"
>繁體中文</el-dropdown-item
>
</el-dropdown-menu>
</el-dropdown>
<div class="layout-navbars-breadcrumb-user-icon" @click="onSearchClick">
<i class="el-icon-search" :title="$t('message.user.title2')"></i>
</div>
<div class="layout-navbars-breadcrumb-user-icon" @click="onLayoutSetingClick">
<i class="icon-skin iconfont" :title="$t('message.user.title3')"></i>
</div>
<div class="layout-navbars-breadcrumb-user-icon">
<el-popover
placement="bottom"
trigger="click"
v-model="isShowUserNewsPopover"
:width="300"
popper-class="el-popover-pupop-user-news"
>
<el-badge
:is-dot="true"
@click.stop="isShowUserNewsPopover = !isShowUserNewsPopover"
slot="reference"
>
<i class="el-icon-bell" :title="$t('message.user.title4')"></i>
</el-badge>
<transition name="el-zoom-in-top">
<UserNews v-show="isShowUserNewsPopover" />
</transition>
</el-popover>
</div>
<div class="layout-navbars-breadcrumb-user-icon mr10" @click="onScreenfullClick">
<i
class="iconfont"
:title="isScreenfull ? $t('message.user.title6') : $t('message.user.title5')"
:class="!isScreenfull ? 'icon-fullscreen' : 'icon-tuichuquanping'"
></i>
</div>
<el-dropdown :show-timeout="70" :hide-timeout="50" @command="onDropdownCommand">
<span class="layout-navbars-breadcrumb-user-link">
<img
:src="UserInformation.avatar"
class="layout-navbars-breadcrumb-user-link-photo mr5"
/>
{{ UserInformation.name }}
<i class="el-icon-arrow-down el-icon--right"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="/home">{{
$t("message.user.dropdown1")
}}</el-dropdown-item>
<!-- <el-dropdown-item command="wareHouse">{{
$t("message.user.dropdown6")
}}</el-dropdown-item>
<el-dropdown-item command="/personal">{{
$t("message.user.dropdown2")
}}</el-dropdown-item>
<el-dropdown-item command="/404">{{
$t("message.user.dropdown3")
}}</el-dropdown-item>
<el-dropdown-item command="/401">{{
$t("message.user.dropdown4")
}}</el-dropdown-item> -->
<el-dropdown-item divided command="logOut">{{
$t("message.user.dropdown5")
}}</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<Search ref="searchRef" />
</div>
</template>
<script>
import screenfull from "screenfull";
import { Session, Local } from "@/utils/storage.js";
import UserNews from "@/layout/navBars/breadcrumb/userNews.vue";
import Search from "@/layout/navBars/breadcrumb/search.vue";
export default {
name: "layoutBreadcrumbUser",
components: { UserNews, Search },
data() {
return {
isScreenfull: false,
isShowUserNewsPopover: false,
disabledI18n: "zh-cn",
disabledSize: "",
UserInformation: {},
};
},
computed: {
// 获取用户信息
// getUserInfos() {
// return this.$store.state.userInfos.userInfosDD;
// },
// 设置弹性盒子布局 flex
layoutUserFlexNum() {
let { layout, isClassicSplitMenu } = this.$store.state.themeConfig.themeConfig;
let num = "";
if (
layout === "defaults" ||
(layout === "classic" && !isClassicSplitMenu) ||
layout === "columns"
)
num = 1;
else num = null;
return num;
},
},
mounted() {
this.resetUserInformation();
if (Local.get("themeConfigPrev")) {
this.initI18n();
this.initComponentSize();
}
},
methods: {
// 搜索点击
onSearchClick() {
this.$refs.searchRef.openSearch();
},
// 布局配置点击
onLayoutSetingClick() {
this.bus.$emit("openSetingsDrawer");
},
// 全屏点击
onScreenfullClick() {
if (!screenfull.isEnabled) {
this.$message.warning("暂不不支持全屏");
return false;
}
screenfull.toggle();
screenfull.on("change", () => {
if (screenfull.isFullscreen) this.isScreenfull = true;
else this.isScreenfull = false;
});
// 监听菜单 horizontal.vue 滚动条高度更新
this.bus.$emit("updateElScrollBar");
},
// 组件大小改变
onComponentSizeChange(size) {
Local.remove("themeConfigPrev");
this.$store.state.themeConfig.themeConfig.globalComponentSize = size;
Local.set("themeConfigPrev", this.$store.state.themeConfig.themeConfig);
this.$ELEMENT.size = size;
this.initComponentSize();
window.location.reload();
},
// 语言切换
onLanguageChange(lang) {
Local.remove("themeConfigPrev");
this.$store.state.themeConfig.themeConfig.globalI18n = lang;
Local.set("themeConfigPrev", this.$store.state.themeConfig.themeConfig);
this.$i18n.locale = lang;
this.initI18n();
},
// 初始化言语国际化
initI18n() {
switch (Local.get("themeConfigPrev").globalI18n) {
case "zh-cn":
this.disabledI18n = "zh-cn";
break;
case "en":
this.disabledI18n = "en";
break;
case "zh-tw":
this.disabledI18n = "zh-tw";
break;
}
},
// 初始化全局组件大小
initComponentSize() {
switch (Local.get("themeConfigPrev").globalComponentSize) {
case "":
this.disabledSize = "";
break;
case "medium":
this.disabledSize = "medium";
break;
case "small":
this.disabledSize = "small";
break;
case "mini":
this.disabledSize = "mini";
break;
}
},
// `dropdown 下拉菜单` 当前项点击
onDropdownCommand(path) {
if (path === "logOut") {
setTimeout(() => {
this.$msgbox({
closeOnClickModal: false,
closeOnPressEscape: false,
title: this.$t("message.user.logOutTitle"),
message: this.$t("message.user.logOutMessage"),
showCancelButton: true,
confirmButtonText: this.$t("message.user.logOutConfirm"),
cancelButtonText: this.$t("message.user.logOutCancel"),
beforeClose: (action, instance, done) => {
if (action === "confirm") {
instance.confirmButtonLoading = true;
instance.confirmButtonText = this.$t("message.user.logOutExit");
setTimeout(() => {
done();
setTimeout(() => {
instance.confirmButtonLoading = false;
}, 300);
}, 700);
} else {
done();
}
},
})
.then(() => {
// 清除缓存/token等
Session.clear();
// 使用 reload 时,不需要调用 resetRoute() 重置路由
window.location.reload();
})
.catch(() => {});
}, 150);
} else if (path === "wareHouse") {
window.open("http://www.baidu.com");
} else {
this.$router.push(path);
}
},
// 重置DD用户信息
resetUserInformation() {
let res = Session.get("userInfoDD");
this.UserInformation = res;
},
},
};
</script>
<style scoped lang="scss">
.layout-navbars-breadcrumb-user {
display: flex;
align-items: center;
justify-content: flex-end;
&-link {
height: 100%;
display: flex;
align-items: center;
white-space: nowrap;
&-photo {
width: 25px;
height: 25px;
border-radius: 100%;
}
}
&-icon {
padding: 0 10px;
cursor: pointer;
color: var(--prev-bg-topBarColor);
height: 50px;
line-height: 50px;
display: flex;
align-items: center;
&:hover {
background: var(--prev-color-hover);
i {
display: inline-block;
animation: logoAnimation 0.3s ease-in-out;
}
}
}
& ::v-deep .el-dropdown {
color: var(--prev-bg-topBarColor);
}
& ::v-deep .el-badge {
height: 40px;
line-height: 40px;
display: flex;
align-items: center;
}
& ::v-deep .el-badge__content.is-fixed {
top: 12px;
}
}
</style>
+130
View File
@@ -0,0 +1,130 @@
<template>
<div class="layout-navbars-breadcrumb-user-news">
<div class="head-box">
<div class="head-box-title">{{ $t("message.user.newTitle") }}</div>
<div class="head-box-btn" v-if="newsList.length > 0" @click="onAllReadClick">
{{ $t("message.user.newBtn") }}
</div>
</div>
<div class="content-box">
<template v-if="newsList.length > 0">
<div class="content-box-item" v-for="(v, k) in newsList" :key="k">
<div>{{ v.label }}</div>
<div class="content-box-msg">
{{ v.value }}
</div>
<div class="content-box-time">{{ v.time }}</div>
</div>
</template>
<div class="content-box-empty" v-else>
<div class="content-box-empty-margin">
<i class="el-icon-s-promotion"></i>
<div class="mt15">{{ $t("message.user.newDesc") }}</div>
</div>
</div>
</div>
<div class="foot-box" @click="onGoToGiteeClick" v-if="newsList.length > 0">
{{ $t("message.user.newGo") }}
</div>
</div>
</template>
<script>
export default {
name: "layoutBreadcrumbUserNews",
data() {
return {
newsList: [
{
label: "暂无",
value: "暂无",
time: "2023-8-15",
},
{
label: "暂无",
value: "暂无",
time: "2023-8-15",
},
],
};
},
methods: {
// 全部已读点击
onAllReadClick() {
this.newsList = [];
},
// 前往通知中心点击
onGoToGiteeClick() {
window.open("https://www.baidu.com/");
},
},
};
</script>
<style scoped lang="scss">
.layout-navbars-breadcrumb-user-news {
.head-box {
display: flex;
border-bottom: 1px solid var(--prev-border-color-lighter);
box-sizing: border-box;
color: var(--prev-color-text-primary);
justify-content: space-between;
height: 35px;
align-items: center;
.head-box-btn {
color: var(--prev-color-primary);
font-size: 13px;
cursor: pointer;
opacity: 0.8;
&:hover {
opacity: 1;
}
}
}
.content-box {
font-size: 13px;
.content-box-item {
padding-top: 12px;
&:last-of-type {
padding-bottom: 12px;
}
.content-box-msg {
color: var(--prev-color-text-secondary);
margin-top: 5px;
margin-bottom: 5px;
}
.content-box-time {
color: var(--prev-color-text-secondary);
}
}
.content-box-empty {
height: 260px;
display: flex;
.content-box-empty-margin {
margin: auto;
text-align: center;
i {
font-size: 60px;
}
}
}
}
.foot-box {
height: 35px;
color: var(--prev-color-primary);
font-size: 13px;
cursor: pointer;
opacity: 0.8;
display: flex;
align-items: center;
justify-content: center;
border-top: 1px solid var(--prev-border-color-lighter);
&:hover {
opacity: 1;
}
}
::v-deep(.el-empty__description p) {
font-size: 13px;
}
}
</style>
+34
View File
@@ -0,0 +1,34 @@
<template>
<div class="layout-navbars-container">
<BreadcrumbIndex />
<TagsView v-if="setShowTagsView" />
</div>
</template>
<script>
import BreadcrumbIndex from '@/layout/navBars/breadcrumb/index.vue';
import TagsView from '@/layout/navBars/tagsView/tagsView.vue';
export default {
name: 'layoutNavBars',
components: { BreadcrumbIndex, TagsView },
data() {
return {};
},
computed: {
// 设置是否显示 tagsView
setShowTagsView() {
let { layout, isTagsview } = this.$store.state.themeConfig.themeConfig;
return layout !== 'classic' && isTagsview;
},
},
};
</script>
<style scoped lang="scss">
.layout-navbars-container {
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
}
</style>
+110
View File
@@ -0,0 +1,110 @@
<template>
<div>
<transition name="el-zoom-in-center">
<ul
class="el-dropdown-menu el-popper el-dropdown-menu--medium custom-contextmenu"
:style="`top: ${dropdowns.y}px;left: ${dropdowns.x}px;`"
x-placement="bottom-end"
id="contextmenu"
v-show="isShow"
>
<li class="el-dropdown-menu__item" v-for="(v, k) in dropdownList" :key="k" @click="onCurrentContextmenuClick(v.id)">
<template v-if="!v.affix">
<i :class="v.icon"></i>
<span>{{ $t(v.txt) }}</span>
</template>
</li>
<div x-arrow class="popper__arrow" :style="{ left: `${arrowLeft}px` }"></div>
</ul>
</transition>
</div>
</template>
<script>
export default {
name: 'layoutTagsViewContextmenu',
props: {
dropdown: {
type: Object,
},
},
data() {
return {
isShow: false,
dropdownList: [
{ id: 0, txt: 'message.tagsView.refresh', affix: false, icon: 'el-icon-refresh-right' },
{ id: 1, txt: 'message.tagsView.close', affix: false, icon: 'el-icon-close' },
{ id: 2, txt: 'message.tagsView.closeOther', affix: false, icon: 'el-icon-circle-close' },
{ id: 3, txt: 'message.tagsView.closeAll', affix: false, icon: 'el-icon-folder-delete' },
],
path: {},
arrowLeft: 5,
};
},
computed: {
dropdowns() {
// 99 为 `Dropdown 下拉菜单` 的宽度
if (this.dropdown.x + 99 > document.documentElement.clientWidth) {
return {
x: document.documentElement.clientWidth - 99 - 5,
y: this.dropdown.y,
};
} else {
return this.dropdown;
}
},
},
mounted() {
// 监听页面监听进行右键菜单的关闭
document.body.addEventListener('click', this.closeContextmenu);
},
methods: {
// 当前项菜单点击
onCurrentContextmenuClick(id) {
this.$emit('currentContextmenuClick', { id, path: this.path });
},
// 打开右键菜单:判断是否固定,固定则不显示关闭按钮
openContextmenu(item) {
this.path = item.path;
item.meta.isAffix ? (this.dropdownList[1].affix = true) : (this.dropdownList[1].affix = false);
this.closeContextmenu();
setTimeout(() => {
this.isShow = true;
}, 80);
},
// 关闭右键菜单
closeContextmenu() {
this.isShow = false;
},
},
destroyed() {
// 页面卸载时,移除右键菜单监听事件
document.body.removeEventListener('click', this.closeContextmenu);
},
// 监听下拉菜单位置
watch: {
dropdown: {
handler({ x }) {
if (x + 99 > document.documentElement.clientWidth) this.arrowLeft = 99 - (document.documentElement.clientWidth - x);
else this.arrowLeft = 10;
},
deep: true,
},
},
};
</script>
<style scoped lang="scss">
.custom-contextmenu {
transform-origin: center top;
z-index: 2190;
position: fixed;
.el-dropdown-menu__item {
font-size: 12px !important;
white-space: nowrap;
i {
font-size: 12px !important;
}
}
}
</style>
+404
View File
@@ -0,0 +1,404 @@
<template>
<div class="layout-navbars-tagsview">
<el-scrollbar ref="scrollbarRef" @wheel.native.prevent="onHandleScroll">
<ul class="layout-navbars-tagsview-ul" :class="setTagsStyle" ref="tagsUlRef">
<li
v-for="(v, k) in tagsViewList"
:key="k"
class="layout-navbars-tagsview-ul-li"
:data-name="v.name"
:class="{ 'is-active': v.path === tagsRoutePath }"
@contextmenu.prevent="onContextmenu(v, $event)"
@click="onTagsClick(v, k)"
ref="tagsRefs"
>
<i class="iconfont icon-webicon318 layout-navbars-tagsview-ul-li-iconfont font14" v-if="v.path === tagsRoutePath"></i>
<i
class="layout-navbars-tagsview-ul-li-iconfont font14 is-tagsview-icon"
:class="v.meta.icon"
v-if="v.path !== tagsRoutePath && getThemeConfig.isTagsviewIcon"
></i>
<span>{{ $t(v.meta.title) }}</span>
<i
class="el-icon-refresh-right layout-navbars-tagsview-ul-li-icon ml5"
v-if="v.path === tagsRoutePath"
@click.stop="refreshCurrentTagsView(v.path)"
></i>
<i class="el-icon-close layout-navbars-tagsview-ul-li-icon ml5" v-if="!v.meta.isAffix" @click.stop="closeCurrentTagsView(v.path)"></i>
</li>
</ul>
</el-scrollbar>
<Contextmenu :dropdown="tagsDropdown" ref="tagsContextmenu" @currentContextmenuClick="onCurrentContextmenuClick" />
</div>
</template>
<script>
import Contextmenu from '@/layout/navBars/tagsView/contextmenu';
import { Session } from '@/utils/storage.js';
export default {
name: 'tagsView',
components: { Contextmenu },
data() {
return {
userInfo: {},
tagsViewList: [],
tagsDropdown: {
x: '',
y: '',
},
tagsRefsIndex: 0,
tagsRoutePath: this.$route.path,
tagsViewRoutesList: [],
};
},
computed: {
// 获取布局配置信息
getThemeConfig() {
return this.$store.state.themeConfig.themeConfig;
},
// 动态设置 tagsView 风格样式
setTagsStyle() {
return this.$store.state.themeConfig.themeConfig.tagsStyle;
},
},
created() {
// 监听非本页面调用 0 刷新当前,1 关闭当前,2 关闭其它,3 关闭全部
this.bus.$on('onCurrentContextmenuClick', (data) => {
this.onCurrentContextmenuClick(data);
});
},
mounted() {
this.getTagsViewRoutes();
},
methods: {
// 获取路由信息
getRoutesList() {
return this.$store.state.routesList.routesList;
},
// 当前的 tagsView 项点击时
onTagsClick(v, k) {
this.tagsRoutePath = v.path;
this.tagsRefsIndex = k;
this.$router.push(v);
},
// 获取 tagsView 的下标:用于处理 tagsView 点击时的横向滚动
getTagsRefsIndex(path) {
if (this.tagsViewList.length > 0) {
this.tagsRefsIndex = this.tagsViewList.findIndex((item) => item.path === path);
}
},
// 鼠标滚轮滚动
onHandleScroll(e) {
this.$refs.scrollbarRef.$refs.wrap.scrollLeft += e.wheelDelta / 4;
},
// tagsView 横向滚动
tagsViewmoveToCurrentTag() {
this.$nextTick(() => {
const tagsRefs = this.$refs.tagsRefs;
if (tagsRefs.length <= 0) return false;
// 当前 li 元素
let liDom = tagsRefs[this.tagsRefsIndex];
// 当前 li 元素下标
let liIndex = this.tagsRefsIndex;
// 当前 ul 下 li 元素总长度
let liLength = tagsRefs.length;
// 最前 li
let liFirst = tagsRefs[0];
// 最后 li
let liLast = tagsRefs[tagsRefs.length - 1];
// 当前滚动条的值
let scrollRefs = this.$refs.scrollbarRef.$refs.wrap;
// 当前滚动条滚动宽度
let scrollS = scrollRefs.scrollWidth;
// 当前滚动条偏移宽度
let offsetW = scrollRefs.offsetWidth;
// 当前滚动条偏移距离
let scrollL = scrollRefs.scrollLeft;
// 上一个 tags li dom
let liPrevTag = tagsRefs[this.tagsRefsIndex - 1];
// 下一个 tags li dom
let liNextTag = tagsRefs[this.tagsRefsIndex + 1];
// 上一个 tags li dom 的偏移距离
let beforePrevL = '';
// 下一个 tags li dom 的偏移距离
let afterNextL = '';
if (liDom === liFirst) {
// 头部
scrollRefs.scrollLeft = 0;
} else if (liDom === liLast) {
// 尾部
scrollRefs.scrollLeft = scrollS - offsetW;
} else {
// 非头/尾部
if (liIndex === 0) beforePrevL = liFirst?.offsetLeft - 5;
else beforePrevL = liPrevTag?.offsetLeft - 5;
if (liIndex === liLength) afterNextL = liLast?.offsetLeft + liLast.offsetWidth + 5;
else afterNextL = liNextTag?.offsetLeft + liNextTag.offsetWidth + 5;
if (afterNextL > scrollL + offsetW) {
scrollRefs.scrollLeft = afterNextL - offsetW;
} else if (beforePrevL < scrollL) {
scrollRefs.scrollLeft = beforePrevL;
}
}
// 更新滚动条,防止不出现
this.updateScrollbar();
});
},
// 更新滚动条显示
updateScrollbar() {
this.$refs.scrollbarRef.update();
},
// 递归查找当前路径下的组件信息
filterCurrentMenu(arr, currentPath, callback) {
arr.map((item) => {
if (item.path === currentPath) {
callback(item);
return false;
}
item = Object.assign({}, item);
if (item.children) {
item.children = this.filterCurrentMenu(item.children, currentPath, callback);
}
});
},
// 数组对象去重
duplicate(arr) {
let newobj = {};
arr = arr.reduce((preVal, curVal) => {
newobj[curVal.path] ? '' : (newobj[curVal.path] = preVal.push(curVal));
return preVal;
}, []);
return arr;
},
// 获取 vuex 中的 tagsViewRoutes 列表
getTagsViewRoutes() {
this.tagsRoutePath = this.$route.path;
this.tagsViewList = [];
if (!this.$store.state.themeConfig.themeConfig.isCacheTagsView) Session.remove('tagsViewList');
this.tagsViewRoutesList = this.$store.state.tagsViewRoutes.tagsViewRoutes;
this.initTagsViewList();
},
// 存储 tagsViewList 到浏览器临时缓存中,页面刷新时,保留记录
addBrowserSetSession(tagsViewList) {
Session.set('tagsViewList', tagsViewList);
},
// 初始化设置了 tagsView 数据
initTagsViewList() {
if (Session.get('tagsViewList') && this.$store.state.themeConfig.themeConfig.isCacheTagsView) {
this.tagsViewList = Session.get('tagsViewList');
} else {
this.tagsViewRoutesList.map((v) => {
if (v.meta.isAffix && !v.meta.isHide) this.tagsViewList.push({ ...v });
});
this.addTagsView(this.$route.path);
}
// 初始化当前元素(li)的下标
this.getTagsRefsIndex(this.$route.path);
// 添加初始化横向滚动条移动到对应位置
this.tagsViewmoveToCurrentTag();
},
// 添加 tagsView:未设置隐藏(isHide)也添加到在 tagsView 中
addTagsView(path, to) {
if (this.tagsViewList.some((v) => v.path === path)) return false;
const item = this.tagsViewRoutesList.find((v) => v.path === path);
if (item.meta.isLink && !item.meta.isIframe) return false;
item.query = to?.query ? to?.query : this.$route.query;
this.tagsViewList.push({ ...item });
this.addBrowserSetSession(this.tagsViewList);
},
// 右键菜单点击时显示菜单列表
onContextmenu(v, e) {
let { clientX, clientY } = e;
this.tagsDropdown.x = clientX;
this.tagsDropdown.y = clientY;
this.$refs.tagsContextmenu.openContextmenu(v);
},
// 当前项右键菜单点击
onCurrentContextmenuClick(data) {
let { id, path } = data;
let currentTag = this.tagsViewList.find((v) => v.path === path);
switch (id) {
case 0:
this.refreshCurrentTagsView(path);
this.$router.push({ path, query: currentTag.query });
break;
case 1:
this.closeCurrentTagsView(path);
break;
case 2:
this.$router.push({ path, query: currentTag.query });
this.closeOtherTagsView(path);
break;
case 3:
this.closeAllTagsView(path);
break;
}
},
// 1、刷新当前 tagsView:
refreshCurrentTagsView(path) {
this.bus.$emit('onTagsViewRefreshRouterView', path);
},
// 2、关闭当前 tagsView:当前项 `tags-view` icon 关闭时点击,如果是设置了固定的(isAffix),不可以关闭
closeCurrentTagsView(path) {
this.tagsViewList.map((v, k, arr) => {
if (!v.meta.isAffix) {
if (v.path === path) {
this.tagsViewList.splice(k, 1);
setTimeout(() => {
// 最后一个
if (this.tagsViewList.length === k) this.$router.push({ path: arr[arr.length - 1].path, query: arr[arr.length - 1].query });
// 否则,跳转到下一个
else this.$router.push({ path: arr[k].path, query: arr[k].query });
}, 0);
}
}
});
this.addBrowserSetSession(this.tagsViewList);
},
// 3、关闭其它 tagsView:如果是设置了固定的(isAffix),不进行关闭
closeOtherTagsView(path) {
this.tagsViewList = [];
this.tagsViewRoutesList.map((v) => {
if (v.meta.isAffix && !v.meta.isHide) this.tagsViewList.push({ ...v });
});
this.addTagsView(path);
},
// 4、关闭全部 tagsView:如果是设置了固定的(isAffix),不进行关闭
closeAllTagsView(path) {
this.tagsViewList = [];
this.tagsViewRoutesList.map((v) => {
if (v.meta.isAffix && !v.meta.isHide) {
this.tagsViewList.push({ ...v });
if (this.tagsViewList.some((v) => v.path === path)) this.$router.push({ path, query: this.$route.query });
else this.$router.push({ path: v.path, query: this.$route.query });
}
});
this.addBrowserSetSession(this.tagsViewList);
},
},
watch: {
// 监听路由变化
$route: {
handler(to) {
this.tagsRoutePath = to.path;
this.addTagsView(to.path, to);
this.getTagsRefsIndex(to.path);
this.tagsViewmoveToCurrentTag();
},
deep: true,
},
},
destroyed() {
// 取消非本页面调用监听(fun/tagsView)
this.bus.$off('onCurrentContextmenuClick');
},
};
</script>
<style scoped lang="scss">
.layout-navbars-tagsview {
flex: 1;
background-color: var(--prev-bg-white);
border-bottom: 1px solid var(--prev-border-color-lighter);
& ::v-deep .is-vertical {
display: none !important;
}
&-ul {
list-style: none;
margin: 0;
padding: 0;
width: 100%;
height: 34px;
display: flex;
align-items: center;
white-space: nowrap;
color: var(--prev-color-text-regular);
font-size: 12px;
padding: 0 15px;
&-li {
height: 26px;
line-height: 26px;
display: flex;
align-items: center;
border: 1px solid var(--prev-border-color-lighter);
padding: 0 12px 0 15px;
margin-right: 5px;
border-radius: 2px;
position: relative;
z-index: 0;
cursor: pointer;
justify-content: space-between;
transition: all 0.3s cubic-bezier(0.2, 1, 0.3, 1);
&::before {
content: '';
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background: var(--prev-color-primary);
z-index: -1;
opacity: 0;
transform: scale3d(0.7, 1, 1);
transition: transform 0.3s, opacity 0.3s;
transition-timing-function: cubic-bezier(0.2, 1, 0.3, 1);
}
&:hover {
color: var(--prev-color-text-white);
transition: all 0.3s cubic-bezier(0.2, 1, 0.3, 1);
border-color: transparent;
&::before {
opacity: 1;
transform: translate3d(0, 0, 0);
border-radius: 2px;
}
.is-tagsview-icon {
color: var(--prev-color-text-white);
transition: all 0.3s cubic-bezier(0.2, 1, 0.3, 1);
}
}
&-iconfont {
position: relative;
left: -5px;
top: 1px;
color: var(--prev-color-text-white);
}
&-icon {
border-radius: 100%;
position: relative;
height: 14px;
width: 14px;
text-align: center;
line-height: 14px;
top: 1px;
}
.is-tagsview-icon {
color: var(--prev-color-text-regular);
transition: all 0.3s cubic-bezier(0.2, 1, 0.3, 1);
}
}
.is-active {
color: var(--prev-color-text-white);
transition: all 0.3s cubic-bezier(0.2, 1, 0.3, 1);
border-color: transparent;
&::before {
opacity: 1;
transform: translate3d(0, 0, 0);
border-radius: 2px;
}
}
}
& ::-webkit-scrollbar {
display: none !important;
}
// // 风格2
// .tags-style-two {
// }
// // 风格3
// .tags-style-three {
// }
// // 风格4
// .tags-style-four {
// }
}
</style>
+138
View File
@@ -0,0 +1,138 @@
<template>
<div class="el-menu-horizontal-warp">
<el-scrollbar @wheel.native.prevent="onElMenuHorizontalScroll" ref="elMenuHorizontalScrollRef">
<el-menu router :default-active="defaultActive" background-color="transparent" mode="horizontal" @select="onHorizontalSelect">
<template v-for="val in menuList">
<el-submenu :index="val.path" v-if="val.children && val.children.length > 0" :key="val.path">
<template slot="title">
<i :class="val.meta.icon ? val.meta.icon : ''"></i>
<span>{{ $t(val.meta.title) }}</span>
</template>
<SubItem :chil="val.children" />
</el-submenu>
<template v-else>
<el-menu-item :index="val.path" :key="val.path">
<template slot="title" v-if="!val.meta.isLink || (val.meta.isLink && val.meta.isIframe)">
<i :class="val.meta.icon ? val.meta.icon : ''"></i>
{{ $t(val.meta.title) }}
</template>
<template slot="title" v-else>
<a :href="val.meta.isLink" target="_blank">
<i :class="val.meta.icon ? val.meta.icon : ''"></i>
{{ $t(val.meta.title) }}
</a>
</template>
</el-menu-item>
</template>
</template>
</el-menu>
</el-scrollbar>
</div>
</template>
<script>
import SubItem from '@/layout/navMenu/subItem.vue';
export default {
name: 'navMenuHorizontal',
components: { SubItem },
props: {
menuList: {
type: Array,
default: () => [],
},
},
data() {
return {
defaultActive: null,
};
},
mounted() {
this.initElMenuOffsetLeft();
this.setCurrentRouterHighlight(this.$route.path);
},
methods: {
// 设置横向滚动条可以鼠标滚轮滚动
onElMenuHorizontalScroll(e) {
const eventDelta = e.wheelDelta || -e.deltaY * 40;
this.$refs.elMenuHorizontalScrollRef.$refs.wrap.scrollLeft = this.$refs.elMenuHorizontalScrollRef.$refs.wrap.scrollLeft + eventDelta / 4;
},
// 初始化数据,页面刷新时,滚动条滚动到对应位置
initElMenuOffsetLeft() {
this.$nextTick(() => {
let els = document.querySelector('.el-menu.el-menu--horizontal li.is-active');
if (!els) return false;
this.$refs.elMenuHorizontalScrollRef.$refs.wrap.scrollLeft = els.offsetLeft;
});
},
// 路由过滤递归函数
filterRoutesFun(arr) {
return arr
.filter((item) => !item.meta.isHide)
.map((item) => {
item = Object.assign({}, item);
if (item.children) item.children = this.filterRoutesFun(item.children);
return item;
});
},
// 传送当前子级数据到菜单中
setSendClassicChildren(path) {
const currentPathSplit = path.split('/');
let currentData = {};
this.filterRoutesFun(this.$store.state.routesList.routesList).map((v, k) => {
if (v.path === `/${currentPathSplit[1]}`) {
v['k'] = k;
currentData['item'] = [{ ...v }];
currentData['children'] = [{ ...v }];
if (v.children) currentData['children'] = v.children;
}
});
return currentData;
},
// 菜单激活回调
onHorizontalSelect(path) {
this.bus.$emit('setSendClassicChildren', this.setSendClassicChildren(path));
},
// 设置页面当前路由高亮
setCurrentRouterHighlight(path) {
const currentPathSplit = path.split('/');
if (this.$store.state.themeConfig.themeConfig.layout === 'classic') {
this.defaultActive = `/${currentPathSplit[1]}`;
} else {
this.defaultActive = path;
}
},
},
watch: {
// 监听路由的变化
$route: {
handler(to) {
this.setCurrentRouterHighlight(to.path);
},
deep: true,
},
},
};
</script>
<style scoped lang="scss">
.el-menu-horizontal-warp {
flex: 1;
overflow: hidden;
margin-right: 30px;
::v-deep .el-scrollbar__bar.is-vertical {
display: none;
}
::v-deep .el-scrollbar__wrap {
overflow-y: hidden !important;
}
::v-deep a {
width: 100%;
}
.el-menu.el-menu--horizontal {
display: flex;
height: 100%;
width: 100%;
box-sizing: border-box;
}
}
</style>
+41
View File
@@ -0,0 +1,41 @@
<template>
<div>
<template v-for="val in chil">
<el-submenu :index="val.path" :key="val.path" v-if="val.children && val.children.length > 0">
<template slot="title">
<i :class="val.meta.icon"></i>
<span>{{ $t(val.meta.title) }}</span>
</template>
<sub-item :chil="val.children" />
</el-submenu>
<template v-else>
<el-menu-item :index="val.path" :key="val.path">
<template v-if="!val.meta.isLink || (val.meta.isLink && val.meta.isIframe)">
<i :class="val.meta.icon ? val.meta.icon : ''"></i>
<span>{{ $t(val.meta.title) }}</span>
</template>
<template v-else>
<a :href="val.meta.isLink" target="_blank">
<i :class="val.meta.icon ? val.meta.icon : ''"></i>
{{ $t(val.meta.title) }}
</a>
</template>
</el-menu-item>
</template>
</template>
</div>
</template>
<script>
export default {
name: 'subItem',
props: {
chil: {
type: Array,
default() {
return [];
},
},
},
};
</script>
+73
View File
@@ -0,0 +1,73 @@
<template>
<el-menu
router
background-color="transparent"
:default-active="defaultActive"
:collapse="setIsCollapse"
:unique-opened="getThemeConfig.isUniqueOpened"
:collapse-transition="false"
>
<template v-for="val in menuList">
<el-submenu :index="val.path" v-if="val.children && val.children.length > 0" :key="val.path">
<template slot="title">
<i :class="val.meta.icon ? val.meta.icon : ''"></i>
<span>{{ $t(val.meta.title) }}</span>
</template>
<SubItem :chil="val.children" />
</el-submenu>
<template v-else>
<el-menu-item :index="val.path" :key="val.path">
<i :class="val.meta.icon ? val.meta.icon : ''"></i>
<template slot="title" v-if="!val.meta.isLink || (val.meta.isLink && val.meta.isIframe)">
<span>{{ $t(val.meta.title) }}</span>
</template>
<template slot="title" v-else>
<a :href="val.meta.isLink" target="_blank">{{ $t(val.meta.title) }}</a>
</template>
</el-menu-item>
</template>
</template>
</el-menu>
</template>
<script>
import SubItem from '@/layout/navMenu/subItem.vue';
export default {
name: 'navMenuVertical',
components: { SubItem },
props: {
menuList: {
type: Array,
default() {
return [];
},
},
},
data() {
return {
defaultActive: this.$route.path,
};
},
computed: {
// 获取布局配置信息
getThemeConfig() {
return this.$store.state.themeConfig.themeConfig;
},
// 设置左侧菜单是否展开/收起
setIsCollapse() {
return document.body.clientWidth < 1000 ? false : this.$store.state.themeConfig.themeConfig.isCollapse;
},
},
watch: {
// 监听路由的变化
$route: {
handler(to) {
this.defaultActive = to.path;
const clientWidth = document.body.clientWidth;
if (clientWidth < 1000) this.$store.state.themeConfig.themeConfig.isCollapse = false;
},
deep: true,
},
},
};
</script>
+46
View File
@@ -0,0 +1,46 @@
<template>
<div>
<div class="layout-view-bg-white flex h100" v-loading="iframeLoading">
<iframe :src="meta.isLink" frameborder="0" height="100%" width="100%" id="iframe"></iframe>
</div>
</div>
</template>
<script>
export default {
name: 'layoutIfameView',
props: {
meta: {
type: Object,
default: () => {},
},
},
data() {
return {
iframeLoading: true,
};
},
created() {
this.bus.$on('onTagsViewRefreshRouterView', (path) => {
if (this.$route.path !== path) return false;
this.$emit('getCurrentRouteMeta');
});
},
mounted() {
this.initIframeLoad();
},
methods: {
// 初始化页面加载 loading
initIframeLoad() {
this.$nextTick(() => {
this.iframeLoading = true;
const iframe = document.getElementById('iframe');
if (!iframe) return false;
iframe.onload = () => {
this.iframeLoading = false;
};
});
},
},
};
</script>
+83
View File
@@ -0,0 +1,83 @@
<template>
<div class="layout-scrollbar layout-link-container">
<div class="layout-view-bg-white flex layout-view-link">
<div class="layout-link-warp">
<i class="layout-link-icon iconfont icon-xingqiu"></i>
<div class="layout-link-msg">页面 "{{ $t(meta.title) }}" 已在新窗口中打开</div>
<el-button class="mt30" round size="small" @click="onGotoFullPage">
<i class="iconfont icon-lianjie"></i>
<span>立即前往体验</span>
</el-button>
</div>
</div>
</div>
</template>
<script>
import { verifyUrl } from '@/utils/toolsValidate';
export default {
name: 'layoutLinkView',
props: {
meta: {
type: Object,
default: () => {},
},
},
methods: {
// 立即前往
onGotoFullPage() {
const { origin, pathname } = window.location;
if (verifyUrl(this.meta.isLink)) window.open(this.meta.isLink);
else window.open(`${origin}${pathname}#${this.meta.isLink}`);
},
},
};
</script>
<style scoped lang="scss">
.layout-link-container {
.layout-link-warp {
margin: auto;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
i.layout-link-icon {
position: relative;
font-size: 100px;
color: var(--prev-color-primary);
&::after {
content: '';
position: absolute;
left: 50px;
top: 0;
width: 15px;
height: 100px;
background: linear-gradient(
rgba(255, 255, 255, 0.01),
rgba(255, 255, 255, 0.01),
rgba(255, 255, 255, 0.01),
rgba(255, 255, 255, 0.05),
rgba(255, 255, 255, 0.05),
rgba(255, 255, 255, 0.05),
rgba(235, 255, 255, 0.5),
rgba(255, 255, 255, 0.05),
rgba(255, 255, 255, 0.05),
rgba(255, 255, 255, 0.05),
rgba(255, 255, 255, 0.01),
rgba(255, 255, 255, 0.01),
rgba(255, 255, 255, 0.01)
);
transform: rotate(-15deg);
animation: toRight 5s linear infinite;
}
}
.layout-link-msg {
font-size: 12px;
color: var(--prev-bg-topBarColor);
opacity: 0.7;
margin-top: 15px;
}
}
}
</style>
+47
View File
@@ -0,0 +1,47 @@
<template>
<div class="h100">
<transition :name="setTransitionName" mode="out-in">
<keep-alive :include="keepAliveNameList">
<router-view :key="refreshRouterViewKey" />
</keep-alive>
</transition>
</div>
</template>
<script>
export default {
name: 'parent',
data() {
return {
refreshRouterViewKey: null,
keepAliveNameList: [],
keepAliveNameNewList: [],
};
},
created() {
// 页面加载前,处理缓存,页面刷新时路由缓存处理
this.keepAliveNameList = this.getKeepAliveNames();
this.bus.$on('onTagsViewRefreshRouterView', (path) => {
if (this.$route.path !== path) return false;
this.keepAliveNameList = this.getKeepAliveNames().filter((name) => this.$route.name !== name);
this.refreshRouterViewKey = this.$route.path;
this.$nextTick(() => {
this.refreshRouterViewKey = null;
this.keepAliveNameList = this.getKeepAliveNames();
});
});
},
computed: {
// 设置主界面切换动画
setTransitionName() {
return this.$store.state.themeConfig.themeConfig.animation;
},
},
methods: {
// 获取路由缓存列表(name),默认路由全部缓存
getKeepAliveNames() {
return this.$store.state.keepAliveNames.keepAliveNames;
},
},
};
</script>
+123
View File
@@ -0,0 +1,123 @@
<template>
<div
class="sponsors-container"
title="点击前往体验"
v-show="sponsors.isShow"
@click="onSponsorsClick"
>
<el-carousel
height="240px"
indicator-position="none"
:arrow="setCarouselShow"
@change="onCarouselChange"
>
<el-carousel-item v-for="(v, k) in sponsors.list" :key="k">
<img :src="v.url" class="sponsors-img" />
<div class="sponsors-text" v-html="v.text"></div>
</el-carousel-item>
</el-carousel>
<div class="sponsors-close" title="关闭赞助商" @click.stop="onCloseSponsors">
<i class="el-icon-close"></i>
</div>
</div>
</template>
<script>
import sponsorsOne from "@/assets/ccflowRightNextAdmin.png";
export default {
name: "layoutSponsors",
data() {
return {
sponsors: {
list: [
{
url: sponsorsOne,
text: `自创建鼎盛无际后台管理系统模板`,
link: "http://www.ccflow.org/",
},
],
isShow: false,
index: 0,
},
};
},
computed: {
// 设置轮播图箭头显示
setCarouselShow() {
return this.sponsors.list.length <= 1 ? "never" : "hover";
},
},
methods: {
// 关闭赞助商
onCloseSponsors() {
this.sponsors.isShow = false;
},
// 轮播图改变时
onCarouselChange(e) {
this.sponsors.index = e;
},
// 当前项内容点击
onSponsorsClick() {
window.open(this.sponsors.list[this.sponsors.index].link);
},
// 延迟显示,防止影响其它界面加载
delayShow() {
setTimeout(() => {
this.sponsors.isShow = true;
}, 3000);
},
},
mounted() {
this.delayShow();
},
};
</script>
<style scoped lang="scss">
.sponsors-container {
position: fixed;
right: 15px;
bottom: 15px;
z-index: 3;
width: 200px;
background-color: var(--prev-bg-main-color);
box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.12);
border-radius: 5px;
overflow: hidden;
cursor: pointer;
.sponsors-img {
width: 100%;
height: 80px;
}
.sponsors-text {
padding: 10px;
color: var(--prev-color-text-regular);
font-size: 14px;
}
.sponsors-close {
width: 60px;
height: 60px;
border-radius: 100%;
background: rgba(0, 0, 0, 0.05);
transition: all 0.3s ease;
position: absolute;
right: -35px;
bottom: -35px;
z-index: 5;
i {
position: absolute;
left: 9px;
top: 9px;
color: #afafaf;
transition: all 0.3s ease;
}
&:hover {
transition: all 0.3s ease;
i {
color: var(--prev-color-primary);
transition: all 0.3s ease;
}
}
}
}
</style>
+164
View File
@@ -0,0 +1,164 @@
<template>
<div class="upgrade-dialog">
<el-dialog
:visible.sync="isUpgrade"
width="300px"
destroy-on-close
:show-close="false"
:close-on-click-modal="false"
:close-on-press-escape="false"
>
<div class="upgrade-title">
<div class="upgrade-title-warp">
<span class="upgrade-title-warp-txt">{{ $t("message.upgrade.title") }}</span>
<span class="upgrade-title-warp-version">{{ version }}</span>
</div>
</div>
<div class="upgrade-content">
{{ getThemeConfig.globalTitle }} {{ $t("message.upgrade.msg") }}
<div class="mt5">
<el-link
type="primary"
class="font12"
href="https://gitee.com/lyt-top/vue-next-admin/blob/vue-prev-admin/CHANGELOG.md"
target="_black"
>
CHANGELOG.md
</el-link>
</div>
<div class="upgrade-content-desc mt5">{{ $t("message.upgrade.desc") }}</div>
</div>
<div class="upgrade-btn">
<el-button round size="small" @click="onCancel">{{
$t("message.upgrade.btnOne")
}}</el-button>
<el-button
type="primary"
disabled="disabled"
round
size="small"
@click="onUpgrade"
:loading="isLoading"
>{{ btnTxt }}</el-button
>
</div>
</el-dialog>
</div>
</template>
<script>
import { Local } from "@/utils/storage";
import config from "/package.json";
export default {
data() {
return {
isUpgrade: false,
version: config.version,
isLoading: false,
btnTxt: "",
};
},
computed: {
// 获取布局配置信息
getThemeConfig() {
return this.$store.state.themeConfig.themeConfig;
},
},
methods: {
// 残忍拒绝
onCancel() {
this.isUpgrade = false;
},
// 马上更新
onUpgrade() {
this.isLoading = true;
this.btnTxt = this.$t("message.upgrade.btnTwoLoading");
setTimeout(() => {
Local.clear();
window.location.reload();
Local.set("version", this.version);
}, 2000);
},
// 延迟显示,防止刷新时界面显示太快
delayShow() {
setTimeout(() => {
this.isUpgrade = true;
}, 2000);
},
},
mounted() {
this.delayShow();
setTimeout(() => {
this.btnTxt = this.$t("message.upgrade.btnTwo");
}, 200);
},
};
</script>
<style scoped lang="scss">
.upgrade-dialog {
& ::v-deep .el-dialog {
.el-dialog__body {
padding: 0 !important;
}
.el-dialog__header {
display: none !important;
}
.upgrade-title {
text-align: center;
height: 130px;
display: flex;
align-items: center;
justify-content: center;
position: relative;
&::after {
content: "";
position: absolute;
background-color: var(--prev-color-primary-light-1);
width: 130%;
height: 130px;
border-bottom-left-radius: 100%;
border-bottom-right-radius: 100%;
}
.upgrade-title-warp {
z-index: 1;
position: relative;
.upgrade-title-warp-txt {
color: var(--prev-color-text-white);
font-size: 22px;
letter-spacing: 3px;
}
.upgrade-title-warp-version {
background-color: var(--prev-color-primary-light-4);
color: var(--prev-color-text-white);
font-size: 12px;
position: absolute;
display: flex;
top: -2px;
right: -50px;
padding: 2px 4px;
border-radius: 2px;
}
}
}
.upgrade-content {
padding: 20px;
line-height: 22px;
color: var(--prev-color-text-regular);
.upgrade-content-desc {
color: var(--prev-color-text-placeholder);
font-size: 12px;
}
}
.upgrade-btn {
border-top: 1px solid var(--prev-border-color-lighter);
display: flex;
justify-content: space-around;
padding: 15px 20px;
.el-button {
width: 100%;
}
}
}
}
</style>
+41
View File
@@ -0,0 +1,41 @@
import Vue from 'vue';
import App from './App.vue';
import router from './router';
import store from './store';
import Particles from 'vue-particles';
import Element from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import '@/theme/index.scss';
import { i18n } from '@/i18n/index.js';
import { globalComponentSize } from '@/utils/componentSize.js';
import CommonTables from '@/components/CommonTables'
import CommonHead from '@/components/CommonHead'
import CommonTablesImg from '@/components/CommonTablesImg'
import Pagination from '@/components/pagination/index.vue'; // 分页器
import { formatDate } from './com';
// import { download } from '@/utils/request'
import VueCropper from 'vue-cropper'
Vue.use(VueCropper) //方便我们直接用
Vue.use(Particles);
Vue.use(Element, { i18n: (key, value) => i18n.t(key, value), size: globalComponentSize });
Vue.config.productionTip = false;
Vue.prototype.bus = new Vue();
Vue.prototype.formatDate = formatDate;
// Vue.prototype.download = download
// 注册全局组件
Vue.component(CommonTables.name,CommonTables)
Vue.component(CommonHead.name,CommonHead)
Vue.component('CommonTablesImg',CommonTablesImg)
Vue.component('Pagination', Pagination)
new Vue({
router,
store,
i18n,
render: (h) => h(App),
}).$mount('#app');
+365
View File
@@ -0,0 +1,365 @@
import Vue from 'vue';
import store from '../store';
import VueRouter from 'vue-router';
import NProgress from 'nprogress';
import 'nprogress/nprogress.css';
import { Session } from '@/utils/storage';
import { PrevLoading } from '@/utils/loading.js';
import { useMenuApi } from '@/api/menu';
import adminbendirout from '../../public/admin'
// import config from "/package.json";
const menuApi = useMenuApi();
// 解决 `element ui` 导航栏重复点菜单报错问题
const originalPush = VueRouter.prototype.push;
VueRouter.prototype.push = function push(location) {
return originalPush.call(this, location).catch((err) => err);
};
// 安装 VueRouter 插件
Vue.use(VueRouter);
// 定义动态路由
const dynamicRoutes = [
{
path: '/',
name: '/',
component: 'layout/index',
redirect: '/home',
meta: {
isKeepAlive: true,
},
children: [],
},
];
// 定义静态路由
const staticRoutes = [
{
path: '/login',
name: 'login',
component: () => import('@/views/login'),
meta: {
title: '登录',
},
},
{
path: '/404',
name: 'notFound',
component: () => import('@/views/error/404.vue'),
meta: {
title: 'message.staticRoutes.notFound',
},
},
{
path: '/401',
name: 'noPower',
component: () => import('@/views/error/401.vue'),
meta: {
title: 'message.staticRoutes.noPower',
},
},
];
// 加载静态路由
const createRouter = () =>
new VueRouter({
// mode: 'history',
routes: staticRoutes,
base: '/',
});
// 创建路由
const router = createRouter();
// 处理错误路由
router.onError((error) => {
const pattern = /Loading chunk (\d)+ failed/g;
const isChunkLoadFailed = error.message.match(pattern);
if (isChunkLoadFailed) {
window.location.reload();
router.replace(router.history.pending.fullPath);
}else{
console.log(error)
}
});
// 加载 loading
PrevLoading.start();
// 多级嵌套数组处理成一维数组
export function formatFlatteningRoutes(arr) {
if (arr.length <= 0) return false;
for (let i = 0; i < arr.length; i++) {
if (arr[i].children) {
arr = arr.slice(0, i + 1).concat(arr[i].children, arr.slice(i + 1));
}
}
return arr;
}
// 处理 tagsViewList 数据,默认路由全部缓存
// isKeepAlive 处理 `name` 值,进行路由缓存
export function formatTwoStageRoutes(arr) {
if (arr.length <= 0) return false;
const newArr = [];
const cacheList = [];
arr.forEach((v) => {
newArr.push({ ...v });
cacheList.push(v.name);
store.dispatch('keepAliveNames/setCacheKeepAlive', cacheList);
});
return newArr;
}
// 判断路由 meta.roles 中是否包含当前登录用户权限字段
export function hasAuth(roles, route) {
if (route.meta && route.meta.roles) return roles.some((role) => route.meta.roles.includes(role));
else return true;
}
// 递归过滤有权限的路由
export function setFilterMenuFun(routes, role) {
const menu = [];
routes.forEach((route) => {
const item = { ...route };
if (hasAuth(role, item)) {
if (item.children) item.children = setFilterMenuFun(item.children, role);
menu.push(item);
}
});
return menu;
}
// 缓存多级嵌套数组处理后的一维数组(tagsView、菜单搜索中使用:未过滤隐藏的(isHide))
export function setCacheTagsViewRoutes(arr) {
// 先处理有权限的路由,否则 tagsView、菜单搜索中无权限的路由也将显示
let rolesRoutes = setFilterMenuFun(arr, store.state.userInfos.userInfos.roles);
// 添加到 vuex setTagsViewRoutes 中
store.dispatch('tagsViewRoutes/setTagsViewRoutes', formatTwoStageRoutes(formatFlatteningRoutes(rolesRoutes)));
}
// 递归处理多余的 layout : <router-view>,让需要访问的组件保持在第一层 layout 层。
// 因为 `keep-alive` 只能缓存二级路由
// 默认初始化时就执行
export function keepAliveSplice(to) {
if (to.matched && to.matched.length > 2) {
to.matched.map((v, k) => {
if (v.components.default instanceof Function) {
v.components.default().then((components) => {
if (components.default.name === 'parent') {
to.matched.splice(k, 1);
router.push({ path: to.path, query: to.query });
keepAliveSplice(to);
}
});
} else {
if (v.components.default.name === 'parent') {
to.matched.splice(k, 1);
keepAliveSplice(to);
}
}
});
}
}
// 处理后端返回的 `component` 路径,拼装实现懒加载
export function loadView(path) {
/**
* 打包成一个 js、一个 css
*/
// if (path.indexOf('layout') > -1) return () => Promise.resolve(require(`@/${path}`));
// else return () => Promise.resolve(require(`@/views/${path}`));
/**
* 打包成多个 js、多个 css
*/
if (path.indexOf('layout') > -1) return () => import(`@/${path}`);
else return () => import(`@/views/${path}`);
}
// 递归处理每一项 `component` 中的路径
export function dynamicRouter(routes) {
return routes.map((view) => {
if (view.component) view.component = loadView(view.component);
if (view.children) dynamicRouter(view.children);
return view;
});
}
// 处理后端传来的路由表进行过滤操作
// 定义一个函数,用于过滤本地路由表
function filterLocalRoutes(localRoutes, backendRoutes) {
const backendPaths = getRoutePaths(backendRoutes);
function filterRoutes(routes) {
return routes.filter((route) => {
if (backendPaths.includes(route.path)) {
return true;
} else if (route.children) {
route.children = filterRoutes(route.children);
return route.children.length > 0;
} else {
return false;
}
});
}
return filterRoutes(localRoutes);
}
// 获取后端路由中所有的 path 值数组
function getRoutePaths(routes) {
const paths = [];
routes.forEach((route) => {
if (route.path) {
paths.push(route.path);
}
if (route.children && route.children.length > 0) {
paths.push(...getRoutePaths(route.children));
}
});
return paths;
}
// 添加路由,模拟数据与方法,可自行进行修改 admin
// 添加动态路由,`{ path: '*', redirect: '/404' }` 防止页面刷新,静态路由丢失问题
// next({ ...to, replace: true }) 动态路由 addRoute 完毕后才放行,防止刷新时 NProgress 进度条加载2次
// 文档地址:https://router.vuejs.org/zh/api/#router-addroutes
export function adminUser(router, to, next) {
resetRouter();
// 发请求获取路由表操作
// let parameter = {
// clientName:config.name,
// version:config.version,
// }
// menuApi
// .getMenuAdmin(parameter)
// .then(async (res) => {
// // 获取路由表
// console.log(res.data);
// // 读取用户信息,获取对应权限进行判断
// store.dispatch('userInfos/setUserInfos');
// store.dispatch('routesList/setRoutesList', setFilterMenuFun(res.data, store.state.userInfos.userInfos.roles));
// dynamicRoutes[0].children = res.data;
// const awaitRoute = await dynamicRouter(dynamicRoutes);
// [...awaitRoute, { path: '*', redirect: '/404' }].forEach((route) => {
// router.addRoute({ ...route });
// });
// setCacheTagsViewRoutes(JSON.parse(JSON.stringify(res.data)));
// next({ ...to, replace: true });
// })
// .catch(() => {});
// 本地数据路由表操作
let routingTable = sessionStorage.getItem('smart-campus:userInfoDD')
let value = JSON.parse(routingTable);
console.log(value.authorities);
let filteredLocalRoutes = filterLocalRoutes(adminbendirout.data, value.authorities)
let home ={
path: "/home",
name: "home",
component: "home",
meta: {
"title": "message.router.home",
"isLink": "",
"isHide": false,
"isKeepAlive": true,
"isAffix": true,
"isIframe": false,
"roles": ["admin", "common"],
"icon": "iconfont icon-shouye"
}
}
filteredLocalRoutes.unshift(home)
console.log(filteredLocalRoutes);;
store.dispatch('userInfos/setUserInfos');
store.dispatch('routesList/setRoutesList', setFilterMenuFun(filteredLocalRoutes, store.state.userInfos.userInfos.roles));
dynamicRoutes[0].children = filteredLocalRoutes;
const awaitRoute = dynamicRouter(dynamicRoutes);
[...awaitRoute, { path: '*', redirect: '/404' }].forEach((route) => {
router.addRoute({ ...route });
});
setCacheTagsViewRoutes(JSON.parse(JSON.stringify(filteredLocalRoutes)));
next({ ...to, replace: true });
}
// 添加路由,模拟数据与方法,可自行进行修改 test
// 添加动态路由,`{ path: '*', redirect: '/404' }` 防止页面刷新,静态路由丢失问题
export function testUser(router, to, next) {
resetRouter();
menuApi
.getMenuTest()
.then(async (res) => {
// 读取用户信息,获取对应权限进行判断
store.dispatch('userInfos/setUserInfos');
store.dispatch('routesList/setRoutesList', setFilterMenuFun(res.data, store.state.userInfos.userInfos.roles));
dynamicRoutes[0].children = res.data;
const awaitRoute = await dynamicRouter(dynamicRoutes);
[...awaitRoute, { path: '*', redirect: '/404' }].forEach((route) => {
router.addRoute({ ...route });
});
setCacheTagsViewRoutes(JSON.parse(JSON.stringify(res.data)));
next({ ...to, replace: true });
})
.catch(() => {});
}
// 重置路由
export function resetRouter() {
router.matcher = createRouter().matcher;
}
// 延迟关闭进度条
export function delayNProgressDone(time = 300) {
setTimeout(() => {
NProgress.done();
}, time);
}
// 动态加载后端返回路由路由(模拟数据)
export function getRouterList(router, to, next) {
if (!Session.get('userInfo')) return false;
if (Session.get('userInfo').userName === 'admin') adminUser(router, to, next);
else if (Session.get('userInfo').userName === 'test') testUser(router, to, next);
}
// 路由加载前
router.beforeEach((to, from, next) => {
keepAliveSplice(to);
NProgress.configure({ showSpinner: false });
if (to.meta.title && to.path !== '/login') NProgress.start();
let token = Session.get('token');
if (to.path === '/login' && !token) {
NProgress.start();
next();
delayNProgressDone();
} else {
if (!token) {
NProgress.start();
next('/login');
Session.clear();
delayNProgressDone();
} else if (token && to.path === '/login') {
next('/home');
delayNProgressDone();
} else {
if (Object.keys(store.state.routesList.routesList).length <= 0) {
getRouterList(router, to, next);
} else {
next();
delayNProgressDone(0);
}
}
}
});
// 路由加载后
router.afterEach(() => {
PrevLoading.done();
delayNProgressDone();
});
// 导出路由
export default router;
+25
View File
@@ -0,0 +1,25 @@
import Vue from 'vue';
import Vuex from 'vuex';
import { Session } from '@/utils/storage';
Vue.use(Vuex);
let moduleFn = require.context('./modules', false, /\.js$/);
let modules = moduleFn.keys().reduce((p, c) => {
let mod = moduleFn(c).default;
mod = { ...mod, namespaced: true };
let modName = c.match(/\.\/(\w+)\.js$/)[1];
p[modName] = mod;
return p;
}, {});
const state = {
imgUrl: 'https://hxhl.lzyyj.com/prod-api/file/upload/face',
uploadHeader: {
Authorization: `${Session.get('token')}`
},
campusCalendarTempentUrl: process.env.VUE_APP_BASE_API, //
}
export default new Vuex.Store({ state, modules });
+20
View File
@@ -0,0 +1,20 @@
const keepAliveNamesModule = {
namespaced: true,
state: {
keepAliveNames: [],
},
mutations: {
// 设置路由缓存(name字段)
getCacheKeepAlive(state, data) {
state.keepAliveNames = data;
},
},
actions: {
// 设置路由缓存(name字段)
async setCacheKeepAlive({ commit }, data) {
commit('getCacheKeepAlive', data);
},
},
};
export default keepAliveNamesModule;
+20
View File
@@ -0,0 +1,20 @@
const routesListModule = {
namespaced: true,
state: {
routesList: [],
},
mutations: {
// 设置路由,菜单中使用到
getRoutesList(state, data) {
state.routesList = data;
},
},
actions: {
// 设置路由,菜单中使用到
async setRoutesList({ commit }, data) {
commit('getRoutesList', data);
},
},
};
export default routesListModule;
+20
View File
@@ -0,0 +1,20 @@
const tagsViewRoutesModule = {
namespaced: true,
state: {
tagsViewRoutes: [],
},
mutations: {
// 设置 TagsView 路由
getTagsViewRoutes(state, data) {
state.tagsViewRoutes = data;
},
},
actions: {
// 设置 TagsView 路由
async setTagsViewRoutes({ commit }, data) {
commit('getTagsViewRoutes', data);
},
},
};
export default tagsViewRoutesModule;
+122
View File
@@ -0,0 +1,122 @@
/**
* 2020.05.28 by lyt 优化
* 修改一下配置时,需要每次都清理 `window.localStorage` 浏览器永久缓存,配置才会生效
*/
const themeConfigModule = {
namespaced: true,
state: {
themeConfig: {
// 是否开启布局配置抽屉
isDrawer: false,
/**
* 全局主题
*/
// 默认 primary 主题颜色
primary: '#409eff',
// 是否开启深色模式
isIsDark: false,
/**
* 菜单 / 顶栏
* 请注意:
* 需要同时修改 `/@/theme/common/var.scss` 对应的值,
* 不提供像 vue-next-admin 一样的实现
*/
// 默认顶栏导航背景颜色
topBar: '#ffffff',
// 默认顶栏导航字体颜色
topBarColor: '#606266',
// 默认菜单导航背景颜色
menuBar: '#545c64',
// 默认菜单导航字体颜色
menuBarColor: '#eaeaea',
// 默认分栏菜单背景颜色
columnsMenuBar: '#545c64',
// 默认分栏菜单字体颜色
columnsMenuBarColor: '#e6e6e6',
/**
* 界面设置
*/
// 是否开启菜单水平折叠效果
isCollapse: false,
// 是否开启菜单手风琴效果
isUniqueOpened: false,
// 是否开启固定 Header
isFixedHeader: false,
/**
* 界面显示
*/
// 是否开启侧边栏 Logo
isShowLogo: true,
// 是否开启 Breadcrumb
isBreadcrumb: true,
// 是否开启 Breadcrumb 图标
isBreadcrumbIcon: false,
// 是否开启 Tagsview
isTagsview: true,
// 是否开启 Tagsview 图标
isTagsviewIcon: false,
// 是否开启 TagsView 缓存
isCacheTagsView: false,
// 是否开启 Footer 底部版权信息
isFooter: false,
// 是否开启灰色模式
isGrayscale: false,
// 是否开启色弱模式
isInvert: false,
/**
* 其它设置
*/
// 默认 Tagsview 风格,可选 1、 tags-style-one,自行扩展:
// 1、需修改 @/layout/navBars/breadcrumb/setings.vue `getThemeConfig.tagsStyle` el-option
// 2、需修改 @/layout/navBars/tagsView/tagsView.vue 代码最底部注释部分 css 样式
tagsStyle: 'tags-style-one',
// 主页面切换动画:可选值"<slide-right|slide-left|opacitys>",默认 slide-right
animation: 'slide-right',
// 分栏高亮风格:可选值"<columns-round|columns-card>",默认 columns-round
columnsAsideStyle: 'columns-round',
// 分栏布局风格:可选值"<columns-horizontal|columns-vertical>",默认 columns-horizontal
columnsAsideLayout: 'columns-vertical',
/**
* 布局切换
* 注意:为了演示,切换布局时,颜色会被还原成默认,代码位置:/@/layout/navBars/breadcrumb/setings.vue
* 中的 `initSetLayoutChange(设置布局切换,重置主题样式)` 方法
*/
// 布局切换:可选值"<defaults|classic|transverse|columns>",默认 defaults
layout: 'defaults',
/**
* 全局网站标题 / 副标题
*/
// 网站主标题(菜单导航、浏览器当前网页标题)
globalTitle: '数字校园教育管理平台',
// 网站副标题(登录页顶部文字)
globalViceTitle: '数字校园教育管理平台',
// 网站描述(登录页顶部文字)
globalViceDes: '数字校园教育管理平台',
// 默认初始语言,可选值"<zh-cn|en|zh-tw>",默认 zh-cn
globalI18n: 'zh-cn',
// 默认全局组件大小,可选值"<|medium|small|mini>",默认 ''
globalComponentSize: 'mini',
},
},
mutations: {
// 设置布局配置
getThemeConfig(state, data) {
state.themeConfig = data;
},
},
actions: {
// 设置布局配置
setThemeConfig({ commit }, data) {
commit('getThemeConfig', data);
},
},
};
export default themeConfigModule;
+39
View File
@@ -0,0 +1,39 @@
import { Session } from '@/utils/storage.js';
const userInfosModule = {
namespaced: true,
state: {
userInfos: {},
userInfosDD:{}
},
mutations: {
// 设置用户信息
getUserInfos(state, data) {
state.userInfos = data;
},
// 设置钉钉用户信息
setUserInfosDD(state, data) {
state.userInfosDD = data;
},
},
actions: {
// 设置用户信息
async setUserInfos({ commit }, data) {
if (data) {
commit('getUserInfos', data);
} else {
if (Session.get('userInfo')) commit('getUserInfos', Session.get('userInfo'));
}
},
// 设置钉钉用户信息
async setUserInfosDD({ commit }, data) {
if (data) {
commit('setUserInfosDD', data);
} else {
if (Session.get('setUserInfosDD')) commit('setUserInfosDD', Session.get('setUserInfosDD'));
}
},
},
};
export default userInfosModule;
+240
View File
@@ -0,0 +1,240 @@
/* 初始化样式
------------------------------- */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
outline: none;
}
:root {
--prev-bg-menuBar: #545c64;
--prev-bg-menuBarColor: #eaeaea;
--prev-bg-topBar: #ffffff;
--prev-bg-topBarColor: #606266;
--prev-bg-columnsMenuBar: #545c64;
--prev-bg-columnsMenuBarColor: #e6e6e6;
--prev-bg-main-color: #f8f8f8;
--prev-bg-color: #f5f7fa;
--prev-bg-white: #ffffff;
--prev-color-primary: #409eff;
--prev-color-text-white: #ffffff;
--prev-color-text-black: #000000;
--prev-color-text-primary: #303133;
--prev-color-text-regular: #606266;
--prev-color-text-secondary: #909399;
--prev-color-text-placeholder: #c0c4cc;
--prev-color-hover: rgba(0, 0, 0, 0.04);
--prev-color-seting-main: #e9eef3;
--prev-color-seting-aside: #d3dce6;
--prev-color-seting-header: #b3c0d1;
--prev-border-color-hover: #c0c4cc;
--prev-border-color-base: #dcdfe6;
--prev-border-color-light: #e4e7ed;
--prev-border-color-lighter: #ebeef5;
--prev-border-color-extra-light: #f2f6fc;
}
html,
body,
#app {
width: 100%;
height: 100%;
background-color: var(--prev-bg-main-color);
font-size: 14px;
}
/* 主布局样式
------------------------------- */
.layout-container {
width: 100%;
height: 100%;
.layout-aside {
background: var(--prev-bg-menuBar);
box-shadow: 2px 0 6px rgb(0 21 41 / 1%);
height: inherit;
position: relative;
z-index: 1;
display: flex;
flex-direction: column;
overflow-x: hidden !important;
.el-scrollbar__view {
overflow: hidden;
}
}
.layout-header {
padding: 0 !important;
}
.layout-main {
padding: 0 !important;
overflow: hidden;
width: 100%;
background-color: var(--prev-bg-main-color);
}
.el-scrollbar {
width: 100%;
}
.layout-view-bg-white {
background: var(--prev-bg-white);
width: 100%;
height: 100%;
border-radius: 4px;
border: 1px solid var(--prev-border-color-lighter);
}
.layout-el-aside-br-color {
border-right: 1px solid rgb(238, 238, 238);
}
.layout-aside-width-default {
width: 220px !important;
transition: width 0.3s ease;
}
.layout-aside-width64 {
width: 64px !important;
transition: width 0.3s ease;
}
.layout-aside-width1 {
width: 1px !important;
transition: width 0.3s ease;
}
.layout-scrollbar {
@extend .el-scrollbar;
padding: 15px;
}
.layout-mian-height-50 {
height: calc(100vh - 50px);
}
.layout-columns-warp {
flex: 1;
display: flex;
overflow: hidden;
}
.layout-hide {
display: none;
}
}
/* 进度条颜色
------------------------------- */
#nprogress .bar {
background: var(--prev-color-primary) !important;
}
/* flex 弹性布局
------------------------------- */
.flex {
display: flex;
}
.flex-auto {
flex: 1;
}
.flex-center {
@extend .flex;
flex-direction: column;
width: 100%;
overflow: hidden;
}
.flex-margin {
margin: auto;
}
.flex-warp {
display: flex;
flex-wrap: wrap;
align-content: flex-start;
margin: 0 -5px;
.flex-warp-item {
padding: 5px;
.flex-warp-item-box {
width: 100%;
height: 100%;
}
}
}
/* 宽高 100%
------------------------------- */
.w100 {
width: 100% !important;
}
.h100 {
height: 100% !important;
}
.vh100 {
height: 100vh !important;
}
.max100vh {
max-height: 100vh !important;
}
.min100vh {
min-height: 100vh !important;
}
/* 颜色值
------------------------------- */
.color-primary {
color: var(--prev-color-primary);
}
.color-success {
color: var(--prev-color-success);
}
.color-warning {
color: var(--prev-color-warning);
}
.color-danger {
color: var(--prev-color-danger);
}
.color-info {
color: var(--prev-color-info);
}
/* 溢出省略号
------------------------------- */
.one-text-overflow {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.two-text-overflow {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
}
.overflow {
overflow: hidden !important;
}
/* 字体大小全局样式
------------------------------- */
@for $i from 10 through 32 {
.font#{$i} {
font-size: #{$i}px !important;
}
}
/* 外边距、内边距全局样式
------------------------------- */
@for $i from 5 through 35 {
.mt#{$i} {
margin-top: #{$i}px !important;
}
.mr#{$i} {
margin-right: #{$i}px !important;
}
.mb#{$i} {
margin-bottom: #{$i}px !important;
}
.ml#{$i} {
margin-left: #{$i}px !important;
}
.pt#{$i} {
padding-top: #{$i}px !important;
}
.pr#{$i} {
padding-right: #{$i}px !important;
}
.pb#{$i} {
padding-bottom: #{$i}px !important;
}
.pl#{$i} {
padding-left: #{$i}px !important;
}
}
+1
View File
@@ -0,0 +1 @@
@import 'common/transition.scss';
+102
View File
@@ -0,0 +1,102 @@
/* 页面切换动画
------------------------------- */
.slide-right-enter-active,
.slide-right-leave-active,
.slide-left-enter-active,
.slide-left-leave-active {
will-change: transform;
transition: all 0.3s ease;
}
// slide-right
.slide-right-enter {
opacity: 0;
transform: translateX(-20px);
}
.slide-right-leave-active {
opacity: 0;
transform: translateX(20px);
}
// slide-left
.slide-left-enter-from {
@extend .slide-right-leave-active;
}
.slide-left-leave-to {
@extend .slide-right-enter;
}
// opacitys
.opacitys-enter-active,
.opacitys-leave-active {
will-change: transform;
transition: all 0.3s ease;
}
.opacitys-enter,
.opacitys-leave-active {
opacity: 0;
}
/* Breadcrumb 面包屑过渡动画
------------------------------- */
.breadcrumb-enter-active,
.breadcrumb-leave-active {
transition: all 0.3s;
}
.breadcrumb-enter,
.breadcrumb-leave-active {
opacity: 0;
transform: translateX(20px);
}
.breadcrumb-move {
transition: all 0.3s;
}
.breadcrumb-leave-active {
position: absolute;
}
/* logo 过渡动画
------------------------------- */
@keyframes logoAnimation {
0% {
transform: scale(0);
}
80% {
transform: scale(1.2);
}
100% {
transform: scale(1);
}
}
/* 404、401 过渡动画
------------------------------- */
@keyframes error-num {
0% {
transform: translateY(60px);
opacity: 0;
}
100% {
transform: translateY(0);
opacity: 1;
}
}
@keyframes error-img {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
/* 左右左 link.vue
------------------------------- */
@keyframes toRight {
0% {
left: -5px;
}
50% {
left: 100%;
}
100% {
left: -5px;
}
}
+109
View File
@@ -0,0 +1,109 @@
/* 深色模式样式
------------------------------- */
[data-theme='dark'] {
--prev-bg-menuBar: #191919 !important;
--prev-bg-menuBarColor: #dadada !important;
--prev-bg-topBar: #191919 !important;
--prev-bg-topBarColor: #dadada !important;
--prev-bg-columnsMenuBar: #191919 !important;
--prev-bg-columnsMenuBarColor: #dadada !important;
--prev-bg-main-color: #1f1f1f !important;
--prev-bg-color: rgba(0, 0, 0, 0.3) !important;
--prev-bg-white: #191919 !important;
--prev-color-text-black: #ffffff !important;
--prev-color-text-primary: #dadada !important;
--prev-color-text-regular: #dadada !important;
--prev-color-text-secondary: #a3a3a3 !important;
--prev-color-hover: rgba(0, 0, 0, 0.3) !important;
--prev-color-seting-main: #505050 !important;
--prev-color-seting-aside: #3c3c3c !important;
--prev-color-seting-header: #303030 !important;
--prev-border-color-hover: #616161 !important;
--prev-border-color-base: #333333 !important;
--prev-border-color-light: #333333 !important;
--prev-border-color-lighter: #333333 !important;
--prev-border-color-extra-light: #333333 !important;
// menu
.layout-aside {
border-right: 1px solid var(--prev-border-color-lighter) !important;
}
// drawer
.el-drawer {
border-left: 1px solid var(--prev-border-color-lighter) !important;
}
// button
.el-button--default {
background: var(--prev-bg-white);
color: var(--prev-color-text-primary);
border-color: var(--prev-border-color-lighter);
&:hover,
&:focus {
color: var(--prev-color-primary) !important;
background: var(--prev-color-primary-light-8) !important;
border-color: var(--prev-color-primary-light-6) !important;
}
&:focus {
border-color: var(--prev-color-primary-light-1) !important;
}
&:active {
border-color: var(--prev-color-primary-light-6) !important;
}
}
// tag
.el-tag.el-tag--info {
background-color: var(--prev-bg-white) !important;
border-color: var(--prev-border-color-light) !important;
color: var(--prev-color-text-regular) !important;
}
// switch
.el-switch:not(.is-checked) {
.el-switch__core {
border-color: var(--prev-border-color-base) !important;
background-color: var(--prev-border-color-base) !important;
}
}
// TimePicker
.el-time-spinner__item.active:not(.disabled) {
color: var(--prev-color-primary) !important;
}
// date
.el-date-table td.in-range div,
.el-date-table td.in-range div:hover,
.el-date-table.is-week-mode .el-date-table__row.current div,
.el-date-table.is-week-mode .el-date-table__row:hover div,
.el-date-table td.selected div,
.el-month-table td.in-range div,
.el-month-table td.in-range div:hover {
background-color: var(--prev-bg-color) !important;
}
// transfer
.el-transfer-panel,
.el-transfer-panel .el-transfer-panel__header {
background-color: var(--prev-bg-color) !important;
}
// loading
.el-loading-mask {
background-color: var(--prev-bg-color) !important;
}
// dropdown
.el-dropdown-menu__item:focus,
.el-dropdown-menu__item:not(.is-disabled):hover {
background-color: var(--prev-color-hover) !important;
}
// dialog
.el-dialog,
.el-calendar {
border: 1px solid var(--prev-border-color-lighter);
}
}
+219
View File
@@ -0,0 +1,219 @@
/* 防止页面切换时,滚动条高度不变的问题(滚动条高度非滚动条滚动高度)
------------------------------- */
.el-scrollbar {
overflow: hidden;
position: relative;
height: 100%;
}
.el-scrollbar__wrap {
overflow: auto !important;
overflow-x: hidden !important;
max-height: 100%; /*防止页面切换时,滚动条高度不变的问题(滚动条高度非滚动条滚动高度)*/
}
.el-select-dropdown .el-scrollbar__wrap {
overflow-x: scroll !important;
}
.el-select-dropdown__wrap {
max-height: 274px !important; /*修复Select 选择器高度问题*/
}
.el-autocomplete-suggestion__wrap {
max-height: 280px !important;
}
/* Button 按钮
------------------------------- */
// 第三方字体图标大小
.el-button i.iconfont,
.el-button i.fa {
font-size: 14px !important;
margin-right: 5px;
}
.el-button--medium i.iconfont,
.el-button--medium i.fa {
font-size: 14px !important;
margin-right: 5px;
}
.el-button--small i.iconfont,
.el-button--small i.fa {
font-size: 12px !important;
margin-right: 5px;
}
.el-button--mini i.iconfont,
.el-button--mini i.fa {
font-size: 12px !important;
margin-right: 5px;
}
/* Dialog 对话框
------------------------------- */
.el-overlay,
.el-dialog__wrapper {
display: flex;
align-items: center;
justify-content: center;
.el-dialog {
margin: 0 auto !important;
.el-dialog__body {
padding: 20px !important;
}
}
}
.el-dialog__body {
max-height: calc(90vh - 111px) !important;
overflow-y: auto;
overflow-x: hidden;
}
/* Alert 警告
------------------------------- */
.el-alert--warning.is-light {
border: 1px solid rgba(230, 162, 60, 0.3) !important;
}
.el-alert--success.is-light {
border: 1px solid rgba(103, 194, 58, 0.3) !important;
}
.el-alert--info.is-light {
border: 1px solid rgba(144, 147, 153, 0.3) !important;
}
.el-alert--error.is-light {
border: 1px solid rgba(245, 108, 108, 0.3) !important;
}
/* Table 表格
------------------------------- */
.el-table-column--selection {
.el-checkbox {
margin-right: unset !important;
}
}
.el-table::before,
.el-table--group::after,
.el-table--border::after {
z-index: 99 !important;
}
/* 下拉选择器/时间选择器滚动条
------------------------------- */
.el-select-dropdown .el-scrollbar__wrap,
.el-picker-panel .el-scrollbar__wrap {
overflow-x: scroll !important;
}
/* NavMenu 导航菜单
------------------------------- */
// 默认样式修改
.el-menu {
border-right: none !important;
}
.el-menu-item,
.el-submenu__title {
height: 50px !important;
line-height: 50px !important;
color: var(--prev-bg-menuBarColor) !important;
transition: none !important;
}
// horizontal 水平方向时
.el-menu--horizontal > .el-menu-item.is-active,
.el-menu--horizontal > .el-submenu.is-active .el-submenu__title {
border-bottom: 3px solid !important;
border-bottom-color: var(--prev-color-primary) !important;
color: var(--prev-color-primary) !important;
}
.el-menu--horizontal .el-menu-item:not(.is-disabled):focus,
.el-menu--horizontal .el-menu-item:not(.is-disabled):hover,
.el-menu--horizontal > .el-submenu:focus .el-submenu__title,
.el-menu--horizontal > .el-submenu:hover .el-submenu__title,
.el-menu--horizontal .el-menu .el-menu-item.is-active,
.el-menu--horizontal .el-menu .el-submenu.is-active > .el-submenu__title {
color: var(--prev-color-primary) !important;
}
.el-menu.el-menu--horizontal {
border-bottom: none !important;
}
.el-menu--horizontal > .el-menu-item,
.el-menu--horizontal > .el-submenu .el-submenu__title {
color: var(--bg-topBarColor) !important;
}
// 外部链接时
.el-menu-item a,
.el-menu-item a:hover,
.el-menu-item i,
.el-submenu__title i {
color: inherit;
text-decoration: none;
}
.el-menu-item a {
width: 86%;
display: inline-block;
}
// 默认 hover 时
.el-menu-item:hover,
.el-submenu__title:hover {
color: var(--prev-color-primary) !important;
background-color: transparent !important;
i {
color: var(--prev-color-primary) !important;
}
}
// 高亮时
.el-menu-item.is-active {
color: var(--prev-color-primary) !important;
}
.el-active-extend {
color: #ffffff !important;
background-color: var(--prev-color-primary) !important;
i {
color: #ffffff !important;
}
}
#add-is-active {
@extend .el-active-extend;
&:hover {
@extend .el-active-extend;
}
}
// 菜单收起时且是a链接
.is-dark a {
color: #ffffff !important;
text-decoration: none;
}
// 菜单收起时鼠标经过背景颜色/字体颜色
.el-menu--vertical {
background: var(--prev-bg-menuBar) !important;
}
.el-menu--horizontal {
.el-menu {
background: var(--bg-topBar) !important;
}
.el-menu-item,
.el-submenu__title {
color: var(--bg-topBarColor);
}
}
// 第三方图标字体间距/大小设置
.el-menu-item .iconfont,
.el-submenu .iconfont,
.el-menu-item .fa,
.el-submenu__title .fa {
font-size: 14px !important;
display: inline-block;
vertical-align: middle;
margin-right: 5px;
width: 24px;
text-align: center;
}
// element plus 本身字体图标
.el-submenu [class^='el-icon-'],
.el-menu-item [class^='el-icon-'] {
font-size: 14px !important;
}
// 去掉离开浏览器时,菜单的默认高亮
.el-menu-item:focus {
background-color: transparent !important;
}
/* Alert 警告
------------------------------- */
.el-alert__title {
word-break: break-all;
}
+7
View File
@@ -0,0 +1,7 @@
@import './base.scss';
@import './app.scss';
@import './other.scss';
@import './element.scss';
@import './media/media.scss';
@import './variables.scss';
@import './dark.scss';
+56
View File
@@ -0,0 +1,56 @@
.loading-prev {
width: 100%;
height: 100%;
position: fixed;
top: 0;
left: 0;
z-index: 2;
background-color: var(--prev-bg-white);
}
.loading-prev .loading-prev-box {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.loading-prev .loading-prev-box-warp {
width: 80px;
height: 80px;
}
.loading-prev .loading-prev-box-warp .loading-prev-box-item {
width: 33.333333%;
height: 33.333333%;
background: var(--prev-color-primary);
float: left;
animation: loading-prev-animation 1.2s infinite ease;
border-radius: 1px;
}
.loading-prev .loading-prev-box-warp .loading-prev-box-item:nth-child(7) {
animation-delay: 0s;
}
.loading-prev .loading-prev-box-warp .loading-prev-box-item:nth-child(4),
.loading-prev .loading-prev-box-warp .loading-prev-box-item:nth-child(8) {
animation-delay: 0.1s;
}
.loading-prev .loading-prev-box-warp .loading-prev-box-item:nth-child(1),
.loading-prev .loading-prev-box-warp .loading-prev-box-item:nth-child(5),
.loading-prev .loading-prev-box-warp .loading-prev-box-item:nth-child(9) {
animation-delay: 0.2s;
}
.loading-prev .loading-prev-box-warp .loading-prev-box-item:nth-child(2),
.loading-prev .loading-prev-box-warp .loading-prev-box-item:nth-child(6) {
animation-delay: 0.3s;
}
.loading-prev .loading-prev-box-warp .loading-prev-box-item:nth-child(3) {
animation-delay: 0.4s;
}
@keyframes loading-prev-animation {
0%,
70%,
100% {
transform: scale3D(1, 1, 1);
}
35% {
transform: scale3D(0, 0, 1);
}
}
+12
View File
@@ -0,0 +1,12 @@
@import './index.scss';
/* 页面宽度小于800px
------------------------------- */
@media screen and (max-width: 800px) {
.el-dialog {
width: 90%;
}
.el-dialog.is-fullscreen {
width: 100% !important;
}
}
+35
View File
@@ -0,0 +1,35 @@
@import './index.scss';
/* 页面宽度小于768px
------------------------------- */
@media screen and (max-width: $sm) {
.error {
.error-flex {
flex-direction: column-reverse !important;
height: auto !important;
width: 100% !important;
}
.right,
.left {
flex: unset !important;
display: flex !important;
}
.left-item {
margin: auto !important;
}
.right img {
max-width: 450px !important;
@extend .left-item;
}
}
}
/* 页面宽度大于768px小于992px
------------------------------- */
@media screen and (min-width: $sm) and (max-width: $md) {
.error {
.error-flex {
padding-left: 30px !important;
}
}
}
+19
View File
@@ -0,0 +1,19 @@
@import './index.scss';
/* 页面宽度小于576px
------------------------------- */
@media screen and (max-width: $xs) {
.el-form-item__label {
width: 100% !important;
text-align: left !important;
}
.el-form-item__content {
margin-left: 0 !important;
}
.el-form-item {
display: unset !important;
}
.login-form .el-form-item {
display: block !important;
}
}
+35
View File
@@ -0,0 +1,35 @@
@import './index.scss';
/* 页面宽度小于1200px
------------------------------- */
@media screen and (max-width: $lg) {
.home-recommend-row {
.home-recommend {
margin-bottom: 15px;
}
& .el-col:last-of-type,
& .el-col:nth-last-child(2) {
.home-recommend {
margin-bottom: 0;
}
}
}
.home-lg {
margin-bottom: 15px;
}
}
/* 页面宽度小于992px
------------------------------- */
@media screen and (max-width: $md) {
.home-recommend-row {
& .el-col:nth-last-child(2) {
margin-bottom: 15px;
}
& .el-col:last-of-type {
.home-recommend {
margin-bottom: 0;
}
}
}
}
+37
View File
@@ -0,0 +1,37 @@
/* 栅格布局(媒体查询变量)
* $xs <768px 响应式栅格
* $sm ≥768px 响应式栅格
* $md ≥992px 响应式栅格
* $lg ≥1200px 响应式栅格
* $xl ≥1920px 响应式栅格
------------------------------- */
$xs: 576px;
$sm: 768px;
$md: 992px;
$lg: 1200px;
$xl: 1920px;
/* 页面宽度小于576px
------------------------------- */
@media screen and (max-width: $xs) {
}
/* 页面宽度小于768px
------------------------------- */
@media screen and (max-width: $sm) {
}
/* 页面宽度大于768px小于992px
------------------------------- */
@media screen and (min-width: $sm) and (max-width: $md) {
}
/* 页面宽度大于992px小于1200px
------------------------------- */
@media screen and (min-width: $md) and (max-width: $lg) {
}
/* 页面宽度大于1920px
------------------------------- */
@media screen and (min-width: $xl) {
}
+55
View File
@@ -0,0 +1,55 @@
@import './index.scss';
/* 页面宽度小于576px
------------------------------- */
@media screen and (max-width: $xs) {
// MessageBox 弹框
.el-message-box {
width: 80% !important;
}
}
/* 页面宽度小于768px
------------------------------- */
@media screen and (max-width: $sm) {
// Breadcrumb 面包屑
.layout-navbars-breadcrumb-hide {
display: none;
}
// 外链视图
.layout-view-link {
a {
max-width: 80%;
text-align: center;
}
}
// 菜单搜索
.layout-search-dialog {
.el-autocomplete {
width: 80% !important;
}
}
}
/* 页面宽度小于1000px
------------------------------- */
@media screen and (max-width: 1000px) {
// 布局配置
.layout-drawer-content-flex {
position: relative;
&::after {
content: '手机版不支持切换布局';
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 1;
text-align: center;
height: 140px;
line-height: 140px;
background: rgba(255, 255, 255, 0.9);
color: #666666;
}
}
}
+32
View File
@@ -0,0 +1,32 @@
@import './index.scss';
/* 页面宽度小于576px
------------------------------- */
@media screen and (max-width: $xs) {
.login-weaper {
height: 420px !important;
.login-left {
display: none !important;
}
.login-right {
width: 100% !important;
border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
.login-main {
width: 94% !important;
}
}
}
}
/* 页面宽度大于576px小于992px
------------------------------- */
@media screen and (min-width: $xs) and (max-width: $md) {
.login-left {
display: none !important;
}
.login-right {
border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
}
}
+7
View File
@@ -0,0 +1,7 @@
@import './login.scss';
@import './error.scss';
@import './home.scss';
@import './layout.scss';
@import './scrollbar.scss';
@import './dialog.scss';
@import './form.scss';
+13
View File
@@ -0,0 +1,13 @@
@import './index.scss';
/* 页面宽度小于768px
------------------------------- */
@media screen and (max-width: $sm) {
// element plus scrollbar
.el-scrollbar__bar.is-vertical {
width: 2px !important;
}
.el-scrollbar__bar.is-horizontal {
height: 2px !important;
}
}
View File
+952
View File
@@ -0,0 +1,952 @@
/* Button 按钮
------------------------------- */
// text
.el-button--text {
color: var(--prev-color-primary);
&:focus,
&:hover {
color: var(--prev-color-primary-light-3);
}
}
.el-button--text:active {
color: var(--prev-color-primary-light-3);
}
// default
.el-button--default:hover,
.el-button--default:focus {
color: var(--prev-color-primary);
background: var(--prev-color-primary-light-8);
border-color: var(--prev-color-primary-light-6);
}
.el-button--default.is-plain:hover,
.el-button--default.is-plain:focus {
color: var(--prev-color-primary);
background: var(--prev-bg-white);
border-color: var(--prev-color-primary-light-1);
}
.el-button--default:active {
color: var(--prev-color-primary);
background: var(--prev-bg-white);
border-color: var(--prev-color-primary-light-1);
}
// primary
.el-button--primary {
color: var(--prev-color-text-white) !important;
background: var(--prev-color-primary) !important;
border-color: var(--prev-color-primary) !important;
&:hover,
&:focus {
color: var(--prev-color-text-white) !important;
background: var(--prev-color-primary-light-3) !important;
border-color: var(--prev-color-primary-light-3) !important;
}
}
.el-button--primary.is-plain {
color: var(--prev-color-primary) !important;
background: var(--prev-color-primary-light-8) !important;
border-color: var(--prev-color-primary-light-6) !important;
&:hover,
&:focus {
color: var(--prev-color-text-white) !important;
background: var(--prev-color-primary) !important;
border-color: var(--prev-color-primary) !important;
}
}
.el-button--primary.is-disabled,
.el-button--primary.is-disabled:active,
.el-button--primary.is-disabled:focus,
.el-button--primary.is-disabled:hover {
color: var(--prev-color-primary) !important;
background: var(--prev-color-primary-light-7) !important;
border-color: var(--prev-color-primary-light-7) !important;
}
.el-button--primary.is-active,
.el-button--primary:active {
color: var(--prev-color-text-white) !important;
background: var(--prev-color-primary) !important;
border-color: var(--prev-color-primary) !important;
}
.el-button.is-disabled.is-plain,
.el-button.is-disabled.is-plain:focus,
.el-button.is-disabled.is-plain:hover {
background-color: var(--prev-bg-white);
border-color: var(--prev-border-color-lighter);
color: var(--prev-color-text-placeholder);
}
/* Link 文字链接
------------------------------- */
// default
.el-link.el-link--default:hover {
color: var(--prev-color-primary-light-3);
}
// primary
.el-link.el-link--primary {
color: var(--prev-color-primary);
&:hover {
color: var(--prev-color-primary-light-3);
}
}
.el-link.el-link--default::after,
.el-link.is-underline:hover::after,
.el-link.el-link--primary.is-underline:hover::after,
.el-link.el-link--primary::after {
border-color: var(--prev-color-primary);
}
/* Radio 单选框
------------------------------- */
.el-radio,
.el-checkbox {
color: var(--prev-color-text-regular);
}
.el-radio__input.is-checked + .el-radio__label,
.el-radio-button__inner:hover {
color: var(--prev-color-primary);
}
.el-radio__input.is-checked .el-radio__inner {
background-color: var(--prev-color-primary);
border-color: var(--prev-color-primary);
}
.el-radio-button__orig-radio:checked + .el-radio-button__inner {
color: var(--prev-color-text-white);
background-color: var(--prev-color-primary);
border-color: var(--prev-color-primary);
box-shadow: -1px 0 0 0 var(--prev-color-primary);
}
.el-radio.is-bordered.is-checked,
.el-radio__inner:hover {
border-color: var(--prev-color-primary);
}
.el-radio-button__inner,
.el-checkbox-button__inner {
background-color: var(--prev-bg-white);
color: var(--prev-color-text-regular);
border-color: var(--prev-border-color-base);
}
.el-radio-button:first-child .el-radio-button__inner,
.el-checkbox-button:first-child .el-checkbox-button__inner {
border-left-color: var(--prev-border-color-base);
}
.el-radio.is-bordered,
.el-checkbox.is-bordered {
border-color: var(--prev-border-color-base);
}
/* Checkbox 多选框
------------------------------- */
.el-checkbox__input.is-checked + .el-checkbox__label,
.el-checkbox-button__inner:hover {
color: var(--prev-color-primary);
}
.el-checkbox__input.is-checked .el-checkbox__inner {
background-color: var(--prev-color-primary);
border-color: var(--prev-color-primary);
}
.el-checkbox__input.is-focus .el-checkbox__inner,
.el-checkbox__inner:hover,
.el-checkbox.is-bordered.is-checked,
.el-checkbox-button.is-focus .el-checkbox-button__inner {
border-color: var(--prev-color-primary);
}
.el-checkbox-button.is-checked .el-checkbox-button__inner {
color: var(--prev-color-text-white);
background-color: var(--prev-color-primary);
border-color: var(--prev-color-primary);
box-shadow: -1px 0 0 0 var(--prev-color-primary);
}
.el-checkbox-button.is-checked:first-child .el-checkbox-button__inner {
border-left-color: var(--prev-color-primary);
}
.el-checkbox__input.is-checked .el-checkbox__inner,
.el-checkbox__input.is-indeterminate .el-checkbox__inner {
background-color: var(--prev-color-primary);
border-color: var(--prev-color-primary);
}
.el-checkbox-button.is-disabled .el-checkbox-button__inner {
background-color: var(--prev-bg-white);
border-color: var(--prev-border-color-base);
}
/* Input 输入框、InputNumber 计数器
------------------------------- */
// input-number
.el-input__inner:focus,
.el-input-number__decrease:hover:not(.is-disabled) ~ .el-input .el-input__inner:not(.is-disabled),
.el-input-number__increase:hover:not(.is-disabled) ~ .el-input .el-input__inner:not(.is-disabled),
.el-textarea__inner:focus {
border-color: var(--prev-color-primary) !important;
}
.el-input-number__increase:hover,
.el-input-number__decrease:hover {
color: var(--prev-color-primary);
}
.el-input-number__decrease,
.el-input-number__increase {
background-color: var(--prev-bg-color);
border-color: var(--prev-border-color-base) !important;
}
// input
.el-input__inner,
.el-textarea__inner {
background-color: var(--prev-bg-white);
border-color: var(--prev-border-color-base);
color: var(--prev-color-text-regular);
&:hover {
border-color: var(--prev-border-color-hover);
}
}
.el-input.is-disabled .el-input__inner,
.el-textarea.is-disabled .el-textarea__inner {
background-color: var(--prev-bg-white);
border-color: var(--prev-border-color-base);
}
.el-input-group__append,
.el-input-group__prepend {
background-color: var(--prev-bg-color);
color: var(--prev-color-text-regular);
border-color: var(--prev-border-color-base);
}
.el-input .el-input__count .el-input__count-inner {
background-color: var(--prev-bg-color);
}
// autocomplete
.el-autocomplete-suggestion {
background-color: var(--prev-bg-white);
border-color: var(--prev-border-color-base);
}
.el-autocomplete-suggestion__wrap {
max-height: 280px !important;
}
// scss 循环
$positions: 'top', 'right', 'bottom', 'left';
@each $i in $positions {
.el-popper[x-placement^='#{$i}'] .popper__arrow {
border-#{$i}-color: var(--prev-border-color-base);
&::after {
border-#{$i}-color: var(--prev-bg-white);
}
}
}
.el-autocomplete-suggestion li {
color: var(--prev-color-text-regular);
}
.el-autocomplete-suggestion li.highlighted,
.el-autocomplete-suggestion li:hover {
background-color: var(--prev-color-hover);
}
/* Select 选择器
------------------------------- */
.el-range-editor.is-active,
.el-range-editor.is-active:hover,
.el-select .el-input.is-focus .el-input__inner,
.el-select .el-input__inner:focus {
border-color: var(--prev-color-primary);
}
.el-select-dropdown__item.selected {
color: var(--prev-color-primary);
}
.el-select-dropdown {
background-color: var(--prev-bg-white);
border-color: var(--prev-border-color-light);
}
.el-select-dropdown__item {
color: var(--prev-color-text-regular);
}
.el-select-dropdown__item.hover,
.el-select-dropdown__item:hover {
background-color: var(--prev-color-hover);
}
.el-select-dropdown__item.is-disabled:hover {
background-color: var(--prev-bg-white);
}
.el-select .el-input.is-disabled .el-input__inner:hover {
border-color: var(--prev-border-color-light);
}
.el-select:hover .el-input__inner {
border-color: var(--prev-border-color-hover);
}
.el-select-dropdown.is-multiple .el-select-dropdown__item.selected {
background-color: var(--prev-bg-white);
}
.el-select-dropdown.is-multiple .el-select-dropdown__item.selected.hover {
background-color: var(--prev-color-hover);
}
.el-select-group__wrap:not(:last-of-type)::after {
background: var(--prev-border-color-light);
}
/* Cascader 级联选择器
------------------------------- */
.el-cascader .el-input .el-input__inner:focus,
.el-cascader .el-input.is-focus .el-input__inner {
border-color: var(--prev-color-primary);
}
.el-cascader-node.in-active-path,
.el-cascader-node.is-active,
.el-cascader-node.is-selectable.in-checked-path {
color: var(--prev-color-primary);
}
.el-cascader__dropdown {
background-color: var(--prev-bg-white);
border-color: var(--prev-border-color-light);
}
.el-cascader-menu {
border-color: var(--prev-border-color-light);
color: var(--prev-color-text-regular);
}
.el-cascader-node:not(.is-disabled):focus,
.el-cascader-node:not(.is-disabled):hover {
background-color: var(--prev-color-hover);
}
/* Switch 开关
------------------------------- */
.el-switch.is-checked .el-switch__core {
border-color: var(--prev-color-primary);
background-color: var(--prev-color-primary);
}
.el-switch__label.is-active {
color: var(--prev-color-primary);
}
/* Slider 滑块
------------------------------- */
.el-slider__bar {
background-color: var(--prev-color-primary);
}
.el-slider__button {
border-color: var(--prev-color-primary);
}
.el-slider__runway {
background-color: var(--prev-border-color-light);
}
.el-slider__marks-text {
color: var(--prev-color-text-secondary);
}
/* TimePicker 时间选择器
------------------------------- */
.el-time-panel__btn.confirm,
.el-time-spinner__arrow:hover,
.time-select-item.selected:not(.disabled) {
color: var(--prev-color-primary);
}
.el-picker-panel {
border-color: var(--prev-border-color-light);
background-color: var(--prev-bg-white);
color: var(--prev-color-text-regular);
}
.time-select-item:hover,
.el-time-spinner__item:hover:not(.disabled):not(.active),
.el-time-spinner__wrapper.is-arrow .el-time-spinner__item:hover:not(.disabled):not(.active) {
background-color: var(--prev-color-hover);
}
.el-time-panel {
border-color: var(--prev-border-color-light);
background-color: var(--prev-bg-white);
}
.el-time-panel__footer,
.el-time-panel__content::after,
.el-time-panel__content::before,
.el-time-range-picker__body {
border-color: var(--prev-border-color-light);
}
.el-time-panel__btn,
.el-date-editor .el-range-separator {
color: var(--prev-color-text-primary);
}
.el-date-editor .el-range-input {
background-color: var(--prev-bg-white);
color: var(--prev-color-text-primary);
}
/* DatePicker 日期选择器
------------------------------- */
.el-date-table td.today span,
.el-date-table td.available:hover,
.el-date-picker__header-label.active,
.el-date-picker__header-label:hover,
.el-picker-panel__icon-btn:hover,
.el-year-table td.today .cell,
.el-year-table td .cell:hover,
.el-year-table td.current:not(.disabled) .cell,
.el-month-table td .cell:hover,
.el-month-table td.today .cell,
.el-month-table td.current:not(.disabled) .cell,
.el-picker-panel__shortcut:hover {
color: var(--prev-color-primary);
}
.el-date-table td.current:not(.disabled) span,
.el-date-table td.selected span {
color: var(--prev-color-text-white);
background-color: var(--prev-color-primary);
}
.el-date-table td.end-date span,
.el-date-table td.start-date span,
.el-month-table td.end-date .cell,
.el-month-table td.start-date .cell {
background-color: var(--prev-color-primary);
}
.el-date-table td.in-range div,
.el-date-table td.in-range div:hover,
.el-date-table.is-week-mode .el-date-table__row.current div,
.el-date-table.is-week-mode .el-date-table__row:hover div,
.el-date-table td.selected div {
background-color: var(--prev-color-primary-light-9);
}
.el-date-table th,
.el-date-picker__header--bordered,
.el-date-range-picker__content.is-left,
.el-date-picker__time-header,
.el-date-range-picker__time-header {
border-color: var(--prev-border-color-lighter);
}
.el-date-table th,
.el-date-picker__header-label,
.el-picker-panel__shortcut,
.el-month-table td .cell,
.el-year-table td .cell {
color: var(--prev-color-text-regular);
}
.el-date-table td.next-month,
.el-date-table td.prev-month {
color: var(--prev-border-color-hover);
}
.el-picker-panel__icon-btn {
color: var(--prev-color-text-primary);
}
.el-date-table td.disabled div {
background-color: var(--prev-bg-color);
}
.el-picker-panel [slot='sidebar'],
.el-picker-panel__sidebar,
.el-picker-panel__footer {
border-color: var(--prev-border-color-light);
background-color: var(--prev-bg-white);
}
.el-month-table td.end-date .cell,
.el-month-table td.start-date .cell {
color: var(--prev-color-text-white);
}
/* Upload 上传
------------------------------- */
.el-upload-list__item.is-success .el-upload-list__item-name:focus,
.el-upload-list__item.is-success .el-upload-list__item-name:hover,
.el-upload-list__item .el-icon-close-tip,
.el-upload-dragger .el-upload__text em {
color: var(--prev-color-primary);
}
.el-upload--picture-card,
.el-upload-dragger {
background-color: var(--prev-bg-white);
border-color: var(--prev-border-color-light);
i {
color: var(--prev-color-text-regular);
}
}
.el-upload--picture-card:hover,
.el-upload:focus {
color: var(--prev-color-primary);
border-color: var(--prev-color-primary);
}
.el-upload-dragger:hover,
.el-upload:focus .el-upload-dragger {
border-color: var(--prev-color-primary);
}
.el-upload__tip,
.el-upload-list__item,
.el-upload-dragger .el-upload__text,
.el-upload-list__item-name,
.el-upload-list__item .el-icon-close {
color: var(--prev-color-text-regular);
}
.el-upload-list__item:hover {
background-color: var(--prev-bg-color);
}
/* ColorPicker 颜色选择器
------------------------------- */
.el-color-picker__trigger {
border-color: var(--prev-border-color-light);
}
/* Transfer 穿梭框
------------------------------- */
.el-transfer-panel__item:hover {
color: var(--prev-color-primary);
}
.el-transfer-panel,
.el-transfer-panel .el-transfer-panel__header {
border-color: var(--prev-border-color-lighter);
}
.el-transfer-panel .el-transfer-panel__footer {
border-color: var(--prev-border-color-lighter);
background-color: var(--prev-bg-white);
}
.el-transfer-panel .el-transfer-panel__header .el-checkbox .el-checkbox__label {
color: var(--prev-color-text-primary);
}
/* Form 表单
------------------------------- */
.el-form {
.el-form-item:last-of-type {
margin-bottom: 0 !important;
}
}
.el-form-item__label {
color: var(--prev-color-text-regular);
}
/* Table 表格
------------------------------- */
.el-table {
color: var(--prev-color-text-regular);
}
.el-table .descending .sort-caret.descending {
border-top-color: var(--prev-color-primary);
}
.el-table .ascending .sort-caret.ascending {
border-bottom-color: var(--prev-color-primary);
}
.el-table thead {
color: var(--prev-color-text-secondary);
}
.el-table td.el-table__cell,
.el-table th.el-table__cell.is-leaf,
.el-table--border,
.el-table--group {
border-color: var(--prev-border-color-lighter) !important;
}
.el-table th.el-table__cell,
.el-table tr {
background-color: var(--prev-bg-white);
}
.el-table--striped .el-table__body tr.el-table__row--striped td.el-table__cell,
.el-table--enable-row-hover .el-table__body tr:hover > td.el-table__cell {
background-color: var(--prev-bg-color);
}
.el-table--border::after,
.el-table--group::after,
.el-table::before {
background-color: var(--prev-border-color-lighter);
}
/* Tag 标签
------------------------------- */
// primary
.el-tag {
color: var(--prev-color-primary);
background-color: var(--prev-color-primary-light-8);
border-color: var(--prev-color-primary-light-6);
}
.el-tag .el-tag__close {
color: var(--prev-color-primary);
&:hover {
color: var(--prev-color-text-white);
background-color: var(--prev-color-primary);
}
}
.el-tag--dark {
color: var(--prev-color-text-white);
background-color: var(--prev-color-primary);
}
.el-tag--dark .el-tag__close {
color: var(--prev-color-text-white);
&:hover {
background-color: var(--prev-color-primary-light-3);
}
}
.el-tag--plain {
color: var(--prev-color-primary);
background-color: var(--prev-bg-white);
border-color: var(--prev-color-primary-light-3);
}
/* Progress 进度条
------------------------------- */
// primary
.el-progress-bar__inner {
background-color: var(--prev-color-primary) !important;
}
.el-progress-bar__outer {
background-color: var(--prev-border-color-lighter);
}
.el-progress__text {
color: var(--prev-color-text-regular);
}
/* Tree 树形控件
------------------------------- */
.el-tree {
background-color: var(--prev-bg-white);
color: var(--prev-color-text-regular);
}
.el-tree-node__content:hover,
.el-tree-node:focus > .el-tree-node__content {
background-color: var(--prev-bg-color);
}
/* Pagination 分页
------------------------------- */
.el-pager li.active,
.el-pager li:hover,
.el-pagination button:hover,
.el-pagination.is-background .el-pager li:not(.disabled):hover {
color: var(--prev-color-primary);
}
.el-pagination__sizes .el-input .el-input__inner:hover {
border-color: var(--prev-color-primary);
}
.el-pagination.is-background .el-pager li:not(.disabled).active {
background-color: var(--prev-color-primary);
color: var(--prev-color-text-white);
}
.el-pagination__total,
.el-pagination__jump {
color: var(--prev-color-text-regular);
}
.el-pagination button:disabled,
.el-pagination .btn-next,
.el-pagination .btn-prev {
background-color: var(--prev-bg-white);
}
.el-pagination .btn-next,
.el-pagination .btn-prev {
color: var(--prev-color-text-primary);
}
.el-pager li {
background-color: var(--prev-bg-white);
color: var(--prev-color-text-primary);
}
/* Badge 标记
------------------------------- */
// primary
.el-badge__content--primary {
background-color: var(--prev-color-primary);
}
/* Loading 加载
------------------------------- */
.el-loading-spinner .path {
stroke: var(--prev-color-primary);
}
.el-loading-spinner .el-loading-text,
.el-loading-spinner i {
color: var(--prev-color-primary);
}
/* Message 消息提示
------------------------------- */
// default/info
.el-message {
min-width: unset !important;
padding: 15px !important;
}
/* MessageBox 弹框
------------------------------- */
.el-message-box__headerbtn:focus .el-message-box__close,
.el-message-box__headerbtn:hover .el-message-box__close {
color: var(--prev-color-primary);
}
.el-message-box {
background-color: var(--prev-bg-white);
border-color: var(--prev-border-color-lighter);
}
.el-message-box__title {
color: var(--prev-color-text-primary);
}
.el-message-box__content {
color: var(--prev-color-text-regular);
}
/* Notification 通知
------------------------------- */
.el-notification {
background-color: var(--prev-bg-white);
border-color: var(--prev-border-color-lighter);
.el-notification__title {
color: var(--prev-color-text-primary);
}
.el-notification__content {
color: var(--prev-color-text-regular);
}
}
/* Tabs 标签页
------------------------------- */
.el-tabs__item.is-active,
.el-tabs__item:hover,
.el-tabs--border-card > .el-tabs__header .el-tabs__item.is-active,
.el-tabs--border-card > .el-tabs__header .el-tabs__item:not(.is-disabled):hover {
color: var(--prev-color-primary);
}
.el-tabs__active-bar {
background-color: var(--prev-color-primary);
}
.el-tabs__nav-wrap::after {
height: 1px !important;
}
.el-tabs__item {
color: var(--prev-color-text-primary);
}
.el-tabs__nav-wrap::after {
background-color: var(--prev-border-color-light);
}
.el-tabs--card > .el-tabs__header .el-tabs__item.is-active,
.el-tabs--card > .el-tabs__header .el-tabs__item,
.el-tabs--card > .el-tabs__header,
.el-tabs--card > .el-tabs__header .el-tabs__nav {
border-color: var(--prev-bg-color);
}
.el-tabs--border-card {
background-color: var(--prev-bg-white);
border-color: var(--prev-border-color-base);
}
.el-tabs--border-card > .el-tabs__header {
background-color: var(--prev-bg-color);
border-color: var(--prev-border-color-light);
}
.el-tabs--border-card > .el-tabs__header .el-tabs__item.is-active {
background-color: var(--prev-bg-white);
border-color: var(--prev-border-color-base);
}
/* Breadcrumb 面包屑
------------------------------- */
.el-breadcrumb__inner a:hover,
.el-breadcrumb__inner.is-link:hover {
color: var(--prev-color-primary);
}
.el-breadcrumb__inner a,
.el-breadcrumb__inner.is-link {
color: var(--bg-topBarColor);
font-weight: normal;
}
.el-breadcrumb__inner a,
.el-breadcrumb__inner.is-link {
color: var(--prev-color-text-black);
opacity: 0.7;
}
.el-breadcrumb__separator {
color: var(--prev-border-color-hover);
}
/* PageHeader 页头
------------------------------- */
.el-page-header__left {
color: var(--prev-color-text-black);
&::after {
background-color: var(--prev-border-color-base);
}
}
.el-page-header__content {
color: var(--prev-color-text-primary);
}
/* Dropdown 下拉菜单
------------------------------- */
.el-dropdown-menu__item:focus,
.el-dropdown-menu__item:not(.is-disabled):hover {
color: var(--prev-color-primary);
background-color: var(--prev-color-primary-light-9);
}
.el-dropdown-menu {
background-color: var(--prev-bg-white);
border-color: var(--prev-border-color-lighter);
}
.el-dropdown-menu__item {
color: var(--prev-color-text-regular);
}
.el-dropdown-menu__item--divided {
border-color: var(--prev-border-color-lighter);
}
.el-dropdown-menu__item--divided:before {
background-color: var(--prev-bg-white);
}
/* Steps 步骤条
------------------------------- */
// default
.el-step__title.is-finish,
.el-step__description.is-finish,
.el-step__head.is-finish {
color: var(--prev-color-primary);
}
.el-step__head.is-finish {
border-color: var(--prev-color-primary);
}
/* Dialog 对话框
------------------------------- */
.el-dialog__headerbtn:focus .el-dialog__close,
.el-dialog__headerbtn:hover .el-dialog__close {
color: var(--prev-color-primary);
}
.el-dialog {
background-color: var(--prev-bg-white);
}
.el-dialog__title {
color: var(--prev-color-text-primary);
}
.el-dialog__body {
color: var(--prev-color-text-regular);
}
/* Popover 弹出框
------------------------------- */
.el-popover {
background-color: var(--prev-bg-white);
border-color: var(--prev-border-color-lighter);
color: var(--prev-color-text-regular);
}
.el-popover__title {
color: var(--prev-color-text-primary);
}
/* Card 卡片
------------------------------- */
.el-card {
color: var(--prev-color-text-primary);
background-color: var(--prev-bg-white);
border-color: var(--prev-border-color-lighter);
}
.el-card__header {
padding: 15px 20px;
border-bottom-color: var(--prev-border-color-lighter);
}
/* Collapse 折叠面板
------------------------------- */
.el-collapse {
border-color: var(--prev-border-color-lighter);
}
.el-collapse-item__header {
color: var(--prev-color-text-primary);
background-color: var(--prev-bg-white);
border-color: var(--prev-border-color-lighter);
}
.el-collapse-item__wrap {
background-color: var(--prev-bg-white);
border-color: var(--prev-border-color-lighter);
}
.el-collapse-item__content {
color: var(--prev-color-text-primary);
}
/* Timeline 时间线
------------------------------- */
// primary
.el-timeline-item__node--primary {
background-color: var(--prev-color-primary);
}
.el-timeline-item__content {
color: var(--prev-color-text-primary);
}
/* Divider 分割线
------------------------------- */
.el-divider {
background-color: var(--prev-border-color-base);
}
/* Calendar 日历
------------------------------- */
.el-calendar-table td {
color: var(--prev-color-text-black);
}
.el-calendar-table td.is-today {
color: var(--prev-color-primary) !important;
background-color: var(--prev-color-primary-light-9);
}
.el-calendar-table .el-calendar-day:hover,
.el-calendar-table td.is-selected {
background-color: var(--prev-color-primary-light-9);
color: var(--prev-color-primary) !important;
}
.el-calendar {
background-color: var(--prev-bg-white);
}
.el-calendar__title {
color: var(--prev-color-text-black);
}
.el-calendar__header,
.el-calendar-table tr:first-child td,
.el-calendar-table td,
.el-calendar-table tr td:first-child {
border-color: var(--prev-border-color-lighter);
}
.el-calendar-table thead th {
color: var(--prev-color-text-regular);
}
.el-calendar-table:not(.is-range) td.next,
.el-calendar-table:not(.is-range) td.prev {
color: var(--prev-color-text-placeholder);
}
.el-calendar__button-group {
.el-button {
color: var(--prev-color-text-regular);
background-color: var(--prev-bg-white);
border-color: var(--prev-border-color-base);
&:focus,
&:hover {
color: var(--prev-color-primary) !important;
background: var(--prev-color-primary-light-8) !important;
border-color: var(--prev-color-primary-light-6) !important;
}
&:active {
color: var(--prev-color-primary-light-3);
}
}
}
/* Backtop 回到顶部
------------------------------- */
.el-backtop {
color: var(--prev-color-primary);
&:hover {
background-color: var(--prev-color-primary-light-9);
}
}
/* scrollbar
------------------------------- */
.el-scrollbar__wrap {
overflow-x: hidden !important;
max-height: 100%; /*防止页面切换时,滚动条高度不变的问题(滚动条高度非滚动条滚动高度)*/
}
.el-select-dropdown .el-scrollbar__wrap {
overflow-x: scroll !important;
}
/* Drawer 抽屉
------------------------------- */
.el-drawer,
.el-divider__text {
background-color: var(--prev-bg-white);
}
.el-divider__text {
color: var(--prev-color-text-primary);
}
.el-drawer__close-btn:hover {
color: var(--prev-color-primary);
}
.el-drawer__body {
width: 100%;
height: 100%;
overflow: auto;
}
.el-drawer__header {
padding: 0 15px !important;
height: 50px;
display: flex;
align-items: center;
margin-bottom: 0 !important;
border-bottom: 1px solid var(--prev-border-color-lighter);
color: var(--prev-color-text-primary);
}
+4
View File
@@ -0,0 +1,4 @@
import { Local } from '@/utils/storage.js';
// 全局组件大小
export const globalComponentSize = Local.get('themeConfigPrev') ? Local.get('themeConfigPrev').globalComponentSize : '';
+134
View File
@@ -0,0 +1,134 @@
/*
* 年(Y) 可用1-4个占位符
* 月(m)、日(d)、小时(H)、分(M)、秒(S) 可用1-2个占位符
* 星期(W) 可用1-3个占位符
* 季度(q为阿拉伯数字,Q为中文数字)可用1或4个占位符
*
* let date = new Date()
* formatDate(date, "YYYY-mm-dd HH:MM:SS") // 2020-02-09 14:04:23
* formatDate(date, "YYYY-mm-dd HH:MM:SS Q") // 2020-02-09 14:09:03 一
* formatDate(date, "YYYY-mm-dd HH:MM:SS WWW") // 2020-02-09 14:45:12 星期日
* formatDate(date, "YYYY-mm-dd HH:MM:SS QQQQ") // 2020-02-09 14:09:36 第一季度
* formatDate(date, "YYYY-mm-dd HH:MM:SS WWW QQQQ") // 2020-02-09 14:46:12 星期日 第一季度
*/
export function formatDate(date, format) {
let we = date.getDay(); // 星期
let qut = Math.floor((date.getMonth() + 3) / 3).toString(); // 季度
const opt = {
'Y+': date.getFullYear().toString(), // 年
'm+': (date.getMonth() + 1).toString(), // 月(月份从0开始,要+1)
'd+': date.getDate().toString(), // 日
'H+': date.getHours().toString(), // 时
'M+': date.getMinutes().toString(), // 分
'S+': date.getSeconds().toString(), // 秒
'q+': qut, // 季度
};
const week = {
// 中文数字 (星期)
'0': '日',
'1': '一',
'2': '二',
'3': '三',
'4': '四',
'5': '五',
'6': '六',
};
const quarter = {
// 中文数字(季度)
'1': '一',
'2': '二',
'3': '三',
'4': '四',
};
if (/(W+)/.test(format)) {
format = format.replace(RegExp.$1, RegExp.$1.length > 1 ? (RegExp.$1.length > 2 ? '星期' + week[we] : '周' + week[we]) : week[we]);
}
if (/(Q+)/.test(format)) {
// 输入一个Q,只输出一个中文数字,输入4个Q,则拼接上字符串
format = format.replace(RegExp.$1, RegExp.$1.length == 4 ? '第' + quarter[qut] + '季度' : quarter[qut]);
}
for (let k in opt) {
let r = new RegExp('(' + k + ')').exec(format);
if (r) {
// 若输入的长度不为1,则前面补零
format = format.replace(r[1], RegExp.$1.length == 1 ? opt[k] : opt[k].padStart(RegExp.$1.length, '0'));
}
}
return format;
}
/**
* 10秒: 10 * 1000
* 1分: 60 * 1000
* 1小时: 60 * 60 * 1000
* 24小时:60 * 60 * 24 * 1000
* 3天: 60 * 60* 24 * 1000 * 3
*
* let data = new Date()
* formatPast(data) // 刚刚
* formatPast(data - 11 * 1000) // 11秒前
* formatPast(data - 2 * 60 * 1000) // 2分钟前
* formatPast(data - 60 * 60 * 2 * 1000) // 2小时前
* formatPast(data - 60 * 60 * 2 * 1000) // 2小时前
* formatPast(data - 60 * 60 * 71 * 1000) // 2天前
* formatPast("2020-06-01") // 2020-06-01
* formatPast("2020-06-01", "YYYY-mm-dd HH:MM:SS WWW QQQQ") // 2020-06-01 08:00:00 星期一 第二季度
*/
export function formatPast(param, format = 'YYYY-mm-dd') {
// 传入格式处理、存储转换值
let t, s;
// 获取js 时间戳
let time = new Date().getTime();
// 是否是对象
typeof param === 'string' || 'object' ? (t = new Date(param).getTime()) : (t = param);
// 当前时间戳 - 传入时间戳
time = Number.parseInt(time - t);
if (time < 10000) {
// 10秒内
return '刚刚';
} else if (time < 60000 && time >= 10000) {
// 超过10秒少于1分钟内
s = Math.floor(time / 1000);
return `${s}秒前`;
} else if (time < 3600000 && time >= 60000) {
// 超过1分钟少于1小时
s = Math.floor(time / 60000);
return `${s}分钟前`;
} else if (time < 86400000 && time >= 3600000) {
// 超过1小时少于24小时
s = Math.floor(time / 3600000);
return `${s}小时前`;
} else if (time < 259200000 && time >= 86400000) {
// 超过1天少于3天内
s = Math.floor(time / 86400000);
return `${s}天前`;
} else {
// 超过3天
let date = typeof param === 'string' || 'object' ? new Date(param) : param;
return formatDate(date, format);
}
}
/**
* formatAxis(new Date()) // 上午好
*/
export function formatAxis(param) {
let hour = new Date(param).getHours();
if (hour < 6) {
return '凌晨好';
} else if (hour < 9) {
return '早上好';
} else if (hour < 12) {
return '上午好';
} else if (hour < 14) {
return '中午好';
} else if (hour < 17) {
return '下午好';
} else if (hour < 19) {
return '傍晚好';
} else if (hour < 22) {
return '晚上好';
} else {
return '夜里好';
}
}
+99
View File
@@ -0,0 +1,99 @@
import Vue from 'vue';
// 获取阿里字体图标
const getAlicdnIconfont = () => {
return new Promise((resolve, reject) => {
Vue.nextTick(() => {
const styles = document.styleSheets;
let sheetsList = [];
let sheetsIconList = [];
for (let i = 0; i < styles.length; i++) {
if (styles[i].href && styles[i].href.indexOf('at.alicdn.com') > -1) {
sheetsList.push(styles[i]);
}
}
for (let i = 0; i < sheetsList.length; i++) {
for (let j = 0; j < sheetsList[i].cssRules.length; j++) {
if (sheetsList[i].cssRules[j].selectorText && sheetsList[i].cssRules[j].selectorText.indexOf('.icon-') > -1) {
sheetsIconList.push(
`${sheetsList[i].cssRules[j].selectorText.substring(1, sheetsList[i].cssRules[j].selectorText.length).replace(/\\:\\:before/gi, '')}`
);
}
}
}
if (sheetsIconList.length > 0) resolve(sheetsIconList);
else reject('未获取到值,请刷新重试');
});
});
};
// 初始化获取 css 样式,获取 element plus 自带图标
const getElementPlusIconfont = () => {
return new Promise((resolve, reject) => {
Vue.nextTick(() => {
const styles = document.styleSheets;
let sheetsIconList = [];
for (let i = 0; i < styles.length; i++) {
for (let j = 0; j < styles[i].cssRules.length; j++) {
if (styles[i].cssRules[j].selectorText && styles[i].cssRules[j].selectorText.indexOf('.el-icon-') === 0) {
sheetsIconList.push(
`${styles[i].cssRules[j].selectorText.substring(1, styles[i].cssRules[j].selectorText.length).replace(/\\:\\:before/gi, '')}`
);
}
}
}
if (sheetsIconList.length > 0) resolve(sheetsIconList);
else reject('未获取到值,请刷新重试');
});
});
};
// 初始化获取 css 样式,这里使用 fontawesome 的图标
const getAwesomeIconfont = () => {
return new Promise((resolve, reject) => {
Vue.nextTick(() => {
const styles = document.styleSheets;
let sheetsList = [];
let sheetsIconList = [];
for (let i = 0; i < styles.length; i++) {
if (styles[i].href && styles[i].href.indexOf('netdna.bootstrapcdn.com') > -1) {
sheetsList.push(styles[i]);
}
}
for (let i = 0; i < sheetsList.length; i++) {
for (let j = 0; j < sheetsList[i].cssRules.length; j++) {
if (
sheetsList[i].cssRules[j].selectorText &&
sheetsList[i].cssRules[j].selectorText.indexOf('.fa-') === 0 &&
sheetsList[i].cssRules[j].selectorText.indexOf(',') === -1
) {
sheetsIconList.push(
`${sheetsList[i].cssRules[j].selectorText.substring(1, sheetsList[i].cssRules[j].selectorText.length).replace(/\\:\\:before/gi, '')}`
);
}
}
}
if (sheetsIconList.length > 0) resolve(sheetsIconList);
else reject('未获取到值,请刷新重试');
});
});
};
// 定义导出方法集合
const initIconfont = {
// iconfont
ali: () => {
return getAlicdnIconfont();
},
// element plus
ele: () => {
return getElementPlusIconfont();
},
// fontawesome
awe: () => {
return getAwesomeIconfont();
},
};
// 导出方法
export default initIconfont;
+46
View File
@@ -0,0 +1,46 @@
import Vue from 'vue';
import loadingCss from '@/theme/loading.scss';
// 定义方法
export const PrevLoading = {
// 载入 css
setCss: () => {
let link = document.createElement('link');
link.rel = 'stylesheet';
link.href = loadingCss;
link.crossOrigin = 'anonymous';
document.getElementsByTagName('head')[0].appendChild(link);
},
// 创建 loading
start: () => {
const bodys = document.body;
const div = document.createElement('div');
div.setAttribute('class', 'loading-prev');
const htmls = `
<div class="loading-prev-box">
<div class="loading-prev-box-warp">
<div class="loading-prev-box-item"></div>
<div class="loading-prev-box-item"></div>
<div class="loading-prev-box-item"></div>
<div class="loading-prev-box-item"></div>
<div class="loading-prev-box-item"></div>
<div class="loading-prev-box-item"></div>
<div class="loading-prev-box-item"></div>
<div class="loading-prev-box-item"></div>
<div class="loading-prev-box-item"></div>
</div>
</div>
`;
div.innerHTML = htmls;
bodys.insertBefore(div, bodys.childNodes[0]);
},
// 移除 loading
done: () => {
Vue.nextTick(() => {
setTimeout(() => {
const el = document.querySelector('.loading-prev');
el && el.parentNode?.removeChild(el);
}, 1000);
});
},
};
+68
View File
@@ -0,0 +1,68 @@
import store from '@/store';
import router, { resetRouter } from '@/router/index';
import axios from 'axios';
import { Message, MessageBox } from 'element-ui';
import { Session } from '@/utils/storage';
// 创建 axios 实例
const service = axios.create({
baseURL: process.env.VUE_APP_BASE_LOGO_API,
timeout: 50000,
headers: { 'Content-Type': 'application/json' },
});
// 添加请求拦截器
service.interceptors.request.use(
(config) => {
// 在发送请求之前做些什么 token
if (Session.get('token')) {
// 带头部token
config.headers.common['Authorization'] = `${Session.get('token')}`;
}
return config;
},
(error) => {
// 对请求错误做些什么
return Promise.reject(error);
}
);
// 添加响应拦截器
service.interceptors.response.use(
(response) => {
// 对响应数据做点什么
const res = response.data;
// 根据后端状态码判断
if (true) {
// if (res.code && res.code !== 0 ) {
// `token` 过期或者账号已在别处登录
if (res.code === 401 || res.code === 4001) {
// 清除浏览器全部临时缓存
Session.clear();
router.push('/login');
store.commit('setMenuData', {});
resetRouter(); // 重置路由
MessageBox.alert('你已被登出,请重新登录', '提示', {})
.then(() => {})
.catch(() => {});
}
return response.data;
} else {
return Promise.reject(response.data);
}
},
(error) => {
// 对响应错误做点什么
if (error.message.indexOf('timeout') != -1) {
Message.error('网络超时');
} else if (error.message == 'Network Error') {
Message.error('网络连接错误');
} else {
Message.error(error.response.data.message || '错误');
}
return Promise.reject(error);
}
);
// 导出 axios 实例
export default service;
+88
View File
@@ -0,0 +1,88 @@
import store from '@/store';
import router, { resetRouter } from '@/router/index';
import axios from 'axios';
import { Message, MessageBox } from 'element-ui';
import { Session } from '@/utils/storage';
import { setTimeout } from 'core-js';
// 创建 axios 实例
const service = axios.create({
baseURL: process.env.VUE_APP_BASE_API,
timeout: 50000,
headers: { 'Content-Type': 'application/json' },
});
// 添加请求拦截器
service.interceptors.request.use(
(config) => {
// 在发送请求之前做些什么 token
if (Session.get('token')) {
// 带头部token
config.headers.common['Authorization'] = `${Session.get('token')}`;
}
let params = config.params
let newData = {}
for( let key in params){
if( params[key] !== null && params[key] !== ''){
newData[key] = params[key]
}
}
config.params = newData
console.log(config)
return config;
},
(error) => {
// 对请求错误做些什么
return Promise.reject(error);
}
);
// 添加响应拦截器
service.interceptors.response.use(
(response) => {
// 对响应数据做点什么
const res = response.data;
// 根据后端状态码判断
if (res.code) {
// if (res.code && res.code !== 0 ) {
// `token` 过期或者账号已在别处登录
if (res.code === 401 || res.code === 4001) {
// 清除浏览器全部临时缓存
Session.clear();
router.push('/login');
store.commit('setMenuData', {});
resetRouter(); // 重置路由
MessageBox.alert('你已被登出,请重新登录', '提示', {})
.then(() => {})
.catch(() => {});
}
return response.data;
} else {
return Promise.reject(response.data);
}
},
(error) => {
console.log(error);
if (error.message.indexOf('timeout') != -1) {
Message.error('网络超时');
} else if (error.message == 'Network Error') {
Message.error('网络连接错误');
// 错误thenk失效
} else {
// 清除浏览器全部临时缓存
// Session.clear();
// router.push('/login');
// store.commit('setMenuData', {});
// resetRouter(); // 重置路由
// MessageBox.alert('你已被登出,请重新登录', '提示', {})
// .then(() => {})
// .catch(() => {});
Message.error(error.response.data.msg || '错误');
}
return Promise.reject(error);
}
);
// 导出 axios 实例
export default service;
+39
View File
@@ -0,0 +1,39 @@
// 字体图标 url
const cssCdnUrlList = ['//at.alicdn.com/t/font_2348547_zjuiclx86c.css', '//netdna.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css'];
// 第三方 js url
const jsCdnUrlList = [];
// 动态设置字体图标
export function setCssCdn() {
if (cssCdnUrlList.length <= 0) return false;
cssCdnUrlList.map((v) => {
let link = document.createElement('link');
link.rel = 'stylesheet';
link.href = v;
link.crossOrigin = 'anonymous';
document.getElementsByTagName('head')[0].appendChild(link);
});
}
// 批量设置第三方js
export function setJsCdn() {
if (jsCdnUrlList.length <= 0) return false;
jsCdnUrlList.map((v) => {
let link = document.createElement('script');
link.src = v;
document.body.appendChild(link);
});
}
// 设置执行函数
const setIntroduction = {
cssCdn: () => {
setCssCdn();
},
jsCdn: () => {
setJsCdn();
},
};
// 导出函数方法
export default setIntroduction;
+48
View File
@@ -0,0 +1,48 @@
import config from '/package.json';
// 1、window.localStorage 浏览器永久缓存
export const Local = {
// 查看 v2.4.3版本更新日志
setKey(key) {
// @ts-ignore
return `${config.name}:${key}`;
},
// 设置永久缓存
set(key, val) {
window.localStorage.setItem(Local.setKey(key), JSON.stringify(val));
},
// 获取永久缓存
get(key) {
let json = window.localStorage.getItem(Local.setKey(key));
return JSON.parse(json);
},
// 移除永久缓存
remove(key) {
window.localStorage.removeItem(Local.setKey(key));
},
// 移除全部永久缓存
clear() {
window.localStorage.clear();
},
};
// 2、window.sessionStorage 浏览器临时缓存
export const Session = {
// 设置临时缓存
set(key, val) {
window.sessionStorage.setItem(Local.setKey(key), JSON.stringify(val));
},
// 获取临时缓存
get(key) {
let json = window.sessionStorage.getItem(Local.setKey(key));
return JSON.parse(json);
},
// 移除临时缓存
remove(key) {
window.sessionStorage.removeItem(Local.setKey(key));
},
// 移除全部临时缓存
clear() {
window.sessionStorage.clear();
},
};
+63
View File
@@ -0,0 +1,63 @@
import { Message } from 'element-ui';
/**
* 颜色转换函数
* @method hexToRgb hex 颜色转 rgb 颜色
* @method rgbToHex rgb 颜色转 Hex 颜色
* @method getDarkColor 加深颜色值
* @method getLightColor 变浅颜色值
*/
export function useChangeColor() {
// str 颜色值字符串
const hexToRgb = (str) => {
let hexs = '';
let reg = /^#?[0-9A-Fa-f]{6}$/;
if (!reg.test(str)) {
Message.warning('输入错误的hex');
return '';
}
str = str.replace('#', '');
hexs = str.match(/../g);
for (let i = 0; i < 3; i++) hexs[i] = parseInt(hexs[i], 16);
return hexs;
};
// r 代表红色 | g 代表绿色 | b 代表蓝色
const rgbToHex = (r, g, b) => {
let reg = /^\d{1,3}$/;
if (!reg.test(r) || !reg.test(g) || !reg.test(b)) {
Message.warning('输入错误的rgb颜色值');
return '';
}
let hexs = [r.toString(16), g.toString(16), b.toString(16)];
for (let i = 0; i < 3; i++) if (hexs[i].length == 1) hexs[i] = `0${hexs[i]}`;
return `#${hexs.join('')}`;
};
// color 颜色值字符串 | level 变浅的程度,限0-1之间
const getDarkColor = (color, level) => {
let reg = /^#?[0-9A-Fa-f]{6}$/;
if (!reg.test(color)) {
Message.warning('输入错误的hex颜色值');
return '';
}
let rgb = useChangeColor().hexToRgb(color);
for (let i = 0; i < 3; i++) rgb[i] = Math.floor(rgb[i] * (1 - level));
return useChangeColor().rgbToHex(rgb[0], rgb[1], rgb[2]);
};
// color 颜色值字符串 | level 加深的程度,限0-1之间
const getLightColor = (color, level) => {
let reg = /^#?[0-9A-Fa-f]{6}$/;
if (!reg.test(color)) {
Message.warning('输入错误的hex颜色值');
return '';
}
let rgb = useChangeColor().hexToRgb(color);
for (let i = 0; i < 3; i++) rgb[i] = Math.floor((255 - rgb[i]) * level + rgb[i]);
return useChangeColor().rgbToHex(rgb[0], rgb[1], rgb[2]);
};
return {
hexToRgb,
rgbToHex,
getDarkColor,
getLightColor,
};
}
+283
View File
@@ -0,0 +1,283 @@
/**
* 2020.11.29 lyt 整理
* 工具类集合,适用于平时开发
*/
/**
* 验证百分比(不可以小数)
* @param val 当前值字符串
* @returns 返回处理后的字符串
*/
export function verifyNumberPercentage(val) {
// 匹配空格
let v = val.replace(/(^\s*)|(\s*$)/g, '');
// 只能是数字和小数点,不能是其他输入
v = v.replace(/[^\d]/g, '');
// 不能以0开始
v = v.replace(/^0/g, '');
// 数字超过100,赋值成最大值100
v = v.replace(/^[1-9]\d\d{1,3}$/, '100');
// 返回结果
return v;
}
/**
* 验证百分比(可以小数)
* @param val 当前值字符串
* @returns 返回处理后的字符串
*/
export function verifyNumberPercentageFloat(val) {
let v = verifyNumberIntegerAndFloat(val);
// 数字超过100,赋值成最大值100
v = v.replace(/^[1-9]\d\d{1,3}$/, '100');
// 超过100之后不给再输入值
v = v.replace(/^100\.$/, '100');
// 返回结果
return v;
}
// 小数或整数(不可以负数)
export function verifyNumberIntegerAndFloat(val) {
// 匹配空格
let v = val.replace(/(^\s*)|(\s*$)/g, '');
// 只能是数字和小数点,不能是其他输入
v = v.replace(/[^\d.]/g, '');
// 以0开始只能输入一个
v = v.replace(/^0{2}$/g, '0');
// 保证第一位只能是数字,不能是点
v = v.replace(/^\./g, '');
// 小数只能出现1位
v = v.replace('.', '$#$').replace(/\./g, '').replace('$#$', '.');
// 小数点后面保留2位
v = v.replace(/^(\\-)*(\d+)\.(\d\d).*$/, '$1$2.$3');
// 返回结果
return v;
}
// 正整数验证
export function verifiyNumberInteger(val) {
// 匹配空格
let v = val.replace(/(^\s*)|(\s*$)/g, '');
// 去掉 '.' , 防止贴贴的时候出现问题 如 0.1.12.12
v = v.replace(/[\\.]*/g, '');
// 去掉以 0 开始后面的数, 防止贴贴的时候出现问题 如 00121323
v = v.replace(/(^0[\d]*)$/g, '0');
// 首位是0,只能出现一次
v = v.replace(/^0\d$/g, '0');
// 只匹配数字
v = v.replace(/[^\d]/g, '');
// 返回结果
return v;
}
// 去掉中文及空格
export function verifyCnAndSpace(val) {
// 匹配中文与空格
let v = val.replace(/[\u4e00-\u9fa5\s]+/g, '');
// 匹配空格
v = v.replace(/(^\s*)|(\s*$)/g, '');
// 返回结果
return v;
}
// 去掉英文及空格
export function verifyEnAndSpace(val) {
// 匹配英文与空格
let v = val.replace(/[a-zA-Z]+/g, '');
// 匹配空格
v = v.replace(/(^\s*)|(\s*$)/g, '');
// 返回结果
return v;
}
// 禁止输入空格
export function verifyAndSpace(val) {
// 匹配空格
let v = val.replace(/(^\s*)|(\s*$)/g, '');
// 返回结果
return v;
}
// 金额用 `,` 区分开
export function verifyNumberComma(val) {
// 调用小数或整数(不可以负数)方法
let v = verifyNumberIntegerAndFloat(val);
// 字符串转成数组
v = v.toString().split('.');
// \B 匹配非单词边界,两边都是单词字符或者两边都是非单词字符
v[0] = v[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',');
// 数组转字符串
v = v.join('.');
// 返回结果
return v;
}
// 匹配文字变色(搜索时)
export function verifyTextColor(val, text = '', color = 'red') {
// 返回内容,添加颜色
let v = text.replace(new RegExp(val, 'gi'), `<span style='color: ${color}'>${val}</span>`);
// 返回结果
return v;
}
// 数字转中文大写
export function verifyNumberCnUppercase(val, unit = '仟佰拾亿仟佰拾万仟佰拾元角分', v = '') {
// 当前内容字符串添加 2个0,为什么??
val += '00';
// 返回某个指定的字符串值在字符串中首次出现的位置,没有出现,则该方法返回 -1
let lookup = val.indexOf('.');
// substring:不包含结束下标内容,substr:包含结束下标内容
if (lookup >= 0) val = val.substring(0, lookup) + val.substr(lookup + 1, 2);
// 根据内容 val 的长度,截取返回对应大写
unit = unit.substr(unit.length - val.length);
// 循环截取拼接大写
for (let i = 0; i < val.length; i++) {
v += '零壹贰叁肆伍陆柒捌玖'.substr(val.substr(i, 1), 1) + unit.substr(i, 1);
}
// 正则处理
v = v
.replace(/零角零分$/, '整')
.replace(/零[仟佰拾]/g, '零')
.replace(/零{2,}/g, '零')
.replace(/零([亿|万])/g, '$1')
.replace(/零+元/, '元')
.replace(/亿零{0,3}万/, '亿')
.replace(/^元/, '零元');
// 返回结果
return v;
}
// 手机号码
export function verifyPhone(val) {
// false: 手机号码不正确
if (!/^((12[0-9])|(13[0-9])|(14[5|7])|(15([0-3]|[5-9]))|(18[0,5-9]))\d{8}$/.test(val)) return false;
// true: 手机号码正确
else return true;
}
// 国内电话号码
export function verifyTelPhone(val) {
// false: 国内电话号码不正确
if (!/\d{3}-\d{8}|\d{4}-\d{7}/.test(val)) return false;
// true: 国内电话号码正确
else return true;
}
// 登录账号 (字母开头,允许5-16字节,允许字母数字下划线)
export function verifyAccount(val) {
// false: 登录账号不正确
if (!/^[a-zA-Z][a-zA-Z0-9_]{4,15}$/.test(val)) return false;
// true: 登录账号正确
else return true;
}
// 密码 (以字母开头,长度在6~16之间,只能包含字母、数字和下划线)
export function verifyPassword(val) {
// false: 密码不正确
if (!/^[a-zA-Z]\w{5,15}$/.test(val)) return false;
// true: 密码正确
else return true;
}
// 强密码 (字母+数字+特殊字符,长度在6-16之间)
export function verifyPasswordPowerful(val) {
// false: 强密码不正确
if (
!/^(?![a-zA-z]+$)(?!\d+$)(?![!@#$%^&\\.*]+$)(?![a-zA-z\d]+$)(?![a-zA-z!@#$%^&\\.*]+$)(?![\d!@#$%^&\\.*]+$)[a-zA-Z\d!@#$%^&\\.*]{6,16}$/.test(val)
)
return false;
// true: 强密码正确
else return true;
}
// 密码强度
export function verifyPasswordStrength(val) {
let v = '';
// 弱:纯数字,纯字母,纯特殊字符
if (/^(?:\d+|[a-zA-Z]+|[!@#$%^&\\.*]+){6,16}$/.test(val)) v = '弱';
// 中:字母+数字,字母+特殊字符,数字+特殊字符
if (/^(?![a-zA-z]+$)(?!\d+$)(?![!@#$%^&\\.*]+$)[a-zA-Z\d!@#$%^&\\.*]{6,16}$/.test(val)) v = '中';
// 强:字母+数字+特殊字符
if (
/^(?![a-zA-z]+$)(?!\d+$)(?![!@#$%^&\\.*]+$)(?![a-zA-z\d]+$)(?![a-zA-z!@#$%^&\\.*]+$)(?![\d!@#$%^&\\.*]+$)[a-zA-Z\d!@#$%^&\\.*]{6,16}$/.test(val)
)
v = '强';
// 返回结果
return v;
}
// IP地址
export function verifyIPAddress(val) {
// false: IP地址不正确
if (
!/^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/.test(
val
)
)
return false;
// true: IP地址正确
else return true;
}
// 邮箱
export function verifyEmail(val) {
// false: 邮箱不正确
if (
!/^(([^<>()\\[\]\\.,;:\s@"]+(\.[^<>()\\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(
val
)
)
return false;
// true: 邮箱正确
else return true;
}
// 身份证
export function verifyIdCard(val) {
// false: 身份证不正确
if (!/^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/.test(val)) return false;
// true: 身份证正确
else return true;
}
// 姓名
export function verifyFullName(val) {
// false: 姓名不正确
if (!/^[\u4e00-\u9fa5]{1,6}(·[\u4e00-\u9fa5]{1,6}){0,2}$/.test(val)) return false;
// true: 姓名正确
else return true;
}
// 邮政编码
export function verifyPostalCode(val) {
// false: 邮政编码不正确
if (!/^[1-9][0-9]{5}$/.test(val)) return false;
// true: 邮政编码正确
else return true;
}
// url
export function verifyUrl(val) {
// false: url不正确
if (
!/^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})).?)(?::\d{2,5})?(?:[/?#]\S*)?$/i.test(
val
)
)
return false;
// true: url正确
else return true;
}
// 车牌号
export function verifyCarNum(val) {
// false: 车牌号不正确
if (
!/^(([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z](([0-9]{5}[DF])|([DF]([A-HJ-NP-Z0-9])[0-9]{4})))|([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z][A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9挂学警港澳使领]))$/.test(
val
)
)
return false;
// true:车牌号正确
else return true;
}
+73
View File
@@ -0,0 +1,73 @@
import request from '@/utils/request';
// get获取列表
export function getOrders (params) {
return request({
url: '/calendar/dayInfo/select/showCalendard',
method: 'get',
params
});
}
// 新增
export function postAddOrders (data) {
return request({
url: '/calendar/dayInfo/insert',
method: 'post',
data,
});
}
// 修改
export function postUpdateOrders (data) {
return request({
url: '/calendar/dayInfo/update',
method: 'post',
data,
});
}
// 删除
export function deleteOrders (id) {
return request({
url: `/calendar/dayInfo/delete/${id}`,
method: 'delete',
});
}
// 新增周
export function postAddWeek (data) {
return request({
url: '/weekinfo/insert',
method: 'post',
data,
});
}
// get获取周次列表
export function getWeek (params) {
return request({
url: '/weekinfo/select/term',
method: 'get',
params
});
}
// 获取所对应的年、周、时间字典
export function getTerm (){
return request({
url: '/calendar/weekinfo/select/term',
method: 'get',
})
}
// 获取组织架构
export function getOrganization (superId){
return request({
url: `/user-dept/user/dept/${superId}`,
method: 'get',
})
}
@@ -0,0 +1,47 @@
<template>
<div>
<el-button @click="newlyClick" type="primary" size="mini" icon="el-icon-plus"
>新增</el-button
>
<el-button @click="resetClick" type="info" size="mini" icon="iconfont icon-biaodan"
>重置</el-button
>
<el-button @click="searchClick" type="warning" size="mini" icon="el-icon-search"
>搜索</el-button
>
<el-input
v-if="false"
v-model="searchData"
size="mini"
style="width: 20%"
placeholder="请输入搜索的关键字"
>
</el-input>
</div>
</template>
<script>
export default {
name: "CommonHead",
data() {
return {
searchData: "",
};
},
methods: {
newlyClick() {
// 在此处调用父组件传入的方法叫父组件做事情
this.$emit("newly-data");
},
resetClick() {
this.$emit("reset-data");
},
searchClick() {
this.$emit("search-data", this.searchData);
},
},
};
</script>
<style lang="scss" scoped></style>
@@ -0,0 +1,116 @@
<template>
<el-table
border
:header-cell-style="{
background: '#f5f7fa',
}"
:data="tableData"
style="width: 100%; margin-top: 20px"
height="650"
size="mini"
>
<el-table-column
v-if="column.label !== 'id' && column.label != '校区id'"
v-for="(column, index) in tableColumns"
:key="index"
:prop="column.prop"
:label="column.label"
width="auto"
:min-width="column.minWidth"
></el-table-column>
<el-table-column prop="zip" label="操作" width="160">
<template slot-scope="scope">
<el-button
@click="handleEdit(scope.row)"
class="el-icon-edit"
type="text"
size="small"
>编辑</el-button
>
<el-popconfirm @confirm="handleDelete(scope.row)" :title="'确定要删除?'">
<el-button
slot="reference"
style="margin-left: 10px; color: red"
class="el-icon-delete"
type="text"
size="small"
>删除</el-button
>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
</template>
<script>
export default {
props: {
columns: {
type: Array,
required: true,
},
data: {
type: Array,
required: true,
},
deleteFunc: {
type: Function,
default: () => {},
},
editFunc: {
type: Function,
default: () => {},
},
},
name: "CommonTables",
data() {
return {};
},
created() {
console.log("this.columns");
console.log(this.columns);
for (let i = 0; i < this.columns.length; i++) {
console.log(this.columns[i].width);
}
},
methods: {
// 删除事件
handleDelete(row) {
this.deleteFunc(row.id);
},
// 编辑事件
handleEdit(row) {
console.log(row);
this.editFunc(row);
},
},
computed: {
tableColumns() {
// 处理传进来的列配置,返回符合 Element UI 表格要求的配置
return this.columns.map((column) => {
return {
label: column.label,
prop: column.prop,
minWidth: column.minWidth ? column.minWidth : "",
};
});
},
tableData() {
// 处理传进来的数据,返回符合 Element UI 表格要求的数据
return this.data.map((rowData) => {
let row = {};
for (let column of this.columns) {
row[column.prop] = rowData[column.prop];
}
return row;
});
},
},
};
</script>
<style lang="scss" scoped>
.s {
color: red;
}
</style>
+562
View File
@@ -0,0 +1,562 @@
<template>
<div>
<!-- 搜索 -->
<div class="form-adapt-container">
<el-card shadow="hover" header="">
<div style="display: flex">
<CommonHead @newly-data="fetchData" @reset-data="reset" @search-data="search" />
<el-button
@click="handleImport"
style="margin-left: 10px"
type="info"
plain
icon="el-icon-upload2"
size="mini"
>导入</el-button
>
</div>
<el-form :model="form" size="mini" label-width="100px" class="mt35 mb35">
<el-row :gutter="35">
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" class="mb20">
<el-form-item label="校区名称">
<el-select
v-model="query.school"
placeholder="请选择校区"
clearable
class="w100"
>
<el-option
v-for="(item, index) in schoolArr"
:label="item.name"
:value="item.deptId"
:key="index"
></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" class="mb20">
<el-form-item label="年份" prop="yyyy">
<el-date-picker
size="mini"
v-model="query.yyyy"
type="year"
value-format="yyyy"
placeholder="请选择年份"
>
</el-date-picker>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" class="mb20">
<el-form-item label="学期" prop="campus">
<el-select
size="mini"
v-model="query.campus"
placeholder="请选择学期"
clearable
class="w100"
>
<el-option label="春期" value="春期"></el-option>
<el-option label="秋期" value="秋期"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" class="mb20">
<el-form-item label="周" prop="week">
<el-input
size="mini"
type="number"
v-model="query.week"
clearable
placeholder="请输入第几周"
></el-input>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" class="mb20">
<el-form-item label="日期" prop="day">
<el-date-picker
v-model="query.day"
type="date"
size="mini"
value-format="yyyy-MM-dd"
placeholder="选择日期"
>
</el-date-picker>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" class="mb20">
<el-form-item label="参与人" prop="principal">
<el-input
size="mini"
v-model="query.principal"
placeholder="请输入参与人"
></el-input>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" class="mb20">
<el-form-item label="负责人" prop="participant">
<el-input
size="mini"
v-model="query.participant"
placeholder="请输入负责人"
></el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
</el-card>
</div>
<!-- 表格 -->
<CommonTables
:delete-func="deleteData"
:edit-func="editData"
:columns="columns"
:data="data"
></CommonTables>
<Pagination
:total="total"
v-show="total > 0"
:pageNum="query.pageNum"
:pageSize="query.pageSize"
@clickCurrent="onClickCurrent"
@clickSize="onClickSize"
/>
<!-- 创建缴费 -->
<el-dialog :title="title" :visible.sync="isVisible" width="30%">
<el-form
ref="form"
:model="form"
:rules="rules"
label-width="80px"
class="demo-ruleForm"
>
<el-form-item label="校区" prop="school">
<el-select
size="mini"
v-model="form.school"
placeholder="请选择校区"
clearable
class="w100"
>
<el-option
v-for="(item, index) in schoolArr"
:label="item.name"
:value="item.deptId"
:key="index"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="年份" prop="yyyy">
<el-date-picker
size="mini"
v-model="form.yyyy"
type="year"
value-format="yyyy"
placeholder="请选择年份"
>
</el-date-picker>
</el-form-item>
<el-form-item label="学期" prop="campus">
<el-select
size="mini"
v-model="form.campus"
placeholder="请选择学期"
clearable
class="w100"
>
<el-option label="春期" value="春期"></el-option>
<el-option label="秋期" value="秋期"></el-option>
</el-select>
</el-form-item>
<el-form-item label="周" prop="week">
<el-input
size="mini"
type="number"
v-model="form.week"
placeholder="请输入第几周"
></el-input>
</el-form-item>
<el-form-item label="日期" prop="day">
<el-date-picker
v-model="form.day"
type="date"
size="mini"
placeholder="选择日期"
>
</el-date-picker>
</el-form-item>
<el-form-item label="工作内容" prop="workInfo">
<el-input
type="textarea"
v-model="form.workInfo"
placeholder="请输入工作内容"
></el-input>
</el-form-item>
<el-form-item label="参与人" prop="principal">
<el-input
size="mini"
v-model="form.principal"
placeholder="请输入参与人"
></el-input>
</el-form-item>
<el-form-item label="负责人" prop="participant">
<el-input
size="mini"
v-model="form.participant"
placeholder="请输入负责人"
></el-input>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input size="mini" v-model="form.remark" placeholder="请输入备注"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button size="mini" @click="isVisible = false">取 消</el-button>
<el-button size="mini" type="primary" @click="onClickSubmit">确定</el-button>
</div>
</el-dialog>
<!-- 导入对话框 -->
<el-dialog
:title="upload.title"
:visible.sync="upload.open"
width="400px"
append-to-body
>
<el-upload
ref="upload"
:limit="1"
accept=".xlsx, .xls"
name="multipartFile"
:headers="upload.headers"
:action="upload.url + '?updateSupport=' + upload.updateSupport"
:disabled="upload.isUploading"
:on-progress="handleFileUploadProgress"
:on-success="handleFileSuccess"
:auto-upload="false"
drag
>
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
<div class="el-upload__tip text-center" slot="tip">
<span>仅允许导入xls、xlsx格式文件。</span>
<el-link
type="primary"
:underline="false"
style="font-size: 12px; vertical-align: baseline"
><a
:href="$store.state.campusCalendarTempentUrl + '/calendar/dayInfo/getExcel'"
>下载模板</a
>
</el-link>
</div>
</el-upload>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitFileForm">确 定</el-button>
<el-button @click="upload.open = false">取 消</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import CommonTables from "./components/CommonTables.vue";
import {
postAddOrders,
getOrders,
postUpdateOrders,
deleteOrders,
getOrganization,
} from "./api";
export default {
name: "CreatePayment",
data() {
var validates = (rule, value, callback) => {
console.log(value);
if (value <= 0 || value == null) {
callback(new Error("最小值为1"));
} else {
callback();
}
};
return {
form: {
school: null, // 校区
campus: null, // 春秋期
yyyy: null, // 年
week: null, // 周
day: null, // 开始时间
workInfo: null, // 工作内容
principal: null, // 参与人
participant: null, //负责人
remark: null, // 备注
},
schoolArr: [], // 校区
columns: [
{
label: "id",
prop: "id",
},
{
label: "校区id",
prop: "school",
},
{
label: "校区名称",
prop: "schoolName",
},
{
label: "春/秋期",
prop: "campus",
},
{
label: "年",
prop: "yyyy",
},
{
label: "周",
prop: "week",
},
{
label: "工作内容",
prop: "workInfo",
minWidth: "200",
},
{
label: "参与人",
prop: "principal",
},
{
label: "负责人",
prop: "participant",
},
{
label: "备注",
prop: "remark",
minWidth: "150",
},
{
label: "日期",
prop: "day",
},
],
data: [],
query: {
pageNum: 1,
pageSize: 10,
school: null, // 校区
campus: null, // 春秋期
yyyy: null, // 年
week: null, // 周
day: null, // 时间
principal: null, // 参与人
participant: null, //负责人
},
total: 0, // 总页数
isVisible: false, // 弹出层
title: "新增", // 弹出层按钮
rules: {
school: [{ required: true, message: "请选择校区", trigger: "change" }],
campus: [{ required: true, message: "请选择学期", trigger: "blur" }],
yyyy: [{ required: true, message: "请选择年份", trigger: "blur" }],
week: [{ required: true, validator: validates, trigger: "change" }],
day: [{ required: true, message: "请选择开始日期", trigger: "blur" }],
workInfo: [{ required: true, message: "请输入工作内容", trigger: "blur" }],
principal: [{ required: true, message: "请输入参与人", trigger: "blur" }],
participant: [{ required: true, message: "请输入负责人", trigger: "blur" }],
},
upload: {
// 是否显示弹出层(行事历导入)
open: false,
// 弹出层标题(行事历导入)
title: "",
// 是否禁用上传
isUploading: false,
// 是否更新已经存在的部门数据
updateSupport: 0,
// 设置上传的请求头部
headers: this.$store.state.uploadHeader,
// 上传的地址
url: process.env.VUE_APP_BASE_API + "/calendar/dayInfo/uploadExcel",
},
};
},
components: {
CommonTables,
},
created() {
this.getList();
// {“yyyy”,”campus”,”day”,”week”,”workInfo”,”principal”,”participant”,”remark”}
getOrganization(0).then((res) => {
console.log(res);
this.schoolArr = res.data;
});
},
methods: {
/** 导入按钮操作 */
handleImport() {
this.upload.title = "兴趣班导入";
this.upload.open = true;
},
// 文件上传中处理
handleFileUploadProgress(event, file, fileList) {
this.upload.isUploading = true;
},
// 文件上传成功处理
handleFileSuccess(response, file, fileList) {
this.upload.open = false;
this.upload.isUploading = false;
this.$refs.upload.clearFiles();
this.$alert(
"<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" +
response.msg +
"</div>",
"导入结果",
{ dangerouslyUseHTMLString: true }
);
this.getList();
},
// 提交上传文件
submitFileForm() {
this.$refs.upload.submit();
},
// 点击确定提交
onClickSubmit() {
console.log(this.form);
this.$refs["form"].validate((valid) => {
if (valid) {
let obj = { ...this.form };
if (this.title == "新增行事历") {
postAddOrders(obj).then((res) => {
if (res.code == 200) {
this.getList();
this.resetForm();
this.message();
this.isVisible = false;
} else if (res.code == 300) {
this.message(res.msg, "error");
} else {
this.message("新增失败", "error");
}
});
} else {
postUpdateOrders(obj).then((res) => {
if (res.code == 200) {
this.getList();
this.resetForm();
this.message("修改成功");
this.isVisible = false;
} else if (res.code == 300) {
this.message(res.msg, "error");
} else {
this.message("修改失败", "error");
}
});
}
}
});
},
// 点击新增
fetchData() {
this.isVisible = true;
this.title = "新增行事历";
this.resetForm();
},
// 重置按钮
reset() {
console.log("按钮重置点击了");
this.query = {
pageNum: 1,
pageSize: 10,
campus: null, // 春秋期
yyyy: null, // 年
week: null, // 周
day: null, // 时间
principal: null, // 参与人
participant: null, //负责人
};
this.getList();
},
// 重置表单
resetForm() {
this.form = {
school: null,
campus: null, // 春秋期
yyyy: null, // 年
week: null, // 周
day: null, // 天
workInfo: null, // 工作内容
principal: null, // 参与人
participant: null, //负责人
remark: null, // 备注
};
},
// 搜索按钮
search() {
this.query.pageNum = 1;
this.query.pageSize = 10;
this.getList();
},
// 获取数据
getList() {
getOrders(this.query).then((res) => {
console.log(res);
this.data = res.data.list.map((item) => {
// item.day = this.formatDate(item.day)
return item;
});
this.total = res.data.total;
});
},
// 删除
deleteData(id) {
console.log("------------------------------------------");
console.log(id);
deleteOrders(id).then((res) => {
if (res.code == 200) {
this.message("删除成功");
this.getList();
} else {
this.message("删除失败", "error");
}
});
},
// 编辑
editData(item) {
this.isVisible = true;
this.title = "修改行事历";
this.resetForm();
this.form = item;
},
// 点击切换页数
onClickCurrent(pageNum) {
console.log("点击切换页数" + pageNum);
this.query.pageNum = pageNum;
this.getList();
},
// 点击了每页页数
onClickSize(pageSize) {
this.pageSize = pageSize;
this.query.pageSize = pageSize;
this.getList();
console.log(pageSize);
},
message(message = "新增成功", type = "success") {
// type类型 success成功 warning警告 error错误
this.$message({
message,
type,
});
},
},
};
</script>
<style lang="scss" scoped>
html::v-deep.stretchNone {
.el-textarea__inner {
resize: none;
}
}
</style>
+320
View File
@@ -0,0 +1,320 @@
<template>
<div>
<!-- 搜索 -->
<CommonHead @newly-data="fetchData" @reset-data="reset" @search-data="search" />
<div class="form-adapt-container">
<el-card shadow="hover" header="">
<el-form :model="form" size="mini" label-width="100px" class="mt35 mb35">
<el-row :gutter="35">
<!-- <el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" class="mb20">
<el-form-item label="校区">
<el-select
v-model="form.teacherName"
placeholder="请选择校区"
clearable
class="w100"
>
<el-option label="城西校园" value="1"></el-option>
<el-option label="城北校区" value="2"></el-option>
<el-option label="龙马潭校区区" value="3"></el-option>
</el-select>
</el-form-item>
</el-col> -->
<!-- <el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" class="mb20">
<el-form-item label="发生时期">
<el-select
v-model="form.className"
placeholder="请选择发生时期"
clearable
class="w100"
>
<el-option label="春季" value="春季"></el-option>
<el-option label="秋季" value="秋季"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" class="mb20">
<el-form-item label="负责人">
<el-select v-model="value2" placeholder="请选择校区" clearable class="w100">
<el-option label="张三" value="1"></el-option>
<el-option label="李四" value="2"></el-option>
<el-option label="王麻子" value="3"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" class="mb20">
<el-form-item label="参与人">
<el-select v-model="value6" placeholder="请选择校区" clearable class="w100">
<el-option label="张三" value="1"></el-option>
<el-option label="李四" value="2"></el-option>
<el-option label="王麻子" value="3"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" class="mb20">
<el-form-item label="日期">
<div class="block">
<el-date-picker
v-model="value6"
type="daterange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
>
</el-date-picker>
</div>
</el-form-item>
</el-col> -->
</el-row>
</el-form>
</el-card>
</div>
<!-- 表格 -->
<CommonTables
:delete-func="deleteData"
:edit-func="editData"
:columns="columns"
:data="data"
></CommonTables>
<Pagination
:total="total"
v-show="total > 0"
:pageNum="query.pageNum"
:pageSize="query.pageSize"
@clickCurrent="onClickCurrent"
@clickSize="onClickSize"
/>
<!-- 创建缴费 -->
<el-dialog :title="title" :visible.sync="isVisible" width="30%">
<el-form ref="form" :model="form" :rules="rules" label-width="80px" class="demo-ruleForm">
<el-form-item label="学期" prop="campus">
<el-select
v-model="form.campus"
placeholder="请选择学期"
clearable
class="w100"
>
<el-option label="春季" value="春季"></el-option>
<el-option label="秋季" value="秋季"></el-option>
</el-select>
</el-form-item>
<el-form-item label="年份" prop="yyyy">
<el-date-picker
v-model="form.yyyy"
type="year"
value-format="yyyy"
placeholder="请选择年份">
</el-date-picker>
</el-form-item>
<el-form-item label="周" prop="week" >
<el-input size="mini" v-model="form.week" placeholder="请输入周" type="number"></el-input>
</el-form-item>
<el-form-item label="日期" prop="date" >
<el-date-picker
v-model="form.date"
type="daterange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期">
</el-date-picker>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button size="mini" @click="isVisible = false">取 消</el-button>
<el-button size="mini" type="primary" @click="onClickSubmit">确定</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { postAddWeek, getWeek, putOrders } from './api'
export default {
name: "CreatePayment",
data() {
return {
form: {
campus: null, // 春秋期
yyyy: null, // 年
week: null, // 周
date: null, // 开始时间和结束时间
},
columns: [
{
label: "id",
prop: "id",
},
{
label: "春/秋期",
prop: "campus",
},
{
label: "年",
prop: "yyyy",
},
{
label: "周",
prop: "week",
},
{
label: "开始时间",
prop: "startTime",
},
{
label: "结束时间",
prop: "endTime",
},
],
data: [],
query: {
pageNum: 1,
pageSize: 10,
},
total: 0, // 总页数
isVisible: false, // 弹出层
title: '新增', // 弹出层按钮
rules: {
campus: [
{ required: true, message: '请选择学期', trigger: 'blur' },
],
yyyy: [
{ required: true, message: '请选择年份', trigger: 'blur' },
],
week: [
{ required: true, message: '请选择第几周', trigger: 'blur' },
],
date: [
{ required: true, message: '请选择日期', trigger: 'blur' },
],
},
}
},
created(){
this.getList()
// {“yyyy”,”campus”,”day”,”week”,”workInfo”,”principal”,”participant”,”remark”}
let obj = {
campus: null, // 春秋期
yyyy: null, // 年
week: null, // 周
date: null, // 开始时间和结束时间
}
},
methods:{
// 点击确定提交
onClickSubmit(){
console.log(this.form)
this.$refs['form'].validate((valid) => {
if (valid) {
let obj = { ...this.form }
obj.startTime = this.form.date[0]
obj.endTime = this.form.date[1]
postAddWeek(obj).then(res =>{
if(res.code == 200){
this.getList()
this.resetForm()
this.message()
this.isVisible = false;
}else{
this.message('新增失败', 'error')
}
})
}
})
},
// 点击新增
fetchData() {
this.isVisible = true;
this.title = '新增'
this.resetForm()
},
// 重置按钮
reset() {
console.log("按钮重置点击了");
this.query = {
pageNum: 1,
pageSize: 10,
}
this.getList()
},
// 重置表单
resetForm() {
this.form = {
campus: null, // 春秋期
yyyy: null, // 年
week: null, // 周
date: null, // 开始结束时间
}
},
// 搜索按钮
search() {
this.getList()
},
// 获取数据
getList(){
getWeek(this.query).then( res =>{
console.log(res)
this.data = res.data.map(item =>{
return item
})
this.total = res.total
})
},
// 删除
deleteData(item) {
console.log('------------------------------------------')
console.log(item)
// putOrders().then(res =>{
// })
},
// 编辑
editData() {
this.isVisible = true;
this.title = '修改'
this.resetForm()
},
// 点击切换页数
onClickCurrent(pageNum){
console.log( '点击切换页数' +pageNum)
this.query.pageNum = pageNum
this.getList()
},
// 点击了每页页数
onClickSize(pageSize){
this.pageSize = pageSize
this.query.pageSize = pageSize
this.getList()
console.log(pageSize)
},
message(message = '新增成功',type = 'success'){ // type类型 success成功 warning警告 error错误
if(type == 'success'){
this.$message({
message,
type
});
}
}
}
};
</script>
<style lang="scss" scoped>
html::v-deep.stretchNone{
.el-textarea__inner{
resize: none;
}
}
</style>
+370
View File
@@ -0,0 +1,370 @@
<template>
<div>
<!-- 搜索 -->
<CommonHead @newly-data="fetchData" @reset-data="reset" @search-data="search" />
<div class="form-adapt-container">
<el-card shadow="hover" header="">
<el-form :model="form" size="mini" label-width="100px" class="mt35 mb35">
<el-row :gutter="35">
<!-- <el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" class="mb20">
<el-form-item label="校区">
<el-select
v-model="form.teacherName"
placeholder="请选择校区"
clearable
class="w100"
>
<el-option label="城西校园" value="1"></el-option>
<el-option label="城北校区" value="2"></el-option>
<el-option label="龙马潭校区区" value="3"></el-option>
</el-select>
</el-form-item>
</el-col> -->
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" class="mb20">
<el-form-item label="发生时期">
<el-select
v-model="form.className"
placeholder="请选择发生时期"
clearable
class="w100"
>
<el-option label="春季" value="春季"></el-option>
<el-option label="秋季" value="秋季"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" class="mb20">
<el-form-item label="负责人">
<el-select v-model="value2" placeholder="请选择校区" clearable class="w100">
<el-option label="张三" value="1"></el-option>
<el-option label="李四" value="2"></el-option>
<el-option label="王麻子" value="3"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" class="mb20">
<el-form-item label="参与人">
<el-select v-model="value6" placeholder="请选择校区" clearable class="w100">
<el-option label="张三" value="1"></el-option>
<el-option label="李四" value="2"></el-option>
<el-option label="王麻子" value="3"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" class="mb20">
<el-form-item label="日期">
<div class="block">
<el-date-picker
v-model="value6"
type="daterange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
>
</el-date-picker>
</div>
</el-form-item>
</el-col>
</el-row>
</el-form>
</el-card>
</div>
<!-- 表格 -->
<CommonTables
:delete-func="deleteData"
:edit-func="editData"
:columns="columns"
:data="data"
></CommonTables>
<Pagination
:total="total"
v-show="total > 0"
:pageNum="query.pageNum"
:pageSize="query.pageSize"
@clickCurrent="onClickCurrent"
@clickSize="onClickSize"
/>
<!-- 创建缴费 -->
<el-dialog :title="title" :visible.sync="isVisible" width="30%">
<el-form ref="form" :model="form" :rules="rules" label-width="80px" class="demo-ruleForm">
<el-form-item label="学期" prop="campus">
<el-select
v-model="form.campus"
placeholder="请选择学期"
clearable
class="w100"
>
<el-option label="春季" value="春季"></el-option>
<el-option label="秋季" value="秋季"></el-option>
</el-select>
</el-form-item>
<el-form-item label="年份" prop="yyyy">
<el-date-picker
v-model="form.yyyy"
type="year"
placeholder="请选择年份">
</el-date-picker>
</el-form-item>
<el-form-item label="周" prop="week" >
<el-date-picker
v-model="form.week"
type="week"
placeholder="请选择第几周">
</el-date-picker>
</el-form-item>
<el-form-item label="开始日期" prop="day" >
<el-date-picker
v-model="form.day"
type="date"
placeholder="选择开始日期">
</el-date-picker>
</el-form-item>
<el-form-item label="工作内容" prop="workInfo">
<el-input type="textarea" v-model="form.workInfo" placeholder="请输入工作内容"></el-input>
</el-form-item>
<el-form-item label="参与人" prop="principal">
<el-input size="mini" v-model="form.principal" placeholder="请输入参与人"></el-input>
</el-form-item>
<el-form-item label="负责人" prop="participant">
<el-input size="mini" v-model="form.participant" placeholder="请输入负责人"></el-input>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input size="mini" v-model="form.remark" placeholder="请输入备注"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button size="mini" @click="isVisible = false">取 消</el-button>
<el-button size="mini" type="primary" @click="onClickSubmit">确定</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { postAddOrders, getOrders, putOrders } from './api'
export default {
name: "CreatePayment",
data() {
return {
form: {
campus: null, // 春秋期
yyyy: null, // 年
week: null, // 周
day: null, // 开始时间
workInfo: null, // 工作内容
principal: null, // 参与人
participant: null, //负责人
remark: null, // 备注
},
columns: [
{
label: "id",
prop: "id",
},
{
label: "春/秋期",
prop: "campus",
},
{
label: "年",
prop: "yyyy",
},
{
label: "周",
prop: "week",
},
{
label: "工作内容",
prop: "workInfo",
},
{
label: "参与人",
prop: "principal",
},
{
label: "负责人",
prop: "participant",
},
{
label: "备注",
prop: "remark",
},
{
label: "开始",
prop: "startTime",
},
{
label: "结束时间",
prop: "endTime",
},
],
data: [],
query: {
pageNum: 1,
pageSize: 10,
},
total: 0, // 总页数
isVisible: false, // 弹出层
title: '新增', // 弹出层按钮
rules: {
campus: [
{ required: true, message: '请选择学期', trigger: 'blur' },
],
yyyy: [
{ required: true, message: '请选择年份', trigger: 'blur' },
],
week: [
{ required: true, message: '请选择第几周', trigger: 'blur' },
],
day: [
{ required: true, message: '请选择开始日期', trigger: 'blur' },
],
workInfo: [
{ required: true, message: '请输入工作内容', trigger: 'blur' },
],
principal: [
{ required: true, message: '请输入参与人', trigger: 'blur' },
],
participant: [
{ required: true, message: '请输入负责人', trigger: 'blur' },
],
},
}
},
created(){
this.getList()
// {“yyyy”,”campus”,”day”,”week”,”workInfo”,”principal”,”participant”,”remark”}
let obj = {
campus: null, // 春秋期
yyyy: null, // 年
week: null, // 周
day: null, // 开始时间
workInfo: null, // 工作内容
principal: null, // 参与人
participant: null, //负责人
remark: null, // 备注
}
},
methods:{
// 点击确定提交
onClickSubmit(){
console.log(this.form)
this.$refs['form'].validate((valid) => {
if (valid) {
let obj = { ...this.form }
let startTime = new Date(this.form.startTime)
let endTime = new Date(this.form.endTime)
obj.startTime = startTime
obj.endTime = endTime
console.log(startTime)
console.log(endTime)
postAddOrders(obj).then(res =>{
if(res.code == 200){
this.getList()
this.resetForm()
this.message()
this.isVisible = false;
}else{
this.message('新增失败', 'error')
}
})
}
})
},
// 点击新增
fetchData() {
this.isVisible = true;
this.title = '新增'
this.resetForm()
},
// 重置按钮
reset() {
console.log("按钮重置点击了");
this.query = {
pageNum: 1,
pageSize: 10,
}
this.getList()
},
// 重置表单
resetForm() {
this.form = {
campus: null, // 春秋期
yyyy: null, // 年
week: null, // 周
day: null, // 开始时间
workInfo: null, // 工作内容
principal: null, // 参与人
participant: null, //负责人
remark: null, // 备注
}
},
// 搜索按钮
search() {
this.getList()
},
// 获取数据
getList(){
getOrders(this.query).then( res =>{
console.log(res)
this.data = res.data.map(item =>{
return item
})
this.total = res.total
})
},
// 删除
deleteData(item) {
console.log('------------------------------------------')
console.log(item)
// putOrders().then(res =>{
// })
},
// 编辑
editData() {
this.isVisible = true;
this.title = '修改'
this.resetForm()
},
// 点击切换页数
onClickCurrent(pageNum){
console.log( '点击切换页数' +pageNum)
this.query.pageNum = pageNum
this.getList()
},
// 点击了每页页数
onClickSize(pageSize){
this.pageSize = pageSize
this.query.pageSize = pageSize
this.getList()
console.log(pageSize)
},
message(message = '新增成功',type = 'success'){ // type类型 success成功 warning警告 error错误
this.$message({
message,
type
});
}
}
};
</script>
<style lang="scss" scoped>
html::v-deep.stretchNone{
.el-textarea__inner{
resize: none;
}
}
</style>
@@ -0,0 +1,94 @@
export default [
{
label: "id",
prop: "id",
type: "text",
},
{
label: "teacherId",
prop: "teacherId",
type: "text",
},
{
label: "classDate",
prop: "classDate",
type: "text",
},
{
label: "date",
prop: "date",
type: "text",
},
{
label: "weeks",
prop: "weeks",
type: "text",
},
{
label: "classDays",
prop: "classDays",
type: "text",
},
{
label: "任课老师",
prop: "teacherName",
type: "text",
},
{
label: "课程名称",
prop: "className",
type: "text",
},
{
label: "上课教室",
prop: "classRoom",
type: "text",
},
{
label: "上课时间",
prop: "time",
type: "text",
},
{
label: "最大报名人数",
prop: "maxNum",
type: "text",
},
{
label: "现在报名人数",
prop: "nowNum",
type: "text",
},
{
label: "报名开始时间",
prop: "startTime",
type: "text",
},
{
label: "报名结束时间",
prop: "endTime",
type: "text",
},
{
label: "课程开始日期",
prop: "classStartDate",
type: "text",
},
{
label: "课程结束日期",
prop: "classEndDate",
type: "text",
},
{
label: "课程图片",
prop: "classImg",
type: "image",
},
{
label: "状态",
prop: "status",
type: "signUp",
},
]
@@ -0,0 +1,881 @@
<template>
<div>
<el-card>
<div style="display: flex">
<CommonHead
@newly-data="fetchDataNewlyAdded"
@reset-data="reset"
@search-data="search"
></CommonHead>
<!-- newly-data新增事件 -->
<!-- reset-data重置表单内容 -->
<!-- search-data搜索事件,接收被搜索的内容 -->
<el-button
@click="handleImport"
style="margin-left: 10px"
type="info"
plain
icon="el-icon-upload2"
size="mini"
>导入</el-button
>
</div>
<el-form
:model="searchFormDatass"
size="mini"
label-width="100px"
class="mt35 mb35"
>
<el-row :gutter="35">
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" class="mb20">
<el-form-item label="任课教师">
<el-select
filterable
v-model="searchFormDatass.teacherId"
placeholder="请选择任课教师"
clearable
class="w100"
>
<el-option
v-for="(items, index) in teacher"
:key="index"
:label="items.name"
:value="items.userId"
></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" class="mb20">
<el-form-item label="课程名称">
<el-input
v-model="searchFormDatass.className"
placeholder="请输入课程名称"
></el-input>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" class="mb20">
<el-form-item label="上课教室">
<el-input
v-model="searchFormDatass.classRoom"
placeholder="请输入课程名称"
></el-input>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" class="mb20">
<el-form-item label="最大报名人数">
<el-input
type="number"
v-model="searchFormDatass.maxNum"
placeholder="请输入最大报名人数"
></el-input>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" class="mb20">
<el-form-item label="现在报名人数">
<el-input
type="number"
v-model="searchFormDatass.nowNum"
placeholder="请输入现在报名人数"
></el-input>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" class="mb20">
<el-form-item label="状态">
<el-select
filterable
v-model="searchFormDatass.status"
placeholder="请选择状态"
clearable
class="w100"
>
<el-option label="报名中" value="0"></el-option>
<el-option label="报名已结束" value="1"></el-option>
<el-option label="已删除" value="2"></el-option>
<el-option label="课程已结束" value="3"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6" class="mb20">
<el-form-item label="报名日期">
<div class="block">
<el-date-picker
class="w100"
v-model="searchFormDatass.date"
type="daterange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
>
</el-date-picker>
</div>
</el-form-item>
</el-col>
<el-col ::xs="24" :sm="12" :md="8" :lg="6" :xl="6" class="mb20">
<el-form-item label="课程日期">
<div class="block">
<el-date-picker
class="w100"
v-model="searchFormDatass.classDate"
type="daterange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
>
</el-date-picker>
</div>
</el-form-item>
</el-col>
</el-row>
</el-form>
</el-card>
<!-- 表格数据 -->
<InterestClassTabes
class="box-card"
:delete-func="deleteData"
:edit-func="editData"
:upload-func="uploadBut"
:registered-func="registeredStudentsBtn"
:columns="columns"
:data="data"
v-loading="loadingIST"
></InterestClassTabes>
<!-- 分页器 -->
<el-pagination
style="margin-top: 10px"
@current-change="currentChange"
@size-change="sizeChange"
:current-page="1"
:page-sizes="[10, 20, 30]"
:page-size="10"
:pager-count="7"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
>
</el-pagination>
<el-dialog
:before-close="handleClose"
:title="formData.id ? '修改兴趣班' : '添加兴趣班'"
:visible.sync="dialogVisible"
width="30%"
>
<el-form
:rules="rules"
:model="formData"
label-width="100px"
size="mini"
ref="ruleForm"
>
<el-form-item label="任课教师" prop="teacherId">
<el-select
filterable
v-model="formData.teacherId"
placeholder="请选择任课教师"
clearable
class="w100"
>
<el-option
v-for="(items, index) in teacher"
:key="index"
:label="items.name"
:value="items.userId"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="课程名称" prop="className">
<el-input v-model="formData.className" placeholder="请输入课程名称"></el-input>
</el-form-item>
<el-form-item label="上课教室" prop="classRoom">
<el-input v-model="formData.classRoom" placeholder="请输入上课教室"></el-input>
</el-form-item>
<el-form-item label="报名人数" prop="maxNum">
<el-input
type="number"
v-model="formData.maxNum"
placeholder="请输入最大报名人数"
></el-input>
</el-form-item>
<el-form-item label="报名日期" prop="date">
<div class="block">
<el-date-picker
v-model="formData.date"
type="daterange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
>
</el-date-picker>
</div>
</el-form-item>
<el-form-item label="上课时间" prop="time">
<el-time-picker
value-format="HH:mm"
v-model="formData.time"
placeholder="任意时间点"
>
</el-time-picker>
</el-form-item>
<el-form-item label="时间模式" prop="timeClass">
<div @change="selectLongMode" style="display: inline-block">
<el-radio v-model="radio" label="1">长期日期</el-radio>
</div>
<div @change="selectSelected" style="display: inline-block; margin-left: 20px">
<el-radio v-model="radio" label="2">选定日期</el-radio>
</div>
</el-form-item>
<el-form-item label="课程日期" prop="classDate" v-if="radio == '1'">
<div class="block">
<el-date-picker
v-model="formData.classDate"
type="daterange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
>
</el-date-picker>
</div>
</el-form-item>
<el-form-item label="固定周次" prop="weeks" v-if="radio == '1'">
<el-checkbox-group v-model="formData.weeks">
<el-checkbox
v-for="(item, index) in weeksData"
:key="index"
:label="item.value"
>{{ item.weeksday }}</el-checkbox
>
</el-checkbox-group>
</el-form-item>
<el-form-item label="固定日期" prop="classDays" v-if="radio == '2'">
<el-date-picker
type="dates"
v-model="formData.classDays"
placeholder="选择一个或多个日期"
value-format="yyyy-MM-dd"
>
</el-date-picker>
</el-form-item>
<el-form-item label="图片上传" prop="classImg">
<el-upload
class="avatar-uploader"
:action="$store.state.imgUrl"
:headers="$store.state.uploadHeader"
:show-file-list="false"
name="img"
:on-success="handleAvatarSuccess"
:before-upload="beforeAvatarUpload"
>
<img v-if="formData.classImg" :src="formData.classImg" class="avatar" />
<i v-else class="el-icon-plus avatar-uploader-icon clss"></i>
<div slot="tip" class="el-upload__tip">
只能上传jpg/png/gif/jpeg文件,且不超过500kb
</div>
</el-upload>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="closeAdd">取 消</el-button>
<el-button type="primary" @click="addInterestClass('ruleForm')">确 定</el-button>
</span>
</el-dialog>
<!-- 导入对话框 -->
<el-dialog
:title="upload.title"
:visible.sync="upload.open"
width="400px"
append-to-body
>
<el-upload
ref="upload"
name="multipartFile"
:limit="1"
accept=".xlsx, .xls"
:headers="upload.headers"
:action="upload.url"
:disabled="upload.isUploading"
:on-progress="handleFileUploadProgress"
:on-success="handleFileSuccess"
:on-error="failedToUploadCourse"
:auto-upload="false"
drag
>
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
<div class="el-upload__tip text-center" slot="tip">
<span>仅允许导入xls、xlsx格式文件。</span>
<el-link
type="primary"
:underline="false"
style="font-size: 12px; vertical-align: baseline"
><a
:href="
$store.state.campusCalendarTempentUrl + '/interestclass/course/getExcel'
"
>下载模板</a
>
</el-link>
</div>
</el-upload>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitFileForm">确 定</el-button>
<el-button @click="upload.open = false">取 消</el-button>
</div>
</el-dialog>
<!-- 导入学生对话框 -->
<el-dialog
:title="uploadStudents.title"
:visible.sync="uploadStudents.open"
width="400px"
append-to-body
>
<el-upload
ref="uploadStudents"
name="multipartFile"
:limit="1"
accept=".xlsx, .xls"
:headers="uploadStudents.headers"
:action="uploadStudents.url"
:disabled="uploadStudents.isUploading"
:on-progress="handleFileUploadProgressStudents"
:on-success="handleFileSuccessStudents"
:on-error="failedToUploadStudent"
:auto-upload="false"
drag
>
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
<div class="el-upload__tip text-center" slot="tip">
<span>仅允许导入xls、xlsx格式文件。</span>
<el-link
type="primary"
:underline="false"
style="font-size: 12px; vertical-align: baseline"
><a
:href="
$store.state.campusCalendarTempentUrl + '/interestclass/enroll/getExcel'
"
>下载模板</a
>
</el-link>
</div>
</el-upload>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitFileFormStudents">确 定</el-button>
<el-button @click="uploadStudents.open = false">取 消</el-button>
</div>
</el-dialog>
<!-- 查看班级报名的学生列表 -->
<el-dialog title="已报名学生列表" :visible.sync="enrollmentStudentData.open">
<div v-loading="loadingST">
<InterestClassTabesSt
:delete-func="deleteDataS"
:edit-func="editDataS"
:columns="columnsST"
:data="enrollmentStudentData.data"
></InterestClassTabesSt>
</div>
</el-dialog>
</div>
</template>
<script>
import InterestClassTabes from "../components/InterestClassTabes.vue";
import {
getListOfInterestClasses,
requestAddInterestClass,
requestDeleteInterestClass,
requestObtainAListOfTeacherNames,
reqObtainAListOfRegisteredStudents,
} from "../api.js";
import InterestClassTabesSt from "../components/InterestClassTabesSt.vue";
import columns from "./columns";
import columnsST from "./listOfRegisteredStudents";
import { Session } from "@/utils/storage";
export default {
name: "InterestClassEntry",
components: {
InterestClassTabes,
InterestClassTabesSt,
},
data() {
// 自定义表单验证
var validates = (rule, value, callback) => {
if (value <= 0 || value == null) {
callback(new Error("最小值为1"));
} else {
callback();
}
};
var timeRules = (rule, value, callback) => {
if (this.radio == "") {
callback(new Error("请选择时间模式"));
} else {
callback();
}
};
return {
// 单选
radio: "1",
radiobt1: false,
radiobt2: false,
// 星期
weeksData: [
{ weeksday: "星期天", value: "1" },
{ weeksday: "星期一", value: "2" },
{ weeksday: "星期二", value: "3" },
{ weeksday: "星期三", value: "4" },
{ weeksday: "星期四", value: "5" },
{ weeksday: "星期五", value: "6" },
{ weeksday: "星期六", value: "7" },
],
dialogVisible: false,
// 初始值
formData: {
classEndDate: null,
classImg: null,
className: null,
classRoom: null,
classDate: [],
date: [],
endTime: null,
maxNum: null,
nowNum: null,
startTime: null,
status: null,
teacherId: null,
teacherName: null,
classDays: null,
weeks: [],
time: null,
},
// 搜索初始值
searchFormDatass: {
className: null,
classRoom: null,
classDate: [],
date: [],
maxNum: null,
nowNum: null,
status: null,
teacherId: null,
teacherName: null,
},
// 对话框表单验证
rules: {
teacherId: [{ required: true, message: "请选择任课教师", trigger: "change" }],
className: [{ required: true, message: "请输入课程名称", trigger: "change" }],
classRoom: [{ required: true, message: "请输入上课教室", trigger: "change" }],
maxNum: [{ required: true, validator: validates, trigger: "change" }],
classImg: [{ required: true, message: "请选择图片上传", trigger: "change" }],
time: [{ required: true, message: "请选择上课时间", trigger: "change" }],
date: [{ required: true, message: "请选择报名日期", trigger: "change" }],
classDate: [
{
required: true,
message: "请选择课程日期",
trigger: "change",
},
],
classDays: [{ required: true, message: "请选择固定日期", trigger: "change" }],
timeClass: [{ required: true, validator: timeRules, trigger: "change" }],
},
// 表格行
columns,
columnsST,
// 表格数据
data: [],
loadingIST: false,
// 分页数据总条数
total: 10,
pagination: {
pageSize: 10,
pageNum: 1,
},
// 老师列表
teacher: [],
//上传课程
upload: {
// 是否显示弹出层
open: false,
// 弹出层标题
title: "",
// 是否禁用上传
isUploading: false,
// 是否更新已经存在的部门数据
updateSupport: 0,
// 设置上传的请求头部
headers: { Authorization: "Bearer " + "getToken()" },
// 上传的地址
url: process.env.VUE_APP_BASE_API + "/interestclass/course/uploadExcel",
},
//上传学生
uploadStudents: {
// 是否显示弹出层
open: false,
// 弹出层标题
title: "",
// 是否禁用上传
isUploading: false,
// 是否更新已经存在的部门数据
updateSupport: 0,
// 设置上传的请求头部
headers: { Authorization: "Bearer " + "getToken()" },
// 上传的地址
url: process.env.VUE_APP_BASE_API + "/interestclass/enroll/uploadExcel",
},
// 报名学生数据
enrollmentStudentData: {
// 是否显示弹出层
open: false,
// 学生列表数据
data: [],
},
loadingST: false,
};
},
methods: {
selectLongMode() {
this.formData.weeks = [];
console.log("-----");
this.radiobt1 = true;
this.formData.classDays = null;
this.formData.classDays = null;
},
selectSelected() {
this.radiobt2 = true;
this.formData.classDate = null;
this.formData.classDays = null;
this.formData.weeks = [];
},
getStoageUserTk() {
console.log(Session.get("token"));
return Session.get("token");
},
fetchDataNewlyAdded() {
this.dialogVisible = true;
// 清除数据
this.formData = {
classImg: "",
weeks: [],
};
this.radiobt1 = false;
this.radiobt2 = false;
this.radio = "";
},
uploadBut(row) {
this.uploadStudents.url = this.uploadStudents.url + "?id=" + row.id;
this.uploadStudents.title = "报名学生导入";
this.uploadStudents.open = true;
},
search() {
this.getInterstList();
},
reset() {
this.bus.$emit("onCurrentContextmenuClick", {
id: 0,
path: this.$route.path,
});
},
/** 导入按钮操作 */
handleImport() {
this.upload.title = "兴趣班导入";
this.upload.open = true;
},
// 删除兴趣班
async deleteData(id) {
let result = await requestDeleteInterestClass(id);
if (result.code == 200) {
this.getInterstList();
this.$message({
message: "删除成功",
type: "success",
});
} else {
this.$message.error("删除失败");
}
},
// 修改兴趣班
editData(row) {
console.log(row);
if (row.weeks) {
this.radio = "1";
} else {
this.radio = "2";
}
this.dialogVisible = true;
delete row.startTime;
delete row.endTime;
delete row.classStartDate;
delete row.classEndDate;
if (!row.weeks) {
row.weeks = [];
let result = row;
this.formData = { ...result };
} else {
this.formData = { ...row };
}
},
// 获取教师列表姓名
async obtainingTeacherLis() {
let result = await requestObtainAListOfTeacherNames();
if (result.code == 200) {
this.teacher = result.data;
}
},
// 提交上传文件
submitFileForm() {
this.upload.headers.Authorization = this.getStoageUserTk();
console.log("88888888888888888");
this.$refs.upload.submit();
},
// 提交上传学生文件
submitFileFormStudents() {
this.uploadStudents.headers.Authorization = this.getStoageUserTk();
this.$refs.uploadStudents.submit();
},
// 文件上传中处理
handleFileUploadProgress(event, file, fileList) {
this.upload.isUploading = true;
},
// 文件上传学生中处理
handleFileUploadProgressStudents(event, file, fileList) {
this.uploadStudents.isUploading = true;
},
// 上传课程失败
failedToUploadCourse(response, file, fileList) {
this.upload.open = false;
this.upload.isUploading = false;
this.$alert(
"<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" +
response.msg +
"</div>",
"导入结果",
{ dangerouslyUseHTMLString: true }
);
},
// 上传学生失败
failedToUploadStudent() {
this.uploadStudents.open = false;
this.uploadStudents.isUploading = false;
this.$alert(
"<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" +
response.msg +
"</div>",
"导入结果",
{ dangerouslyUseHTMLString: true }
);
},
// 文件上传学生成功处理
handleFileSuccessStudents(response, file, fileList) {
this.uploadStudents.open = false;
this.uploadStudents.isUploading = false;
this.$refs.uploadStudents.clearFiles();
this.$alert(
"<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" +
response.msg +
"</div>",
"导入结果",
{ dangerouslyUseHTMLString: true }
);
this.getInterstList();
},
// 文件上传成功处理
handleFileSuccess(response, file, fileList) {
this.upload.open = false;
this.upload.isUploading = false;
this.$refs.upload.clearFiles();
this.$alert(
"<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" +
response.msg +
"</div>",
"导入结果",
{ dangerouslyUseHTMLString: true }
);
this.getInterstList();
},
//获取兴趣班列表
async getInterstList() {
this.loadingST = true;
let result = await getListOfInterestClasses(
this.pagination.pageNum,
this.pagination.pageSize,
this.searchFormDatass
);
if (result.code == 200) {
this.loadingST = false;
this.total = result.total;
this.data = result.data;
this.data.forEach((element) => {
element.startTime = this.formatDate(element.startTime, "-", "year");
element.endTime = this.formatDate(element.endTime, "-", "year");
element.classEndDate = this.formatDate(element.classEndDate, "-", "year");
element.classStartDate = this.formatDate(element.classStartDate, "-", "year");
});
} else {
this.loadingST = false;
this.$message.error("网络错误");
}
this.loadingST = false;
},
//上传图片方法和回调
handleAvatarSuccess(res, file) {
this.formData.classImg = res.data;
},
// 上传之前的回调
beforeAvatarUpload(file) {
// 获取文件的后缀
const suffix = file.name.substring(file.name.lastIndexOf(".") + 1);
// 判断文件的大小
const isLt2M = file.size / 1024 / 1024 < 2;
let accept = "jpg/png/gif/jpeg";
const isLtType = accept.indexOf(suffix) >= 0;
if (!isLtType) {
this.$message.error("上传头像图片只能是jpg/png/gif/jpeg格式!");
}
if (!isLt2M) {
this.$message.error("上传头像图片大小不能超过 2MB!");
}
return isLtType && isLt2M;
},
// 添加兴趣班
addInterestClass() {
this.$refs.ruleForm.validate(async (success) => {
if (success) {
this.dialogVisible = false;
let result = await requestAddInterestClass(this.formData);
if (result.code == 200) {
this.$message({
message: this.formData.id ? "修改成功" : "添加成功",
type: "success",
});
this.getInterstList();
this.formData = {};
this.formData.weeks = [];
} else {
this.$message.error("添加失败");
}
} else {
return false;
}
});
},
// 查看报名了的学生
registeredStudentsBtn(id) {
console.log(id);
this.enrollmentStudentData.open = true;
this.getObtainStudentList(id);
},
// 获取已报名学生列表
async getObtainStudentList(id) {
this.loadingST = true;
let res = await reqObtainAListOfRegisteredStudents(id);
try {
if (res.code == 200) {
this.enrollmentStudentData.data = res.data;
this.loadingST = false;
} else {
this.loadingST = false;
this.$message.error("网络错误");
}
} catch (error) {
this.loadingST = false;
this.$message.error("网络错误" + error);
}
},
closeAdd() {
this.dialogVisible = false;
this.formData = {};
this.radiobt1 = false;
this.radiobt2 = false;
this.radio = "";
},
handleClose(done) {
this.$confirm("确认关闭?")
.then((_) => {
done();
this.formData = {};
})
.catch((_) => {});
},
currentChange(val) {
this.pagination.pageNum = val;
this.getInterstList();
},
sizeChange(val) {
this.pagination.pageSize = val;
this.getInterstList();
},
changeRadio2() {
this.radiobt2 = true;
},
// 学生表格里的删除
deleteDataS() {},
// 学生表格里的编辑
editDataS() {},
},
mounted() {
this.obtainingTeacherLis();
this.getInterstList();
},
};
</script>
<style lang="scss" scoped>
textarea {
resize: none;
}
.el-textarea .el-textarea__inner {
resize: none;
}
.box-card {
margin-top: 10px;
}
.clss {
border: 4px dashed #d9d9d9 !important;
}
.avatar-uploader .el-upload {
border: 4px dashed #d9d9d9 !important;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
}
.avatar-uploader .el-upload:hover {
border-color: #409eff;
}
.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 178px;
height: 178px;
line-height: 178px;
text-align: center;
}
.avatar {
width: 178px;
height: 178px;
display: block;
}
</style>
@@ -0,0 +1,21 @@
export default [
{
label: "姓名",
prop: "name",
type: "text",
},
{
label: "班级",
prop: "className",
type: "text",
},
{
label: "头像",
prop: "avatar",
type: "image",
},
]
@@ -0,0 +1,88 @@
export let columns = [
{
label: "id",
prop: "id",
type: "text",
},
{
label: "任课老师",
prop: "teacherName",
type: "text",
},
{
label: "课程名称",
prop: "className",
type: "text",
},
{
label: "上课教室",
prop: "classRoom",
type: "text",
},
{
label: "应到",
prop: "arrive",
type: "text",
},
{
label: "实到",
prop: "trueArrive",
type: "text",
},
{
label: "上课日期",
prop: "nowDay",
type: "text",
},
{
label: "课程图片",
prop: "classImg",
type: "image",
},
{
label: "状态",
prop: "status",
type: "signUp",
},
{
label: "备注",
prop: "note",
type: "text",
},
]
export let classStuInfoColumns = [
{
label: "id",
prop: "id",
type: "text",
},
{
label: "学生姓名",
prop: "name",
type: "text",
},
{
label: "考勤状态",
prop: "status",
type: "signUp",
},
{
label: "头像",
prop: "avatar",
type: "image",
},
{
label: "备注",
prop: "note",
type: "text",
},
]
@@ -0,0 +1,153 @@
<template>
<div>
<el-card>
<CommonHead
@newly-data="fetchDataNewlyAdded"
@reset-data="reset"
@search-data="search"
></CommonHead>
<el-form :model="fromData" size="mini" label-width="100px" class="mt35 mb35">
<el-row :gutter="35">
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" class="mb20">
<el-form-item label="日期">
<el-date-picker
class="w100"
v-model="fromData.date"
align="right"
type="date"
placeholder="选择日期"
value-format="yyyy-MM-dd"
>
</el-date-picker>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" class="mb20">
<el-form-item label="状态">
<el-select
filterable
placeholder="请选择状态"
v-model="fromData.status"
clearable
class="w100"
>
<el-option label="未点名" value="0"></el-option>
<el-option label="已点名" value="1"></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
</el-form>
</el-card>
<el-card class="box-card">
<InterestClassTabesTd
v-loading="loading"
:delete-func="deleteData"
:edit-func="editData"
:columns="columns"
:data="data"
></InterestClassTabesTd>
</el-card>
<!-- 对话框 -->
<el-dialog title="班级详情" :visible.sync="dialogTableVisible">
<InterestClassTabesSt
v-loading="loadings"
:delete-func="deleteData"
:edit-func="editData"
:columns="classStuInfoColumns"
:data="stData"
></InterestClassTabesSt>
</el-dialog>
</div>
</template>
<script>
import InterestClassTabesTd from "../components/InterestClassTabesTd.vue";
import InterestClassTabesSt from "../components/InterestClassTabesSt.vue";
import { columns, classStuInfoColumns } from "./columns";
import { requestGetTodaysInterestClass, requestClassDetails } from "../api.js";
export default {
name: "InterestCourseManagement",
data() {
return {
dialogTableVisible: false,
fromData: {
date: null,
},
columns,
classStuInfoColumns,
data: [],
stData: [
{
avatar: undefined,
classInfoId: 0,
id: 0,
name: "string",
note: "string",
status: 0,
studentId: "string",
},
],
loading: false,
loadings: false,
};
},
components: {
InterestClassTabesTd,
InterestClassTabesSt,
},
methods: {
// 新增按钮
fetchDataNewlyAdded() {
this.$message("该板块暂时无法添加");
},
// 重置
reset() {
this.bus.$emit("onCurrentContextmenuClick", {
id: 0,
path: this.$route.path,
});
},
// 搜索
search() {
this.getTodaysInterestClass();
},
// 表格里的删除
deleteData() {},
// 详情编辑
async editData(row) {
this.loadings = true;
let result = await requestClassDetails(row.id);
if (result.code == 200) {
this.loadings = false;
console.log("获取到了");
this.stData = result.data.classStudentInfoVos;
}
this.loadings = false;
this.dialogTableVisible = true;
},
// 获取兴趣班点名班级
async getTodaysInterestClass() {
this.loading = true;
console.log(this.fromData.date);
let result = await requestGetTodaysInterestClass(this.fromData);
if (result.code == 200) {
this.loading = false;
this.data = result.data;
this.data.forEach((element) => {
element.nowDay = this.formatDate(element.nowDay, "-", "year");
});
} else {
this.loading = false;
console.log("失败");
}
},
},
mounted() {
this.getTodaysInterestClass();
},
};
</script>
<style lang="scss" scoped></style>
@@ -0,0 +1,51 @@
export let columns = [
{
label: "id",
prop: "id",
type: "text",
},
{
label: "课程名称",
prop: "className",
type: "text",
},
{
label: "老师姓名",
prop: "teacherName",
type: "text",
},
{
label: "上课日期",
prop: "nowDay",
type: "text",
},
{
label: "学生姓名",
prop: "name",
type: "text",
},
{
label: "状态",
prop: "status",
type: "signUp",
},
{
label: "班级",
prop: "classes",
type: "text",
},
{
label: "头像",
prop: "avatar",
type: "image",
},
{
label: "备注",
prop: "note",
type: "text",
},
]
@@ -0,0 +1,128 @@
<template>
<div>
<el-card>
<CommonHead
@newly-data="fetchDataNewlyAdded"
@reset-data="reset"
@search-data="search"
></CommonHead>
<el-form :model="fromData" size="mini" label-width="100px" class="mt35 mb35">
<el-row :gutter="35">
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="6" class="mb20">
<el-form-item label="日期范围">
<div class="block">
<el-date-picker
class="w100"
v-model="fromData.date"
type="daterange"
range-separator="至"
start-placeholder="开始日期"
end-placeholder="结束日期"
>
</el-date-picker>
</div>
</el-form-item>
</el-col>
<el-col :xs="24" :sm="12" :md="8" :lg="6" :xl="4" class="mb20">
<el-form-item label="状态">
<el-select
filterable
placeholder="请选择状态"
v-model="fromData.status"
clearable
class="w100"
>
<el-option label="迟到" value="1"></el-option>
<el-option label="旷课" value="2"></el-option>
<el-option label="请假" value="3"></el-option>
<el-option label="早退" value="4"></el-option>
<el-option label="未点名" :value="-1"></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
</el-form>
</el-card>
<el-card class="box-card">
<CommonTablesImg
v-loading="loading"
:delete-func="deleteData"
:edit-func="editData"
:columns="columns"
:data="data"
></CommonTablesImg>
</el-card>
</div>
</template>
<script>
import { columns } from "./columns";
import { Message } from "element-ui";
import { reqObtainAListOfAbnormalStudents } from "../api.js";
import { formatDate } from "@/com";
export default {
name: "abnormalStudentManagement",
data() {
return {
fromData: {
date: [],
status: null,
},
columns,
data: [],
loading: false,
};
},
methods: {
// 新增按钮
fetchDataNewlyAdded() {
this.$message("该板块暂时无法添加");
},
// 重置
reset() {
this.bus.$emit("onCurrentContextmenuClick", {
id: 0,
path: this.$route.path,
});
},
// 搜索
search() {
this.getTodaysInterestClass();
},
// 获取兴趣班点名班级
async getTodaysInterestClass() {
this.loading = true;
let result = await reqObtainAListOfAbnormalStudents(this.fromData);
if (result.code == 200) {
let arr = result.data;
arr.forEach((element) => {
element.nowDay = formatDate(element.nowDay, "-");
});
this.loading = false;
this.data = result.data;
} else {
this.loading = false;
console.log("失败");
}
this.loading = false;
},
// 删除
deleteData(id) {
Message.error("该模块不支持被删除或者修改");
},
// 编辑
editData(item) {
Message.error("该模块不支持被删除或者修改");
console.log(item + "---------------");
},
},
mounted() {
this.getTodaysInterestClass();
},
};
</script>
<style lang="scss" scoped></style>
+71
View File
@@ -0,0 +1,71 @@
import request from '@/utils/request';
// 获取兴趣班列表
export const getListOfInterestClasses = (pageNum,pageSize,data={}) => request({
url: `/interestclass/course/get?pageNum=${pageNum}&pageSize=${pageSize}`,
method: 'get',
params:data
})
// 添加兴趣班
export const requestAddInterestClass = (data) => {
if(data.id){
return request({
url: '/interestclass/course/update',
method: 'put',
data
})
}else{
return request({
url: '/interestclass/course/add',
method: 'post',
data
})
}
}
// 删除兴趣班
export const requestDeleteInterestClass = (id) => request({
url: `/interestclass/course/delete?id=${id}`,
method: 'put',
})
// 获取某一天的兴趣班列表
export const requestGetTodaysInterestClass = (params) => request({
url: `/interestclass/classInfo/getToday`,
method: 'get',
params
})
// 获取某一天的兴趣班列表
export const requestClassDetails = (id) => request({
url: `/interestclass/classStuInfo/get?id=${id}`,
method: 'get',
})
// 获取取老师姓名列表
export const requestObtainAListOfTeacherNames = () => request({
url: `/interestclass/course/getTeacher`,
method: 'get',
})
// 获取根据范围获取异常学生列表列表
export const reqObtainAListOfAbnormalStudents = (params) => request({
url: `/interestclass/classInfo/getBadStu`,
method: 'get',
params
})
// 查看已经报名的学生列表
export const reqObtainAListOfRegisteredStudents = (id) => request({
url: `/interestclass/enroll/getEnrollInfo?id=${id}`,
method: 'get',
})

Some files were not shown because too many files have changed in this diff Show More