From e15e35dd8a2940d86b923c5849414690f165262e Mon Sep 17 00:00:00 2001
From: 龚焕茏 <2842157468@qq.com>
Date: 星期四, 05 九月 2024 16:36:30 +0800
Subject: [PATCH] 学员导出
---
src/utils/request.js | 203 +++++++++++++++-------
src/views/home/index.vue | 2
src/utils/cache.js | 77 ++++++++
src/main.js | 2
src/utils/ruoyi.js | 233 +++++++++++++++++++++++++
package.json | 3
src/utils/errorCode.js | 6
src/views/student/index.vue | 8
8 files changed, 463 insertions(+), 71 deletions(-)
diff --git a/package.json b/package.json
index 8ce7d9a..46130e3 100644
--- a/package.json
+++ b/package.json
@@ -26,7 +26,8 @@
"cos-js-sdk-v5": "^1.8.3",
"echarts": "^5.5.1",
"element-ui": "2.13.2",
- "graphql": "^16.9.0",
+ "file-saver": "^2.0.5",
+ "graphql": "^15.0.0",
"graphql-tag": "^2.12.6",
"js-cookie": "2.2.0",
"normalize.css": "7.0.0",
diff --git a/src/main.js b/src/main.js
index 09153ea..1e5df94 100644
--- a/src/main.js
+++ b/src/main.js
@@ -11,10 +11,12 @@
import App from "./App";
import store from "./store";
import router from "./router";
+import { download } from '@/utils/request'
import "@/icons"; // icon
import "@/permission"; // permission control
+Vue.prototype.download = download
// const cors = require('cors');
// // 澶勭悊璺ㄥ煙璇锋眰
// App.use(cors());
diff --git a/src/utils/cache.js b/src/utils/cache.js
new file mode 100644
index 0000000..6b5c00b
--- /dev/null
+++ b/src/utils/cache.js
@@ -0,0 +1,77 @@
+const sessionCache = {
+ set (key, value) {
+ if (!sessionStorage) {
+ return
+ }
+ if (key != null && value != null) {
+ sessionStorage.setItem(key, value)
+ }
+ },
+ get (key) {
+ if (!sessionStorage) {
+ return null
+ }
+ if (key == null) {
+ return null
+ }
+ return sessionStorage.getItem(key)
+ },
+ setJSON (key, jsonValue) {
+ if (jsonValue != null) {
+ this.set(key, JSON.stringify(jsonValue))
+ }
+ },
+ getJSON (key) {
+ const value = this.get(key)
+ if (value != null) {
+ return JSON.parse(value)
+ }
+ },
+ remove (key) {
+ sessionStorage.removeItem(key);
+ }
+}
+const localCache = {
+ set (key, value) {
+ if (!localStorage) {
+ return
+ }
+ if (key != null && value != null) {
+ localStorage.setItem(key, value)
+ }
+ },
+ get (key) {
+ if (!localStorage) {
+ return null
+ }
+ if (key == null) {
+ return null
+ }
+ return localStorage.getItem(key)
+ },
+ setJSON (key, jsonValue) {
+ if (jsonValue != null) {
+ this.set(key, JSON.stringify(jsonValue))
+ }
+ },
+ getJSON (key) {
+ const value = this.get(key)
+ if (value != null) {
+ return JSON.parse(value)
+ }
+ },
+ remove (key) {
+ localStorage.removeItem(key);
+ }
+}
+
+export default {
+ /**
+ * 浼氳瘽绾х紦瀛�
+ */
+ session: sessionCache,
+ /**
+ * 鏈湴缂撳瓨
+ */
+ local: localCache
+}
diff --git a/src/utils/errorCode.js b/src/utils/errorCode.js
new file mode 100644
index 0000000..d2111ee
--- /dev/null
+++ b/src/utils/errorCode.js
@@ -0,0 +1,6 @@
+export default {
+ '401': '璁よ瘉澶辫触锛屾棤娉曡闂郴缁熻祫婧�',
+ '403': '褰撳墠鎿嶄綔娌℃湁鏉冮檺',
+ '404': '璁块棶璧勬簮涓嶅瓨鍦�',
+ 'default': '绯荤粺鏈煡閿欒锛岃鍙嶉缁欑鐞嗗憳'
+}
diff --git a/src/utils/request.js b/src/utils/request.js
index ee21946..521876f 100644
--- a/src/utils/request.js
+++ b/src/utils/request.js
@@ -1,84 +1,153 @@
import axios from 'axios'
-import { MessageBox, Message } from 'element-ui'
+import { Notification, MessageBox, Message, Loading } from 'element-ui'
import store from '@/store'
import { getToken } from '@/utils/auth'
+import errorCode from '@/utils/errorCode'
+import { tansParams, blobValidate } from "@/utils/ruoyi";
+import cache from '@/utils/cache'
+import { saveAs } from 'file-saver'
-// create an axios instance
+let downloadLoadingInstance;
+// 鏄惁鏄剧ず閲嶆柊鐧诲綍
+export let isRelogin = { show: false };
+
+axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
+// 鍒涘缓axios瀹炰緥
const service = axios.create({
- baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
- // withCredentials: true, // send cookies when cross-domain requests
- timeout: 5000 // request timeout
+ // axios涓姹傞厤缃湁baseURL閫夐」锛岃〃绀鸿姹俇RL鍏叡閮ㄥ垎
+ baseURL: process.env.VUE_APP_BASE_API,
+ // 瓒呮椂
+ //榛樿10绉� 淇敼涓�20绉�
+ timeout: 20000
})
-// request interceptor
-service.interceptors.request.use(
- config => {
- // do something before request is sent
-
- if (store.getters.token) {
- // let each request carry token
- // ['X-Token'] is a custom headers key
- // please modify it according to the actual situation
- config.headers['X-Token'] = getToken()
- }
- return config
- },
- error => {
- // do something with request error
- console.log(error) // for debug
- return Promise.reject(error)
+// request鎷︽埅鍣�
+service.interceptors.request.use(config => {
+ // 鏄惁闇�瑕佽缃� token
+ const isToken = (config.headers || {}).isToken === false
+ // 鏄惁闇�瑕侀槻姝㈡暟鎹噸澶嶆彁浜�
+ const isRepeatSubmit = (config.headers || {}).repeatSubmit === false
+ if (getToken() && !isToken) {
+ config.headers['Authorization'] = 'Bearer ' + getToken() // 璁╂瘡涓姹傛惡甯﹁嚜瀹氫箟token 璇锋牴鎹疄闄呮儏鍐佃嚜琛屼慨鏀�
}
-)
-
-// response interceptor
-service.interceptors.response.use(
- /**
- * If you want to get http information such as headers or status
- * Please return response => response
- */
-
- /**
- * Determine the request status by custom code
- * Here is just an example
- * You can also judge the status by HTTP Status Code
- */
- response => {
- const res = response
- // if the custom code is not 20000, it is judged as an error.
- if (res.status !== 200) {
- Message({
- message: res.message || 'Error',
- type: 'error',
- duration: 5 * 1000
- })
-
- // 50008: Illegal token; 50012: Other clients logged in; 50014: Token expired;
- if (res.status === 50008 || res.status === 50012 || res.status === 50014) {
- // to re-login
- MessageBox.confirm('You have been logged out, you can cancel to stay on this page, or log in again', 'Confirm logout', {
- confirmButtonText: 'Re-Login',
- cancelButtonText: 'Cancel',
- type: 'warning'
- }).then(() => {
- store.dispatch('user/resetToken').then(() => {
- location.reload()
- })
- })
- }
- return Promise.reject(new Error(res.message || 'Error'))
+ // get璇锋眰鏄犲皠params鍙傛暟
+ if (config.method === 'get' && config.params) {
+ let url = config.url + '?' + tansParams(config.params);
+ url = url.slice(0, -1);
+ config.params = {};
+ config.url = url;
+ }
+ if (!isRepeatSubmit && (config.method === 'post' || config.method === 'put')) {
+ const requestObj = {
+ url: config.url,
+ data: typeof config.data === 'object' ? JSON.stringify(config.data) : config.data,
+ time: new Date().getTime()
+ }
+ const requestSize = Object.keys(JSON.stringify(requestObj)).length; // 璇锋眰鏁版嵁澶у皬
+ const limitSize = 5 * 1024 * 1024; // 闄愬埗瀛樻斁鏁版嵁5M
+ if (requestSize >= limitSize) {
+ console.warn(`[${config.url}]: ` + '璇锋眰鏁版嵁澶у皬瓒呭嚭鍏佽鐨�5M闄愬埗锛屾棤娉曡繘琛岄槻閲嶅鎻愪氦楠岃瘉銆�')
+ return config;
+ }
+ const sessionObj = cache.session.getJSON('sessionObj')
+ if (sessionObj === undefined || sessionObj === null || sessionObj === '') {
+ cache.session.setJSON('sessionObj', requestObj)
} else {
- return res
+ const s_url = sessionObj.url; // 璇锋眰鍦板潃
+ const s_data = sessionObj.data; // 璇锋眰鏁版嵁
+ const s_time = sessionObj.time; // 璇锋眰鏃堕棿
+ const interval = 1000; // 闂撮殧鏃堕棿(ms)锛屽皬浜庢鏃堕棿瑙嗕负閲嶅鎻愪氦
+ if (s_data === requestObj.data && requestObj.time - s_time < interval && s_url === requestObj.url) {
+ const message = '鏁版嵁姝e湪澶勭悊锛岃鍕块噸澶嶆彁浜�';
+ console.warn(`[${s_url}]: ` + message)
+ return Promise.reject(new Error(message))
+ } else {
+ cache.session.setJSON('sessionObj', requestObj)
+ }
+ }
+ }
+ return config
+}, error => {
+ console.log(error)
+ Promise.reject(error)
+})
+
+// 鍝嶅簲鎷︽埅鍣�
+service.interceptors.response.use(res => {
+ // 鏈缃姸鎬佺爜鍒欓粯璁ゆ垚鍔熺姸鎬�
+ const code = res.data.code || 200;
+ // 鑾峰彇閿欒淇℃伅
+ const msg = errorCode[code] || res.data.msg || errorCode['default']
+ // 浜岃繘鍒舵暟鎹垯鐩存帴杩斿洖
+ if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer') {
+ return res.data
+ }
+ if (code === 401) {
+ if (!isRelogin.show) {
+ isRelogin.show = true;
+ MessageBox.confirm('鐧诲綍鐘舵�佸凡杩囨湡锛屾偍鍙互缁х画鐣欏湪璇ラ〉闈紝鎴栬�呴噸鏂扮櫥褰�', '绯荤粺鎻愮ず', { confirmButtonText: '閲嶆柊鐧诲綍', cancelButtonText: '鍙栨秷', type: 'warning' }).then(() => {
+ isRelogin.show = false;
+ store.dispatch('LogOut').then(() => {
+ location.href = '/index';
+ })
+ }).catch(() => {
+ isRelogin.show = false;
+ });
+ }
+ return Promise.reject('鏃犳晥鐨勪細璇濓紝鎴栬�呬細璇濆凡杩囨湡锛岃閲嶆柊鐧诲綍銆�')
+ } else if (code === 500) {
+ Message({ message: msg, type: 'error' })
+ return Promise.reject(new Error(msg))
+ } else if (code === 601) {
+ Message({ message: msg, type: 'warning' })
+ return Promise.reject('error')
+ } else if (code !== 200) {
+ Notification.error({ title: msg })
+ return Promise.reject('error')
+ } else {
+ return res.data
}
},
error => {
- console.log('err' + error) // for debug
- Message({
- message: error.message,
- type: 'error',
- duration: 5 * 1000
- })
+ console.log('err' + error)
+ let { message } = error;
+ if (message == "Network Error") {
+ message = "鍚庣鎺ュ彛杩炴帴寮傚父";
+ } else if (message.includes("timeout")) {
+ message = "绯荤粺鎺ュ彛璇锋眰瓒呮椂";
+ } else if (message.includes("Request failed with status code")) {
+ message = "绯荤粺鎺ュ彛" + message.substr(message.length - 3) + "寮傚父";
+ }
+ Message({ message: message, type: 'error', duration: 5 * 1000 })
return Promise.reject(error)
}
)
+// 閫氱敤涓嬭浇鏂规硶
+export function download(url, params, filename, config) {
+ downloadLoadingInstance = Loading.service({ text: "姝e湪涓嬭浇鏁版嵁锛岃绋嶅��", spinner: "el-icon-loading", background: "rgba(0, 0, 0, 0.7)", })
+ return service.post(url, params, {
+ transformRequest: [(params) => { return tansParams(params) }],
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
+ responseType: 'blob',
+ ...config
+ }).then(async (data) => {
+ const isBlob = blobValidate(data);
+ if (isBlob) {
+ const blob = new Blob([data])
+ saveAs(blob, filename)
+ } else {
+ const resText = await data.text();
+ const rspObj = JSON.parse(resText);
+ const errMsg = errorCode[rspObj.code] || rspObj.msg || errorCode['default']
+ Message.error(errMsg);
+ }
+ downloadLoadingInstance.close();
+ }).catch((r) => {
+ console.error(r)
+ Message.error('涓嬭浇鏂囦欢鍑虹幇閿欒锛岃鑱旂郴绠$悊鍛橈紒')
+ downloadLoadingInstance.close();
+ })
+}
+
export default service
diff --git a/src/utils/ruoyi.js b/src/utils/ruoyi.js
new file mode 100644
index 0000000..44bf9c4
--- /dev/null
+++ b/src/utils/ruoyi.js
@@ -0,0 +1,233 @@
+
+
+/**
+ * 閫氱敤js鏂规硶灏佽澶勭悊
+ * Copyright (c) 2019 ruoyi
+ */
+
+// 鏃ユ湡鏍煎紡鍖�
+export function parseTime(time, pattern) {
+ if (arguments.length === 0 || !time) {
+ return null
+ }
+ const format = pattern || '{y}-{m}-{d} {h}:{i}:{s}'
+ let date
+ if (typeof time === 'object') {
+ date = time
+ } else {
+ if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) {
+ time = parseInt(time)
+ } else if (typeof time === 'string') {
+ time = time.replace(new RegExp(/-/gm), '/').replace('T', ' ').replace(new RegExp(/\.[\d]{3}/gm), '');
+ }
+ if ((typeof time === 'number') && (time.toString().length === 10)) {
+ time = time * 1000
+ }
+ date = new Date(time)
+ }
+ const formatObj = {
+ y: date.getFullYear(),
+ m: date.getMonth() + 1,
+ d: date.getDate(),
+ h: date.getHours(),
+ i: date.getMinutes(),
+ s: date.getSeconds(),
+ a: date.getDay()
+ }
+ const time_str = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
+ let value = formatObj[key]
+ // Note: getDay() returns 0 on Sunday
+ if (key === 'a') { return ['鏃�', '涓�', '浜�', '涓�', '鍥�', '浜�', '鍏�'][value] }
+ if (result.length > 0 && value < 10) {
+ value = '0' + value
+ }
+ return value || 0
+ })
+ return time_str
+}
+
+// 琛ㄥ崟閲嶇疆
+export function resetForm(refName) {
+ if (this.$refs[refName]) {
+ this.$refs[refName].resetFields();
+ }
+}
+
+// 娣诲姞鏃ユ湡鑼冨洿
+export function addDateRange(params, dateRange, propName) {
+ let search = params;
+ search.params = typeof (search.params) === 'object' && search.params !== null && !Array.isArray(search.params) ? search.params : {};
+ dateRange = Array.isArray(dateRange) ? dateRange : [];
+ if (typeof (propName) === 'undefined') {
+ search.params['beginTime'] = dateRange[0];
+ search.params['endTime'] = dateRange[1];
+ } else {
+ search.params['begin' + propName] = dateRange[0];
+ search.params['end' + propName] = dateRange[1];
+ }
+ return search;
+}
+
+// 鍥炴樉鏁版嵁瀛楀吀
+export function selectDictLabel(datas, value) {
+ if (value === undefined) {
+ return "";
+ }
+ var actions = [];
+ Object.keys(datas).some((key) => {
+ if (datas[key].value == ('' + value)) {
+ actions.push(datas[key].label);
+ return true;
+ }
+ })
+ if (actions.length === 0) {
+ actions.push(value);
+ }
+ return actions.join('');
+}
+
+// 鍥炴樉鏁版嵁瀛楀吀锛堝瓧绗︿覆銆佹暟缁勶級
+export function selectDictLabels(datas, value, separator) {
+ if (value === undefined || value.length ===0) {
+ return "";
+ }
+ if (Array.isArray(value)) {
+ value = value.join(",");
+ }
+ var actions = [];
+ var currentSeparator = undefined === separator ? "," : separator;
+ var temp = value.split(currentSeparator);
+ Object.keys(value.split(currentSeparator)).some((val) => {
+ var match = false;
+ Object.keys(datas).some((key) => {
+ if (datas[key].value == ('' + temp[val])) {
+ actions.push(datas[key].label + currentSeparator);
+ match = true;
+ }
+ })
+ if (!match) {
+ actions.push(temp[val] + currentSeparator);
+ }
+ })
+ return actions.join('').substring(0, actions.join('').length - 1);
+}
+
+// 瀛楃涓叉牸寮忓寲(%s )
+export function sprintf(str) {
+ var args = arguments, flag = true, i = 1;
+ str = str.replace(/%s/g, function () {
+ var arg = args[i++];
+ if (typeof arg === 'undefined') {
+ flag = false;
+ return '';
+ }
+ return arg;
+ });
+ return flag ? str : '';
+}
+
+// 杞崲瀛楃涓诧紝undefined,null绛夎浆鍖栦负""
+export function parseStrEmpty(str) {
+ if (!str || str == "undefined" || str == "null") {
+ return "";
+ }
+ return str;
+}
+
+// 鏁版嵁鍚堝苟
+export function mergeRecursive(source, target) {
+ for (var p in target) {
+ try {
+ if (target[p].constructor == Object) {
+ source[p] = mergeRecursive(source[p], target[p]);
+ } else {
+ source[p] = target[p];
+ }
+ } catch (e) {
+ source[p] = target[p];
+ }
+ }
+ return source;
+};
+
+/**
+ * 鏋勯�犳爲鍨嬬粨鏋勬暟鎹�
+ * @param {*} data 鏁版嵁婧�
+ * @param {*} id id瀛楁 榛樿 'id'
+ * @param {*} parentId 鐖惰妭鐐瑰瓧娈� 榛樿 'parentId'
+ * @param {*} children 瀛╁瓙鑺傜偣瀛楁 榛樿 'children'
+ */
+export function handleTree(data, id, parentId, children) {
+ let config = {
+ id: id || 'id',
+ parentId: parentId || 'parentId',
+ childrenList: children || 'children'
+ };
+
+ var childrenListMap = {};
+ var nodeIds = {};
+ var tree = [];
+
+ for (let d of data) {
+ let parentId = d[config.parentId];
+ if (childrenListMap[parentId] == null) {
+ childrenListMap[parentId] = [];
+ }
+ nodeIds[d[config.id]] = d;
+ childrenListMap[parentId].push(d);
+ }
+
+ for (let d of data) {
+ let parentId = d[config.parentId];
+ if (nodeIds[parentId] == null) {
+ tree.push(d);
+ }
+ }
+
+ for (let t of tree) {
+ adaptToChildrenList(t);
+ }
+
+ function adaptToChildrenList(o) {
+ if (childrenListMap[o[config.id]] !== null) {
+ o[config.childrenList] = childrenListMap[o[config.id]];
+ }
+ if (o[config.childrenList]) {
+ for (let c of o[config.childrenList]) {
+ adaptToChildrenList(c);
+ }
+ }
+ }
+ return tree;
+}
+
+/**
+* 鍙傛暟澶勭悊
+* @param {*} params 鍙傛暟
+*/
+export function tansParams(params) {
+ let result = ''
+ for (const propName of Object.keys(params)) {
+ const value = params[propName];
+ var part = encodeURIComponent(propName) + "=";
+ if (value !== null && value !== "" && typeof (value) !== "undefined") {
+ if (typeof value === 'object') {
+ for (const key of Object.keys(value)) {
+ if (value[key] !== null && value[key] !== "" && typeof (value[key]) !== 'undefined') {
+ let params = propName + '[' + key + ']';
+ var subPart = encodeURIComponent(params) + "=";
+ result += subPart + encodeURIComponent(value[key]) + "&";
+ }
+ }
+ } else {
+ result += part + encodeURIComponent(value) + "&";
+ }
+ }
+ }
+ return result
+}
+
+// 楠岃瘉鏄惁涓篵lob鏍煎紡
+export function blobValidate(data) {
+ return data.type !== 'application/json'
+}
diff --git a/src/views/home/index.vue b/src/views/home/index.vue
index c9254e9..4268322 100644
--- a/src/views/home/index.vue
+++ b/src/views/home/index.vue
@@ -48,7 +48,7 @@
methods: {
getUserDate() {
login({
- code: "0913JF000eW6BS1rZ3100FQTUM03JF05",
+ code: "021dbA000NZ9LS1gKd400jYDAX1dbA0L",
}).then((res) => {
localStorage.setItem("user", JSON.stringify(res.data));
});
diff --git a/src/views/student/index.vue b/src/views/student/index.vue
index 3a28c1b..c9f5af7 100644
--- a/src/views/student/index.vue
+++ b/src/views/student/index.vue
@@ -8,7 +8,7 @@
</el-tabs>
<div style="display: flex; justify-content: space-between">
<!-- <el-button type="primary" size="small" @click="showCreate">鏂板缓瀛﹀憳</el-button> -->
- <el-button type="primary" size="small">瀵煎嚭瀛﹀憳</el-button>
+ <el-button type="primary" size="small" @click="handleExport">瀵煎嚭瀛﹀憳</el-button>
<div style="width: 300px">
<el-input
placeholder="鎸夊鍚嶆悳绱�"
@@ -112,7 +112,7 @@
</template>
<script>
-import { getData, getRenew, getExpire, getDeleted } from "@/api/student";
+import { getData, getRenew, getExpire, getDeleted, handleExport } from "@/api/student";
import StudentCreate from "./components/create.vue";
export default {
@@ -154,6 +154,10 @@
this.fetchData();
},
methods: {
+ handleExport() {
+ this.download('exportPlayer', {
+ }, `瀵煎嚭_${new Date().getTime()}.xlsx`)
+ },
fetchData() {
this.listLoading = true;
getData(this.data).then((response) => {
--
Gitblit v1.8.0