├── .browserslistrc ├── babel.config.js ├── public ├── logo.png ├── favicon.ico ├── logo-192.png ├── logo-48.png ├── logo-96.png ├── export │ ├── caigoujiaocaihuizongbiao.png │ ├── chubanshetongjishuliangbiao.png │ ├── kaoshikaochazongtidingshulv.png │ ├── zhengdingjiaocaihuizongbiao.png │ ├── jiaoshilingqujiaocaihuizongbiao.png │ ├── zhengdingjiaocaiyangshuhuizongbiao.png │ └── xueshengbanjilingqujiaocaifankuibiao.png ├── manifest.json └── index.html ├── postcss.config.js ├── src ├── assets │ └── logo.png ├── store.js ├── main.js ├── components │ ├── ContentTitle.vue │ └── TeacherModifyBookModal.vue ├── user.js ├── api.js ├── router.js ├── App.vue ├── views │ ├── aao │ │ ├── PlanList.vue │ │ ├── Discount.vue │ │ ├── NewPlan.vue │ │ ├── Export.vue │ │ └── Review.vue │ ├── teacher │ │ ├── Buy.vue │ │ └── Add.vue │ └── om │ │ └── Review.vue └── axios.js ├── .editorconfig ├── .gitignore ├── package.json ├── README.md └── mock.json /.browserslistrc: -------------------------------------------------------------------------------- 1 | > 1% 2 | last 2 versions 3 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | '@vue/app' 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /public/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itning/TMPP-FrontEnd/master/public/logo.png -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | autoprefixer: {} 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itning/TMPP-FrontEnd/master/public/favicon.ico -------------------------------------------------------------------------------- /public/logo-192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itning/TMPP-FrontEnd/master/public/logo-192.png -------------------------------------------------------------------------------- /public/logo-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itning/TMPP-FrontEnd/master/public/logo-48.png -------------------------------------------------------------------------------- /public/logo-96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itning/TMPP-FrontEnd/master/public/logo-96.png -------------------------------------------------------------------------------- /src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itning/TMPP-FrontEnd/master/src/assets/logo.png -------------------------------------------------------------------------------- /public/export/caigoujiaocaihuizongbiao.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itning/TMPP-FrontEnd/master/public/export/caigoujiaocaihuizongbiao.png -------------------------------------------------------------------------------- /public/export/chubanshetongjishuliangbiao.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itning/TMPP-FrontEnd/master/public/export/chubanshetongjishuliangbiao.png -------------------------------------------------------------------------------- /public/export/kaoshikaochazongtidingshulv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itning/TMPP-FrontEnd/master/public/export/kaoshikaochazongtidingshulv.png -------------------------------------------------------------------------------- /public/export/zhengdingjiaocaihuizongbiao.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itning/TMPP-FrontEnd/master/public/export/zhengdingjiaocaihuizongbiao.png -------------------------------------------------------------------------------- /public/export/jiaoshilingqujiaocaihuizongbiao.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itning/TMPP-FrontEnd/master/public/export/jiaoshilingqujiaocaihuizongbiao.png -------------------------------------------------------------------------------- /public/export/zhengdingjiaocaiyangshuhuizongbiao.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itning/TMPP-FrontEnd/master/public/export/zhengdingjiaocaiyangshuhuizongbiao.png -------------------------------------------------------------------------------- /public/export/xueshengbanjilingqujiaocaifankuibiao.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/itning/TMPP-FrontEnd/master/public/export/xueshengbanjilingqujiaocaifankuibiao.png -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*.vue] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /src/store.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | 4 | Vue.use(Vuex) 5 | 6 | export default new Vuex.Store({ 7 | state: { 8 | //当前路径 9 | now_path: '' 10 | }, 11 | getters: {}, 12 | mutations: {}, 13 | actions: {} 14 | }) 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /dist 4 | 5 | # local env files 6 | .env.local 7 | .env.*.local 8 | 9 | # Log files 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | 14 | # Editor directories and files 15 | .idea 16 | .vscode 17 | *.suo 18 | *.ntvs* 19 | *.njsproj 20 | *.sln 21 | *.sw? 22 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import App from './App.vue' 3 | import router from './router' 4 | import store from './store' 5 | import Antd from 'ant-design-vue' 6 | import User from '@/user' 7 | 8 | import 'ant-design-vue/dist/antd.css' 9 | 10 | Vue.config.productionTip = false 11 | Vue.use(Antd) 12 | Vue.use(User) 13 | 14 | new Vue({ 15 | router, 16 | store, 17 | render: h => h(App) 18 | }).$mount('#app') 19 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "教材采购系统", 3 | "name": "哈信息教材采购系统", 4 | "icons": [ 5 | { 6 | "src": "/logo-48.png", 7 | "type": "image/png", 8 | "sizes": "48x48" 9 | }, 10 | { 11 | "src": "/logo-96.png", 12 | "type": "image/png", 13 | "sizes": "96x96" 14 | }, 15 | { 16 | "src": "/logo-192.png", 17 | "type": "image/png", 18 | "sizes": "192x192" 19 | } 20 | ], 21 | "start_url": "/", 22 | "display": "standalone", 23 | "orientation": "portrait", 24 | "theme_color": "#fff", 25 | "background_color": "#fff" 26 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tmpp-frontend", 3 | "version": "1.1.0-RC", 4 | "private": true, 5 | "scripts": { 6 | "serve": "vue-cli-service serve", 7 | "build": "vue-cli-service build" 8 | }, 9 | "dependencies": { 10 | "ant-design-vue": "^1.3.10", 11 | "axios": "^0.19.0", 12 | "core-js": "^2.6.5", 13 | "js-base64": "^2.5.1", 14 | "moment": "^2.24.0", 15 | "vue": "^2.6.10", 16 | "vue-router": "^3.0.3", 17 | "vuex": "^3.0.1" 18 | }, 19 | "devDependencies": { 20 | "@vue/cli-plugin-babel": "^3.7.0", 21 | "@vue/cli-service": "^3.7.0", 22 | "vue-template-compiler": "^2.5.21" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/components/ContentTitle.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 14 | 15 | 37 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 哈信息教材采购系统 16 | 17 | 18 | 22 | 25 |
26 | 27 | 28 | -------------------------------------------------------------------------------- /src/user.js: -------------------------------------------------------------------------------- 1 | import {Base64} from 'js-base64'; 2 | 3 | let User = {}; 4 | let loginUser = init(); 5 | 6 | function init() { 7 | if (window.localStorage.getItem('authorization_token') === null) { 8 | return {}; 9 | } 10 | try { 11 | return JSON.parse(JSON.parse( 12 | Base64.decode( 13 | window.localStorage.getItem('authorization_token') 14 | .split('.')[1] 15 | ) 16 | ).loginUser); 17 | } catch (e) { 18 | window.localStorage.removeItem('authorization_token'); 19 | return {}; 20 | } 21 | } 22 | 23 | User.loginUser = loginUser; 24 | User.loginName = loginUser.name; 25 | User.userTypeName = function () { 26 | switch (loginUser.userType) { 27 | case "T": 28 | return '教师'; 29 | case "A": 30 | return '教务处'; 31 | case "O1": 32 | return "软件学院"; 33 | case "O2": 34 | return "电子工程学院"; 35 | case "O3": 36 | return "艺术设计学院"; 37 | case "O4": 38 | return "商学院"; 39 | case "O5": 40 | return "基础部"; 41 | case "O6": 42 | return "素质教育中心"; 43 | case "O7": 44 | return "体育教研室"; 45 | default: 46 | return '未知角色' 47 | } 48 | }; 49 | //T 教师 A 教务处 O 办公室主任 50 | User.user_is_teacher = loginUser.userType === 'T'; 51 | User.user_is_aao = loginUser.userType === 'A'; 52 | User.user_is_office_manager = ['O1', 'O2', 'O3', 'O4', 'O5', 'O6', 'O7'].indexOf(loginUser.userType) !== -1; 53 | 54 | User.install = function (Vue, options) { 55 | Vue.prototype.$user = User; 56 | }; 57 | 58 | export default User; 59 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 哈尔滨信息工程学院教材管理系统 2 | 3 | [![GitHub stars](https://img.shields.io/github/stars/HXCI-Studio/TMPP-FrontEnd.svg?style=social&label=Stars)](https://github.com/HXCI-Studio/TMPP-FrontEnd/stargazers) 4 | [![GitHub forks](https://img.shields.io/github/forks/HXCI-Studio/TMPP-FrontEnd.svg?style=social&label=Fork)](https://github.com/HXCI-Studio/TMPP-FrontEnd/network/members) 5 | [![GitHub watchers](https://img.shields.io/github/watchers/HXCI-Studio/TMPP-FrontEnd.svg?style=social&label=Watch)](https://github.com/HXCI-Studio/TMPP-FrontEnd/watchers) 6 | [![GitHub followers](https://img.shields.io/github/followers/HXCI-Studio.svg?style=social&label=Follow)](https://github.com/HXCI-Studio?tab=followers) 7 | 8 | [![GitHub issues](https://img.shields.io/github/issues/HXCI-Studio/TMPP-FrontEnd.svg)](https://github.com/HXCI-Studio/TMPP-FrontEnd/issues) 9 | [![GitHub license](https://img.shields.io/github/license/HXCI-Studio/TMPP-FrontEnd.svg)](https://github.com/HXCI-Studio/TMPP-FrontEnd/blob/master/LICENSE) 10 | [![GitHub last commit](https://img.shields.io/github/last-commit/HXCI-Studio/TMPP-FrontEnd.svg)](https://github.com/HXCI-Studio/TMPP-FrontEnd/commits) 11 | [![GitHub release](https://img.shields.io/github/release/HXCI-Studio/TMPP-FrontEnd.svg)](https://github.com/HXCI-Studio/TMPP-FrontEnd/releases) 12 | [![GitHub repo size in bytes](https://img.shields.io/github/repo-size/HXCI-Studio/TMPP-FrontEnd.svg)](https://github.com/HXCI-Studio/TMPP-FrontEnd) 13 | [![HitCount](http://hits.dwyl.io/HXCI-Studio/TMPP-FrontEnd.svg)](http://hits.dwyl.io/HXCI-Studio/TMPP-FrontEnd) 14 | [![language](https://img.shields.io/badge/language-Vue-green.svg)](https://github.com/HXCI-Studio/TMPP-FrontEnd) 15 | 16 | ## 开源库 17 | - JavaScript框架:Vue.JS 18 | - CSS框架:Ant Design 19 | - 请求库:axios 20 | - 日期处理:moment 21 | -------------------------------------------------------------------------------- /src/api.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Api 接口文件 3 | * date 2019-06-12 4 | * author itning 5 | * http://itning.top 6 | */ 7 | 'use strict'; 8 | //API地址 9 | export const BASE_URL = "http://localhost:8080"; 10 | //登录接口 11 | export const CAS_LOGIN_URL = BASE_URL + "/login"; 12 | //注销接口 13 | export const CAS_LOGOUT_URL = BASE_URL + "/logout"; 14 | 15 | //以下所有Api必须带请求头Authorization 16 | 17 | export default { 18 | ///获取所有计划 19 | getExecutePlans:BASE_URL +'/execute_AllPlan', 20 | //获取未完成执行计划 21 | getUndonePlan: BASE_URL + '/undone_execute_plan', 22 | //下载执行计划 23 | getDownPlan: BASE_URL + '/down_execute_plan', 24 | //获取所有授课部门 25 | getTeachingDepartments: BASE_URL + '/teaching_departments', 26 | //获取教育层次 27 | getEducationalLevels: BASE_URL + '/educational_levels', 28 | //下载执行计划模板 29 | getDownloadPlanTemplate: BASE_URL + '/download_execute_plan_template', 30 | //提交执行计划 31 | postPlan: BASE_URL + '/execute_plan', 32 | //上传执行计划文件 33 | postPlanFile: BASE_URL + '/execute_plan_file', 34 | //全部审核通过 35 | postExaminationPassed: BASE_URL + '/examination_passed', 36 | //我的审核 37 | getMyReview: BASE_URL + '/my_review', 38 | //是否购买样书 39 | postBuySampleBook: BASE_URL + '/buy_sample_book', 40 | //驳回 41 | postTurnDown: BASE_URL + '/turn_down', 42 | //获取所有计划列表 43 | getPlans: BASE_URL + '/execute_plans', 44 | //删除执行计划 45 | deletePlans: BASE_URL + '/execute_plan', 46 | //获取所有学院 47 | getColleges: BASE_URL + '/colleges', 48 | //获取执行计划年 49 | getYear: BASE_URL + '/year', 50 | //获取计划学期 51 | getTerm: BASE_URL + '/term', 52 | //征订教材汇总表格 53 | getDownBookMaterials: BASE_URL + '/down_book_materials', 54 | //获取已完成执行计划 55 | getDonePlan: BASE_URL + '/done_execute_plan', 56 | //考试/考察/总体订书率表 57 | getSummaryTable: BASE_URL + '/summary_table', 58 | //出版社统计数量表 59 | getPublishingHouseStatistics: BASE_URL + '/publishing_house_statistics', 60 | //征订教材样书统计表 61 | getSubscriptionBook: BASE_URL + '/subscription_book', 62 | //教师领取教材汇总表 63 | getTeacherReceivingTextbook: BASE_URL + '/teacher_receiving_textbook', 64 | //学生班级领取教材反馈表 65 | getStudentTextbook: BASE_URL + '/student_textbook', 66 | //导出采购教材汇总表 67 | getProcurementTable: BASE_URL + '/procurement_table', 68 | //导出征订教材计划表 69 | getSubscriptionPlan: BASE_URL + '/subscription_plan', 70 | //查询所有折扣 71 | getDiscounts: BASE_URL + '/discounts', 72 | //添加折扣 73 | postDiscount: BASE_URL + '/discount', 74 | //删除折扣 75 | deleteDiscount: BASE_URL + '/discount', 76 | //修改折扣 77 | patchDiscount: BASE_URL + '/discount', 78 | //办公室主任征订教材计划统计表 79 | getTextbookPlanStatistics: BASE_URL + '/textbook_execute_plan_statistics', 80 | //办公室主任我的审核 81 | getDirectorReview: BASE_URL + '/director_review', 82 | //办公室主任驳回 83 | postOfficeTurnDown: BASE_URL + '/office_turn_down', 84 | //办公室主任全部审核通过 85 | postAllPassed: BASE_URL + '/all_passed', 86 | //获取课程名称 87 | getCourseTitles: BASE_URL + '/courseTitles', 88 | //提交购书信息 89 | postBookPurchaseInformation: BASE_URL + '/book_purchase_information', 90 | //我的购书 91 | getPurchaseBook: BASE_URL + '/purchase_book', 92 | //修改购书 93 | patchPurchase: BASE_URL + '/purchase', 94 | } 95 | -------------------------------------------------------------------------------- /src/router.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Router from 'vue-router' 3 | import Vuex from './store' 4 | import {CAS_LOGIN_URL} from "./api"; 5 | 6 | Vue.use(Router) 7 | 8 | let router = new Router({ 9 | mode: 'history', 10 | base: process.env.BASE_URL, 11 | routes: [ 12 | { 13 | path: '/', 14 | redirect: '/plan_list' 15 | }, 16 | { 17 | path: '/plan_list', 18 | name: 'planList', 19 | component: () => import(/* webpackChunkName: "planList" */ './views/aao/PlanList.vue') 20 | }, 21 | { 22 | path: '/new_plan', 23 | name: 'newPlan', 24 | component: () => import(/* webpackChunkName: "newPlan" */ './views/aao/NewPlan.vue') 25 | }, 26 | { 27 | path: '/export', 28 | name: 'export', 29 | component: () => import(/* webpackChunkName: "export" */ './views/aao/Export.vue') 30 | }, 31 | { 32 | path: '/discount', 33 | name: 'discount', 34 | component: () => import(/* webpackChunkName: "discount" */ './views/aao/Discount.vue') 35 | }, 36 | { 37 | path: '/buy', 38 | name: 'buy', 39 | component: () => import(/* webpackChunkName: "buy" */ './views/teacher/Buy.vue') 40 | }, 41 | { 42 | path: '/add', 43 | name: 'add', 44 | component: () => import(/* webpackChunkName: "add" */ './views/teacher/Add.vue') 45 | }, 46 | { 47 | path: '/review', 48 | name: 'review', 49 | component: () => import(/* webpackChunkName: "review" */ './views/aao/Review.vue') 50 | }, 51 | { 52 | path: '/office_review', 53 | name: 'officeReview', 54 | component: () => import(/* webpackChunkName: "officeReview" */ './views/om/Review.vue') 55 | }, 56 | { 57 | path: '/token/:id', 58 | name: 'token', 59 | component: () => import(/* webpackChunkName: "planList" */ './views/aao/PlanList.vue'), 60 | beforeEnter: (to, from, next) => { 61 | window.localStorage.setItem('authorization_token', to.params.id); 62 | window.location.href = window.location.protocol + '//' + window.location.host; 63 | next(false); 64 | } 65 | }, 66 | { 67 | path: "*", 68 | redirect: "/" 69 | } 70 | ] 71 | }); 72 | //T 教师 A 教务处 O 办公室主任 73 | const A = ['plan_list', 'new_plan', 'export', 'discount', 'review']; 74 | const O = ['office_review']; 75 | const T = ['buy', 'add']; 76 | 77 | /** 78 | * 检查用户是否有当前路由权限 79 | * @param path 路径 80 | * @returns {boolean} 是否有权限 81 | */ 82 | function havePermission(path) { 83 | const p = path.replace(/[^a-zA-Z_]/g, ''); 84 | switch (Vue.prototype.$user.loginUser.userType) { 85 | //教务处 86 | case 'A': 87 | return A.includes(p); 88 | //办公室主任 89 | case 'O1': 90 | case 'O2': 91 | case 'O3': 92 | case 'O4': 93 | case 'O5': 94 | case 'O6': 95 | case 'O7': 96 | return O.includes(p); 97 | //教师 98 | case 'T': 99 | return T.includes(p); 100 | } 101 | } 102 | 103 | /*** 104 | * 跳转到用户正确的路径 105 | * @param next 路由回调 106 | */ 107 | function route2TruePath(next) { 108 | if (Vue.prototype.$user.user_is_office_manager) { 109 | next('/office_review'); 110 | } else if (Vue.prototype.$user.user_is_teacher) { 111 | next('/buy'); 112 | } else if (Vue.prototype.$user.user_is_aao) { 113 | next('/plan_list'); 114 | } else { 115 | next(false); 116 | } 117 | } 118 | 119 | /** 120 | * 路由全局守卫 121 | * 1.如果Url以'/token'开头,放行 122 | * 2.如果localStorage中last_path key 有值则放弃当前路由跳至last_path路径 123 | */ 124 | router.beforeEach((to, from, next) => { 125 | if (!to.path.startsWith('/token') && window.localStorage.getItem('authorization_token') == null) { 126 | window.location.href = CAS_LOGIN_URL; 127 | return; 128 | } 129 | if (to.path.startsWith('/token')) { 130 | next(); 131 | return; 132 | } 133 | if (!havePermission(to.path)) { 134 | route2TruePath(next); 135 | return; 136 | } 137 | let path = window.localStorage.getItem('last_path'); 138 | if (path !== null) { 139 | window.localStorage.removeItem('last_path'); 140 | next(path); 141 | } else { 142 | next(); 143 | } 144 | }); 145 | /*** 146 | * 全局后置钩子 147 | */ 148 | router.afterEach((to, from) => { 149 | Vuex.state.now_path = to.path; 150 | }); 151 | 152 | export default router; 153 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 78 | 79 | 119 | 120 | 145 | 146 | 159 | -------------------------------------------------------------------------------- /src/views/aao/PlanList.vue: -------------------------------------------------------------------------------- 1 | 28 | 29 | 195 | 196 | 201 | -------------------------------------------------------------------------------- /src/views/aao/Discount.vue: -------------------------------------------------------------------------------- 1 | 36 | 37 | 186 | 187 | 190 | -------------------------------------------------------------------------------- /src/components/TeacherModifyBookModal.vue: -------------------------------------------------------------------------------- 1 | 75 | 76 | 170 | 171 | 174 | -------------------------------------------------------------------------------- /src/axios.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios' 2 | import Vue from 'vue' 3 | import {CAS_LOGIN_URL} from "./api"; 4 | //错误吐司 5 | const showErrorToast = function (title, msg, duration = 4.5) { 6 | Vue.prototype.$notification['error']({ 7 | message: title, 8 | description: msg, 9 | duration: duration 10 | }); 11 | }; 12 | //一次显示错误吐司 13 | let show = false; 14 | const onceToast = function (msg) { 15 | if (show) { 16 | return; 17 | } 18 | showErrorToast('注意:', msg); 19 | show = true; 20 | }; 21 | 22 | //12s超时 23 | let instance = axios.create({timeout: 1000 * 12}); 24 | 25 | //请求拦截器 26 | instance.interceptors.request.use((request) => { 27 | let token = window.localStorage.getItem('authorization_token'); 28 | if (token !== undefined) { 29 | request.headers = { 30 | "Authorization": token, 31 | "Accept": "application/json" 32 | }; 33 | } else { 34 | request.headers = {"Accept": "application/json"}; 35 | } 36 | return request; 37 | 38 | }, function (error) { 39 | // Do something with request error 40 | return Promise.reject(error); 41 | }); 42 | 43 | // 响应拦截器 44 | instance.interceptors.response.use( 45 | response => { 46 | return Promise.resolve(response); 47 | }, 48 | // 服务器状态码不是200的情况 49 | error => { 50 | if (error.response === undefined) { 51 | showErrorToast('网络异常', '请检查网络连接状态后再试', null); 52 | return Promise.reject(error); 53 | } 54 | if (error.response.status) { 55 | switch (error.response.status) { 56 | case 401: 57 | window.localStorage.setItem('last_path', window.location.pathname); 58 | setTimeout(() => { 59 | window.location.href = CAS_LOGIN_URL; 60 | }, 2000); 61 | onceToast(error.response.data.msg); 62 | return; 63 | case 403: 64 | console.warn('权限不足'); 65 | break; 66 | case 404: 67 | console.warn('请求URL不存在'); 68 | break; 69 | case 500: 70 | console.warn('服务器错误'); 71 | break; 72 | case 503: 73 | console.warn('服务器错误'); 74 | break; 75 | default: 76 | console.warn(error); 77 | } 78 | return Promise.reject(error); 79 | } 80 | } 81 | ); 82 | 83 | const Method = {GET: 0, POST: 1, DELETE: 2, UPDATE: 3, PUT: 4, PATCH: 5}; 84 | 85 | export function Get(url) { 86 | return new _request(url, Method.GET); 87 | } 88 | 89 | export function Del(url) { 90 | return new _request(url, Method.DELETE); 91 | } 92 | 93 | export function Post(url) { 94 | return new _request(url, Method.POST); 95 | } 96 | 97 | export function Patch(url) { 98 | return new _request(url, Method.PATCH); 99 | } 100 | 101 | export function Download(url, fileName) { 102 | instance.get(url, { 103 | responseType: 'blob' //指定返回数据的格式为blob 104 | }).then(response => { 105 | let url = window.URL.createObjectURL(response.data); 106 | let a = document.createElement("a"); 107 | document.body.appendChild(a); 108 | a.href = url; 109 | a.download = fileName(response.headers); 110 | a.click(); 111 | window.URL.revokeObjectURL(url); 112 | }).catch(error => { 113 | if (error.response !== undefined) { 114 | console.warn(error); 115 | showErrorToast("下载失败:", error.toString()); 116 | } 117 | }); 118 | } 119 | 120 | function _request(url, method) { 121 | this.method = method; 122 | this.url = url; 123 | this.code = 200; 124 | this.startMsg = '错误:'; 125 | } 126 | 127 | _request.prototype.withErrorStartMsg = function (msg) { 128 | this.startMsg = msg; 129 | return this; 130 | }; 131 | 132 | _request.prototype.withSuccessCode = function (code) { 133 | this.code = code; 134 | return this; 135 | }; 136 | 137 | _request.prototype.withURLSearchParams = function (params) { 138 | let urlSearchParams = new URLSearchParams(); 139 | for (let p in params) { 140 | if (params.hasOwnProperty(p)) { 141 | let v = params[p]; 142 | urlSearchParams.append(p, v); 143 | } 144 | } 145 | this.urlSearchParams = urlSearchParams; 146 | return this; 147 | }; 148 | 149 | _request.prototype.withFormData = function (params, enableUploadProgress = true, uploadProgress) { 150 | let formData = new FormData(); 151 | for (let p in params) { 152 | if (params.hasOwnProperty(p)) { 153 | let v = params[p]; 154 | formData.append(p, v); 155 | } 156 | } 157 | this.formData = formData; 158 | this.enableUploadProgress = enableUploadProgress; 159 | this.uploadProgress = uploadProgress; 160 | return this; 161 | }; 162 | 163 | _request.prototype.doAfter = function (fn) { 164 | this.doAfterFun = fn; 165 | return this; 166 | }; 167 | 168 | _request.prototype.do = function (fn) { 169 | let that = this; 170 | let promise = null; 171 | switch (this.method) { 172 | case Method.GET: 173 | promise = instance.get(this.url); 174 | break; 175 | case Method.DELETE: 176 | if (this.urlSearchParams !== undefined) { 177 | promise = instance.delete(this.url, {data: this.urlSearchParams}); 178 | } else if (this.formData !== undefined) { 179 | promise = instance.delete(this.url, { 180 | data: this.formData, 181 | headers: {'content-type': 'multipart/form-data'} 182 | }); 183 | } else { 184 | promise = instance.delete(this.url); 185 | } 186 | break; 187 | case Method.POST: 188 | if (this.urlSearchParams !== undefined) { 189 | promise = instance.post(this.url, this.urlSearchParams); 190 | } else if (this.formData !== undefined) { 191 | if (this.enableUploadProgress === false) { 192 | promise = instance.post(this.url, this.formData, {headers: {'content-type': 'multipart/form-data'}}); 193 | } else { 194 | const uploadProgress = this.uploadProgress; 195 | let config = { 196 | headers: {'content-type': 'multipart/form-data'}, 197 | onUploadProgress: progressEvent => { 198 | let progress = progressEvent.loaded / progressEvent.total * 100 | 0; 199 | uploadProgress(progress); 200 | } 201 | }; 202 | promise = instance.post(this.url, this.formData, config); 203 | } 204 | } else { 205 | promise = instance.post(this.url); 206 | } 207 | break; 208 | case Method.PATCH: 209 | if (this.urlSearchParams !== undefined) { 210 | promise = instance.patch(this.url, this.urlSearchParams); 211 | } else if (this.formData !== undefined) { 212 | promise = instance.patch(this.url, this.formData, {headers: {'content-type': 'multipart/form-data'}}); 213 | } else { 214 | promise = instance.patch(this.url); 215 | } 216 | break; 217 | default: 218 | return Promise.reject('none switch found of ' + this.method); 219 | } 220 | promise 221 | .then(response => { 222 | if (response.status === that.code) { 223 | fn(response) 224 | } else { 225 | showErrorToast(that.startMsg, response.data.msg); 226 | } 227 | }) 228 | .catch(error => { 229 | if (error.response !== undefined) { 230 | showErrorToast(that.startMsg, error.response.data.msg); 231 | } 232 | }) 233 | .then(() => { 234 | if (that.doAfterFun !== undefined) { 235 | that.doAfterFun(); 236 | } 237 | }); 238 | return this; 239 | }; 240 | 241 | export default instance; 242 | -------------------------------------------------------------------------------- /src/views/aao/NewPlan.vue: -------------------------------------------------------------------------------- 1 | 57 | 58 | 228 | 229 | 232 | -------------------------------------------------------------------------------- /src/views/teacher/Buy.vue: -------------------------------------------------------------------------------- 1 | 33 | 34 | 293 | 294 | 297 | -------------------------------------------------------------------------------- /src/views/om/Review.vue: -------------------------------------------------------------------------------- 1 | 29 | 30 | 294 | 295 | 300 | -------------------------------------------------------------------------------- /mock.json: -------------------------------------------------------------------------------- 1 | { 2 | "teaching_departments": { 3 | "获取所有授课部门": 1, 4 | "code": 200, 5 | "msg": "查询成功", 6 | "data": [ 7 | { 8 | "id": "1", 9 | "name": "软件学院" 10 | }, 11 | { 12 | "id": "2", 13 | "name": "商学院" 14 | } 15 | ] 16 | }, 17 | "educational_levels": { 18 | "获取教育层次": 1, 19 | "code": 200, 20 | "msg": "查询成功", 21 | "data": [ 22 | { 23 | "id": "1", 24 | "name": "本科" 25 | }, 26 | { 27 | "id": "2", 28 | "name": "高职" 29 | } 30 | ] 31 | }, 32 | "undone_plan": { 33 | "获取未完成执行计划": 1, 34 | "code": 200, 35 | "msg": "查询成功", 36 | "data": [ 37 | { 38 | "id": "1", 39 | "year": "2018-2019", 40 | "term": 1, 41 | "teachingDepartment": "软件学院", 42 | "educationalLevel": "本科" 43 | }, 44 | { 45 | "id": "2", 46 | "year": "2018-2019", 47 | "term": 2, 48 | "teachingDepartment": "软件学院", 49 | "educationalLevel": "本科" 50 | } 51 | ] 52 | }, 53 | "plans": { 54 | "获取所有计划列表": 1, 55 | "code": 200, 56 | "msg": "获取计划列表成功", 57 | "data": { 58 | "pageNum": 1, 59 | "pageSize": 2, 60 | "size": 5, 61 | "orderBy": null, 62 | "startRow": 1, 63 | "endRow": 5, 64 | "total": 11, 65 | "pages": 3, 66 | "list": [ 67 | { 68 | "id": "1", 69 | "year": "2018-2019", 70 | "term": 1, 71 | "teachingDepartment": "软件学院", 72 | "educationalLevel": "本科", 73 | "startTime": "2017-10-01 12:00", 74 | "endTime": "2017-10-01 12:00", 75 | "approvalStatus": "进行中" 76 | }, 77 | { 78 | "id": "2", 79 | "year": "2018-2019", 80 | "term": 1, 81 | "teachingDepartment": "软件学院", 82 | "educationalLevel": "本科", 83 | "startTime": "2017-10-01 12:00", 84 | "endTime": "2017-10-01 12:00", 85 | "approvalStatus": "已完成" 86 | } 87 | ], 88 | "prePage": 0, 89 | "nextPage": 2, 90 | "isFirstPage": true, 91 | "isLastPage": false, 92 | "hasPreviousPage": false, 93 | "hasNextPage": true, 94 | "navigatePages": 8, 95 | "navigatepageNums": [ 96 | 1, 97 | 2, 98 | 3 99 | ], 100 | "navigateFirstPage": 1, 101 | "navigateLastPage": 3, 102 | "firstPage": 1, 103 | "lastPage": 3 104 | } 105 | }, 106 | "done_plan": { 107 | "获取已完成执行计划": 1, 108 | "code": 200, 109 | "msg": "查询成功", 110 | "data": [ 111 | { 112 | "id": "1", 113 | "year": "2018-2019", 114 | "term": 1, 115 | "teachingDepartment": "软件学院", 116 | "educationalLevel": "本科" 117 | }, 118 | { 119 | "id": "2", 120 | "year": "2018-2019", 121 | "term": 2, 122 | "teachingDepartment": "软件学院", 123 | "educationalLevel": "本科" 124 | } 125 | ] 126 | }, 127 | "colleges": { 128 | "获取所有学院": 1, 129 | "code": 200, 130 | "msg": "查询成功", 131 | "data": [ 132 | { 133 | "id": "1", 134 | "name": "软件学院" 135 | }, 136 | { 137 | "id": "2", 138 | "name": "商学院" 139 | } 140 | ] 141 | }, 142 | "year": { 143 | "获取执行计划年": 1, 144 | "code": 200, 145 | "msg": "查询成功", 146 | "data": [ 147 | "2018-2019", 148 | "2019-2020" 149 | ] 150 | }, 151 | "term": { 152 | "获取计划学期": 1, 153 | "code": 200, 154 | "msg": "查询成功", 155 | "data": [ 156 | 1, 157 | 2 158 | ], 159 | "id": "2018-2019" 160 | }, 161 | "my_review": { 162 | "教务处我的审核": 1, 163 | "code": 200, 164 | "msg": "查询成功", 165 | "data": { 166 | "pageNum": 1, 167 | "pageSize": 2, 168 | "size": 5, 169 | "orderBy": null, 170 | "startRow": 1, 171 | "endRow": 5, 172 | "total": 11, 173 | "pages": 3, 174 | "list": [ 175 | { 176 | "id": "1", 177 | "courseCode": "B001", 178 | "courseTitle": 1, 179 | "isBookPurchase": 0, 180 | "isbn": "9789993700142", 181 | "textbookName": "阿里技术参考图册", 182 | "textbookCategory": "出版", 183 | "press": "清华大学出版社", 184 | "author": "某某", 185 | "unitPrice": 15.00, 186 | "teacherBookNumber": 1, 187 | "discount": 0.76, 188 | "awardInformation": "获奖信息", 189 | "publicationDate": "2018-09", 190 | "subscriber": "周老师", 191 | "subscriberNumber": "13333333333", 192 | "approvalStatus": "审核通过", 193 | "isBuyBook": true 194 | }, 195 | { 196 | "id": "2", 197 | "courseCode": "B001", 198 | "courseTitle": 1, 199 | "isBookPurchase": 0, 200 | "isbn": "9789993700142", 201 | "textbookName": "阿里技术参考图册", 202 | "textbookCategory": "出版", 203 | "press": "清华大学出版社", 204 | "author": "某某", 205 | "unitPrice": 15.00, 206 | "teacherBookNumber": 1, 207 | "discount": 0.76, 208 | "awardInformation": "获奖信息", 209 | "publicationDate": "2018-09", 210 | "subscriber": "周老师", 211 | "subscriberNumber": "13333333333", 212 | "approvalStatus": "审核通过", 213 | "isBuyBook": true 214 | } 215 | ], 216 | "prePage": 0, 217 | "nextPage": 2, 218 | "isFirstPage": true, 219 | "isLastPage": false, 220 | "hasPreviousPage": false, 221 | "hasNextPage": true, 222 | "navigatePages": 8, 223 | "navigatepageNums": [ 224 | 1, 225 | 2, 226 | 3 227 | ], 228 | "navigateFirstPage": 1, 229 | "navigateLastPage": 3, 230 | "firstPage": 1, 231 | "lastPage": 3 232 | } 233 | }, 234 | "discounts": { 235 | "查询所有折扣": 1, 236 | "code": 200, 237 | "msg": "查询成功", 238 | "data": { 239 | "pageNum": 1, 240 | "pageSize": 2, 241 | "size": 5, 242 | "orderBy": null, 243 | "startRow": 1, 244 | "endRow": 5, 245 | "total": 11, 246 | "pages": 3, 247 | "list": [ 248 | { 249 | "id": "1", 250 | "discount": 0.76 251 | }, 252 | { 253 | "id": "2", 254 | "discount": 0.76 255 | } 256 | ], 257 | "prePage": 0, 258 | "nextPage": 2, 259 | "isFirstPage": true, 260 | "isLastPage": false, 261 | "hasPreviousPage": false, 262 | "hasNextPage": true, 263 | "navigatePages": 8, 264 | "navigatepageNums": [ 265 | 1, 266 | 2, 267 | 3 268 | ], 269 | "navigateFirstPage": 1, 270 | "navigateLastPage": 3, 271 | "firstPage": 1, 272 | "lastPage": 3 273 | } 274 | }, 275 | "director_review": { 276 | "办公室主任我的审核": 1, 277 | "code": 200, 278 | "msg": "查询成功", 279 | "data": { 280 | "pageNum": 1, 281 | "pageSize": 2, 282 | "size": 5, 283 | "orderBy": null, 284 | "startRow": 1, 285 | "endRow": 5, 286 | "total": 11, 287 | "pages": 3, 288 | "list": [ 289 | { 290 | "id": "1", 291 | "courseCode": "B001", 292 | "courseTitle": 1, 293 | "isBookPurchase": 0, 294 | "isbn": "9789993700142", 295 | "textbookName": "阿里技术参考图册", 296 | "textbookCategory": "出版", 297 | "press": "清华大学出版社", 298 | "author": "某某", 299 | "unitPrice": 15.00, 300 | "teacherBookNumber": 1, 301 | "discount": 0.76, 302 | "awardInformation": "获奖信息", 303 | "publicationDate": "2018-09", 304 | "subscriber": "周老师", 305 | "subscriberNumber": "13333333333", 306 | "approvalStatus": "审核通过" 307 | }, 308 | { 309 | "id": "2", 310 | "courseCode": "B001", 311 | "courseTitle": 1, 312 | "isBookPurchase": 0, 313 | "isbn": "9789993700142", 314 | "textbookName": "阿里技术参考图册", 315 | "textbookCategory": "出版", 316 | "press": "清华大学出版社", 317 | "author": "某某", 318 | "unitPrice": 15.00, 319 | "teacherBookNumber": 1, 320 | "discount": 0.76, 321 | "awardInformation": "获奖信息", 322 | "publicationDate": "2018-09", 323 | "subscriber": "周老师", 324 | "subscriberNumber": "13333333333", 325 | "approvalStatus": "审核通过" 326 | } 327 | ], 328 | "prePage": 0, 329 | "nextPage": 2, 330 | "isFirstPage": true, 331 | "isLastPage": false, 332 | "hasPreviousPage": false, 333 | "hasNextPage": true, 334 | "navigatePages": 8, 335 | "navigatepageNums": [ 336 | 1, 337 | 2, 338 | 3 339 | ], 340 | "navigateFirstPage": 1, 341 | "navigateLastPage": 3, 342 | "firstPage": 1, 343 | "lastPage": 3 344 | } 345 | }, 346 | "purchase_book": { 347 | "我的购书": 1, 348 | "code": 200, 349 | "msg": "查询成功", 350 | "data": { 351 | "pageNum": 1, 352 | "pageSize": 2, 353 | "size": 5, 354 | "orderBy": null, 355 | "startRow": 1, 356 | "endRow": 5, 357 | "total": 11, 358 | "pages": 3, 359 | "list": [ 360 | { 361 | "id": "1", 362 | "courseCode": "B001", 363 | "courseTitle": 1, 364 | "isBookPurchase": 0, 365 | "isbn": "9789993700142", 366 | "textbookName": "阿里技术参考图册", 367 | "textbookCategory": "出版", 368 | "press": "清华大学出版社", 369 | "author": "某某", 370 | "unitPrice": 15.00, 371 | "teacherBookNumber": 1, 372 | "discount": 0.76, 373 | "awardInformation": "获奖信息", 374 | "publicationDate": "2018-09", 375 | "subscriber": "周老师", 376 | "subscriberNumber": "13333333333", 377 | "approvalStatus": "审核通过" 378 | }, 379 | { 380 | "id": "2", 381 | "courseCode": "B001", 382 | "courseTitle": 1, 383 | "isBookPurchase": 0, 384 | "isbn": "9789993700142", 385 | "textbookName": "阿里技术参考图册", 386 | "textbookCategory": "出版", 387 | "press": "清华大学出版社", 388 | "author": "某某", 389 | "unitPrice": 15.00, 390 | "teacherBookNumber": 1, 391 | "discount": 0.76, 392 | "awardInformation": "获奖信息", 393 | "publicationDate": "2018-09", 394 | "subscriber": "周老师", 395 | "subscriberNumber": "13333333333", 396 | "approvalStatus": "审核通过" 397 | } 398 | ], 399 | "prePage": 0, 400 | "nextPage": 2, 401 | "isFirstPage": true, 402 | "isLastPage": false, 403 | "hasPreviousPage": false, 404 | "hasNextPage": true, 405 | "navigatePages": 8, 406 | "navigatepageNums": [ 407 | 1, 408 | 2, 409 | 3 410 | ], 411 | "navigateFirstPage": 1, 412 | "navigateLastPage": 3, 413 | "firstPage": 1, 414 | "lastPage": 3 415 | } 416 | }, 417 | "courseTitles": { 418 | "获取课程名称": 1, 419 | "code": 200, 420 | "msg": "获取课程名称成功", 421 | "data": [ 422 | { 423 | "id": "1", 424 | "courseCode": "B001", 425 | "courseTitle": 1 426 | }, 427 | { 428 | "id": "2", 429 | "courseCode": "B001", 430 | "courseTitle": 1 431 | } 432 | ] 433 | } 434 | } -------------------------------------------------------------------------------- /src/views/aao/Export.vue: -------------------------------------------------------------------------------- 1 | 87 | 88 | 314 | 315 | 320 | -------------------------------------------------------------------------------- /src/views/teacher/Add.vue: -------------------------------------------------------------------------------- 1 | 92 | 93 | 298 | 299 | 302 | -------------------------------------------------------------------------------- /src/views/aao/Review.vue: -------------------------------------------------------------------------------- 1 | 39 | 40 | 326 | 327 | 333 | 350 | --------------------------------------------------------------------------------